summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore29
-rw-r--r--.gitmodules9
-rw-r--r--.travis.yml24
-rw-r--r--Makefile245
-rw-r--r--Vagrantfile98
-rw-r--r--doc/BUILD_GUIDE.md103
-rw-r--r--doc/COPYING.GPLv2339
-rw-r--r--doc/COPYING.GPLv3674
-rwxr-xr-xdoc/CYGWIN_GUIDE.md352
-rw-r--r--doc/FUSE.txt50
-rw-r--r--doc/HAND_WIRE.md321
-rw-r--r--doc/PCB_GUIDE.md151
-rw-r--r--doc/POWER.txt62
-rw-r--r--doc/TMK_README.md243
-rw-r--r--doc/USB_NKRO.txt160
-rw-r--r--doc/VAGRANT_GUIDE.md26
-rw-r--r--doc/build_old.md187
-rw-r--r--doc/keycode.txt261
-rw-r--r--doc/keymap.md599
-rw-r--r--doc/keymap_config_h_example.h8
-rw-r--r--doc/keymap_makefile_example.mk21
-rw-r--r--doc/other_projects.md62
-rw-r--r--keyboards/alps64/Makefile70
-rw-r--r--keyboards/alps64/alps64.c30
-rw-r--r--keyboards/alps64/alps64.h40
-rw-r--r--keyboards/alps64/config.h75
-rw-r--r--keyboards/alps64/keymaps/default/keymap.c12
-rw-r--r--keyboards/alps64/led.c34
-rw-r--r--keyboards/alps64/matrix.c199
-rw-r--r--keyboards/arrow_pad/Makefile74
-rw-r--r--keyboards/arrow_pad/arrow_pad.c1
-rw-r--r--keyboards/arrow_pad/arrow_pad.h13
-rw-r--r--keyboards/arrow_pad/config.h160
-rw-r--r--keyboards/arrow_pad/keymaps/default/keymap.c163
-rw-r--r--keyboards/arrow_pad/keymaps/pad_21/Makefile17
-rw-r--r--keyboards/arrow_pad/keymaps/pad_21/config.h158
-rw-r--r--keyboards/arrow_pad/keymaps/pad_21/keymap.c160
-rw-r--r--keyboards/arrow_pad/keymaps/pad_24/Makefile17
-rw-r--r--keyboards/arrow_pad/keymaps/pad_24/config.h160
-rw-r--r--keyboards/arrow_pad/keymaps/pad_24/keymap.c163
-rw-r--r--keyboards/arrow_pad/readme.md24
-rw-r--r--keyboards/atomic/Makefile73
-rw-r--r--keyboards/atomic/atomic.c15
-rw-r--r--keyboards/atomic/atomic.h27
-rw-r--r--keyboards/atomic/config.h160
-rw-r--r--keyboards/atomic/keymaps/abienz.c36
-rw-r--r--keyboards/atomic/keymaps/default/keymap.c234
-rw-r--r--keyboards/atomic/keymaps/michelle.c183
-rw-r--r--keyboards/atomic/keymaps/pvc/Makefile15
-rw-r--r--keyboards/atomic/keymaps/pvc/config.h169
-rw-r--r--keyboards/atomic/keymaps/pvc/keymap.c578
-rw-r--r--keyboards/atomic/readme.md25
-rw-r--r--keyboards/atreus/Makefile87
-rw-r--r--keyboards/atreus/atreus.c1
-rw-r--r--keyboards/atreus/atreus.h25
-rw-r--r--keyboards/atreus/config.h88
-rw-r--r--keyboards/atreus/keymaps/default/keymap.c51
-rw-r--r--keyboards/atreus/keymaps/gerb/keymap.c66
-rw-r--r--keyboards/atreus/readme.md186
-rw-r--r--keyboards/bantam44/Makefile72
-rw-r--r--keyboards/bantam44/bantam44.c1
-rw-r--r--keyboards/bantam44/bantam44.h23
-rw-r--r--keyboards/bantam44/config.h82
-rw-r--r--keyboards/bantam44/keymaps/default/keymap.c30
-rw-r--r--keyboards/bantam44/readme.md24
-rw-r--r--keyboards/chibios_test/Makefile14
-rw-r--r--keyboards/chibios_test/boards/GENERIC_STM32_F103/board.c49
-rw-r--r--keyboards/chibios_test/boards/GENERIC_STM32_F103/board.h166
-rw-r--r--keyboards/chibios_test/boards/GENERIC_STM32_F103/board.mk5
-rw-r--r--keyboards/chibios_test/boards/GENERIC_STM32_F103/mini_stm32_mapping.pngbin0 -> 162908 bytes
-rw-r--r--keyboards/chibios_test/boards/maple_mini_mapping.pngbin0 -> 237977 bytes
-rw-r--r--keyboards/chibios_test/chibios_test.c1
-rw-r--r--keyboards/chibios_test/chibios_test.h6
-rw-r--r--keyboards/chibios_test/config.h74
-rw-r--r--keyboards/chibios_test/keymaps/default/keymap.c25
-rw-r--r--keyboards/chibios_test/ld/MKL26Z64.ld105
-rw-r--r--keyboards/chibios_test/ld/STM32F103x8_stm32duino_bootloader.ld88
-rw-r--r--keyboards/chibios_test/stm32_f072_onekey/Makefile41
-rw-r--r--keyboards/chibios_test/stm32_f072_onekey/bootloader_defs.h7
-rw-r--r--keyboards/chibios_test/stm32_f072_onekey/chconf.h524
-rw-r--r--keyboards/chibios_test/stm32_f072_onekey/config.h7
-rw-r--r--keyboards/chibios_test/stm32_f072_onekey/halconf.h353
-rw-r--r--keyboards/chibios_test/stm32_f072_onekey/led.c34
-rw-r--r--keyboards/chibios_test/stm32_f072_onekey/matrix.c163
-rw-r--r--keyboards/chibios_test/stm32_f072_onekey/mcuconf.h171
-rw-r--r--keyboards/chibios_test/stm32_f072_onekey/stm32_f072_onekey.c1
-rw-r--r--keyboards/chibios_test/stm32_f072_onekey/stm32_f072_onekey.h5
-rw-r--r--keyboards/chibios_test/stm32_f103_onekey/Makefile52
-rw-r--r--keyboards/chibios_test/stm32_f103_onekey/bootloader_defs.h10
-rw-r--r--keyboards/chibios_test/stm32_f103_onekey/chconf.h524
-rw-r--r--keyboards/chibios_test/stm32_f103_onekey/config.h6
-rwxr-xr-xkeyboards/chibios_test/stm32_f103_onekey/flash.sh2
-rw-r--r--keyboards/chibios_test/stm32_f103_onekey/halconf.h353
-rw-r--r--keyboards/chibios_test/stm32_f103_onekey/led.c43
-rw-r--r--keyboards/chibios_test/stm32_f103_onekey/matrix.c177
-rw-r--r--keyboards/chibios_test/stm32_f103_onekey/mcuconf.h209
-rw-r--r--keyboards/chibios_test/stm32_f103_onekey/stm32_f103_onekey.c1
-rw-r--r--keyboards/chibios_test/stm32_f103_onekey/stm32_f103_onekey.h4
-rw-r--r--keyboards/chibios_test/teensy_lc_onekey/Makefile49
-rw-r--r--keyboards/chibios_test/teensy_lc_onekey/Makefile.3.077
-rw-r--r--keyboards/chibios_test/teensy_lc_onekey/Makefile.3.277
-rw-r--r--keyboards/chibios_test/teensy_lc_onekey/chconf.h524
-rw-r--r--keyboards/chibios_test/teensy_lc_onekey/config.h6
-rw-r--r--keyboards/chibios_test/teensy_lc_onekey/halconf.h187
-rw-r--r--keyboards/chibios_test/teensy_lc_onekey/instructions.md82
-rw-r--r--keyboards/chibios_test/teensy_lc_onekey/led.c32
-rw-r--r--keyboards/chibios_test/teensy_lc_onekey/matrix.c163
-rw-r--r--keyboards/chibios_test/teensy_lc_onekey/mcuconf.h55
-rw-r--r--keyboards/chibios_test/teensy_lc_onekey/teensy_lc_onekey.c1
-rw-r--r--keyboards/chibios_test/teensy_lc_onekey/teensy_lc_onekey.h4
-rw-r--r--keyboards/clueboard/Makefile109
-rw-r--r--keyboards/clueboard/clueboard.c17
-rw-r--r--keyboards/clueboard/clueboard.h13
-rw-r--r--keyboards/clueboard/config.h74
-rw-r--r--keyboards/clueboard/keymaps/default/keymap.c180
-rw-r--r--keyboards/clueboard/keymaps/max/Makefile49
-rw-r--r--keyboards/clueboard/keymaps/max/keymap.c143
-rw-r--r--keyboards/clueboard/keymaps/skully/keymap.c108
-rw-r--r--keyboards/clueboard/rev1/Makefile5
-rw-r--r--keyboards/clueboard/rev1/config.h37
-rw-r--r--keyboards/clueboard/rev1/rev1.c1
-rw-r--r--keyboards/clueboard/rev1/rev1.h47
-rw-r--r--keyboards/clueboard/rev2/Makefile5
-rw-r--r--keyboards/clueboard/rev2/config.h40
-rw-r--r--keyboards/clueboard/rev2/rev2.c47
-rw-r--r--keyboards/clueboard/rev2/rev2.h52
-rw-r--r--keyboards/clueboard2/Makefile71
-rw-r--r--keyboards/clueboard2/clueboard2.c63
-rw-r--r--keyboards/cluepad/Makefile70
-rw-r--r--keyboards/cluepad/cluepad.c60
-rw-r--r--keyboards/cluepad/cluepad.h36
-rw-r--r--keyboards/cluepad/config.h101
-rw-r--r--keyboards/cluepad/keymaps/default/keymap.c122
-rwxr-xr-xkeyboards/ergodox_ez/190hotfix.sh19
-rw-r--r--keyboards/ergodox_ez/Makefile86
-rw-r--r--keyboards/ergodox_ez/config.h84
-rw-r--r--keyboards/ergodox_ez/ergodox_ez.c85
-rw-r--r--keyboards/ergodox_ez/ergodox_ez.h122
-rw-r--r--keyboards/ergodox_ez/i2cmaster.h178
-rw-r--r--keyboards/ergodox_ez/keymaps/ab/Makefile9
-rw-r--r--keyboards/ergodox_ez/keymaps/ab/keyboard-layout.json387
-rw-r--r--keyboards/ergodox_ez/keymaps/ab/keyboard-layout.pngbin0 -> 80776 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/ab/keymap.c155
-rw-r--r--keyboards/ergodox_ez/keymaps/ab/readme.md21
-rw-r--r--keyboards/ergodox_ez/keymaps/adnw_k_o_y/keymap.c185
-rw-r--r--keyboards/ergodox_ez/keymaps/adnw_k_o_y/readme.md7
-rw-r--r--keyboards/ergodox_ez/keymaps/alexjj/keymap.c238
-rw-r--r--keyboards/ergodox_ez/keymaps/alexjj/readme.md179
-rw-r--r--keyboards/ergodox_ez/keymaps/alexjj/rl-layout.jpgbin0 -> 833107 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/algernon/COPYING674
-rw-r--r--keyboards/ergodox_ez/keymaps/algernon/Makefile26
-rw-r--r--keyboards/ergodox_ez/keymaps/algernon/config.h27
-rw-r--r--keyboards/ergodox_ez/keymaps/algernon/images/base-layer.pngbin0 -> 105162 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/algernon/images/experimental-layer.pngbin0 -> 105172 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/algernon/images/hun-layer.pngbin0 -> 67924 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/algernon/images/nav-n-media-layer.pngbin0 -> 94837 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/algernon/images/one-handed-layer.pngbin0 -> 91140 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/algernon/images/steno-layer.pngbin0 -> 69557 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/algernon/keymap.c1104
-rw-r--r--keyboards/ergodox_ez/keymaps/algernon/readme.md230
-rwxr-xr-xkeyboards/ergodox_ez/keymaps/algernon/tools/max-focused5
-rw-r--r--keyboards/ergodox_ez/keymaps/andrew_osx/keymap.c187
-rw-r--r--keyboards/ergodox_ez/keymaps/bepo/bepo.pngbin0 -> 79747 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/bepo/keymap.c311
-rw-r--r--keyboards/ergodox_ez/keymaps/bepo/readme.md34
-rw-r--r--keyboards/ergodox_ez/keymaps/coderkun_neo2/Makefile1
-rw-r--r--keyboards/ergodox_ez/keymaps/coderkun_neo2/keymap.c274
-rw-r--r--keyboards/ergodox_ez/keymaps/coderkun_neo2/readme.md31
-rw-r--r--keyboards/ergodox_ez/keymaps/colemak/keymap.c184
-rw-r--r--keyboards/ergodox_ez/keymaps/colemak/readme.md4
-rw-r--r--keyboards/ergodox_ez/keymaps/colemak_osx_pc_no/keyboard-layout.pngbin0 -> 103158 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/colemak_osx_pc_no/keymap.c264
-rw-r--r--keyboards/ergodox_ez/keymaps/colemak_osx_pc_no/readme.md23
-rw-r--r--keyboards/ergodox_ez/keymaps/csharp_dev/csharp_dev.pngbin0 -> 97642 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/csharp_dev/csharp_dev_legend.pngbin0 -> 387797 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/csharp_dev/keymap.c239
-rw-r--r--keyboards/ergodox_ez/keymaps/csharp_dev/readme.md47
-rw-r--r--keyboards/ergodox_ez/keymaps/dave/keymap.c199
-rw-r--r--keyboards/ergodox_ez/keymaps/dave/readme.md38
-rw-r--r--keyboards/ergodox_ez/keymaps/default/default.pngbin0 -> 193672 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/default/default_highres.pngbin0 -> 1459389 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/default/keymap.c182
-rw-r--r--keyboards/ergodox_ez/keymaps/default/readme.md10
-rw-r--r--keyboards/ergodox_ez/keymaps/default_osx/default_osx_highres.pngbin0 -> 772418 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/default_osx/keymap.c187
-rw-r--r--keyboards/ergodox_ez/keymaps/default_osx/readme.md8
-rw-r--r--keyboards/ergodox_ez/keymaps/dragon788/keymap.c229
-rw-r--r--keyboards/ergodox_ez/keymaps/dvorak/dvorak.pngbin0 -> 87314 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/dvorak/keymap.c184
-rw-r--r--keyboards/ergodox_ez/keymaps/dvorak_intl_squisher/keyboard-layout0.pngbin0 -> 73585 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/dvorak_intl_squisher/keyboard-layout1.pngbin0 -> 59122 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/dvorak_intl_squisher/keyboard-layout2.pngbin0 -> 53319 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/dvorak_intl_squisher/keymap.c185
-rw-r--r--keyboards/ergodox_ez/keymaps/dvorak_intl_squisher/readme.md29
-rwxr-xr-xkeyboards/ergodox_ez/keymaps/dvorak_spanish/keymap.c284
-rw-r--r--keyboards/ergodox_ez/keymaps/dvorak_spanish/readme.md99
-rw-r--r--keyboards/ergodox_ez/keymaps/emacs_osx_dk/default_highres.pngbin0 -> 142146 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/emacs_osx_dk/keymap.c184
-rw-r--r--keyboards/ergodox_ez/keymaps/emacs_osx_dk/readme.md10
-rw-r--r--keyboards/ergodox_ez/keymaps/erez_experimental/Makefile9
-rw-r--r--keyboards/ergodox_ez/keymaps/erez_experimental/config.h12
-rw-r--r--keyboards/ergodox_ez/keymaps/erez_experimental/keymap.c199
-rw-r--r--keyboards/ergodox_ez/keymaps/erez_experimental/readme.md51
-rw-r--r--keyboards/ergodox_ez/keymaps/german-kinergo/keymap.c210
-rw-r--r--keyboards/ergodox_ez/keymaps/german-kinergo/layout-code.pngbin0 -> 55386 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/german-kinergo/layout-media.pngbin0 -> 67634 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/german-kinergo/layout.pngbin0 -> 71175 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/german-kinergo/readme.md35
-rw-r--r--keyboards/ergodox_ez/keymaps/german-manuneo/compile_keymap.py710
-rw-r--r--keyboards/ergodox_ez/keymaps/german-manuneo/keymap.c783
-rw-r--r--keyboards/ergodox_ez/keymaps/german-manuneo/keymap.md188
-rw-r--r--keyboards/ergodox_ez/keymaps/german/keymap.c185
-rw-r--r--keyboards/ergodox_ez/keymaps/j3rn/keymap.c187
-rw-r--r--keyboards/ergodox_ez/keymaps/j3rn/readme.md29
-rw-r--r--keyboards/ergodox_ez/keymaps/jack/keymap.c118
-rw-r--r--keyboards/ergodox_ez/keymaps/jacobono/img/colemak-default-layer.pngbin0 -> 70434 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/jacobono/img/number-dpad-layer.pngbin0 -> 46225 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/jacobono/img/symbol-layer.pngbin0 -> 49615 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/jacobono/keymap.c273
-rw-r--r--keyboards/ergodox_ez/keymaps/jacobono/readme.md34
-rw-r--r--keyboards/ergodox_ez/keymaps/jgarr/keymap.c184
-rw-r--r--keyboards/ergodox_ez/keymaps/kastyle/keymap.c184
-rw-r--r--keyboards/ergodox_ez/keymaps/kines-ish/keymap.c184
-rw-r--r--keyboards/ergodox_ez/keymaps/kines-ish/readme.md19
-rw-r--r--keyboards/ergodox_ez/keymaps/mpiechotka/keymap.c276
-rw-r--r--keyboards/ergodox_ez/keymaps/mpiechotka/readme.md6
-rw-r--r--keyboards/ergodox_ez/keymaps/msc/img/code_layer.pngbin0 -> 71266 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/msc/img/main_layer.pngbin0 -> 90624 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/msc/img/media_layer.pngbin0 -> 75750 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/msc/keymap.c184
-rw-r--r--keyboards/ergodox_ez/keymaps/msc/readme.md32
-rw-r--r--keyboards/ergodox_ez/keymaps/naps62/keymap.c187
-rw-r--r--keyboards/ergodox_ez/keymaps/naps62/readme.md29
-rw-r--r--keyboards/ergodox_ez/keymaps/ordinary/keymap.c454
-rw-r--r--keyboards/ergodox_ez/keymaps/ordinary/ordinary-base.pngbin0 -> 99605 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/ordinary/ordinary-base.txt27
-rw-r--r--keyboards/ergodox_ez/keymaps/ordinary/ordinary-media.pngbin0 -> 124144 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/ordinary/ordinary-media.txt27
-rw-r--r--keyboards/ergodox_ez/keymaps/ordinary/ordinary-special.pngbin0 -> 63065 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/ordinary/ordinary-special.txt27
-rw-r--r--keyboards/ergodox_ez/keymaps/ordinary/ordinary-symbol.pngbin0 -> 103735 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/ordinary/ordinary-symbol.txt27
-rw-r--r--keyboards/ergodox_ez/keymaps/ordinary/readme.md103
-rw-r--r--keyboards/ergodox_ez/keymaps/osx_de/keymap.c364
-rw-r--r--keyboards/ergodox_ez/keymaps/osx_de/osx_de_highres.pngbin0 -> 298446 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/osx_de/readme.md41
-rw-r--r--keyboards/ergodox_ez/keymaps/osx_de_adnw_koy/keymap.c174
-rw-r--r--keyboards/ergodox_ez/keymaps/osx_de_adnw_koy/osx_de_adnw_koy_highres.pngbin0 -> 183892 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/osx_de_experimental/keymap.c597
-rw-r--r--keyboards/ergodox_ez/keymaps/osx_de_experimental/osx_de_experimental_highres.pngbin0 -> 303904 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/osx_de_experimental/readme.md22
-rw-r--r--keyboards/ergodox_ez/keymaps/osx_fr/keymap.c187
-rw-r--r--keyboards/ergodox_ez/keymaps/osx_kinesis_pnut/keymap.c191
-rw-r--r--keyboards/ergodox_ez/keymaps/plover/keymap.c228
-rw-r--r--keyboards/ergodox_ez/keymaps/plums/keymap.c229
-rw-r--r--keyboards/ergodox_ez/keymaps/plums/plums.pngbin0 -> 223300 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/plums/readme.md11
-rw-r--r--keyboards/ergodox_ez/keymaps/romanzolotarev-norman-osx/keymap.c46
-rw-r--r--keyboards/ergodox_ez/keymaps/romanzolotarev-norman-osx/readme.md28
-rw-r--r--keyboards/ergodox_ez/keymaps/romanzolotarev-norman-osx/romanzolotarev-norman-osx.pngbin0 -> 96954 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/romanzolotarev-norman-plover-osx-hjkl/keymap.c134
-rw-r--r--keyboards/ergodox_ez/keymaps/romanzolotarev-norman-plover-osx-hjkl/readme.md50
-rw-r--r--keyboards/ergodox_ez/keymaps/romanzolotarev-norman-plover-osx-hjkl/romanzolotarev-norman-plover-osx-hjkl.pngbin0 -> 130692 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/romanzolotarev-norman-plover-osx/keymap.c134
-rw-r--r--keyboards/ergodox_ez/keymaps/romanzolotarev-norman-plover-osx/readme.md50
-rw-r--r--keyboards/ergodox_ez/keymaps/romanzolotarev-norman-plover-osx/romanzolotarev-norman-plover-osx.pngbin0 -> 130464 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/romanzolotarev-norman-qwerty-osx/keymap.c74
-rw-r--r--keyboards/ergodox_ez/keymaps/romanzolotarev-norman-qwerty-osx/readme.md34
-rw-r--r--keyboards/ergodox_ez/keymaps/romanzolotarev-norman-qwerty-osx/romanzolotarev-norman-qwerty-osx.pngbin0 -> 100627 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/sneako/keymap.c187
-rw-r--r--keyboards/ergodox_ez/keymaps/sneako/readme.md6
-rw-r--r--keyboards/ergodox_ez/keymaps/software_neo2/keymap.c139
-rw-r--r--keyboards/ergodox_ez/keymaps/supercoder/config_user.h9
-rw-r--r--keyboards/ergodox_ez/keymaps/supercoder/images/layout.pngbin0 -> 65607 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/supercoder/images/supercoder_2000.jpgbin0 -> 75444 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/supercoder/keymap.c75
-rw-r--r--keyboards/ergodox_ez/keymaps/supercoder/makefile.mk6
-rw-r--r--keyboards/ergodox_ez/keymaps/supercoder/readme.md29
-rw-r--r--keyboards/ergodox_ez/keymaps/techtomas/keymap.c231
-rw-r--r--keyboards/ergodox_ez/keymaps/techtomas/readme.md57
-rw-r--r--keyboards/ergodox_ez/keymaps/tkuichooseyou/README.md13
-rw-r--r--keyboards/ergodox_ez/keymaps/tkuichooseyou/compiled.hex1137
-rw-r--r--keyboards/ergodox_ez/keymaps/tkuichooseyou/keymap.c184
-rw-r--r--keyboards/ergodox_ez/keymaps/tm2030/keymap.c242
-rw-r--r--keyboards/ergodox_ez/keymaps/tm2030/readme.md136
-rw-r--r--keyboards/ergodox_ez/keymaps/tonyabra_osx/keymap.c184
-rw-r--r--keyboards/ergodox_ez/keymaps/tonyabra_osx/readme.md5
-rw-r--r--keyboards/ergodox_ez/keymaps/townk_osx/config.h92
-rw-r--r--keyboards/ergodox_ez/keymaps/townk_osx/keymap.c285
-rw-r--r--keyboards/ergodox_ez/keymaps/townk_osx/makefile.mk4
-rw-r--r--keyboards/ergodox_ez/keymaps/townk_osx/readme.md77
-rw-r--r--keyboards/ergodox_ez/keymaps/townk_osx/townk_osx_base.pngbin0 -> 785859 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/townk_osx/townk_osx_fn.pngbin0 -> 390041 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/townk_osx/townk_osx_keypad.pngbin0 -> 424425 bytes
-rw-r--r--keyboards/ergodox_ez/keymaps/twey/keymap.c221
-rw-r--r--keyboards/ergodox_ez/keymaps/twey/readme.md17
-rw-r--r--keyboards/ergodox_ez/keymaps/workman_osx_mdw/keymap.c366
-rw-r--r--keyboards/ergodox_ez/keymaps/zweihander-osx/keymap.c233
-rw-r--r--keyboards/ergodox_ez/keymaps/zweihander-osx/readme.markdown45
-rw-r--r--keyboards/ergodox_ez/matrix.c370
-rw-r--r--keyboards/ergodox_ez/readme.md44
-rw-r--r--keyboards/ergodox_ez/twimaster.c208
-rw-r--r--keyboards/ergodox_ez/util/compile_keymap.py710
-rw-r--r--keyboards/ergodox_ez/util/readme.md3
-rw-r--r--keyboards/gh60/Makefile74
-rw-r--r--keyboards/gh60/config.h161
-rw-r--r--keyboards/gh60/gh60.c25
-rw-r--r--keyboards/gh60/gh60.h74
-rw-r--r--keyboards/gh60/gh60revc.jpgbin0 -> 1424987 bytes
-rw-r--r--keyboards/gh60/keymaps/default/keymap.c69
-rw-r--r--keyboards/gh60/pinout.txt18
-rw-r--r--keyboards/gh60/readme.md60
-rw-r--r--keyboards/handwired/Makefile3
-rw-r--r--keyboards/handwired/fivethirteen/Makefile73
-rw-r--r--keyboards/handwired/fivethirteen/README.md28
-rw-r--r--keyboards/handwired/fivethirteen/config.h162
-rw-r--r--keyboards/handwired/fivethirteen/fivethirteen.c8
-rw-r--r--keyboards/handwired/fivethirteen/fivethirteen.h21
-rw-r--r--keyboards/handwired/fivethirteen/keymaps/default/keymap.c49
-rw-r--r--keyboards/handwired/handwired.c1
-rw-r--r--keyboards/handwired/handwired.h1
-rw-r--r--keyboards/handwired/onekey/Makefile65
-rw-r--r--keyboards/handwired/onekey/config.h75
-rw-r--r--keyboards/handwired/onekey/keymaps/default/keymap.c5
-rw-r--r--keyboards/handwired/onekey/onekey.c1
-rw-r--r--keyboards/handwired/onekey/onekey.h1
-rw-r--r--keyboards/hhkb/Makefile86
-rw-r--r--keyboards/hhkb/config.h71
-rw-r--r--keyboards/hhkb/hhkb.c1
-rw-r--r--keyboards/hhkb/hhkb.h24
-rw-r--r--keyboards/hhkb/hhkb_avr.h167
-rw-r--r--keyboards/hhkb/keymaps/default/keymap.c78
-rw-r--r--keyboards/hhkb/keymaps/lxol/keymap.c208
-rw-r--r--keyboards/hhkb/matrix.c215
-rw-r--r--keyboards/hhkb/readme.md180
-rw-r--r--keyboards/infinity_chibios/MEMO.txt385
-rw-r--r--keyboards/infinity_chibios/Makefile70
-rw-r--r--keyboards/infinity_chibios/bootloader_defs.h1
-rw-r--r--keyboards/infinity_chibios/chconf.h524
-rw-r--r--keyboards/infinity_chibios/config.h75
-rw-r--r--keyboards/infinity_chibios/halconf.h353
-rw-r--r--keyboards/infinity_chibios/infinity_chibios.c17
-rw-r--r--keyboards/infinity_chibios/infinity_chibios.h66
-rw-r--r--keyboards/infinity_chibios/keymaps/default/keymap.c48
-rw-r--r--keyboards/infinity_chibios/keymaps/hasu/keymap.c199
-rw-r--r--keyboards/infinity_chibios/led.c24
-rw-r--r--keyboards/infinity_chibios/matrix.c128
-rw-r--r--keyboards/infinity_chibios/mcuconf.h55
-rw-r--r--keyboards/infinity_ergodox/MEMO.txt385
-rw-r--r--keyboards/infinity_ergodox/Makefile72
-rw-r--r--keyboards/infinity_ergodox/bootloader_defs.h1
-rw-r--r--keyboards/infinity_ergodox/chconf.h524
-rw-r--r--keyboards/infinity_ergodox/config.h80
-rw-r--r--keyboards/infinity_ergodox/halconf.h353
-rw-r--r--keyboards/infinity_ergodox/infinity_ergodox.c1
-rw-r--r--keyboards/infinity_ergodox/infinity_ergodox.h44
-rw-r--r--keyboards/infinity_ergodox/keymaps/default/keymap.c111
-rw-r--r--keyboards/infinity_ergodox/led.c49
-rw-r--r--keyboards/infinity_ergodox/matrix.c169
-rw-r--r--keyboards/infinity_ergodox/mcuconf.h74
-rw-r--r--keyboards/jd45/Makefile71
-rw-r--r--keyboards/jd45/config.h82
-rw-r--r--keyboards/jd45/jd45.c1
-rw-r--r--keyboards/jd45/jd45.h20
-rw-r--r--keyboards/jd45/keymaps/default/keymap.c17
-rw-r--r--keyboards/jd45/keymaps/justin/keymap.c86
-rw-r--r--keyboards/kc60/Makefile76
-rw-r--r--keyboards/kc60/config.h164
-rw-r--r--keyboards/kc60/kc60.c1
-rw-r--r--keyboards/kc60/kc60.h23
-rw-r--r--keyboards/kc60/keymaps/default/keymap.c24
-rw-r--r--keyboards/kc60/keymaps/sgoodwin/keymap.c42
-rw-r--r--keyboards/kc60/keymaps/stanleylai/Makefile25
-rw-r--r--keyboards/kc60/keymaps/stanleylai/base_layer.pngbin0 -> 35164 bytes
-rw-r--r--keyboards/kc60/keymaps/stanleylai/config.h3
-rw-r--r--keyboards/kc60/keymaps/stanleylai/keymap.c151
-rw-r--r--keyboards/kc60/keymaps/stanleylai/readme.md26
-rw-r--r--keyboards/kc60/keymaps/stanleylai/rgb_layer.pngbin0 -> 19192 bytes
-rw-r--r--keyboards/kc60/keymaps/wigguno/Makefile24
-rw-r--r--keyboards/kc60/keymaps/wigguno/keymap.c62
-rw-r--r--keyboards/kc60/keymaps/wigguno/readme.md14
-rw-r--r--keyboards/kc60/keymaps/ws2812/Makefile25
-rw-r--r--keyboards/kc60/keymaps/ws2812/config.h10
-rw-r--r--keyboards/kc60/keymaps/ws2812/keymap.c161
-rw-r--r--keyboards/kc60/keymaps/ws2812/readme.md21
-rw-r--r--keyboards/kc60/keymaps/ws2812/ws2812_example.jpgbin0 -> 226362 bytes
-rw-r--r--keyboards/kc60/keymaps/ws2812/ws2812_underside-lit.jpgbin0 -> 205067 bytes
-rw-r--r--keyboards/kc60/keymaps/ws2812/ws2812_underside.jpgbin0 -> 354124 bytes
-rw-r--r--keyboards/kc60/keymaps/ws2812/ws2812_wiring.jpgbin0 -> 347989 bytes
-rw-r--r--keyboards/kc60/readme.md27
-rw-r--r--keyboards/phantom/Makefile74
-rw-r--r--keyboards/phantom/config.h91
-rw-r--r--keyboards/phantom/keymaps/default/keymap.c169
-rw-r--r--keyboards/phantom/led.c43
-rw-r--r--keyboards/phantom/phantom.c9
-rw-r--r--keyboards/phantom/phantom.h40
-rw-r--r--keyboards/phantom/pinout.jpgbin0 -> 86118 bytes
-rw-r--r--keyboards/phantom/pinout.txt1
-rw-r--r--keyboards/planck/Makefile74
-rw-r--r--keyboards/planck/config.h88
-rw-r--r--keyboards/planck/keymaps/ab/Makefile63
-rw-r--r--keyboards/planck/keymaps/ab/keyboard-layout.json185
-rw-r--r--keyboards/planck/keymaps/ab/keyboard-layout.pngbin0 -> 26518 bytes
-rw-r--r--keyboards/planck/keymaps/ab/keyboard-photo.jpgbin0 -> 252997 bytes
-rw-r--r--keyboards/planck/keymaps/ab/keymap.c132
-rw-r--r--keyboards/planck/keymaps/ab/readme.md18
-rw-r--r--keyboards/planck/keymaps/alexey/Makefile25
-rw-r--r--keyboards/planck/keymaps/alexey/keymap.c51
-rw-r--r--keyboards/planck/keymaps/angerthosenear/Makefile25
-rw-r--r--keyboards/planck/keymaps/angerthosenear/keymap.c39
-rw-r--r--keyboards/planck/keymaps/austin/Makefile25
-rw-r--r--keyboards/planck/keymaps/austin/keymap.c39
-rw-r--r--keyboards/planck/keymaps/basic/Makefile25
-rw-r--r--keyboards/planck/keymaps/basic/keymap.c94
-rw-r--r--keyboards/planck/keymaps/basic/readme.md2
-rw-r--r--keyboards/planck/keymaps/bone2planck/Makefile25
-rw-r--r--keyboards/planck/keymaps/bone2planck/keymap.c112
-rw-r--r--keyboards/planck/keymaps/brandon/Makefile25
-rw-r--r--keyboards/planck/keymaps/brandon/keymap.c134
-rw-r--r--keyboards/planck/keymaps/cbbrowne/Makefile25
-rw-r--r--keyboards/planck/keymaps/cbbrowne/config.h15
-rw-r--r--keyboards/planck/keymaps/cbbrowne/keymap.c173
-rw-r--r--keyboards/planck/keymaps/cbbrowne/readme.md64
-rw-r--r--keyboards/planck/keymaps/charlie/Makefile25
-rw-r--r--keyboards/planck/keymaps/charlie/keymap.c54
-rw-r--r--keyboards/planck/keymaps/daniel/Makefile25
-rw-r--r--keyboards/planck/keymaps/daniel/keymap.c37
-rw-r--r--keyboards/planck/keymaps/david/Makefile25
-rw-r--r--keyboards/planck/keymaps/david/keymap.c38
-rw-r--r--keyboards/planck/keymaps/default/Makefile25
-rw-r--r--keyboards/planck/keymaps/default/keymap.c314
-rw-r--r--keyboards/planck/keymaps/default/readme.md2
-rw-r--r--keyboards/planck/keymaps/dzobert/Makefile25
-rw-r--r--keyboards/planck/keymaps/dzobert/keymap.c38
-rw-r--r--keyboards/planck/keymaps/experimental/Makefile25
-rw-r--r--keyboards/planck/keymaps/experimental/config.h9
-rw-r--r--keyboards/planck/keymaps/experimental/keymap.c366
-rw-r--r--keyboards/planck/keymaps/experimental/readme.md2
-rw-r--r--keyboards/planck/keymaps/gabriel/Makefile25
-rw-r--r--keyboards/planck/keymaps/gabriel/keymap.c108
-rw-r--r--keyboards/planck/keymaps/jacob/Keyboard Layout.PNGbin0 -> 17292 bytes
-rw-r--r--keyboards/planck/keymaps/jacob/Makefile25
-rw-r--r--keyboards/planck/keymaps/jacob/keymap.c56
-rw-r--r--keyboards/planck/keymaps/jacob/readme.md1
-rw-r--r--keyboards/planck/keymaps/joe/Makefile25
-rw-r--r--keyboards/planck/keymaps/joe/keymap.c89
-rw-r--r--keyboards/planck/keymaps/kyle/Makefile25
-rw-r--r--keyboards/planck/keymaps/kyle/keymap.c38
-rw-r--r--keyboards/planck/keymaps/leo/Makefile25
-rw-r--r--keyboards/planck/keymaps/leo/keymap.c35
-rw-r--r--keyboards/planck/keymaps/lucas/Makefile25
-rw-r--r--keyboards/planck/keymaps/lucas/keymap.c164
-rw-r--r--keyboards/planck/keymaps/lukas/Makefile25
-rw-r--r--keyboards/planck/keymaps/lukas/keymap.c64
-rw-r--r--keyboards/planck/keymaps/max/Makefile25
-rw-r--r--keyboards/planck/keymaps/max/keymap.c38
-rw-r--r--keyboards/planck/keymaps/mollat/Makefile25
-rw-r--r--keyboards/planck/keymaps/mollat/keymap.c149
-rw-r--r--keyboards/planck/keymaps/nico/Makefile25
-rw-r--r--keyboards/planck/keymaps/nico/keymap.c69
-rw-r--r--keyboards/planck/keymaps/pete/Makefile15
-rw-r--r--keyboards/planck/keymaps/pete/keymap.c266
-rw-r--r--keyboards/planck/keymaps/pete/readme.md14
-rw-r--r--keyboards/planck/keymaps/pvc/Makefile24
-rw-r--r--keyboards/planck/keymaps/pvc/config.h89
-rw-r--r--keyboards/planck/keymaps/pvc/keymap.c478
-rw-r--r--keyboards/planck/keymaps/readme.md23
-rw-r--r--keyboards/planck/keymaps/tak3over/Makefile25
-rw-r--r--keyboards/planck/keymaps/tak3over/keymap.c130
-rw-r--r--keyboards/planck/keymaps/unicode/Makefile11
-rw-r--r--keyboards/planck/keymaps/unicode/keymap.c326
-rw-r--r--keyboards/planck/keymaps/yang/Makefile10
-rw-r--r--keyboards/planck/keymaps/yang/WS2812-wiring.jpgbin0 -> 290495 bytes
-rw-r--r--keyboards/planck/keymaps/yang/config.h15
-rw-r--r--keyboards/planck/keymaps/yang/keymap.c146
-rw-r--r--keyboards/planck/keymaps/yang/planck-with-rgb-underglow.jpgbin0 -> 343033 bytes
-rw-r--r--keyboards/planck/old_keymap_files/common_keymaps/keymap_brett.c42
-rw-r--r--keyboards/planck/old_keymap_files/common_keymaps/keymap_dotcom.c34
-rw-r--r--keyboards/planck/old_keymap_files/common_keymaps/keymap_jack.c50
-rw-r--r--keyboards/planck/old_keymap_files/common_keymaps/keymap_joe.c83
-rw-r--r--keyboards/planck/old_keymap_files/common_keymaps/keymap_matthew.c70
-rw-r--r--keyboards/planck/old_keymap_files/common_keymaps/keymap_mitch.c49
-rw-r--r--keyboards/planck/old_keymap_files/common_keymaps/keymap_nathan.c153
-rw-r--r--keyboards/planck/old_keymap_files/common_keymaps/keymap_paul.c49
-rw-r--r--keyboards/planck/old_keymap_files/common_keymaps/keymap_peasant.c51
-rw-r--r--keyboards/planck/old_keymap_files/common_keymaps/keymap_reed.c74
-rw-r--r--keyboards/planck/old_keymap_files/common_keymaps/keymap_sean.c53
-rw-r--r--keyboards/planck/old_keymap_files/common_keymaps/keymap_shane.c98
-rw-r--r--keyboards/planck/old_keymap_files/common_keymaps/keymap_simon.c44
-rw-r--r--keyboards/planck/old_keymap_files/common_keymaps/keymap_tim.c44
-rw-r--r--keyboards/planck/old_keymap_files/common_keymaps/keymap_wilba.c56
-rw-r--r--keyboards/planck/old_keymap_files/keymap_common.c30
-rw-r--r--keyboards/planck/old_keymap_files/keymap_common.h129
-rw-r--r--keyboards/planck/out.txt66
-rw-r--r--keyboards/planck/planck.c9
-rw-r--r--keyboards/planck/planck.h39
-rw-r--r--keyboards/planck/readme.md31
-rw-r--r--keyboards/planck/rev3/Makefile5
-rw-r--r--keyboards/planck/rev3/config.h8
-rw-r--r--keyboards/planck/rev3/rev3.c1
-rw-r--r--keyboards/planck/rev3/rev3.h6
-rw-r--r--keyboards/planck/rev4/Makefile5
-rw-r--r--keyboards/planck/rev4/config.h8
-rw-r--r--keyboards/planck/rev4/rev4.c1
-rw-r--r--keyboards/planck/rev4/rev4.h6
-rw-r--r--keyboards/preonic/Makefile73
-rw-r--r--keyboards/preonic/config.h91
-rw-r--r--keyboards/preonic/keymaps/default/Makefile25
-rw-r--r--keyboards/preonic/keymaps/default/keymap.c280
-rw-r--r--keyboards/preonic/keymaps/default/readme.md1
-rw-r--r--keyboards/preonic/preonic.c10
-rw-r--r--keyboards/preonic/preonic.h36
-rw-r--r--keyboards/preonic/readme.md25
-rw-r--r--keyboards/readme.md45
-rw-r--r--keyboards/retro_refit/Makefile74
-rw-r--r--keyboards/retro_refit/config.h123
-rw-r--r--keyboards/retro_refit/keymaps/default/keymap.c33
-rw-r--r--keyboards/retro_refit/readme.md24
-rw-r--r--keyboards/retro_refit/retro_refit.c47
-rw-r--r--keyboards/retro_refit/retro_refit.h38
-rw-r--r--keyboards/satan/Makefile70
-rw-r--r--keyboards/satan/config.h94
-rw-r--r--keyboards/satan/controller.jpgbin0 -> 140199 bytes
-rw-r--r--keyboards/satan/keymaps/default/keymap.c162
-rw-r--r--keyboards/satan/keymaps/sethbc/keymap.c149
-rw-r--r--keyboards/satan/pinout.txt1
-rw-r--r--keyboards/satan/power.jpgbin0 -> 433947 bytes
-rw-r--r--keyboards/satan/satan.c30
-rw-r--r--keyboards/satan/satan.h69
-rw-r--r--keyboards/sixkeyboard/Makefile75
-rw-r--r--keyboards/sixkeyboard/config.h115
-rw-r--r--keyboards/sixkeyboard/keymaps/default/keymap.c39
-rw-r--r--keyboards/sixkeyboard/matrix.c130
-rw-r--r--keyboards/sixkeyboard/readme.md18
-rw-r--r--keyboards/sixkeyboard/sixkeyboard.c30
-rw-r--r--keyboards/sixkeyboard/sixkeyboard.h18
m---------lib/chibios0
m---------lib/chibios-contrib0
-rw-r--r--quantum/analog.c53
-rw-r--r--quantum/analog.h36
-rw-r--r--quantum/audio/audio.c477
-rw-r--r--quantum/audio/audio.h91
-rw-r--r--quantum/audio/audio_pwm.c643
-rw-r--r--quantum/audio/luts.c382
-rw-r--r--quantum/audio/luts.h15
-rw-r--r--quantum/audio/musical_notes.h217
-rw-r--r--quantum/audio/song_list.h117
-rw-r--r--quantum/audio/voices.c165
-rw-r--r--quantum/audio/voices.h31
-rw-r--r--quantum/audio/wave.h265
-rw-r--r--quantum/config_common.h119
-rw-r--r--quantum/keycode_config.c74
-rw-r--r--quantum/keycode_config.h21
-rw-r--r--quantum/keymap.h328
-rw-r--r--quantum/keymap_common.c171
-rw-r--r--quantum/keymap_extras/keymap_bepo.h311
-rw-r--r--quantum/keymap_extras/keymap_colemak.h75
-rw-r--r--quantum/keymap_extras/keymap_dvorak.h74
-rw-r--r--quantum/keymap_extras/keymap_fr_ch.h98
-rw-r--r--quantum/keymap_extras/keymap_french.h83
-rw-r--r--quantum/keymap_extras/keymap_french_osx.h77
-rw-r--r--quantum/keymap_extras/keymap_german.h99
-rw-r--r--quantum/keymap_extras/keymap_german_ch.h102
-rw-r--r--quantum/keymap_extras/keymap_german_osx.h97
-rw-r--r--quantum/keymap_extras/keymap_neo2.h63
-rw-r--r--quantum/keymap_extras/keymap_nordic.h59
-rw-r--r--quantum/keymap_extras/keymap_norwegian.h41
-rw-r--r--quantum/keymap_extras/keymap_plover.h32
-rw-r--r--quantum/keymap_extras/keymap_spanish.h62
-rw-r--r--quantum/keymap_extras/keymap_uk.h36
-rwxr-xr-xquantum/light_ws2812.c181
-rwxr-xr-xquantum/light_ws2812.h73
-rw-r--r--quantum/matrix.c307
-rw-r--r--quantum/process_keycode/process_chording.c60
-rw-r--r--quantum/process_keycode/process_chording.h16
-rw-r--r--quantum/process_keycode/process_leader.c38
-rw-r--r--quantum/process_keycode/process_leader.h23
-rw-r--r--quantum/process_keycode/process_midi.c66
-rw-r--r--quantum/process_keycode/process_midi.h207
-rw-r--r--quantum/process_keycode/process_music.c171
-rw-r--r--quantum/process_keycode/process_music.h27
-rw-r--r--quantum/process_keycode/process_tap_dance.c90
-rw-r--r--quantum/process_keycode/process_tap_dance.h62
-rw-r--r--quantum/process_keycode/process_unicode.c57
-rw-r--r--quantum/process_keycode/process_unicode.h122
-rw-r--r--quantum/quantum.c717
-rw-r--r--quantum/quantum.h107
-rw-r--r--quantum/rgblight.c505
-rw-r--r--quantum/rgblight.h86
-rw-r--r--quantum/serial_link/.gitignore1
-rw-r--r--quantum/serial_link/.gitmodules3
-rw-r--r--quantum/serial_link/LICENSE (renamed from LICENSE)0
-rw-r--r--quantum/serial_link/README.md (renamed from README.md)0
-rw-r--r--quantum/serial_link/cgreen/Makefile (renamed from cgreen/Makefile)0
-rw-r--r--quantum/serial_link/cgreen/Makefile.build (renamed from cgreen/Makefile.build)0
m---------quantum/serial_link/cgreen/cgreen (renamed from cgreen/cgreen)0
-rw-r--r--quantum/serial_link/serial_link.mk (renamed from serial_link.mk)0
-rw-r--r--quantum/serial_link/serial_link/protocol/byte_stuffer.c (renamed from serial_link/protocol/byte_stuffer.c)0
-rw-r--r--quantum/serial_link/serial_link/protocol/byte_stuffer.h (renamed from serial_link/protocol/byte_stuffer.h)0
-rw-r--r--quantum/serial_link/serial_link/protocol/frame_router.c (renamed from serial_link/protocol/frame_router.c)0
-rw-r--r--quantum/serial_link/serial_link/protocol/frame_router.h (renamed from serial_link/protocol/frame_router.h)0
-rw-r--r--quantum/serial_link/serial_link/protocol/frame_validator.c (renamed from serial_link/protocol/frame_validator.c)0
-rw-r--r--quantum/serial_link/serial_link/protocol/frame_validator.h (renamed from serial_link/protocol/frame_validator.h)0
-rw-r--r--quantum/serial_link/serial_link/protocol/physical.h (renamed from serial_link/protocol/physical.h)0
-rw-r--r--quantum/serial_link/serial_link/protocol/transport.c (renamed from serial_link/protocol/transport.c)0
-rw-r--r--quantum/serial_link/serial_link/protocol/transport.h (renamed from serial_link/protocol/transport.h)0
-rw-r--r--quantum/serial_link/serial_link/protocol/triple_buffered_object.c (renamed from serial_link/protocol/triple_buffered_object.c)0
-rw-r--r--quantum/serial_link/serial_link/protocol/triple_buffered_object.h (renamed from serial_link/protocol/triple_buffered_object.h)0
-rw-r--r--quantum/serial_link/serial_link/system/serial_link.c (renamed from serial_link/system/serial_link.c)0
-rw-r--r--quantum/serial_link/serial_link/system/serial_link.h (renamed from serial_link/system/serial_link.h)0
-rw-r--r--quantum/serial_link/serial_link/tests/Makefile (renamed from serial_link/tests/Makefile)0
-rw-r--r--quantum/serial_link/serial_link/tests/byte_stuffer_tests.c (renamed from serial_link/tests/byte_stuffer_tests.c)0
-rw-r--r--quantum/serial_link/serial_link/tests/frame_router_tests.c (renamed from serial_link/tests/frame_router_tests.c)0
-rw-r--r--quantum/serial_link/serial_link/tests/frame_validator_tests.c (renamed from serial_link/tests/frame_validator_tests.c)0
-rw-r--r--quantum/serial_link/serial_link/tests/transport_tests.c (renamed from serial_link/tests/transport_tests.c)0
-rw-r--r--quantum/serial_link/serial_link/tests/triple_buffered_object_tests.c (renamed from serial_link/tests/triple_buffered_object_tests.c)0
-rw-r--r--quantum/serial_link/serial_link_tests.mk (renamed from serial_link_tests.mk)0
-rw-r--r--quantum/template/Makefile75
-rw-r--r--quantum/template/config.h162
-rw-r--r--quantum/template/keymaps/default/Makefile21
-rw-r--r--quantum/template/keymaps/default/config.h8
-rw-r--r--quantum/template/keymaps/default/keymap.c44
-rw-r--r--quantum/template/keymaps/default/readme.md1
-rw-r--r--quantum/template/readme.md28
-rw-r--r--quantum/template/template.c28
-rw-r--r--quantum/template/template.h19
-rw-r--r--quantum/tools/eeprom_reset.hex9
-rw-r--r--quantum/tools/readme.md6
-rw-r--r--readme.md813
-rw-r--r--tmk_core/.gitignore13
-rw-r--r--tmk_core/.gitmodules0
-rw-r--r--tmk_core/avr.mk186
-rw-r--r--tmk_core/chibios.mk158
-rw-r--r--tmk_core/common.mk112
-rw-r--r--tmk_core/common/action.c698
-rw-r--r--tmk_core/common/action.h90
-rw-r--r--tmk_core/common/action_code.h318
-rw-r--r--tmk_core/common/action_layer.c203
-rw-r--r--tmk_core/common/action_layer.h89
-rw-r--r--tmk_core/common/action_macro.c85
-rw-r--r--tmk_core/common/action_macro.h102
-rw-r--r--tmk_core/common/action_tapping.c377
-rw-r--r--tmk_core/common/action_tapping.h39
-rw-r--r--tmk_core/common/action_util.c378
-rw-r--r--tmk_core/common/action_util.h93
-rw-r--r--tmk_core/common/avr/bootloader.c185
-rw-r--r--tmk_core/common/avr/sleep_led.c95
-rw-r--r--tmk_core/common/avr/suspend.c148
-rw-r--r--tmk_core/common/avr/suspend_avr.h27
-rw-r--r--tmk_core/common/avr/timer.c117
-rw-r--r--tmk_core/common/avr/timer_avr.h42
-rw-r--r--tmk_core/common/avr/xprintf.S500
-rw-r--r--tmk_core/common/avr/xprintf.h111
-rw-r--r--tmk_core/common/backlight.c90
-rw-r--r--tmk_core/common/backlight.h41
-rw-r--r--tmk_core/common/bootloader.h25
-rw-r--r--tmk_core/common/bootmagic.c129
-rw-r--r--tmk_core/common/bootmagic.h100
-rw-r--r--tmk_core/common/chibios/bootloader.c47
-rw-r--r--tmk_core/common/chibios/eeprom.c588
-rw-r--r--tmk_core/common/chibios/printf.c240
-rw-r--r--tmk_core/common/chibios/printf.h111
-rw-r--r--tmk_core/common/chibios/sleep_led.c226
-rw-r--r--tmk_core/common/chibios/suspend.c65
-rw-r--r--tmk_core/common/chibios/timer.c27
-rw-r--r--tmk_core/common/command.c794
-rw-r--r--tmk_core/common/command.h157
-rw-r--r--tmk_core/common/debug.c24
-rw-r--r--tmk_core/common/debug.h117
-rw-r--r--tmk_core/common/eeconfig.c56
-rw-r--r--tmk_core/common/eeconfig.h82
-rw-r--r--tmk_core/common/eeprom.h22
-rw-r--r--tmk_core/common/host.c97
-rw-r--r--tmk_core/common/host.h57
-rw-r--r--tmk_core/common/host_driver.h33
-rw-r--r--tmk_core/common/keyboard.c188
-rw-r--r--tmk_core/common/keyboard.h74
-rw-r--r--tmk_core/common/keycode.h494
-rw-r--r--tmk_core/common/led.h43
-rw-r--r--tmk_core/common/magic.c38
-rw-r--r--tmk_core/common/magic.h6
-rw-r--r--tmk_core/common/matrix.h79
-rw-r--r--tmk_core/common/mbed/bootloader.c4
-rw-r--r--tmk_core/common/mbed/suspend.c6
-rw-r--r--tmk_core/common/mbed/timer.c41
-rw-r--r--tmk_core/common/mbed/xprintf.cpp51
-rw-r--r--tmk_core/common/mbed/xprintf.h17
-rw-r--r--tmk_core/common/mousekey.c196
-rw-r--r--tmk_core/common/mousekey.h77
-rw-r--r--tmk_core/common/nodebug.h29
-rw-r--r--tmk_core/common/print.c52
-rw-r--r--tmk_core/common/print.h145
-rw-r--r--tmk_core/common/progmem.h12
-rw-r--r--tmk_core/common/report.h188
-rw-r--r--tmk_core/common/sendchar.h35
-rw-r--r--tmk_core/common/sendchar_null.c23
-rw-r--r--tmk_core/common/sendchar_uart.c25
-rw-r--r--tmk_core/common/sleep_led.h21
-rw-r--r--tmk_core/common/suspend.h13
-rw-r--r--tmk_core/common/timer.h53
-rw-r--r--tmk_core/common/uart.c129
-rw-r--r--tmk_core/common/uart.h11
-rw-r--r--tmk_core/common/util.c101
-rw-r--r--tmk_core/common/util.h43
-rw-r--r--tmk_core/common/wait.h24
-rw-r--r--tmk_core/ldscript_keymap_avr35.x268
-rw-r--r--tmk_core/ldscript_keymap_avr5.x268
-rw-r--r--tmk_core/protocol.mk54
-rw-r--r--tmk_core/protocol/adb.c478
-rw-r--r--tmk_core/protocol/adb.h66
-rw-r--r--tmk_core/protocol/bluefruit.mk27
-rw-r--r--tmk_core/protocol/bluefruit/bluefruit.c205
-rw-r--r--tmk_core/protocol/bluefruit/bluefruit.h25
-rw-r--r--tmk_core/protocol/bluefruit/main.c138
-rw-r--r--tmk_core/protocol/chibios.mk10
-rw-r--r--tmk_core/protocol/chibios/README.md55
-rw-r--r--tmk_core/protocol/chibios/main.c147
-rw-r--r--tmk_core/protocol/chibios/usb_main.c1372
-rw-r--r--tmk_core/protocol/chibios/usb_main.h139
-rw-r--r--tmk_core/protocol/ibm4704.c189
-rw-r--r--tmk_core/protocol/ibm4704.h110
-rw-r--r--tmk_core/protocol/iwrap.mk26
-rw-r--r--tmk_core/protocol/iwrap/iWRAP4.txt376
-rw-r--r--tmk_core/protocol/iwrap/iWRAP5.txt356
-rw-r--r--tmk_core/protocol/iwrap/iwrap.c469
-rw-r--r--tmk_core/protocol/iwrap/iwrap.h49
-rw-r--r--tmk_core/protocol/iwrap/main.c376
-rw-r--r--tmk_core/protocol/iwrap/mux_exit.rb7
-rw-r--r--tmk_core/protocol/iwrap/suart.S156
-rw-r--r--tmk_core/protocol/iwrap/suart.h8
-rw-r--r--tmk_core/protocol/iwrap/wd.h159
-rw-r--r--tmk_core/protocol/lufa.mk60
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/.gitignore14
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/BootloaderAPI.c75
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/BootloaderAPI.h58
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/BootloaderAPITable.S91
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/BootloaderCDC.c641
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/BootloaderCDC.h144
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/BootloaderCDC.txt240
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/Config/AppConfig.h50
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/Config/LUFAConfig.h93
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/Descriptors.c244
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/Descriptors.h158
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/LUFA CDC Bootloader.inf66
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/asf.xml161
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/doxyfile2365
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/makefile55
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/BootloaderAPI.c76
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/BootloaderAPI.h58
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/BootloaderAPITable.S91
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/BootloaderDFU.c804
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/BootloaderDFU.h216
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/BootloaderDFU.txt233
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/Config/AppConfig.h48
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/Config/LUFAConfig.h93
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/Descriptors.c185
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/Descriptors.h194
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/asf.xml156
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/doxyfile2365
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/makefile55
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/BootloaderHID.c190
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/BootloaderHID.h73
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/BootloaderHID.txt105
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/Config/LUFAConfig.h93
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/Descriptors.c187
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/Descriptors.h80
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/HostLoaderApp/Makefile39
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/HostLoaderApp/Makefile.bsd21
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/HostLoaderApp/gpl3.txt674
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/HostLoaderApp/hid_bootloader_cli.c1010
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/HostLoaderApp_Python/hid_bootloader_loader.py120
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/asf.xml123
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/doxyfile2367
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/makefile48
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/BootloaderAPI.c76
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/BootloaderAPI.h63
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/BootloaderAPITable.S102
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/BootloaderMassStorage.c238
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/BootloaderMassStorage.h99
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/BootloaderMassStorage.txt225
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Config/AppConfig.h47
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Config/LUFAConfig.h93
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Descriptors.c157
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Descriptors.h88
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Lib/SCSI.c294
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Lib/SCSI.h84
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Lib/VirtualFAT.c482
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Lib/VirtualFAT.h302
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/asf.xml156
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/doxyfile2365
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/makefile68
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/BootloaderAPI.c75
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/BootloaderAPI.h56
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/BootloaderAPITable.S91
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/BootloaderPrinter.c431
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/BootloaderPrinter.h108
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/BootloaderPrinter.txt190
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/Config/LUFAConfig.h93
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/Descriptors.c194
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/Descriptors.h96
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/asf.xml159
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/doxyfile2365
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/makefile55
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Bootloaders/makefile46
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/Board/Board.h82
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/Board/Buttons.h92
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/Board/Dataflash.h197
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/Board/Joystick.h104
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/Board/LEDs.h132
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/BoardDeviceMap.cfg87
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/Test.c115
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/makefile68
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/makefile.test27
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/BuildTests/BootloaderTest/BootloaderDeviceMap.cfg167
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/BuildTests/BootloaderTest/makefile64
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/BuildTests/ModuleTest/Dummy.S41
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/BuildTests/ModuleTest/Modules.h56
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/BuildTests/ModuleTest/Test_C.c31
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/BuildTests/ModuleTest/Test_CPP.cpp31
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/BuildTests/ModuleTest/makefile66
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/BuildTests/ModuleTest/makefile.test88
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/BuildTests/SingleUSBModeTest/Dummy.S42
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/BuildTests/SingleUSBModeTest/Test.c32
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/BuildTests/SingleUSBModeTest/makefile56
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/BuildTests/SingleUSBModeTest/makefile.test69
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/BuildTests/StaticAnalysisTest/makefile47
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/BuildTests/makefile24
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Build/HID_EEPROM_Loader/HID_EEPROM_Loader.c61
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Build/HID_EEPROM_Loader/makefile42
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_atprogram.mk103
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_avrdude.mk86
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_build.mk351
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_core.mk175
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_cppcheck.mk107
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_dfu.mk95
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_doxygen.mk100
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_hid.mk96
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_sources.mk144
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DeviceTemplate/Descriptors.c180
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DeviceTemplate/Descriptors.h59
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DeviceTemplate/DeviceApplication.c106
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DeviceTemplate/DeviceApplication.h53
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DeviceTemplate/asf.xml55
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DriverStubs/Board.h82
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DriverStubs/Buttons.h90
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DriverStubs/Dataflash.h223
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DriverStubs/Joystick.h102
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DriverStubs/LEDs.h130
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/HostTemplate/HostApplication.c133
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/HostTemplate/HostApplication.h56
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/HostTemplate/asf.xml41
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/LUFAConfig.h167
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/WindowsINF/LUFA CDC-ACM.inf64
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/WindowsINF/LUFA RNDIS.inf59
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/makefile_template38
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Common/ArchitectureSpecific.h185
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Common/Architectures.h84
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Common/Attributes.h150
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Common/BoardTypes.h254
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Common/Common.h393
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Common/CompilerSpecific.h97
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Common/Endianness.h493
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/BuildSystem.txt975
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/BuildingLinkableLibraries.txt23
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/ChangeLog.txt1597
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/CompileTimeTokens.txt223
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/CompilingApps.txt46
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/ConfiguringApps.txt157
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/DevelopingWithLUFA.txt24
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/DeviceSupport.txt422
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/DirectorySummaries.txt80
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Donating.txt26
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/ExportingLibrary.txt112
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/FutureChanges.txt47
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/GettingStarted.txt37
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Groups.txt38
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step1.pngbin0 -> 98201 bytes
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step2.pngbin0 -> 100532 bytes
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step3.pngbin0 -> 32987 bytes
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step4.pngbin0 -> 161824 bytes
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step5_1.pngbin0 -> 43666 bytes
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step5_2.pngbin0 -> 28918 bytes
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step5_3.pngbin0 -> 23561 bytes
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/Author.jpgbin0 -> 28410 bytes
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/LUFA.pngbin0 -> 10296 bytes
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/LUFA_thumb.pngbin0 -> 3729 bytes
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/KnownIssues.txt170
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/LUFAPoweredProjects.txt224
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/LibraryResources.txt33
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/LicenseInfo.txt43
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/MainPage.txt52
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/MigrationInformation.txt708
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/OSDrivers.txt111
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/ProgrammingApps.txt30
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/SoftwareBootloaderJump.txt71
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Style/Footer.htm35
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Style/Style.css93
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/VIDAndPIDValues.txt199
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/WritingBoardDrivers.txt47
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/ADAFRUITU4/Board.h78
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/ADAFRUITU4/LEDs.h135
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/Board.h82
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/Buttons.h103
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/LEDs.h139
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BENITO/Board.h82
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BENITO/Buttons.h103
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BENITO/LEDs.h139
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BIGMULTIO/Board.h78
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BIGMULTIO/LEDs.h161
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BLACKCAT/Board.h78
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BLACKCAT/LEDs.h139
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BUI/Board.h78
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BUI/LEDs.h143
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BUMBLEB/Board.h86
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BUMBLEB/Buttons.h105
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BUMBLEB/Joystick.h123
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BUMBLEB/LEDs.h149
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/CULV3/Board.h82
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/CULV3/Buttons.h103
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/CULV3/LEDs.h135
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/DUCE/Board.h78
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/DUCE/LEDs.h147
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/EVK527/Board.h90
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/EVK527/Buttons.h103
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/EVK527/Dataflash.h222
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/EVK527/Joystick.h130
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/EVK527/LEDs.h143
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/JMDBU2/Board.h82
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/JMDBU2/Buttons.h103
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/JMDBU2/LEDs.h135
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/LEONARDO/Board.h78
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/LEONARDO/LEDs.h169
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MAXIMUS/Board.h78
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MAXIMUS/LEDs.h139
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICRO/Board.h78
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICRO/LEDs.h169
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICROPENDOUS/Board.h149
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICROPENDOUS/Buttons.h205
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICROPENDOUS/LEDs.h174
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICROSIN162/Board.h82
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICROSIN162/Buttons.h103
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICROSIN162/LEDs.h135
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MINIMUS/Board.h82
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MINIMUS/Buttons.h103
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MINIMUS/LEDs.h139
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MULTIO/Board.h78
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MULTIO/LEDs.h161
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEX162/Board.h82
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEX162/Buttons.h103
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEX162/LEDs.h135
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEX32U4/Board.h82
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEX32U4/Buttons.h103
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEX32U4/LEDs.h179
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/Board.h82
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/Buttons.h103
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/LEDs.h143
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/Board.h82
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/Buttons.h103
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/LEDs.h169
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/RZUSBSTICK/Board.h78
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/RZUSBSTICK/LEDs.h175
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/SPARKFUN8U2/Board.h78
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/SPARKFUN8U2/LEDs.h135
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STANGE_ISP/Board.h82
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STANGE_ISP/Buttons.h103
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STANGE_ISP/LEDs.h138
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK525/Board.h90
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK525/Buttons.h103
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK525/Dataflash.h222
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK525/Joystick.h130
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK525/LEDs.h147
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK526/Board.h90
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK526/Buttons.h103
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK526/Dataflash.h222
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK526/Joystick.h123
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK526/LEDs.h147
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/TEENSY/Board.h85
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/TEENSY/LEDs.h176
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/TUL/Board.h82
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/TUL/Buttons.h103
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/TUL/LEDs.h135
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/U2S/Board.h82
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/U2S/Buttons.h103
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/U2S/LEDs.h135
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/UDIP/Board.h82
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/UDIP/Buttons.h103
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/UDIP/LEDs.h163
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/UNO/Board.h78
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/UNO/LEDs.h139
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USB2AX/Board.h105
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USB2AX/Buttons.h120
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USB2AX/LEDs.h218
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBFOO/Board.h82
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBFOO/Buttons.h103
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBFOO/LEDs.h135
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBKEY/Board.h90
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBKEY/Buttons.h103
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBKEY/Dataflash.h237
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBKEY/Joystick.h130
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBKEY/LEDs.h147
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBTINYMKII/Board.h82
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBTINYMKII/Buttons.h103
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBTINYMKII/LEDs.h143
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/XPLAIN/Board.h89
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/XPLAIN/Dataflash.h245
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/XPLAIN/LEDs.h142
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/YUN/Board.h78
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/YUN/LEDs.h169
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/Board.h167
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/Buttons.h188
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/Dataflash.h264
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/Joystick.h151
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/LEDs.h298
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/Temperature.c66
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/Temperature.h147
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1100/Board.h86
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1100/Buttons.h117
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1100/Joystick.h122
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1100/LEDs.h173
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1101/Board.h86
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1101/Buttons.h113
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1101/Joystick.h131
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1101/LEDs.h156
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1104/Board.h82
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1104/Buttons.h109
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1104/LEDs.h174
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/UC3A3_XPLAINED/Board.h82
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/UC3A3_XPLAINED/Buttons.h109
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/UC3A3_XPLAINED/LEDs.h182
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Board.h86
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Buttons.h119
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Dataflash.h228
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/LEDs.h181
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Board.h86
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Buttons.h119
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Dataflash.h229
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/LEDs.h183
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/C3_XPLAINED/Board.h83
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/C3_XPLAINED/Buttons.h109
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/C3_XPLAINED/LEDs.h181
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Misc/AT45DB321C.h100
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Misc/AT45DB642D.h116
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Misc/RingBuffer.h308
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Misc/TerminalCodes.h231
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/ADC.h75
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/AVR8/ADC_AVR8.h446
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/AVR8/SPI_AVR8.h258
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/AVR8/SerialSPI_AVR8.h208
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/AVR8/Serial_AVR8.c119
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/AVR8/Serial_AVR8.h270
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.c209
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.h305
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/SPI.h76
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/Serial.h76
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/SerialSPI.h76
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/TWI.h76
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/XMEGA/SPI_XMEGA.h251
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/XMEGA/SerialSPI_XMEGA.h212
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.c122
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.h286
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/XMEGA/TWI_XMEGA.c185
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/XMEGA/TWI_XMEGA.h302
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/AndroidAccessoryClass.h77
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/AudioClass.h81
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/CDCClass.h81
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/AndroidAccessoryClassCommon.h129
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/AudioClassCommon.h780
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/CDCClassCommon.h391
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/HIDClassCommon.h682
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/HIDParser.c389
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/HIDParser.h364
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/HIDReportData.h126
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/MIDIClassCommon.h363
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/MassStorageClassCommon.h368
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/PrinterClassCommon.h119
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/RNDISClassCommon.h411
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/StillImageClassCommon.h161
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/AudioClassDevice.c197
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/AudioClassDevice.h396
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/CDCClassDevice.c341
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/CDCClassDevice.h352
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/HIDClassDevice.c211
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/HIDClassDevice.h210
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.c131
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.h175
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.c215
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.h161
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/PrinterClassDevice.c314
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/PrinterClassDevice.h293
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.c508
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.h207
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/HIDClass.h82
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/AndroidAccessoryClassHost.c422
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/AndroidAccessoryClassHost.h314
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/AudioClassHost.c223
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/AudioClassHost.h411
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/CDCClassHost.c477
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/CDCClassHost.h351
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/HIDClassHost.c399
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/HIDClassHost.h313
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/MIDIClassHost.c231
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/MIDIClassHost.h190
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/MassStorageClassHost.c579
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/MassStorageClassHost.h335
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/PrinterClassHost.c400
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/PrinterClassHost.h285
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/RNDISClassHost.c476
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/RNDISClassHost.h270
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/StillImageClassHost.c436
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/StillImageClassHost.h317
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/MIDIClass.h84
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/MassStorageClass.h81
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/PrinterClass.h83
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/RNDISClass.h81
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/StillImageClass.h76
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Device_AVR8.c57
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Device_AVR8.h269
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/EndpointStream_AVR8.c275
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/EndpointStream_AVR8.h658
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.c201
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.h819
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Host_AVR8.c297
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Host_AVR8.h372
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/OTG_AVR8.h159
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/PipeStream_AVR8.c221
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/PipeStream_AVR8.h442
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.c210
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.h922
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_Control_R.c84
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_Control_W.c95
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_RW.c89
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Template/Template_Pipe_RW.c88
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/USBController_AVR8.c273
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/USBController_AVR8.h432
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/USBInterrupt_AVR8.c279
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/USBInterrupt_AVR8.h375
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/ConfigDescriptors.c146
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/ConfigDescriptors.h287
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/Device.h159
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/DeviceStandardReq.c380
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/DeviceStandardReq.h158
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/Endpoint.h130
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/EndpointStream.h124
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/Events.c39
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/Events.h372
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/Host.h139
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/HostStandardReq.c322
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/HostStandardReq.h292
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/OTG.h80
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/Pipe.h144
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/PipeStream.h100
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/StdDescriptors.h765
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/StdRequestType.h258
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Device_UC3.c51
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Device_UC3.h267
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/EndpointStream_UC3.c235
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/EndpointStream_UC3.h438
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.c196
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.h794
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Host_UC3.c297
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Host_UC3.h363
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/PipeStream_UC3.c166
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/PipeStream_UC3.h352
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Pipe_UC3.c209
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Pipe_UC3.h924
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_Control_R.c84
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_Control_W.c95
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_RW.c89
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Template/Template_Pipe_RW.c88
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/USBController_UC3.c222
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/USBController_UC3.h353
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/USBInterrupt_UC3.c228
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/USBInterrupt_UC3.h376
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/USBController.h165
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/USBInterrupt.h73
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/USBMode.h283
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/USBTask.c89
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/USBTask.h200
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.c49
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.h266
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/EndpointStream_XMEGA.c275
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/EndpointStream_XMEGA.h658
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.c268
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.h689
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Host_XMEGA.c41
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/PipeStream_XMEGA.c41
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Pipe_XMEGA.c37
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_Control_R.c86
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_Control_W.c97
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_RW.c89
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.c204
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.h313
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/USBInterrupt_XMEGA.c106
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/USBInterrupt_XMEGA.h172
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/USB.h422
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/License.txt24
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/Platform.h80
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/UC3/ClockManagement.h338
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/UC3/Exception.S128
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/UC3/InterruptManagement.c62
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/UC3/InterruptManagement.h174
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/UC3/UC3ExperimentalInfo.txt1
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/XMEGA/ClockManagement.h397
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/XMEGA/XMEGAExperimentalInfo.txt1
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/Docbook/mshelp/placeholder.txt1
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/Docbook/placeholder.txt1
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/HV1/helpcontentsetup.msha27
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/HV1/lufa_docbook_transform.xslt808
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/HV1/lufa_helpcontentsetup_transform.xslt43
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/HV1/lufa_hv1_transform.xslt45
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/HV1/lufa_studio_help_styling.css53
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/ProjectGenerator/placeholder.txt1
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/LUFA.dllbin0 -> 749056 bytes
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/LUFA.pkgdefbin0 -> 2242 bytes
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/[Content_Types].xml13
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/asf-manifest.xml18
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/extension.vsixmanifest33
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/generate_caches.py38
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/lufa_asfmanifest_transform.xslt36
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/lufa_vsmanifest_transform.xslt33
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/XDK/lufa_extension_transform.xslt68
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/XDK/lufa_filelist_transform.xslt35
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/XDK/lufa_indent_transform.xslt23
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/XDK/lufa_module_transform.xslt66
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa.xml96
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_common.xml34
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_board.xml114
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_board_names.xml853
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_misc.xml57
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_peripheral.xml198
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb.xml32
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class.xml32
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_android.xml54
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_audio.xml109
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_cdc.xml99
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_hid.xml99
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_midi.xml99
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_ms.xml99
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_printer.xml99
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_rndis.xml99
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_si.xml56
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_core.xml85
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_core_avr8.xml43
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_core_uc3.xml42
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_core_xmega.xml36
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_platform.xml60
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_platform_uc3.xml26
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_platform_xmega.xml23
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_toolchain.xml43
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/makefile140
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/Version.h52
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/doxyfile2368
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/LUFA/makefile53
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Maintenance/lufa_functionlist_transform.xslt19
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/Maintenance/makefile94
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/README.txt56
-rw-r--r--tmk_core/protocol/lufa/LUFA-git/makefile26
-rw-r--r--tmk_core/protocol/lufa/bluetooth.c36
-rw-r--r--tmk_core/protocol/lufa/bluetooth.h65
-rw-r--r--tmk_core/protocol/lufa/descriptor.c789
-rw-r--r--tmk_core/protocol/lufa/descriptor.h213
-rw-r--r--tmk_core/protocol/lufa/lufa.c977
-rw-r--r--tmk_core/protocol/lufa/lufa.h85
-rw-r--r--tmk_core/protocol/m0110.c591
-rw-r--r--tmk_core/protocol/m0110.h92
-rw-r--r--tmk_core/protocol/mbed/HIDKeyboard.cpp271
-rw-r--r--tmk_core/protocol/mbed/HIDKeyboard.h31
-rw-r--r--tmk_core/protocol/mbed/mbed_driver.cpp41
-rw-r--r--tmk_core/protocol/mbed/mbed_driver.h3
-rw-r--r--tmk_core/protocol/midi.mk9
-rwxr-xr-xtmk_core/protocol/midi/Config/LUFAConfig.h93
-rwxr-xr-xtmk_core/protocol/midi/bytequeue/COPYING674
-rwxr-xr-xtmk_core/protocol/midi/bytequeue/bytequeue.c65
-rwxr-xr-xtmk_core/protocol/midi/bytequeue/bytequeue.h59
-rwxr-xr-xtmk_core/protocol/midi/bytequeue/interrupt_setting.c36
-rwxr-xr-xtmk_core/protocol/midi/bytequeue/interrupt_setting.h39
-rwxr-xr-xtmk_core/protocol/midi/midi.c277
-rwxr-xr-xtmk_core/protocol/midi/midi.h498
-rwxr-xr-xtmk_core/protocol/midi/midi_device.c291
-rwxr-xr-xtmk_core/protocol/midi/midi_device.h156
-rwxr-xr-xtmk_core/protocol/midi/midi_function_types.h50
-rwxr-xr-xtmk_core/protocol/midi/sysex_tools.c99
-rwxr-xr-xtmk_core/protocol/midi/sysex_tools.h95
-rw-r--r--tmk_core/protocol/news.c168
-rw-r--r--tmk_core/protocol/news.h51
-rw-r--r--tmk_core/protocol/next_kbd.c212
-rw-r--r--tmk_core/protocol/next_kbd.h63
-rw-r--r--tmk_core/protocol/pjrc.mk30
-rw-r--r--tmk_core/protocol/pjrc/MEMO.txt25
-rw-r--r--tmk_core/protocol/pjrc/main.c74
-rw-r--r--tmk_core/protocol/pjrc/pjrc.c76
-rw-r--r--tmk_core/protocol/pjrc/pjrc.h26
-rw-r--r--tmk_core/protocol/pjrc/usb.c1002
-rw-r--r--tmk_core/protocol/pjrc/usb.h137
-rw-r--r--tmk_core/protocol/pjrc/usb_debug.c102
-rw-r--r--tmk_core/protocol/pjrc/usb_debug.h42
-rw-r--r--tmk_core/protocol/pjrc/usb_extra.c70
-rw-r--r--tmk_core/protocol/pjrc/usb_extra.h46
-rw-r--r--tmk_core/protocol/pjrc/usb_keyboard.c110
-rw-r--r--tmk_core/protocol/pjrc/usb_keyboard.h40
-rw-r--r--tmk_core/protocol/pjrc/usb_mouse.c81
-rw-r--r--tmk_core/protocol/pjrc/usb_mouse.h50
-rw-r--r--tmk_core/protocol/ps2.h134
-rw-r--r--tmk_core/protocol/ps2_busywait.c189
-rw-r--r--tmk_core/protocol/ps2_interrupt.c279
-rw-r--r--tmk_core/protocol/ps2_io.h15
-rw-r--r--tmk_core/protocol/ps2_io_avr.c75
-rw-r--r--tmk_core/protocol/ps2_io_mbed.c60
-rw-r--r--tmk_core/protocol/ps2_mouse.c220
-rw-r--r--tmk_core/protocol/ps2_mouse.h66
-rw-r--r--tmk_core/protocol/ps2_usart.c223
-rw-r--r--tmk_core/protocol/serial.h47
-rw-r--r--tmk_core/protocol/serial_mouse.h33
-rw-r--r--tmk_core/protocol/serial_mouse_microsoft.c124
-rw-r--r--tmk_core/protocol/serial_mouse_mousesystems.c131
-rw-r--r--tmk_core/protocol/serial_soft.c240
-rw-r--r--tmk_core/protocol/serial_uart.c112
-rw-r--r--tmk_core/protocol/usb_hid.mk74
-rw-r--r--tmk_core/protocol/usb_hid/README47
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/.gitattributes23
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/.gitignore4
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/.gitmodules12
-rwxr-xr-xtmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTD.cpp1364
-rwxr-xr-xtmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTD.h620
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTHID.cpp399
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTHID.h155
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3BT.cpp634
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3BT.h240
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3Enums.h141
-rwxr-xr-xtmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3USB.cpp572
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3USB.h303
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4BT.h121
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4Parser.cpp116
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4Parser.h407
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4USB.h130
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PSBuzz.cpp82
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PSBuzz.h185
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/SPP.cpp829
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/SPP.h225
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Usb.cpp812
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Usb.h41
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/UsbCore.h298
-rwxr-xr-xtmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Wii.cpp1268
-rwxr-xr-xtmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Wii.h518
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/WiiCameraReadme.md13
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXOLD.cpp337
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXOLD.h185
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXONE.cpp374
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXONE.h172
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXRECV.cpp583
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXRECV.h276
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXUSB.cpp361
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXUSB.h225
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/address.h282
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/adk.cpp371
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/adk.h140
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/avrpins.h1130
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdc_XR21B1411.cpp211
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdc_XR21B1411.h272
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcacm.cpp331
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcacm.h252
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcftdi.cpp334
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcftdi.h145
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcprolific.cpp247
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcprolific.h159
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/confdescparser.h213
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/controllerEnums.h204
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/BTHID.ino55
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/KeyboardParser.h105
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/MouseParser.h46
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS3BT/PS3BT.ino188
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS3Multi/PS3Multi.ino149
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS3SPP/PS3SPP.ino162
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS4BT/PS4BT.ino146
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/SPP/SPP.ino52
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/SPPMulti/SPPMulti.ino67
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/Wii/Wii.ino118
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiBalanceBoard/WiiBalanceBoard.ino51
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiIRCamera/WiiIRCamera.ino133
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiMulti/WiiMulti.ino132
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiUProController/WiiUProController.ino104
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDBootKbd/USBHIDBootKbd.ino129
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDBootKbdAndMouse/USBHIDBootKbdAndMouse.ino178
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDBootMouse/USBHIDBootMouse.ino83
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/USBHIDJoystick.ino38
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/hidjoystickrptparser.cpp84
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/hidjoystickrptparser.h33
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHID_desc/USBHID_desc.ino77
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHID_desc/pgmstrings.h52
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp.ino42
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp_rptparser.cpp43
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp_rptparser.h42
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/scale/scale.ino51
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/scale/scale_rptparser.cpp150
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/scale/scale_rptparser.h55
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/PS3USB/PS3USB.ino148
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/PS4USB/PS4USB.ino133
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/PSBuzz/PSBuzz.ino49
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/USB_desc/USB_desc.ino349
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/USB_desc/pgmstrings.h52
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXOLD/XBOXOLD.ino110
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXONE/XBOXONE.ino106
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXRECV/XBOXRECV.ino122
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXUSB/XBOXUSB.ino113
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/acm/acm_terminal/acm_terminal.ino100
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/acm/acm_terminal/pgmstrings.h52
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/ArduinoBlinkLED/ArduinoBlinkLED.ino89
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/adk_barcode/adk_barcode.ino91
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/demokit_20/demokit_20.ino103
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/term_test/term_test.ino65
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/term_time/term_time.ino50
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/board_qc/board_qc.ino259
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/cdc_XR21B1411/XR_terminal/XR_terminal.ino83
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/ftdi/USBFTDILoopback/USBFTDILoopback.ino98
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/ftdi/USBFTDILoopback/pgmstrings.h52
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/hub_demo/hub_demo.ino345
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/hub_demo/pgmstrings.h52
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/max_LCD/max_LCD.ino29
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_gprs_terminal/pl2303_gprs_terminal.ino101
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_gps/pl2303_gps.ino88
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_tinygps/pl2303_tinygps.ino217
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_xbee_terminal/pl2303_xbee_terminal.ino117
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/testusbhostFAT/Makefile64
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/testusbhostFAT/readme.md29
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/testusbhostFAT/testusbhostFAT.ino736
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/gpl2.txt340
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hexdump.h61
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hid.cpp112
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hid.h188
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidboot.cpp201
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidboot.h618
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidescriptorparser.cpp1588
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidescriptorparser.h176
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hiduniversal.cpp425
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hiduniversal.h108
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidusagestr.h977
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidusagetitlearrays.cpp1048
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/keywords.txt371
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/library.json47
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/library.properties9
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/macros.h82
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/masstorage.cpp1266
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/masstorage.h571
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/max3421e.h228
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/max_LCD.cpp255
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/max_LCD.h106
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/message.cpp116
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/message.h78
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/parsetools.cpp67
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/parsetools.h140
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/printhex.h84
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/readme.md351
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/settings.h139
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/sink_parser.h41
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usb_ch9.h166
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usbhost.h529
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usbhub.cpp425
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usbhub.h252
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/version_helper.h194
-rw-r--r--tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/xboxEnums.h65
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Arduino.h215
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/CDC.cpp233
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Client.h26
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/HID.cpp520
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/HardwareSerial.cpp428
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/HardwareSerial.h81
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/IPAddress.cpp56
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/IPAddress.h76
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Platform.h23
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Print.cpp263
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Print.h78
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Printable.h40
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Server.h9
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Stream.cpp270
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Stream.h96
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Tone.cpp601
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/USBAPI.h195
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/USBCore.cpp672
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/USBCore.h303
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/USBDesc.h63
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Udp.h88
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WCharacter.h168
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WInterrupts.c298
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WMath.cpp60
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WString.cpp645
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WString.h205
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/binary.h515
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/main.cpp20
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/new.cpp18
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/new.h22
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring.c324
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_analog.c282
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_digital.c178
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_private.h69
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_pulse.c69
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_shift.c55
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/variants/eightanaloginputs/pins_arduino.h27
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/variants/leonardo/pins_arduino.h256
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/variants/mega/pins_arduino.h363
-rw-r--r--tmk_core/protocol/usb_hid/arduino-1.0.1/variants/standard/pins_arduino.h218
-rw-r--r--tmk_core/protocol/usb_hid/override_Serial.cpp51
-rw-r--r--tmk_core/protocol/usb_hid/override_wiring.c29
-rw-r--r--tmk_core/protocol/usb_hid/parser.cpp33
-rw-r--r--tmk_core/protocol/usb_hid/parser.h12
-rw-r--r--tmk_core/protocol/usb_hid/test/Makefile88
-rw-r--r--tmk_core/protocol/usb_hid/test/config.h40
-rw-r--r--tmk_core/protocol/usb_hid/test/test.cpp92
-rw-r--r--tmk_core/protocol/usb_hid/usb_hid.h10
-rw-r--r--tmk_core/protocol/vusb.mk21
-rw-r--r--tmk_core/protocol/vusb/main.c100
-rw-r--r--tmk_core/protocol/vusb/sendchar_usart.c23
-rw-r--r--tmk_core/protocol/vusb/usbdrv/Changelog.txt308
-rw-r--r--tmk_core/protocol/vusb/usbdrv/CommercialLicense.txt166
-rw-r--r--tmk_core/protocol/vusb/usbdrv/License.txt361
-rw-r--r--tmk_core/protocol/vusb/usbdrv/Readme.txt172
-rw-r--r--tmk_core/protocol/vusb/usbdrv/USB-ID-FAQ.txt149
-rw-r--r--tmk_core/protocol/vusb/usbdrv/USB-IDs-for-free.txt148
-rw-r--r--tmk_core/protocol/vusb/usbdrv/asmcommon.inc188
-rw-r--r--tmk_core/protocol/vusb/usbdrv/oddebug.c50
-rw-r--r--tmk_core/protocol/vusb/usbdrv/oddebug.h123
-rw-r--r--tmk_core/protocol/vusb/usbdrv/usbconfig-prototype.h376
-rw-r--r--tmk_core/protocol/vusb/usbdrv/usbdrv.c625
-rw-r--r--tmk_core/protocol/vusb/usbdrv/usbdrv.h735
-rw-r--r--tmk_core/protocol/vusb/usbdrv/usbdrvasm.S393
-rw-r--r--tmk_core/protocol/vusb/usbdrv/usbdrvasm.asm21
-rw-r--r--tmk_core/protocol/vusb/usbdrv/usbdrvasm12.inc393
-rw-r--r--tmk_core/protocol/vusb/usbdrv/usbdrvasm128.inc750
-rw-r--r--tmk_core/protocol/vusb/usbdrv/usbdrvasm15.inc423
-rw-r--r--tmk_core/protocol/vusb/usbdrv/usbdrvasm16.inc346
-rw-r--r--tmk_core/protocol/vusb/usbdrv/usbdrvasm165.inc453
-rw-r--r--tmk_core/protocol/vusb/usbdrv/usbdrvasm18-crc.inc707
-rw-r--r--tmk_core/protocol/vusb/usbdrv/usbdrvasm20.inc360
-rw-r--r--tmk_core/protocol/vusb/usbdrv/usbportability.h144
-rw-r--r--tmk_core/protocol/vusb/vusb.c496
-rw-r--r--tmk_core/protocol/vusb/vusb.h27
-rw-r--r--tmk_core/readme.md150
-rw-r--r--tmk_core/ring_buffer.h53
-rw-r--r--tmk_core/rules.mk516
-rw-r--r--tmk_core/tool/chibios/.gitignore2
-rw-r--r--tmk_core/tool/chibios/ch-bootloader-jump.patch116
-rw-r--r--util/1-setup-path-win.bat66
-rw-r--r--util/2-setup-environment-win.bat72
-rw-r--r--util/ELEVATE_LICENSE.md25
-rw-r--r--util/add-paths.bat30
-rwxr-xr-xutil/bootloader.hex253
-rw-r--r--util/elevate.exebin0 -> 79360 bytes
-rw-r--r--util/install_dependencies.sh92
-rwxr-xr-xutil/new_project.sh31
-rw-r--r--util/travis_compiled_push.sh23
1549 files changed, 236965 insertions, 4 deletions
diff --git a/.gitignore b/.gitignore
index 2d68e206e..7c1e434e3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,28 @@
-*.stackdump
+.dep
+*.o
+*.eep
+*.elf
+*.hex
+!util/bootloader.hex
+!quantum/tools/eeprom_reset.hex
+*.log
+*.lss
+*.lst
+*.map
+*.sym
+*.swp
+tags
+*~
+build/
+.build/
+*.bak
+.vagrant/
+.idea/
+CMakeLists.txt
+.DS_STORE
+
+# Eclipse/PyCharm/Other IDE Settings
+.cproject
+.project
+.settings/
+.idea
diff --git a/.gitmodules b/.gitmodules
index 991cfe96d..1576b8dc0 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,6 @@
-[submodule "cgreen/cgreen"]
- path = cgreen/cgreen
- url = http://github.com/cgreen-devs/cgreen
+[submodule "lib/chibios"]
+ path = lib/chibios
+ url = https://github.com/ChibiOS/ChibiOS.git
+[submodule "lib/chibios-contrib"]
+ path = lib/chibios-contrib
+ url = https://github.com/ChibiOS/ChibiOS-Contrib.git
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 000000000..26deac0ce
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,24 @@
+os: linux
+dist: trusty
+sudo: required
+language: c
+compiler: avr-gcc
+branches:
+ except:
+ - /^.*-automated-build$/
+env:
+ global:
+ - secure: vBTSL34BDPxDilKUuTXqU4CJ26Pv5hogD2nghatkxSQkI1/jbdnLj/DQdPUrMJFDIY6TK3AltsBx72MaMsLQ1JO/Ou24IeHINHXzUC1FlS9yQa48cpxnhX5kzXNyGs3oa0qaFbvnr7RgYRWtmD52n4bIZuSuW+xpBv05x2OCizdT2ZonH33nATaHGFasxROm4qYZ241VfzcUv766V6RVHgL4x9V08warugs+RENVkfzxxwhk3NmkrISabze0gSVJLHBPHxroZC6EUcf/ocobcuDrCwFqtEt90i7pNIAFUE7gZsN2uE75LmpzAWin21G7lLPcPL2k4FJVd8an1HiP2WmscJU6U89fOfMb2viObnKcCzebozBCmKGtHEuXZo9FcReOx49AnQSpmESJGs+q2dL/FApkTjQiyT4J6O5dJpoww0/r57Wx0cmmqjETKBb5rSgXM51Etk3wO09mvcPHsEwrT7qH8r9XWdyCDoEn7FCLX3/LYnf/D4SmZ633YPl5gv3v9XEwxR5+04akjgnvWDSNIaDbWBdxHNb7l4pMc+WR1bwCyMyA7KXj0RrftEGOrm9ZRLe6BkbT4cycA+j77nbPOMcyZChliV9pPQos+4TOJoTzcK2L8yWVoY409aDNVuAjdP6Yum0R2maBGl/etLmIMpJC35C5/lZ+dUNjJAM=
+script:
+- make all-keyboards-quick AUTOGEN=true
+addons:
+ apt:
+ packages:
+ - avr-libc
+ - gcc-avr
+ - dfu-programmer
+ - pandoc
+ - gcc-arm-none-eabi
+ - binutils-arm-none-eabi
+ - libnewlib-arm-none-eabi
+after_success: bash util/travis_compiled_push.sh
diff --git a/Makefile b/Makefile
new file mode 100644
index 000000000..c285dabad
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,245 @@
+ifndef VERBOSE
+.SILENT:
+endif
+
+.DEFAULT_GOAL := all
+
+space := $(subst ,, )
+starting_makefile := $(subst $(space),_SPACE_,$(abspath $(firstword $(MAKEFILE_LIST))))
+mkfile_path := $(subst $(space),_SPACE_,$(abspath $(lastword $(MAKEFILE_LIST))))
+abs_tmk_root := $(patsubst %/,%,$(dir $(mkfile_path)))
+
+ifneq (,$(findstring /keyboards/,$(starting_makefile)))
+ possible_keyboard:=$(patsubst %/,%,$(dir $(patsubst $(abs_tmk_root)/keyboards/%,%,$(starting_makefile))))
+ ifneq (,$(findstring /keymaps/,$(possible_keyboard)))
+ KEYMAP_DIR:=$(lastword $(subst /keymaps/, ,$(possible_keyboard)))
+ KEYBOARD_DIR:=$(firstword $(subst /keymaps/, ,$(possible_keyboard)))
+ ifneq (,$(findstring /,$(KEYBOARD_DIR)))
+ # SUBPROJECT_DIR:=$(lastword $(subst /, ,$(KEYBOARD_DIR)))
+ # KEYBOARD_DIR:=$(firstword $(subst /, ,$(KEYBOARD_DIR)))
+ tmk_root = ../../..
+ else
+ tmk_root = ../../../..
+ endif
+ else
+ KEYMAP_DIR:=default
+ KEYBOARD_DIR:=$(possible_keyboard)
+ ifneq (,$(findstring /,$(KEYBOARD_DIR)))
+ # SUBPROJECT_DIR:=$(lastword $(subst /, ,$(KEYBOARD_DIR)))
+ # KEYBOARD_DIR:=$(firstword $(subst /, ,$(KEYBOARD_DIR)))
+ tmk_root = ../../..
+ else
+ tmk_root = ../..
+ endif
+ endif
+else
+ tmk_root = .
+endif
+# $(info $(KEYBOARD_DIR))
+# $(info $(KEYMAP_DIR))
+# $(info $(SUBPROJECT_DIR))
+
+# Directory common source filess exist
+TOP_DIR = $(tmk_root)
+TMK_DIR = tmk_core
+TMK_PATH = $(TOP_DIR)/$(TMK_DIR)
+LIB_PATH = $(TOP_DIR)/lib
+
+QUANTUM_DIR = quantum
+QUANTUM_PATH = $(TOP_DIR)/$(QUANTUM_DIR)
+
+
+ifdef keyboard
+ KEYBOARD ?= $(keyboard)
+endif
+ifdef KEYBOARD_DIR
+ KEYBOARD ?= $(KEYBOARD_DIR)
+endif
+ifndef KEYBOARD
+ KEYBOARD=planck
+endif
+
+# converts things to keyboards/subproject
+ifneq (,$(findstring /,$(KEYBOARD)))
+ TEMP:=$(KEYBOARD)
+ KEYBOARD:=$(firstword $(subst /, ,$(TEMP)))
+ SUBPROJECT:=$(lastword $(subst /, ,$(TEMP)))
+endif
+
+KEYBOARD_PATH = $(TOP_DIR)/keyboards/$(KEYBOARD)
+
+ifdef sub
+ SUBPROJECT=$(sub)
+endif
+ifdef subproject
+ SUBPROJECT=$(subproject)
+endif
+
+ifneq ("$(wildcard $(KEYBOARD_PATH)/$(KEYBOARD).c)","")
+ KEYBOARD_FILE = keyboards/$(KEYBOARD)/$(KEYBOARD).c
+ ifndef ARCH
+ ifneq ("$(wildcard $(KEYBOARD_PATH)/Makefile)","")
+ include $(KEYBOARD_PATH)/Makefile
+ endif
+ endif
+else
+$(error "$(KEYBOARD_PATH)/$(KEYBOARD).c" does not exist)
+endif
+
+ifdef SUBPROJECT_DEFAULT
+ SUBPROJECT?=$(SUBPROJECT_DEFAULT)
+endif
+
+ifdef SUBPROJECT
+ SUBPROJECT_PATH = $(TOP_DIR)/keyboards/$(KEYBOARD)/$(SUBPROJECT)
+ ifneq ("$(wildcard $(SUBPROJECT_PATH)/$(SUBPROJECT).c)","")
+ OPT_DEFS += -DSUBPROJECT_$(SUBPROJECT)
+ SUBPROJECT_FILE = keyboards/$(KEYBOARD)/$(SUBPROJECT)/$(SUBPROJECT).c
+ -include $(SUBPROJECT_PATH)/Makefile
+ else
+$(error "$(SUBPROJECT_PATH)/$(SUBPROJECT).c" does not exist)
+ endif
+endif
+
+ifdef keymap
+ KEYMAP ?= $(keymap)
+endif
+ifdef KEYMAP_DIR
+ KEYMAP ?= $(KEYMAP_DIR)
+endif
+ifndef KEYMAP
+ KEYMAP = default
+endif
+KEYMAP_PATH = $(KEYBOARD_PATH)/keymaps/$(KEYMAP)
+ifneq ("$(wildcard $(KEYMAP_PATH)/keymap.c)","")
+ KEYMAP_FILE = keyboards/$(KEYBOARD)/keymaps/$(KEYMAP)/keymap.c
+ -include $(KEYMAP_PATH)/Makefile
+else
+ ifeq ("$(wildcard $(SUBPROJECT_PATH)/keymaps/$(KEYMAP)/keymap.c)","")
+$(error "$(KEYMAP_PATH)/keymap.c" does not exist)
+ else
+ KEYMAP_PATH = $(SUBPROJECT_PATH)/keymaps/$(KEYMAP)
+ KEYMAP_FILE = keyboards/$(KEYBOARD)/$(SUBPROJECT)/keymaps/$(KEYMAP)/keymap.c
+ -include $(KEYMAP_PATH)/Makefile
+ endif
+endif
+
+ifdef SUBPROJECT
+ TARGET ?= $(KEYBOARD)_$(SUBPROJECT)_$(KEYMAP)
+else
+ TARGET ?= $(KEYBOARD)_$(KEYMAP)
+endif
+BUILD_DIR = .build
+
+# Object files directory
+# To put object files in current directory, use a dot (.), do NOT make
+# this an empty or blank macro!
+OBJDIR = $(BUILD_DIR)/obj_$(TARGET)
+
+
+
+ifneq ("$(wildcard $(KEYMAP_PATH)/config.h)","")
+ CONFIG_H = $(KEYMAP_PATH)/config.h
+else
+ CONFIG_H = $(KEYBOARD_PATH)/config.h
+ ifdef SUBPROJECT
+ ifneq ("$(wildcard $(SUBPROJECT_PATH)/$(SUBPROJECT).c)","")
+ CONFIG_H = $(SUBPROJECT_PATH)/config.h
+ endif
+ endif
+endif
+
+# # project specific files
+SRC += $(KEYBOARD_FILE) \
+ $(KEYMAP_FILE) \
+ $(QUANTUM_DIR)/quantum.c \
+ $(QUANTUM_DIR)/keymap_common.c \
+ $(QUANTUM_DIR)/keycode_config.c \
+ $(QUANTUM_DIR)/process_keycode/process_leader.c
+
+ifdef SUBPROJECT
+ SRC += $(SUBPROJECT_FILE)
+endif
+
+ifdef SUBPROJECT
+ SRC += $(SUBPROJECT_FILE)
+endif
+
+ifdef SUBPROJECT
+ SRC += $(SUBPROJECT_FILE)
+endif
+
+ifndef CUSTOM_MATRIX
+ SRC += $(QUANTUM_DIR)/matrix.c
+endif
+
+ifeq ($(strip $(MIDI_ENABLE)), yes)
+ OPT_DEFS += -DMIDI_ENABLE
+ SRC += $(QUANTUM_DIR)/process_keycode/process_audio.c
+endif
+
+ifeq ($(strip $(AUDIO_ENABLE)), yes)
+ OPT_DEFS += -DAUDIO_ENABLE
+ SRC += $(QUANTUM_DIR)/process_keycode/process_music.c
+ SRC += $(QUANTUM_DIR)/audio/audio.c
+ SRC += $(QUANTUM_DIR)/audio/voices.c
+ SRC += $(QUANTUM_DIR)/audio/luts.c
+endif
+
+ifeq ($(strip $(UNICODE_ENABLE)), yes)
+ OPT_DEFS += -DUNICODE_ENABLE
+ SRC += $(QUANTUM_DIR)/process_keycode/process_unicode.c
+endif
+
+ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
+ OPT_DEFS += -DRGBLIGHT_ENABLE
+ SRC += $(QUANTUM_DIR)/light_ws2812.c
+ SRC += $(QUANTUM_DIR)/rgblight.c
+endif
+
+ifeq ($(strip $(TAP_DANCE_ENABLE)), yes)
+ OPT_DEFS += -DTAP_DANCE_ENABLE
+ SRC += $(QUANTUM_DIR)/process_keycode/process_tap_dance.c
+endif
+
+# Optimize size but this may cause error "relocation truncated to fit"
+#EXTRALDFLAGS = -Wl,--relax
+
+# Search Path
+VPATH += $(KEYMAP_PATH)
+ifdef SUBPROJECT
+ VPATH += $(SUBPROJECT_PATH)
+endif
+VPATH += $(KEYBOARD_PATH)
+VPATH += $(TOP_DIR)
+VPATH += $(TMK_PATH)
+VPATH += $(QUANTUM_PATH)
+VPATH += $(QUANTUM_PATH)/keymap_extras
+VPATH += $(QUANTUM_PATH)/audio
+VPATH += $(QUANTUM_PATH)/process_keycode
+
+
+# We can assume a ChibiOS target When MCU_FAMILY is defined, since it's not used for LUFA
+ifdef MCU_FAMILY
+ PLATFORM=CHIBIOS
+else
+ PLATFORM=AVR
+endif
+
+include $(TMK_PATH)/common.mk
+ifeq ($(PLATFORM),AVR)
+ include $(TMK_PATH)/protocol/lufa.mk
+ include $(TMK_PATH)/avr.mk
+else ifeq ($(PLATFORM),CHIBIOS)
+ include $(TMK_PATH)/protocol/chibios.mk
+ include $(TMK_PATH)/chibios.mk
+else
+ $(error Unknown platform)
+endif
+
+include $(TMK_PATH)/rules.mk
+
+GIT_VERSION := $(shell git describe --abbrev=6 --dirty --always --tags 2>/dev/null || date +"%Y-%m-%d-%H:%M:%S")
+BUILD_DATE := $(shell date +"%Y-%m-%d-%H:%M:%S")
+OPT_DEFS += -DQMK_KEYBOARD=\"$(KEYBOARD)\" -DQMK_KEYMAP=\"$(KEYMAP)\"
+OPT_DEFS += -DQMK_VERSION=\"$(GIT_VERSION)\" -DQMK_BUILDDATE=\"$(BUILD_DATE)\"
diff --git a/Vagrantfile b/Vagrantfile
new file mode 100644
index 000000000..8cadeaddf
--- /dev/null
+++ b/Vagrantfile
@@ -0,0 +1,98 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+
+Vagrant.configure(2) do |config|
+ # You can only have one config.vm.box uncommented at a time
+
+ # Comment this and uncomment another if you don't want to use the minimal Arch box
+ #config.vm.box = "dragon788/arch-ala-elasticdog"
+
+ # VMware/Virtualbox 64 bit
+ config.vm.box = "phusion/ubuntu-14.04-amd64"
+ #
+ # VMware/Virtualbox 64 bit
+ #config.vm.box = "puphpet/centos65-x64"
+ #
+ # The opensuse boxes don't have dfu-util in their default repositories
+ #
+ # The virtualbox version has tools issues
+ # VMware/Virtualbox 64 bit
+ #config.vm.box = "bento/opensuse-13.2-x86_64"
+ #
+ # Virtualbox only
+ #config.vm.box = "bento/opensuse-13.2-i386"
+ # config.vm.box = ""
+ # config.vm.box = ""
+
+ # This section allows you to customize the Virtualbox VM
+ # settings, ie showing the GUI or upping the memory
+ # or cores if desired
+ config.vm.provider "virtualbox" do |vb|
+ # Hide the VirtualBox GUI when booting the machine
+ vb.gui = false
+ # Uncomment the below lines if you want to program
+ # your Teensy via the VM rather than your host OS
+ #vb.customize ['modifyvm', :id, '--usb', 'on']
+ #vb.customize ['usbfilter', 'add', '0',
+ # '--target', :id,
+ # '--name', 'teensy',
+ # '--vendorid', '0x16c0',
+ # '--productid','0x0478'
+ # ]
+ # Customize the amount of memory on the VM:
+ vb.memory = "512"
+ end
+
+ # This section allows you to customize the VMware VM
+ # settings, ie showing the GUI or upping the memory
+ # or cores if desired
+ config.vm.provider "vmware_workstation" do |vmw|
+ # Hide the VMware GUI when booting the machine
+ vmw.gui = false
+
+ # Customize the amount of memory on the VM:
+ vmw.memory = "512"
+ end
+
+ config.vm.provider "vmware_fusion" do |vmf|
+ # Hide the vmfare GUI when booting the machine
+ vmf.gui = false
+
+ # Customize the amount of memory on the VM:
+ vmf.memory = "512"
+ end
+
+ # Docker provider pulls from hub.docker.com respecting docker.image if
+ # config.vm.box is nil. Note that this bind-mounts from the current dir to
+ # /vagrant in the guest, so unless your UID is 1000 to match vagrant in the
+ # image, you'll need to: chmod -R a+rw .
+ config.vm.provider "docker" do |docker, override|
+ override.vm.box = nil
+ docker.image = "jesselang/debian-vagrant:jessie"
+ docker.has_ssh = true
+ end
+
+ # This script ensures the required packages for AVR programming are installed
+ # It also ensures the system always gets the latest updates when powered on
+ # If this causes issues you can run a 'vagrant destroy' and then
+ # add a # before ,args: and run 'vagrant up' to get a working
+ # non-updated box and then attempt to troubleshoot or open a Github issue
+
+ config.vm.provision "shell", run: "always", path: "./util/install_dependencies.sh", args: "-update"
+
+ config.vm.post_up_message = <<-EOT
+ Log into the VM using 'vagrant ssh' on OSX or from Git Bash (Win)
+ or 'vagrant ssh-config' and Putty or Bitvise SSH or another SSH tool
+
+ Change directory (cd) to the keyboard you wish to program
+ (Optionally) modify your layout,
+ then run 'make clean'
+ and then 'make' to compile the .eep and .hex files.
+
+ Or you can copy and paste the example line below.
+
+ cd /vagrant; cd keyboards; cd ergodox_ez; make clean; make
+
+
+ EOT
+end
diff --git a/doc/BUILD_GUIDE.md b/doc/BUILD_GUIDE.md
new file mode 100644
index 000000000..70a4e10fa
--- /dev/null
+++ b/doc/BUILD_GUIDE.md
@@ -0,0 +1,103 @@
+# This guide has now been included in the main readme - please reference that one instead.
+
+## Build Environment Setup
+
+### Windows (Vista and later)
+1. If you have ever installed WinAVR, uninstall it.
+2. Install [MHV AVR Tools](https://infernoembedded.com/sites/default/files/project/MHV_AVR_Tools_20131101.exe). Disable smatch, but **be sure to leave the option to add the tools to the PATH checked**.
+3. Install [MinGW](https://sourceforge.net/projects/mingw/files/Installer/mingw-get-setup.exe/download). During installation, uncheck the option to install a graphical user interface. **DO NOT change the default installation folder.** The scripts depend on the default location.
+4. Clone this repository. [This link will download it as a zip file, which you'll need to extract.](https://github.com/jackhumbert/qmk_firmware/archive/master.zip) Open the extracted folder in Windows Explorer.
+5. Double-click on the 1-setup-path-win batch script to run it. You'll need to accept a User Account Control prompt. Press the spacebar to dismiss the success message in the command prompt that pops up.
+6. Right-click on the 2-setup-environment-win batch script, select "Run as administrator", and accept the User Account Control prompt. This part may take a couple of minutes, and you'll need to approve a driver installation, but once it finishes, your environment is complete!
+7. Future build commands should be run from the standard Windows command prompt, which you can find by searching for "command prompt" from the start menu or start screen. Ignore the "MHV AVR Shell".
+
+### Mac
+If you're using [homebrew,](http://brew.sh/) you can use the following commands:
+
+ brew tap osx-cross/avr
+ brew install avr-libc
+ brew install dfu-programmer
+
+This is the recommended method. If you don't have homebrew, [install it!](http://brew.sh/) It's very much worth it for anyone who works in the command line.
+
+You can also try these instructions:
+
+1. Install Xcode from the App Store.
+2. Install the Command Line Tools from `Xcode->Preferences->Downloads`.
+3. Install [DFU-Programmer][dfu-prog].
+
+### Linux
+Install AVR GCC, AVR libc, and dfu-progammer with your favorite package manager.
+
+Debian/Ubuntu example:
+
+ sudo apt-get update
+ sudo apt-get install gcc-avr avr-libc dfu-programmer
+
+### Vagrant
+If you have any problems building the firmware, you can try using a tool called Vagrant. It will set up a virtual computer with a known configuration that's ready-to-go for firmware building. OLKB does NOT host the files for this virtual computer. Details on how to set up Vagrant are in the [VAGRANT_GUIDE file](VAGRANT_GUIDE.md).
+
+## Verify Your Installation
+1. If you haven't already, obtain this repository ([https://github.com/jackhumbert/qmk_firmware](https://github.com/jackhumbert/qmk_firmware)). You can either download it as a zip file and extract it, or clone it using the command line tool git or the Github Desktop application.
+2. Open up a terminal or command prompt and navigate to the `qmk_firmware` folder using the `cd` command. The command prompt will typically open to your home directory. If, for example, you cloned the repository to your Documents folder, then you would type `cd Documents/qmk_firmware`. If you extracted the file from a zip, then it may be named `qmk_firmware-master` instead.
+3. To confirm that you're in the correct location, you can display the contents of your current folder using the `dir` command on Windows, or the `ls` command on Linux or Mac. You should see several files, including `readme.md` and a `quantum` folder. From here, you need to navigate to the appropriate folder under `keyboards/`. For example, if you're building for a Planck, run `cd keyboards/planck`.
+4. Once you're in the correct keyboard-specific folder, run the `make` command. This should output a lot of information about the build process. More information about the `make` command can be found below.
+
+## Customizing, Building, and Deploying Your Firmware
+
+### The Make command
+
+The `make` command is how you compile the firmware into a .hex file, which can be loaded by a dfu programmer (like dfu-progammer via `make dfu`) or the [Teensy loader](https://www.pjrc.com/teensy/loader.html) (only used with Teensys). You can run `make` from the root (`/`), your keyboard folder (`/keyboards/<keyboard>/`), or your keymap folder (`/keyboards/<keyboard>/keymaps/<keymap>/`) if you have a `Makefile` there (see the example [here](/doc/keymap_makefile_example.mk)).
+
+By default, this will generate a `<keyboard>_<keymap>.hex` file in whichever folder you run `make` from. These files are ignored by git, so don't worry about deleting them when committing/creating pull requests.
+
+* The "root" (`/`) folder is the qmk_firmware folder, in which are `doc`, `keyboard`, `quantum`, etc.
+* The "keyboard" folder is any keyboard project's folder, like `/keyboards/planck`.
+* The "keymap" folder is any keymap's folder, like `/keyboards/planck/keymaps/default`.
+
+Below is a list of the useful `make` commands in QMK:
+
+* `make` - cleans automatically and builds your keyboard and keymap depending on which folder you're in. This defaults to the "default" layout (unless in a keymap folder), and Planck keyboard in the root folder
+ * `make keyboard=<keyboard>` - specifies the keyboard (only to be used in root)
+ * `make keymap=<keymap>` - specifies the keymap (only to be used in root and keyboard folder - not needed when in keymap folder)
+* `make quick` - skips the clean step (cannot be used immediately after modifying config.h or Makefiles)
+* `make dfu` - (requires dfu-programmer) builds and flashes the keymap to your keyboard once placed in reset/dfu mode (button or press `KC_RESET`). This does not work for Teensy-based keyboards like the ErgoDox EZ.
+ * `keyboard=` and `keymap=` are compatible with this
+* `make all-keyboards` - builds all keymaps for all keyboards and outputs status of each (use in root)
+* `make all-keyboards-default` - builds all default keymaps for all keyboards and outputs status of each (use in root)
+* `make all-keymaps [keyboard=<keyboard>]` - builds all of the keymaps for whatever keyboard folder you're in, or specified by `<keyboard>`
+* `make all-keyboards-quick`, `make all-keyboards-default-quick` and `make all-keymaps-quick [keyboard=<keyboard>]` - like the normal "make-all-*" commands, but they skip the clean steps
+
+Other, less useful functionality:
+
+* `make COLOR=false` - turns off color output
+* `make SILENT=true` - turns off output besides errors/warnings
+* `make VERBOSE=true` - outputs all of the avr-gcc stuff (not interesting)
+
+### The Makefile
+
+There are 3 different `make` and `Makefile` locations:
+
+* root (`/`)
+* keyboard (`/keyboards/<keyboard>/`)
+* keymap (`/keyboards/<keyboard>/keymaps/<keymap>/`)
+
+The root contains the code used to automatically figure out which keymap or keymaps to compile based on your current directory and commandline arguments. It's considered stable, and shouldn't be modified. The keyboard one will contain the MCU set-up and default settings for your keyboard, and shouldn't be modified unless you are the producer of that keyboard. The keymap Makefile can be modified by users, and is optional. It is included automatically if it exists. You can see an example [here](/doc/keymap_makefile_example.mk) - the last few lines are the most important. The settings you set here will override any defaults set in the keyboard Makefile. **It is required if you want to run `make` in the keymap folder.**
+
+### The `config.h` file
+
+There are 2 `config.h` locations:
+
+* keyboard (`/keyboards/<keyboard>/`)
+* keymap (`/keyboards/<keyboard>/keymaps/<keymap>/`)
+
+The keyboard `config.h` is included only if the keymap one doesn't exist. The format to use for your custom one [is here](/doc/keymap_config_h_example.h). If you want to override a setting from the parent `config.h` file, you need to do this:
+
+```
+#undef MY_SETTING
+#define MY_SETTING 4
+```c
+
+For a value of `4` for this imaginary setting. So we `undef` it first, then `define` it.
+
+You can then override any settings, rather than having to copy and paste the whole thing.
diff --git a/doc/COPYING.GPLv2 b/doc/COPYING.GPLv2
new file mode 100644
index 000000000..d159169d1
--- /dev/null
+++ b/doc/COPYING.GPLv2
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/doc/COPYING.GPLv3 b/doc/COPYING.GPLv3
new file mode 100644
index 000000000..94a9ed024
--- /dev/null
+++ b/doc/COPYING.GPLv3
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/doc/CYGWIN_GUIDE.md b/doc/CYGWIN_GUIDE.md
new file mode 100755
index 000000000..05e7a55f7
--- /dev/null
+++ b/doc/CYGWIN_GUIDE.md
@@ -0,0 +1,352 @@
+#Planck Advanced (but not too advanced) `cygwin` Users Guide
+If you are a user of the [cygwin environment](https://cygwin.com) in Windows and want the freedom to use the latest tools available, then this is the guide for you. If compiling your own copy of the latest and greatest Gnu C Compiler makes you super happy, then this is the guide for you. If the command line make you smile, then this is the guide for you.
+
+This guide was written step by step as I went through the process on a `Windows 10` `x86_64` and a `Windows 7` `amd k10` based system. This should be generally applicable to to any `Windows` environment with `cygwin`.
+
+#####Do not skip steps. Do not move past a step until the previous step finishes successfully.
+
+Based on [avr-libc installation guide](http://www.nongnu.org/avr-libc/user-manual/install_tools.html)
+
+##Get the Required Packages
+Download the `cygwin` setup ([x86_64](https://cygwin.com/setup-x86_64.exe)) and install the default system plus the following if they are not already selected:
+- devel/git
+- devel/gcc-core
+- devel/gcc-g++
+- devel/flex
+- devel/bison
+- devel/make
+- devel/texinfo
+- devel/gettext-devel
+- devel/automake
+- devel/autoconfig
+- devel/libtool
+- text/gettext
+- libs/libgcc1
+- interpreters/m4
+- web/wget
+- archive/unzip
+
+The following sources will be required:
+- [gmp](https://gmplib.org/) (6.1.0)
+- [mpfr](http://www.mpfr.org/) (3.1.4)
+- [mpc](http://www.multiprecision.org/) (1.0.3)
+- [binutils](https://www.sourceware.org/binutils/) (2.26)
+- [gcc](https://gcc.gnu.org/) (5.3.0)
+- [avr-libc](http://www.nongnu.org/avr-libc/) (2.0.0)
+
+The `dfu-programmer` will be required to flash the new firmware
+- [dfu-programmer](https://dfu-programmer.github.io/) (0.7.2)
+
+The set of commands below will create a directory (`~/local/avr`) for the sources you compile to be installed on the machine and a directory (`~/src`) for these source files to be stored. The commands then download the sources of the needed packages and unpack them. Note: the expand commands are different depending on if the packages are offered as a `bz2` or `gz` archive
+```
+$ mkdir ~/local
+$ mkdir ~/local/avr
+$ mkdir ~/src
+$ cd ~/src
+$ wget https://gmplib.org/download/gmp/gmp-6.1.0.tar.bz2
+$ wget http://www.mpfr.org/mpfr-3.1.4/mpfr-3.1.4.tar.bz2
+$ wget ftp://ftp.gnu.org/gnu/mpc/mpc-1.0.3.tar.gz
+$ wget http://ftp.gnu.org/gnu/binutils/binutils-2.26.tar.gz
+$ wget http://mirror0.babylon.network/gcc/releases/gcc-5.3.0/gcc-5.3.0.tar.gz
+$ wget http://download.savannah.gnu.org/releases/avr-libc/avr-libc-2.0.0.tar.bz2
+$ tar -xjf gmp-6.1.0.tar.bz2
+$ tar -xjf mpfr-3.1.4.tar.bz2
+$ tar -zxf mpc-1.0.3.tar.gz
+$ tar -zxf binutils-2.26.tar.gz
+$ tar -zxf gcc-5.3.0.tar.gz
+$ tar -xjf avr-libc-2.0.0.tar.bz2
+```
+
+##Setup the Build Environment
+These commands will set up the install directory and the `PATH` variable, which will allow you to access your installed packages. Note: if you close the `cygwin` terminal window, you will need to rerun these commands, they are not permanent.
+```
+$ PREFIX=$HOME/local/avr
+$ export PREFIX
+$ PATH=/usr/local/bin:/usr/local/lib:/usr/local/include:/bin:/lib:/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS
+$ PATH=$PATH:$PREFIX/bin:$PREFIX/lib
+$ export PATH
+```
+
+##The `gcc` Required Math Library Packages
+The following packages are required to be complied and installed in order to compile `gcc`. They are not sufficiently available through the `cygwin` package system, so we have to make them ourselves. They must be complied in this order because each one depends on the previous. Verfiy that for each package, `make check` returns all passing and no fails.
+
+###Build and Install `gmp`
+```
+$ cd ~/src/gmp-6.1.0
+$ ./configure --enable-static --disable-shared
+$ make
+$ make check
+$ make install
+```
+
+###Build and Install `mpfr`
+```
+$ cd ~/src/mpfr-3.1.4
+$ ./configure --with-gmp-build=../gmp-6.1.0 --enable-static --disable-shared
+$ make
+$ make check
+$ make install
+```
+
+###Build and Install `mpc`
+```
+$ cd ~/src/mpc-1.0.3
+$ ./configure --with-gmp=/usr/local --with-mpfr=/usr/local --enable-static --disable-shared
+$ make
+$ make check
+$ make install
+```
+
+##OPTIONAL Part
+You can build and install a brand new `gcc` or you can use the one supplied by `cygwin`. This will take about 4-5 hours to compile (It is a "native build", so it does the entire build **3 times**. This takes a long while).
+
+###Build and Install `gcc` for Your Machine
+```
+$ cd ~/src/gcc-5.3.0
+$ mkdir obj-local
+$ cd obj-local
+$ ../configure --enable-languages=c,c++ --with-gmp=/usr/local --with-mpfr=/usr/local --with-mpc=/usr/local --enable-static --disable-shared
+$ make
+$ make install
+```
+##End OPTIONAL Part
+
+###Build and Install `binutils` for Your Machine
+```
+$ cd ~/src/binutils-2.26
+$ mkdir obj-local
+$ cd obj-local
+$ ../configure
+$ make
+$ make install
+```
+
+##Buliding `binutils`, `gcc`, and `avr-libc` for the AVR system
+Now we can make the critical stuff for compiling our firmware: `binutils`, `gcc`, and `avr-libc` for the AVR architecture. These allow us to build and manipulate the firmware for the keyboard.
+
+###Build `binutils` for AVR
+If you plan to build and install `avr-gdb` also, use the `gdb` install at the end of this guide as it also builds the `binutils`
+```
+$ cd ~/src/binutils-2.26
+$ mkdir obj-avr
+$ cd obj-avr
+$ ../configure --prefix=$PREFIX --target=avr --disable-nls
+$ make
+$ make install
+```
+
+###Build `gcc` for AVR
+```
+$ cd ~/src/gcc-5.3.0
+$ mkdir obj-avr
+$ cd obj-avr
+$ ../configure --prefix=$PREFIX --target=avr --enable-languages=c,c++ --with-gmp=/usr/local --with-mpfr=/usr/local --with-mpc=/usr/local --enable-static --disable-shared --disable-nls --disable-libssp --with-dwarf2
+$ make
+$ make install
+```
+
+###Build `avr-libc` for AVR
+For building the `avr-libc`, we have to specify the host build system. In my case it is `x86_64-unknown-cygwin`. You can look for build system type in the `gcc` configure notes for the proper `--build` specification to pass when you configure `avr-libc`.
+```
+$ cd ~/src/avr-libc-2.0.0
+$ ./configure --prefix=$PREFIX --build=x86_64-unknown-cygwin --host=avr
+$ make
+$ make install
+```
+
+##Building 'dfu-programmer' for flashing the firmware via USB and installing the drivers
+We can either build our own, or use the precomplied binaries. The precompiled binaries don't play well with `cygwin` so it is better to build them ourselves. The procedure for the precompiled binaries is included at the end of this guide.
+
+### Build and Install the `libusb`
+The `dfu-programmer` requires `libusb` so that it can interact with the USB system. These repos must be bootstrapped in order to create an appropriate `./configure` and `Makefile` for your system.
+```
+$ cd ~/src
+$ git clone https://github.com/libusb/libusb.git
+$ cd libusb
+$ ./bootstrap.sh
+$ ./configure
+$ make
+$ make install
+```
+
+### Build and Install the `dfu-programmer`
+```
+$ cd ~/src
+$ git clone https://github.com/dfu-programmer/dfu-programmer.git
+$ cd dfu-programmer
+$ ./bootstrap.sh
+$ ./configure
+$ make
+$ make install
+```
+
+Verify the installation with:
+```
+$ which dfu-programmer
+/usr/local/bin/dfu-programmer
+
+$ dfu-programmer
+dfu-programmer 0.7.2
+https://github.com/dfu-programmer/dfu-programmer
+Type 'dfu-programmer --help' for a list of commands
+ 'dfu-programmer --targets' to list supported target devices
+```
+If you are not getting the above result, you will not be able to flash the firmware!
+
+###Install the USB drivers
+The drivers are included in the windows binary version of [`dfu-programmer` 0.7.2](http://iweb.dl.sourceforge.net/project/dfu-programmer/dfu-programmer/0.7.2/dfu-programmer-win-0.7.2.zip).
+```
+$ cd ~/src
+$ wget http://iweb.dl.sourceforge.net/project/dfu-programmer/dfu-programmer/0.7.2/dfu-programmer-win-0.7.2.zip
+$ unzip dfu-programmer-win-0.7.2.zip -d dfu-programmer-win-0.7.2
+```
+
+or
+
+The official drivers are found in [Atmel's `FLIP` installer](http://www.atmel.com/images/Flip%20Installer%20-%203.4.7.112.exe). Download and then install `FLIP`. Upon installation, the drivers will be found in `C:\Program Files (x86)\Atmel\Flip 3.4.7\usb`.
+
+Then, from an **administrator-privileged** `Windows` terminal, run the following command (adjust the path for username, etc. as necessary) and accept the prompt that pops up:
+```
+C:\> pnputil -i -a C:\cygwin64\home\Kevin\src\dfu-programmer-win-0.7.2\dfu-prog-usb-1.2.2\atmel_usb_dfu.inf
+or
+C:\> pnputil -i -a "C:\Program Files (x86)\Atmel\Flip 3.4.7\usb\atmel_usb_dfu.inf"
+```
+
+This should be the result:
+```
+Microsoft PnP Utility
+
+Processing inf : atmel_usb_dfu.inf
+Successfully installed the driver on a device on the system.
+Driver package added successfully.
+Published name : oem104.inf
+
+
+Total attempted: 1
+Number successfully imported: 1
+```
+
+Alternatively, the `Windows` driver can be installed when prompted by `Windows` when the keyboard is attached. Do not let `Windows` search for a driver; specify the path to search for a driver and point it to the `atmel_usb_dfu.inf` file.
+
+##Building and Flashing the Planck firmware!
+If you did everything else right. This part should be a snap! Grab the latest sources from `github`, make the Plank firmware, then flash it.
+
+###Build Planck and Load the Firmware
+```
+$ cd ~/src
+$ git clone https://github.com/jackhumbert/qmk_firmware.git
+$ cd qmk_firmware/keyboards/planck
+$ make
+```
+
+Make sure there are no errors. You should end up with this or something similar:
+```
+Creating load file for Flash: planck.hex
+avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature planck.elf planck.hex
+
+Creating load file for EEPROM: planck.eep
+avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \
+--change-section-lma .eeprom=0 --no-change-warnings -O ihex planck.elf planck.eep || exit 0
+
+Creating Extended Listing: planck.lss
+avr-objdump -h -S -z planck.elf > planck.lss
+
+Creating Symbol Table: planck.sym
+avr-nm -n planck.elf > planck.sym
+
+Size after:
+ text data bss dec hex filename
+ 18602 82 155 18839 4997 planck.elf
+
+-------- end --------
+```
+
+If you do not get the above, you **did not** build the firmware, and you will have nothing to flash. If you have the fresh clone from `github`, it was probably something gone wrong in this install process, go check and see what didn't work and threw errors or what steps you might have missed.
+
+But if everything went OK, you are ready to flash! Press the reset button on the bottom of the Planck, wait two seconds, then:
+```
+$ make dfu
+```
+.
+.
+.
+profit!!!
+
+
+
+
+
+##extra bits...
+
+###Installing Precompiled `dfu-programmer` Binaries (not recommended for `cygwin`)
+To install the `dfu-programmer` from the binaries, we must get if from [the `dfu-programmer` website](https://dfu-programmer.github.io/) ([0.7.2](http://iweb.dl.sourceforge.net/project/dfu-programmer/dfu-programmer/0.7.2/dfu-programmer-win-0.7.2.zip)).
+
+Copy this file into your `cygwin` home\src directory. (For me, it is `C:\cygwin64\home\Kevin\src`), extract the files, move `dfu-programmer.exe` to `~/local/avr/bin`. Most obnoxiously, the `libusb0_x86.dll` and `libusb0.sys` need to be moved from `./dfu-prog-usb-1.2.2/x86/` to a directory in the `Windows` `PATH` and the `cygwin` `PATH`. This is because the `dfu-programmer` binary is `mingw` based, not `cygwin` based, so the `dlls` do not cooperate. I achieved acceptable pathing by moving the files to `C:\cygwin64\home\Kevin\local\avr\bin` Then, in a `WINDOWS` command prompt running (Adjusting your path for username, etc. as needed):
+```
+C:\> set PATH=%PATH%;C:\cygwin64\home\Kevin\local\avr\bin
+```
+
+Then, rename `libusb0_x86.dll` to `libusb0.dll`.
+
+You can tell that you were successful by trying to execute 'dfu-programmer' from the 'cygwin' prompt:
+```
+$ which dfu-programmer
+/home/Kevin/local/avr/bin/dfu-programmer
+
+$ dfu-programmer
+dfu-programmer 0.7.2
+https://github.com/dfu-programmer/dfu-programmer
+Type 'dfu-programmer --help' for a list of commands
+ 'dfu-programmer --targets' to list supported target devices
+```
+
+If you are not getting the above result, you will not be able to flash the firmware!
+- Try making sure your `PATH` variables are set correctly for both `Windows` and `cygwin`.
+- Make sure the `dll` is named correctly.
+- Do not extract it with `cygwin`'s `unzip` as it does not set the executable permission. If you did it anyway, do `chmod +x dfu-programmer.exe`.
+- Still have problems? Try building it instead.
+
+
+##Debugging Tools
+
+These tools are for debugging your firmware, etc. before flashing. Theoretically, it can save your memory from wearing out. However, these tool do not work 100% for the Planck firmware.
+
+### `gdb` for AVR
+`gdb` has a simulator for AVR but it does not support all instructions (like WDT), so it immediately crashes when running the Planck firmware (because `lufa.c` disables the WDT in the first few lines of execution). But it can still be useful in debugging example code and test cases, if you know how to use it.
+
+```
+$ cd ~/src
+$ git clone git://sourceware.org/git/binutils-gdb.git
+$ cd binutils-gdb
+$ mkdir obj-avr
+$ cd obj-avr
+$ ../configure --prefix=$PREFIX --target=avr --build=x86_64-unknown-cygwin --with-gmp=/usr/local --with-mpfr=/usr/local --with-mpc=/usr/local --disable-nls --enable-static
+$ make
+$ make install
+```
+
+### `simulavr`
+`simulavr` is an AVR simulator. It runs the complied AVR elfs. `simulavr` does not support the `atmega32u4` device... it does `atmega32` but that is not good enough for the firmware (no PORTE and other things), so you cannot run the Planck firmware. I use it to simulate ideas I have for features in separate test projects.
+
+This one is a major pain in the butt because it has a lot of dependencies and it is buggy. I will do my best to explain it but... it was hard to figure out. A few things need to be changed in the 'Makefile' to make it work in `cygwin`.
+
+
+```
+$ cd ~/src
+$ git clone https://github.com/Traumflug/simulavr.git
+$ cd simulavr
+$ ./bootstrap
+$ ./configure --prefix=$PREFIX --enable-static --disable-tcl --disable-doxygen-doc
+```
+ Edit `src/Makefile.am` now so that `-no-undefined` is included (I did this by removing the SYS_MINGW conditional surrounding `libsim_la_LDFLAGS += -no-undefined` and `libsimulavr_la_LDFLAGS += -no-undefined \ libsimulavr_la_LIBADD += $(TCL_LIB)`. Also, `$(EXEEXT)` is added after `kbdgentables` in two places.
+
+```
+$ make
+$ make install
+```
+
+
+TODO:
+- git repos for all sources
+- command line magic for cygwin setup
+- better options for `dfu-drivers`
diff --git a/doc/FUSE.txt b/doc/FUSE.txt
new file mode 100644
index 000000000..99ddd2d18
--- /dev/null
+++ b/doc/FUSE.txt
@@ -0,0 +1,50 @@
+Atmega32u4 Fuse/Lock Bits for Planck/Atomic/Preonic
+=========================
+
+ Low Fuse: 0x5E
+ High Fuse: 0x99
+ Extended Fuse: 0xF3
+ Lock Byte: 0xFF
+
+
+ATMega168P Fuse/Lock Bits
+=========================
+This configuration is from usbasploader's Makefile.
+
+ HFUSE 0xD6
+ LFUSE 0xDF
+ EFUSE 0x00
+ LOCK 0x3F(intact)
+
+#---------------------------------------------------------------------
+# ATMega168P
+#---------------------------------------------------------------------
+# Fuse extended byte:
+# 0x00 = 0 0 0 0 0 0 0 0 <-- BOOTRST (boot reset vector at 0x1800)
+# \+/
+# +------- BOOTSZ (00 = 2k bytes)
+# Fuse high byte:
+# 0xd6 = 1 1 0 1 0 1 1 0
+# ^ ^ ^ ^ ^ \-+-/
+# | | | | | +------ BODLEVEL 0..2 (110 = 1.8 V)
+# | | | | + --------- EESAVE (preserve EEPROM over chip erase)
+# | | | +-------------- WDTON (if 0: watchdog always on)
+# | | +---------------- SPIEN (allow serial programming)
+# | +------------------ DWEN (debug wire enable)
+# +-------------------- RSTDISBL (reset pin is enabled)
+# Fuse low byte:
+# 0xdf = 1 1 0 1 1 1 1 1
+# ^ ^ \ / \--+--/
+# | | | +------- CKSEL 3..0 (external >8M crystal)
+# | | +--------------- SUT 1..0 (crystal osc, BOD enabled)
+# | +------------------ CKOUT (if 0: Clock output enabled)
+# +-------------------- CKDIV8 (if 0: divide by 8)
+
+
+# Lock Bits
+# 0x3f = - - 1 1 1 1 1 1
+# \ / \-/ \-/
+# | | +----- LB 2..1 (No memory lock features enabled)
+# | +--------- BLB0 2..1 (No restrictions for SPM or LPM accessing the Application section)
+# +--------------- BLB1 2..1 (No restrictions for SPM or LPM accessing the Boot Loader section)
+
diff --git a/doc/HAND_WIRE.md b/doc/HAND_WIRE.md
new file mode 100644
index 000000000..18cb7011f
--- /dev/null
+++ b/doc/HAND_WIRE.md
@@ -0,0 +1,321 @@
+# Quantum Hand-wiring Guide
+
+Parts list:
+* *x* keyswitches (MX, Matias, Gateron, etc)
+* *x* diodes
+* Keyboard plate (metal, plastic, cardboard, etc)
+* Wire (strained for wiring to the Teensy, anything for the rows/columns)
+* Soldering iron set at 600ºF or 315ºC (if temperature-controlled)
+* Resin-cored solder (leaded or lead-free)
+* Adequate ventilation/a fan
+* Tweezers (optional)
+* Wire cutters/snippers
+
+## How the matrix works (why we need diodes)
+
+The microcontroller (in this case, the Teensy 2.0) will be setup up via the firmware to send a logical 1 to the columns, one at a time, and read from the rows, all at once - this process is called matrix scanning. The matrix is a bunch of open switches that, by default, don't allow any current to pass through - the firmware will read this as no keys being pressed. As soon as you press one key down, the logical 1 that was coming from the column the keyswitch is attached to gets passed through the switch and to the corresponding row - check out the following 2x2 example:
+
+ Column 0 being scanned Column 1 being scanned
+ x x
+ col0 col1 col0 col1
+ | | | |
+ row0 ---(key0)---(key1) row0 ---(key0)---(key1)
+ | | | |
+ row1 ---(key2)---(key3) row1 ---(key2)---(key3)
+
+The `x` represents that the column/row associated has a value of 1, or is HIGH. Here, we see that no keys are being pressed, so no rows get an `x`. For one keyswitch, keep in mind that one side of the contacts is connected to its row, and the other, its column.
+
+When we press `key0`, `col0` gets connected to `row0`, so the values that the firmware receives for that row is `0b01` (the `0b` here means that this is a bit value, meaning all of the following digits are bits - 0 or 1 - and represent the keys in that column). We'll use this notation to show when a keyswitch has been pressed, to show that the column and row are being connected:
+
+ Column 0 being scanned Column 1 being scanned
+ x x
+ col0 col1 col0 col1
+ | | | |
+ x row0 ---(-+-0)---(key1) row0 ---(-+-0)---(key1)
+ | | | |
+ row1 ---(key2)---(key3) row1 ---(key2)---(key3)
+
+We can now see that `row0` has an `x`, so has the value of 1. As a whole, the data the firmware receives when `key0` is pressed is
+
+ col0: 0b01
+ col1: 0b00
+ │└row0
+ └row1
+
+A problem arises when you start pressing more than one key at a time. Looking at our matrix again, it should become pretty obvious:
+
+ Column 0 being scanned Column 1 being scanned
+ x x
+ col0 col1 col0 col1
+ | | | |
+ x row0 ---(-+-0)---(-+-1) x row0 ---(-+-0)---(-+-1)
+ | | | |
+ x row1 ---(key2)---(-+-3) x row1 ---(key2)---(-+-3)
+
+ Remember that this ^ is still connected to row1
+
+The data we get from that is:
+
+ col0: 0b11
+ col1: 0b11
+ │└row0
+ └row1
+
+Which isn't accurate, since we only have 3 keys pressed down, not all 4. This behavior is called ghosting, and only happens in odd scenarios like this, but can be much more common on a bigger keyboard. The way we can get around this is by placing a diode after the keyswitch, but before it connects to its row. A diode only allows current to pass through one way, which will protect our other columns/rows from being activated in the previous example. We'll represent a dioded matrix like this;
+
+ Column 0 being scanned Column 1 being scanned
+ x x
+ col0 col1 col0 col1
+ │ │ | │
+ (key0) (key1) (key0) (key1)
+ ! │ ! │ ! | ! │
+ row0 ─────┴────────┘ │ row0 ─────┴────────┘ │
+ │ │ | │
+ (key2) (key3) (key2) (key3)
+ ! ! ! !
+ row1 ─────┴────────┘ row1 ─────┴────────┘
+
+In practical applications, the black line of the diode will be placed facing the row, and away from the keyswitch - the `!` in this case is the diode, where the gap represents the black line. A good way to remember this is to think of this symbol: `>|`
+
+Now when we press the three keys, invoking what would be a ghosting scenario:
+
+ Column 0 being scanned Column 1 being scanned
+ x x
+ col0 col1 col0 col1
+ │ │ │ │
+ (┌─┤0) (┌─┤1) (┌─┤0) (┌─┤1)
+ ! │ ! │ ! │ ! │
+ x row0 ─────┴────────┘ │ x row0 ─────┴────────┘ │
+ │ │ │ │
+ (key2) (┌─┘3) (key2) (┌─┘3)
+ ! ! ! !
+ row1 ─────┴────────┘ x row1 ─────┴────────┘
+
+Things act as they should! Which will get us the following data:
+
+ col0: 0b01
+ col1: 0b11
+ │└row0
+ └row1
+
+The firmware can then use this correct data to detect what it should do, and eventually, what signals it needs to send to the OS.
+
+## The actual hand-wiring
+
+### Getting things in place
+
+When starting this, you should have all of your stabilisers and keyswitches already installed (and optionally keycaps). If you're using a Cherry-type stabiliser (plate-mounted only, obviously), you'll need to install that before your keyswitches. If you're using Costar ones, you can installed them afterwards.
+
+To make things easier on yourself, make sure all of the keyswitches are oriented the same way (if they can be - not all layouts support this). Despite this, it's important to remember that the contacts on the keyswitches are completely symmetrical. We'll be using the keyswitch's left side contact for wiring the rows, and the right side one for wiring the columns.
+
+Get your soldering iron heated-up and collect the rest of the materials from the part list at the beginning of the guide. Place your keyboard so that the bottoms of the keyswitches are accessible - it may be a good idea to place it on a cloth to protect your keyswitches/keycaps.
+
+Before continuing, plan out where you're going to place your Teensy. If you're working with a board that has a large (6.25u) spacebar, it may be a good idea to place it in-between switches against the plate. Otherwise, you may want to trim some of the leads on the keyswitches where you plan on putting it - this will make it a little harder to solder the wire/diodes, but give you more room to place the Teensy.
+
+### Preparing the diodes
+
+It's a little easier to solder the diodes in place if you bend them at a 90º angle immediately after the black line - this will help to make sure you put them on the right way (direction matters), and in the correct position. The diodes will look like this when bent (with longer leads):
+
+ ┌─────┬─┐
+ ───┤ │ ├─┐
+ └─────┴─┘ │
+ │
+
+We'll be using the long lead at the bent end to connect it to the elbow (bent part) of the next diode, creating the row.
+
+### Soldering the diodes
+
+Starting at the top-left switch, place the diode (with tweezers if you have them) on the switch so that the diode itself is vertically aligned, and the black line is facing toward you. The straight end of the diode should be touching the left contact on the switch, and the bent end should be facing to the right and resting on the switch there, like this:
+
+ │o
+ ┌┴┐ o
+ │ │ O
+ ├─┤
+ └┬┘
+ └─────────────
+
+Letting the diode rest, grab your solder, and touch both it and the soldering iron to the left contact at the same time - the rosin in the solder should make it easy for the solder to flow over both the diode and the keyswitch contact. The diode may move a little, and if it does, carefully position it back it place by grabbing the bent end of the diode - the other end will become hot very quickly. If you find that it's moving too much, using needle-nose pliers of some sort may help to keep the diode still when soldering.
+
+The smoke that the rosin releases is harmful, so be careful not to breath it or get it in your eyes/face.
+
+After soldering things in place, it may be helpful to blow on the joint to push the smoke away from your face, and cool the solder quicker. You should see the solder develop a matte (not shiney) surface as it solidifies. Keep in mind that it will still be very hot afterwards, and will take a couple minutes to be cool to touch. Blow on it will accelerate this process.
+
+When the first diode is complete, the next one will need to be soldered to both the keyswitch, and the previous diode at the new elbow. That will look something like this:
+
+ │o │o
+ ┌┴┐ o ┌┴┐ o
+ │ │ O │ │ O
+ ├─┤ ├─┤
+ └┬┘ └┬┘
+ └────────────────┴─────────────
+
+After completing a row, use the wire cutters to trim the excess wire from the tops of the diodes, and from the right side on the final switch. This process will need to completed for each row you have.
+
+When all of the diodes are completely soldered, it's a good idea to quickly inspect each one to ensure that your solder joints are solid and sturdy - repairing things after this is possible, but more difficult.
+
+### Soldering the columns
+
+You'll have some options in the next process - it's a good idea to insulate the column wires (since the diodes aren't), but if you're careful enough, you can use exposed wires for the columns - it's not recommended, though. If you're using single-cored wire, stripping the plastic off of the whole wire and feeding it back on is probably the best option, but can be difficult depending on the size and materials. You'll want to leave parts of the wire exposed where you're going to be solder it onto the keyswitch.
+
+If you're using stranded wire, it's probably easiest to just use a lot of small wires to connect each keyswitch along the column. It's possible to use one and melt through the insulation, but this isn't recommended, will produce even more harmful fumes, and can ruin your soldering iron.
+
+Before beginning to solder, it helps to have your wire pre-bent (if using single-cored), or at least have an idea of how you're going to route the column (especially if you're making a staggered board). Where you go in particular doesn't matter too much, as we'll be basing our keymap definitions on how it was wired - just make sure every key in a particular row is in a unique column, and that they're in order from left to right.
+
+If you're not using any insulation, you can try to keep the column wires elevated, and solder them near the tips of the keyswitch contacts - if the wires are sturdy enough, they won't short out to the row wiring an diodes.
+
+### Wiring things to the Teensy
+
+Now that the matrix itself is complete, it's time to connect what you've done to the Teensy. You'll be needing the number of pins equal to your number of columns + your number of rows. There are some pins on the Teensy that are special, like D6 (the LED on the chip), or some of the UART, SPI, I2C, or PWM channels, but only avoid those if you're planning something in addition to a keyboard. If you're unsure about wanting to add something later, you should have enough pins in total to avoid a couple.
+
+The pins you'll absolutely have to avoid are: GND, VCC, AREF, and RST - all the others are usable and accessible in the firmware.
+
+Place the Teensy where you plan to put it - you'll have to cut wires to length in the next step, and you'll want to make sure they reach.
+
+Starting with the first column on the right side, measure out how much wire you'll need to connect it to the first pin on the Teensy - it helps to pick a side that you'll be able to work down, to keep the wires from overlapping too much. It may help to leave a little bit of slack so things aren't too tight. Cut the piece of wire, and solder it to the Teensy, and then the column - you can solder it anywhere along the column, but it may be easiest at the keyswitch. Just be sure the wire doesn't separate from the keyswitch when soldering.
+
+As you move from column to column, it'll be helpful to write the locations of the pins down. We'll use this data to setup the matrix in the future.
+
+When you're done with the columns, start with the rows in the same process, from top to bottom, and write them all down. Again, you can solder anywhere along the row, as long as it's after the diode - soldering before the diode (on the keyswitch side) will cause that row not to work.
+
+As you move along, be sure that the Teensy is staying in place - recutting and soldering the wires is a pain!
+
+### Getting some basic firmware set-up
+
+From here, you should have a working keyboard with the correct firmware. Before we attach the Teensy permanently to the keyboard, let's quickly get some firmware loaded onto the Teensy so we can test each keyswitch.
+
+To start out, download [the firmware](https://github.com/jackhumbert/qmk_firmware/) - we'll be using my (Jack's) fork of TMK called QMK/Quantum. We'll be doing a lot from the Terminal/command prompt, so get that open, along with a decent text editor like [Sublime Text](http://www.sublimetext.com/).
+
+The first thing we're going to do is create a new project using the script in the root directory of the firmware. In your terminal, run this command with `<project_name>` replaced by the name of your project - it'll need to be different from any other project in the `keyboards/` folder:
+
+ util/new_project.sh <project_name>
+
+You'll want to navigate to the `keyboards/<project_name>/` folder by typing, like the print-out from the script specifies:
+
+ cd keyboards/<project_name>
+
+#### config.h
+
+The first thing you're going to want to modify is the `config.h` file. Find `MATRIX_ROWS` and `MATRIX_COLS` and change their definitions to match the dimensions of your keyboard's matrix.
+
+Farther down are `MATRIX_ROW_PINS` and `MATRIX_COL_PINS`. Change their definitions to match how you wired up your matrix (looking from the top of the keyboard, the rows run top-to-bottom and the columns run left-to-right). Likewise, change the definition of `UNUSED_PINS` to match the pins you did not use (this will save power).
+
+#### \<project_name\>.h
+
+The next file you'll want to look at is `<project_name>.h`. You're going to want to rewrite the `KEYMAP` definition - the format and syntax here is extremely important, so pay attention to how things are setup. The first half of the definition are considered the arguments - this is the format that you'll be following in your keymap later on, so you'll want to have as many k*xy* variables here as you do keys. The second half is the part that the firmware actually looks at, and will contain gaps depending on how you wired your matrix.
+
+We'll dive into how this will work with the following example. Say we have a keyboard like this:
+
+ ┌───┬───┬───┐
+ │ │ │ │
+ ├───┴─┬─┴───┤
+ │ │ │
+ └─────┴─────┘
+
+This can be described by saying the top row is 3 1u keys, and the bottom row is 2 1.5u keys. The difference between the two rows is important, because the bottom row has an unused column spot (3 v 2). Let's say that this is how we wired the columns:
+
+ ┌───┬───┬───┐
+ │ ┋ │ ┋ │ ┋ │
+ ├─┋─┴─┬─┴─┋─┤
+ │ ┋ │ ┋ │
+ └─────┴─────┘
+
+The middle column is unused on the bottom row in this example. Our `KEYMAP` definition would look like this:
+
+ #define KEYMAP( \
+ k00, k01, k02, \
+ k10, k11, \
+ ) \
+ { \
+ { k00, k01, k02 }, \
+ { k10, KC_NO, k11 }, \
+ }
+
+Notice how the top half is spaced to resemble our physical layout - this helps us understand which keys are associated with which columns. The bottom half uses the keycode `KC_NO` where there is no keyswitch wired in. It's easiest to keep the bottom half aligned in a grid to help us make sense of how the firmware actually sees the wiring.
+
+Let's say that instead, we wired our keyboard like this (a fair thing to do):
+
+ ┌───┬───┬───┐
+ │ ┋ │ ┋│ ┋ │
+ ├─┋─┴─┬┋┴───┤
+ │ ┋ │┋ │
+ └─────┴─────┘
+
+This would require our `KEYMAP` definition to look like this:
+
+ #define KEYMAP( \
+ k00, k01, k02, \
+ k10, k11, \
+ ) \
+ { \
+ { k00, k01, k02 }, \
+ { k10, k11, KC_NO }, \
+ }
+
+Notice how the `k11` and `KC_NO` switched places to represent the wiring, and the unused final column on the bottom row. Sometimes it'll make more sense to put a keyswitch on a particular column, but in the end, it won't matter, as long as all of them are accounted for. You can use this process to write out the `KEYMAP` for your entire keyboard - be sure to remember that your keyboard is actually backwards when looking at the underside of it.
+
+#### keymaps/default.c
+
+This is the actual keymap for your keyboard, and the main place you'll make changes as you perfect your layout. `default.c` is the file that gets pull by default when typing `make`, but you can make other files as well, and specify them by typing `make KEYMAP=<variant>`, which will pull `keymaps/<variant>.c`.
+
+The basis of a keymap is its layers - by default, layer 0 is active. You can activate other layers, the highest of which will be referenced first. Let's start with our base layer.
+
+Using our previous example, let's say we want to create the following layout:
+
+ ┌───┬───┬───┐
+ │ A │ 1 │ H │
+ ├───┴─┬─┴───┤
+ │ TAB │ SPC │
+ └─────┴─────┘
+
+This can be accomplished by using the following `keymaps` definition:
+
+ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ [0] = KEYMAP( /* Base */
+ KC_A, KC_1, KC_H, \
+ KC_TAB, KC_SPC \
+ ),
+ };
+
+Note that the layout of the keycodes is similar to the physical layout of our keyboard - this make it much easier to see what's going on. A lot of the keycodes should be fairly obvious, but for a full list of them, check out [tmk_code/doc/keycode.txt](https://github.com/jackhumbert/qmk_firmware/blob/master/tmk_core/doc/keycode.txt) - there are also a lot of aliases to condense your keymap file.
+
+It's also important to use the `KEYMAP` function we defined earlier - this is what allows the firmware to associate our intended readable keymap with the actual wiring.
+
+#### Compiling your firmware
+
+After you've written out your entire keymap, you're ready to get the firmware compiled and onto your Teensy. Before compiling, you'll need to get your [development environment set-up](/doc/BUILD_GUIDE.md) - you can skip the dfu-programmer instructions, but you'll need to download and install the [Teensy Loader](https://www.pjrc.com/teensy/loader.html) to get the firmware on your Teensy.
+
+Once everything is installed, running `make` in the terminal should get you some output, and eventually a `<project_name>.hex` file in that folder. If you're having trouble with this step, see the end of the guide for the trouble-shooting section.
+
+Once you have your `<project_name>.hex` file, open up the Teensy loader application, and click the file icon. From here, navigate to your `QMK/keyboards/<project_name>/` folder, and select the `<project_name>.hex` file. Plug in your keyboard and press the button on the Teensy - you should see the LED on the device turn off once you do. The Teensy Loader app will change a little, and the buttons should be clickable - click the download button (down arrow), and then the reset button (right arrow), and your keyboard should be ready to go!
+
+#### Testing your firmware
+
+Carefully flip your keyboard over, open up a new text document, and try typing - you should get the characters that you put into your keymap. Test each key, and note the ones that aren't working. Here's a quick trouble-shooting guide for non-working keys:
+
+0. Flip the keyboard back over and short the keyswitch's contacts with a piece wire - this will eliminate the possibility of the keyswitch being bad and needing to be replaced.
+1. Check the solder points on the keyswitch - these need to be plump and whole. If you touch it with a moderate amount of force and it comes apart, it's not strong enough.
+2. Check the solder joints on the diode - if the diode is loose, part of your row may register, while the other may not.
+3. Check the solder joints on the columns - if your column wiring is loose, part or all of the column may not work.
+4. Check the solder joints on both sides of the wires going to/from the Teensy - the wires need to be fully soldered and connect to both sides.
+5. Check the <project_name>.h file for errors and incorrectly placed `KC_NO`s - if you're unsure where they should be, instead duplicate a k*xy* variable.
+6. Check to make sure you actually compiled the firmware and flashed the Teensy correctly. Unless you got error messages in the terminal, or a pop-up during flashing, you probably did everything correctly.
+
+If you've done all of these things, keep in mind that sometimes you might have had multiple things affecting the keyswitch, so it doesn't hurt to test the keyswitch by shorting it out at the end.
+
+#### Securing the Teensy, finishing your hardware, getting fancier firmware
+
+Now that you have a working board, it's time to get things in their permanent positions. I've often used liberal amounts of hot glue to secure and insulate things, so if that's your style, start spreading that stuff like butter. Otherwise, double-sided tape is always an elegant solution, and electrical tape is a distant second. Due to the nature of these builds, a lot of this part is up to you and how you planned (or didn't plan) things out.
+
+There are a lot of possibilities inside the firmware - check out the [readme](https://github.com/jackhumbert/qmk_firmware/blob/master/readme.md) for a full feature list, and dive into the different project (Planck, Ergodox EZ, etc) to see how people use all of them. You can always stop by [the OLKB subreddit for help!](http://reddit.com/r/olkb)
+
+## Trouble-shooting compiling
+
+### Windows
+
+#### fork: Resource temporarily unavailable
+
+http://www.avrfreaks.net/forum/windows-81-compilation-error
+
+### Mac
+
+### Linux
diff --git a/doc/PCB_GUIDE.md b/doc/PCB_GUIDE.md
new file mode 100644
index 000000000..3fad41dfb
--- /dev/null
+++ b/doc/PCB_GUIDE.md
@@ -0,0 +1,151 @@
+# Planck Firmware Guide
+
+## Setting up the environment
+
+### Windows
+1. Install [MHV AVR Tools](https://infernoembedded.com/sites/default/files/project/MHV_AVR_Tools_20131101.exe). Disable smatch, but **be sure to leave the option to add the tools to the PATH checked**.
+2. Install [MinGW](https://sourceforge.net/projects/mingw/files/Installer/mingw-get-setup.exe/download). During installation, uncheck the option to install a graphical user interface. **DO NOT change the default installation folder.** The scripts depend on the default location.
+3. Clone this repository. [This link will download it as a zip file, which you'll need to extract.](https://github.com/jackhumbert/qmk_firmware/archive/master.zip) Open the extracted folder in Windows Explorer.
+4. Right-click on the 1-setup-path-win batch script, select "Run as administrator", and accept the User Account Control prompt. Press the spacebar to dismiss the success message in the command prompt that pops up.
+5. Right-click on the 2-setup-environment-win batch script, select "Run as administrator", and accept the User Account Control prompt. This part may take a couple of minutes, and you'll need to approve a driver installation, but once it finishes, your environment is complete!
+
+
+### Mac
+
+If you're using homebrew, you can use the following commands:
+
+ brew tap osx-cross/avr
+ brew install avr-libc
+ brew install dfu-programmer
+
+Otherwise, these instructions will work:
+
+1. Install Xcode from the App Store.
+2. Install the Command Line Tools from `Xcode->Preferences->Downloads`.
+3. Install [DFU-Programmer][dfu-prog].
+
+### Linux
+1. Install AVR GCC with your favorite package manager.
+2. Install [DFU-Programmer][dfu-prog].
+
+Note that, since it will be directly accessing USB hardware, the
+`dfu-programmer` program needs to be run as root.
+
+## Verify Your Installation
+1. Clone the following repository: https://github.com/jackhumbert/qmk_firmware
+2. Open a Terminal and `cd` into `qmk_firmware/keyboards/planck`
+3. Run `make`. This should output a lot of information about the build process.
+
+## Using the built-in functions
+
+Here is a list of some of the functions available from the command line:
+
+* `make clean`: clean the environment - may be required in-between builds
+* `make`: compile the code
+* `make KEYMAP=<keymap>`: compile with the extended keymap file `extended_keymaps/extended_keymap_<keymap>.c`
+* `make dfu`: build and flash the layout to the PCB
+* `make dfu-force`: build and force-flash the layout to the PCB (may be require for first flash)
+
+Generally, the instructions to flash the PCB are as follows:
+
+1. Make changes to the appropriate keymap file
+2. Save the file
+3. `make clean`
+4. Press the reset button on the PCB/press the key with the `RESET` keycode
+5. `make <arguments> dfu` - use the necessary `KEYMAP=<keymap>` and/or `COMMON=true` arguments here.
+
+## Troubleshooting
+If you see something like this
+
+ 0 [main] sh 13384 sync_with_child: child 9716(0x178) died before initialization with status code 0xC0000142
+ 440 [main] sh 13384 sync_with_child: *** child state waiting for longjmp
+ /usr/bin/sh: fork: Resource temporarily unavailable
+
+after running 'make' on Windows than you are encountering a very popular issue with WinAVR on Windows 8.1 and 10.
+You can easily fix this problem by replacing msys-1.0.dll in WinAVR/utils/bin with [this one](http://www.madwizard.org/download/electronics/msys-1.0-vista64.zip).
+Restart your system and everything should work fine!
+
+
+If you see this
+
+ dfu-programmer atmega32u4 erase
+ process_begin: CreateProcess(NULL, dfu-programmer atmega32u4 erase, ...) failed.
+ make (e=2): The system cannot find the file specified.
+ make: *** [dfu] Error 2
+
+when trying to 'make dfu' on Windows you need to copy the dfu-programmer.exe to qmk_firmware/keyboards/planck.
+
+
+## Quantum MK Firmware
+
+### Keymap
+
+Unlike the other keymaps, prefixing the keycodes with `KC_` is required. A full list of the keycodes is available [here](https://github.com/jackhumbert/qmk_firmware/blob/master/tmk_core/doc/keycode.txt). For the keycodes available only in the extended keymap, see this [header file](https://github.com/jackhumbert/qmk_firmware/blob/master/quantum/keymap_common.h).
+
+You can use modifiers with keycodes like this:
+
+ LCTL(KC_C)
+
+Which will generate Ctrl+c. These are daisy-chainable, meaning you can do things like:
+
+ LCTL(LALT(KC_C))
+
+That will generate Ctrl+Alt+c. The entire list of these functions is here:
+
+* `LCTL()`: Left control
+* `LSFT()` / `S()`: Left shift
+* `LALT()`: Left alt/opt
+* `LGUI()`: Left win/cmd
+* `RCTL()`: Right control
+* `RSFT()`: Right shift
+* `RALT()`: Right alt/opt
+* `RGUI()`: Right win/cmd
+
+`S(KC_1)`-like entries are useful in writing keymaps for the Planck.
+
+### Other keycodes
+
+A number of other keycodes have been added that you may find useful:
+
+* `CM_<key>`: the Colemak equivalent of a key (in place of `KC_<key>`), when using Colemak in software (`CM_O` generates `KC_SCLN`)
+* `RESET`: jump to bootloader for flashing (same as press the reset button)
+* `BL_STEP`: step through the backlight brightnesses
+* `BL_<0-15>`: set backlight brightness to 0-15
+* `BL_DEC`: lower the backlight brightness
+* `BL_INC`: raise the backlight brightness
+* `BL_TOGG`: toggle the backlight on/off
+
+### Function layers
+
+The extended keymap extends the number of function layers from 32 to the near-infinite value of 256. Rather than using `FN<num>` notation (still available, but limited to `FN0`-`FN31`), you can use the `FUNC(<num>)` notation. `F(<num>)` is a shortcut for this.
+
+The function actions are unchanged, and you can see the full list of them [here](https://github.com/jackhumbert/tmk_keyboard/blob/master/common/action_code.h). They are explained in detail [here](https://github.com/jackhumbert/tmk_keyboard/blob/master/doc/keymap.md#2-action).
+
+### Macros
+
+Macros have been setup in the `keymaps/keymap_default.c` file so that you can use `M(<num>)` to access a macro in the `action_get_macro` section on your keymap. The switch/case structure you see here is required, and is setup for `M(0)` - you'll need to copy and paste the code to look like this (e.g. to support `M(3)`):
+
+ switch(id) {
+ case 0:
+ return MACRODOWN(TYPE(KC_A), END);
+ break;
+ case 1:
+ return MACRODOWN(TYPE(KC_B), END);
+ break;
+ case 2:
+ return MACRODOWN(TYPE(KC_C), END);
+ break;
+ case 3:
+ return MACRODOWN(TYPE(KC_D), END);
+ break;
+ }
+ return MACRO_NONE;
+
+`MACRODOWN()` is a shortcut for `(record->event.pressed ? MACRO(__VA_ARGS__) : MACRO_NONE)` which tells the macro to execute when the key is pressed. Without this, the macro will be executed on both the down and up stroke.
+
+[cygwin]: https://www.cygwin.com/
+[mingw]: http://www.mingw.org/
+[mhv]: https://infernoembedded.com/products/avr-tools
+[winavr]: http://winavr.sourceforge.net/
+[crosspack]: http://www.obdev.at/products/crosspack/index.html
+[dfu-prog]: http://dfu-programmer.sourceforge.net/
diff --git a/doc/POWER.txt b/doc/POWER.txt
new file mode 100644
index 000000000..0abbbe48e
--- /dev/null
+++ b/doc/POWER.txt
@@ -0,0 +1,62 @@
+Time to Sleep
+=============
+USB suspend no activity on USB line for 3ms
+No Interaction no user interaction
+ matrix has no change
+ matrix has no switch on
+
+
+AVR Power Management
+====================
+
+V-USB suspend
+ USB suspend
+ http://vusb.wikidot.com/examples
+
+MCUSR MCU Status Register
+ WDRF Watchdog Reset Flag
+ BORF
+ EXTRF
+ PORF Power-on Reset Flag
+
+SMCR Sleep Mode Control Register
+ SE Sleep Enable
+ SM2:0
+ #define set_sleep_mode(mode) \
+ #define SLEEP_MODE_IDLE (0)
+ #define SLEEP_MODE_ADC _BV(SM0)
+ #define SLEEP_MODE_PWR_DOWN _BV(SM1)
+ #define SLEEP_MODE_PWR_SAVE (_BV(SM0) | _BV(SM1))
+ #define SLEEP_MODE_STANDBY (_BV(SM1) | _BV(SM2))
+ #define SLEEP_MODE_EXT_STANDBY (_BV(SM0) | _BV(SM1) | _BV(SM2))
+
+
+ACSR Analog Comparator Control and Status Register
+ To disable Analog Comparator
+ ACSR = 0x80;
+ or
+ ACSR &= ~_BV(ACIE);
+ ACSR |= _BV(ACD);
+
+ ACD: Analog Comparator Disable
+ When this bit is written logic one, the power to the Analog Comparator is
+ switched off. This bit can be set at any time to turn off the Analog
+ Comparator. This will reduce power consumption in Active and Idle mode.
+ When changing the ACD bit, the Analog Comparator Interrupt must be disabled
+ by clearing the ACIE bit in ACSR. Otherwise an interrupt can occur when
+ the bit is changed.
+
+DIDR1 Digital Input Disable Register 1
+ AIN1D
+ AIN0D
+ When this bit is written logic one, the digital input buffer on the AIN1/0 pin is disabled. The corresponding PIN Register bit will always read as zero when this bit is set. When an analog signal is applied to the AIN1/0 pin and the digital input from this pin is not needed, this bit should be written logic one to reduce power consumption in the digital input buffer.
+
+
+PRR Power Reduction Register
+ PRTWI
+ PRTIM2
+ PRTIM0
+ PRTIM1
+ PRSPI
+ PRUSART0
+ PRADC
diff --git a/doc/TMK_README.md b/doc/TMK_README.md
new file mode 100644
index 000000000..6164dacd3
--- /dev/null
+++ b/doc/TMK_README.md
@@ -0,0 +1,243 @@
+# TMK Documenation
+
+Features
+--------
+These features can be used in your keyboard.
+
+* Multi-layer Keymap - Multiple keyboard layouts with layer switching
+* Mouse key - Mouse control with keyboard
+* System Control Key - Power Down, Sleep, Wake Up and USB Remote Wake up
+* Media Control Key - Volume Down/Up, Mute, Next/Prev track, Play, Stop and etc
+* USB NKRO - 120 keys(+ 8 modifiers) simultaneously
+* PS/2 mouse support - PS/2 mouse(TrackPoint) as composite device
+* Keyboard protocols - PS/2, ADB, M0110, Sun and other old keyboard protocols
+* User Function - Customizable function of key with writing code
+* Macro - Very primitive at this time
+* Keyboard Tricks - Oneshot modifier and modifier with tapping feature
+* Debug Console - Messages for debug and interaction with firmware
+* Virtual DIP Switch - Configurations stored EEPROM(Boot Magic)
+* Locking CapsLock - Mechanical switch support for CapsLock
+* Breathing Sleep LED - Sleep indicator with charm during USB suspend
+* Backlight - Control backlight levels
+
+
+
+Projects
+--------
+You can find some keyboard specific projects under `converter` and `keyboard` directory.
+
+## Main projects
+
+### OLKB products
+* [planck](keyboards/planck/) - [Planck] Ortholinear 40% keyboard
+* [preonic](keyboards/preonic/) - [Preonic] Ortholinear 50% keyboard
+* [atomic](keyboards/atomic/) - [Atomic] Ortholinear 60% keyboard
+
+### Ergodox EZ
+* [ergodox_ez](keyboards/ergodox_ez) - [Ergodox_EZ] Assembled split keyboard
+
+## Other projects
+
+### converter
+* [ps2_usb](converter/ps2_usb/) - [PS/2 keyboard to USB][GH_ps2]
+* [adb_usb](converter/adb_usb/) - [ADB keyboard to USB][GH_adb]
+* [m0110_usb](converter/m0110_usb) - [Macintosh 128K/512K/Plus keyboard to USB][GH_m0110]
+* [terminal_usb](converter/terminal_usb/) - [IBM Model M terminal keyboard(PS/2 scancode set3) to USB][GH_terminal]
+* [news_usb](converter/news_usb/) - [Sony NEWS keyboard to USB][GH_news]
+* [x68k_usb](converter/x68k_usb/) - [Sharp X68000 keyboard to USB][GH_x68k]
+* [sun_usb](converter/sun_usb/) - [Sun] to USB(type4, 5 and 3?)
+* [pc98_usb](converter/pc98_usb/) - [PC98] to USB
+* [usb_usb](converter/usb_usb/) - USB to USB(experimental)
+* [ascii_usb](converter/ascii_usb/) - ASCII(Serial console terminal) to USB
+* [ibm4704_usb](converter/ibm4704_usb) - [IBM 4704 keyboard Converter][GH_ibm4704]
+
+### keyboard
+* [hhkb](keyboards/hhkb/) - [Happy Hacking Keyboard pro][GH_hhkb] hasu's main board
+* [gh60](keyboards/gh60/) - [GH60] DIY 60% keyboard [prototype][GH60_proto] hasu's second board
+* [hbkb](keyboards/hbkb/) - [Happy Buckling spring keyboard][GH_hbkb](IBM Model M 60% mod)
+* [hid_liber](keyboards/hid_liber/) - [HID liberation][HID_liber] controller (by alaricljs)
+* [phantom](keyboards/phantom/) - [Phantom] keyboard (by Tranquilite)
+* [IIgs_Standard](keyboards/IIgs/) - Apple [IIGS] keyboard mod(by JeffreySung)
+* [macway](keyboards/macway/) - [Compact keyboard mod][GH_macway] [retired]
+* [KMAC](keyboards/kmac/) - Korean custom keyboard
+* [Lightsaber](keyboards/lightsaber/) - Korean custom keyboard
+* [Infinity](keyboards/infinity/) - Massdrop [Infinity keyboard][Infinity]
+* [NerD](keyboards/nerd/) - Korean custom keyboard
+* [KittenPaw](keyboards/kitten_paw) - Custom Majestouch controller
+* [Lightpad](keyboards/lightpad) - Korean custom keypad
+* [ghost_squid](keyboards/ghost_squid/) - [The Ghost Squid][ghost_squid] controller for [Cooler Master QuickFire XT][cmxt]
+
+### Extenal projects using tmk_keyboard
+* [ErgoDox_cub-uanic][cub-uanic] - Split Ergonomic Keyboard [ErgoDox][ergodox_org]
+* [mcdox][mcdox_tmk] - [mcdox][mcdox]
+
+
+[GH_macway]: http://geekhack.org/showwiki.php?title=Island:11930
+[GH_hhkb]: http://geekhack.org/showwiki.php?title=Island:12047
+[GH_ps2]: http://geekhack.org/showwiki.php?title=Island:14618
+[GH_adb]: http://geekhack.org/showwiki.php?title=Island:14290
+[GH_hhkb_bt]: http://geekhack.org/showwiki.php?title=Island:20851
+[GH_m0110]: http://geekhack.org/showwiki.php?title=Island:24965
+[GH_news]: http://geekhack.org/showwiki.php?title=Island:25759
+[GH_terminal]: http://geekhack.org/showwiki.php?title=Island:27272
+[GH_x68k]: http://geekhack.org/showwiki.php?title=Island:29060
+[GH_hbkb]: http://geekhack.org/showwiki.php?title=Island:29483
+[GH_ibm4704]: http://geekhack.org/index.php?topic=54706.0
+[HID_liber]: http://deskthority.net/wiki/HID_Liberation_Device_-_DIY_Instructions
+[Phantom]: http://geekhack.org/index.php?topic=26742
+[GH60]: http://geekhack.org/index.php?topic=34959
+[GH60_proto]: http://geekhack.org/index.php?topic=37570.0
+[PC98]: http://en.wikipedia.org/wiki/NEC_PC-9801
+[Sun]: http://en.wikipedia.org/wiki/Sun-3
+[IIGS]: http://en.wikipedia.org/wiki/Apple_IIGS
+[Infinity]: https://www.massdrop.com/buy/infinity-keyboard-kit
+[ghost_squid]: http://deskthority.net/wiki/Costar_replacement_controllers#The_Ghost_Squid
+[cmxt]: http://gaming.coolermaster.com/en/products/keyboard/quickfirext/
+[ergodox_org]: http://ergodox.org/
+[cub-uanic]: https://github.com/cub-uanic/tmk_keyboard/tree/master/keyboard/ergodox
+[mcdox]: https://github.com/DavidMcEwan/mcdox
+[mcdox_tmk]: https://github.com/DavidMcEwan/tmk_keyboard/tree/master/keyboard/mcdox
+[Planck]: http://olkb.co/planck
+[Preonic]: http://olkb.co/preonic
+[Atomic]: http://olkb.co/atomic
+[Ergodox_EZ]: https://www.indiegogo.com/projects/ergodox-ez-an-incredible-mechanical-keyboard
+
+
+License
+-------
+**GPLv2** or later. Some protocol files are under **Modified BSD License**.
+
+Third party libraries like LUFA, PJRC and V-USB have their own license respectively.
+
+
+
+Build Firmware and Program Controller
+-------------------------------------
+See [doc/build.md](tmk_core/doc/build.md), or the readme in the particular keyboards/* folder.
+
+
+
+Change your keymap
+------------------
+See [doc/keymap.md](tmk_core/doc/keymap.md).
+
+
+
+Magic Commands
+--------------
+To see help press `Magic` + `H`.
+
+`Magic` key combination is `LShift` + `RShift` in many project, but `Power` key on ADB converter.
+`Magic` keybind can be vary on each project, check `config.h` in project directory.
+
+Following commands can be also executed with `Magic` + key. In console mode `Magic` keybind is not needed.
+
+ ----- Command Help -----
+ c: enter console mode
+ d: toggle debug enable
+ x: toggle matrix debug
+ k: toggle keyboard debug
+ m: toggle mouse debug
+ v: print device version & info
+ t: print timer count
+ s: print status
+ e: print eeprom config
+ n: toggle NKRO
+ 0/F10: switch to Layer0
+ 1/F1: switch to Layer1
+ 2/F2: switch to Layer2
+ 3/F3: switch to Layer3
+ 4/F4: switch to Layer4
+ PScr: power down/remote wake-up
+ Caps: Lock Keyboard(Child Proof)
+ Paus: jump to bootloader
+
+
+
+Boot Magic Configuration - Virtual DIP Switch
+---------------------------------------------
+Boot Magic are executed during boot up time. Press Magic key below then plug in keyboard cable.
+Note that you must use keys of **Layer 0** as Magic keys. These settings are stored in EEPROM so that retain your configure over power cycles.
+
+To avoid configuring accidentally additive salt key `KC_SPACE` also needs to be pressed along with the following configuration keys. The salt key is configurable in `config.h`. See [tmk_core/common/bootmagic.h](tmk_core/common/bootmagic.h).
+
+#### General
+- Skip reading EEPROM to start with default configuration(`ESC`)
+- Clear configuration stored in EEPROM to reset configuration(`Backspace`)
+
+#### Bootloader
+- Kick up Bootloader(`B`)
+
+#### Debug
+- Debug enable(`D`)
+- Debug matrix enable(`D`+`X`)
+- Debug keyboard enable(`D`+`K`)
+- Debug mouse enable(`D`+`M`)
+
+#### Keymap
+- Swap Control and CapsLock(`Left Control`)
+- Change CapsLock to Control(`Caps Lock`)
+- Swap LeftAlt and Gui(`Left Alt`)
+- Swap RightAlt and Gui(`Right Alt`)
+- Disable Gui(`Left Gui`)
+- Swap Grave and Escape(`Grave`)
+- Swap BackSlash and BackSpace(`Back Slash`)
+- Enable NKRO on boot(`N`)
+
+#### Default Layer
+- Set Default Layer to 0(`0`)
+- Set Default Layer to 1(`1`)
+- Set Default Layer to 2(`2`)
+- Set Default Layer to 3(`3`)
+- Set Default Layer to 4(`4`)
+- Set Default Layer to 5(`5`)
+- Set Default Layer to 6(`6`)
+- Set Default Layer to 7(`7`)
+
+
+
+Mechanical Locking support
+--------------------------
+This feature makes it possible for you to use mechanical locking switch for `CapsLock`, `NumLock`
+or `ScrollLock`. To enable this feature define these macros in `config.h` and use `KC_LCAP`, `KC_LN
+UM` or `KC_LSCR` in keymap for locking key instead of normal `KC_CAPS`, `KC_NLCK` or `KC_SLCK`. Res
+ync option tries to keep switch state consistent with keyboard LED state.
+
+ #define LOCKING_SUPPORT_ENABLE
+ #define LOCKING_RESYNC_ENABLE
+
+
+
+Start Your Own Project
+-----------------------
+**TBD**
+
+
+
+Debugging
+--------
+Use PJRC's `hid_listen` to see debug messages. You can use the tool for debug even if firmware use LUFA stack.
+
+You can use xprintf() to display debug info on `hid_listen`, see `tmk_core/common/xprintf.h`.
+
+
+
+Files and Directories
+-------------------
+### Top
+* tmk_core/ - core library
+* keyboards/ - keyboard projects
+* converter/ - protocol converter projects
+* doc/ - documents
+
+
+
+Coding Style
+-------------
+- Doesn't use Tab to indent, use 4-spaces instead.
+
+
+
+Other Keyboard Firmware Projects
+------------------
+You can learn a lot about keyboard firmware from these. See [doc/other_projects.md](tmk_core/doc/other_projects.md).
diff --git a/doc/USB_NKRO.txt b/doc/USB_NKRO.txt
new file mode 100644
index 000000000..d9f1d1229
--- /dev/null
+++ b/doc/USB_NKRO.txt
@@ -0,0 +1,160 @@
+USB NKRO MEMO
+=============
+2010/12/09
+
+
+References
+----------
+USB - boot mode, NKRO, compatibility, etc...
+ http://geekhack.org/showthread.php?t=13162
+NKey Rollover - Overview, Testing Methodology, and Results
+ http://geekhack.org/showwiki.php?title=NKey+Rollover+-+Overview+Testing+Methodology+and+Results
+dfj's NKRO(2010/06)
+ http://geekhack.org/showpost.php?p=191195&postcount=251
+ http://geekhack.org/showthread.php?p=204389#post204389
+
+
+Terminology
+---------
+NKRO
+ghost
+matrix
+mechanical with diodes
+membrane
+
+
+OS Support Status
+-----------------
+USB NKRO is possible *without* a custom driver.
+At least following OS's supports.
+ Windows7 64bit
+ WindowsXP
+ Windows2000 SP4
+ Ubuntu10.4(Linux 2.6)
+ MacOSX(To be tested)
+
+
+Custom Driver for USB NKRO
+--------------------------
+NOT NEEDED
+at least when using following report formats on Windows, Linux or MacOSX.
+
+
+USB NKRO methods
+----------------
+1. Virtual keyboards
+ Keyboard can increase its KRO by using virtual keyboards with Standard or Extended report.
+ If the keyboard has 2 virtual keyboard with Standard report(6KRO), it gets 12KRO.
+ Using this method means the keyboard is a composite device.
+
+2. Extended report
+ It needs large report size for this method to achieve NKRO.
+ If a keyboard has 101keys, it needs 103byte report. It seems to be inefficient.
+
+3. Bitmap report
+ If the keyboard has less than 128keys, 16byte report will be enough for NKRO.
+ The 16byte report seems to be reasonable cost to get NKRO.
+
+
+Report Format
+-------------
+Other report formats than followings are possible, though these format are typical one.
+
+1. Standard 8bytes
+ modifiers(bitmap) 1byte
+ reserved 1byte(not used)
+ keys(array) 1byte*6
+Standard report can send 6keys plus 8modifiers simultaneously.
+Standard report is used by most keyboards in the marketplace.
+Standard report is identical to boot protocol report.
+Standard report is hard to suffer from compatibility problems.
+
+2. Extended standard 16,32,64bytes
+ modifiers(bitmap) 1byte
+ reserved 1byte(not used)
+ keys(array) 1byte*(14,32,62)
+Extended report can send N-keys by using N+2bytes.
+Extended report is expected to be compatible with boot protocol.
+
+3. Bitmap 16,32,64bytes
+ keys(bitmap) (16,32)bytes
+Bitmap report can send at most 128keys by 16bytes and 256keys by 32bytes.
+Bitmap report can achieve USB NKRO efficiently in terms of report size.
+Bitmap report needs a deliberation for boot protocol implementation.
+Bitmap report descriptor sample:
+ 0x05, 0x01, // Usage Page (Generic Desktop),
+ 0x09, 0x06, // Usage (Keyboard),
+ 0xA1, 0x01, // Collection (Application),
+ // bitmap of modifiers
+ 0x75, 0x01, // Report Size (1),
+ 0x95, 0x08, // Report Count (8),
+ 0x05, 0x07, // Usage Page (Key Codes),
+ 0x19, 0xE0, // Usage Minimum (224),
+ 0x29, 0xE7, // Usage Maximum (231),
+ 0x15, 0x00, // Logical Minimum (0),
+ 0x25, 0x01, // Logical Maximum (1),
+ 0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte
+ // LED output report
+ 0x95, 0x05, // Report Count (5),
+ 0x75, 0x01, // Report Size (1),
+ 0x05, 0x08, // Usage Page (LEDs),
+ 0x19, 0x01, // Usage Minimum (1),
+ 0x29, 0x05, // Usage Maximum (5),
+ 0x91, 0x02, // Output (Data, Variable, Absolute),
+ 0x95, 0x01, // Report Count (1),
+ 0x75, 0x03, // Report Size (3),
+ 0x91, 0x03, // Output (Constant),
+ // bitmap of keys
+ 0x95, (REPORT_BYTES-1)*8, // Report Count (),
+ 0x75, 0x01, // Report Size (1),
+ 0x15, 0x00, // Logical Minimum (0),
+ 0x25, 0x01, // Logical Maximum(1),
+ 0x05, 0x07, // Usage Page (Key Codes),
+ 0x19, 0x00, // Usage Minimum (0),
+ 0x29, (REPORT_BYTES-1)*8-1, // Usage Maximum (),
+ 0x81, 0x02, // Input (Data, Variable, Absolute),
+ 0xc0 // End Collection
+where REPORT_BYTES is a report size in bytes.
+
+
+Considerations
+--------------
+Compatibility
+ boot protocol
+ minor/old system
+ Some BIOS doesn't send SET_PROTOCOL request, a keyboard can't switch to boot protocol mode.
+ This may cause a problem on a keyboard which uses other report than Standard.
+Reactivity
+ USB polling time
+ OS/Driver processing time
+
+
+Windows Problem
+---------------
+1. Windows accepts only 6keys in case of Standard report.
+ It should be able to send 6keys plus 8modifiers.
+2. Windows accepts only 10keys in case of 16bytes Extended report.
+ It should be able to send 14keys plus 8modifiers.
+3. Windows accepts only 18keys in case of 32bytes Extended report.
+ It should be able to send 30keys plus 8modifiers.
+If keys are pressed in excess of the number, wrong keys are registered on Windows.
+
+This problem will be reportedly fixed soon.(2010/12/05)
+ http://forums.anandtech.com/showpost.php?p=30873364&postcount=17
+
+
+Tools for testing NKRO
+----------------------
+Browser App:
+http://www.microsoft.com/appliedsciences/content/projects/KeyboardGhostingDemo.aspx
+http://random.xem.us/rollover.html
+
+Windows:
+AquaKeyTest.exe http://geekhack.org/showthread.php?t=6643
+
+Linux:
+xkeycaps
+xev
+showkeys
+
+EOF
diff --git a/doc/VAGRANT_GUIDE.md b/doc/VAGRANT_GUIDE.md
new file mode 100644
index 000000000..62044b7f7
--- /dev/null
+++ b/doc/VAGRANT_GUIDE.md
@@ -0,0 +1,26 @@
+# Quick Start Directions
+
+This project includes a Vagrantfile that will allow you to build a new firmware for your keyboard very easily without major changes to your primary operating system. This also ensures that when you clone the project and perform a build, you have the exact same environment as anyone else using the Vagrantfile to build. This makes it much easier for people to help you troubleshoot any issues you encounter.
+
+## Requirements
+
+Using the `/Vagrantfile` in this repository requires you have [Vagrant](http://www.vagrantup.com/) as well as [VirtualBox](https://www.virtualbox.org/) (or [VMware Workstation](https://www.vmware.com/products/workstation) and [Vagrant VMware plugin](http://www.vagrantup.com/vmware) but the (paid) VMware plugin requires a licensed copy of VMware Workstation/Fusion).
+
+*COMPATIBILITY NOTICE* Certain versions of Virtualbox 5 appear to have an incompatibility with the Virtualbox extensions installed in the boxes in this Vagrantfile. If you encounter any issues with the /vagrant mount not succeeding, please upgrade your version of Virtualbox to at least 5.0.12.
+
+Other than having Vagrant and Virtualbox installed and possibly a restart of your computer afterwards, you can simple run a 'vagrant up' anywhere inside the folder where you checked out this project and it will start a Linux virtual machine that contains all the tools required to build this project. There is a post Vagrant startup hint that will get you off on the right foot, otherwise you can also reference the build documentation below.
+
+Build Firmware and Program Controller
+-------------------------------------
+See [/doc/BUIDE_GUIDE.md](/doc/BUILD_GUIDE.md), or the readme in the particular keyboards/* folder.
+
+Change your keymap
+------------------
+See [/doc/keymap.md](/doc/keymap.md).
+
+## Flashing the firmware
+
+The "easy" way to flash the firmware is using a tool from your host OS like the Teensy programming app. [ErgoDox EZ](/keyboards/ergodox_ez/readme.md) gives a great example.
+
+If you want to program via the command line you can uncomment the ['modifyvm'] lines in the Vagrantfile to enable the USB passthrough into Linux and then program using the command line tools like dfu-util/dfu-programmer or you can install the Teensy CLI version.
+ \ No newline at end of file
diff --git a/doc/build_old.md b/doc/build_old.md
new file mode 100644
index 000000000..5c2d57d02
--- /dev/null
+++ b/doc/build_old.md
@@ -0,0 +1,187 @@
+Build Firmware and Program Controller
+=====================================
+
+## This guide may be out-dated - use doc/BUILD_GUIDE.md instead
+
+Download and Install
+--------------------
+### 1. Install Tools
+
+1. **Toolchain** On Windows install [MHV AVR Tools][mhv] for AVR GCC compiler and [Cygwin][cygwin](or [MinGW][mingw]) for shell terminal. On Mac you can use [CrossPack][crosspack]. On Linux you can install AVR GCC (and avr-libc) with your favorite package manager or run the avr_setup.sh script in the root of this repository.
+
+2. **Programmer** On Windows install [Atmel FLIP][flip]. On Mac and Linux install [dfu-programmer][dfu-prog].
+
+3. **Driver** On Windows you start DFU bootloader on the chip first time you will see 'Found New Hardware Wizard' to install driver. If you install device driver properly you can find chip name like 'ATmega32U4' under 'LibUSB-Win32 Devices' tree on 'Device Manager'. If not you shall need to update its driver on 'Device Manager'. You will find the driver in `FLIP` install directory like: C:\Program Files (x86)\Atmel\Flip 3.4.5\usb\. In case of `dfu-programmer` use its driver.
+
+If you use PJRC Teensy you don't need step 2 and 3 above, just get [Teensy loader][teensy-loader].
+
+
+### 2. Download source
+You can find firmware source at github:
+
+- <https://github.com/tmk/tmk_keyboard>
+
+If you are familiar with `Git` tools you are recommended to use it but you can also download zip archive from:
+
+- <https://github.com/tmk/tmk_keyboard/archive/master.zip>
+
+
+Build firmware
+--------------
+### 1. Open terminal
+Open terminal window to get access to commands. Use Cygwin(or MingGW) `shell terminal` in Windows or `Terminal.app` on Mac OSX. In Windows press `Windows` key and `R` then enter `cmd` in 'Run command' dialog showing up.
+
+### 2. Change directory
+Move to project directory in the firmware source.
+
+ cd tmk_keyboard/{'keyboard' or 'converter'}/<project>
+
+### 3. Make
+Build firmware using GNU `make` command. You'll see `<project>_<variant>.hex` file in that directory unless something unexpected occurs in build process.
+
+
+ make -f Makefile.<variant> clean
+ make -f Makefile.<variant>
+
+
+
+
+Program Controller
+------------------
+Now you have **hex** file to program on current directory. This **hex** is only needed to program your controller, other files are used for development and you may leave and forget them.
+
+### 1. Start bootloader
+How to program controller depends on controller chip and its board design. To program AVR USB chips you'll need to start it up in bootloader mode. Most of boards with the chip have a push button to let bootloader come up. Consult with your controller board manual.
+
+### 2. Program with DFU bootloader
+Stock AVR USB chip including ATmega32U4 has DFU bootloader by factory default. `FLIP` is a DFU programmer on Windows offered by Atmel. Open source command line tool `dfu-programmer` also supports AVR chips, it runs on Linux, Mac OSX and even Windows.
+
+To program AVR chip with DFU bootloader use `FLIP` or `dfu-programmer`.
+If you have a proper program command in `Makefile` just type this.
+
+`FLIP` has two version of tool, GUI app and command line program. If you want GUI see tutorial below.
+To use command line tool run this command. Note that you need to set PATH variable properly.
+
+ $ make -f Makefile.<variant> flip
+
+Or to program with `dfu-programmer` run:
+
+ $ make -f Makefile.<variant> dfu
+
+#### FLIP GUI tutorial
+1. On menu bar click Device -> Select, then. `ATmega32u4`.
+2. On menu bar click Settings -> Communication -> USB, then click 'Open' button on 'USB Port Connection' dialog.
+At this point you'll see grey-outed widgets on the app get colored and ready.
+
+3. On menu bar click File -> Load HEX File, then select your firmware hex file on File Selector dialog.
+4. On 'Operations Flow' panel click 'Run' button to load the firmware binary to the chip. Note that you should keep 'Erase', 'Blank Check', 'Program' and 'Verify' check boxes selected.
+5. Re-plug USB cord or click 'Start Application' button to restart your controller.
+Done.
+
+See also these instructions if you need.
+
+- <http://code.google.com/p/micropendous/wiki/LoadingFirmwareWithFLIP>
+- <http://www.atmel.com/Images/doc7769.pdf>
+
+
+### 3. Program with Teensy Loader
+If you have PJRC Teensy see instruction of `Teensy Loader`.
+
+- <http://www.pjrc.com/teensy/loader.html>
+
+Or use this command if you have command line version of Teensy Loader installed.
+
+ $ make -f Makefile.<variant> teensy
+
+
+### 4. Program with Other programmer
+You may want to use other programmer like `avrdude` with AVRISPmkII, Arduino or USBasp. In that case you can still use make target `program` for build with configuring `PROGRAM_CMD` in Makefile.
+
+ $ make -f Makefile.<variant> program
+
+
+[cygwin]: https://www.cygwin.com/
+[mingw]: http://www.mingw.org/
+[mhv]: https://infernoembedded.com/products/avr-tools
+[winavr]: http://winavr.sourceforge.net/
+[crosspack]: http://www.obdev.at/products/crosspack/index.html
+[flip]: http://www.atmel.com/tools/FLIP.aspx
+[dfu-prog]: http://dfu-programmer.sourceforge.net/
+[teensy-loader]:http://www.pjrc.com/teensy/loader.html
+
+
+
+Makefile Options
+----------------
+### 1. MCU and Frequency.
+
+ MCU = atmega32u4 # Teensy 2.0
+ #MCU = at90usb1286 # Teensy++ 2.0
+ F_CPU = 16000000
+
+Set your MCU and its clock in Hz.
+
+ # Boot Section Size in *bytes*
+ # Teensy halfKay 512
+ # Atmel DFU loader 4096
+ # LUFA bootloader 4096
+ OPT_DEFS += -DBOOTLOADER_SIZE=4096
+
+If you are using PJRC Teensy use `512` for `BOOTLOADER_SIZE`, otherwise use `4096` unless you are sure.
+
+### 2. Features
+Optional. Note that ***comment out*** with `#` to disable them.
+
+ BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000)
+ MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+ EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+ CONSOLE_ENABLE = yes # Console for debug(+400)
+ COMMAND_ENABLE = yes # Commands for debug and configuration
+ SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend
+ #NKRO_ENABLE = yes # USB Nkey Rollover - not yet supported in LUFA
+ #BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
+
+### 3. Programmer
+Optional. Set proper command for your controller, bootloader and programmer. This command can be used with `make program`. Not needed if you use `FLIP`, `dfu-programmer` or `Teensy Loader`.
+
+ # avrdude with AVRISPmkII
+ PROGRAM_CMD = avrdude -p $(MCU) -c avrispmkII -P USB -U flash:w:$(TARGET).hex
+
+ # avrdude with USBaspLoader
+ PROGRAM_CMD = avrdude -p $(MCU) -c usbasp -U flash:w:$(TARGET).hex
+
+ # avrdude with arduino
+ PROGRAM_CMD = avrdude -p $(MCU) -c arduino -P COM1 -b 57600 -U flash:w:$(TARGET).hex
+
+
+
+Config.h Options
+----------------
+### 1. Magic command key combination
+
+ #define IS_COMMAND() (keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT)))
+
+### 2. Mechanical Locking Support for CapsLock
+
+ /* Mechanical locking CapsLock support. Use KC_LCAP instead of KC_CAPS in keymap */
+ #define CAPSLOCK_LOCKING_ENABLE
+ /* Locking CapsLock re-synchronize hack */
+ #define CAPSLOCK_LOCKING_RESYNC_ENABLE
+
+### 3. Disable Debug and Print
+
+ /* disable debug print */
+ #define NO_DEBUG
+
+ /* disable print */
+ #define NO_PRINT
+
+### 4. Disable Action Features
+
+ #define NO_ACTION_LAYER
+ #define NO_ACTION_TAPPING
+ #define NO_ACTION_ONESHOT
+ #define NO_ACTION_MACRO
+ #define NO_ACTION_FUNCTION
+
+***TBD***
diff --git a/doc/keycode.txt b/doc/keycode.txt
new file mode 100644
index 000000000..c1134f9bf
--- /dev/null
+++ b/doc/keycode.txt
@@ -0,0 +1,261 @@
+Keycode Symbol Table
+====================
+Keycodes are defined in `common/keycode.h`.
+Range of 00-A4 and E0-E7 are identical with HID Usage:
+<http://www.usb.org/developers/devclass_docs/Hut1_11.pdf>
+Virtual keycodes are defined out of above range to support special actions.
+
+
+Keycode Symbol Short name Description
+--------------------------------------------------------------------------------
+KC_NO 00 Reserved (no event indicated)
+KC_ROLL_OVER 01 Keyboard ErrorRollOver
+KC_POST_FAIL 02 Keyboard POSTFail
+KC_UNDEFINED 03 Keyboard ErrorUndefined
+KC_A 04 Keyboard a and A
+KC_B 05 Keyboard b and B
+KC_C 06 Keyboard c and C
+KC_D 07 Keyboard d and D
+KC_E 08 Keyboard e and E
+KC_F 09 Keyboard f and F
+KC_G 0A Keyboard g and G
+KC_H 0B Keyboard h and H
+KC_I 0C Keyboard i and I
+KC_J 0D Keyboard j and J
+KC_K 0E Keyboard k and K
+KC_L 0F Keyboard l and L
+KC_M 10 Keyboard m and M
+KC_N 11 Keyboard n and N
+KC_O 12 Keyboard o and O
+KC_P 13 Keyboard p and P
+KC_Q 14 Keyboard q and Q
+KC_R 15 Keyboard r and R
+KC_S 16 Keyboard s and S
+KC_T 17 Keyboard t and T
+KC_U 18 Keyboard u and U
+KC_V 19 Keyboard v and V
+KC_W 1A Keyboard w and W
+KC_X 1B Keyboard x and X
+KC_Y 1C Keyboard y and Y
+KC_Z 1D Keyboard z and Z
+KC_1 1E Keyboard 1 and !
+KC_2 1F Keyboard 2 and @
+KC_3 20 Keyboard 3 and #
+KC_4 21 Keyboard 4 and $
+KC_5 22 Keyboard 5 and %
+KC_6 23 Keyboard 6 and ^
+KC_7 24 Keyboard 7 and &
+KC_8 25 Keyboard 8 and *
+KC_9 26 Keyboard 9 and (
+KC_0 27 Keyboard 0 and )
+KC_ENTER KC_ENT 28 Keyboard Return (ENTER)
+KC_ESCAPE KC_ESC 29 Keyboard ESCAPE
+KC_BSPACE KC_BSPC 2A Keyboard DELETE (Backspace)
+KC_TAB 2B Keyboard Tab
+KC_SPACE KC_SPC 2C Keyboard Spacebar
+KC_MINUS KC_MINS 2D Keyboard - and (underscore)
+KC_EQUAL KC_EQL 2E Keyboard = and +
+KC_LBRACKET KC_LBRC 2F Keyboard [ and {
+KC_RBRACKET KC_RBRC 30 Keyboard ] and }
+KC_BSLASH KC_BSLS 31 Keyboard \ and |
+KC_NONUS_HASH KC_NUHS 32 Keyboard Non-US # and ~
+KC_SCOLON KC_SCLN 33 Keyboard ; and :
+KC_QUOTE KC_QUOT 34 Keyboard ‘ and “
+KC_GRAVE KC_GRV 35 Keyboard Grave Accent and Tilde
+KC_COMMA KC_COMM 36 Keyboard , and <
+KC_DOT 37 Keyboard . and >
+KC_SLASH KC_SLSH 38 Keyboard / and ?
+KC_CAPSLOCK KC_CAPS 39 Keyboard Caps Lock
+KC_F1 3A Keyboard F1
+KC_F2 3B Keyboard F2
+KC_F3 3C Keyboard F3
+KC_F4 3D Keyboard F4
+KC_F5 3E Keyboard F5
+KC_F6 3F Keyboard F6
+KC_F7 40 Keyboard F7
+KC_F8 41 Keyboard F8
+KC_F9 42 Keyboard F9
+KC_F10 43 Keyboard F10
+KC_F11 44 Keyboard F11
+KC_F12 45 Keyboard F12
+KC_PSCREEN KC_PSCR 46 Keyboard PrintScreen1
+KC_SCKLOCK KC_SLCK 47 Keyboard Scroll Lock11
+KC_PAUSE KC_PAUS 48 Keyboard Pause1
+KC_INSERT KC_INS 49 Keyboard Insert1
+KC_HOME 4A Keyboard Home1
+KC_PGUP 4B Keyboard PageUp1
+KC_DELETE KC_DELETE 4C Keyboard Delete Forward
+KC_END 4D Keyboard End1
+KC_PGDOWN KC_PGDN 4E Keyboard PageDown1
+KC_RIGHT KC_RGHT 4F Keyboard RightArrow1
+KC_LEFT 50 Keyboard LeftArrow1
+KC_DOWN 51 Keyboard DownArrow1
+KC_UP 52 Keyboard UpArrow1
+KC_NUMLOCK KC_NLCK 53 Keypad Num Lock and Clear11
+KC_KP_SLASH KC_PSLS 54 Keypad /
+KC_KP_ASTERISK KC_PAST 55 Keypad *
+KC_KP_MINUS KC_PMNS 56 Keypad -
+KC_KP_PLUS KC_PPLS 57 Keypad +
+KC_KP_ENTER KC_PENT 58 Keypad ENTER5
+KC_KP_1 KC_P1 59 Keypad 1 and End
+KC_KP_2 KC_P2 5A Keypad 2 and Down Arrow
+KC_KP_3 KC_P3 5B Keypad 3 and PageDn
+KC_KP_4 KC_P4 5C Keypad 4 and Left Arrow
+KC_KP_5 KC_P5 5D Keypad 5
+KC_KP_6 KC_P6 5E Keypad 6 and Right Arrow
+KC_KP_7 KC_P7 5F Keypad 7 and Home
+KC_KP_8 KC_P8 60 Keypad 8 and Up Arrow
+KC_KP_9 KC_P9 61 Keypad 9 and PageUp
+KC_KP_0 KC_P0 62 Keypad 0 and Insert
+KC_KP_DOT KC_PDOT 63 Keypad . and Delete
+KC_NONUS_BSLASH KC_NUBS 64 Keyboard Non-US \ and |
+KC_APPLICATION KC_APP 65 Keyboard Application10
+KC_POWER 66 Keyboard Power9
+KC_KP_EQUAL KC_PEQL 67 Keypad =
+KC_F13 68 Keyboard F13
+KC_F14 69 Keyboard F14
+KC_F15 6A Keyboard F15
+KC_F16 6B Keyboard F16
+KC_F17 6C Keyboard F17
+KC_F18 6D Keyboard F18
+KC_F19 6E Keyboard F19
+KC_F20 6F Keyboard F20
+KC_F21 70 Keyboard F21
+KC_F22 71 Keyboard F22
+KC_F23 72 Keyboard F23
+KC_F24 73 Keyboard F24
+KC_EXECUTE 74 Keyboard Execute
+KC_HELP 75 Keyboard Help
+KC_MENU 76 Keyboard Menu
+KC_SELECT 77 Keyboard Select
+KC_STOP 78 Keyboard Stop
+KC_AGAIN 79 Keyboard Again
+KC_UNDO 7A Keyboard Undo
+KC_CUT 7B Keyboard Cut
+KC_COPY 7C Keyboard Copy
+KC_PASTE 7D Keyboard Paste
+KC_FIND 7E Keyboard Find
+KC__MUTE 7F Keyboard Mute
+KC__VOLUP 80 Keyboard Volume Up
+KC__VOLDOWN 81 Keyboard Volume Down
+KC_LOCKING_CAPS 82 Keyboard Locking Caps Lock12
+KC_LOCKING_NUM 83 Keyboard Locking Num Lock12
+KC_LOCKING_SCROLL 84 Keyboard Locking Scroll Lock12
+KC_KP_COMMA KC_PCMM 85 Keypad Comma27
+KC_KP_EQUAL_AS400 86 Keypad Equal Sign29
+KC_INT1 KC_RO 87 Keyboard International115,28
+KC_INT2 KC_KANA 88 Keyboard International216
+KC_INT3 KC_JYEN 89 Keyboard International317
+KC_INT4 KC_HENK 8A Keyboard International418
+KC_INT5 KC_MHEN 8B Keyboard International519
+KC_INT6 8C Keyboard International620
+KC_INT7 8D Keyboard International721
+KC_INT8 8E Keyboard International822
+KC_INT9 8F Keyboard International922
+KC_LANG1 90 Keyboard LANG125
+KC_LANG2 91 Keyboard LANG226
+KC_LANG3 92 Keyboard LANG330
+KC_LANG4 93 Keyboard LANG431
+KC_LANG5 94 Keyboard LANG532
+KC_LANG6 95 Keyboard LANG68
+KC_LANG7 96 Keyboard LANG78
+KC_LANG8 97 Keyboard LANG88
+KC_LANG9 98 Keyboard LANG98
+KC_ALT_ERASE 99 Keyboard Alternate Erase7
+KC_SYSREQ 9A Keyboard SysReq/Attention1
+KC_CANCEL 9B Keyboard Cancel
+KC_CLEAR 9C Keyboard Clear
+KC_PRIOR 9D Keyboard Prior
+KC_RETURN 9E Keyboard Return
+KC_SEPARATOR 9F Keyboard Separator
+KC_OUT A0 Keyboard Out
+KC_OPER A1 Keyboard Oper
+KC_CLEAR_AGAIN A2 Keyboard Clear/Again
+KC_CRSEL A3 Keyboard CrSel/Props
+KC_EXSEL A4 Keyboard ExSel
+/* Modifiers */
+KC_LCTRL KC_LCTL E0 Keyboard LeftControl
+KC_LSHIFT KC_LSFT E1 Keyboard LeftShift
+KC_LALT E2 Keyboard LeftAlt
+KC_LGUI E3 Keyboard Left GUI(Windows/Apple/Meta key)
+KC_RCTRL KC_RCTL E4 Keyboard RightControl
+KC_RSHIFT KC_RSFT E5 Keyboard RightShift
+KC_RALT E6 Keyboard RightAlt
+KC_RGUI E7 Keyboard Right GUI(Windows/Apple/Meta key)
+
+/*
+ * Virtual keycodes
+ */
+/* System Control */
+KC_SYSTEM_POWER KC_PWR System Power Down
+KC_SYSTEM_SLEEP KC_SLEP System Sleep
+KC_SYSTEM_WAKE KC_WAKE System Wake
+/* Consumer Page */
+KC_AUDIO_MUTE KC_MUTE
+KC_AUDIO_VOL_UP KC_VOLU
+KC_AUDIO_VOL_DOWN KC_VOLD
+KC_MEDIA_NEXT_TRACK KC_MNXT
+KC_MEDIA_PREV_TRACK KC_MPRV
+KC_MEDIA_STOP KC_MSTP
+KC_MEDIA_PLAY_PAUSE KC_MPLY
+KC_MEDIA_SELECT KC_MSEL
+KC_MAIL KC_MAIL
+KC_CALCULATOR KC_CALC
+KC_MY_COMPUTER KC_MYCM
+KC_WWW_SEARCH KC_WSCH
+KC_WWW_HOME KC_WHOM
+KC_WWW_BACK KC_WBAK
+KC_WWW_FORWARD KC_WFWD
+KC_WWW_STOP KC_WSTP
+KC_WWW_REFRESH KC_WREF
+KC_WWW_FAVORITES KC_WFAV
+/* Mousekey */
+KC_MS_UP KC_MS_U Mouse Cursor Up
+KC_MS_DOWN KC_MS_D Mouse Cursor Down
+KC_MS_LEFT KC_MS_L Mouse Cursor Left
+KC_MS_RIGHT KC_MS_R Mouse Cursor Right
+KC_MS_BTN1 KC_BTN1 Mouse Button 1
+KC_MS_BTN2 KC_BTN2 Mouse Button 2
+KC_MS_BTN3 KC_BTN3 Mouse Button 3
+KC_MS_BTN4 KC_BTN4 Mouse Button 4
+KC_MS_BTN5 KC_BTN5 Mouse Button 5
+KC_MS_WH_UP KC_WH_U Mouse Wheel Up
+KC_MS_WH_DOWN KC_WH_D Mouse Wheel Down
+KC_MS_WH_LEFT KC_WH_L Mouse Wheel Left
+KC_MS_WH_RIGHT KC_WH_R Mouse Wheel Right
+KC_MS_ACCEL0 KC_ACL0 Mouse Acceleration 0
+KC_MS_ACCEL1 KC_ACL1 Mouse Acceleration 1
+KC_MS_ACCEL2 KC_ACL2 Mouse Acceleration 2
+/* Fn key */
+KC_FN0
+KC_FN1
+KC_FN2
+KC_FN3
+KC_FN4
+KC_FN5
+KC_FN6
+KC_FN7
+KC_FN8
+KC_FN9
+KC_FN10
+KC_FN11
+KC_FN12
+KC_FN13
+KC_FN14
+KC_FN15
+KC_FN16
+KC_FN17
+KC_FN18
+KC_FN19
+KC_FN20
+KC_FN21
+KC_FN22
+KC_FN23
+KC_FN24
+KC_FN25
+KC_FN26
+KC_FN27
+KC_FN28
+KC_FN29
+KC_FN30
+KC_FN31
diff --git a/doc/keymap.md b/doc/keymap.md
new file mode 100644
index 000000000..d1985e567
--- /dev/null
+++ b/doc/keymap.md
@@ -0,0 +1,599 @@
+Keymap framework - how to define your keymap
+============================================
+***NOTE: This is not final version, may be inconsistent with source code and changed occasionally for a while.***
+
+## 0. Keymap and layers
+**Keymap** is comprised of multiple layers of key layout, you can define **32 layers** at most.
+**Layer** is an array of **keycodes** to define **actions** for each physical keys.
+respective layers can be validated simultaneously. Layers are indexed with 0 to 31 and higher layer has precedence.
+
+ Keymap: 32 Layers Layer: Keycode matrix
+ ----------------- ---------------------
+ stack of layers array_of_keycode[row][column]
+ ____________ precedence _______________________
+ / / | high / ESC / F1 / F2 / F3 ....
+ 31 /___________// | /-----/-----/-----/-----
+ 30 /___________// | / TAB / Q / W / E ....
+ 29 /___________/ | /-----/-----/-----/-----
+ : _:_:_:_:_:__ | : /LCtrl/ A / S / D ....
+ : / : : : : : / | : / : : : :
+ 2 /___________// | 2 `--------------------------
+ 1 /___________// | 1 `--------------------------
+ 0 /___________/ V low 0 `--------------------------
+
+
+
+### 0.1 Keymap status
+Keymap has its state in two parameters:
+**`default_layer`** indicates a base keymap layer(0-31) which is always valid and to be referred, **`keymap_stat`** is 16bit variable which has current on/off status of layers on its each bit.
+
+Keymap layer '0' is usually `default_layer` and which is the only valid layer and other layers is initially off after boot up firmware, though, you can configured them in `config.h`.
+To change `default_layer` will be useful when you switch key layout completely, say you want Colmak instead of Qwerty.
+
+ Initial state of Keymap Change base layout
+ ----------------------- ------------------
+
+ 31 31
+ 30 30
+ 29 29
+ : :
+ : : ____________
+ 2 ____________ 2 / /
+ 1 / / ,->1 /___________/
+ ,->0 /___________/ | 0
+ | |
+ `--- default_layer = 0 `--- default_layer = 1
+ layer_state = 0x00000001 layer_state = 0x00000002
+
+On the other hand, you shall change `layer_state` to overlay base layer with some layers for feature such as navigation keys, function key(F1-F12), media keys or special actions.
+
+ Overlay feature layer
+ --------------------- bit|status
+ ____________ ---+------
+ 31 / / 31 | 0
+ 30 /___________// -----> 30 | 1
+ 29 /___________/ -----> 29 | 1
+ : : | :
+ : ____________ : | :
+ 2 / / 2 | 0
+ ,->1 /___________/ -----> 1 | 1
+ | 0 0 | 0
+ | +
+ `--- default_layer = 1 |
+ layer_state = 0x60000002 <-'
+
+
+
+### 0.2 Layer Precedence and Transparency
+Note that ***higher layer has higher priority on stack of layers***, namely firmware falls down from top layer to bottom to look up keycode. Once it spots keycode other than **`KC_TRNS`**(transparent) on a layer it stops searching and lower layers aren't referred.
+
+You can place `KC_TRNS` on overlay layer changes just part of layout to fall back on lower or base layer.
+Key with `KC_TRANS` doesn't has its own keycode and refers to lower valid layers for keycode, instead.
+See example below.
+
+
+### 0.3 Keymap Example
+Keymap is **`keymaps[]`** C array in fact and you can define layers in it with **`KEYMAP()`** C macro and keycodes. To use complex actions you need to define `Fn` keycode in **`fn_actions[]`** array.
+
+This is a keymap example for [HHKB](http://en.wikipedia.org/wiki/Happy_Hacking_Keyboard) keyboard.
+This example has three layers, 'Qwerty' as base layer, 'Cursor' and 'Mousekey'.
+In this example,
+
+ `Fn0` is a **momentary layer switching** key, you can use keys on Cursor layer while holding the key.
+
+ `Fn1` is a momentary layer switching key with tapping feature, you can get semicolon **';'** with taping the key and switch layers while holding the key. The word **'tap'** or **'tapping'** mean to press and release a key quickly.
+
+ `Fn2` is a **toggle layer switch** key, you can stay switched layer after releasing the key unlike momentary switching.
+
+You can find other keymap definitions in file `keymap.c` located on project directories.
+
+ static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ /* 0: Qwerty
+ * ,-----------------------------------------------------------.
+ * |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| \| `|
+ * |-----------------------------------------------------------|
+ * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]|Backs|
+ * |-----------------------------------------------------------|
+ * |Contro| A| S| D| F| G| H| J| K| L|Fn1| '|Enter |
+ * |-----------------------------------------------------------|
+ * |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift |Fn0|
+ * `-----------------------------------------------------------'
+ * |Gui|Alt |Space |Alt |Fn2|
+ * `-------------------------------------------'
+ */
+ KEYMAP(ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSLS,GRV, \
+ TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSPC, \
+ LCTL,A, S, D, F, G, H, J, K, L, FN1, QUOT,ENT, \
+ LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH,RSFT,FN0, \
+ LGUI,LALT, SPC, RALT,FN2),
+ /* 1: Cursor(HHKB mode)
+ * ,-----------------------------------------------------------.
+ * |Pwr| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
+ * |-----------------------------------------------------------|
+ * |Caps | | | | | | | |Psc|Slk|Pus|Up | |Backs|
+ * |-----------------------------------------------------------|
+ * |Contro|VoD|VoU|Mut| | | *| /|Hom|PgU|Lef|Rig|Enter |
+ * |-----------------------------------------------------------|
+ * |Shift | | | | | | +| -|End|PgD|Dow|Shift | |
+ * `-----------------------------------------------------------'
+ * |Gui |Alt |Space |Alt |Gui|
+ * `--------------------------------------------'
+ */
+ KEYMAP(PWR, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
+ CAPS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PSCR,SLCK,PAUS,UP, TRNS,BSPC, \
+ LCTL,VOLD,VOLU,MUTE,TRNS,TRNS,PAST,PSLS,HOME,PGUP,LEFT,RGHT,ENT, \
+ LSFT,TRNS,TRNS,TRNS,TRNS,TRNS,PPLS,PMNS,END, PGDN,DOWN,RSFT,TRNS, \
+ LGUI,LALT, SPC, RALT,RGUI),
+ /* 2: Mousekey
+ * ,-----------------------------------------------------------.
+ * |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
+ * |-----------------------------------------------------------|
+ * |Tab | | | | | |MwL|MwD|MwU|MwR| | | |Backs|
+ * |-----------------------------------------------------------|
+ * |Contro| | | | | |McL|McD|McU|McR| | |Return |
+ * |-----------------------------------------------------------|
+ * |Shift | | | | |Mb3|Mb2|Mb1|Mb4|Mb5| |Shift | |
+ * `-----------------------------------------------------------'
+ * |Gui |Alt |Mb1 |Alt | |
+ * `--------------------------------------------'
+ * Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel
+ */
+ KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
+ TAB, TRNS,TRNS,TRNS,TRNS,TRNS,WH_L,WH_D,WH_U,WH_R,TRNS,TRNS,TRNS,BSPC, \
+ LCTL,TRNS,ACL0,ACL1,ACL2,TRNS,MS_L,MS_D,MS_U,MS_R,TRNS,QUOT,ENT, \
+ LSFT,TRNS,TRNS,TRNS,TRNS,BTN3,BTN2,BTN1,BTN4,BTN5,SLSH,RSFT,TRNS, \
+ LGUI,LALT, BTN1, RALT,TRNS),
+ };
+
+ static const uint16_t PROGMEM fn_actions[] = {
+ ACTION_LAYER_MOMENTARY(1), // FN0
+ ACTION_LAYER_TAP_KEY(2, KC_SCLN), // FN1
+ ACTION_LAYER_TOGGLE(2), // FN2
+ };
+
+
+
+
+## 1. Keycode
+See [`common/keycode.h`](../common/keycode.h) or keycode table below for the detail. Keycode is internal **8bit code** to indicate action performed on key in keymap. Keycode has `KC_` prefixed symbol respectively. Most of keycodes like `KC_A` have simple action registers key to host on press and unregister on release, while some of other keycodes has some special actions like `Fn` keys, Media control keys, System control keys and Mousekeys.
+
+ ***In `KEYMAP()` macro you should omit prefix part `KC_` of keycode to keep keymap compact.*** For example, just use `A` instead you place `KC_A` in `KEYMAP()`. Some keycodes has 4-letter **short name** in addition to descriptive name, you'll prefer short one in `KEYMAP()`.
+
+### 1.0 Other key
+- `KC_NO` for no action
+- `KC_TRNS` for layer transparency (See above)
+
+### 1.1 Normal key
+- `KC_A` to `KC_Z`, `KC_1` to `KC_0` for alpha numeric key
+- `KC_MINS`, `KC_EQL`, `KC_GRV`, `KC_RBRC`, `KC_LBRC`, `KC_COMM`, `KC_DOT`, `KC_BSLS`, `KC_SLSH`, `KC_SCLN`, `KC_QUOT`
+- `KC_ESC`, `KC_TAB`, `KC_SPC`, `KC_BSPC`, `KC_ENT`, `KC_DEL`, `KC_INS`
+- `KC_UP`, `KC_DOWN`, `KC_RGHT`, `KC_LEFT`, `KC_PGUP`, `KC_PGDN`, `KC_HOME`, `KC_END`
+- `KC_CAPS`, `KC_NLCK`, `KC_SLCK`, `KC_PSCR`, `KC_PAUS`, `KC_APP`, `KC_F1` to `KC_F24`
+- `KC_P1` to `KC_P0`, `KC_PDOT`, `KC_PCMM`, `KC_PSLS`, `KC_PAST`, `KC_PMNS`, `KC_PPLS`, `KC_PEQL`, `KC_PENT` for keypad.
+
+### 1.2 Modifier
+There are 8 modifiers which has discrimination between left and right.
+
+- `KC_LCTL` and `KC_RCTL` for Control
+- `KC_LSFT` and `KC_RSFT` for Shift
+- `KC_LALT` and `KC_RALT` for Alt
+- `KC_LGUI` and `KC_RGUI` for Windows key or Command key in Mac
+
+### 1.3 Mousekey
+- `KC_MS_U`, `KC_MS_D`, `KC_MS_L`, `KC_MS_R` for mouse cursor
+- `KC_WH_U`, `KC_WH_D`, `KC_WH_L`, `KC_WH_R` for mouse wheel
+- `KC_BTN1`, `KC_BTN2`, `KC_BTN3`, `KC_BTN4`, `KC_BTN5` for mouse buttons
+
+### 1.4 System & Media key
+- `KC_PWR`, `KC_SLEP`, `KC_WAKE` for Power, Sleep, Wake
+- `KC_MUTE`, `KC_VOLU`, `KC_VOLD` for audio volume control
+- `KC_MNXT`, `KC_MPRV`, `KC_MSTP`, `KC_MPLY`, `KC_MSEL` for media control
+- `KC_MAIL`, `KC_CALC`, `KC_MYCM` for application launch
+- `KC_WSCH`, `KC_WHOM`, `KC_WBAK`, `KC_WFWD`, `KC_WSTP`, `KC_WREF`, `KC_WFAV` for web browser operation
+
+### 1.5 Fn key
+`KC_FNnn` are keycodes for `Fn` key which not given any actions at the beginning unlike most of keycodes has its own inborn action. To use these keycodes in `KEYMAP()` you need to assign action you want at first. Action of `Fn` key is defined in `fn_actions[]` and its index of the array is identical with number part of `KC_FNnn`. Thus `KC_FN0` keycode indicates the action defined in first element of the array. ***32 `Fn` keys can be defined at most.***
+
+### 1.6 Keycode Table
+ See keycode table in [`doc/keycode.txt`](./keycode.txt) for description of keycodes.
+
+ In regard to implementation side most of keycodes are identical with [HID usage][HID_usage](pdf) sent to host for real and some virtual keycodes are defined to support special actions.
+[HID_usage]: http://www.usb.org/developers/hidpage/Hut1_12v2.pdf
+
+
+
+## 2. Action
+See [`common/action_code.h`](../common/action_code.h). Action is a **16bit code** and defines function to perform on events of a key like press, release, holding and tapping.
+
+Most of keys just register 8bit scancode to host, but to support other complex features needs 16bit extended action codes internally. However, using 16bit action codes in keymap results in double size in memory compared to using just keycodes. To avoid this waste 8bit keycodes are used in `KEYMAP()` instead of action codes.
+
+***You can just use keycodes of `Normal key`, `Modifier`, `Mousekey` and `System & Media key` in keymap*** to indicate corresponding actions instead of using action codes. While ***to use other special actions you should use keycode of `Fn` key defined in `fn_actions[]`.***
+
+
+### 2.1 Key Action
+This is a simple action that registers scancodes(HID usage in fact) to host on press event of key and unregister on release.
+
+#### Parameters
++ **mods**: { ` MOD_LCTL`, ` MOD_LSFT`, ` MOD_LALT`, ` MOD_LGUI`,
+ ` MOD_RCTL`, ` MOD_RSFT`, ` MOD_RALT`, ` MOD_RGUI` }
++ **key**: keycode
+
+
+#### 2.1.1 Normal key and Modifier
+***This action usually won't be used expressly in keymap*** because you can just use keycodes in `KEYMAP()` instead.
+
+You can define these actions on *'A'* key and *'left shift'* modifier with:
+
+ ACTION_KEY(KC_A)
+ ACTION_KEY(KC_LSFT)
+
+#### 2.1.2 Modified key
+This action is comprised of strokes of modifiers and a key. `Macro` action is needed if you want more complex key strokes.
+
+Say you want to assign a key to `Shift + 1` to get character *'!'* or `Alt + Tab` to switch application windows.
+
+ ACTION_MODS_KEY(MOD_LSFT, KC_1)
+ ACTION_MODS_KEY(MOD_LALT, KC_TAB)
+
+Or `Alt,Shift + Tab` can be defined. `ACTION_MODS_KEY(mods, key)` requires **4-bit modifier state** and a **keycode** as arguments. See `keycode.h` for `MOD_BIT()` macro.
+
+ ACTION_MODS_KEY(MOD_LALT | MOD_LSFT, KC_TAB)
+
+#### 2.1.3 Multiple Modifiers
+Registers multiple modifiers with pressing a key. To specify multiple modifiers use `|`.
+
+ ACTION_MODS(MOD_ALT | MOD_LSFT)
+
+#### 2.1.3 Modifier with Tap key([Dual role][dual_role])
+Works as a modifier key while holding, but registers a key on tap(press and release quickly).
+
+
+ ACTION_MODS_TAP_KEY(MOD_RCTL, KC_ENT)
+
+
+
+### 2.2 Layer Action
+These actions operate layers of keymap.
+
+#### Parameters
+You can specify a **target layer** of action and **when the action is executed**. Some actions take a **bit value** for bitwise operation.
+
+
++ **layer**: `0`-`31`
++ **on**: { `ON_PRESS` | `ON_RELEASE` | `ON_BOTH` }
++ **bits**: 4-bit value and 1-bit mask bit
+
+
+#### 2.2.1 Default Layer
+Default Layer is a layer which always is valid and referred to when actions is not defined on other overlay layers.
+
+This sets Default Layer to given parameter `layer` and activate it.
+
+ ACTION_DEFAULT_LAYER_SET(layer)
+
+
+#### 2.2.2 Momentary
+Turns on `layer` momentarily while holding, in other words it activates when key is pressed and deactivate when released.
+
+ ACTION_LAYER_MOMENTARY(layer)
+
+
+#### 2.2.3 Toggle Switch
+Turns on `layer` with first type(press and release) and turns off with next.
+
+ ACTION_LAYER_TOGGLE(layer)
+
+
+#### 2.2.4 Momentary Switch with tap key
+Turns on `layer` momentary while holding, but registers key on tap(press and release quickly).
+
+ ACTION_LAYER_TAP_KEY(layer, key)
+
+
+#### 2.2.5 Momentary Switch with tap toggle
+Turns on `layer` momentary while holding and toggles it with serial taps.
+
+ ACTION_LAYER_TAP_TOGGLE(layer)
+
+
+#### 2.2.6 Invert state of layer
+Inverts current state of `layer`. If the layer is on it becomes off with this action.
+
+ ACTION_LAYER_INVERT(layer, on)
+
+
+#### 2.2.7 Turn On layer
+Turns on layer state.
+
+ ACTION_LAYER_ON(layer, on)
+
+Turns on layer state on press and turns off on release.
+
+ ACTION_LAYER_ON_OFF(layer)
+
+
+#### 2.2.8 Turn Off layer
+Turns off layer state.
+
+ ACTION_LAYER_OFF(layer, on)
+
+Turns off layer state on press and activates on release.
+
+ ACTION_LAYER_OFF_ON(layer)
+
+
+#### 2.2.9 Set layer
+Turn on layer only.
+`layer_state = (1<<layer) [layer: 0-31]`
+
+ ACTION_LAYER_SET(layer, on)
+
+Turns on layer only and clear all layer on release..
+
+ ACTION_LAYER_SET_CLEAR(layer)
+
+
+#### 2.2.10 Bitwise operation
+
+**part** indicates which part of 32bit layer state(0-7). **bits** is 5-bit value. **on** indicates when the action is executed.
+
+ ACTION_LAYER_BIT_AND(part, bits, on)
+ ACTION_LAYER_BIT_OR(part, bits, on)
+ ACTION_LAYER_BIT_XOR(part, bits, on)
+ ACTION_LAYER_BIT_SET(part, bits, on)
+
+These actions works with parameters as following code.
+
+ uint8_t shift = part*4;
+ uint32_t mask = (bits&0x10) ? ~(0xf<<shift) : 0;
+ uint32_t layer_state = layer_state <bitop> ((bits<<shift)|mask);
+
+
+Default Layer also has bitwise operations, they are executed when key is released.
+
+ ACTION_DEFAULT_LAYER_BIT_AND(part, bits)
+ ACTION_DEFAULT_LAYER_BIT_OR(part, bits)
+ ACTION_DEFAULT_LAYER_BIT_XOR(part, bits)
+ ACTION_DEFAULT_LAYER_BIT_SET(part, bits)
+
+
+
+### 2.3 Macro action
+***TBD***
+
+`Macro` action indicates complex key strokes.
+
+ MACRO( D(LSHIFT), D(D), END )
+ MACRO( U(D), U(LSHIFT), END )
+ MACRO( I(255), T(H), T(E), T(L), T(L), W(255), T(O), END )
+
+#### 2.3.1 Macro Commands
+- **I()** change interval of stroke.
+- **D()** press key
+- **U()** release key
+- **T()** type key(press and release)
+- **W()** wait
+- **END** end mark
+
+#### 2.3.2 Examples
+
+***TODO: sample implementation***
+See `keyboards/hhkb/keymap.c` for sample.
+
+
+
+### 2.4 Function action
+***TBD***
+
+There are two type of action, normal `Function` and tappable `Function`.
+These actions call user defined function with `id`, `opt`, and key event information as arguments.
+
+#### 2.4.1 Function
+To define normal `Function` action in keymap use this.
+
+ ACTION_FUNCTION(id, opt)
+
+#### 2.4.2 Function with tap
+To define tappable `Function` action in keymap use this.
+
+ ACTION_FUNCTION_TAP(id, opt)
+
+#### 2.4.3 Implement user function
+`Function` actions can be defined freely with C by user in callback function:
+
+ void keymap_call_function(keyrecord_t *event, uint8_t id, uint8_t opt)
+
+This C function is called every time key is operated, argument `id` selects action to be performed and `opt` can be used for option. Function `id` can be 0-255 and `opt` can be 0-15.
+
+ `keyrecord_t` is comprised of key event and tap count. `keyevent_t` indicates which and when key is pressed or released. From `tap_count` you can know tap state, 0 means no tap. These information will be used in user function to decide how action of key is performed.
+
+ typedef struct {
+ keyevent_t event;
+ uint8_t tap_count;
+ } keyrecord_t;
+
+ typedef struct {
+ key_t key;
+ bool pressed;
+ uint16_t time;
+ } keyevent_t;
+
+ typedef struct {
+ uint8_t col;
+ uint8_t row;
+ } key_t;
+
+***TODO: sample implementation***
+See `keyboards/hhkb/keymap.c` for sample.
+
+
+
+### 2.5 Backlight Action
+These actions control the backlight.
+
+#### 2.5.1 Change backlight level
+Increase backlight level.
+
+ ACTION_BACKLIGHT_INCREASE()
+
+Decrease backlight level.
+
+ ACTION_BACKLIGHT_DECREASE()
+
+Step through backlight levels.
+
+ ACTION_BACKLIGHT_STEP()
+
+Turn a specific backlight level on or off.
+
+ ACTION_BACKLIGHT_LEVEL(1)
+
+#### 2.5.2 Turn on / off backlight
+Turn the backlight on and off without changing level.
+
+ ACTION_BACKLIGHT_TOGGLE()
+
+
+
+## 3. Layer switching Example
+There are some ways to switch layer with 'Layer' actions.
+
+### 3.1 Momentary switching
+Momentary switching changes layer only while holding Fn key.
+
+This action makes 'Layer 1' active(valid) on key press event and inactive on release event. Namely you can overlay a layer on lower layers or default layer temporarily with this action.
+
+ ACTION_LAYER_MOMENTARY(1)
+
+
+Note that after switching on press the actions on destination layer(Layer 1) are performed.
+***Thus you shall need to place an action to go back on destination layer***, or you will be stuck in destination layer without way to get back. Usually you need to place same action or 'KC_TRNS` on destination layer to get back.
+
+
+### 3.2 Toggle switching
+Toggle switching performed after releasing a key. With this action you can keep staying on the destination layer until you type the key again to return.
+
+This performs toggle switching action of 'Layer 2'.
+
+ ACTION_LAYER_TOGGLE(2)
+
+
+
+### 3.3 Momentary switching with Tap key
+These actions switch a layer only while holding a key but register the key on tap. **Tap** means to press and release a key quickly.
+
+ ACTION_LAYER_TAP_KEY(2, KC_SCLN)
+
+With this you can place a layer switching action on normal key like ';' without losing its original key register function. This action allows you to have layer switching action without necessity of a dedicated key. It means you can have it even on home row of keyboard.
+
+
+
+### 3.4 Momentary switching with Tap Toggle
+This switches layer only while holding a key but toggle layer with several taps. **Tap** means to press and release key quickly.
+
+ ACTION_LAYER_TAP_TOGGLE(1)
+
+Number of taps can be configured with `TAPPING_TOGGLE` in `config.h`, `5` by default.
+
+
+
+### 3.5 Momentary switching with Modifiers
+This registers modifier key(s) simultaneously with layer switching.
+
+ ACTION_LAYER_MODS(2, MOD_LSFT | MOD_LALT)
+
+
+
+## 4. Tapping
+Tapping is to press and release a key quickly. Tapping speed is determined with setting of `TAPPING_TERM`, which can be defined in `config.h`, 200ms by default.
+
+### 4.1 Tap Key
+This is a feature to assign normal key action and modifier including layer switching to just same one physical key. This is a kind of [Dual role key][dual_role]. It works as modifier when holding the key but registers normal key when tapping.
+
+Modifier with tap key:
+
+ ACTION_MODS_TAP_KEY(MOD_RSFT, KC_GRV)
+
+Layer switching with tap key:
+
+ ACTION_LAYER_TAP_KEY(2, KC_SCLN)
+
+[dual_role]: http://en.wikipedia.org/wiki/Modifier_key#Dual-role_keys
+
+
+### 4.2 Tap Toggle
+This is a feature to assign both toggle layer and momentary switch layer action to just same one physical key. It works as momentary layer switch when holding a key but toggle switch with several taps.
+
+ ACTION_LAYER_TAP_TOGGLE(1)
+
+
+### 4.3 Oneshot Modifier
+This runs onetime effects which modify only on just one following key. It works as normal modifier key when holding down while oneshot modifier when tapping. The behavior of oneshot modifiers is similar to the [sticky keys](https://en.wikipedia.org/wiki/StickyKeys) functionality found in most operating systems.
+
+ ACTION_MODS_ONESHOT(MOD_LSFT)
+
+Oneshot layer key:
+
+ ACTION_LAYER_ONESHOT(MY_LAYER)
+
+Say you want to type 'The', you have to push and hold Shift key before type 't' then release it before type 'h' and 'e', otherwise you'll get 'THe' or 'the' unintentionally. With Oneshot Modifier you can tap Shift then type 't', 'h' and 'e' normally, you don't need to holding Shift key properly here. This mean you can release Shift before 't' is pressed down.
+
+Oneshot effect is cancel unless following key is pressed down within `ONESHOT_TIMEOUT` of `config.h`. No timeout when it is `0` or not defined.
+
+Most implementations of sticky keys allow you to lock a modifier by double tapping the modifier. The layer then remains locked untill the modifier is tapped again. To enable this behaviour for oneshot modifiers set `ONESHOT_TAP_TOGGLE` to the number taps required. The feature is disabled if `ONESHOT_TAP_TOGGLE<2` or not defined.
+
+
+### 4.4 Tap Toggle Mods
+Similar to layer tap toggle, this works as a momentary modifier when holding, but toggles on with several taps. A single tap will 'unstick' the modifier again.
+
+ ACTION_MODS_TAP_TOGGLE(MOD_LSFT)
+
+
+
+
+## 5. Legacy Keymap
+This was used in prior version and still works due to legacy support code in `common/keymap.c`. Legacy keymap doesn't support many of features that new keymap offers. ***It is not recommended to use Legacy Keymap for new project.***
+
+To enable Legacy Keymap support define this macro in `config.h`.
+
+ #define USE_LEGACY_KEYMAP
+
+Legacy Keymap uses two arrays `fn_layer[]` and `fn_keycode[]` to define Fn key. The index of arrays corresponds with postfix number of `Fn` key. Array `fn_layer[]` indicates destination layer to switch and `fn_keycode[]` has keycodes to send when tapping `Fn` key.
+
+In following setting example, `Fn0`, `Fn1` and `Fn2` switch layer to 1, 2 and 2 respectively. `Fn2` registers `Space` key when tapping while `Fn0` and `Fn1` doesn't send any key.
+
+ static const uint8_t PROGMEM fn_layer[] = {
+ 1, // Fn0
+ 2, // Fn1
+ 2, // Fn2
+ };
+
+ static const uint8_t PROGMEM fn_keycode[] = {
+ KC_NO, // Fn0
+ KC_NO, // Fn1
+ KC_SPC, // Fn2
+ };
+
+
+## 6. Terminology
+***TBD***
+### keymap
+is comprised of multiple layers.
+### layer
+is matrix of keycodes.
+### key
+is physical button on keyboard or logical switch on software.
+### keycode
+is codes used on firmware.
+### action
+is a function assigned on a key.
+### layer transparency
+Using transparent keycode one layer can refer key definition on other lower layer.
+### layer precedence
+Top layer has higher precedence than lower layers.
+### tapping
+is to press and release a key quickly.
+### Fn key
+is key which executes a special action like layer switching, mouse key, macro or etc.
+### dual role key
+<http://en.wikipedia.org/wiki/Modifier_key#Dual-role_keys>
diff --git a/doc/keymap_config_h_example.h b/doc/keymap_config_h_example.h
new file mode 100644
index 000000000..8893d122e
--- /dev/null
+++ b/doc/keymap_config_h_example.h
@@ -0,0 +1,8 @@
+#ifndef CONFIG_USER_H
+#define CONFIG_USER_H
+
+#include "../../config.h"
+
+// place overrides here
+
+#endif
diff --git a/doc/keymap_makefile_example.mk b/doc/keymap_makefile_example.mk
new file mode 100644
index 000000000..f4671a9d1
--- /dev/null
+++ b/doc/keymap_makefile_example.mk
@@ -0,0 +1,21 @@
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = no # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/doc/other_projects.md b/doc/other_projects.md
new file mode 100644
index 000000000..bf980b0a9
--- /dev/null
+++ b/doc/other_projects.md
@@ -0,0 +1,62 @@
+Other Keyboard Firmware Projects
+================================
+## PJRC USB Keyboard/Mouse Example[USB][PJRC][Teensy][AVR]
+- <http://www.pjrc.com/teensy/usb_keyboard.html>
+- <http://www.pjrc.com/teensy/usb_mouse.html>
+
+## kbupgrade[USB][V-USB][AVR]
+- <http://github.com/rhomann/kbupgrade>
+- <http://geekhack.org/showwiki.php?title=Island:8406>
+
+## c64key[USB][V-USB][AVR]
+- <http://symlink.dk/projects/c64key/>
+
+## rump[USB][V-USB][AVR]
+- <http://mg8.org/rump/>
+- <http://github.com/clee/rump>
+
+## dulcimer[USB][V-USB][AVR]
+- <http://www.schatenseite.de/dulcimer.html>
+
+## humblehacker-keyboard[USB][LUFA][AVR][Ergo]
+- <http://github.com/humblehacker>
+- <http://www.humblehacker.com/keyboard/>
+- <http://geekhack.org/showwiki.php?title=Island:6292>
+
+## ps2avr[PS/2][AVR]
+- <http://sourceforge.net/projects/ps2avr/>
+
+## ErgoDox[Ergo][Split][USB][AVR]
+- <http://geekhack.org/index.php?topic=22780.0>
+- <https://github.com/benblazak/ergodox-firmware>
+- <https://github.com/cub-uanic/tmk_keyboard>
+
+## Suka's keyboard collection[Ergo][Split][3DPrinting][USB][AVR]
+- <http://deskthority.net/workshop-f7/my-diy-keyboard-collection-or-how-i-became-a-kb-geek-t2534.html>
+- <https://github.com/frobiac/adnw>
+
+## bpiphany's AVR-Keyboard[PJRC][AVR][USB]
+- <https://github.com/BathroomEpiphanies/AVR-Keyboard>
+- <http://deskthority.net/wiki/HID_Liberation_Device_-_DIY_Instructions>
+- <http://deskthority.net/wiki/Phantom>
+
+## USB-USB keyboard remapper[converter][USB-USB][AVR][Arduino]
+- <http://forum.colemak.com/viewtopic.php?pid=10837>
+- <https://github.com/darkytoothpaste/keymapper>
+
+## USB-USB converter threads[converter][USB-USB]
+- <http://deskthority.net/workshop-f7/is-remapping-a-usb-keyboard-using-teensy-possible-t2841-30.html>
+- <http://geekhack.org/index.php?topic=19458.0>
+
+## kbdbabel.org[converter][vintage][protocol][8051]
+Great resource of vintage keyboard protocol information and code
+
+- <http://www.kbdbabel.org/>
+
+## Haata's kiibohd Controller[converter][vintage][protocol][AVR][PJRC][Cortex]
+A lots of vintage keyboard protocol supports
+
+- <http://gitorious.org/kiibohd-controller>
+
+## Kinesis ergonomic keyboard firmware replacement[V-USB][LUFA][Ergo]
+- <https://github.com/chrisandreae/kinesis-firmware>
diff --git a/keyboards/alps64/Makefile b/keyboards/alps64/Makefile
new file mode 100644
index 000000000..d8325e6c8
--- /dev/null
+++ b/keyboards/alps64/Makefile
@@ -0,0 +1,70 @@
+
+
+# Target file name (without extension).
+
+# project specific files
+SRC = led.c
+
+# MCU name
+MCU = atmega32u2
+
+# Processor frequency.
+# This will define a symbol, F_CPU, in all source code files equal to the
+# processor frequency in Hz. You can then use this symbol in your source code to
+# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
+# automatically to create a 32-bit value in your source code.
+#
+# This will be an integer division of F_USB below, as it is sourced by
+# F_USB after it has run through any CPU prescalers. Note that this value
+# does not *change* the processor frequency - it should merely be updated to
+# reflect the processor speed set externally so that the code can use accurate
+# software delays.
+F_CPU = 16000000
+
+
+#
+# LUFA specific
+#
+# Target architecture (see library "Board Types" documentation).
+ARCH = AVR8
+
+# Input clock frequency.
+# This will define a symbol, F_USB, in all source code files equal to the
+# input clock frequency (before any prescaling is performed) in Hz. This value may
+# differ from F_CPU if prescaling is used on the latter, and is required as the
+# raw input clock is fed directly to the PLL sections of the AVR for high speed
+# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
+# at the end, this will be done automatically to create a 32-bit value in your
+# source code.
+#
+# If no clock division is performed on the input clock inside the AVR (via the
+# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
+F_USB = $(F_CPU)
+
+# Interrupt driven control endpoint task(+60)
+OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
+
+
+# Boot Section Size in *bytes*
+# Teensy halfKay 512
+# Teensy++ halfKay 1024
+# Atmel DFU loader 4096
+# LUFA bootloader 4096
+# USBaspLoader 2048
+OPT_DEFS += -DBOOTLOADER_SIZE=4096
+
+
+# Build Options
+# comment out to disable the options.
+#
+BOOTMAGIC_ENABLE ?= yes # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE ?= yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450)
+CONSOLE_ENABLE ?= yes # Console for debug(+400)
+COMMAND_ENABLE ?= yes # Commands for debug and configuration
+#SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend
+#NKRO_ENABLE = yes # USB Nkey Rollover - not yet supported in LUFA
+
+ifndef QUANTUM_DIR
+ include ../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/alps64/alps64.c b/keyboards/alps64/alps64.c
new file mode 100644
index 000000000..472d1d445
--- /dev/null
+++ b/keyboards/alps64/alps64.c
@@ -0,0 +1,30 @@
+/*
+Copyright 2012,2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "quantum.h"
+
+#define LED_ON() do { DDRC |= (1<<5); PORTC |= (1<<5); } while (0)
+#define LED_OFF() do { DDRC &= ~(1<<5); PORTC &= ~(1<<5); } while (0)
+#define LED_TGL() do { DDRC |= (1<<5); PINC |= (1<<5); } while (0)
+
+
+void matrix_init_kb(void) {
+ LED_ON();
+ _delay_ms(500);
+ LED_OFF();
+
+ matrix_init_user();
+} \ No newline at end of file
diff --git a/keyboards/alps64/alps64.h b/keyboards/alps64/alps64.h
new file mode 100644
index 000000000..f265c3358
--- /dev/null
+++ b/keyboards/alps64/alps64.h
@@ -0,0 +1,40 @@
+/*
+Copyright 2012,2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef ALPS64_H
+#define ALPS64_H
+
+#include "quantum.h"
+
+/* Alps64 keymap definition macro */
+#define KEYMAP( \
+ K36, K37, K46, K47, K56, K57, K66, K67, K76, K77, K06, K07, K17, K26, K27, \
+ K34, K35, K44, K45, K54, K55, K64, K65, K75, K05, K15, K16, K25, K24, \
+ K32, K33, K43, K52, K53, K63, K73, K74, K03, K04, K13, K14, K23, \
+ K31, K41, K42, K51, K61, K62, K71, K72, K01, K02, K11, K12, K21, K22, \
+ K30, K40, K50, K60, K70, K00, K10, K20 \
+) { \
+ { KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07 }, \
+ { KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_##K17 }, \
+ { KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_##K27 }, \
+ { KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36, KC_##K37 }, \
+ { KC_##K40, KC_##K41, KC_##K42, KC_##K43, KC_##K44, KC_##K45, KC_##K46, KC_##K47 }, \
+ { KC_##K50, KC_##K51, KC_##K52, KC_##K53, KC_##K54, KC_##K55, KC_##K56, KC_##K57 }, \
+ { KC_##K60, KC_##K61, KC_##K62, KC_##K63, KC_##K64, KC_##K65, KC_##K66, KC_##K67 }, \
+ { KC_##K70, KC_##K71, KC_##K72, KC_##K73, KC_##K74, KC_##K75, KC_##K76, KC_##K77 } \
+}
+
+#endif
diff --git a/keyboards/alps64/config.h b/keyboards/alps64/config.h
new file mode 100644
index 000000000..858a82ecd
--- /dev/null
+++ b/keyboards/alps64/config.h
@@ -0,0 +1,75 @@
+/*
+Copyright 2015 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "config_common.h"
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x6464
+#define DEVICE_VER 0x0001
+#define MANUFACTURER TMK
+#define PRODUCT Alps64
+#define DESCRIPTION TMK keyboard firmware for Alps64
+
+/* key matrix size */
+#define MATRIX_ROWS 8
+#define MATRIX_COLS 8
+
+#define MATRIX_COL_PINS { B0, B1, B2, B3, B4, B5, B6, B7 }
+#define MATRIX_ROW_PINS { D0, D1, D2, D3, D4, D5, D6, C2 }
+#define UNUSED_PINS
+
+/* define if matrix has ghost */
+//#define MATRIX_HAS_GHOST
+
+/* Set 0 if debouncing isn't needed */
+#define DEBOUNCE 5
+
+/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
+#define LOCKING_SUPPORT_ENABLE
+/* Locking resynchronize hack */
+#define LOCKING_RESYNC_ENABLE
+
+/* key combination for command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+
+
+/*
+ * Feature disable options
+ * These options are also useful to firmware size reduction.
+ */
+
+/* disable debug print */
+//#define NO_DEBUG
+
+/* disable print */
+//#define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+
+#endif
diff --git a/keyboards/alps64/keymaps/default/keymap.c b/keyboards/alps64/keymaps/default/keymap.c
new file mode 100644
index 000000000..2c45dc7f3
--- /dev/null
+++ b/keyboards/alps64/keymaps/default/keymap.c
@@ -0,0 +1,12 @@
+#include "alps64.h"
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ /* 0: qwerty */
+ KEYMAP( \
+ GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, NUHS, BSPC, \
+ TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, \
+ CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT,ENT, \
+ LSFT,NUBS,Z, X, C, V, B, N, M, COMM,DOT, SLSH,RSFT,ESC, \
+ LCTL,LGUI,LALT, SPC, APP, RALT,RGUI,RCTL),
+};
+const uint16_t PROGMEM fn_actions[] = {};
diff --git a/keyboards/alps64/led.c b/keyboards/alps64/led.c
new file mode 100644
index 000000000..d20c51aab
--- /dev/null
+++ b/keyboards/alps64/led.c
@@ -0,0 +1,34 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <avr/io.h>
+#include "stdint.h"
+#include "led.h"
+
+
+void led_set(uint8_t usb_led)
+{
+ if (usb_led & (1<<USB_LED_CAPS_LOCK)) {
+ // output high
+ DDRC |= (1<<5);
+ PORTC |= (1<<5);
+ } else {
+ // Hi-Z
+ DDRC &= ~(1<<5);
+ PORTC &= ~(1<<5);
+ }
+}
diff --git a/keyboards/alps64/matrix.c b/keyboards/alps64/matrix.c
new file mode 100644
index 000000000..b3508850d
--- /dev/null
+++ b/keyboards/alps64/matrix.c
@@ -0,0 +1,199 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * scan matrix
+ */
+#include <stdint.h>
+#include <stdbool.h>
+#include <avr/io.h>
+#include <util/delay.h>
+#include "print.h"
+#include "debug.h"
+#include "util.h"
+#include "matrix.h"
+
+
+#ifndef DEBOUNCE
+# define DEBOUNCE 5
+#endif
+static uint8_t debouncing = DEBOUNCE;
+
+/* matrix state(1:on, 0:off) */
+static matrix_row_t matrix[MATRIX_ROWS];
+static matrix_row_t matrix_debouncing[MATRIX_ROWS];
+
+static matrix_row_t read_cols(void);
+static void init_cols(void);
+static void unselect_rows(void);
+static void select_row(uint8_t row);
+
+
+inline
+uint8_t matrix_rows(void)
+{
+ return MATRIX_ROWS;
+}
+
+inline
+uint8_t matrix_cols(void)
+{
+ return MATRIX_COLS;
+}
+
+void matrix_init(void)
+{
+ // initialize row and col
+ unselect_rows();
+ init_cols();
+
+ // initialize matrix state: all keys off
+ for (uint8_t i=0; i < MATRIX_ROWS; i++) {
+ matrix[i] = 0;
+ matrix_debouncing[i] = 0;
+ }
+
+ //debug
+ debug_matrix = true;
+ LED_ON();
+ _delay_ms(500);
+ LED_OFF();
+}
+
+uint8_t matrix_scan(void)
+{
+ for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+ select_row(i);
+ _delay_us(30); // without this wait read unstable value.
+ matrix_row_t cols = read_cols();
+ if (matrix_debouncing[i] != cols) {
+ matrix_debouncing[i] = cols;
+ if (debouncing) {
+ debug("bounce!: "); debug_hex(debouncing); debug("\n");
+ }
+ debouncing = DEBOUNCE;
+ }
+ unselect_rows();
+ }
+
+ if (debouncing) {
+ if (--debouncing) {
+ _delay_ms(1);
+ } else {
+ for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+ matrix[i] = matrix_debouncing[i];
+ }
+ }
+ }
+
+ matrix_scan_quantum();
+
+ return 1;
+}
+
+inline
+bool matrix_is_on(uint8_t row, uint8_t col)
+{
+ return (matrix[row] & ((matrix_row_t)1<<col));
+}
+
+inline
+matrix_row_t matrix_get_row(uint8_t row)
+{
+ return matrix[row];
+}
+
+void matrix_print(void)
+{
+ print("\nr/c 0123456789ABCDEF\n");
+ for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
+ phex(row); print(": ");
+ pbin_reverse16(matrix_get_row(row));
+ print("\n");
+ }
+}
+
+/* Column pin configuration
+ * col: 0 1 2 3 4 5 6 7
+ * pin: B0 B1 B2 B3 B4 B5 B6 B7
+ */
+static void init_cols(void)
+{
+ // Input with pull-up(DDR:0, PORT:1)
+ DDRB &= ~0b11111111;
+ PORTB |= 0b11111111;
+}
+
+/* Returns status of switches(1:on, 0:off) */
+static matrix_row_t read_cols(void)
+{
+ // Invert because PIN indicates 'switch on' with low(0) and 'off' with high(1)
+ return ~PINB;
+}
+
+/* Row pin configuration
+ * row: 0 1 2 3 4 5 6 7
+ * pin: D0 D1 D2 D3 D4 D5 D6 C2
+ */
+static void unselect_rows(void)
+{
+ // Hi-Z(DDR:0, PORT:0) to unselect
+ DDRD &= ~0b01111111;
+ PORTD &= ~0b01111111;
+ DDRC &= ~0b00000100;
+ PORTC &= ~0b00000100;
+}
+
+
+static void select_row(uint8_t row)
+{
+ // Output low(DDR:1, PORT:0) to select
+ switch (row) {
+ case 0:
+ DDRD |= (1<<0);
+ PORTD &= ~(1<<0);
+ break;
+ case 1:
+ DDRD |= (1<<1);
+ PORTD &= ~(1<<1);
+ break;
+ case 2:
+ DDRD |= (1<<2);
+ PORTD &= ~(1<<2);
+ break;
+ case 3:
+ DDRD |= (1<<3);
+ PORTD &= ~(1<<3);
+ break;
+ case 4:
+ DDRD |= (1<<4);
+ PORTD &= ~(1<<4);
+ break;
+ case 5:
+ DDRD |= (1<<5);
+ PORTD &= ~(1<<5);
+ break;
+ case 6:
+ DDRD |= (1<<6);
+ PORTD &= ~(1<<6);
+ break;
+ case 7:
+ DDRC |= (1<<2);
+ PORTC &= ~(1<<2);
+ break;
+ }
+}
diff --git a/keyboards/arrow_pad/Makefile b/keyboards/arrow_pad/Makefile
new file mode 100644
index 000000000..09fcf3e7a
--- /dev/null
+++ b/keyboards/arrow_pad/Makefile
@@ -0,0 +1,74 @@
+
+
+# MCU name
+#MCU = at90usb1287
+MCU = atmega32u4
+
+# Processor frequency.
+# This will define a symbol, F_CPU, in all source code files equal to the
+# processor frequency in Hz. You can then use this symbol in your source code to
+# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
+# automatically to create a 32-bit value in your source code.
+#
+# This will be an integer division of F_USB below, as it is sourced by
+# F_USB after it has run through any CPU prescalers. Note that this value
+# does not *change* the processor frequency - it should merely be updated to
+# reflect the processor speed set externally so that the code can use accurate
+# software delays.
+F_CPU = 16000000
+
+
+#
+# LUFA specific
+#
+# Target architecture (see library "Board Types" documentation).
+ARCH = AVR8
+
+# Input clock frequency.
+# This will define a symbol, F_USB, in all source code files equal to the
+# input clock frequency (before any prescaling is performed) in Hz. This value may
+# differ from F_CPU if prescaling is used on the latter, and is required as the
+# raw input clock is fed directly to the PLL sections of the AVR for high speed
+# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
+# at the end, this will be done automatically to create a 32-bit value in your
+# source code.
+#
+# If no clock division is performed on the input clock inside the AVR (via the
+# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
+F_USB = $(F_CPU)
+
+# Interrupt driven control endpoint task(+60)
+OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
+
+
+# Boot Section Size in *bytes*
+# Teensy halfKay 512
+# Teensy++ halfKay 1024
+# Atmel DFU loader 4096
+# LUFA bootloader 4096
+# USBaspLoader 2048
+OPT_DEFS += -DBOOTLOADER_SIZE=512
+
+
+# Build Options
+# change yes to no to disable
+#
+BOOTMAGIC_ENABLE ?= yes # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE ?= yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450)
+CONSOLE_ENABLE ?= yes # Console for debug(+400)
+COMMAND_ENABLE ?= yes # Commands for debug and configuration
+KEYBOARD_LOCK_ENABLE ?= yes # Allow locking of keyboard via magic key
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE ?= no # Breathing sleep LED during USB suspend
+# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+NKRO_ENABLE ?= yes # USB Nkey Rollover
+BACKLIGHT_ENABLE ?= yes # Enable keyboard backlight functionality
+MIDI_ENABLE ?= no # MIDI controls
+UNICODE_ENABLE ?= no # Unicode
+BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID
+AUDIO_ENABLE ?= no # Audio output on port C6
+
+ifndef QUANTUM_DIR
+ include ../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/arrow_pad/arrow_pad.c b/keyboards/arrow_pad/arrow_pad.c
new file mode 100644
index 000000000..381934aa8
--- /dev/null
+++ b/keyboards/arrow_pad/arrow_pad.c
@@ -0,0 +1 @@
+#include "arrow_pad.h" \ No newline at end of file
diff --git a/keyboards/arrow_pad/arrow_pad.h b/keyboards/arrow_pad/arrow_pad.h
new file mode 100644
index 000000000..62882b9b5
--- /dev/null
+++ b/keyboards/arrow_pad/arrow_pad.h
@@ -0,0 +1,13 @@
+#ifndef ARROW_PAD_H
+#define ARROW_PAD_H
+
+#include "quantum.h"
+#include "matrix.h"
+#include "keymap.h"
+#ifdef BACKLIGHT_ENABLE
+ #include "backlight.h"
+#endif
+#include <avr/io.h>
+#include <stddef.h>
+
+#endif
diff --git a/keyboards/arrow_pad/config.h b/keyboards/arrow_pad/config.h
new file mode 100644
index 000000000..3d8d8709a
--- /dev/null
+++ b/keyboards/arrow_pad/config.h
@@ -0,0 +1,160 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "config_common.h"
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x4096
+#define DEVICE_VER 0x0001
+#define MANUFACTURER Nobody
+#define PRODUCT GoldPad
+#define DESCRIPTION A custom keyboard
+
+/* key matrix size */
+#define MATRIX_ROWS 6
+#define MATRIX_COLS 4
+
+/*
+ * Keyboard Matrix Assignments
+ *
+ * Change this to how you wired your keyboard
+ * COLS: AVR pins used for columns, left to right
+ * ROWS: AVR pins used for rows, top to bottom
+ * DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode)
+ * ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode)
+ *
+*/
+#define MATRIX_ROW_PINS { F0, F1, F4, F5, F6, F7 }
+#define MATRIX_COL_PINS { B0, B1, B2, B3 }
+#define UNUSED_PINS
+
+#define BACKLIGHT_PIN B7
+
+/* COL2ROW or ROW2COL */
+#define DIODE_DIRECTION ROW2COL
+
+/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
+#define DEBOUNCING_DELAY 5
+
+/* define if matrix has ghost (lacks anti-ghosting diodes) */
+//#define MATRIX_HAS_GHOST
+
+/* number of backlight levels */
+#define BACKLIGHT_LEVELS 3
+
+/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
+//#define LOCKING_SUPPORT_ENABLE
+/* Locking resynchronize hack */
+//#define LOCKING_RESYNC_ENABLE
+
+/*
+ * Force NKRO
+ *
+ * Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved
+ * state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the
+ * makefile for this to work.)
+ *
+ * If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N)
+ * until the next keyboard reset.
+ *
+ * NKRO may prevent your keystrokes from being detected in the BIOS, but it is
+ * fully operational during normal computer usage.
+ *
+ * For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N)
+ * or via bootmagic (hold SPACE+N while plugging in the keyboard). Once set by
+ * bootmagic, NKRO mode will always be enabled until it is toggled again during a
+ * power-up.
+ *
+ */
+#define FORCE_NKRO
+
+/*
+ * Magic Key Options
+ *
+ * Magic keys are hotkey commands that allow control over firmware functions of
+ * the keyboard. They are best used in combination with the HID Listen program,
+ * found here: https://www.pjrc.com/teensy/hid_listen.html
+ *
+ * The options below allow the magic key functionality to be changed. This is
+ * useful if your keyboard/keypad is missing keys and you want magic key support.
+ *
+ */
+
+/* key combination for magic key command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+/* control how magic key switches layers */
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS true
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS true
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM false
+
+/* override magic key keymap */
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM
+//#define MAGIC_KEY_HELP1 H
+//#define MAGIC_KEY_HELP2 SLASH
+//#define MAGIC_KEY_DEBUG D
+//#define MAGIC_KEY_DEBUG_MATRIX X
+//#define MAGIC_KEY_DEBUG_KBD K
+//#define MAGIC_KEY_DEBUG_MOUSE M
+//#define MAGIC_KEY_VERSION V
+//#define MAGIC_KEY_STATUS S
+//#define MAGIC_KEY_CONSOLE C
+//#define MAGIC_KEY_LAYER0_ALT1 ESC
+//#define MAGIC_KEY_LAYER0_ALT2 GRAVE
+//#define MAGIC_KEY_LAYER0 0
+//#define MAGIC_KEY_LAYER1 1
+//#define MAGIC_KEY_LAYER2 2
+//#define MAGIC_KEY_LAYER3 3
+//#define MAGIC_KEY_LAYER4 4
+//#define MAGIC_KEY_LAYER5 5
+//#define MAGIC_KEY_LAYER6 6
+//#define MAGIC_KEY_LAYER7 7
+//#define MAGIC_KEY_LAYER8 8
+//#define MAGIC_KEY_LAYER9 9
+//#define MAGIC_KEY_BOOTLOADER PAUSE
+//#define MAGIC_KEY_LOCK CAPS
+//#define MAGIC_KEY_EEPROM E
+//#define MAGIC_KEY_NKRO N
+//#define MAGIC_KEY_SLEEP_LED Z
+
+/*
+ * Feature disable options
+ * These options are also useful to firmware size reduction.
+ */
+
+/* disable debug print */
+//#define NO_DEBUG
+
+/* disable print */
+//#define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+
+#endif
diff --git a/keyboards/arrow_pad/keymaps/default/keymap.c b/keyboards/arrow_pad/keymaps/default/keymap.c
new file mode 100644
index 000000000..5647f75af
--- /dev/null
+++ b/keyboards/arrow_pad/keymaps/default/keymap.c
@@ -0,0 +1,163 @@
+// This is the canonical layout file for the Quantum project. If you want to add another keyboard,
+// this is the style you want to emulate.
+
+#include "arrow_pad.h"
+#include "led.h"
+
+// This is the 21-key keypad to 2x11 element matrix mapping
+#define KEYMAP( \
+ KM_ESC, KM_TAB, KM_BSL, KM_ARR, \
+ KM_NUM, KM_FSL, KM_AST, KM_MIN, \
+ KM___7, KM___8, KM___9, KM_EQU, \
+ KM___4, KM___5, KM___6, KM_PLS, \
+ KM___1, KM___2, KM___3, ___ENT, \
+ KM___0, _____0, KM_DOT, KM_ENT \
+) { \
+ { KM_ESC, KM_TAB, KM_BSL, KM_ARR }, \
+ { KM_NUM, KM_FSL, KM_AST, KM_MIN }, \
+ { KM___7, KM___8, KM___9, KM_EQU }, \
+ { KM___4, KM___5, KM___6, KM_PLS }, \
+ { KM___1, KM___2, KM___3, KC_NO }, \
+ { KM___0, KC_NO, KM_DOT, KM_ENT } \
+}
+
+#define LAYER_BASE 0
+#define LAYER_EDIT 1
+#define LAYER_FUNCTION 2
+
+#define MACRO_COPY_CUT 0
+#define MACRO_SHIFT_CONTROL 1
+#define MACRO_CONTROL_ALT 2
+
+#define M_COPY KC_FN5
+#define M_SHFCT KC_FN6
+#define M_CTALT KC_FN7
+
+#define SC_UNDO LCTL(KC_Z)
+#define SC_REDO LCTL(KC_Y)
+#define SC_CUT LCTL(KC_X)
+#define SC_COPY LCTL(KC_C)
+#define SC_PSTE LCTL(KC_V)
+#define SC_SELA LCTL(KC_A)
+#define SC_SAVE LCTL(KC_S)
+#define SC_OPEN LCTL(KC_O)
+#define SC_ACLS LALT(KC_F4)
+#define SC_CCLS LCTL(KC_F4)
+
+#define _______ KC_TRNS
+#define XXXXXXX KC_NO
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+
+[LAYER_BASE] = KEYMAP( \
+ KC_ESC, KC_TAB, KC_BSLS, KC_FN0, \
+ KC_NLCK, KC_PSLS, KC_PAST, KC_PMNS, \
+ KC_P7, KC_P8, KC_P9, KC_PEQL, \
+ KC_P4, KC_P5, KC_P6, KC_PPLS, \
+ KC_P1, KC_P2, KC_P3, XXXXXXX, \
+ KC_P0, KC_PCMM, KC_PDOT, KC_PENT ),
+
+[LAYER_EDIT] = KEYMAP( \
+ KC_ESC, KC_TAB, KC_SPC, _______, \
+ KC_FN1, SC_PSTE, SC_REDO, SC_UNDO, \
+ KC_HOME, KC_UP, KC_PGUP, KC_LALT, \
+ KC_LEFT, M_COPY, KC_RGHT, KC_LCTL, \
+ KC_END, KC_DOWN, KC_PGDN, XXXXXXX, \
+ KC_BSPC, KC_PENT, KC_DEL, M_SHFCT),
+
+[LAYER_FUNCTION] = KEYMAP( \
+ KC_FN2, KC_FN3, KC_FN4, _______, \
+ KC_FN1, _______, _______, _______, \
+ _______, _______, _______, _______, \
+ _______, _______, _______, _______, \
+ _______, _______, _______, XXXXXXX, \
+ RESET, _______, _______, _______ ),
+
+};
+
+
+const uint16_t PROGMEM fn_actions[] = {
+ [0] = ACTION_LAYER_MOMENTARY(LAYER_FUNCTION),
+ [1] = ACTION_LAYER_TOGGLE(LAYER_EDIT),
+ [2] = ACTION_BACKLIGHT_TOGGLE(),
+ [3] = ACTION_BACKLIGHT_INCREASE(),
+ [4] = ACTION_BACKLIGHT_DECREASE(),
+ [5] = ACTION_MACRO_TAP(MACRO_COPY_CUT),
+ [6] = ACTION_MACRO_TAP(MACRO_SHIFT_CONTROL),
+ [7] = ACTION_MACRO_TAP(MACRO_CONTROL_ALT),
+
+};
+
+
+void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+}
+
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch (id) {
+
+ case MACRO_COPY_CUT:
+ if (record->event.pressed) {
+ register_code(KC_LCTL);
+ if (record->tap.count == 1) {
+ register_code(KC_C);
+ unregister_code(KC_C);
+ }
+ else if (record->tap.count == 2) {
+ register_code(KC_X);
+ unregister_code(KC_X);
+ }
+ unregister_code(KC_LCTL);
+ }
+ break;
+
+ case MACRO_SHIFT_CONTROL:
+ if (record->event.pressed) {
+ if (record->tap.count <= 2) register_mods(MOD_BIT(KC_LSFT));
+ if (record->tap.count == 2) register_mods(MOD_BIT(KC_LCTL));
+ if (record->tap.count == 3) register_code(KC_PENT);;
+ }
+ else {
+ unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_LCTL));
+ unregister_code(KC_PENT);
+ }
+ break;
+
+ case MACRO_CONTROL_ALT:
+ if (record->event.pressed) {
+ if (record->tap.count < 2) register_mods(MOD_BIT(KC_LCTL));
+ if (record->tap.count >= 2) register_mods(MOD_BIT(KC_LALT));
+ }
+ else {
+ unregister_mods(MOD_BIT(KC_LCTL) | MOD_BIT(KC_LALT));
+ }
+ break;
+ }
+
+ return MACRO_NONE;
+}
+
+void led_set_user(uint8_t usb_led)
+{
+ if (usb_led & (1<<USB_LED_CAPS_LOCK)) {
+ // output high
+ DDRD |= (1<<6);
+ PORTD |= (1<<6);
+ } else {
+ // Hi-Z
+ DDRD &= ~(1<<6);
+ PORTD &= ~(1<<6);
+ }
+ if (usb_led & (1<<USB_LED_NUM_LOCK)) {
+ // output low
+ DDRC |= (1<<7);
+ PORTC |= ~(1<<7);
+ } else {
+ // Hi-Z
+ DDRC &= ~(1<<7);
+ PORTC &= ~(1<<7);
+ }
+} \ No newline at end of file
diff --git a/keyboards/arrow_pad/keymaps/pad_21/Makefile b/keyboards/arrow_pad/keymaps/pad_21/Makefile
new file mode 100644
index 000000000..af51976a8
--- /dev/null
+++ b/keyboards/arrow_pad/keymaps/pad_21/Makefile
@@ -0,0 +1,17 @@
+BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = no # Mouse keys(+4700)
+EXTRAKEY_ENABLE = no # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = no # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+CONFIG_H = keymaps/$(KEYMAP)/config.h \ No newline at end of file
diff --git a/keyboards/arrow_pad/keymaps/pad_21/config.h b/keyboards/arrow_pad/keymaps/pad_21/config.h
new file mode 100644
index 000000000..a095e8737
--- /dev/null
+++ b/keyboards/arrow_pad/keymaps/pad_21/config.h
@@ -0,0 +1,158 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "config_common.h"
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x4097
+#define DEVICE_VER 0x0001
+#define MANUFACTURER Nobody
+#define PRODUCT Arrow Pad 21
+#define DESCRIPTION 21-Key QMK Assistant
+
+/* key matrix size */
+#define MATRIX_ROWS 2
+#define MATRIX_COLS 11
+
+/*
+ * Keyboard Matrix Assignments
+ *
+ * Change this to how you wired your keyboard
+ * COLS: AVR pins used for columns, left to right
+ * ROWS: AVR pins used for rows, top to bottom
+ * DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode)
+ * ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode)
+ *
+*/
+#define MATRIX_ROW_PINS { D3, D5 }
+#define MATRIX_COL_PINS { F0, F1, F4, F5, F6, F7, B6, B5, B4, D7, D4 }
+#define UNUSED_PINS
+
+/* COL2ROW or ROW2COL */
+#define DIODE_DIRECTION ROW2COL
+
+/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
+#define DEBOUNCING_DELAY 5
+
+/* define if matrix has ghost (lacks anti-ghosting diodes) */
+//#define MATRIX_HAS_GHOST
+
+/* number of backlight levels */
+#define BACKLIGHT_LEVELS 3
+
+/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
+//#define LOCKING_SUPPORT_ENABLE
+/* Locking resynchronize hack */
+//#define LOCKING_RESYNC_ENABLE
+
+/*
+ * Force NKRO
+ *
+ * Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved
+ * state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the
+ * makefile for this to work.)
+ *
+ * If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N)
+ * until the next keyboard reset.
+ *
+ * NKRO may prevent your keystrokes from being detected in the BIOS, but it is
+ * fully operational during normal computer usage.
+ *
+ * For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N)
+ * or via bootmagic (hold SPACE+N while plugging in the keyboard). Once set by
+ * bootmagic, NKRO mode will always be enabled until it is toggled again during a
+ * power-up.
+ *
+ */
+#define FORCE_NKRO
+
+/*
+ * Magic Key Options
+ *
+ * Magic keys are hotkey commands that allow control over firmware functions of
+ * the keyboard. They are best used in combination with the HID Listen program,
+ * found here: https://www.pjrc.com/teensy/hid_listen.html
+ *
+ * The options below allow the magic key functionality to be changed. This is
+ * useful if your keyboard/keypad is missing keys and you want magic key support.
+ *
+ */
+
+/* key combination for magic key command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+/* control how magic key switches layers */
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS true
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS true
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM false
+
+/* override magic key keymap */
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM
+//#define MAGIC_KEY_HELP1 H
+//#define MAGIC_KEY_HELP2 SLASH
+//#define MAGIC_KEY_DEBUG D
+//#define MAGIC_KEY_DEBUG_MATRIX X
+//#define MAGIC_KEY_DEBUG_KBD K
+//#define MAGIC_KEY_DEBUG_MOUSE M
+//#define MAGIC_KEY_VERSION V
+//#define MAGIC_KEY_STATUS S
+//#define MAGIC_KEY_CONSOLE C
+//#define MAGIC_KEY_LAYER0_ALT1 ESC
+//#define MAGIC_KEY_LAYER0_ALT2 GRAVE
+//#define MAGIC_KEY_LAYER0 0
+//#define MAGIC_KEY_LAYER1 1
+//#define MAGIC_KEY_LAYER2 2
+//#define MAGIC_KEY_LAYER3 3
+//#define MAGIC_KEY_LAYER4 4
+//#define MAGIC_KEY_LAYER5 5
+//#define MAGIC_KEY_LAYER6 6
+//#define MAGIC_KEY_LAYER7 7
+//#define MAGIC_KEY_LAYER8 8
+//#define MAGIC_KEY_LAYER9 9
+//#define MAGIC_KEY_BOOTLOADER PAUSE
+//#define MAGIC_KEY_LOCK CAPS
+//#define MAGIC_KEY_EEPROM E
+//#define MAGIC_KEY_NKRO N
+//#define MAGIC_KEY_SLEEP_LED Z
+
+/*
+ * Feature disable options
+ * These options are also useful to firmware size reduction.
+ */
+
+/* disable debug print */
+//#define NO_DEBUG
+
+/* disable print */
+//#define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+
+#endif
diff --git a/keyboards/arrow_pad/keymaps/pad_21/keymap.c b/keyboards/arrow_pad/keymaps/pad_21/keymap.c
new file mode 100644
index 000000000..28917a5d9
--- /dev/null
+++ b/keyboards/arrow_pad/keymaps/pad_21/keymap.c
@@ -0,0 +1,160 @@
+// This is the canonical layout file for the Quantum project. If you want to add another keyboard,
+// this is the style you want to emulate.
+
+#include "arrow_pad.h"
+#include "led.h"
+
+// This is the 21-key keypad to 2x11 element matrix mapping
+#define KEYMAP( \
+ KM_ESC, KM_TAB, KM_BSL, KM_ARR, \
+ KM_NUM, KM_FSL, KM_AST, KM_MIN, \
+ KM___7, KM___8, KM___9, ___PLS, \
+ KM___4, KM___5, KM___6, KM_PLS, \
+ KM___1, KM___2, KM___3, ___ENT, \
+ KM___0, _____0, KM_DOT, KM_ENT \
+) { \
+ { KM_ESC, KM_TAB, KM_BSL, KM_ARR, KM___7, KM___8, KM___9, KM_PLS, KM___1, KM___2, KM___3, }, \
+ { KM_NUM, KM_FSL, KM_AST, KM_MIN, KM___4, KM___5, KM___6, KM_ENT, KC_NO, KM___0, KM_DOT, }, \
+}
+
+
+#define LAYER_BASE 0
+#define LAYER_EDIT 1
+#define LAYER_FUNCTION 2
+
+#define MACRO_COPY_CUT 0
+#define MACRO_SHIFT_CONTROL 1
+#define MACRO_CONTROL_ALT 2
+
+#define M_COPY KC_FN5
+#define M_SHFCT KC_FN6
+#define M_CTALT KC_FN7
+
+#define SC_UNDO LCTL(KC_Z)
+#define SC_REDO LCTL(KC_Y)
+#define SC_CUT LCTL(KC_X)
+#define SC_COPY LCTL(KC_C)
+#define SC_PSTE LCTL(KC_V)
+#define SC_SELA LCTL(KC_A)
+#define SC_SAVE LCTL(KC_S)
+#define SC_OPEN LCTL(KC_O)
+#define SC_ACLS LALT(KC_F4)
+#define SC_CCLS LCTL(KC_F4)
+
+#define _______ KC_TRNS
+#define XXXXXXX KC_NO
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+
+[LAYER_BASE] = KEYMAP( \
+ KC_ESC, KC_TAB, KC_BSLS, KC_FN0, \
+ KC_NLCK, KC_PSLS, KC_PAST, KC_PMNS, \
+ KC_P7, KC_P8, KC_P9, XXXXXXX, \
+ KC_P4, KC_P5, KC_P6, KC_PPLS, \
+ KC_P1, KC_P2, KC_P3, XXXXXXX, \
+ KC_P0, XXXXXXX, KC_PDOT, KC_PENT ),
+
+[LAYER_EDIT] = KEYMAP( \
+ KC_ESC, KC_TAB, KC_SPC, _______, \
+ KC_FN1, SC_PSTE, SC_REDO, SC_UNDO, \
+ KC_HOME, KC_UP, KC_PGUP, XXXXXXX, \
+ KC_LEFT, M_COPY, KC_RGHT, M_CTALT, \
+ KC_END, KC_DOWN, KC_PGDN, XXXXXXX, \
+ KC_BSPC, XXXXXXX, KC_DEL, M_SHFCT),
+
+[LAYER_FUNCTION] = KEYMAP( \
+ KC_FN2, KC_FN3, KC_FN4, _______, \
+ KC_FN1, _______, _______, _______, \
+ _______, _______, _______, XXXXXXX, \
+ _______, _______, _______, _______, \
+ _______, _______, _______, XXXXXXX, \
+ RESET, XXXXXXX, _______, _______ ),
+
+};
+
+
+const uint16_t PROGMEM fn_actions[] = {
+ [0] = ACTION_LAYER_MOMENTARY(LAYER_FUNCTION),
+ [1] = ACTION_LAYER_TOGGLE(LAYER_EDIT),
+ [2] = ACTION_BACKLIGHT_TOGGLE(),
+ [3] = ACTION_BACKLIGHT_INCREASE(),
+ [4] = ACTION_BACKLIGHT_DECREASE(),
+ [5] = ACTION_MACRO_TAP(MACRO_COPY_CUT),
+ [6] = ACTION_MACRO_TAP(MACRO_SHIFT_CONTROL),
+ [7] = ACTION_MACRO_TAP(MACRO_CONTROL_ALT),
+
+};
+
+
+void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+}
+
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch (id) {
+
+ case MACRO_COPY_CUT:
+ if (record->event.pressed) {
+ register_code(KC_LCTL);
+ if (record->tap.count == 1) {
+ register_code(KC_C);
+ unregister_code(KC_C);
+ }
+ else if (record->tap.count == 2) {
+ register_code(KC_X);
+ unregister_code(KC_X);
+ }
+ unregister_code(KC_LCTL);
+ }
+ break;
+
+ case MACRO_SHIFT_CONTROL:
+ if (record->event.pressed) {
+ if (record->tap.count <= 2) register_mods(MOD_BIT(KC_LSFT));
+ if (record->tap.count == 2) register_mods(MOD_BIT(KC_LCTL));
+ if (record->tap.count == 3) register_code(KC_PENT);;
+ }
+ else {
+ unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_LCTL));
+ unregister_code(KC_PENT);
+ }
+ break;
+
+ case MACRO_CONTROL_ALT:
+ if (record->event.pressed) {
+ if (record->tap.count < 2) register_mods(MOD_BIT(KC_LCTL));
+ if (record->tap.count >= 2) register_mods(MOD_BIT(KC_LALT));
+ }
+ else {
+ unregister_mods(MOD_BIT(KC_LCTL) | MOD_BIT(KC_LALT));
+ }
+ break;
+ }
+
+ return MACRO_NONE;
+}
+
+void led_set_user(uint8_t usb_led)
+{
+ if (usb_led & (1<<USB_LED_CAPS_LOCK)) {
+ // output high
+ DDRD |= (1<<6);
+ PORTD |= (1<<6);
+ } else {
+ // Hi-Z
+ DDRD &= ~(1<<6);
+ PORTD &= ~(1<<6);
+ }
+ if (usb_led & (1<<USB_LED_NUM_LOCK)) {
+ // output low
+ DDRC |= (1<<7);
+ PORTC |= ~(1<<7);
+ } else {
+ // Hi-Z
+ DDRC &= ~(1<<7);
+ PORTC &= ~(1<<7);
+ }
+} \ No newline at end of file
diff --git a/keyboards/arrow_pad/keymaps/pad_24/Makefile b/keyboards/arrow_pad/keymaps/pad_24/Makefile
new file mode 100644
index 000000000..e31bfe1af
--- /dev/null
+++ b/keyboards/arrow_pad/keymaps/pad_24/Makefile
@@ -0,0 +1,17 @@
+BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = no # Mouse keys(+4700)
+EXTRAKEY_ENABLE = no # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = no # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+CONFIG_H = keymaps/$(KEYMAP)/config.h \ No newline at end of file
diff --git a/keyboards/arrow_pad/keymaps/pad_24/config.h b/keyboards/arrow_pad/keymaps/pad_24/config.h
new file mode 100644
index 000000000..e940acaa0
--- /dev/null
+++ b/keyboards/arrow_pad/keymaps/pad_24/config.h
@@ -0,0 +1,160 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "config_common.h"
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x4096
+#define DEVICE_VER 0x0001
+#define MANUFACTURER Nobody
+#define PRODUCT Arrow Pad 24
+#define DESCRIPTION 24-Key QMK Assistant
+
+/* key matrix size */
+#define MATRIX_ROWS 6
+#define MATRIX_COLS 4
+
+/*
+ * Keyboard Matrix Assignments
+ *
+ * Change this to how you wired your keyboard
+ * COLS: AVR pins used for columns, left to right
+ * ROWS: AVR pins used for rows, top to bottom
+ * DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode)
+ * ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode)
+ *
+*/
+#define MATRIX_ROW_PINS { F0, F1, F4, F5, F6, F7 }
+#define MATRIX_COL_PINS { B0, B1, B2, B3 }
+#define UNUSED_PINS
+
+#define BACKLIGHT_PIN B7
+
+/* COL2ROW or ROW2COL */
+#define DIODE_DIRECTION ROW2COL
+
+/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
+#define DEBOUNCING_DELAY 5
+
+/* define if matrix has ghost (lacks anti-ghosting diodes) */
+//#define MATRIX_HAS_GHOST
+
+/* number of backlight levels */
+#define BACKLIGHT_LEVELS 3
+
+/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
+//#define LOCKING_SUPPORT_ENABLE
+/* Locking resynchronize hack */
+//#define LOCKING_RESYNC_ENABLE
+
+/*
+ * Force NKRO
+ *
+ * Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved
+ * state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the
+ * makefile for this to work.)
+ *
+ * If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N)
+ * until the next keyboard reset.
+ *
+ * NKRO may prevent your keystrokes from being detected in the BIOS, but it is
+ * fully operational during normal computer usage.
+ *
+ * For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N)
+ * or via bootmagic (hold SPACE+N while plugging in the keyboard). Once set by
+ * bootmagic, NKRO mode will always be enabled until it is toggled again during a
+ * power-up.
+ *
+ */
+#define FORCE_NKRO
+
+/*
+ * Magic Key Options
+ *
+ * Magic keys are hotkey commands that allow control over firmware functions of
+ * the keyboard. They are best used in combination with the HID Listen program,
+ * found here: https://www.pjrc.com/teensy/hid_listen.html
+ *
+ * The options below allow the magic key functionality to be changed. This is
+ * useful if your keyboard/keypad is missing keys and you want magic key support.
+ *
+ */
+
+/* key combination for magic key command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+/* control how magic key switches layers */
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS true
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS true
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM false
+
+/* override magic key keymap */
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM
+//#define MAGIC_KEY_HELP1 H
+//#define MAGIC_KEY_HELP2 SLASH
+//#define MAGIC_KEY_DEBUG D
+//#define MAGIC_KEY_DEBUG_MATRIX X
+//#define MAGIC_KEY_DEBUG_KBD K
+//#define MAGIC_KEY_DEBUG_MOUSE M
+//#define MAGIC_KEY_VERSION V
+//#define MAGIC_KEY_STATUS S
+//#define MAGIC_KEY_CONSOLE C
+//#define MAGIC_KEY_LAYER0_ALT1 ESC
+//#define MAGIC_KEY_LAYER0_ALT2 GRAVE
+//#define MAGIC_KEY_LAYER0 0
+//#define MAGIC_KEY_LAYER1 1
+//#define MAGIC_KEY_LAYER2 2
+//#define MAGIC_KEY_LAYER3 3
+//#define MAGIC_KEY_LAYER4 4
+//#define MAGIC_KEY_LAYER5 5
+//#define MAGIC_KEY_LAYER6 6
+//#define MAGIC_KEY_LAYER7 7
+//#define MAGIC_KEY_LAYER8 8
+//#define MAGIC_KEY_LAYER9 9
+//#define MAGIC_KEY_BOOTLOADER PAUSE
+//#define MAGIC_KEY_LOCK CAPS
+//#define MAGIC_KEY_EEPROM E
+//#define MAGIC_KEY_NKRO N
+//#define MAGIC_KEY_SLEEP_LED Z
+
+/*
+ * Feature disable options
+ * These options are also useful to firmware size reduction.
+ */
+
+/* disable debug print */
+//#define NO_DEBUG
+
+/* disable print */
+//#define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+
+#endif
diff --git a/keyboards/arrow_pad/keymaps/pad_24/keymap.c b/keyboards/arrow_pad/keymaps/pad_24/keymap.c
new file mode 100644
index 000000000..5647f75af
--- /dev/null
+++ b/keyboards/arrow_pad/keymaps/pad_24/keymap.c
@@ -0,0 +1,163 @@
+// This is the canonical layout file for the Quantum project. If you want to add another keyboard,
+// this is the style you want to emulate.
+
+#include "arrow_pad.h"
+#include "led.h"
+
+// This is the 21-key keypad to 2x11 element matrix mapping
+#define KEYMAP( \
+ KM_ESC, KM_TAB, KM_BSL, KM_ARR, \
+ KM_NUM, KM_FSL, KM_AST, KM_MIN, \
+ KM___7, KM___8, KM___9, KM_EQU, \
+ KM___4, KM___5, KM___6, KM_PLS, \
+ KM___1, KM___2, KM___3, ___ENT, \
+ KM___0, _____0, KM_DOT, KM_ENT \
+) { \
+ { KM_ESC, KM_TAB, KM_BSL, KM_ARR }, \
+ { KM_NUM, KM_FSL, KM_AST, KM_MIN }, \
+ { KM___7, KM___8, KM___9, KM_EQU }, \
+ { KM___4, KM___5, KM___6, KM_PLS }, \
+ { KM___1, KM___2, KM___3, KC_NO }, \
+ { KM___0, KC_NO, KM_DOT, KM_ENT } \
+}
+
+#define LAYER_BASE 0
+#define LAYER_EDIT 1
+#define LAYER_FUNCTION 2
+
+#define MACRO_COPY_CUT 0
+#define MACRO_SHIFT_CONTROL 1
+#define MACRO_CONTROL_ALT 2
+
+#define M_COPY KC_FN5
+#define M_SHFCT KC_FN6
+#define M_CTALT KC_FN7
+
+#define SC_UNDO LCTL(KC_Z)
+#define SC_REDO LCTL(KC_Y)
+#define SC_CUT LCTL(KC_X)
+#define SC_COPY LCTL(KC_C)
+#define SC_PSTE LCTL(KC_V)
+#define SC_SELA LCTL(KC_A)
+#define SC_SAVE LCTL(KC_S)
+#define SC_OPEN LCTL(KC_O)
+#define SC_ACLS LALT(KC_F4)
+#define SC_CCLS LCTL(KC_F4)
+
+#define _______ KC_TRNS
+#define XXXXXXX KC_NO
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+
+[LAYER_BASE] = KEYMAP( \
+ KC_ESC, KC_TAB, KC_BSLS, KC_FN0, \
+ KC_NLCK, KC_PSLS, KC_PAST, KC_PMNS, \
+ KC_P7, KC_P8, KC_P9, KC_PEQL, \
+ KC_P4, KC_P5, KC_P6, KC_PPLS, \
+ KC_P1, KC_P2, KC_P3, XXXXXXX, \
+ KC_P0, KC_PCMM, KC_PDOT, KC_PENT ),
+
+[LAYER_EDIT] = KEYMAP( \
+ KC_ESC, KC_TAB, KC_SPC, _______, \
+ KC_FN1, SC_PSTE, SC_REDO, SC_UNDO, \
+ KC_HOME, KC_UP, KC_PGUP, KC_LALT, \
+ KC_LEFT, M_COPY, KC_RGHT, KC_LCTL, \
+ KC_END, KC_DOWN, KC_PGDN, XXXXXXX, \
+ KC_BSPC, KC_PENT, KC_DEL, M_SHFCT),
+
+[LAYER_FUNCTION] = KEYMAP( \
+ KC_FN2, KC_FN3, KC_FN4, _______, \
+ KC_FN1, _______, _______, _______, \
+ _______, _______, _______, _______, \
+ _______, _______, _______, _______, \
+ _______, _______, _______, XXXXXXX, \
+ RESET, _______, _______, _______ ),
+
+};
+
+
+const uint16_t PROGMEM fn_actions[] = {
+ [0] = ACTION_LAYER_MOMENTARY(LAYER_FUNCTION),
+ [1] = ACTION_LAYER_TOGGLE(LAYER_EDIT),
+ [2] = ACTION_BACKLIGHT_TOGGLE(),
+ [3] = ACTION_BACKLIGHT_INCREASE(),
+ [4] = ACTION_BACKLIGHT_DECREASE(),
+ [5] = ACTION_MACRO_TAP(MACRO_COPY_CUT),
+ [6] = ACTION_MACRO_TAP(MACRO_SHIFT_CONTROL),
+ [7] = ACTION_MACRO_TAP(MACRO_CONTROL_ALT),
+
+};
+
+
+void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+}
+
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch (id) {
+
+ case MACRO_COPY_CUT:
+ if (record->event.pressed) {
+ register_code(KC_LCTL);
+ if (record->tap.count == 1) {
+ register_code(KC_C);
+ unregister_code(KC_C);
+ }
+ else if (record->tap.count == 2) {
+ register_code(KC_X);
+ unregister_code(KC_X);
+ }
+ unregister_code(KC_LCTL);
+ }
+ break;
+
+ case MACRO_SHIFT_CONTROL:
+ if (record->event.pressed) {
+ if (record->tap.count <= 2) register_mods(MOD_BIT(KC_LSFT));
+ if (record->tap.count == 2) register_mods(MOD_BIT(KC_LCTL));
+ if (record->tap.count == 3) register_code(KC_PENT);;
+ }
+ else {
+ unregister_mods(MOD_BIT(KC_LSFT) | MOD_BIT(KC_LCTL));
+ unregister_code(KC_PENT);
+ }
+ break;
+
+ case MACRO_CONTROL_ALT:
+ if (record->event.pressed) {
+ if (record->tap.count < 2) register_mods(MOD_BIT(KC_LCTL));
+ if (record->tap.count >= 2) register_mods(MOD_BIT(KC_LALT));
+ }
+ else {
+ unregister_mods(MOD_BIT(KC_LCTL) | MOD_BIT(KC_LALT));
+ }
+ break;
+ }
+
+ return MACRO_NONE;
+}
+
+void led_set_user(uint8_t usb_led)
+{
+ if (usb_led & (1<<USB_LED_CAPS_LOCK)) {
+ // output high
+ DDRD |= (1<<6);
+ PORTD |= (1<<6);
+ } else {
+ // Hi-Z
+ DDRD &= ~(1<<6);
+ PORTD &= ~(1<<6);
+ }
+ if (usb_led & (1<<USB_LED_NUM_LOCK)) {
+ // output low
+ DDRC |= (1<<7);
+ PORTC |= ~(1<<7);
+ } else {
+ // Hi-Z
+ DDRC &= ~(1<<7);
+ PORTC &= ~(1<<7);
+ }
+} \ No newline at end of file
diff --git a/keyboards/arrow_pad/readme.md b/keyboards/arrow_pad/readme.md
new file mode 100644
index 000000000..5aa44cce5
--- /dev/null
+++ b/keyboards/arrow_pad/readme.md
@@ -0,0 +1,24 @@
+arrow_pad keyboard firmware
+======================
+
+## Quantum MK Firmware
+
+For the full Quantum feature list, see [the parent readme.md](/readme.md).
+
+## Building
+
+Download or clone the whole firmware and navigate to the keyboards/arrow_pad folder. Once your dev env is setup, you'll be able to type `make` to generate your .hex - you can then use the Teensy Loader to program your .hex file.
+
+Depending on which keymap you would like to use, you will have to compile slightly differently.
+
+### Default
+To build with the default keymap, simply run `make`.
+
+### Other Keymaps
+Several version of keymap are available in advance but you are recommended to define your favorite layout yourself. To define your own keymap create file named `<name>.c` in the keymaps folder, and see keymap document (you can find in top readme.md) and existent keymap files.
+
+To build the firmware binary hex file with a keymap just do `make` with `KEYMAP` option like:
+```
+$ make KEYMAP=[default|jack|<name>]
+```
+Keymaps follow the format **__\<name\>.c__** and are stored in the `keymaps` folder. \ No newline at end of file
diff --git a/keyboards/atomic/Makefile b/keyboards/atomic/Makefile
new file mode 100644
index 000000000..08e9205cb
--- /dev/null
+++ b/keyboards/atomic/Makefile
@@ -0,0 +1,73 @@
+
+
+# MCU name
+#MCU = at90usb1287
+MCU = atmega32u4
+
+# Processor frequency.
+# This will define a symbol, F_CPU, in all source code files equal to the
+# processor frequency in Hz. You can then use this symbol in your source code to
+# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
+# automatically to create a 32-bit value in your source code.
+#
+# This will be an integer division of F_USB below, as it is sourced by
+# F_USB after it has run through any CPU prescalers. Note that this value
+# does not *change* the processor frequency - it should merely be updated to
+# reflect the processor speed set externally so that the code can use accurate
+# software delays.
+F_CPU = 16000000
+
+#
+# LUFA specific
+#
+# Target architecture (see library "Board Types" documentation).
+ARCH = AVR8
+
+# Input clock frequency.
+# This will define a symbol, F_USB, in all source code files equal to the
+# input clock frequency (before any prescaling is performed) in Hz. This value may
+# differ from F_CPU if prescaling is used on the latter, and is required as the
+# raw input clock is fed directly to the PLL sections of the AVR for high speed
+# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
+# at the end, this will be done automatically to create a 32-bit value in your
+# source code.
+#
+# If no clock division is performed on the input clock inside the AVR (via the
+# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
+F_USB = $(F_CPU)
+
+# Interrupt driven control endpoint task(+60)
+OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
+
+
+# Boot Section Size in *bytes*
+# Teensy halfKay 512
+# Teensy++ halfKay 1024
+# Atmel DFU loader 4096
+# LUFA bootloader 4096
+# USBaspLoader 2048
+OPT_DEFS += -DBOOTLOADER_SIZE=4096
+
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE ?= no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE ?= yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450)
+CONSOLE_ENABLE ?= no # Console for debug(+400)
+COMMAND_ENABLE ?= yes # Commands for debug and configuration
+NKRO_ENABLE ?= no # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE ?= yes # Enable keyboard backlight functionality
+MIDI_ENABLE ?= no # MIDI controls
+AUDIO_ENABLE ?= no # Audio output on port C6
+UNICODE_ENABLE ?= no # Unicode
+BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE ?= no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE ?= no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/atomic/atomic.c b/keyboards/atomic/atomic.c
new file mode 100644
index 000000000..6f393315e
--- /dev/null
+++ b/keyboards/atomic/atomic.c
@@ -0,0 +1,15 @@
+#include "atomic.h"
+
+void matrix_init_kb(void) {
+ // put your keyboard start-up code here
+ // runs once when the firmware starts up
+
+ MCUCR |= (1<<JTD);
+ MCUCR |= (1<<JTD);
+
+ // Turn status LED on
+ DDRE |= (1<<6);
+ PORTE |= (1<<6);
+
+ matrix_init_user();
+} \ No newline at end of file
diff --git a/keyboards/atomic/atomic.h b/keyboards/atomic/atomic.h
new file mode 100644
index 000000000..88e11fadf
--- /dev/null
+++ b/keyboards/atomic/atomic.h
@@ -0,0 +1,27 @@
+#ifndef ATOMIC_H
+#define ATOMIC_H
+
+#include "quantum.h"
+#include <stddef.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+
+// This a shortcut to help you visually see your layout.
+// The following is an example using the Planck MIT layout
+// The first section contains all of the arguements
+// The second converts the arguments into a two-dimensional array
+#define KEYMAP_SEMI_STANDARD( \
+ K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0E, \
+ K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, K1E, \
+ K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, K2D, K2E, \
+ K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3C, K3D, K3E, \
+ K40, K41, K43, K46, K4A, K4B, K4C, K4D, K4E \
+) { \
+ { K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, KC_NO, K0E }, \
+ { K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, K1E }, \
+ { K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, KC_NO, K2D, K2E }, \
+ { K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, KC_NO, K3C, K3D, K3E }, \
+ { K40, K41, KC_NO, K43, KC_NO, KC_NO, K46, KC_NO, KC_NO, KC_NO, K4A, K4B, K4C, K4D, K4E } \
+}
+
+#endif \ No newline at end of file
diff --git a/keyboards/atomic/config.h b/keyboards/atomic/config.h
new file mode 100644
index 000000000..9c40f54e7
--- /dev/null
+++ b/keyboards/atomic/config.h
@@ -0,0 +1,160 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "config_common.h"
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x6060
+#define DEVICE_VER 0x0001
+#define MANUFACTURER Ortholinear Keyboards
+#define PRODUCT The Atomic Keyboard
+#define DESCRIPTION A compact ortholinear keyboard
+
+/* key matrix size */
+#define MATRIX_ROWS 5
+#define MATRIX_COLS 15
+
+/*
+ * Keyboard Matrix Assignments
+ *
+ * Change this to how you wired your keyboard
+ * COLS: AVR pins used for columns, left to right
+ * ROWS: AVR pins used for rows, top to bottom
+ * DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode)
+ * ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode)
+ *
+*/
+#define MATRIX_ROW_PINS { D0, D5, B5, B6, C6 }
+#define MATRIX_COL_PINS { F1, F0, B0, C7, F4, F5, F6, F7, D4, D6, B4, D7, D3, D2, D1 }
+#define UNUSED_PINS
+
+#define BACKLIGHT_PIN B7
+
+/* COL2ROW or ROW2COL */
+#define DIODE_DIRECTION COL2ROW
+
+/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
+#define DEBOUNCING_DELAY 5
+
+/* define if matrix has ghost (lacks anti-ghosting diodes) */
+//#define MATRIX_HAS_GHOST
+
+/* number of backlight levels */
+#define BACKLIGHT_LEVELS 3
+
+/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
+#define LOCKING_SUPPORT_ENABLE
+/* Locking resynchronize hack */
+#define LOCKING_RESYNC_ENABLE
+
+/*
+ * Force NKRO
+ *
+ * Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved
+ * state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the
+ * makefile for this to work.)
+ *
+ * If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N)
+ * until the next keyboard reset.
+ *
+ * NKRO may prevent your keystrokes from being detected in the BIOS, but it is
+ * fully operational during normal computer usage.
+ *
+ * For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N)
+ * or via bootmagic (hold SPACE+N while plugging in the keyboard). Once set by
+ * bootmagic, NKRO mode will always be enabled until it is toggled again during a
+ * power-up.
+ *
+ */
+//#define FORCE_NKRO
+
+/*
+ * Magic Key Options
+ *
+ * Magic keys are hotkey commands that allow control over firmware functions of
+ * the keyboard. They are best used in combination with the HID Listen program,
+ * found here: https://www.pjrc.com/teensy/hid_listen.html
+ *
+ * The options below allow the magic key functionality to be changed. This is
+ * useful if your keyboard/keypad is missing keys and you want magic key support.
+ *
+ */
+
+/* key combination for magic key command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+/* control how magic key switches layers */
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS true
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS true
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM false
+
+/* override magic key keymap */
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM
+//#define MAGIC_KEY_HELP1 H
+//#define MAGIC_KEY_HELP2 SLASH
+//#define MAGIC_KEY_DEBUG D
+//#define MAGIC_KEY_DEBUG_MATRIX X
+//#define MAGIC_KEY_DEBUG_KBD K
+//#define MAGIC_KEY_DEBUG_MOUSE M
+//#define MAGIC_KEY_VERSION V
+//#define MAGIC_KEY_STATUS S
+//#define MAGIC_KEY_CONSOLE C
+//#define MAGIC_KEY_LAYER0_ALT1 ESC
+//#define MAGIC_KEY_LAYER0_ALT2 GRAVE
+//#define MAGIC_KEY_LAYER0 0
+//#define MAGIC_KEY_LAYER1 1
+//#define MAGIC_KEY_LAYER2 2
+//#define MAGIC_KEY_LAYER3 3
+//#define MAGIC_KEY_LAYER4 4
+//#define MAGIC_KEY_LAYER5 5
+//#define MAGIC_KEY_LAYER6 6
+//#define MAGIC_KEY_LAYER7 7
+//#define MAGIC_KEY_LAYER8 8
+//#define MAGIC_KEY_LAYER9 9
+#define MAGIC_KEY_BOOTLOADER B
+//#define MAGIC_KEY_LOCK CAPS
+//#define MAGIC_KEY_EEPROM E
+//#define MAGIC_KEY_NKRO N
+//#define MAGIC_KEY_SLEEP_LED Z
+
+/*
+ * Feature disable options
+ * These options are also useful to firmware size reduction.
+ */
+
+/* disable debug print */
+//#define NO_DEBUG
+
+/* disable print */
+//#define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+
+#endif
diff --git a/keyboards/atomic/keymaps/abienz.c b/keyboards/atomic/keymaps/abienz.c
new file mode 100644
index 000000000..589a64dc4
--- /dev/null
+++ b/keyboards/atomic/keymaps/abienz.c
@@ -0,0 +1,36 @@
+#include "atomic.h"
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ [0] = { /* Colemak */
+ { KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_NO },
+ { KC_TAB, CM_Q, CM_W, CM_F, CM_P, CM_G, CM_J, CM_L, CM_U, CM_Y, CM_SCLN, KC_LBRC, KC_RBRC, KC_BSLS, KC_DEL },
+ { KC_BSPC, CM_A, CM_R, CM_S, CM_T, CM_D, CM_H, CM_N, CM_E, CM_I, CM_O, KC_QUOT, KC_ENT, KC_NO, KC_PGUP },
+ { KC_LSFT, CM_Z, CM_X, CM_C, CM_V, CM_B, CM_K, CM_M, CM_COMM, CM_DOT, CM_SLSH, KC_RSFT, KC_NO, KC_UP, KC_PGDN },
+ { KC_LCTL, KC_LGUI, KC_NO, KC_LALT, FUNC(1), KC_SPC, KC_NO, KC_RALT, FUNC(2), KC_RGUI, KC_NO, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT },
+ },
+ [1] = { /* function */
+ { KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_BSPC, KC_NO },
+ { KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS },
+ { KC_TRNS, KC_TRNS, KC_TRNS, KC_SLEP, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS },
+ { KC_TRNS, KC_TRNS, KC_TRNS, KC_CALC, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_VOLU, KC_MPLY },
+ { KC_TRNS, KC_TRNS, KC_NO, KC_TRNS, FUNC(1), KC_TRNS, KC_NO, KC_TRNS, FUNC(2), KC_TRNS, KC_NO, KC_TRNS, KC_MPRV, KC_VOLD, KC_MNXT },
+ }
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_MOMENTARY(1),
+ [2] = ACTION_LAYER_MOMENTARY(1),
+
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ return MACRODOWN(TYPE(KC_T), END);
+ break;
+ }
+ return MACRO_NONE;
+};
+
diff --git a/keyboards/atomic/keymaps/default/keymap.c b/keyboards/atomic/keymaps/default/keymap.c
new file mode 100644
index 000000000..0ede363a1
--- /dev/null
+++ b/keyboards/atomic/keymaps/default/keymap.c
@@ -0,0 +1,234 @@
+#include "atomic.h"
+
+// Fillers to make layering more clear
+#define _______ KC_TRNS
+#define ___T___ KC_TRNS
+#define XXXXXXX KC_NO
+
+// Layer shorthand
+#define _QW 0
+#define _CM 1
+#define _DV 2
+#define _LW 3
+#define _RS 4
+#define _FN 5
+
+/* ROW 1 OPTIONS
+ * .--------------------------------------------------------------------------------------------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * '--------------------------------------------------------------------------------------------------------------------------------------'
+ * .- 2u ------------.
+ * | KEY . XXXXXX |
+ * '-----------------'
+ */
+
+/* ROW 2 OPTIONS
+ * .--------------------------------------------------------------------------------------------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * '--------------------------------------------------------------------------------------------------------------------------------------'
+ * .- 2u ------------. .- 2u ------------.
+ * | KEY . XXXXXX | | KEY . XXXXXX |
+ * '-----------------' '-----------------'
+ */
+
+/* ROW 3 OPTIONS
+ * .--------------------------------------------------------------------------------------------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * '--------------------------------------------------------------------------------------------------------------------------------------'
+ * .- 2u ------------. .- 2u ------------.
+ * | KEY . XXXXXX | | X |
+ * '-----------------' '-----------------'
+ * .- 2u ------------.
+ * | X |
+ * '-----------------'
+ */
+
+/* ROW 4 OPTIONS
+ * .--------------------------------------------------------------------------------------------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * '--------------------------------------------------------------------------------------------------------------------------------------'
+ * .- 2u ------------.
+ * | KEY . XXXXXX |
+ * '-----------------'
+ * .- 2u ------------. .- 2u ------------.
+ * | KEY . XXXXXX | | KEY . XXXXXX |
+ * '-----------------' '-----------------'
+ * .- 2u ------------.
+ * | KEY . XXXXXX |
+ * '-----------------'
+ */
+
+/* ROW 5 OPTIONS
+ * .--------------------------------------------------------------------------------------------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * '--------------------------------------------------------------------------------------------------------------------------------------'
+ * .- 1.25u --+ 1.25u ------- 1.25u +--- 1.25u --- 2u -------------- 1.25u ---- 1.25u ------ 1.25u +---- 1.25u .
+ * | X | X | X | X | X | X | X | X | X |
+ * '-----------------------------------------------------------------------------------------------------------'
+ * .- 2u ------------.
+ * | X |
+ * '-----------------'
+ * .--------------------- 6.25u ----------------------------.
+ * | X |
+ * '--------------------------------------------------------'
+ * .----------------------- 6.25u ---------------------------- 1.25u ---- 1.25u ---- 1.25u ------ 1.25u +-- 1.25u --.
+ * | X | X | X | X | X | X |
+ * '----------------------------------------------------------------------------------------------------------------'
+ */
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+
+/* QWERTY - MIT ENHANCED / GRID COMPATIBLE
+ * .---------------------------------------------------------------------------------------------------------------------- 2u ------------.
+ * | ` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | - | = | XXXXXX . BACKSP |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+-----------------|
+ * | TAB | Q | W | E | R | T | Y | U | I | O | P | [ | ] | \ | DEL |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+- 2u ------------+--------|
+ * | ESC | A | S | D | F | G | H | J | K | L | ; | ' | XXXXXX . ENTER | PG UP |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+- 2u ---------------------+--------|
+ * | LSHIFT | Z | X | C | V | B | N | M | , | . | / | XXXXXX . RSHIFT | UP | PG DN |
+ * |--------+--------+--------+--------+--------+- 2u ------------+--------+--------+--------+--------+-----------------+--------+--------|
+ * | BRITE | LCTRL | LALT | LGUI | RAISE | XXXXXX . SPACE | LOWER | RGUI | RALT | RCTRL | FN | LEFT | DOWN | RIGHT |
+ * '--------------------------------------------------------------------------------------------------------------------------------------'
+ */
+
+ [_QW] = { /* QWERTY */
+ { KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_BSPC },
+ { KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_DEL },
+ { KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_ENT, KC_PGUP },
+ { KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_RSFT, KC_UP, KC_PGDN },
+ { M(0), KC_LCTL, KC_LALT, KC_LGUI, MO(_RS), KC_SPC, KC_SPC, MO(_LW), KC_RGUI, KC_RALT, KC_RCTL, MO(_FN), KC_LEFT, KC_DOWN, KC_RGHT },
+ },
+
+/* COLEMAK - MIT ENHANCED / GRID COMPATIBLE
+ * .---------------------------------------------------------------------------------------------------------------------- 2u ------------.
+ * | ` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | - | = | XXXXXX . BACKSP |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+-----------------|
+ * | TAB | Q | W | F | P | G | J | L | U | Y | ; | [ | ] | \ | DEL |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+- 2u ------------+--------|
+ * | ESC | A | R | S | T | D | H | N | E | I | O | ' | XXXXXX . ENTER | PG UP |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+- 2u ---------------------+--------|
+ * | LSHIFT | Z | X | C | V | B | K | M | , | . | / | XXXXXX . RSHIFT | UP | PG DN |
+ * |--------+--------+--------+--------+--------+- 2u ------------+--------+--------+--------+--------+-----------------+--------+--------|
+ * | BRITE | LCTRL | LALT | LGUI | RAISE | XXXXXX . SPACE | LOWER | RGUI | RALT | RCTRL | FN | LEFT | DOWN | RIGHT |
+ * '--------------------------------------------------------------------------------------------------------------------------------------'
+ */
+
+ [_CM] = { /* COLEMAK */
+ { KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_BSPC },
+ { KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_LBRC, KC_RBRC, KC_BSLS, KC_DEL },
+ { KC_ESC, KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT, KC_ENT, KC_ENT, KC_PGUP },
+ { KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_K, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_RSFT, KC_UP, KC_PGDN },
+ { M(0), KC_LCTL, KC_LALT, KC_LGUI, MO(_RS), KC_SPC, KC_SPC, MO(_LW), KC_RGUI, KC_RALT, KC_RCTL, MO(_FN), KC_LEFT, KC_DOWN, KC_RGHT },
+ },
+
+/* DVORAK - MIT ENHANCED / GRID COMPATIBLE
+ * .---------------------------------------------------------------------------------------------------------------------- 2u ------------.
+ * | ` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | - | = | XXXXXX . BACKSP |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+-----------------|
+ * | TAB | ' | , | . | P | Y | F | G | C | R | L | [ | ] | \ | DEL |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+- 2u ------------+--------|
+ * | ESC | A | O | E | U | I | D | H | T | N | S | / | XXXXXX . ENTER | PG UP |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+- 2u ---------------------+--------|
+ * | LSHIFT | ; | Q | J | K | X | B | M | W | V | Z | XXXXXX . RSHIFT | UP | PG DN |
+ * |--------+--------+--------+--------+--------+- 2u ------------+--------+--------+--------+--------+-----------------+--------+--------|
+ * | BRITE | LCTRL | LALT | LGUI | RAISE | XXXXXX . SPACE | LOWER | RGUI | RALT | RCTRL | FN | LEFT | DOWN | RIGHT |
+ * '--------------------------------------------------------------------------------------------------------------------------------------'
+ */
+
+ [_DV] = { /* DVORAK */
+ { KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_BSPC },
+ { KC_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, KC_F, KC_G, KC_C, KC_R, KC_L, KC_LBRC, KC_RBRC, KC_BSLS, KC_DEL },
+ { KC_ESC, KC_A, KC_O, KC_E, KC_U, KC_I, KC_D, KC_H, KC_T, KC_N, KC_S, KC_SLSH, KC_ENT, KC_ENT, KC_PGUP },
+ { KC_LSFT, KC_SCLN, KC_Q, KC_J, KC_K, KC_X, KC_B, KC_M, KC_W, KC_V, KC_Z, KC_RSFT, KC_RSFT, KC_UP, KC_PGDN },
+ { M(0), KC_LCTL, KC_LALT, KC_LGUI, MO(_RS), KC_SPC, KC_SPC, MO(_LW), KC_RGUI, KC_RALT, KC_RCTL, MO(_FN), KC_LEFT, KC_DOWN, KC_RGHT },
+ },
+
+/* LOWERED
+ * .---------------------------------------------------------------------------------------------------------------------- 2u ------------.
+ * | | F1 | F2 | F3 | F4 | F5 | F6 | F7 | F8 | F9 | F10 | F11 | F12 | XXXXXX . |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+-----------------|
+ * | | ! | @ | # | $ | % | ^ | & | * | ( | ) | | | | INS |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+- 2u ------------+--------|
+ * | | F1 | F2 | F3 | F4 | F5 | F6 | _ | + | { | } | | | XXXXXX . | |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+- 2u ---------------------+--------|
+ * | | F7 | F8 | F9 | F10 | F11 | F12 | | | | | XXXXXX . | | |
+ * |--------+--------+--------+--------+--------+- 2u ------------+--------+--------+--------+--------+-----------------+--------+--------|
+ * | | | | | | XXXXXX . | | | | | | | | |
+ * '--------------------------------------------------------------------------------------------------------------------------------------'
+ */
+
+ [_LW] = { /* LOWERED */
+ { _______, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, ___T___, ___T___ },
+ { _______, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, _______, _______, _______, KC_INS },
+ { _______, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE, ___T___, ___T___, _______ },
+ { _______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______, _______, _______, _______, ___T___, ___T___, _______, _______ },
+ { _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ },
+ },
+
+/* RAISED
+ * .---------------------------------------------------------------------------------------------------------------------- 2u ------------.
+ * | | F1 | F2 | F3 | F4 | F5 | F6 | F7 | F8 | F9 | F10 | F11 | F12 | XXXXXX . |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+-----------------|
+ * | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | | | | INS |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+- 2u ------------+--------|
+ * | | F1 | F2 | F3 | F4 | F5 | F6 | - | = | [ | ] | \ | XXXXXX . | |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+- 2u ---------------------+--------|
+ * | | F7 | F8 | F9 | F10 | F11 | F12 | | | | | XXXXXX . | | |
+ * |--------+--------+--------+--------+--------+- 2u ------------+--------+--------+--------+--------+-----------------+--------+--------|
+ * | | | | | | XXXXXX . | | | | | | | | |
+ * '--------------------------------------------------------------------------------------------------------------------------------------'
+ */
+
+ [_RS] = { /* RAISED */
+ { _______, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, ___T___, ___T___ },
+ { _______, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, _______, _______, _______, KC_INS },
+ { _______, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS, ___T___, ___T___, _______ },
+ { _______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______, _______, _______, _______, ___T___, ___T___, _______, _______ },
+ { _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ },
+ },
+
+/* FUNCTION
+ * .---------------------------------------------------------------------------------------------------------------------- 2u ------------.
+ * | NUM LK | F1 | F2 | F3 | F4 | F5 | F6 | F7 | F8 | F9 | F10 | F11 | F12 | XXXXXX . |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+-----------------|
+ * | SCR LK | F13 | F14 | F15 | F16 | F17 | F18 | F19 | F20 | F21 | F22 | F23 | F24 | PAUSE | PR SCR |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+- 2u ------------+--------|
+ * | CAP LK | MS BT5 | MS BT4 | MS BT3 | MS BT2 | SLOW M | FAST M | NEXT | VOL+ | VOL- | PLAY | | XXXXXX . | WHEEL+ |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+- 2u ---------------------+--------|
+ * | | | QWERTY | COLEMK | DVORAK | | | | | | | XXXXXX . | MOUS U | WHEEL- |
+ * |--------+--------+--------+--------+--------+- 2u ------------+--------+--------+--------+--------+-----------------+--------+--------|
+ * | | | | | | XXXXXX . MS BT1 | | | | | | MOUS L | MOUS D | MOUS R |
+ * '--------------------------------------------------------------------------------------------------------------------------------------'
+ */
+
+ [_FN] = { /* FUNCTION */
+ { KC_NLCK, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, ___T___, ___T___ },
+ { KC_SLCK, KC_F13, KC_F14, KC_F15, KC_F16, KC_F17, KC_F18, KC_F19, KC_F20, KC_F21, KC_F22, KC_F23, KC_F24, KC_PAUS, KC_PSCR },
+ { KC_CAPS, KC_BTN5, KC_BTN4, KC_BTN3, KC_BTN2, KC_ACL0, KC_ACL2, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY, _______, ___T___, ___T___, KC_WH_U },
+ { _______, _______, DF(_QW), DF(_CM), DF(_DV), _______, _______, _______, _______, _______, _______, ___T___, ___T___, KC_MS_U, KC_WH_D },
+ { _______, _______, _______, _______, _______, KC_BTN1, KC_BTN1, _______, _______, _______, _______, _______, KC_MS_L, KC_MS_D, KC_MS_R },
+ },
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ #ifdef BACKLIGHT_ENABLE
+ backlight_step();
+ #endif
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
diff --git a/keyboards/atomic/keymaps/michelle.c b/keyboards/atomic/keymaps/michelle.c
new file mode 100644
index 000000000..2364c46a1
--- /dev/null
+++ b/keyboards/atomic/keymaps/michelle.c
@@ -0,0 +1,183 @@
+#include "atomic.h"
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ [0] = { /* Dvorak */
+ { KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_LBRC, KC_RBRC, KC_BSPC, KC_NO },
+// ┌────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐
+// │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
+// └────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘
+// ┌─ 2u ────────────┐
+// │ X │
+// └─────────────────┘
+ { KC_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, KC_F, KC_G, KC_C, KC_R, KC_L, KC_SLSH, KC_EQL, KC_INS, KC_DEL },
+// ┌────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐
+// │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
+// └────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘
+// ┌─ 2u ────────────┐ ┌─ 2u ────────────┐
+// │ X │ │ X │
+// └─────────────────┘ └─────────────────┘
+ { KC_CAPS, KC_A, KC_O, KC_E, KC_U, KC_I, KC_D, KC_H, KC_T, KC_N, KC_S, KC_MINS, KC_ENT, KC_NO, KC_PGUP },
+// ┌────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐
+// │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
+// └────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘
+// ┌─ 2u ────────────┐ ┌─ 2u ────────────┐
+// │ X │ │ X │
+// └─────────────────┘ └─────────────────┘
+// ┌─ 2u ────────────┐
+// │ X │
+// └─────────────────┘
+ { KC_LSFT, KC_SCLN, KC_Q, KC_J, KC_K, KC_X, KC_B, KC_M, KC_W, KC_V, KC_Z, KC_RSFT, KC_NO, KC_UP, KC_PGDN },
+// ┌────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐
+// │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
+// └────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘
+// ┌─ 2u ────────────┐
+// │ X │
+// └─────────────────┘
+// ┌─ 2u ────────────┐ ┌─ 2u ────────────┐
+// │ X │ │ X │
+// └─────────────────┘ └─────────────────┘
+// ┌─ 2u ────────────┐
+// │ X │
+// └─────────────────┘
+ { KC_LCTL, MO(1), KC_NO, KC_LALT, KC_NO, KC_NO, KC_SPC, KC_NO, KC_NO, KC_NO, KC_LGUI, MO(2), KC_LEFT, KC_DOWN, KC_RGHT },
+// ┌────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐
+// │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
+// └────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘
+// ┌─ 1.25u ──┬ 1.25u ───┬─── 1.25u ┬─── 1.25u ─┬─ 2u ────────────┬─ 1.25u ──┬─ 1.25u ──┬─── 1.25u ┬──── 1.25u ┐
+// │ X │ X │ X │ X │ X │ X │ X │ X │ X │
+// └──────────┴──────────┴──────────┴───────────┴─────────────────┴──────────┴──────────┴──────────┴───────────┘
+// ┌─ 2u ────────────┐
+// │ X │
+// └─────────────────┘
+// ┌───────────────────── 6.25u ────────────────────────────┐
+// │ X │
+// └────────────────────────────────────────────────────────┘
+// ┌─────────────────────── 6.25u ──────────────────────────┬─ 1.25u ──┬─ 1.25u ──┬─ 1.25u ──┬─── 1.25u ┬── 1.25u ──┐
+// │ X │ X │ X │ X │ X │ X │
+// └────────────────────────────────────────────────────────┴──────────┴──────────┴──────────┴──────────┴───────────┘
+ },
+ [1] = { /* Qwerty + F keys */
+ { KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_BSPC, KC_NO },
+// ┌────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐
+// │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
+// └────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘
+// ┌─ 2u ────────────┐
+// │ X │
+// └─────────────────┘
+ { KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_INS, KC_DEL },
+// ┌────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐
+// │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
+// └────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘
+// ┌─ 2u ────────────┐ ┌─ 2u ────────────┐
+// │ X │ │ X │
+// └─────────────────┘ └─────────────────┘
+ { KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_NO, KC_PGUP },
+// ┌────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐
+// │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
+// └────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘
+// ┌─ 2u ────────────┐ ┌─ 2u ────────────┐
+// │ X │ │ X │
+// └─────────────────┘ └─────────────────┘
+// ┌─ 2u ────────────┐
+// │ X │
+// └─────────────────┘
+ { KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_NO, KC_UP, KC_PGDN },
+// ┌────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐
+// │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
+// └────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘
+// ┌─ 2u ────────────┐
+// │ X │
+// └─────────────────┘
+// ┌─ 2u ────────────┐ ┌─ 2u ────────────┐
+// │ X │ │ X │
+// └─────────────────┘ └─────────────────┘
+// ┌─ 2u ────────────┐
+// │ X │
+// └─────────────────┘
+ { KC_LCTL, KC_TRNS, KC_NO, KC_LALT, KC_NO, KC_NO, KC_SPC, KC_NO, KC_NO, KC_NO, KC_LGUI, KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT },
+// ┌────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐
+// │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
+// └────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘
+// ┌─ 1.25u ──┬ 1.25u ───┬─── 1.25u ┬─── 1.25u ─┬─ 2u ────────────┬─ 1.25u ──┬─ 1.25u ──┬─── 1.25u ┬──── 1.25u ┐
+// │ X │ X │ X │ X │ X │ X │ X │ X │ X │
+// └──────────┴──────────┴──────────┴───────────┴─────────────────┴──────────┴──────────┴──────────┴───────────┘
+// ┌─ 2u ────────────┐
+// │ X │
+// └─────────────────┘
+// ┌───────────────────── 6.25u ────────────────────────────┐
+// │ X │
+// └────────────────────────────────────────────────────────┘
+// ┌─────────────────────── 6.25u ──────────────────────────┬─ 1.25u ──┬─ 1.25u ──┬─ 1.25u ──┬─── 1.25u ┬── 1.25u ──┐
+// │ X │ X │ X │ X │ X │ X │
+// └────────────────────────────────────────────────────────┴──────────┴──────────┴──────────┴──────────┴───────────┘
+ },
+ [2] = { /* Numpad + qwerty shortcut keys */
+ { KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_P7, KC_P8, KC_P9, KC_0, KC_LBRC, KC_RBRC, KC_BSPC, KC_NO },
+// ┌────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐
+// │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
+// └────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘
+// ┌─ 2u ────────────┐
+// │ X │
+// └─────────────────┘
+ { KC_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, KC_F, KC_P4, KC_P5, KC_P6, KC_L, KC_SLSH, KC_EQL, KC_INS, KC_DEL },
+// ┌────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐
+// │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
+// └────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘
+// ┌─ 2u ────────────┐ ┌─ 2u ────────────┐
+// │ X │ │ X │
+// └─────────────────┘ └─────────────────┘
+ { KC_CAPS, KC_A, KC_O, KC_E, KC_U, KC_I, KC_D, KC_P1, KC_P2, KC_P3, KC_S, KC_MINS, KC_ENT, KC_NO, KC_PGUP },
+// ┌────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐
+// │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
+// └────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘
+// ┌─ 2u ────────────┐ ┌─ 2u ────────────┐
+// │ X │ │ X │
+// └─────────────────┘ └─────────────────┘
+// ┌─ 2u ────────────┐
+// │ X │
+// └─────────────────┘
+ { KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_X, KC_B, KC_P0, KC_P0, KC_PENT, KC_Z, KC_RSFT, KC_NO, KC_UP, KC_PGDN },
+// ┌────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐
+// │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
+// └────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘
+// ┌─ 2u ────────────┐
+// │ X │
+// └─────────────────┘
+// ┌─ 2u ────────────┐ ┌─ 2u ────────────┐
+// │ X │ │ X │
+// └─────────────────┘ └─────────────────┘
+// ┌─ 2u ────────────┐
+// │ X │
+// └─────────────────┘
+ { KC_LCTL, KC_TRNS, KC_NO, KC_LALT, KC_NO, KC_NO, KC_SPC, KC_NO, KC_NO, KC_NO, KC_LGUI, KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT },
+// ┌────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐
+// │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
+// └────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘
+// ┌─ 1.25u ──┬ 1.25u ───┬─── 1.25u ┬─── 1.25u ─┬─ 2u ────────────┬─ 1.25u ──┬─ 1.25u ──┬─── 1.25u ┬──── 1.25u ┐
+// │ X │ X │ X │ X │ X │ X │ X │ X │ X │
+// └──────────┴──────────┴──────────┴───────────┴─────────────────┴──────────┴──────────┴──────────┴───────────┘
+// ┌─ 2u ────────────┐
+// │ X │
+// └─────────────────┘
+// ┌───────────────────── 6.25u ────────────────────────────┐
+// │ X │
+// └────────────────────────────────────────────────────────┘
+// ┌─────────────────────── 6.25u ──────────────────────────┬─ 1.25u ──┬─ 1.25u ──┬─ 1.25u ──┬─── 1.25u ┬── 1.25u ──┐
+// │ X │ X │ X │ X │ X │ X │
+// └────────────────────────────────────────────────────────┴──────────┴──────────┴──────────┴──────────┴───────────┘
+ },
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ return MACRODOWN(TYPE(KC_T), END);
+ break;
+ }
+ return MACRO_NONE;
+};
diff --git a/keyboards/atomic/keymaps/pvc/Makefile b/keyboards/atomic/keymaps/pvc/Makefile
new file mode 100644
index 000000000..278407e6c
--- /dev/null
+++ b/keyboards/atomic/keymaps/pvc/Makefile
@@ -0,0 +1,15 @@
+BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = yes # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend \ No newline at end of file
diff --git a/keyboards/atomic/keymaps/pvc/config.h b/keyboards/atomic/keymaps/pvc/config.h
new file mode 100644
index 000000000..70353323b
--- /dev/null
+++ b/keyboards/atomic/keymaps/pvc/config.h
@@ -0,0 +1,169 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "config_common.h"
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x0419
+#define DEVICE_VER 0x0001
+#define MANUFACTURER Ortholinear Keyboards
+#define PRODUCT The Atomic Keyboard
+#define DESCRIPTION A compact ortholinear keyboard
+
+/* key matrix size */
+#define MATRIX_ROWS 5
+#define MATRIX_COLS 15
+
+/*
+ * Keyboard Matrix Assignments
+ *
+ * Change this to how you wired your keyboard
+ * COLS: AVR pins used for columns, left to right
+ * ROWS: AVR pins used for rows, top to bottom
+ * DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode)
+ * ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode)
+ *
+*/
+#define MATRIX_ROW_PINS { D0, D5, B5, B6, B3 }
+#define MATRIX_COL_PINS { F1, F0, B0, C7, F4, F5, F6, F7, D4, D6, B4, D7, D3, D2, D1 }
+#define UNUSED_PINS
+
+#define BACKLIGHT_PIN B7
+#define BACKLIGHT_BREATHING
+
+/* COL2ROW or ROW2COL */
+#define DIODE_DIRECTION COL2ROW
+
+/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
+#define DEBOUNCING_DELAY 5
+
+/* define if matrix has ghost (lacks anti-ghosting diodes) */
+//#define MATRIX_HAS_GHOST
+
+/* number of backlight levels */
+#define BACKLIGHT_LEVELS 3
+
+/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
+#define LOCKING_SUPPORT_ENABLE
+/* Locking resynchronize hack */
+#define LOCKING_RESYNC_ENABLE
+
+// Enable Keyboard Locking via magic key
+#define KEYBOARD_LOCK_ENABLE
+
+
+/*
+ * Force NKRO
+ *
+ * Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved
+ * state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the
+ * makefile for this to work.)
+ *
+ * If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N)
+ * until the next keyboard reset.
+ *
+ * NKRO may prevent your keystrokes from being detected in the BIOS, but it is
+ * fully operational during normal computer usage.
+ *
+ * For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N)
+ * or via bootmagic (hold SPACE+N while plugging in the keyboard). Once set by
+ * bootmagic, NKRO mode will always be enabled until it is toggled again during a
+ * power-up.
+ *
+ */
+//#define FORCE_NKRO
+
+/*
+ * Magic Key Options
+ *
+ * Magic keys are hotkey commands that allow control over firmware functions of
+ * the keyboard. They are best used in combination with the HID Listen program,
+ * found here: https://www.pjrc.com/teensy/hid_listen.html
+ *
+ * The options below allow the magic key functionality to be changed. This is
+ * useful if your keyboard/keypad is missing keys and you want magic key support.
+ *
+ */
+
+/* key combination for magic key command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+/* control how magic key switches layers */
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS true
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS true
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM false
+
+/* override magic key keymap */
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM
+//#define MAGIC_KEY_HELP1 H
+//#define MAGIC_KEY_HELP2 SLASH
+//#define MAGIC_KEY_DEBUG D
+//#define MAGIC_KEY_DEBUG_MATRIX X
+//#define MAGIC_KEY_DEBUG_KBD K
+//#define MAGIC_KEY_DEBUG_MOUSE M
+//#define MAGIC_KEY_VERSION V
+//#define MAGIC_KEY_STATUS S
+//#define MAGIC_KEY_CONSOLE C
+//#define MAGIC_KEY_LAYER0_ALT1 ESC
+//#define MAGIC_KEY_LAYER0_ALT2 GRAVE
+//#define MAGIC_KEY_LAYER0 0
+//#define MAGIC_KEY_LAYER1 1
+//#define MAGIC_KEY_LAYER2 2
+//#define MAGIC_KEY_LAYER3 3
+//#define MAGIC_KEY_LAYER4 4
+//#define MAGIC_KEY_LAYER5 5
+//#define MAGIC_KEY_LAYER6 6
+//#define MAGIC_KEY_LAYER7 7
+//#define MAGIC_KEY_LAYER8 8
+//#define MAGIC_KEY_LAYER9 9
+#define MAGIC_KEY_BOOTLOADER B
+//#define MAGIC_KEY_LOCK CAPS
+//#define MAGIC_KEY_EEPROM E
+//#define MAGIC_KEY_NKRO N
+//#define MAGIC_KEY_SLEEP_LED Z
+
+/*
+ * Feature disable options
+ * These options are also useful to firmware size reduction.
+ */
+
+/* disable debug print */
+//#define NO_DEBUG
+
+/* disable print */
+//#define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+
+
+//#define VIBRATO_ENABLE
+//#define VIBRATO_STRENGTH_ENABLE
+
+#endif
diff --git a/keyboards/atomic/keymaps/pvc/keymap.c b/keyboards/atomic/keymaps/pvc/keymap.c
new file mode 100644
index 000000000..f16ec8a6e
--- /dev/null
+++ b/keyboards/atomic/keymaps/pvc/keymap.c
@@ -0,0 +1,578 @@
+#include "atomic.h"
+#include "action_layer.h"
+#include "eeconfig.h"
+#include "led.h"
+
+#ifdef AUDIO_ENABLE
+ #include "audio.h"
+ #include "song_list.h"
+#endif
+
+#define LAYER_QWERTY 0
+#define LAYER_COLEMAK 1
+#define LAYER_DVORAK 2
+#define LAYER_UPPER 3
+#define LAYER_LOWER 4
+#define LAYER_FUNCTION 5
+#define LAYER_MOUSE 6
+#define LAYER_ADJUST 7
+
+#define MACRO_QWERTY 0
+#define MACRO_COLEMAK 1
+#define MACRO_DVORAK 2
+#define MACRO_UPPER 3
+#define MACRO_LOWER 4
+#define MACRO_FUNCTION 5
+#define MACRO_MOUSE 6
+#define MACRO_TIMBRE_1 7
+#define MACRO_TIMBRE_2 8
+#define MACRO_TIMBRE_3 9
+#define MACRO_TIMBRE_4 10
+#define MACRO_TEMPO_U 11
+#define MACRO_TEMPO_D 12
+#define MACRO_TONE_DEFAULT 13
+#define MACRO_MUSIC_TOGGLE 14
+#define MACRO_AUDIO_TOGGLE 16
+#define MACRO_INC_VOICE 18
+#define MACRO_DEC_VOICE 19
+#define MACRO_BACKLIGHT 20
+#define MACRO_BREATH_TOGGLE 21
+#define MACRO_BREATH_SPEED_INC 23
+#define MACRO_BREATH_SPEED_DEC 24
+#define MACRO_BREATH_DEFAULT 25
+
+#define M_QWRTY M(MACRO_QWERTY)
+#define M_COLMK M(MACRO_COLEMAK)
+#define M_DVORK M(MACRO_DVORAK)
+#define M_UPPER M(MACRO_UPPER)
+#define M_LOWER M(MACRO_LOWER)
+#define M_FUNCT M(MACRO_FUNCTION)
+#define M_MOUSE M(MACRO_MOUSE)
+#define TIMBR_1 M(MACRO_TIMBRE_1)
+#define TIMBR_2 M(MACRO_TIMBRE_2)
+#define TIMBR_3 M(MACRO_TIMBRE_3)
+#define TIMBR_4 M(MACRO_TIMBRE_4)
+#define TMPO_UP M(MACRO_TEMPO_U)
+#define TMPO_DN M(MACRO_TEMPO_D)
+#define TMPO_DF M(MACRO_TONE_DEFAULT)
+#define M_BACKL M(MACRO_BACKLIGHT)
+#define M_BRTOG M(MACRO_BREATH_TOGGLE)
+#define M_BSPDU M(MACRO_BREATH_SPEED_INC)
+#define M_BSPDD M(MACRO_BREATH_SPEED_DEC)
+#define M_BDFLT M(MACRO_BREATH_DEFAULT)
+
+
+#define VC_UP M(MACRO_INC_VOICE)
+#define VC_DOWN M(MACRO_DEC_VOICE)
+
+
+#define SC_UNDO LCTL(KC_Z)
+#define SC_REDO LCTL(KC_Y)
+#define SC_CUT LCTL(KC_X)
+#define SC_COPY LCTL(KC_C)
+#define SC_PSTE LCTL(KC_V)
+#define SC_SELA LCTL(KC_A)
+#define SC_SAVE LCTL(KC_S)
+#define SC_OPEN LCTL(KC_O)
+#define SC_ACLS LALT(KC_F4)
+#define SC_CCLS LCTL(KC_F4)
+
+#define OS_SHFT KC_FN0
+
+#define _______ KC_TRNS
+#define XXXXXXX KC_NO
+#define ________________ _______, _______
+#define XXXXXXXXXXXXXXXX XXXXXXX, XXXXXXX
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+
+/* QWERTY
+ * .---------------------------------------------------------------------------------------------------------------------- 2u ------------.
+ * | ESC | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | - | = | XXXXXX . BACKSP |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+-----------------|
+ * | TAB | Q | W | E | R | T | Y | U | I | O | P | [ | ] | \ | DEL |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+- 2u ------------+--------|
+ * | CAPS | A | S | D | F | G | H | J | K | L | ; | ' | XXXXXX . ENTER | PG UP |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+- 2u ---------------------+--------|
+ * | LSHIFT | Z | X | C | V | B | N | M | , | . | / | XXXXXX . RSHIFT | UP | PG DN |
+ * |--------+--------+--------+--------+--------+- 2u ------------+--------+--------+--------+--------+-----------------+--------+--------|
+ * | LCTRL | LWIN | FN | LALT | UPPER | XXXXXX . SPACE | LOWER | SHIFT | RALT | APP | RCTRL | LEFT | DOWN | RIGHT |
+ * '--------------------------------------------------------------------------------------------------------------------------------------'
+ */
+
+ [LAYER_QWERTY] = { // QWERTY
+ { KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_BSPC },
+ { KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_DEL },
+ { KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_ENT, KC_PGUP },
+ { KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_RSFT, KC_UP, KC_PGDN },
+ { KC_LCTL, KC_LGUI, M_FUNCT, KC_LALT, M_UPPER, KC_SPC, KC_SPC, M_LOWER, OS_SHFT, KC_RALT, KC_APP, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT },
+ },
+
+ /* COLEMAK
+ * .---------------------------------------------------------------------------------------------------------------------- 2u ------------.
+ * | ESC | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | - | = | XXXXXX . BACKSP |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+-----------------|
+ * | TAB | Q | W | F | P | G | J | L | U | Y | ; | [ | ] | \ | DEL |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+- 2u ------------+--------|
+ * | BACKSP | A | R | S | T | D | H | N | E | I | O | ' | XXXXXX . ENTER | PG UP |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+- 2u ---------------------+--------|
+ * | LSHIFT | Z | X | C | V | B | K | M | , | . | / | XXXXXX . RSHIFT | UP | PG DN |
+ * |--------+--------+--------+--------+--------+- 2u ------------+--------+--------+--------+--------+-----------------+--------+--------|
+ * | LCTRL | LWIN | FN | LALT | UPPER | XXXXXX . SPACE | LOWER | SHIFT | RALT | APP | RCTRL | LEFT | DOWN | RIGHT |
+ * '--------------------------------------------------------------------------------------------------------------------------------------'
+ */
+
+ [LAYER_COLEMAK] = { // COLEMAK
+ { KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_BSPC },
+ { KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_LBRC, KC_RBRC, KC_BSLS, KC_DEL },
+ { KC_BSPC, KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT, KC_ENT, KC_ENT, KC_PGUP },
+ { KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_K, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_RSFT, KC_UP, KC_PGDN },
+ { KC_LCTL, KC_LGUI, M_FUNCT, KC_LALT, M_UPPER, KC_SPC, KC_SPC, M_LOWER, OS_SHFT, KC_RALT, KC_APP, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT },
+},
+
+/* DVORAK
+ * .---------------------------------------------------------------------------------------------------------------------- 2u ------------.
+ * | ESC | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | [ | ] | XXXXXX . BACKSP |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+-----------------|
+ * | TAB | ' | , | . | P | Y | F | G | C | R | L | / | = | \ | DEL |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+- 2u ------------+--------|
+ * | CAPS | A | O | E | U | I | D | H | T | N | S | - | XXXXXX . ENTER | PG UP |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+- 2u ---------------------+--------|
+ * | LSHIFT | ; | Q | J | K | X | B | M | W | V | Z | XXXXXX . RSHIFT | UP | PG DN |
+ * |--------+--------+--------+--------+--------+- 2u ------------+--------+--------+--------+--------+-----------------+--------+--------|
+ * | LCTRL | LWIN | FN | LALT | UPPER | XXXXXX . SPACE | LOWER | SHIFT | RALT | APP | RCTRL | LEFT | DOWN | RIGHT |
+ * '--------------------------------------------------------------------------------------------------------------------------------------'
+ */
+
+ [LAYER_DVORAK] = { // DVORAK
+ { KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_LBRC, KC_RBRC, KC_BSPC, KC_BSPC },
+ { KC_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, KC_F, KC_G, KC_C, KC_R, KC_L, KC_SLSH, KC_EQL, KC_BSLS, KC_DEL },
+ { KC_CAPS, KC_A, KC_O, KC_E, KC_U, KC_I, KC_D, KC_H, KC_T, KC_N, KC_S, KC_MINS, KC_ENT, KC_ENT, KC_PGUP },
+ { KC_LSFT, KC_SCLN, KC_Q, KC_J, KC_K, KC_X, KC_B, KC_M, KC_W, KC_V, KC_Z, KC_RSFT, KC_RSFT, KC_UP, KC_PGDN },
+ { KC_LCTL, KC_LGUI, M_FUNCT, KC_LALT, M_UPPER, KC_SPC, KC_SPC, M_LOWER, OS_SHFT, KC_RALT, KC_APP, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT },
+ },
+
+/* UPPER
+ * .---------------------------------------------------------------------------------------------------------------------- 2u ------------.
+ * | PRINT | XXXXXX | XXXXXX | XXXXXX | XXXXXX | XXXXXX | XXXXXX | NUM LK | / | * | | NUM LK | SCR LK | XXXXXX . PAUSE |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+-----------------|
+ * | | F1 | F2 | F3 | F4 | | | 7 | 8 | 9 | - | | | | INS |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+- 2u ------------+--------|
+ * | CAP LK | F5 | F6 | F7 | F8 | | | 4 | 5 | 6 | + | | XXXXXX . | HOME |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+- 2u ---------------------+--------|
+ * | | F9 | F10 | F11 | F12 | | | 1 | 2 | 3 | ENTER | XXXXXX . | | END |
+ * |--------+--------+--------+--------+--------+- 2u ------------+--------+--------+--------+--------+-----------------+--------+--------|
+ * | | | | | | 0 | | RALT | . | ENTER | | | | |
+ * '--------------------------------------------------------------------------------------------------------------------------------------'
+ */
+
+ [LAYER_UPPER] = { // UPPER
+ { KC_PSCR, M_BRTOG, M_BSPDU, M_BSPDD, M_BDFLT, XXXXXXX, XXXXXXX, KC_NLCK, KC_PSLS, KC_PAST, XXXXXXX, XXXXXXX, KC_SLCK, KC_PAUS, KC_PAUS },
+ { _______, KC_F1, KC_F2, KC_F3, KC_F4, XXXXXXX, XXXXXXX, KC_KP_7, KC_KP_8, KC_KP_9, KC_PMNS, _______, _______, _______, KC_INS },
+ { KC_CAPS, KC_F5, KC_F6, KC_F7, KC_F8, XXXXXXX, XXXXXXX, KC_KP_4, KC_KP_5, KC_KP_6, KC_PPLS, _______, ________________, KC_HOME },
+ { _______, KC_F9, KC_F10, KC_F11, KC_F12, XXXXXXX, XXXXXXX, KC_KP_1, KC_KP_2, KC_KP_3, KC_PENT, ________________, _______, KC_END },
+ { _______, _______, _______, _______, _______, KC_KP_0, KC_KP_0, _______, KC_RALT, KC_PDOT, KC_PENT, _______, _______, _______, _______ },
+ },
+
+/* LOWER
+ * .---------------------------------------------------------------------------------------------------------------------- 2u ------------.
+ * | | F1 | F2 | F3 | F4 | F5 | F6 | F7 | F8 | F9 | F10 | F11 | F12 | XXXXXX . BACKSP |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+-----------------|
+ * | | $ | { | [ | ( | % | # | ) | ] | } | @ | | | | INS |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+- 2u ------------+--------|
+ * | | ^ | * | + | - | ; | : | _ | ' | " | ` | | XXXXXX . | HOME |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+- 2u ---------------------+--------|
+ * | | | | & | ! | ~ | / | \ | = | < | > | ? | XXXXXX . | | END |
+ * |--------+--------+--------+--------+--------+- 2u ------------+--------+--------+--------+--------+-----------------+--------+--------|
+ * | | | | | | | | | | | | | | |
+ * '--------------------------------------------------------------------------------------------------------------------------------------'
+ */
+
+ [LAYER_LOWER] = { // LOWER
+ { _______, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, ________________ },
+ { _______, KC_DLR, KC_LCBR, KC_LBRC, KC_LPRN, KC_PERC, KC_HASH, KC_RPRN, KC_RBRC, KC_RCBR, KC_AT, _______, _______, _______, KC_INS },
+ { _______, KC_CIRC, KC_ASTR, KC_PPLS, KC_PMNS, KC_SCLN, KC_COLN, KC_UNDS, KC_QUOT, KC_DQT, KC_GRV, _______, ________________, KC_HOME },
+ { _______, KC_PIPE, KC_AMPR, KC_EXLM, KC_TILD, KC_SLSH, KC_BSLS, KC_EQL, KC_LT, KC_GT, KC_QUES, ________________, _______, KC_END },
+ { _______, _______, _______, _______, _______, ________________, _______, _______, _______, _______, _______, _______, _______, _______ },
+ },
+
+ [LAYER_FUNCTION] = { // FUNCTION
+ { KC_NLCK, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, ________________ },
+ { KC_SLCK, KC_F13, KC_F14, KC_F15, KC_F16, KC_F17, KC_F18, KC_F19, KC_F20, KC_F21, KC_F22, KC_F23, KC_F24, _______, KC_PAUS },
+ { KC_CAPS, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, ________________, KC_PSCR },
+ { _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, ________________, KC_VOLU, KC_MUTE },
+ { _______, _______, _______, _______, _______, KC_MPLY, KC_MPLY, _______, _______, _______, _______, _______, KC_MPRV, KC_VOLD, KC_MNXT },
+ },
+
+#ifdef MOUSEKEY_ENABLE
+
+ [LAYER_MOUSE] = { // MOUSE
+ { _______, KC_ACL0, KC_ACL1, KC_ACL2, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXXXXXXXXXXX },
+ { XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX },
+ { XXXXXXX, KC_BTN5, KC_BTN4, KC_BTN3, KC_BTN2, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXXXXXXXXXXX, KC_WH_U },
+ { _______, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, ________________, KC_MS_U, KC_WH_D },
+ { _______, _______, _______, _______, _______, KC_BTN1, KC_BTN1, _______, _______, _______, _______, _______, KC_MS_L, KC_MS_D, KC_MS_R },
+ },
+
+#endif
+
+ [LAYER_ADJUST] = { // ADJUST
+ { _______, TIMBR_1, TIMBR_2, TIMBR_3, TIMBR_4, TMPO_UP, TMPO_DN, TMPO_DF, _______, _______, _______, MU_TOG, AU_TOG, ________________ },
+ { _______, M_QWRTY, M_COLMK, M_DVORK, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ },
+ { _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, ________________, _______ },
+ { _______, _______, _______, _______, M_BACKL, RESET, _______, M_MOUSE, _______, _______, _______, ________________, MUV_IN, _______ },
+ { _______, _______, _______, _______, _______, ________________, _______, _______, _______, _______, _______, _______, MUV_DE, _______ },
+ },
+
+
+/*
+ [LAYER_EMPTY] = { // LAYER
+ { _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, ________________ },
+ { _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ },
+ { _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, ________________, _______ },
+ { _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, ________________, _______, _______ },
+ { _______, _______, _______, _______, _______, ________________, _______, _______, _______, _______, _______, _______, _______, _______ },
+ },
+*/
+
+};
+
+#ifdef AUDIO_ENABLE
+
+float tone_my_startup[][2] = SONG(ODE_TO_JOY);
+float tone_my_goodbye[][2] = SONG(ROCK_A_BYE_BABY);
+
+float tone_qwerty[][2] = SONG(QWERTY_SOUND);
+float tone_dvorak[][2] = SONG(DVORAK_SOUND);
+float tone_colemak[][2] = SONG(COLEMAK_SOUND);
+
+float tone_audio_on[][2] = SONG(CLOSE_ENCOUNTERS_5_NOTE);
+float tone_music_on[][2] = SONG(DOE_A_DEER);
+float music_scale[][2] = SONG(MUSIC_SCALE_SOUND);
+
+float tone_caps_on[][2] = SONG(CAPS_LOCK_ON_SOUND);
+float tone_caps_off[][2] = SONG(CAPS_LOCK_OFF_SOUND);
+float tone_numlk_on[][2] = SONG(NUM_LOCK_ON_SOUND);
+float tone_numlk_off[][2] = SONG(NUM_LOCK_OFF_SOUND);
+float tone_scroll_on[][2] = SONG(SCROLL_LOCK_ON_SOUND);
+float tone_scroll_off[][2] = SONG(SCROLL_LOCK_OFF_SOUND);
+
+#endif /* AUDIO_ENABLE */
+
+void persistant_default_layer_set(uint16_t default_layer)
+{
+ eeconfig_update_default_layer(default_layer);
+ default_layer_set(default_layer);
+}
+
+const uint16_t PROGMEM fn_actions[] = {
+ [0] = ACTION_MODS_ONESHOT(MOD_LSFT),
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+
+ // MACRODOWN only works in this function
+ switch(id)
+ {
+
+ case MACRO_BREATH_TOGGLE:
+ if (record->event.pressed)
+ {
+ breathing_toggle();
+ }
+ break;
+
+ case MACRO_BREATH_SPEED_INC:
+ if (record->event.pressed)
+ {
+ breathing_speed_inc(1);
+ }
+ break;
+
+ case MACRO_BREATH_SPEED_DEC:
+ if (record->event.pressed)
+ {
+ breathing_speed_dec(1);
+ }
+ break;
+
+ case MACRO_BREATH_DEFAULT:
+ if (record->event.pressed)
+ {
+ breathing_defaults();
+ }
+ break;
+
+ case MACRO_QWERTY:
+ if (record->event.pressed)
+ {
+ persistant_default_layer_set(1UL<<LAYER_QWERTY);
+ #ifdef AUDIO_ENABLE
+ PLAY_NOTE_ARRAY(tone_qwerty, false, STACCATO);
+ #endif /* AUDIO_ENABLE */
+ }
+ break;
+
+ case MACRO_COLEMAK:
+ if (record->event.pressed)
+ {
+ persistant_default_layer_set(1UL<<LAYER_COLEMAK);
+ #ifdef AUDIO_ENABLE
+ PLAY_NOTE_ARRAY(tone_colemak, false, STACCATO);
+ #endif /* AUDIO_ENABLE */
+ }
+ break;
+
+ case MACRO_DVORAK:
+ if (record->event.pressed)
+ {
+ persistant_default_layer_set(1UL<<LAYER_DVORAK);
+ #ifdef AUDIO_ENABLE
+ PLAY_NOTE_ARRAY(tone_dvorak, false, STACCATO);
+ #endif /* AUDIO_ENABLE */
+ }
+ break;
+
+ case MACRO_UPPER:
+ if (record->event.pressed)
+ {
+ layer_on(LAYER_UPPER);
+ breathing_speed_set(2);
+ breathing_pulse();
+ update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST);
+ }
+ else
+ {
+ layer_off(LAYER_UPPER);
+ update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST);
+ }
+ break;
+
+ case MACRO_LOWER:
+ if (record->event.pressed)
+ {
+ layer_on(LAYER_LOWER);
+ breathing_speed_set(2);
+ breathing_pulse();
+ update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST);
+ }
+ else
+ {
+ layer_off(LAYER_LOWER);
+ update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST);
+ }
+ break;
+
+ case MACRO_FUNCTION:
+ if (record->event.pressed)
+ {
+ breathing_speed_set(3);
+ breathing_enable();
+ layer_on(LAYER_FUNCTION);
+ }
+ else
+ {
+ breathing_speed_set(1);
+ breathing_self_disable();
+ layer_off(LAYER_FUNCTION);
+ }
+ break;
+
+#ifdef MOUSEKEY_ENABLE
+
+ case MACRO_MOUSE:
+ if (record->event.pressed)
+ {
+ layer_invert(LAYER_MOUSE);
+ }
+ break;
+
+#endif /* MOUSEKEY_ENABLE */
+
+#ifdef AUDIO_ENABLE
+
+ case MACRO_TIMBRE_1:
+ if (record->event.pressed) set_timbre(TIMBRE_12);
+ break;
+
+ case MACRO_TIMBRE_2:
+ if (record->event.pressed) set_timbre(TIMBRE_25);
+ break;
+
+ case MACRO_TIMBRE_3:
+ if (record->event.pressed) set_timbre(TIMBRE_50);
+ break;
+
+ case MACRO_TIMBRE_4:
+ if (record->event.pressed) set_timbre(TIMBRE_75);
+ break;
+
+ case MACRO_TEMPO_U:
+ if (record->event.pressed) increase_tempo(10);
+ break;
+
+ case MACRO_TEMPO_D:
+ if (record->event.pressed) decrease_tempo(10);
+ break;
+
+ case MACRO_TONE_DEFAULT:
+ if (record->event.pressed)
+ {
+ set_timbre(TIMBRE_DEFAULT);
+ set_tempo(TEMPO_DEFAULT);
+ }
+ break;
+
+/*
+ case MACRO_AUDIO_TOGGLE:
+ if (record->event.pressed)
+ {
+ if (is_audio_on())
+ {
+ audio_off();
+ }
+ else
+ {
+ audio_on();
+ PLAY_NOTE_ARRAY(tone_audio_on, false, STACCATO);
+ }
+ }
+ break;
+
+ case MACRO_MUSIC_TOGGLE:
+ if (record->event.pressed)
+ {
+ if (IS_LAYER_ON(LAYER_MUSIC))
+ {
+ layer_off(LAYER_MUSIC);
+ stop_all_notes();
+ }
+ else
+ {
+ PLAY_NOTE_ARRAY(tone_music_on, false, STACCATO);
+ layer_on(LAYER_MUSIC);
+ }
+ }
+ break;
+ case MACRO_INC_VOICE:
+ if (record->event.pressed)
+ {
+ #ifdef AUDIO_ENABLE
+ voice_iterate();
+ PLAY_NOTE_ARRAY(music_scale, false, STACCATO);
+ #endif
+ }
+ break;
+
+ case MACRO_DEC_VOICE:
+ if (record->event.pressed)
+ {
+ #ifdef AUDIO_ENABLE
+ voice_deiterate();
+ PLAY_NOTE_ARRAY(music_scale, false, STACCATO);
+ #endif
+ }
+ break;
+*/
+
+#endif /* AUDIO_ENABLE */
+
+#ifdef BACKLIGHT_ENABLE
+ case MACRO_BACKLIGHT:
+ if (record->event.pressed)
+ {
+ backlight_step();
+ }
+#endif
+
+ default:
+ break;
+
+ }
+ return MACRO_NONE;
+};
+
+
+#ifdef AUDIO_ENABLE
+
+void matrix_init_user(void)
+{
+ set_voice(default_voice);
+ startup_user();
+ println("Matrix Init");
+}
+
+void led_set_user(uint8_t usb_led)
+{
+ static uint8_t old_usb_led = 0;
+
+ _delay_ms(10); // gets rid of tick
+
+ if (!is_playing_notes())
+ {
+ if ((usb_led & (1<<USB_LED_CAPS_LOCK)) && !(old_usb_led & (1<<USB_LED_CAPS_LOCK)))
+ {
+ // If CAPS LK LED is turning on...
+ PLAY_NOTE_ARRAY(tone_caps_on, false, LEGATO);
+ }
+ else if (!(usb_led & (1<<USB_LED_CAPS_LOCK)) && (old_usb_led & (1<<USB_LED_CAPS_LOCK)))
+ {
+ // If CAPS LK LED is turning off...
+ PLAY_NOTE_ARRAY(tone_caps_off, false, LEGATO);
+ }
+ else if ((usb_led & (1<<USB_LED_NUM_LOCK)) && !(old_usb_led & (1<<USB_LED_NUM_LOCK)))
+ {
+ // If NUM LK LED is turning on...
+ PLAY_NOTE_ARRAY(tone_numlk_on, false, LEGATO);
+ }
+ else if (!(usb_led & (1<<USB_LED_NUM_LOCK)) && (old_usb_led & (1<<USB_LED_NUM_LOCK)))
+ {
+ // If NUM LED is turning off...
+ PLAY_NOTE_ARRAY(tone_numlk_off, false, LEGATO);
+ }
+ else if ((usb_led & (1<<USB_LED_SCROLL_LOCK)) && !(old_usb_led & (1<<USB_LED_SCROLL_LOCK)))
+ {
+ // If SCROLL LK LED is turning on...
+ PLAY_NOTE_ARRAY(tone_scroll_on, false, LEGATO);
+ }
+ else if (!(usb_led & (1<<USB_LED_SCROLL_LOCK)) && (old_usb_led & (1<<USB_LED_SCROLL_LOCK)))
+ {
+ // If SCROLL LED is turning off...
+ PLAY_NOTE_ARRAY(tone_scroll_off, false, LEGATO);
+ }
+ }
+
+ old_usb_led = usb_led;
+}
+
+
+void startup_user()
+{
+ _delay_ms(10); // gets rid of tick
+ PLAY_NOTE_ARRAY(tone_my_startup, false, STACCATO);
+}
+
+void shutdown_user()
+{
+ PLAY_NOTE_ARRAY(tone_my_goodbye, false, STACCATO);
+ _delay_ms(2000);
+ stop_all_notes();
+}
+
+void audio_on_user(void)
+{
+ PLAY_NOTE_ARRAY(tone_audio_on, false, STACCATO);
+}
+
+void music_on_user(void)
+{
+ PLAY_NOTE_ARRAY(tone_music_on, false, STACCATO);
+}
+
+void music_scale_user(void)
+{
+ PLAY_NOTE_ARRAY(music_scale, false, STACCATO);
+}
+
+#endif /* AUDIO_ENABLE */ \ No newline at end of file
diff --git a/keyboards/atomic/readme.md b/keyboards/atomic/readme.md
new file mode 100644
index 000000000..ab1e7ba1f
--- /dev/null
+++ b/keyboards/atomic/readme.md
@@ -0,0 +1,25 @@
+Atomic keyboard firmware
+======================
+DIY/Assembled ortholinear 60% keyboard by [Ortholinear Keyboards](http://ortholinearkeyboards.com).
+
+## Quantum MK Firmware
+
+For the full Quantum feature list, see [the parent readme.md](/readme.md).
+
+## Building
+
+Download or clone the whole firmware and navigate to the keyboards/atomic folder. Once your dev env is setup, you'll be able to type `make` to generate your .hex - you can then use `make dfu` to program your PCB once you hit the reset button.
+
+Depending on which keymap you would like to use, you will have to compile slightly differently.
+
+### Default
+To build with the default keymap, simply run `make`.
+
+### Other Keymaps
+Several version of keymap are available in advance but you are recommended to define your favorite layout yourself. To define your own keymap create a file in the keymaps folder named `<name>.c` and see keymap document (you can find in top readme.md) and existent keymap files.
+
+To build the firmware binary hex file with a keymap just do `make` with `KEYMAP` option like:
+```
+$ make KEYMAP=[default|jack|<name>]
+```
+Keymaps follow the format **__\<name\>.c__** and are stored in the `keymaps` folder.
diff --git a/keyboards/atreus/Makefile b/keyboards/atreus/Makefile
new file mode 100644
index 000000000..72b694faa
--- /dev/null
+++ b/keyboards/atreus/Makefile
@@ -0,0 +1,87 @@
+
+
+ifdef TEENSY2
+ OPT_DEFS += -DATREUS_TEENSY2
+ ATRUES_UPLOAD_COMMAND = teensy_loader_cli -w -mmcu=$(MCU) $(TARGET).hex
+else
+ OPT_DEFS += -DATREUS_ASTAR
+ ATRUES_UPLOAD_COMMAND = while [ ! -r $(USB) ]; do sleep 1; done; \
+ avrdude -p $(MCU) -c avr109 -U flash:w:$(TARGET).hex -P $(USB)
+endif
+
+# MCU name
+#MCU = at90usb1287
+MCU = atmega32u4
+
+# Processor frequency.
+# This will define a symbol, F_CPU, in all source code files equal to the
+# processor frequency in Hz. You can then use this symbol in your source code to
+# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
+# automatically to create a 32-bit value in your source code.
+#
+# This will be an integer division of F_USB below, as it is sourced by
+# F_USB after it has run through any CPU prescalers. Note that this value
+# does not *change* the processor frequency - it should merely be updated to
+# reflect the processor speed set externally so that the code can use accurate
+# software delays.
+F_CPU = 16000000
+
+
+#
+# LUFA specific
+#
+# Target architecture (see library "Board Types" documentation).
+ARCH = AVR8
+
+# Input clock frequency.
+# This will define a symbol, F_USB, in all source code files equal to the
+# input clock frequency (before any prescaling is performed) in Hz. This value may
+# differ from F_CPU if prescaling is used on the latter, and is required as the
+# raw input clock is fed directly to the PLL sections of the AVR for high speed
+# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
+# at the end, this will be done automatically to create a 32-bit value in your
+# source code.
+#
+# If no clock division is performed on the input clock inside the AVR (via the
+# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
+F_USB = $(F_CPU)
+
+# Interrupt driven control endpoint task(+60)
+OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
+
+
+# Boot Section Size in *bytes*
+# Teensy halfKay 512
+# Teensy++ halfKay 1024
+# Atmel DFU loader 4096
+# LUFA bootloader 4096
+# USBaspLoader 2048
+OPT_DEFS += -DBOOTLOADER_SIZE=4096
+
+
+# Build Options
+# comment out to disable the options.
+#
+#BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE ?= yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450)
+CONSOLE_ENABLE ?= yes # Console for debug(+400)
+COMMAND_ENABLE ?= yes # Commands for debug and configuration
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+# SLEEP_LED_ENABLE ?= yes # Breathing sleep LED during USB suspend
+NKRO_ENABLE ?= yes # USB Nkey Rollover - not yet supported in LUFA
+# BACKLIGHT_ENABLE ?= yes # Enable keyboard backlight functionality
+# MIDI_ENABLE ?= YES # MIDI controls
+UNICODE_ENABLE ?= YES # Unicode
+# BLUETOOTH_ENABLE ?= yes # Enable Bluetooth with the Adafruit EZ-Key HID
+
+
+ifndef QUANTUM_DIR
+ include ../../Makefile
+endif
+
+USB ?= /dev/cu.usbmodem1411
+
+upload: build
+ $(ATRUES_UPLOAD_COMMAND)
+ \ No newline at end of file
diff --git a/keyboards/atreus/atreus.c b/keyboards/atreus/atreus.c
new file mode 100644
index 000000000..263ec8732
--- /dev/null
+++ b/keyboards/atreus/atreus.c
@@ -0,0 +1 @@
+#include "atreus.h" \ No newline at end of file
diff --git a/keyboards/atreus/atreus.h b/keyboards/atreus/atreus.h
new file mode 100644
index 000000000..2b3803bc2
--- /dev/null
+++ b/keyboards/atreus/atreus.h
@@ -0,0 +1,25 @@
+#ifndef ATREUS_H
+#define ATREUS_H
+
+#include "quantum.h"
+#include "matrix.h"
+#include "backlight.h"
+#include <stddef.h>
+
+// This a shortcut to help you visually see your layout.
+// The first section contains all of the arguements
+// The second converts the arguments into a two-dimensional array
+#define KEYMAP( \
+ k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, \
+ k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, \
+ k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, \
+ k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k3a \
+) \
+{ \
+ { k00, k01, k02, k03, k04, KC_NO, k05, k06, k07, k08, k09 }, \
+ { k10, k11, k12, k13, k14, KC_NO, k15, k16, k17, k18, k19 }, \
+ { k20, k21, k22, k23, k24, k35, k25, k26, k27, k28, k29 }, \
+ { k2a, k30, k31, k32, k33, k34, k36, k37, k38, k39, k3a } \
+}
+
+#endif
diff --git a/keyboards/atreus/config.h b/keyboards/atreus/config.h
new file mode 100644
index 000000000..624d90188
--- /dev/null
+++ b/keyboards/atreus/config.h
@@ -0,0 +1,88 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "config_common.h"
+
+/* USB Device descriptor parameter */
+
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x6060
+#define DEVICE_VER 0x0001
+#define MANUFACTURER Technomancy
+#define PRODUCT Atreus
+#define DESCRIPTION q.m.k. keyboard firmware for Atreus
+
+/* key matrix size */
+#define MATRIX_ROWS 4
+#define MATRIX_COLS 11
+
+// Change this to how you wired your keyboard
+// COLS: Left to right, ROWS: Top to bottom
+#if defined(ATREUS_ASTAR)
+# define MATRIX_ROW_PINS { D0, D1, D3, D2 }
+# define MATRIX_COL_PINS { D7, C6, B5, B4, E6, D4, B6, F6, F7, D6, B7 }
+# define UNUSED_PINS
+#elif defined(ATREUS_TEENSY2)
+# define MATRIX_ROW_PINS { D0, D1, D2, D3 }
+# define MATRIX_COL_PINS { F6, F5, F4, B7, B6, B5, B4, B3, B2, B1, B0 }
+# define UNUSED_PINS
+#endif
+
+/* COL2ROW or ROW2COL */
+#define DIODE_DIRECTION COL2ROW
+
+/* define if matrix has ghost */
+//#define MATRIX_HAS_GHOST
+
+/* number of backlight levels */
+//#define BACKLIGHT_LEVELS 3
+
+/* Set 0 if debouncing isn't needed */
+#define DEBOUNCING_DELAY 5
+
+/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
+#define LOCKING_SUPPORT_ENABLE
+/* Locking resynchronize hack */
+#define LOCKING_RESYNC_ENABLE
+
+/* key combination for command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+/*
+ * Feature disable options
+ * These options are also useful to firmware size reduction.
+ */
+
+/* disable debug print */
+//#define NO_DEBUG
+
+/* disable print */
+//#define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+
+#endif
diff --git a/keyboards/atreus/keymaps/default/keymap.c b/keyboards/atreus/keymaps/default/keymap.c
new file mode 100644
index 000000000..1c4280ff5
--- /dev/null
+++ b/keyboards/atreus/keymaps/default/keymap.c
@@ -0,0 +1,51 @@
+// this is the style you want to emulate.
+// This is the canonical layout file for the Quantum project. If you want to add another keyboard,
+
+#include "atreus.h"
+
+// Each layer gets a name for readability, which is then used in the keymap matrix below.
+// The underscores don't mean anything - you can have a layer called STUFF or any other name.
+// Layer names don't all need to be of the same length, obviously, and you can also skip them
+// entirely and just use numbers.
+#define _QW 0
+#define _RS 1
+#define _LW 2
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[_QW] = { /* Qwerty */
+ {KC_Q, KC_W, KC_E, KC_R, KC_T, KC_TRNS, KC_Y, KC_U, KC_I, KC_O, KC_P },
+ {KC_A, KC_S, KC_D, KC_F, KC_G, KC_TRNS, KC_H, KC_J, KC_K, KC_L, KC_SCLN },
+ {KC_Z, KC_X, KC_C, KC_V, KC_B, KC_LALT, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH },
+ {KC_ESC, KC_TAB, KC_LGUI, KC_LSFT, KC_BSPC, KC_LCTL, KC_SPC, MO(_RS), KC_MINS, KC_QUOT, KC_ENT }
+},
+[_RS] = { /* [> RAISE <] */
+ {KC_EXLM, KC_AT, KC_LCBR, KC_RCBR, KC_PIPE, KC_TRNS, KC_PGUP, KC_7, KC_8, KC_9, KC_ASTR},
+ {KC_HASH, KC_DLR, KC_LPRN, KC_RPRN, KC_GRV, KC_TRNS, KC_PGDN, KC_4, KC_5, KC_6, KC_PLUS},
+ {KC_PERC, KC_CIRC, KC_LBRC, KC_RBRC, KC_TILD, KC_LALT, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS},
+ {TG(_LW), KC_INS, KC_LGUI, KC_LSFT, KC_BSPC, KC_LCTL, KC_SPC, KC_TRNS, KC_DOT, KC_0, KC_EQL}
+},
+[_LW] = { /* [> LOWER <] */
+ {KC_INS, KC_HOME, KC_UP, KC_END, KC_PGUP, KC_TRNS, KC_UP, KC_F7, KC_F8, KC_F9, KC_F10},
+ {KC_DELT, KC_LEFT, KC_DOWN, KC_RGHT, KC_DOWN, KC_TRNS, KC_DOWN, KC_F4, KC_F5, KC_F6, KC_F11},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_LALT, KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F12},
+ {KC_TRNS, KC_TRNS, KC_LGUI, KC_LSFT, KC_BSPC, KC_LCTL, KC_SPC, DF(_QW), KC_TRNS, KC_TRNS, RESET}
+}};
+
+const uint16_t PROGMEM fn_actions[] = {
+
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
diff --git a/keyboards/atreus/keymaps/gerb/keymap.c b/keyboards/atreus/keymaps/gerb/keymap.c
new file mode 100644
index 000000000..1ba3942e3
--- /dev/null
+++ b/keyboards/atreus/keymaps/gerb/keymap.c
@@ -0,0 +1,66 @@
+// This is the personal keymap of Chris Gerber (@gerbercj). I haven't worked out the kinks
+// with the Colemak and Dvorak support yet, but everything else works nicely.
+
+#include "atreus.h"
+
+// Each layer gets a name for readability, which is then used in the keymap matrix below.
+// The underscores don't mean anything - you can have a layer called STUFF or any other name.
+// Layer names don't all need to be of the same length, obviously, and you can also skip them
+// entirely and just use numbers.
+#define _QW 0
+#define _CM 1
+#define _DV 2
+#define _L1 3
+#define _L2 4
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ [_QW] = { /* Qwerty */
+ {KC_Q, KC_W, KC_E, KC_R, KC_T, KC_NO, KC_Y, KC_U, KC_I, KC_O, KC_P },
+ {KC_A, KC_S, KC_D, KC_F, KC_G, KC_NO, KC_H, KC_J, KC_K, KC_L, KC_SCLN},
+ {KC_Z, KC_X, KC_C, KC_V, KC_B, KC_LALT, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH},
+ {KC_ESC, KC_TAB, KC_LGUI, KC_LSFT, KC_BSPC, KC_RCTL, KC_SPC, MO(_L1), KC_MINS, KC_QUOT, KC_ENT }
+ },
+ [_CM] = { /* Colemak */
+ {KC_Q, KC_W, KC_F, KC_P, KC_G, KC_NO, KC_J, KC_L, KC_U, KC_Y, KC_SCLN},
+ {KC_A, KC_R, KC_S, KC_T, KC_D, KC_NO, KC_H, KC_N, KC_E, KC_I, KC_O },
+ {KC_Z, KC_X, KC_C, KC_V, KC_B, KC_LALT, KC_K, KC_M, KC_COMM, KC_DOT, KC_SLSH},
+ {KC_ESC, KC_TAB, KC_LGUI, KC_LSFT, KC_BSPC, KC_RCTL, KC_SPC, MO(_L1), KC_MINS, KC_QUOT, KC_ENT }
+ },
+ [_DV] = { /* Dvorak */
+ {KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, KC_NO, KC_F, KC_G, KC_C, KC_R, KC_L },
+ {KC_A, KC_O, KC_E, KC_U, KC_I, KC_NO, KC_D, KC_H, KC_T, KC_N, KC_S },
+ {KC_SCLN, KC_Q, KC_J, KC_K, KC_X, KC_LALT, KC_B, KC_M, KC_W, KC_V, KC_Z },
+ {KC_ESC, KC_TAB, KC_LGUI, KC_LSFT, KC_BSPC, KC_RCTL, KC_SPC, MO(_L1), KC_MINS, KC_SLSH, KC_ENT }
+ },
+ [_L1] = { /* LAYER 1 */
+ {KC_INS, KC_HOME, KC_UP, KC_END, KC_PGUP, KC_NO, KC_VOLU, KC_7, KC_8, KC_9, KC_LBRC},
+ {KC_DEL, KC_LEFT, KC_DOWN, KC_RGHT, KC_PGDN, KC_NO, KC_VOLD, KC_4, KC_5, KC_6, KC_RBRC},
+ {KC_GRV, KC_MPRV, KC_MPLY, KC_MNXT, KC_MINS, KC_LALT, KC_MUTE, KC_1, KC_2, KC_3, KC_BSLS},
+ {TG(_L2), KC_APP, KC_LGUI, KC_LSFT, KC_BSPC, KC_RCTL, KC_SPC, KC_TRNS, KC_DOT, KC_0, KC_EQL }
+ },
+ [_L2] = { /* LAYER 2 */
+ {KC_TRNS, KC_WH_L, KC_MS_U, KC_WH_R, KC_WH_U, KC_NO, DF(_QW), KC_F7, KC_F8, KC_F9, KC_F10 },
+ {KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_WH_D, KC_NO, DF(_CM), KC_F6, KC_F5, KC_F6, KC_F11 },
+ {KC_BTN4, KC_BTN1, KC_BTN2, KC_BTN3, KC_BTN4, KC_LALT, DF(_DV), KC_F1, KC_F2, KC_F3, KC_F12 },
+ {KC_TRNS, KC_TRNS, KC_LGUI, KC_LSFT, KC_BSPC, KC_RCTL, KC_SPC, KC_TRNS, KC_TRNS, KC_TRNS, RESET }
+ }
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
diff --git a/keyboards/atreus/readme.md b/keyboards/atreus/readme.md
new file mode 100644
index 000000000..734f58f0f
--- /dev/null
+++ b/keyboards/atreus/readme.md
@@ -0,0 +1,186 @@
+atreus keyboard firmware
+======================
+
+## Quantum MK Firmware
+
+You have access to a bunch of goodies! Check out the Makefile to enable/disable some of the features. Uncomment the `#` to enable them. Setting them to `no` does nothing and will only confuse future you.
+
+ BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
+ MIDI_ENABLE = yes # MIDI controls
+ # UNICODE_ENABLE = yes # Unicode support - this is commented out, just as an example. You have to use #, not //
+ BLUETOOTH_ENABLE = yes # Enable Bluetooth with the Adafruit EZ-Key HID
+
+## Atreus specific information
+
+These configuration files are specifically for the Atreus keyboards created by Phil Hagelberg (@technomancy). This keyboard is available in two variants: one powered by a Teensy 2, one powered by an A-Star. This repository currently assumes that you have an A-Star powered Atreus. If you are using a Teensy2, specify that by adding `TEENSY2=yes` to your `make` commands.
+
+If you are coming from the [atreus-firmware](https://github.com/technomancy/atreus-firmware), we've also brought forward the `make upload` command for you to use.
+
+## Quick aliases to common actions
+
+Your keymap can include shortcuts to common operations (called "function actions" in tmk).
+
+### Switching and toggling layers
+
+`MO(layer)` - momentary switch to *layer*. As soon as you let go of the key, the layer is deactivated and you pop back out to the previous layer. When you apply this to a key, that same key must be set as `KC_TRNS` on the destination layer. Otherwise, you won't make it back to the original layer when you release the key (and you'll get a keycode sent). You can only switch to layers *above* your current layer. If you're on layer 0 and you use `MO(1)`, that will switch to layer 1 just fine. But if you include `MO(3)` on layer 5, that won't do anything for you -- because layer 3 is lower than layer 5 on the stack.
+
+`LT(layer, kc)` - momentary switch to *layer* when held, and *kc* when tapped. Like `MO()`, this only works upwards in the layer stack (`layer` must be higher than the current layer).
+
+`TG(layer)` - toggles a layer on or off. As with `MO()`, you should set this key as `KC_TRNS` in the destination layer so that tapping it again actually toggles back to the original layer. Only works upwards in the layer stack.
+
+### Fun with modifier keys
+
+* `LSFT(kc)` - applies left Shift to *kc* (keycode) - `S(kc)` is an alias
+* `RSFT(kc)` - applies right Shift to *kc*
+* `LCTL(kc)` - applies left Control to *kc*
+* `RCTL(kc)` - applies right Control to *kc*
+* `LALT(kc)` - applies left Alt to *kc*
+* `RALT(kc)` - applies right Alt to *kc*
+* `LGUI(kc)` - applies left GUI (command/win) to *kc*
+* `RGUI(kc)` - applies right GUI (command/win) to *kc*
+
+You can also chain these, like this:
+
+ LALT(LCTL(KC_DEL)) -- this makes a key that sends Alt, Control, and Delete in a single keypress.
+
+The following shortcuts automatically add `LSFT()` to keycodes to get commonly used symbols. Their long names are also available and documented in `/quantum/keymap_common.h`.
+
+ KC_TILD ~
+ KC_EXLM !
+ KC_AT @
+ KC_HASH #
+ KC_DLR $
+ KC_PERC %
+ KC_CIRC ^
+ KC_AMPR &
+ KC_ASTR *
+ KC_LPRN (
+ KC_RPRN )
+ KC_UNDS _
+ KC_PLUS +
+ KC_LCBR {
+ KC_RCBR }
+ KC_PIPE |
+ KC_COLN :
+
+`MT(mod, kc)` - is *mod* (modifier key - MOD_LCTL, MOD_LSFT) when held, and *kc* when tapped. In other words, you can have a key that sends Esc (or the letter O or whatever) when you tap it, but works as a Control key or a Shift key when you hold it down.
+
+These are the values you can use for the `mod` in `MT()` (right-hand modifiers are not available):
+
+ * MOD_LCTL
+ * MOD_LSFT
+ * MOD_LALT
+ * MOD_LGUI
+
+These can also be combined like `MOD_LCTL | MOD_LSFT` e.g. `MT(MOD_LCTL | MOD_LSFT, KC_ESC)` which would activate Control and Shift when held, and send Escape when tapped.
+
+We've added shortcuts to make common modifier/tap (mod-tap) mappings more compact:
+
+ * `CTL_T(kc)` - is LCTL when held and *kc* when tapped
+ * `SFT_T(kc)` - is LSFT when held and *kc* when tapped
+ * `ALT_T(kc)` - is LALT when held and *kc* when tapped
+ * `GUI_T(kc)` - is LGUI when held and *kc* when tapped
+ * `ALL_T(kc)` - is Hyper (all mods) when held and *kc* when tapped. To read more about what you can do with a Hyper key, see [this blog post by Brett Terpstra](http://brettterpstra.com/2012/12/08/a-useful-caps-lock-key/)
+
+### Temporarily setting the default layer
+
+`DF(layer)` - sets default layer to *layer*. The default layer is the one at the "bottom" of the layer stack - the ultimate fallback layer. This currently does not persist over power loss. When you plug the keyboard back in, layer 0 will always be the default. It is theoretically possible to work around that, but that's not what `DF` does.
+
+### Remember: These are just aliases
+
+These functions work the same way that their `ACTION_*` functions do - they're just quick aliases. To dig into all of the tmk ACTION_* functions, please see the [TMK documentation](https://github.com/jackhumbert/qmk_firmware/blob/master/tmk_core/doc/keymap.md#2-action).
+
+Instead of using `FNx` when defining `ACTION_*` functions, you can use `F(x)` - the benefit here is being able to use more than 32 function actions (up to 4096), if you happen to need them.
+
+## Macro shortcuts: Send a whole string when pressing just one key
+
+Instead of using the `ACTION_MACRO` function, you can simply use `M(n)` to access macro *n* - *n* will get passed into the `action_get_macro` as the `id`, and you can use a switch statement to trigger it. This gets called on the keydown and keyup, so you'll need to use an if statement testing `record->event.pressed` (see keymap_default.c).
+
+```c
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) // this is the function signature -- just copy/paste it into your keymap file as it is.
+{
+ switch(id) {
+ case 0: // this would trigger when you hit a key mapped as M(0)
+ if (record->event.pressed) {
+ return MACRO( I(255), T(H), T(E), T(L), T(L), W(255), T(O), END ); // this sends the string 'hello' when the macro executes
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+```
+A macro can include the following commands:
+
+* I() change interval of stroke in milliseconds.
+* D() press key.
+* U() release key.
+* T() type key(press and release).
+* W() wait (milliseconds).
+* END end mark.
+
+So above you can see the stroke interval changed to 255ms between each keystroke, then a bunch of keys being typed, waits a while, then the macro ends.
+
+Note: Using macros to have your keyboard send passwords for you is a bad idea.
+
+### Additional keycode aliases for software-implemented layouts (Colemak, Dvorak, etc)
+
+Everything is assuming you're in Qwerty (in software) by default, but there is built-in support for using a Colemak or Dvorak layout by including this at the top of your keymap:
+
+ #include "keymap_<layout>.h"
+
+Where <layout> is "colemak" or "dvorak". After including this line, you will get access to:
+
+ * `CM_*` for all of the Colemak-equivalent characters
+ * `DV_*` for all of the Dvorak-equivalent characters
+
+These implementations assume you're using Colemak or Dvorak on your OS, not on your keyboard - this is referred to as a software-implemented layout. If your computer is in Qwerty and your keymap is in Colemak or Dvorak, this is referred to as a firmware-implemented layout, and you won't need these features.
+
+To give an example, if you're using software-implemented Colemak, and want to get an `F`, you would use `CM_F` - `KC_F` under these same circumstances would result in `T`.
+
+## Additional language support
+
+In `quantum/keymap_extras/`, you'll see various language files - these work the same way as the alternative layout ones do. Most are defined by their two letter country/language code followed by an underscore and a 4-letter abbreviation of its name. `FR_UGRV` which will result in a `ù` when using a software-implemented AZERTY layout. It's currently difficult to send such characters in just the firmware (but it's being worked on - see Unicode support).
+
+## Unicode support
+
+You can currently send 4 hex digits with your OS-specific modifier key (RALT for OSX with the "Unicode Hex Input" layout) - this is currently limited to supporting one OS at a time, and requires a recompile for switching. 8 digit hex codes are being worked on. The keycode function is `UC(n)`, where *n* is a 4 digit hexidecimal. Enable from the Makefile.
+
+## Other firmware shortcut keycodes
+
+* `RESET` - puts the MCU in DFU mode for flashing new firmware (with `make dfu`)
+* `DEBUG` - the firmware into debug mode - you'll need hid_listen to see things
+* `BL_ON` - turns the backlight on
+* `BL_OFF` - turns the backlight off
+* `BL_<n>` - sets the backlight to level *n*
+* `BL_INC` - increments the backlight level by one
+* `BL_DEC` - decrements the backlight level by one
+* `BL_TOGG` - toggles the backlight
+* `BL_STEP` - steps through the backlight levels
+
+Enable the backlight from the Makefile.
+
+## MIDI functionalty
+
+This is still a WIP, but check out `quantum/keymap_midi.c` to see what's happening. Enable from the Makefile.
+
+## Bluetooth functionality
+
+This requires [some hardware changes](https://www.reddit.com/r/MechanicalKeyboards/comments/3psx0q/the_planck_keyboard_with_bluetooth_guide_and/?ref=search_posts), but can be enabled via the Makefile. The firmware will still output characters via USB, so be aware of this when charging via a computer. It would make sense to have a switch on the Bluefruit to turn it off at will.
+
+## Building
+
+Download or clone the whole firmware and navigate to the keyboards/planck folder. Once your dev env is setup, you'll be able to type `make` to generate your .hex - you can then use `make dfu` to program your PCB once you hit the reset button.
+
+Depending on which keymap you would like to use, you will have to compile slightly differently.
+
+### Default
+To build with the default keymap, simply run `make`.
+
+### Other Keymaps
+Several version of keymap are available in advance but you are recommended to define your favorite layout yourself. To define your own keymap create file named `<name>.c` and see keymap document (you can find in top readme.md) and existent keymap files.
+
+To build the firmware binary hex file with a keymap just do `make` with `KEYMAP` option like:
+```
+$ make KEYMAP=[default|jack|<name>]
+```
+Keymaps follow the format **__\<name\>.c__** and are stored in the `keymaps` folder.
diff --git a/keyboards/bantam44/Makefile b/keyboards/bantam44/Makefile
new file mode 100644
index 000000000..03893dbf8
--- /dev/null
+++ b/keyboards/bantam44/Makefile
@@ -0,0 +1,72 @@
+
+
+# MCU name
+#MCU = at90usb1287
+MCU = atmega32u4
+
+# Processor frequency.
+# This will define a symbol, F_CPU, in all source code files equal to the
+# processor frequency in Hz. You can then use this symbol in your source code to
+# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
+# automatically to create a 32-bit value in your source code.
+#
+# This will be an integer division of F_USB below, as it is sourced by
+# F_USB after it has run through any CPU prescalers. Note that this value
+# does not *change* the processor frequency - it should merely be updated to
+# reflect the processor speed set externally so that the code can use accurate
+# software delays.
+F_CPU = 16000000
+
+
+#
+# LUFA specific
+#
+# Target architecture (see library "Board Types" documentation).
+ARCH = AVR8
+
+# Input clock frequency.
+# This will define a symbol, F_USB, in all source code files equal to the
+# input clock frequency (before any prescaling is performed) in Hz. This value may
+# differ from F_CPU if prescaling is used on the latter, and is required as the
+# raw input clock is fed directly to the PLL sections of the AVR for high speed
+# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
+# at the end, this will be done automatically to create a 32-bit value in your
+# source code.
+#
+# If no clock division is performed on the input clock inside the AVR (via the
+# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
+F_USB = $(F_CPU)
+
+# Interrupt driven control endpoint task(+60)
+OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
+
+
+# Boot Section Size in *bytes*
+# Teensy halfKay 512
+# Teensy++ halfKay 1024
+# Atmel DFU loader 4096
+# LUFA bootloader 4096
+# USBaspLoader 2048
+OPT_DEFS += -DBOOTLOADER_SIZE=512
+
+
+# Build Options
+# comment out to disable the options.
+#
+BOOTMAGIC_ENABLE ?= yes # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE ?= yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450)
+CONSOLE_ENABLE ?= yes # Console for debug(+400)
+COMMAND_ENABLE ?= yes # Commands for debug and configuration
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+# SLEEP_LED_ENABLE ?= yes # Breathing sleep LED during USB suspend
+# NKRO_ENABLE ?= yes # USB Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+# BACKLIGHT_ENABLE ?= yes # Enable keyboard backlight functionality
+# MIDI_ENABLE ?= YES # MIDI controls
+# UNICODE_ENABLE ?= YES # Unicode
+# BLUETOOTH_ENABLE ?= yes # Enable Bluetooth with the Adafruit EZ-Key HID
+
+ifndef QUANTUM_DIR
+ include ../../Makefile
+endif
+
diff --git a/keyboards/bantam44/bantam44.c b/keyboards/bantam44/bantam44.c
new file mode 100644
index 000000000..f995308ae
--- /dev/null
+++ b/keyboards/bantam44/bantam44.c
@@ -0,0 +1 @@
+#include "bantam44.h" \ No newline at end of file
diff --git a/keyboards/bantam44/bantam44.h b/keyboards/bantam44/bantam44.h
new file mode 100644
index 000000000..3c0117434
--- /dev/null
+++ b/keyboards/bantam44/bantam44.h
@@ -0,0 +1,23 @@
+#ifndef BANTAM44_H
+#define BANTAM44_H
+
+#include "quantum.h"
+
+// This a shortcut to help you visually see your layout.
+// The following is an example using the Planck MIT layout
+// The first section contains all of the arguements
+// The second converts the arguments into a two-dimensional array
+#define KEYMAP( \
+ K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, \
+ K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, \
+ K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, \
+ K30, K31, K32, K33, K34, K35, K36, K37, K38 \
+) \
+{ \
+ { K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B }, \
+ { K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, KC_NO, K2A }, \
+ { K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B }, \
+ { K30, K31, K32, KC_NO, K33, KC_NO, K34, KC_NO, K35, K36, K37, K38 }, \
+}
+
+#endif
diff --git a/keyboards/bantam44/config.h b/keyboards/bantam44/config.h
new file mode 100644
index 000000000..a55f62999
--- /dev/null
+++ b/keyboards/bantam44/config.h
@@ -0,0 +1,82 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "config_common.h"
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x6060
+#define DEVICE_VER 0x0001
+#define MANUFACTURER Bantam Keyboards
+#define PRODUCT Bantam44
+#define DESCRIPTION A custom keyboard
+
+/* key matrix size */
+#define MATRIX_ROWS 4
+#define MATRIX_COLS 12
+
+// Planck PCB default pin-out
+// Change this to how you wired your keyboard
+// COLS: Left to right, ROWS: Top to bottom
+#define MATRIX_ROW_PINS { F0, D6, D4, D5 }
+#define MATRIX_COL_PINS { B0, B1, B2, B3, B7, D0, B6, F7, F6, F5, F4, F1 }
+#define UNUSED_PINS
+
+/* COL2ROW or ROW2COL */
+#define DIODE_DIRECTION COL2ROW
+
+/* define if matrix has ghost */
+//#define MATRIX_HAS_GHOST
+
+/* number of backlight levels */
+#define BACKLIGHT_LEVELS 3
+
+/* Set 0 if debouncing isn't needed */
+#define DEBOUNCING_DELAY 5
+
+/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
+#define LOCKING_SUPPORT_ENABLE
+/* Locking resynchronize hack */
+#define LOCKING_RESYNC_ENABLE
+
+/* key combination for command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+/*
+ * Feature disable options
+ * These options are also useful to firmware size reduction.
+ */
+
+/* disable debug print */
+//#define NO_DEBUG
+
+/* disable print */
+//#define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+
+#endif
diff --git a/keyboards/bantam44/keymaps/default/keymap.c b/keyboards/bantam44/keymaps/default/keymap.c
new file mode 100644
index 000000000..ed795eee1
--- /dev/null
+++ b/keyboards/bantam44/keymaps/default/keymap.c
@@ -0,0 +1,30 @@
+#include "bantam44.h"
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ [0] = { /* Base */
+ {KC_ESC, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC },
+ {KC_TAB, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_NO, KC_ENT },
+ {KC_CAPS, KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_RSFT },
+ {KC_LCTL, KC_LGUI, KC_LALT, KC_NO, MO(1), KC_NO, KC_SPC, KC_NO, MO(2), KC_SCLN, KC_QUOT, KC_SLSH }
+ },
+ [1] = { /* LOWER */
+ {KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_DELT },
+ {KC_TAB, KC_MPRV, KC_MPLY, KC_MNXT, KC_GRV, KC_BSLS, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_NO, KC_ENT },
+ {KC_CAPS, KC_LSFT, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_NO, KC_HOME, KC_PGUP, KC_RSFT },
+ {KC_LCTL, KC_LGUI, KC_LALT, KC_NO, KC_TRNS, KC_NO, KC_SPC, KC_NO, KC_TRNS, KC_END, KC_PGDN, KC_EXLM }
+ },
+ [2] = { /* RAISE */
+ {KC_ESC, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_DELT },
+ {KC_TAB, KC_MUTE, KC_VOLD, KC_VOLU, KC_TILD, KC_PIPE, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_NO, KC_ENT },
+ {KC_CAPS, KC_LSFT, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_NO, KC_NO, KC_UP, KC_RSFT },
+ {KC_LCTL, KC_LGUI, KC_LALT, KC_NO, KC_TRNS, KC_NO, KC_SPC, KC_NO, KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT }
+ }
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) // MACRODOWN only works in this function
+{
+ return MACRO_NONE;
+}; \ No newline at end of file
diff --git a/keyboards/bantam44/readme.md b/keyboards/bantam44/readme.md
new file mode 100644
index 000000000..89d7f9d05
--- /dev/null
+++ b/keyboards/bantam44/readme.md
@@ -0,0 +1,24 @@
+Bantam44 keyboard firmware
+======================
+
+## Quantum MK Firmware
+
+For the full Quantum feature list, see [the parent readme.md](/readme.md).
+
+## Building
+
+Download or clone the whole firmware and navigate to the keyboards/Bantam44 folder. Once your dev env is setup, you'll be able to type `make` to generate your .hex - you can then use the Teensy Loader to program your .hex file.
+
+Depending on which keymap you would like to use, you will have to compile slightly differently.
+
+### Default
+To build with the default keymap, simply run `make`.
+
+### Other Keymaps
+Several version of keymap are available in advance but you are recommended to define your favorite layout yourself. To define your own keymap create file named `<name>.c` and see keymap document (you can find in top readme.md) and existent keymap files.
+
+To build the firmware binary hex file with a keymap just do `make` with `KEYMAP` option like:
+```
+$ make KEYMAP=[default|jack|<name>]
+```
+Keymaps follow the format **__\<name\>.c__** and are stored in the `keymaps` folder. \ No newline at end of file
diff --git a/keyboards/chibios_test/Makefile b/keyboards/chibios_test/Makefile
new file mode 100644
index 000000000..d9f2b8b83
--- /dev/null
+++ b/keyboards/chibios_test/Makefile
@@ -0,0 +1,14 @@
+SUBPROJECT_DEFAULT = stm32_f072_onekey
+
+#BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration
+MOUSEKEY_ENABLE ?= yes # Mouse keys
+EXTRAKEY_ENABLE ?= yes # Audio control and System control
+CONSOLE_ENABLE ?= yes # Console for debug
+COMMAND_ENABLE ?= yes # Commands for debug and configuration
+SLEEP_LED_ENABLE ?= yes # Breathing sleep LED during USB suspend
+NKRO_ENABLE ?= yes # USB Nkey Rollover
+CUSTOM_MATRIX ?= yes # Custom matrix file
+
+ifndef QUANTUM_DIR
+ include ../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/chibios_test/boards/GENERIC_STM32_F103/board.c b/keyboards/chibios_test/boards/GENERIC_STM32_F103/board.c
new file mode 100644
index 000000000..31319ef57
--- /dev/null
+++ b/keyboards/chibios_test/boards/GENERIC_STM32_F103/board.c
@@ -0,0 +1,49 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#include "hal.h"
+
+/**
+ * @brief PAL setup.
+ * @details Digital I/O ports static configuration as defined in @p board.h.
+ * This variable is used by the HAL when initializing the PAL driver.
+ */
+#if HAL_USE_PAL || defined(__DOXYGEN__)
+const PALConfig pal_default_config =
+{
+ {VAL_GPIOAODR, VAL_GPIOACRL, VAL_GPIOACRH},
+ {VAL_GPIOBODR, VAL_GPIOBCRL, VAL_GPIOBCRH},
+ {VAL_GPIOCODR, VAL_GPIOCCRL, VAL_GPIOCCRH},
+ {VAL_GPIODODR, VAL_GPIODCRL, VAL_GPIODCRH},
+ {VAL_GPIOEODR, VAL_GPIOECRL, VAL_GPIOECRH},
+};
+#endif
+
+/*
+ * Early initialization code.
+ * This initialization must be performed just after stack setup and before
+ * any other initialization.
+ */
+void __early_init(void) {
+
+ stm32_clock_init();
+}
+
+/*
+ * Board-specific initialization code.
+ */
+void boardInit(void) {
+}
diff --git a/keyboards/chibios_test/boards/GENERIC_STM32_F103/board.h b/keyboards/chibios_test/boards/GENERIC_STM32_F103/board.h
new file mode 100644
index 000000000..7253e7782
--- /dev/null
+++ b/keyboards/chibios_test/boards/GENERIC_STM32_F103/board.h
@@ -0,0 +1,166 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#ifndef _BOARD_H_
+#define _BOARD_H_
+
+/*
+ * Setup for a Generic STM32F103 board.
+ */
+
+/*
+ * Board identifier.
+ */
+#define BOARD_GENERIC_STM32_F103
+#define BOARD_NAME "Generic STM32F103x board"
+
+/*
+ * Board frequencies.
+ */
+#define STM32_LSECLK 32768
+#define STM32_HSECLK 8000000
+
+/*
+ * MCU type, supported types are defined in ./os/hal/platforms/hal_lld.h.
+ */
+#define STM32F103xB
+
+/*
+ * IO pins assignments
+ */
+
+/* on-board */
+
+#define GPIOC_LED 13
+#define GPIOD_OSC_IN 0
+#define GPIOD_OSC_OUT 1
+
+/* In case your board has a "USB enable" hardware
+ controlled by a pin, define it here. (It could be just
+ a 1.5k resistor connected to D+ line.)
+*/
+/*
+#define GPIOB_USB_DISC 10
+*/
+
+/*
+ * I/O ports initial setup, this configuration is established soon after reset
+ * in the initialization code.
+ *
+ * The digits have the following meaning:
+ * 0 - Analog input.
+ * 1 - Push Pull output 10MHz.
+ * 2 - Push Pull output 2MHz.
+ * 3 - Push Pull output 50MHz.
+ * 4 - Digital input.
+ * 5 - Open Drain output 10MHz.
+ * 6 - Open Drain output 2MHz.
+ * 7 - Open Drain output 50MHz.
+ * 8 - Digital input with PullUp or PullDown resistor depending on ODR.
+ * 9 - Alternate Push Pull output 10MHz.
+ * A - Alternate Push Pull output 2MHz.
+ * B - Alternate Push Pull output 50MHz.
+ * C - Reserved.
+ * D - Alternate Open Drain output 10MHz.
+ * E - Alternate Open Drain output 2MHz.
+ * F - Alternate Open Drain output 50MHz.
+ * Please refer to the STM32 Reference Manual for details.
+ */
+
+/*
+ * Port A setup.
+ * Everything input with pull-up except:
+ * PA2 - Alternate output (USART2 TX).
+ * PA3 - Normal input (USART2 RX).
+ * PA9 - Alternate output (USART1 TX).
+ * PA10 - Normal input (USART1 RX).
+ */
+#define VAL_GPIOACRL 0x88884B88 /* PA7...PA0 */
+#define VAL_GPIOACRH 0x888884B8 /* PA15...PA8 */
+#define VAL_GPIOAODR 0xFFFFFFFF
+
+/*
+ * Port B setup.
+ * Everything input with pull-up except:
+ * PB10 - Push Pull output (USB switch).
+ */
+#define VAL_GPIOBCRL 0x88888888 /* PB7...PB0 */
+#define VAL_GPIOBCRH 0x88888388 /* PB15...PB8 */
+#define VAL_GPIOBODR 0xFFFFFFFF
+
+/*
+ * Port C setup.
+ * Everything input with pull-up except:
+ * PC13 - Push Pull output (LED).
+ */
+#define VAL_GPIOCCRL 0x88888888 /* PC7...PC0 */
+#define VAL_GPIOCCRH 0x88388888 /* PC15...PC8 */
+#define VAL_GPIOCODR 0xFFFFFFFF
+
+/*
+ * Port D setup.
+ * Everything input with pull-up except:
+ * PD0 - Normal input (XTAL).
+ * PD1 - Normal input (XTAL).
+ */
+#define VAL_GPIODCRL 0x88888844 /* PD7...PD0 */
+#define VAL_GPIODCRH 0x88888888 /* PD15...PD8 */
+#define VAL_GPIODODR 0xFFFFFFFF
+
+/*
+ * Port E setup.
+ * Everything input with pull-up except:
+ */
+#define VAL_GPIOECRL 0x88888888 /* PE7...PE0 */
+#define VAL_GPIOECRH 0x88888888 /* PE15...PE8 */
+#define VAL_GPIOEODR 0xFFFFFFFF
+
+/*
+ * USB bus activation macro, required by the USB driver.
+ */
+/* The point is that most of the generic STM32F103* boards
+ have a 1.5k resistor connected on one end to the D+ line
+ and on the other end to some pin. Or even a slightly more
+ complicated "USB enable" circuit, controlled by a pin.
+ That should go here.
+
+ However on some boards (e.g. one that I have), there's no
+ such hardware. In which case it's better to not do anything.
+*/
+/*
+#define usb_lld_connect_bus(usbp) palClearPad(GPIOB, GPIOB_USB_DISC)
+*/
+#define usb_lld_connect_bus(usbp) palSetPadMode(GPIOA, 12, PAL_MODE_INPUT);
+
+/*
+ * USB bus de-activation macro, required by the USB driver.
+ */
+/*
+#define usb_lld_disconnect_bus(usbp) palSetPad(GPIOB, GPIOB_USB_DISC)
+*/
+#define usb_lld_disconnect_bus(usbp) palSetPadMode(GPIOA, 12, PAL_MODE_OUTPUT_PUSHPULL); palClearPad(GPIOA, 12);
+
+#if !defined(_FROM_ASM_)
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void boardInit(void);
+#ifdef __cplusplus
+}
+#endif
+#endif /* _FROM_ASM_ */
+
+#endif /* _BOARD_H_ */
diff --git a/keyboards/chibios_test/boards/GENERIC_STM32_F103/board.mk b/keyboards/chibios_test/boards/GENERIC_STM32_F103/board.mk
new file mode 100644
index 000000000..d692c0ee4
--- /dev/null
+++ b/keyboards/chibios_test/boards/GENERIC_STM32_F103/board.mk
@@ -0,0 +1,5 @@
+# List of all the board related files.
+BOARDSRC = $(KEYBOARD_PATH)/boards/GENERIC_STM32_F103/board.c
+
+# Required include directories
+BOARDINC = $(KEYBOARD_PATH)/boards/GENERIC_STM32_F103
diff --git a/keyboards/chibios_test/boards/GENERIC_STM32_F103/mini_stm32_mapping.png b/keyboards/chibios_test/boards/GENERIC_STM32_F103/mini_stm32_mapping.png
new file mode 100644
index 000000000..c44a7d9eb
--- /dev/null
+++ b/keyboards/chibios_test/boards/GENERIC_STM32_F103/mini_stm32_mapping.png
Binary files differ
diff --git a/keyboards/chibios_test/boards/maple_mini_mapping.png b/keyboards/chibios_test/boards/maple_mini_mapping.png
new file mode 100644
index 000000000..12cfa81db
--- /dev/null
+++ b/keyboards/chibios_test/boards/maple_mini_mapping.png
Binary files differ
diff --git a/keyboards/chibios_test/chibios_test.c b/keyboards/chibios_test/chibios_test.c
new file mode 100644
index 000000000..efe2d4a5d
--- /dev/null
+++ b/keyboards/chibios_test/chibios_test.c
@@ -0,0 +1 @@
+#include "chibios_test.h"
diff --git a/keyboards/chibios_test/chibios_test.h b/keyboards/chibios_test/chibios_test.h
new file mode 100644
index 000000000..25b031771
--- /dev/null
+++ b/keyboards/chibios_test/chibios_test.h
@@ -0,0 +1,6 @@
+#ifndef KEYBOARDS_CHIBIOS_TEST_CHIBIOS_TEST_H_
+#define KEYBOARDS_CHIBIOS_TEST_CHIBIOS_TEST_H_
+
+#include "quantum.h"
+
+#endif /* KEYBOARDS_CHIBIOS_TEST_CHIBIOS_TEST_H_ */
diff --git a/keyboards/chibios_test/config.h b/keyboards/chibios_test/config.h
new file mode 100644
index 000000000..c32a77b37
--- /dev/null
+++ b/keyboards/chibios_test/config.h
@@ -0,0 +1,74 @@
+/*
+Copyright 2015 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x6464
+#define DEVICE_VER 0x0001
+/* in python2: list(u"whatever".encode('utf-16-le')) */
+/* at most 32 characters or the ugly hack in usb_main.c borks */
+#define MANUFACTURER "QMK"
+#define USBSTR_MANUFACTURER 'T', '\x00', 'M', '\x00', 'K', '\x00', ' ', '\x00', '\xc6', '\x00'
+#define PRODUCT "ChibiOS QMK test"
+#define USBSTR_PRODUCT 'C', '\x00', 'h', '\x00', 'i', '\x00', 'b', '\x00', 'i', '\x00', 'O', '\x00', 'S', '\x00', ' ', '\x00', 'Q', '\x00', 'M', '\x00', 'K', '\x00', ' ', '\x00', 't', '\x00', 'e', '\x00', 's', '\x00', 't', '\x00'
+#define DESCRIPTION "QMK keyboard firmware test for ChibiOS"
+
+/* key matrix size */
+#define MATRIX_ROWS 1
+#define MATRIX_COLS 1
+#define DIODE_DIRECTION COL2ROW
+
+/* define if matrix has ghost */
+//#define MATRIX_HAS_GHOST
+
+/* Set 0 if debouncing isn't needed */
+#define DEBOUNCE 5
+
+/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
+#define LOCKING_SUPPORT_ENABLE
+/* Locking resynchronize hack */
+#define LOCKING_RESYNC_ENABLE
+
+/* key combination for command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+
+
+/*
+ * Feature disable options
+ * These options are also useful to firmware size reduction.
+ */
+
+/* disable debug print */
+//#define NO_DEBUG
+
+/* disable print */
+//#define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+
+#endif
diff --git a/keyboards/chibios_test/keymaps/default/keymap.c b/keyboards/chibios_test/keymaps/default/keymap.c
new file mode 100644
index 000000000..239d70007
--- /dev/null
+++ b/keyboards/chibios_test/keymaps/default/keymap.c
@@ -0,0 +1,25 @@
+/*
+Copyright 2012,2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "chibios_test.h"
+
+const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ {{KC_CAPS}}, // test with KC_CAPS, KC_A, KC_BTLD
+};
+
+const uint16_t fn_actions[] = {
+};
diff --git a/keyboards/chibios_test/ld/MKL26Z64.ld b/keyboards/chibios_test/ld/MKL26Z64.ld
new file mode 100644
index 000000000..fb141f888
--- /dev/null
+++ b/keyboards/chibios_test/ld/MKL26Z64.ld
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2013-2016 Fabio Utzig, http://fabioutzig.com
+ * (C) 2016 flabbergast <s3+flabbergast@sdfeu.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * KL26Z64 memory setup.
+ */
+MEMORY
+{
+ flash0 : org = 0x00000000, len = 0x100
+ flash1 : org = 0x00000400, len = 0x10
+ flash2 : org = 0x00000410, len = 62k - 0x410
+ flash3 : org = 0x0000F800, len = 2k
+ flash4 : org = 0x00000000, len = 0
+ flash5 : org = 0x00000000, len = 0
+ flash6 : org = 0x00000000, len = 0
+ flash7 : org = 0x00000000, len = 0
+ ram0 : org = 0x1FFFF800, len = 8k
+ ram1 : org = 0x00000000, len = 0
+ ram2 : org = 0x00000000, len = 0
+ ram3 : org = 0x00000000, len = 0
+ ram4 : org = 0x00000000, len = 0
+ ram5 : org = 0x00000000, len = 0
+ ram6 : org = 0x00000000, len = 0
+ ram7 : org = 0x00000000, len = 0
+}
+
+/* Flash region for the configuration bytes.*/
+SECTIONS
+{
+ .cfmprotect : ALIGN(4) SUBALIGN(4)
+ {
+ KEEP(*(.cfmconfig))
+ } > flash1
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash2);
+REGION_ALIAS("XTORS_FLASH_LMA", flash2);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash2);
+REGION_ALIAS("TEXT_FLASH_LMA", flash2);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash2);
+REGION_ALIAS("RODATA_FLASH_LMA", flash2);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash2);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash2);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash2);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash2);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+__eeprom_workarea_start__ = ORIGIN(flash3);
+__eeprom_workarea_size__ = LENGTH(flash3);
+__eeprom_workarea_end__ = __eeprom_workarea_start__ + __eeprom_workarea_size__;
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/keyboards/chibios_test/ld/STM32F103x8_stm32duino_bootloader.ld b/keyboards/chibios_test/ld/STM32F103x8_stm32duino_bootloader.ld
new file mode 100644
index 000000000..00613328e
--- /dev/null
+++ b/keyboards/chibios_test/ld/STM32F103x8_stm32duino_bootloader.ld
@@ -0,0 +1,88 @@
+/*
+ ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * ST32F103xB memory setup for use with the maplemini bootloader.
+ * You will have to
+ * #define CORTEX_VTOR_INIT 0x5000
+ * in your projects chconf.h
+ */
+MEMORY
+{
+ flash0 : org = 0x08002000, len = 128k - 0x2000
+ flash1 : org = 0x00000000, len = 0
+ flash2 : org = 0x00000000, len = 0
+ flash3 : org = 0x00000000, len = 0
+ flash4 : org = 0x00000000, len = 0
+ flash5 : org = 0x00000000, len = 0
+ flash6 : org = 0x00000000, len = 0
+ flash7 : org = 0x00000000, len = 0
+ ram0 : org = 0x20000000, len = 20k
+ ram1 : org = 0x00000000, len = 0
+ ram2 : org = 0x00000000, len = 0
+ ram3 : org = 0x00000000, len = 0
+ ram4 : org = 0x00000000, len = 0
+ ram5 : org = 0x00000000, len = 0
+ ram6 : org = 0x00000000, len = 0
+ ram7 : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/keyboards/chibios_test/stm32_f072_onekey/Makefile b/keyboards/chibios_test/stm32_f072_onekey/Makefile
new file mode 100644
index 000000000..eae38c4b2
--- /dev/null
+++ b/keyboards/chibios_test/stm32_f072_onekey/Makefile
@@ -0,0 +1,41 @@
+# project specific files
+SRC = matrix.c \
+ led.c
+
+## chip/board settings
+# the next two should match the directories in
+# <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
+MCU_FAMILY = STM32
+MCU_SERIES = STM32F0xx
+# linker script to use
+# it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+# or <this_dir>/ld/
+MCU_LDSCRIPT = STM32F072xB
+# startup code to use
+# is should exist in <chibios>/os/common/ports/ARMCMx/compilers/GCC/mk/
+MCU_STARTUP = stm32f0xx
+# it should exist either in <chibios>/os/hal/boards/
+# or <this_dir>/boards
+BOARD = ST_STM32F072B_DISCOVERY
+# Cortex version
+# Teensy LC is cortex-m0; Teensy 3.x are cortex-m4
+MCU = cortex-m0
+# ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
+ARMV = 6
+# If you want to be able to jump to bootloader from firmware on STM32 MCUs,
+# set the correct BOOTLOADER_ADDRESS. Either set it here, or define it in
+# ./bootloader_defs.h or in ./boards/<FOO>/bootloader_defs.h (if you have
+# a custom board definition that you plan to reuse).
+# If you're not setting it here, leave it commented out.
+# It is chip dependent, the correct number can be looked up here (page 175):
+# http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf
+# This also requires a patch to chibios:
+# <tmk_dir>/tmk_core/tool/chibios/ch-bootloader-jump.patch
+#STM32_BOOTLOADER_ADDRESS = 0x1FFFC800
+
+# Build Options
+# comment out to disable the options.
+#
+ifndef QUANTUM_DIR
+ include ../../../Makefile
+endif
diff --git a/keyboards/chibios_test/stm32_f072_onekey/bootloader_defs.h b/keyboards/chibios_test/stm32_f072_onekey/bootloader_defs.h
new file mode 100644
index 000000000..02c48c4e6
--- /dev/null
+++ b/keyboards/chibios_test/stm32_f072_onekey/bootloader_defs.h
@@ -0,0 +1,7 @@
+/* Address for jumping to bootloader on STM32 chips. */
+/* It is chip dependent, the correct number can be looked up here (page 175):
+ * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf
+ * This also requires a patch to chibios:
+ * <tmk_dir>/tmk_core/tool/chibios/ch-bootloader-jump.patch
+ */
+#define STM32_BOOTLOADER_ADDRESS 0x1FFFC800
diff --git a/keyboards/chibios_test/stm32_f072_onekey/chconf.h b/keyboards/chibios_test/stm32_f072_onekey/chconf.h
new file mode 100644
index 000000000..99fa8ce39
--- /dev/null
+++ b/keyboards/chibios_test/stm32_f072_onekey/chconf.h
@@ -0,0 +1,524 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file templates/chconf.h
+ * @brief Configuration file template.
+ * @details A copy of this file must be placed in each project directory, it
+ * contains the application specific kernel settings.
+ *
+ * @addtogroup config
+ * @details Kernel related settings and hooks.
+ * @{
+ */
+
+#ifndef CHCONF_H
+#define CHCONF_H
+
+#define _CHIBIOS_RT_CONF_
+
+/*===========================================================================*/
+/**
+ * @name System timers settings
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief System time counter resolution.
+ * @note Allowed values are 16 or 32 bits.
+ */
+#define CH_CFG_ST_RESOLUTION 32
+
+/**
+ * @brief System tick frequency.
+ * @details Frequency of the system timer that drives the system ticks. This
+ * setting also defines the system tick time unit.
+ */
+#define CH_CFG_ST_FREQUENCY 10000
+
+/**
+ * @brief Time delta constant for the tick-less mode.
+ * @note If this value is zero then the system uses the classic
+ * periodic tick. This value represents the minimum number
+ * of ticks that is safe to specify in a timeout directive.
+ * The value one is not valid, timeouts are rounded up to
+ * this value.
+ */
+#define CH_CFG_ST_TIMEDELTA 2
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Kernel parameters and options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Round robin interval.
+ * @details This constant is the number of system ticks allowed for the
+ * threads before preemption occurs. Setting this value to zero
+ * disables the preemption for threads with equal priority and the
+ * round robin becomes cooperative. Note that higher priority
+ * threads can still preempt, the kernel is always preemptive.
+ * @note Disabling the round robin preemption makes the kernel more compact
+ * and generally faster.
+ * @note The round robin preemption is not supported in tickless mode and
+ * must be set to zero in that case.
+ */
+#define CH_CFG_TIME_QUANTUM 0
+
+/**
+ * @brief Managed RAM size.
+ * @details Size of the RAM area to be managed by the OS. If set to zero
+ * then the whole available RAM is used. The core memory is made
+ * available to the heap allocator and/or can be used directly through
+ * the simplified core memory allocator.
+ *
+ * @note In order to let the OS manage the whole RAM the linker script must
+ * provide the @p __heap_base__ and @p __heap_end__ symbols.
+ * @note Requires @p CH_CFG_USE_MEMCORE.
+ */
+#define CH_CFG_MEMCORE_SIZE 0
+
+/**
+ * @brief Idle thread automatic spawn suppression.
+ * @details When this option is activated the function @p chSysInit()
+ * does not spawn the idle thread. The application @p main()
+ * function becomes the idle thread and must implement an
+ * infinite loop.
+ */
+#define CH_CFG_NO_IDLE_THREAD FALSE
+
+/* Use __WFI in the idle thread for waiting. Does lower the power
+ * consumption. */
+#define CORTEX_ENABLE_WFI_IDLE TRUE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Performance options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief OS optimization.
+ * @details If enabled then time efficient rather than space efficient code
+ * is used when two possible implementations exist.
+ *
+ * @note This is not related to the compiler optimization options.
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_OPTIMIZE_SPEED FALSE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Subsystem options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Time Measurement APIs.
+ * @details If enabled then the time measurement APIs are included in
+ * the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_TM FALSE
+
+/**
+ * @brief Threads registry APIs.
+ * @details If enabled then the registry APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_REGISTRY TRUE
+
+/**
+ * @brief Threads synchronization APIs.
+ * @details If enabled then the @p chThdWait() function is included in
+ * the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_WAITEXIT TRUE
+
+/**
+ * @brief Semaphores APIs.
+ * @details If enabled then the Semaphores APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_SEMAPHORES TRUE
+
+/**
+ * @brief Semaphores queuing mode.
+ * @details If enabled then the threads are enqueued on semaphores by
+ * priority rather than in FIFO order.
+ *
+ * @note The default is @p FALSE. Enable this if you have special
+ * requirements.
+ * @note Requires @p CH_CFG_USE_SEMAPHORES.
+ */
+#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE
+
+/**
+ * @brief Mutexes APIs.
+ * @details If enabled then the mutexes APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MUTEXES TRUE
+
+/**
+ * @brief Enables recursive behavior on mutexes.
+ * @note Recursive mutexes are heavier and have an increased
+ * memory footprint.
+ *
+ * @note The default is @p FALSE.
+ * @note Requires @p CH_CFG_USE_MUTEXES.
+ */
+#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE
+
+/**
+ * @brief Conditional Variables APIs.
+ * @details If enabled then the conditional variables APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_MUTEXES.
+ */
+#define CH_CFG_USE_CONDVARS TRUE
+
+/**
+ * @brief Conditional Variables APIs with timeout.
+ * @details If enabled then the conditional variables APIs with timeout
+ * specification are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_CONDVARS.
+ */
+#define CH_CFG_USE_CONDVARS_TIMEOUT FALSE
+
+/**
+ * @brief Events Flags APIs.
+ * @details If enabled then the event flags APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_EVENTS TRUE
+
+/**
+ * @brief Events Flags APIs with timeout.
+ * @details If enabled then the events APIs with timeout specification
+ * are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_EVENTS.
+ */
+#define CH_CFG_USE_EVENTS_TIMEOUT TRUE
+
+/**
+ * @brief Synchronous Messages APIs.
+ * @details If enabled then the synchronous messages APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MESSAGES TRUE
+
+/**
+ * @brief Synchronous Messages queuing mode.
+ * @details If enabled then messages are served by priority rather than in
+ * FIFO order.
+ *
+ * @note The default is @p FALSE. Enable this if you have special
+ * requirements.
+ * @note Requires @p CH_CFG_USE_MESSAGES.
+ */
+#define CH_CFG_USE_MESSAGES_PRIORITY FALSE
+
+/**
+ * @brief Mailboxes APIs.
+ * @details If enabled then the asynchronous messages (mailboxes) APIs are
+ * included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_SEMAPHORES.
+ */
+#define CH_CFG_USE_MAILBOXES TRUE
+
+/**
+ * @brief Core Memory Manager APIs.
+ * @details If enabled then the core memory manager APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MEMCORE FALSE
+
+/**
+ * @brief Heap Allocator APIs.
+ * @details If enabled then the memory heap allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or
+ * @p CH_CFG_USE_SEMAPHORES.
+ * @note Mutexes are recommended.
+ */
+#define CH_CFG_USE_HEAP FALSE
+
+/**
+ * @brief Memory Pools Allocator APIs.
+ * @details If enabled then the memory pools allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MEMPOOLS FALSE
+
+/**
+ * @brief Dynamic Threads APIs.
+ * @details If enabled then the dynamic threads creation APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_WAITEXIT.
+ * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS.
+ */
+#define CH_CFG_USE_DYNAMIC FALSE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Debug options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Debug option, kernel statistics.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_STATISTICS FALSE
+
+/**
+ * @brief Debug option, system state check.
+ * @details If enabled the correct call protocol for system APIs is checked
+ * at runtime.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_SYSTEM_STATE_CHECK FALSE
+
+/**
+ * @brief Debug option, parameters checks.
+ * @details If enabled then the checks on the API functions input
+ * parameters are activated.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_ENABLE_CHECKS FALSE
+
+/**
+ * @brief Debug option, consistency checks.
+ * @details If enabled then all the assertions in the kernel code are
+ * activated. This includes consistency checks inside the kernel,
+ * runtime anomalies and port-defined checks.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_ENABLE_ASSERTS FALSE
+
+/**
+ * @brief Debug option, trace buffer.
+ * @details If enabled then the trace buffer is activated.
+ *
+ * @note The default is @p CH_DBG_TRACE_MASK_DISABLED.
+ */
+#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED
+
+/**
+ * @brief Trace buffer entries.
+ * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is
+ * different from @p CH_DBG_TRACE_MASK_DISABLED.
+ */
+#define CH_DBG_TRACE_BUFFER_SIZE 128
+
+/**
+ * @brief Debug option, stack checks.
+ * @details If enabled then a runtime stack check is performed.
+ *
+ * @note The default is @p FALSE.
+ * @note The stack check is performed in a architecture/port dependent way.
+ * It may not be implemented or some ports.
+ * @note The default failure mode is to halt the system with the global
+ * @p panic_msg variable set to @p NULL.
+ */
+#define CH_DBG_ENABLE_STACK_CHECK FALSE
+
+/**
+ * @brief Debug option, stacks initialization.
+ * @details If enabled then the threads working area is filled with a byte
+ * value when a thread is created. This can be useful for the
+ * runtime measurement of the used stack.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_FILL_THREADS FALSE
+
+/**
+ * @brief Debug option, threads profiling.
+ * @details If enabled then a field is added to the @p thread_t structure that
+ * counts the system ticks occurred while executing the thread.
+ *
+ * @note The default is @p FALSE.
+ * @note This debug option is not currently compatible with the
+ * tickless mode.
+ */
+#define CH_DBG_THREADS_PROFILING FALSE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Kernel hooks
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Threads descriptor structure extension.
+ * @details User fields added to the end of the @p thread_t structure.
+ */
+#define CH_CFG_THREAD_EXTRA_FIELDS \
+ /* Add threads custom fields here.*/
+
+/**
+ * @brief Threads initialization hook.
+ * @details User initialization code added to the @p chThdInit() API.
+ *
+ * @note It is invoked from within @p chThdInit() and implicitly from all
+ * the threads creation APIs.
+ */
+#define CH_CFG_THREAD_INIT_HOOK(tp) { \
+ /* Add threads initialization code here.*/ \
+}
+
+/**
+ * @brief Threads finalization hook.
+ * @details User finalization code added to the @p chThdExit() API.
+ */
+#define CH_CFG_THREAD_EXIT_HOOK(tp) { \
+ /* Add threads finalization code here.*/ \
+}
+
+/**
+ * @brief Context switch hook.
+ * @details This hook is invoked just before switching between threads.
+ */
+#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \
+ /* Context switch code here.*/ \
+}
+
+/**
+ * @brief ISR enter hook.
+ */
+#define CH_CFG_IRQ_PROLOGUE_HOOK() { \
+ /* IRQ prologue code here.*/ \
+}
+
+/**
+ * @brief ISR exit hook.
+ */
+#define CH_CFG_IRQ_EPILOGUE_HOOK() { \
+ /* IRQ epilogue code here.*/ \
+}
+
+/**
+ * @brief Idle thread enter hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to activate a power saving mode.
+ */
+#define CH_CFG_IDLE_ENTER_HOOK() { \
+ /* Idle-enter code here.*/ \
+}
+
+/**
+ * @brief Idle thread leave hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to deactivate a power saving mode.
+ */
+#define CH_CFG_IDLE_LEAVE_HOOK() { \
+ /* Idle-leave code here.*/ \
+}
+
+/**
+ * @brief Idle Loop hook.
+ * @details This hook is continuously invoked by the idle thread loop.
+ */
+#define CH_CFG_IDLE_LOOP_HOOK() { \
+ /* Idle loop code here.*/ \
+}
+
+/**
+ * @brief System tick event hook.
+ * @details This hook is invoked in the system tick handler immediately
+ * after processing the virtual timers queue.
+ */
+#define CH_CFG_SYSTEM_TICK_HOOK() { \
+ /* System tick event code here.*/ \
+}
+
+/**
+ * @brief System halt hook.
+ * @details This hook is invoked in case to a system halting error before
+ * the system is halted.
+ */
+#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \
+ /* System halt code here.*/ \
+}
+
+/**
+ * @brief Trace hook.
+ * @details This hook is invoked each time a new record is written in the
+ * trace buffer.
+ */
+#define CH_CFG_TRACE_HOOK(tep) { \
+ /* Trace code here.*/ \
+}
+
+/** @} */
+
+/*===========================================================================*/
+/* Port-specific settings (override port settings defaulted in chcore.h). */
+/*===========================================================================*/
+
+#endif /* CHCONF_H */
+
+/** @} */
diff --git a/keyboards/chibios_test/stm32_f072_onekey/config.h b/keyboards/chibios_test/stm32_f072_onekey/config.h
new file mode 100644
index 000000000..bbaf0dc4b
--- /dev/null
+++ b/keyboards/chibios_test/stm32_f072_onekey/config.h
@@ -0,0 +1,7 @@
+#ifndef KEYBOARDS_CHIBIOS_TEST_STM32_F072_ONEKEY_CONFIG_H_
+#define KEYBOARDS_CHIBIOS_TEST_STM32_F072_ONEKEY_CONFIG_H_
+
+#include "../config.h"
+
+
+#endif /* KEYBOARDS_CHIBIOS_TEST_STM32_F072_ONEKEY_CONFIG_H_ */
diff --git a/keyboards/chibios_test/stm32_f072_onekey/halconf.h b/keyboards/chibios_test/stm32_f072_onekey/halconf.h
new file mode 100644
index 000000000..1a450d632
--- /dev/null
+++ b/keyboards/chibios_test/stm32_f072_onekey/halconf.h
@@ -0,0 +1,353 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file templates/halconf.h
+ * @brief HAL configuration header.
+ * @details HAL configuration file, this file allows to enable or disable the
+ * various device drivers from your application. You may also use
+ * this file in order to override the device drivers default settings.
+ *
+ * @addtogroup HAL_CONF
+ * @{
+ */
+
+#ifndef _HALCONF_H_
+#define _HALCONF_H_
+
+#include "mcuconf.h"
+
+/**
+ * @brief Enables the PAL subsystem.
+ */
+#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__)
+#define HAL_USE_PAL TRUE
+#endif
+
+/**
+ * @brief Enables the ADC subsystem.
+ */
+#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__)
+#define HAL_USE_ADC FALSE
+#endif
+
+/**
+ * @brief Enables the CAN subsystem.
+ */
+#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__)
+#define HAL_USE_CAN FALSE
+#endif
+
+/**
+ * @brief Enables the DAC subsystem.
+ */
+#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__)
+#define HAL_USE_DAC FALSE
+#endif
+
+/**
+ * @brief Enables the EXT subsystem.
+ */
+#if !defined(HAL_USE_EXT) || defined(__DOXYGEN__)
+#define HAL_USE_EXT FALSE
+#endif
+
+/**
+ * @brief Enables the GPT subsystem.
+ */
+#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__)
+#define HAL_USE_GPT FALSE
+#endif
+
+/**
+ * @brief Enables the I2C subsystem.
+ */
+#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
+#define HAL_USE_I2C FALSE
+#endif
+
+/**
+ * @brief Enables the I2S subsystem.
+ */
+#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__)
+#define HAL_USE_I2S FALSE
+#endif
+
+/**
+ * @brief Enables the ICU subsystem.
+ */
+#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__)
+#define HAL_USE_ICU FALSE
+#endif
+
+/**
+ * @brief Enables the MAC subsystem.
+ */
+#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__)
+#define HAL_USE_MAC FALSE
+#endif
+
+/**
+ * @brief Enables the MMC_SPI subsystem.
+ */
+#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_MMC_SPI FALSE
+#endif
+
+/**
+ * @brief Enables the PWM subsystem.
+ */
+#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__)
+#define HAL_USE_PWM FALSE
+#endif
+
+/**
+ * @brief Enables the RTC subsystem.
+ */
+#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
+#define HAL_USE_RTC FALSE
+#endif
+
+/**
+ * @brief Enables the SDC subsystem.
+ */
+#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__)
+#define HAL_USE_SDC FALSE
+#endif
+
+/**
+ * @brief Enables the SERIAL subsystem.
+ */
+#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL FALSE
+#endif
+
+/**
+ * @brief Enables the SERIAL over USB subsystem.
+ */
+#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL_USB FALSE
+#endif
+
+/**
+ * @brief Enables the SPI subsystem.
+ */
+#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_SPI FALSE
+#endif
+
+/**
+ * @brief Enables the UART subsystem.
+ */
+#if !defined(HAL_USE_UART) || defined(__DOXYGEN__)
+#define HAL_USE_UART FALSE
+#endif
+
+/**
+ * @brief Enables the USB subsystem.
+ */
+#if !defined(HAL_USE_USB) || defined(__DOXYGEN__)
+#define HAL_USE_USB TRUE
+#endif
+
+/**
+ * @brief Enables the WDG subsystem.
+ */
+#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__)
+#define HAL_USE_WDG FALSE
+#endif
+
+/*===========================================================================*/
+/* ADC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__)
+#define ADC_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define ADC_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* CAN driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Sleep mode related APIs inclusion switch.
+ */
+#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
+#define CAN_USE_SLEEP_MODE TRUE
+#endif
+
+/*===========================================================================*/
+/* I2C driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables the mutual exclusion APIs on the I2C bus.
+ */
+#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define I2C_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* MAC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables an event sources for incoming packets.
+ */
+#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__)
+#define MAC_USE_ZERO_COPY FALSE
+#endif
+
+/**
+ * @brief Enables an event sources for incoming packets.
+ */
+#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__)
+#define MAC_USE_EVENTS TRUE
+#endif
+
+/*===========================================================================*/
+/* MMC_SPI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Delays insertions.
+ * @details If enabled this options inserts delays into the MMC waiting
+ * routines releasing some extra CPU time for the threads with
+ * lower priority, this may slow down the driver a bit however.
+ * This option is recommended also if the SPI driver does not
+ * use a DMA channel and heavily loads the CPU.
+ */
+#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__)
+#define MMC_NICE_WAITING TRUE
+#endif
+
+/*===========================================================================*/
+/* SDC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Number of initialization attempts before rejecting the card.
+ * @note Attempts are performed at 10mS intervals.
+ */
+#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__)
+#define SDC_INIT_RETRY 100
+#endif
+
+/**
+ * @brief Include support for MMC cards.
+ * @note MMC support is not yet implemented so this option must be kept
+ * at @p FALSE.
+ */
+#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__)
+#define SDC_MMC_SUPPORT FALSE
+#endif
+
+/**
+ * @brief Delays insertions.
+ * @details If enabled this options inserts delays into the MMC waiting
+ * routines releasing some extra CPU time for the threads with
+ * lower priority, this may slow down the driver a bit however.
+ */
+#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__)
+#define SDC_NICE_WAITING TRUE
+#endif
+
+/*===========================================================================*/
+/* SERIAL driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Default bit rate.
+ * @details Configuration parameter, this is the baud rate selected for the
+ * default configuration.
+ */
+#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__)
+#define SERIAL_DEFAULT_BITRATE 38400
+#endif
+
+/**
+ * @brief Serial buffers size.
+ * @details Configuration parameter, you can change the depth of the queue
+ * buffers depending on the requirements of your application.
+ * @note The default is 64 bytes for both the transmission and receive
+ * buffers.
+ */
+#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define SERIAL_BUFFERS_SIZE 16
+#endif
+
+/*===========================================================================*/
+/* SERIAL_USB driver related setting. */
+/*===========================================================================*/
+
+/**
+ * @brief Serial over USB buffers size.
+ * @details Configuration parameter, the buffer size must be a multiple of
+ * the USB data endpoint maximum packet size.
+ * @note The default is 64 bytes for both the transmission and receive
+ * buffers.
+ */
+#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define SERIAL_USB_BUFFERS_SIZE 256
+#endif
+
+/*===========================================================================*/
+/* SPI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__)
+#define SPI_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define SPI_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* USB driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__)
+#define USB_USE_WAIT TRUE
+#endif
+
+#endif /* _HALCONF_H_ */
+
+/** @} */
diff --git a/keyboards/chibios_test/stm32_f072_onekey/led.c b/keyboards/chibios_test/stm32_f072_onekey/led.c
new file mode 100644
index 000000000..18edb8ba8
--- /dev/null
+++ b/keyboards/chibios_test/stm32_f072_onekey/led.c
@@ -0,0 +1,34 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "hal.h"
+
+#include "led.h"
+
+
+void led_set(uint8_t usb_led)
+{
+ (void)usb_led;
+ if (usb_led & (1<<USB_LED_CAPS_LOCK)) {
+ // output high
+ palSetPadMode(GPIOC, GPIOC_LED_GREEN, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPad(GPIOC, GPIOC_LED_GREEN);
+ } else {
+ // Hi-Z
+ palSetPadMode(GPIOC, GPIOC_LED_GREEN, PAL_MODE_INPUT);
+ }
+}
diff --git a/keyboards/chibios_test/stm32_f072_onekey/matrix.c b/keyboards/chibios_test/stm32_f072_onekey/matrix.c
new file mode 100644
index 000000000..a05b38cd4
--- /dev/null
+++ b/keyboards/chibios_test/stm32_f072_onekey/matrix.c
@@ -0,0 +1,163 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "ch.h"
+#include "hal.h"
+
+/*
+ * scan matrix
+ */
+#include "print.h"
+#include "debug.h"
+#include "util.h"
+#include "matrix.h"
+#include "wait.h"
+
+#ifndef DEBOUNCE
+# define DEBOUNCE 5
+#endif
+static uint8_t debouncing = DEBOUNCE;
+
+/* matrix state(1:on, 0:off) */
+static matrix_row_t matrix[MATRIX_ROWS];
+static matrix_row_t matrix_debouncing[MATRIX_ROWS];
+
+static matrix_row_t read_cols(void);
+static void init_cols(void);
+static void unselect_rows(void);
+static void select_row(uint8_t row);
+
+
+inline
+uint8_t matrix_rows(void)
+{
+ return MATRIX_ROWS;
+}
+
+inline
+uint8_t matrix_cols(void)
+{
+ return MATRIX_COLS;
+}
+
+#define LED_ON() do { palSetPad(GPIOC, GPIOC_LED_BLUE) ;} while (0)
+#define LED_OFF() do { palClearPad(GPIOC, GPIOC_LED_BLUE); } while (0)
+#define LED_TGL() do { palTogglePad(GPIOC, GPIOC_LED_BLUE); } while (0)
+
+void matrix_init(void)
+{
+ // initialize row and col
+ unselect_rows();
+ init_cols();
+
+ // initialize matrix state: all keys off
+ for (uint8_t i=0; i < MATRIX_ROWS; i++) {
+ matrix[i] = 0;
+ matrix_debouncing[i] = 0;
+ }
+
+ //debug
+ debug_matrix = true;
+ LED_ON();
+ wait_ms(500);
+ LED_OFF();
+}
+
+uint8_t matrix_scan(void)
+{
+ for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+ select_row(i);
+ wait_us(30); // without this wait read unstable value.
+ matrix_row_t cols = read_cols();
+ if (matrix_debouncing[i] != cols) {
+ matrix_debouncing[i] = cols;
+ if (debouncing) {
+ debug("bounce!: "); debug_hex(debouncing); debug("\n");
+ }
+ debouncing = DEBOUNCE;
+ }
+ unselect_rows();
+ }
+
+ if (debouncing) {
+ if (--debouncing) {
+ wait_ms(1);
+ } else {
+ for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+ matrix[i] = matrix_debouncing[i];
+ }
+ }
+ }
+
+ return 1;
+}
+
+inline
+bool matrix_is_on(uint8_t row, uint8_t col)
+{
+ return (matrix[row] & ((matrix_row_t)1<<col));
+}
+
+inline
+matrix_row_t matrix_get_row(uint8_t row)
+{
+ return matrix[row];
+}
+
+void matrix_print(void)
+{
+ print("\nr/c 0123456789ABCDEF\n");
+ for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
+ phex(row); print(": ");
+ pbin_reverse16(matrix_get_row(row));
+ print("\n");
+ }
+}
+
+/* Column pin configuration
+ */
+static void init_cols(void)
+{
+ // don't need pullup/down, since it's pulled down in hardware
+ palSetPadMode(GPIOA, GPIOA_BUTTON, PAL_MODE_INPUT);
+}
+
+/* Returns status of switches(1:on, 0:off) */
+static matrix_row_t read_cols(void)
+{
+ return ((palReadPad(GPIOA, GPIOA_BUTTON)==PAL_LOW) ? 0 : (1<<0));
+ // | ((palReadPad(...)==PAL_HIGH) ? 0 : (1<<1))
+}
+
+/* Row pin configuration
+ */
+static void unselect_rows(void)
+{
+ // palSetPadMode(GPIOA, GPIOA_PIN10, PAL_MODE_INPUT); // hi-Z
+}
+
+static void select_row(uint8_t row)
+{
+ (void)row;
+ // Output low to select
+ // switch (row) {
+ // case 0:
+ // palSetPadMode(GPIOA, GPIOA_PIN10, PAL_MODE_OUTPUT_PUSHPULL);
+ // palSetPad(GPIOA, GPIOA_PIN10, PAL_LOW);
+ // break;
+ // }
+}
diff --git a/keyboards/chibios_test/stm32_f072_onekey/mcuconf.h b/keyboards/chibios_test/stm32_f072_onekey/mcuconf.h
new file mode 100644
index 000000000..3d877aaa2
--- /dev/null
+++ b/keyboards/chibios_test/stm32_f072_onekey/mcuconf.h
@@ -0,0 +1,171 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#ifndef _MCUCONF_H_
+#define _MCUCONF_H_
+
+/*
+ * STM32F0xx drivers configuration.
+ * The following settings override the default settings present in
+ * the various device driver implementation headers.
+ * Note that the settings for each driver only have effect if the whole
+ * driver is enabled in halconf.h.
+ *
+ * IRQ priorities:
+ * 3...0 Lowest...Highest.
+ *
+ * DMA priorities:
+ * 0...3 Lowest...Highest.
+ */
+
+#define STM32F0xx_MCUCONF
+
+/*
+ * HAL driver system settings.
+ */
+#define STM32_NO_INIT FALSE
+#define STM32_PVD_ENABLE FALSE
+#define STM32_PLS STM32_PLS_LEV0
+#define STM32_HSI_ENABLED TRUE
+#define STM32_HSI14_ENABLED TRUE
+#define STM32_HSI48_ENABLED FALSE
+#define STM32_LSI_ENABLED TRUE
+#define STM32_HSE_ENABLED FALSE
+#define STM32_LSE_ENABLED FALSE
+#define STM32_SW STM32_SW_PLL
+#define STM32_PLLSRC STM32_PLLSRC_HSI_DIV2
+#define STM32_PREDIV_VALUE 1
+#define STM32_PLLMUL_VALUE 12
+#define STM32_HPRE STM32_HPRE_DIV1
+#define STM32_PPRE STM32_PPRE_DIV1
+#define STM32_ADCSW STM32_ADCSW_HSI14
+#define STM32_ADCPRE STM32_ADCPRE_DIV4
+#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK
+#define STM32_ADCPRE STM32_ADCPRE_DIV4
+#define STM32_ADCSW STM32_ADCSW_HSI14
+#define STM32_USBSW STM32_USBSW_HSI48
+#define STM32_CECSW STM32_CECSW_HSI
+#define STM32_I2C1SW STM32_I2C1SW_HSI
+#define STM32_USART1SW STM32_USART1SW_PCLK
+#define STM32_RTCSEL STM32_RTCSEL_LSI
+
+/*
+ * ADC driver system settings.
+ */
+#define STM32_ADC_USE_ADC1 FALSE
+#define STM32_ADC_ADC1_DMA_PRIORITY 2
+#define STM32_ADC_IRQ_PRIORITY 2
+#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 2
+
+/*
+ * EXT driver system settings.
+ */
+#define STM32_EXT_EXTI0_1_IRQ_PRIORITY 3
+#define STM32_EXT_EXTI2_3_IRQ_PRIORITY 3
+#define STM32_EXT_EXTI4_15_IRQ_PRIORITY 3
+#define STM32_EXT_EXTI16_IRQ_PRIORITY 3
+#define STM32_EXT_EXTI17_IRQ_PRIORITY 3
+
+/*
+ * GPT driver system settings.
+ */
+#define STM32_GPT_USE_TIM1 FALSE
+#define STM32_GPT_USE_TIM2 FALSE
+#define STM32_GPT_USE_TIM3 FALSE
+#define STM32_GPT_USE_TIM14 FALSE
+#define STM32_GPT_TIM1_IRQ_PRIORITY 2
+#define STM32_GPT_TIM2_IRQ_PRIORITY 2
+#define STM32_GPT_TIM3_IRQ_PRIORITY 2
+#define STM32_GPT_TIM14_IRQ_PRIORITY 2
+
+/*
+ * I2C driver system settings.
+ */
+#define STM32_I2C_USE_I2C1 FALSE
+#define STM32_I2C_USE_I2C2 FALSE
+#define STM32_I2C_BUSY_TIMEOUT 50
+#define STM32_I2C_I2C1_IRQ_PRIORITY 3
+#define STM32_I2C_I2C2_IRQ_PRIORITY 3
+#define STM32_I2C_USE_DMA TRUE
+#define STM32_I2C_I2C1_DMA_PRIORITY 1
+#define STM32_I2C_I2C2_DMA_PRIORITY 1
+#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure")
+
+/*
+ * ICU driver system settings.
+ */
+#define STM32_ICU_USE_TIM1 FALSE
+#define STM32_ICU_USE_TIM2 FALSE
+#define STM32_ICU_USE_TIM3 FALSE
+#define STM32_ICU_TIM1_IRQ_PRIORITY 3
+#define STM32_ICU_TIM2_IRQ_PRIORITY 3
+#define STM32_ICU_TIM3_IRQ_PRIORITY 3
+
+/*
+ * PWM driver system settings.
+ */
+#define STM32_PWM_USE_ADVANCED FALSE
+#define STM32_PWM_USE_TIM1 FALSE
+#define STM32_PWM_USE_TIM2 FALSE
+#define STM32_PWM_USE_TIM3 FALSE
+#define STM32_PWM_TIM1_IRQ_PRIORITY 3
+#define STM32_PWM_TIM2_IRQ_PRIORITY 3
+#define STM32_PWM_TIM3_IRQ_PRIORITY 3
+
+/*
+ * SERIAL driver system settings.
+ */
+#define STM32_SERIAL_USE_USART1 FALSE
+#define STM32_SERIAL_USE_USART2 FALSE
+#define STM32_SERIAL_USART1_PRIORITY 3
+#define STM32_SERIAL_USART2_PRIORITY 3
+
+/*
+ * SPI driver system settings.
+ */
+#define STM32_SPI_USE_SPI1 FALSE
+#define STM32_SPI_USE_SPI2 FALSE
+#define STM32_SPI_SPI1_DMA_PRIORITY 1
+#define STM32_SPI_SPI2_DMA_PRIORITY 1
+#define STM32_SPI_SPI1_IRQ_PRIORITY 2
+#define STM32_SPI_SPI2_IRQ_PRIORITY 2
+#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure")
+
+/*
+ * ST driver system settings.
+ */
+#define STM32_ST_IRQ_PRIORITY 2
+#define STM32_ST_USE_TIMER 2
+
+/*
+ * UART driver system settings.
+ */
+#define STM32_UART_USE_USART1 FALSE
+#define STM32_UART_USE_USART2 FALSE
+#define STM32_UART_USART1_IRQ_PRIORITY 3
+#define STM32_UART_USART2_IRQ_PRIORITY 3
+#define STM32_UART_USART1_DMA_PRIORITY 0
+#define STM32_UART_USART2_DMA_PRIORITY 0
+#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure")
+
+/*
+ * USB driver system settings.
+ */
+#define STM32_USB_USE_USB1 TRUE
+#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE
+#define STM32_USB_USB1_LP_IRQ_PRIORITY 3
+
+#endif /* _MCUCONF_H_ */
diff --git a/keyboards/chibios_test/stm32_f072_onekey/stm32_f072_onekey.c b/keyboards/chibios_test/stm32_f072_onekey/stm32_f072_onekey.c
new file mode 100644
index 000000000..820d062ff
--- /dev/null
+++ b/keyboards/chibios_test/stm32_f072_onekey/stm32_f072_onekey.c
@@ -0,0 +1 @@
+#include "stm32_f072_onekey.h"
diff --git a/keyboards/chibios_test/stm32_f072_onekey/stm32_f072_onekey.h b/keyboards/chibios_test/stm32_f072_onekey/stm32_f072_onekey.h
new file mode 100644
index 000000000..0455ad342
--- /dev/null
+++ b/keyboards/chibios_test/stm32_f072_onekey/stm32_f072_onekey.h
@@ -0,0 +1,5 @@
+#ifndef STM32_F072_ONEKEY_H
+#define STM32_F072_ONEKEY_H
+#include "chibios_test.h"
+#endif
+
diff --git a/keyboards/chibios_test/stm32_f103_onekey/Makefile b/keyboards/chibios_test/stm32_f103_onekey/Makefile
new file mode 100644
index 000000000..307ca5b19
--- /dev/null
+++ b/keyboards/chibios_test/stm32_f103_onekey/Makefile
@@ -0,0 +1,52 @@
+# project specific files
+SRC = matrix.c \
+ led.c
+
+# GENERIC STM32F103C8T6 board - stm32duino bootloader
+OPT_DEFS = -DCORTEX_VTOR_INIT=0x2000
+MCU_LDSCRIPT = STM32F103x8_stm32duino_bootloader
+BOARD = GENERIC_STM32_F103
+
+# GENERIC STM32F103C8T6 board - no bootloader (programmer over serial or SWD)
+# OPT_DEFS =
+# MCU_LDSCRIPT = STM32F103x8
+# BOARD = GENERIC_STM32_F103
+
+# MAPLE MINI
+# OPT_DEFS = -DCORTEX_VTOR_INIT=0x5000
+# MCU_LDSCRIPT = STM32F103xB_maplemini_bootloader
+# BOARD = MAPLEMINI_STM32_F103
+
+## chip/board settings
+# the next two should match the directories in
+# <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
+MCU_FAMILY = STM32
+MCU_SERIES = STM32F1xx
+# linker script to use
+# it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+# or <this_dir>/ld/
+# startup code to use
+# is should exist in <chibios>/os/common/ports/ARMCMx/compilers/GCC/mk/
+MCU_STARTUP = stm32f1xx
+# it should exist either in <chibios>/os/hal/boards/
+# or <this_dir>/boards
+# Cortex version
+# Teensy LC is cortex-m0; Teensy 3.x are cortex-m4
+MCU = cortex-m3
+# ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
+ARMV = 7
+# If you want to be able to jump to bootloader from firmware on STM32 MCUs,
+# set the correct BOOTLOADER_ADDRESS. Either set it here, or define it in
+# ./bootloader_defs.h or in ./boards/<FOO>/bootloader_defs.h (if you have
+# a custom board definition that you plan to reuse).
+# If you're not setting it here, leave it commented out.
+# It is chip dependent, the correct number can be looked up here (page 175):
+# http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf
+# This also requires a patch to chibios:
+# <tmk_dir>/tmk_core/tool/chibios/ch-bootloader-jump.patch
+#STM32_BOOTLOADER_ADDRESS = 0x1FFFC800
+
+
+ifndef QUANTUM_DIR
+ include ../../../Makefile
+endif
diff --git a/keyboards/chibios_test/stm32_f103_onekey/bootloader_defs.h b/keyboards/chibios_test/stm32_f103_onekey/bootloader_defs.h
new file mode 100644
index 000000000..0f45203cb
--- /dev/null
+++ b/keyboards/chibios_test/stm32_f103_onekey/bootloader_defs.h
@@ -0,0 +1,10 @@
+/* Address for jumping to bootloader on STM32 chips. */
+/* It is chip dependent, the correct number can be looked up here (page 175):
+ * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf
+ * This also requires a patch to chibios:
+ * <tmk_dir>/tmk_core/tool/chibios/ch-bootloader-jump.patch
+ */
+
+// STM32F103* does NOT have an USB bootloader in ROM (only serial),
+// so setting anything here does not make much sense
+// #define STM32_BOOTLOADER_ADDRESS 0x1FFFC800
diff --git a/keyboards/chibios_test/stm32_f103_onekey/chconf.h b/keyboards/chibios_test/stm32_f103_onekey/chconf.h
new file mode 100644
index 000000000..dfb1f9dfb
--- /dev/null
+++ b/keyboards/chibios_test/stm32_f103_onekey/chconf.h
@@ -0,0 +1,524 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file templates/chconf.h
+ * @brief Configuration file template.
+ * @details A copy of this file must be placed in each project directory, it
+ * contains the application specific kernel settings.
+ *
+ * @addtogroup config
+ * @details Kernel related settings and hooks.
+ * @{
+ */
+
+#ifndef CHCONF_H
+#define CHCONF_H
+
+#define _CHIBIOS_RT_CONF_
+
+/*===========================================================================*/
+/**
+ * @name System timers settings
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief System time counter resolution.
+ * @note Allowed values are 16 or 32 bits.
+ */
+#define CH_CFG_ST_RESOLUTION 16
+
+/**
+ * @brief System tick frequency.
+ * @details Frequency of the system timer that drives the system ticks. This
+ * setting also defines the system tick time unit.
+ */
+#define CH_CFG_ST_FREQUENCY 2000
+
+/**
+ * @brief Time delta constant for the tick-less mode.
+ * @note If this value is zero then the system uses the classic
+ * periodic tick. This value represents the minimum number
+ * of ticks that is safe to specify in a timeout directive.
+ * The value one is not valid, timeouts are rounded up to
+ * this value.
+ */
+#define CH_CFG_ST_TIMEDELTA 2
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Kernel parameters and options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Round robin interval.
+ * @details This constant is the number of system ticks allowed for the
+ * threads before preemption occurs. Setting this value to zero
+ * disables the preemption for threads with equal priority and the
+ * round robin becomes cooperative. Note that higher priority
+ * threads can still preempt, the kernel is always preemptive.
+ * @note Disabling the round robin preemption makes the kernel more compact
+ * and generally faster.
+ * @note The round robin preemption is not supported in tickless mode and
+ * must be set to zero in that case.
+ */
+#define CH_CFG_TIME_QUANTUM 0
+
+/**
+ * @brief Managed RAM size.
+ * @details Size of the RAM area to be managed by the OS. If set to zero
+ * then the whole available RAM is used. The core memory is made
+ * available to the heap allocator and/or can be used directly through
+ * the simplified core memory allocator.
+ *
+ * @note In order to let the OS manage the whole RAM the linker script must
+ * provide the @p __heap_base__ and @p __heap_end__ symbols.
+ * @note Requires @p CH_CFG_USE_MEMCORE.
+ */
+#define CH_CFG_MEMCORE_SIZE 0
+
+/**
+ * @brief Idle thread automatic spawn suppression.
+ * @details When this option is activated the function @p chSysInit()
+ * does not spawn the idle thread. The application @p main()
+ * function becomes the idle thread and must implement an
+ * infinite loop.
+ */
+#define CH_CFG_NO_IDLE_THREAD FALSE
+
+/* Use __WFI in the idle thread for waiting. Does lower the power
+ * consumption. */
+#define CORTEX_ENABLE_WFI_IDLE TRUE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Performance options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief OS optimization.
+ * @details If enabled then time efficient rather than space efficient code
+ * is used when two possible implementations exist.
+ *
+ * @note This is not related to the compiler optimization options.
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_OPTIMIZE_SPEED TRUE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Subsystem options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Time Measurement APIs.
+ * @details If enabled then the time measurement APIs are included in
+ * the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_TM FALSE
+
+/**
+ * @brief Threads registry APIs.
+ * @details If enabled then the registry APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_REGISTRY TRUE
+
+/**
+ * @brief Threads synchronization APIs.
+ * @details If enabled then the @p chThdWait() function is included in
+ * the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_WAITEXIT TRUE
+
+/**
+ * @brief Semaphores APIs.
+ * @details If enabled then the Semaphores APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_SEMAPHORES TRUE
+
+/**
+ * @brief Semaphores queuing mode.
+ * @details If enabled then the threads are enqueued on semaphores by
+ * priority rather than in FIFO order.
+ *
+ * @note The default is @p FALSE. Enable this if you have special
+ * requirements.
+ * @note Requires @p CH_CFG_USE_SEMAPHORES.
+ */
+#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE
+
+/**
+ * @brief Mutexes APIs.
+ * @details If enabled then the mutexes APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MUTEXES TRUE
+
+/**
+ * @brief Enables recursive behavior on mutexes.
+ * @note Recursive mutexes are heavier and have an increased
+ * memory footprint.
+ *
+ * @note The default is @p FALSE.
+ * @note Requires @p CH_CFG_USE_MUTEXES.
+ */
+#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE
+
+/**
+ * @brief Conditional Variables APIs.
+ * @details If enabled then the conditional variables APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_MUTEXES.
+ */
+#define CH_CFG_USE_CONDVARS TRUE
+
+/**
+ * @brief Conditional Variables APIs with timeout.
+ * @details If enabled then the conditional variables APIs with timeout
+ * specification are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_CONDVARS.
+ */
+#define CH_CFG_USE_CONDVARS_TIMEOUT FALSE
+
+/**
+ * @brief Events Flags APIs.
+ * @details If enabled then the event flags APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_EVENTS TRUE
+
+/**
+ * @brief Events Flags APIs with timeout.
+ * @details If enabled then the events APIs with timeout specification
+ * are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_EVENTS.
+ */
+#define CH_CFG_USE_EVENTS_TIMEOUT TRUE
+
+/**
+ * @brief Synchronous Messages APIs.
+ * @details If enabled then the synchronous messages APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MESSAGES TRUE
+
+/**
+ * @brief Synchronous Messages queuing mode.
+ * @details If enabled then messages are served by priority rather than in
+ * FIFO order.
+ *
+ * @note The default is @p FALSE. Enable this if you have special
+ * requirements.
+ * @note Requires @p CH_CFG_USE_MESSAGES.
+ */
+#define CH_CFG_USE_MESSAGES_PRIORITY FALSE
+
+/**
+ * @brief Mailboxes APIs.
+ * @details If enabled then the asynchronous messages (mailboxes) APIs are
+ * included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_SEMAPHORES.
+ */
+#define CH_CFG_USE_MAILBOXES TRUE
+
+/**
+ * @brief Core Memory Manager APIs.
+ * @details If enabled then the core memory manager APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MEMCORE TRUE
+
+/**
+ * @brief Heap Allocator APIs.
+ * @details If enabled then the memory heap allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or
+ * @p CH_CFG_USE_SEMAPHORES.
+ * @note Mutexes are recommended.
+ */
+#define CH_CFG_USE_HEAP TRUE
+
+/**
+ * @brief Memory Pools Allocator APIs.
+ * @details If enabled then the memory pools allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MEMPOOLS FALSE
+
+/**
+ * @brief Dynamic Threads APIs.
+ * @details If enabled then the dynamic threads creation APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_WAITEXIT.
+ * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS.
+ */
+#define CH_CFG_USE_DYNAMIC FALSE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Debug options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Debug option, kernel statistics.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_STATISTICS FALSE
+
+/**
+ * @brief Debug option, system state check.
+ * @details If enabled the correct call protocol for system APIs is checked
+ * at runtime.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_SYSTEM_STATE_CHECK FALSE
+
+/**
+ * @brief Debug option, parameters checks.
+ * @details If enabled then the checks on the API functions input
+ * parameters are activated.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_ENABLE_CHECKS FALSE
+
+/**
+ * @brief Debug option, consistency checks.
+ * @details If enabled then all the assertions in the kernel code are
+ * activated. This includes consistency checks inside the kernel,
+ * runtime anomalies and port-defined checks.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_ENABLE_ASSERTS FALSE
+
+/**
+ * @brief Debug option, trace buffer.
+ * @details If enabled then the trace buffer is activated.
+ *
+ * @note The default is @p CH_DBG_TRACE_MASK_DISABLED.
+ */
+#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED
+
+/**
+ * @brief Trace buffer entries.
+ * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is
+ * different from @p CH_DBG_TRACE_MASK_DISABLED.
+ */
+#define CH_DBG_TRACE_BUFFER_SIZE 128
+
+/**
+ * @brief Debug option, stack checks.
+ * @details If enabled then a runtime stack check is performed.
+ *
+ * @note The default is @p FALSE.
+ * @note The stack check is performed in a architecture/port dependent way.
+ * It may not be implemented or some ports.
+ * @note The default failure mode is to halt the system with the global
+ * @p panic_msg variable set to @p NULL.
+ */
+#define CH_DBG_ENABLE_STACK_CHECK FALSE
+
+/**
+ * @brief Debug option, stacks initialization.
+ * @details If enabled then the threads working area is filled with a byte
+ * value when a thread is created. This can be useful for the
+ * runtime measurement of the used stack.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_FILL_THREADS FALSE
+
+/**
+ * @brief Debug option, threads profiling.
+ * @details If enabled then a field is added to the @p thread_t structure that
+ * counts the system ticks occurred while executing the thread.
+ *
+ * @note The default is @p FALSE.
+ * @note This debug option is not currently compatible with the
+ * tickless mode.
+ */
+#define CH_DBG_THREADS_PROFILING FALSE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Kernel hooks
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Threads descriptor structure extension.
+ * @details User fields added to the end of the @p thread_t structure.
+ */
+#define CH_CFG_THREAD_EXTRA_FIELDS \
+ /* Add threads custom fields here.*/
+
+/**
+ * @brief Threads initialization hook.
+ * @details User initialization code added to the @p chThdInit() API.
+ *
+ * @note It is invoked from within @p chThdInit() and implicitly from all
+ * the threads creation APIs.
+ */
+#define CH_CFG_THREAD_INIT_HOOK(tp) { \
+ /* Add threads initialization code here.*/ \
+}
+
+/**
+ * @brief Threads finalization hook.
+ * @details User finalization code added to the @p chThdExit() API.
+ */
+#define CH_CFG_THREAD_EXIT_HOOK(tp) { \
+ /* Add threads finalization code here.*/ \
+}
+
+/**
+ * @brief Context switch hook.
+ * @details This hook is invoked just before switching between threads.
+ */
+#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \
+ /* Context switch code here.*/ \
+}
+
+/**
+ * @brief ISR enter hook.
+ */
+#define CH_CFG_IRQ_PROLOGUE_HOOK() { \
+ /* IRQ prologue code here.*/ \
+}
+
+/**
+ * @brief ISR exit hook.
+ */
+#define CH_CFG_IRQ_EPILOGUE_HOOK() { \
+ /* IRQ epilogue code here.*/ \
+}
+
+/**
+ * @brief Idle thread enter hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to activate a power saving mode.
+ */
+#define CH_CFG_IDLE_ENTER_HOOK() { \
+ /* Idle-enter code here.*/ \
+}
+
+/**
+ * @brief Idle thread leave hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to deactivate a power saving mode.
+ */
+#define CH_CFG_IDLE_LEAVE_HOOK() { \
+ /* Idle-leave code here.*/ \
+}
+
+/**
+ * @brief Idle Loop hook.
+ * @details This hook is continuously invoked by the idle thread loop.
+ */
+#define CH_CFG_IDLE_LOOP_HOOK() { \
+ /* Idle loop code here.*/ \
+}
+
+/**
+ * @brief System tick event hook.
+ * @details This hook is invoked in the system tick handler immediately
+ * after processing the virtual timers queue.
+ */
+#define CH_CFG_SYSTEM_TICK_HOOK() { \
+ /* System tick event code here.*/ \
+}
+
+/**
+ * @brief System halt hook.
+ * @details This hook is invoked in case to a system halting error before
+ * the system is halted.
+ */
+#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \
+ /* System halt code here.*/ \
+}
+
+/**
+ * @brief Trace hook.
+ * @details This hook is invoked each time a new record is written in the
+ * trace buffer.
+ */
+#define CH_CFG_TRACE_HOOK(tep) { \
+ /* Trace code here.*/ \
+}
+
+/** @} */
+
+/*===========================================================================*/
+/* Port-specific settings (override port settings defaulted in chcore.h). */
+/*===========================================================================*/
+
+#endif /* CHCONF_H */
+
+/** @} */
diff --git a/keyboards/chibios_test/stm32_f103_onekey/config.h b/keyboards/chibios_test/stm32_f103_onekey/config.h
new file mode 100644
index 000000000..de0b906f3
--- /dev/null
+++ b/keyboards/chibios_test/stm32_f103_onekey/config.h
@@ -0,0 +1,6 @@
+#ifndef KEYBOARDS_CHIBIOS_TEST_STM32_F103_ONEKEY_CONFIG_H_
+#define KEYBOARDS_CHIBIOS_TEST_STM32_F103_ONEKEY_CONFIG_H_
+
+#include "../config.h"
+
+#endif /* KEYBOARDS_CHIBIOS_TEST_STM32_F103_ONEKEY_CONFIG_H_ */
diff --git a/keyboards/chibios_test/stm32_f103_onekey/flash.sh b/keyboards/chibios_test/stm32_f103_onekey/flash.sh
new file mode 100755
index 000000000..15501dfa5
--- /dev/null
+++ b/keyboards/chibios_test/stm32_f103_onekey/flash.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+Arduino_STM32_usb_hid/tools/linux/maple_upload ttyACM0 2 1EAF:0003 build/ch.bin
diff --git a/keyboards/chibios_test/stm32_f103_onekey/halconf.h b/keyboards/chibios_test/stm32_f103_onekey/halconf.h
new file mode 100644
index 000000000..1a450d632
--- /dev/null
+++ b/keyboards/chibios_test/stm32_f103_onekey/halconf.h
@@ -0,0 +1,353 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file templates/halconf.h
+ * @brief HAL configuration header.
+ * @details HAL configuration file, this file allows to enable or disable the
+ * various device drivers from your application. You may also use
+ * this file in order to override the device drivers default settings.
+ *
+ * @addtogroup HAL_CONF
+ * @{
+ */
+
+#ifndef _HALCONF_H_
+#define _HALCONF_H_
+
+#include "mcuconf.h"
+
+/**
+ * @brief Enables the PAL subsystem.
+ */
+#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__)
+#define HAL_USE_PAL TRUE
+#endif
+
+/**
+ * @brief Enables the ADC subsystem.
+ */
+#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__)
+#define HAL_USE_ADC FALSE
+#endif
+
+/**
+ * @brief Enables the CAN subsystem.
+ */
+#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__)
+#define HAL_USE_CAN FALSE
+#endif
+
+/**
+ * @brief Enables the DAC subsystem.
+ */
+#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__)
+#define HAL_USE_DAC FALSE
+#endif
+
+/**
+ * @brief Enables the EXT subsystem.
+ */
+#if !defined(HAL_USE_EXT) || defined(__DOXYGEN__)
+#define HAL_USE_EXT FALSE
+#endif
+
+/**
+ * @brief Enables the GPT subsystem.
+ */
+#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__)
+#define HAL_USE_GPT FALSE
+#endif
+
+/**
+ * @brief Enables the I2C subsystem.
+ */
+#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
+#define HAL_USE_I2C FALSE
+#endif
+
+/**
+ * @brief Enables the I2S subsystem.
+ */
+#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__)
+#define HAL_USE_I2S FALSE
+#endif
+
+/**
+ * @brief Enables the ICU subsystem.
+ */
+#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__)
+#define HAL_USE_ICU FALSE
+#endif
+
+/**
+ * @brief Enables the MAC subsystem.
+ */
+#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__)
+#define HAL_USE_MAC FALSE
+#endif
+
+/**
+ * @brief Enables the MMC_SPI subsystem.
+ */
+#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_MMC_SPI FALSE
+#endif
+
+/**
+ * @brief Enables the PWM subsystem.
+ */
+#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__)
+#define HAL_USE_PWM FALSE
+#endif
+
+/**
+ * @brief Enables the RTC subsystem.
+ */
+#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
+#define HAL_USE_RTC FALSE
+#endif
+
+/**
+ * @brief Enables the SDC subsystem.
+ */
+#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__)
+#define HAL_USE_SDC FALSE
+#endif
+
+/**
+ * @brief Enables the SERIAL subsystem.
+ */
+#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL FALSE
+#endif
+
+/**
+ * @brief Enables the SERIAL over USB subsystem.
+ */
+#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL_USB FALSE
+#endif
+
+/**
+ * @brief Enables the SPI subsystem.
+ */
+#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_SPI FALSE
+#endif
+
+/**
+ * @brief Enables the UART subsystem.
+ */
+#if !defined(HAL_USE_UART) || defined(__DOXYGEN__)
+#define HAL_USE_UART FALSE
+#endif
+
+/**
+ * @brief Enables the USB subsystem.
+ */
+#if !defined(HAL_USE_USB) || defined(__DOXYGEN__)
+#define HAL_USE_USB TRUE
+#endif
+
+/**
+ * @brief Enables the WDG subsystem.
+ */
+#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__)
+#define HAL_USE_WDG FALSE
+#endif
+
+/*===========================================================================*/
+/* ADC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__)
+#define ADC_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define ADC_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* CAN driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Sleep mode related APIs inclusion switch.
+ */
+#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
+#define CAN_USE_SLEEP_MODE TRUE
+#endif
+
+/*===========================================================================*/
+/* I2C driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables the mutual exclusion APIs on the I2C bus.
+ */
+#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define I2C_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* MAC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables an event sources for incoming packets.
+ */
+#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__)
+#define MAC_USE_ZERO_COPY FALSE
+#endif
+
+/**
+ * @brief Enables an event sources for incoming packets.
+ */
+#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__)
+#define MAC_USE_EVENTS TRUE
+#endif
+
+/*===========================================================================*/
+/* MMC_SPI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Delays insertions.
+ * @details If enabled this options inserts delays into the MMC waiting
+ * routines releasing some extra CPU time for the threads with
+ * lower priority, this may slow down the driver a bit however.
+ * This option is recommended also if the SPI driver does not
+ * use a DMA channel and heavily loads the CPU.
+ */
+#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__)
+#define MMC_NICE_WAITING TRUE
+#endif
+
+/*===========================================================================*/
+/* SDC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Number of initialization attempts before rejecting the card.
+ * @note Attempts are performed at 10mS intervals.
+ */
+#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__)
+#define SDC_INIT_RETRY 100
+#endif
+
+/**
+ * @brief Include support for MMC cards.
+ * @note MMC support is not yet implemented so this option must be kept
+ * at @p FALSE.
+ */
+#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__)
+#define SDC_MMC_SUPPORT FALSE
+#endif
+
+/**
+ * @brief Delays insertions.
+ * @details If enabled this options inserts delays into the MMC waiting
+ * routines releasing some extra CPU time for the threads with
+ * lower priority, this may slow down the driver a bit however.
+ */
+#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__)
+#define SDC_NICE_WAITING TRUE
+#endif
+
+/*===========================================================================*/
+/* SERIAL driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Default bit rate.
+ * @details Configuration parameter, this is the baud rate selected for the
+ * default configuration.
+ */
+#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__)
+#define SERIAL_DEFAULT_BITRATE 38400
+#endif
+
+/**
+ * @brief Serial buffers size.
+ * @details Configuration parameter, you can change the depth of the queue
+ * buffers depending on the requirements of your application.
+ * @note The default is 64 bytes for both the transmission and receive
+ * buffers.
+ */
+#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define SERIAL_BUFFERS_SIZE 16
+#endif
+
+/*===========================================================================*/
+/* SERIAL_USB driver related setting. */
+/*===========================================================================*/
+
+/**
+ * @brief Serial over USB buffers size.
+ * @details Configuration parameter, the buffer size must be a multiple of
+ * the USB data endpoint maximum packet size.
+ * @note The default is 64 bytes for both the transmission and receive
+ * buffers.
+ */
+#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define SERIAL_USB_BUFFERS_SIZE 256
+#endif
+
+/*===========================================================================*/
+/* SPI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__)
+#define SPI_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define SPI_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* USB driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__)
+#define USB_USE_WAIT TRUE
+#endif
+
+#endif /* _HALCONF_H_ */
+
+/** @} */
diff --git a/keyboards/chibios_test/stm32_f103_onekey/led.c b/keyboards/chibios_test/stm32_f103_onekey/led.c
new file mode 100644
index 000000000..f5c55f7d9
--- /dev/null
+++ b/keyboards/chibios_test/stm32_f103_onekey/led.c
@@ -0,0 +1,43 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "hal.h"
+#include "led.h"
+
+
+void led_set(uint8_t usb_led)
+{
+ if (usb_led & (1<<USB_LED_CAPS_LOCK)) {
+ /* generic STM32F103C8T6 board */
+#ifdef BOARD_GENERIC_STM32_F103
+ palClearPad(GPIOC, 13);
+#endif
+ /* Maple Mini */
+#ifdef BOARD_MAPLEMINI_STM32_F103
+ palSetPad(GPIOB, 1);
+#endif
+ } else {
+ /* generic STM32F103C8T6 board */
+#ifdef BOARD_GENERIC_STM32_F103
+ palSetPad(GPIOC, 13);
+#endif
+ /* Maple Mini */
+#ifdef BOARD_MAPLEMINI_STM32_F103
+ palClearPad(GPIOB,1);
+#endif
+ }
+}
diff --git a/keyboards/chibios_test/stm32_f103_onekey/matrix.c b/keyboards/chibios_test/stm32_f103_onekey/matrix.c
new file mode 100644
index 000000000..ea9d8d057
--- /dev/null
+++ b/keyboards/chibios_test/stm32_f103_onekey/matrix.c
@@ -0,0 +1,177 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "ch.h"
+#include "hal.h"
+
+/*
+ * scan matrix
+ */
+#include "print.h"
+#include "debug.h"
+#include "util.h"
+#include "matrix.h"
+#include "wait.h"
+
+#ifndef DEBOUNCE
+# define DEBOUNCE 5
+#endif
+static uint8_t debouncing = DEBOUNCE;
+
+/* matrix state(1:on, 0:off) */
+static matrix_row_t matrix[MATRIX_ROWS];
+static matrix_row_t matrix_debouncing[MATRIX_ROWS];
+
+static matrix_row_t read_cols(void);
+static void init_cols(void);
+static void unselect_rows(void);
+static void select_row(uint8_t row);
+
+
+inline
+uint8_t matrix_rows(void)
+{
+ return MATRIX_ROWS;
+}
+
+inline
+uint8_t matrix_cols(void)
+{
+ return MATRIX_COLS;
+}
+
+/* generic STM32F103C8T6 board */
+#ifdef BOARD_GENERIC_STM32_F103
+#define LED_ON() do { palClearPad(GPIOC, GPIOC_LED) ;} while (0)
+#define LED_OFF() do { palSetPad(GPIOC, GPIOC_LED); } while (0)
+#define LED_TGL() do { palTogglePad(GPIOC, GPIOC_LED); } while (0)
+#endif
+
+/* Maple Mini */
+#ifdef BOARD_MAPLEMINI_STM32_F103
+#define LED_ON() do { palSetPad(GPIOB, 1) ;} while (0)
+#define LED_OFF() do { palClearPad(GPIOB, 1); } while (0)
+#define LED_TGL() do { palTogglePad(GPIOB, 1); } while (0)
+#endif
+
+void matrix_init(void)
+{
+ // initialize row and col
+ unselect_rows();
+ init_cols();
+
+ // initialize matrix state: all keys off
+ for (uint8_t i=0; i < MATRIX_ROWS; i++) {
+ matrix[i] = 0;
+ matrix_debouncing[i] = 0;
+ }
+
+ //debug
+ debug_matrix = true;
+ LED_ON();
+ wait_ms(500);
+ LED_OFF();
+}
+
+uint8_t matrix_scan(void)
+{
+ for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+ select_row(i);
+ wait_us(30); // without this wait read unstable value.
+ matrix_row_t cols = read_cols();
+ if (matrix_debouncing[i] != cols) {
+ matrix_debouncing[i] = cols;
+ if (debouncing) {
+ debug("bounce!: "); debug_hex(debouncing); debug("\n");
+ }
+ debouncing = DEBOUNCE;
+ }
+ unselect_rows();
+ }
+
+ if (debouncing) {
+ if (--debouncing) {
+ wait_ms(1);
+ } else {
+ for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+ matrix[i] = matrix_debouncing[i];
+ }
+ }
+ }
+
+ return 1;
+}
+
+inline
+bool matrix_is_on(uint8_t row, uint8_t col)
+{
+ return (matrix[row] & ((matrix_row_t)1<<col));
+}
+
+inline
+matrix_row_t matrix_get_row(uint8_t row)
+{
+ return matrix[row];
+}
+
+void matrix_print(void)
+{
+ print("\nr/c 0123456789ABCDEF\n");
+ for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
+ phex(row); print(": ");
+ pbin_reverse16(matrix_get_row(row));
+ print("\n");
+ }
+}
+
+/* Column pin configuration
+ */
+static void init_cols(void)
+{
+#ifdef BOARD_MAPLEMINI_STM32_F103
+ // don't need pullup/down, since it's pulled down in hardware
+ palSetPadMode(GPIOB, 8, PAL_MODE_INPUT);
+#else
+ palSetPadMode(GPIOB, 8, PAL_MODE_INPUT_PULLDOWN);
+#endif
+}
+
+/* Returns status of switches(1:on, 0:off) */
+static matrix_row_t read_cols(void)
+{
+ return ((palReadPad(GPIOB, 8)==PAL_LOW) ? 0 : (1<<0));
+ // | ((palReadPad(...)==PAL_HIGH) ? 0 : (1<<1))
+}
+
+/* Row pin configuration
+ */
+static void unselect_rows(void)
+{
+ // palSetPadMode(GPIOA, GPIOA_PIN10, PAL_MODE_INPUT); // hi-Z
+}
+
+static void select_row(uint8_t row)
+{
+ (void)row;
+ // Output low to select
+ // switch (row) {
+ // case 0:
+ // palSetPadMode(GPIOA, GPIOA_PIN10, PAL_MODE_OUTPUT_PUSHPULL);
+ // palSetPad(GPIOA, GPIOA_PIN10, PAL_LOW);
+ // break;
+ // }
+}
diff --git a/keyboards/chibios_test/stm32_f103_onekey/mcuconf.h b/keyboards/chibios_test/stm32_f103_onekey/mcuconf.h
new file mode 100644
index 000000000..626332a6a
--- /dev/null
+++ b/keyboards/chibios_test/stm32_f103_onekey/mcuconf.h
@@ -0,0 +1,209 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#ifndef _MCUCONF_H_
+#define _MCUCONF_H_
+
+#define STM32F103_MCUCONF
+
+/*
+ * STM32F103 drivers configuration.
+ * The following settings override the default settings present in
+ * the various device driver implementation headers.
+ * Note that the settings for each driver only have effect if the whole
+ * driver is enabled in halconf.h.
+ *
+ * IRQ priorities:
+ * 15...0 Lowest...Highest.
+ *
+ * DMA priorities:
+ * 0...3 Lowest...Highest.
+ */
+
+/*
+ * HAL driver system settings.
+ */
+#define STM32_NO_INIT FALSE
+#define STM32_HSI_ENABLED TRUE
+#define STM32_LSI_ENABLED FALSE
+#define STM32_HSE_ENABLED TRUE
+#define STM32_LSE_ENABLED FALSE
+#define STM32_SW STM32_SW_PLL
+#define STM32_PLLSRC STM32_PLLSRC_HSE
+#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1
+#define STM32_PLLMUL_VALUE 9
+#define STM32_HPRE STM32_HPRE_DIV1
+#define STM32_PPRE1 STM32_PPRE1_DIV2
+#define STM32_PPRE2 STM32_PPRE2_DIV2
+#define STM32_ADCPRE STM32_ADCPRE_DIV4
+#define STM32_USB_CLOCK_REQUIRED TRUE
+#define STM32_USBPRE STM32_USBPRE_DIV1P5
+#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK
+#define STM32_RTCSEL STM32_RTCSEL_HSEDIV
+#define STM32_PVD_ENABLE FALSE
+#define STM32_PLS STM32_PLS_LEV0
+
+/*
+ * ADC driver system settings.
+ */
+#define STM32_ADC_USE_ADC1 FALSE
+#define STM32_ADC_ADC1_DMA_PRIORITY 2
+#define STM32_ADC_ADC1_IRQ_PRIORITY 6
+
+/*
+ * CAN driver system settings.
+ */
+#define STM32_CAN_USE_CAN1 FALSE
+#define STM32_CAN_CAN1_IRQ_PRIORITY 11
+
+/*
+ * EXT driver system settings.
+ */
+#define STM32_EXT_EXTI0_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI1_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI2_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI3_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI4_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI5_9_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI10_15_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI16_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI17_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI18_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI19_IRQ_PRIORITY 6
+
+/*
+ * GPT driver system settings.
+ */
+#define STM32_GPT_USE_TIM1 FALSE
+#define STM32_GPT_USE_TIM2 FALSE
+#define STM32_GPT_USE_TIM3 FALSE
+#define STM32_GPT_USE_TIM4 FALSE
+#define STM32_GPT_USE_TIM5 FALSE
+#define STM32_GPT_USE_TIM8 FALSE
+#define STM32_GPT_TIM1_IRQ_PRIORITY 7
+#define STM32_GPT_TIM2_IRQ_PRIORITY 7
+#define STM32_GPT_TIM3_IRQ_PRIORITY 7
+#define STM32_GPT_TIM4_IRQ_PRIORITY 7
+#define STM32_GPT_TIM5_IRQ_PRIORITY 7
+#define STM32_GPT_TIM8_IRQ_PRIORITY 7
+
+/*
+ * I2C driver system settings.
+ */
+#define STM32_I2C_USE_I2C1 FALSE
+#define STM32_I2C_USE_I2C2 FALSE
+#define STM32_I2C_BUSY_TIMEOUT 50
+#define STM32_I2C_I2C1_IRQ_PRIORITY 5
+#define STM32_I2C_I2C2_IRQ_PRIORITY 5
+#define STM32_I2C_I2C1_DMA_PRIORITY 3
+#define STM32_I2C_I2C2_DMA_PRIORITY 3
+#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure")
+
+/*
+ * ICU driver system settings.
+ */
+#define STM32_ICU_USE_TIM1 FALSE
+#define STM32_ICU_USE_TIM2 FALSE
+#define STM32_ICU_USE_TIM3 FALSE
+#define STM32_ICU_USE_TIM4 FALSE
+#define STM32_ICU_USE_TIM5 FALSE
+#define STM32_ICU_USE_TIM8 FALSE
+#define STM32_ICU_TIM1_IRQ_PRIORITY 7
+#define STM32_ICU_TIM2_IRQ_PRIORITY 7
+#define STM32_ICU_TIM3_IRQ_PRIORITY 7
+#define STM32_ICU_TIM4_IRQ_PRIORITY 7
+#define STM32_ICU_TIM5_IRQ_PRIORITY 7
+#define STM32_ICU_TIM8_IRQ_PRIORITY 7
+
+/*
+ * PWM driver system settings.
+ */
+#define STM32_PWM_USE_ADVANCED FALSE
+#define STM32_PWM_USE_TIM1 FALSE
+#define STM32_PWM_USE_TIM2 FALSE
+#define STM32_PWM_USE_TIM3 FALSE
+#define STM32_PWM_USE_TIM4 FALSE
+#define STM32_PWM_USE_TIM5 FALSE
+#define STM32_PWM_USE_TIM8 FALSE
+#define STM32_PWM_TIM1_IRQ_PRIORITY 7
+#define STM32_PWM_TIM2_IRQ_PRIORITY 7
+#define STM32_PWM_TIM3_IRQ_PRIORITY 7
+#define STM32_PWM_TIM4_IRQ_PRIORITY 7
+#define STM32_PWM_TIM5_IRQ_PRIORITY 7
+#define STM32_PWM_TIM8_IRQ_PRIORITY 7
+
+/*
+ * RTC driver system settings.
+ */
+#define STM32_RTC_IRQ_PRIORITY 15
+
+/*
+ * SERIAL driver system settings.
+ */
+#define STM32_SERIAL_USE_USART1 FALSE
+#define STM32_SERIAL_USE_USART2 FALSE
+#define STM32_SERIAL_USE_USART3 FALSE
+#define STM32_SERIAL_USE_UART4 FALSE
+#define STM32_SERIAL_USE_UART5 FALSE
+#define STM32_SERIAL_USART1_PRIORITY 12
+#define STM32_SERIAL_USART2_PRIORITY 12
+#define STM32_SERIAL_USART3_PRIORITY 12
+#define STM32_SERIAL_UART4_PRIORITY 12
+#define STM32_SERIAL_UART5_PRIORITY 12
+
+/*
+ * SPI driver system settings.
+ */
+#define STM32_SPI_USE_SPI1 FALSE
+#define STM32_SPI_USE_SPI2 FALSE
+#define STM32_SPI_USE_SPI3 FALSE
+#define STM32_SPI_SPI1_DMA_PRIORITY 1
+#define STM32_SPI_SPI2_DMA_PRIORITY 1
+#define STM32_SPI_SPI3_DMA_PRIORITY 1
+#define STM32_SPI_SPI1_IRQ_PRIORITY 10
+#define STM32_SPI_SPI2_IRQ_PRIORITY 10
+#define STM32_SPI_SPI3_IRQ_PRIORITY 10
+#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure")
+
+/*
+ * ST driver system settings.
+ */
+#define STM32_ST_IRQ_PRIORITY 8
+#define STM32_ST_USE_TIMER 2
+
+/*
+ * UART driver system settings.
+ */
+#define STM32_UART_USE_USART1 FALSE
+#define STM32_UART_USE_USART2 FALSE
+#define STM32_UART_USE_USART3 FALSE
+#define STM32_UART_USART1_IRQ_PRIORITY 12
+#define STM32_UART_USART2_IRQ_PRIORITY 12
+#define STM32_UART_USART3_IRQ_PRIORITY 12
+#define STM32_UART_USART1_DMA_PRIORITY 0
+#define STM32_UART_USART2_DMA_PRIORITY 0
+#define STM32_UART_USART3_DMA_PRIORITY 0
+#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure")
+
+/*
+ * USB driver system settings.
+ */
+#define STM32_USB_USE_USB1 TRUE
+#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE
+#define STM32_USB_USB1_HP_IRQ_PRIORITY 13
+#define STM32_USB_USB1_LP_IRQ_PRIORITY 14
+
+#endif /* _MCUCONF_H_ */
diff --git a/keyboards/chibios_test/stm32_f103_onekey/stm32_f103_onekey.c b/keyboards/chibios_test/stm32_f103_onekey/stm32_f103_onekey.c
new file mode 100644
index 000000000..7fa99bb28
--- /dev/null
+++ b/keyboards/chibios_test/stm32_f103_onekey/stm32_f103_onekey.c
@@ -0,0 +1 @@
+#include "stm32_f103_onekey.h"
diff --git a/keyboards/chibios_test/stm32_f103_onekey/stm32_f103_onekey.h b/keyboards/chibios_test/stm32_f103_onekey/stm32_f103_onekey.h
new file mode 100644
index 000000000..89a62b2bb
--- /dev/null
+++ b/keyboards/chibios_test/stm32_f103_onekey/stm32_f103_onekey.h
@@ -0,0 +1,4 @@
+#ifndef STM32_F103_ONEKEY_H
+#define STM32_F103_ONEKEY_H
+#include "chibios_test.h"
+#endif
diff --git a/keyboards/chibios_test/teensy_lc_onekey/Makefile b/keyboards/chibios_test/teensy_lc_onekey/Makefile
new file mode 100644
index 000000000..43ea9d82d
--- /dev/null
+++ b/keyboards/chibios_test/teensy_lc_onekey/Makefile
@@ -0,0 +1,49 @@
+# project specific files
+SRC = matrix.c \
+ led.c
+
+## chip/board settings
+# - the next two should match the directories in
+# <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
+# - For Teensies, FAMILY = KINETIS and SERIES is either
+# KL2x (LC) or K20x (3.0,3.1,3.2).
+MCU_FAMILY = KINETIS
+MCU_SERIES = KL2x
+
+# Linker script to use
+# - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+# or <this_dir>/ld/
+# - NOTE: a custom ld script is needed for EEPROM on Teensy LC
+# - LDSCRIPT =
+# - MKL26Z64 for Teensy LC
+# - MK20DX128 for Teensy 3.0
+# - MK20DX256 for Teensy 3.1 and 3.2
+MCU_LDSCRIPT = MKL26Z64
+
+# Startup code to use
+# - it should exist in <chibios>/os/common/ports/ARMCMx/compilers/GCC/mk/
+# - STARTUP =
+# - kl2x for Teensy LC
+# - k20x5 for Teensy 3.0
+# - k20x7 for Teensy 3.1 and 3.2
+MCU_STARTUP = kl2x
+
+# Board: it should exist either in <chibios>/os/hal/boards/
+# or <this_dir>/boards
+# - BOARD =
+# - PJRC_TEENSY_LC for Teensy LC
+# - PJRC_TEENSY_3 for Teensy 3.0
+# - PJRC_TEENSY_3_1 for Teensy 3.1 or 3.2
+BOARD = PJRC_TEENSY_LC
+
+# Cortex version
+# Teensy LC is cortex-m0plus; Teensy 3.x are cortex-m4
+MCU = cortex-m0plus
+
+# ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
+# I.e. 6 for Teensy LC; 7 for Teensy 3.x
+ARMV = 6
+
+ifndef QUANTUM_DIR
+ include ../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/chibios_test/teensy_lc_onekey/Makefile.3.0 b/keyboards/chibios_test/teensy_lc_onekey/Makefile.3.0
new file mode 100644
index 000000000..dbf12c363
--- /dev/null
+++ b/keyboards/chibios_test/teensy_lc_onekey/Makefile.3.0
@@ -0,0 +1,77 @@
+# Target file name (without extension).
+PROJECT = ch
+
+# Directory common source files exist
+TMK_DIR = ../../tmk_core
+
+# Directory keyboard dependent files exist
+TARGET_DIR = .
+
+# project specific files
+SRC = matrix.c \
+ led.c
+
+ifdef KEYMAP
+ SRC := keymap_$(KEYMAP).c $(SRC)
+else
+ SRC := keymap_plain.c $(SRC)
+endif
+
+CONFIG_H = config.h
+
+## chip/board settings
+# - the next two should match the directories in
+# <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
+# - For Teensies, FAMILY = KINETIS and SERIES is either
+# KL2x (LC) or K20x (3.0,3.1,3.2).
+MCU_FAMILY = KINETIS
+MCU_SERIES = K20x
+
+# Linker script to use
+# - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+# or <this_dir>/ld/
+# - NOTE: a custom ld script is needed for EEPROM on Teensy LC
+# - LDSCRIPT =
+# - MKL26Z64 for Teensy LC
+# - MK20DX128 for Teensy 3.0
+# - MK20DX256 for Teensy 3.1 and 3.2
+MCU_LDSCRIPT = MK20DX128
+
+# Startup code to use
+# - it should exist in <chibios>/os/common/ports/ARMCMx/compilers/GCC/mk/
+# - STARTUP =
+# - kl2x for Teensy LC
+# - k20x5 for Teensy 3.0
+# - k20x7 for Teensy 3.1 and 3.2
+MCU_STARTUP = k20x5
+
+# Board: it should exist either in <chibios>/os/hal/boards/
+# or <this_dir>/boards
+# - BOARD =
+# - PJRC_TEENSY_LC for Teensy LC
+# - PJRC_TEENSY_3 for Teensy 3.0
+# - PJRC_TEENSY_3_1 for Teensy 3.1 or 3.2
+BOARD = PJRC_TEENSY_3
+
+# Cortex version
+# Teensy LC is cortex-m0; Teensy 3.x are cortex-m4
+MCU = cortex-m4
+
+# ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
+# I.e. 6 for Teensy LC; 7 for Teensy 3.x
+ARMV = 7
+
+# Build Options
+# comment out to disable the options.
+#
+BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration
+## (Note that for BOOTMAGIC on Teensy LC you have to use a custom .ld script.)
+MOUSEKEY_ENABLE = yes # Mouse keys
+EXTRAKEY_ENABLE = yes # Audio control and System control
+CONSOLE_ENABLE = yes # Console for debug
+COMMAND_ENABLE = yes # Commands for debug and configuration
+SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend
+NKRO_ENABLE = yes # USB Nkey Rollover
+
+include $(TMK_DIR)/tool/chibios/common.mk
+include $(TMK_DIR)/tool/chibios/chibios.mk
diff --git a/keyboards/chibios_test/teensy_lc_onekey/Makefile.3.2 b/keyboards/chibios_test/teensy_lc_onekey/Makefile.3.2
new file mode 100644
index 000000000..41bfa41a0
--- /dev/null
+++ b/keyboards/chibios_test/teensy_lc_onekey/Makefile.3.2
@@ -0,0 +1,77 @@
+# Target file name (without extension).
+PROJECT = ch
+
+# Directory common source files exist
+TMK_DIR = ../../tmk_core
+
+# Directory keyboard dependent files exist
+TARGET_DIR = .
+
+# project specific files
+SRC = matrix.c \
+ led.c
+
+ifdef KEYMAP
+ SRC := keymap_$(KEYMAP).c $(SRC)
+else
+ SRC := keymap_plain.c $(SRC)
+endif
+
+CONFIG_H = config.h
+
+## chip/board settings
+# - the next two should match the directories in
+# <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
+# - For Teensies, FAMILY = KINETIS and SERIES is either
+# KL2x (LC) or K20x (3.0,3.1,3.2).
+MCU_FAMILY = KINETIS
+MCU_SERIES = K20x
+
+# Linker script to use
+# - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+# or <this_dir>/ld/
+# - NOTE: a custom ld script is needed for EEPROM on Teensy LC
+# - LDSCRIPT =
+# - MKL26Z64 for Teensy LC
+# - MK20DX128 for Teensy 3.0
+# - MK20DX256 for Teensy 3.1 and 3.2
+MCU_LDSCRIPT = MK20DX256
+
+# Startup code to use
+# - it should exist in <chibios>/os/common/ports/ARMCMx/compilers/GCC/mk/
+# - STARTUP =
+# - kl2x for Teensy LC
+# - k20x5 for Teensy 3.0
+# - k20x7 for Teensy 3.1 and 3.2
+MCU_STARTUP = k20x7
+
+# Board: it should exist either in <chibios>/os/hal/boards/
+# or <this_dir>/boards
+# - BOARD =
+# - PJRC_TEENSY_LC for Teensy LC
+# - PJRC_TEENSY_3 for Teensy 3.0
+# - PJRC_TEENSY_3_1 for Teensy 3.1 or 3.2
+BOARD = PJRC_TEENSY_3_1
+
+# Cortex version
+# Teensy LC is cortex-m0; Teensy 3.x are cortex-m4
+MCU = cortex-m4
+
+# ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
+# I.e. 6 for Teensy LC; 7 for Teensy 3.x
+ARMV = 7
+
+# Build Options
+# comment out to disable the options.
+#
+BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration
+## (Note that for BOOTMAGIC on Teensy LC you have to use a custom .ld script.)
+MOUSEKEY_ENABLE = yes # Mouse keys
+EXTRAKEY_ENABLE = yes # Audio control and System control
+CONSOLE_ENABLE = yes # Console for debug
+COMMAND_ENABLE = yes # Commands for debug and configuration
+SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend
+NKRO_ENABLE = yes # USB Nkey Rollover
+
+include $(TMK_DIR)/tool/chibios/common.mk
+include $(TMK_DIR)/tool/chibios/chibios.mk
diff --git a/keyboards/chibios_test/teensy_lc_onekey/chconf.h b/keyboards/chibios_test/teensy_lc_onekey/chconf.h
new file mode 100644
index 000000000..cb36996c3
--- /dev/null
+++ b/keyboards/chibios_test/teensy_lc_onekey/chconf.h
@@ -0,0 +1,524 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file templates/chconf.h
+ * @brief Configuration file template.
+ * @details A copy of this file must be placed in each project directory, it
+ * contains the application specific kernel settings.
+ *
+ * @addtogroup config
+ * @details Kernel related settings and hooks.
+ * @{
+ */
+
+#ifndef CHCONF_H
+#define CHCONF_H
+
+#define _CHIBIOS_RT_CONF_
+
+/*===========================================================================*/
+/**
+ * @name System timers settings
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief System time counter resolution.
+ * @note Allowed values are 16 or 32 bits.
+ */
+#define CH_CFG_ST_RESOLUTION 32
+
+/**
+ * @brief System tick frequency.
+ * @details Frequency of the system timer that drives the system ticks. This
+ * setting also defines the system tick time unit.
+ */
+#define CH_CFG_ST_FREQUENCY 1000
+
+/**
+ * @brief Time delta constant for the tick-less mode.
+ * @note If this value is zero then the system uses the classic
+ * periodic tick. This value represents the minimum number
+ * of ticks that is safe to specify in a timeout directive.
+ * The value one is not valid, timeouts are rounded up to
+ * this value.
+ */
+#define CH_CFG_ST_TIMEDELTA 0
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Kernel parameters and options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Round robin interval.
+ * @details This constant is the number of system ticks allowed for the
+ * threads before preemption occurs. Setting this value to zero
+ * disables the preemption for threads with equal priority and the
+ * round robin becomes cooperative. Note that higher priority
+ * threads can still preempt, the kernel is always preemptive.
+ * @note Disabling the round robin preemption makes the kernel more compact
+ * and generally faster.
+ * @note The round robin preemption is not supported in tickless mode and
+ * must be set to zero in that case.
+ */
+#define CH_CFG_TIME_QUANTUM 20
+
+/**
+ * @brief Managed RAM size.
+ * @details Size of the RAM area to be managed by the OS. If set to zero
+ * then the whole available RAM is used. The core memory is made
+ * available to the heap allocator and/or can be used directly through
+ * the simplified core memory allocator.
+ *
+ * @note In order to let the OS manage the whole RAM the linker script must
+ * provide the @p __heap_base__ and @p __heap_end__ symbols.
+ * @note Requires @p CH_CFG_USE_MEMCORE.
+ */
+#define CH_CFG_MEMCORE_SIZE 0
+
+/**
+ * @brief Idle thread automatic spawn suppression.
+ * @details When this option is activated the function @p chSysInit()
+ * does not spawn the idle thread. The application @p main()
+ * function becomes the idle thread and must implement an
+ * infinite loop.
+ */
+#define CH_CFG_NO_IDLE_THREAD FALSE
+
+/* Use __WFI in the idle thread for waiting. Does lower the power
+ * consumption. */
+#define CORTEX_ENABLE_WFI_IDLE TRUE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Performance options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief OS optimization.
+ * @details If enabled then time efficient rather than space efficient code
+ * is used when two possible implementations exist.
+ *
+ * @note This is not related to the compiler optimization options.
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_OPTIMIZE_SPEED TRUE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Subsystem options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Time Measurement APIs.
+ * @details If enabled then the time measurement APIs are included in
+ * the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_TM FALSE
+
+/**
+ * @brief Threads registry APIs.
+ * @details If enabled then the registry APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_REGISTRY TRUE
+
+/**
+ * @brief Threads synchronization APIs.
+ * @details If enabled then the @p chThdWait() function is included in
+ * the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_WAITEXIT TRUE
+
+/**
+ * @brief Semaphores APIs.
+ * @details If enabled then the Semaphores APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_SEMAPHORES TRUE
+
+/**
+ * @brief Semaphores queuing mode.
+ * @details If enabled then the threads are enqueued on semaphores by
+ * priority rather than in FIFO order.
+ *
+ * @note The default is @p FALSE. Enable this if you have special
+ * requirements.
+ * @note Requires @p CH_CFG_USE_SEMAPHORES.
+ */
+#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE
+
+/**
+ * @brief Mutexes APIs.
+ * @details If enabled then the mutexes APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MUTEXES TRUE
+
+/**
+ * @brief Enables recursive behavior on mutexes.
+ * @note Recursive mutexes are heavier and have an increased
+ * memory footprint.
+ *
+ * @note The default is @p FALSE.
+ * @note Requires @p CH_CFG_USE_MUTEXES.
+ */
+#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE
+
+/**
+ * @brief Conditional Variables APIs.
+ * @details If enabled then the conditional variables APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_MUTEXES.
+ */
+#define CH_CFG_USE_CONDVARS TRUE
+
+/**
+ * @brief Conditional Variables APIs with timeout.
+ * @details If enabled then the conditional variables APIs with timeout
+ * specification are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_CONDVARS.
+ */
+#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE
+
+/**
+ * @brief Events Flags APIs.
+ * @details If enabled then the event flags APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_EVENTS TRUE
+
+/**
+ * @brief Events Flags APIs with timeout.
+ * @details If enabled then the events APIs with timeout specification
+ * are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_EVENTS.
+ */
+#define CH_CFG_USE_EVENTS_TIMEOUT TRUE
+
+/**
+ * @brief Synchronous Messages APIs.
+ * @details If enabled then the synchronous messages APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MESSAGES TRUE
+
+/**
+ * @brief Synchronous Messages queuing mode.
+ * @details If enabled then messages are served by priority rather than in
+ * FIFO order.
+ *
+ * @note The default is @p FALSE. Enable this if you have special
+ * requirements.
+ * @note Requires @p CH_CFG_USE_MESSAGES.
+ */
+#define CH_CFG_USE_MESSAGES_PRIORITY FALSE
+
+/**
+ * @brief Mailboxes APIs.
+ * @details If enabled then the asynchronous messages (mailboxes) APIs are
+ * included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_SEMAPHORES.
+ */
+#define CH_CFG_USE_MAILBOXES TRUE
+
+/**
+ * @brief Core Memory Manager APIs.
+ * @details If enabled then the core memory manager APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MEMCORE TRUE
+
+/**
+ * @brief Heap Allocator APIs.
+ * @details If enabled then the memory heap allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or
+ * @p CH_CFG_USE_SEMAPHORES.
+ * @note Mutexes are recommended.
+ */
+#define CH_CFG_USE_HEAP TRUE
+
+/**
+ * @brief Memory Pools Allocator APIs.
+ * @details If enabled then the memory pools allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MEMPOOLS TRUE
+
+/**
+ * @brief Dynamic Threads APIs.
+ * @details If enabled then the dynamic threads creation APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_WAITEXIT.
+ * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS.
+ */
+#define CH_CFG_USE_DYNAMIC TRUE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Debug options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Debug option, kernel statistics.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_STATISTICS FALSE
+
+/**
+ * @brief Debug option, system state check.
+ * @details If enabled the correct call protocol for system APIs is checked
+ * at runtime.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_SYSTEM_STATE_CHECK TRUE
+
+/**
+ * @brief Debug option, parameters checks.
+ * @details If enabled then the checks on the API functions input
+ * parameters are activated.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_ENABLE_CHECKS TRUE
+
+/**
+ * @brief Debug option, consistency checks.
+ * @details If enabled then all the assertions in the kernel code are
+ * activated. This includes consistency checks inside the kernel,
+ * runtime anomalies and port-defined checks.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_ENABLE_ASSERTS TRUE
+
+/**
+ * @brief Debug option, trace buffer.
+ * @details If enabled then the trace buffer is activated.
+ *
+ * @note The default is @p CH_DBG_TRACE_MASK_DISABLED.
+ */
+#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED
+
+/**
+ * @brief Trace buffer entries.
+ * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is
+ * different from @p CH_DBG_TRACE_MASK_DISABLED.
+ */
+#define CH_DBG_TRACE_BUFFER_SIZE 128
+
+/**
+ * @brief Debug option, stack checks.
+ * @details If enabled then a runtime stack check is performed.
+ *
+ * @note The default is @p FALSE.
+ * @note The stack check is performed in a architecture/port dependent way.
+ * It may not be implemented or some ports.
+ * @note The default failure mode is to halt the system with the global
+ * @p panic_msg variable set to @p NULL.
+ */
+#define CH_DBG_ENABLE_STACK_CHECK TRUE
+
+/**
+ * @brief Debug option, stacks initialization.
+ * @details If enabled then the threads working area is filled with a byte
+ * value when a thread is created. This can be useful for the
+ * runtime measurement of the used stack.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_FILL_THREADS TRUE
+
+/**
+ * @brief Debug option, threads profiling.
+ * @details If enabled then a field is added to the @p thread_t structure that
+ * counts the system ticks occurred while executing the thread.
+ *
+ * @note The default is @p FALSE.
+ * @note This debug option is not currently compatible with the
+ * tickless mode.
+ */
+#define CH_DBG_THREADS_PROFILING FALSE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Kernel hooks
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Threads descriptor structure extension.
+ * @details User fields added to the end of the @p thread_t structure.
+ */
+#define CH_CFG_THREAD_EXTRA_FIELDS \
+ /* Add threads custom fields here.*/
+
+/**
+ * @brief Threads initialization hook.
+ * @details User initialization code added to the @p chThdInit() API.
+ *
+ * @note It is invoked from within @p chThdInit() and implicitly from all
+ * the threads creation APIs.
+ */
+#define CH_CFG_THREAD_INIT_HOOK(tp) { \
+ /* Add threads initialization code here.*/ \
+}
+
+/**
+ * @brief Threads finalization hook.
+ * @details User finalization code added to the @p chThdExit() API.
+ */
+#define CH_CFG_THREAD_EXIT_HOOK(tp) { \
+ /* Add threads finalization code here.*/ \
+}
+
+/**
+ * @brief Context switch hook.
+ * @details This hook is invoked just before switching between threads.
+ */
+#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \
+ /* Context switch code here.*/ \
+}
+
+/**
+ * @brief ISR enter hook.
+ */
+#define CH_CFG_IRQ_PROLOGUE_HOOK() { \
+ /* IRQ prologue code here.*/ \
+}
+
+/**
+ * @brief ISR exit hook.
+ */
+#define CH_CFG_IRQ_EPILOGUE_HOOK() { \
+ /* IRQ epilogue code here.*/ \
+}
+
+/**
+ * @brief Idle thread enter hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to activate a power saving mode.
+ */
+#define CH_CFG_IDLE_ENTER_HOOK() { \
+ /* Idle-enter code here.*/ \
+}
+
+/**
+ * @brief Idle thread leave hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to deactivate a power saving mode.
+ */
+#define CH_CFG_IDLE_LEAVE_HOOK() { \
+ /* Idle-leave code here.*/ \
+}
+
+/**
+ * @brief Idle Loop hook.
+ * @details This hook is continuously invoked by the idle thread loop.
+ */
+#define CH_CFG_IDLE_LOOP_HOOK() { \
+ /* Idle loop code here.*/ \
+}
+
+/**
+ * @brief System tick event hook.
+ * @details This hook is invoked in the system tick handler immediately
+ * after processing the virtual timers queue.
+ */
+#define CH_CFG_SYSTEM_TICK_HOOK() { \
+ /* System tick event code here.*/ \
+}
+
+/**
+ * @brief System halt hook.
+ * @details This hook is invoked in case to a system halting error before
+ * the system is halted.
+ */
+#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \
+ /* System halt code here.*/ \
+}
+
+/**
+ * @brief Trace hook.
+ * @details This hook is invoked each time a new record is written in the
+ * trace buffer.
+ */
+#define CH_CFG_TRACE_HOOK(tep) { \
+ /* Trace code here.*/ \
+}
+
+/** @} */
+
+/*===========================================================================*/
+/* Port-specific settings (override port settings defaulted in chcore.h). */
+/*===========================================================================*/
+
+#endif /* CHCONF_H */
+
+/** @} */
diff --git a/keyboards/chibios_test/teensy_lc_onekey/config.h b/keyboards/chibios_test/teensy_lc_onekey/config.h
new file mode 100644
index 000000000..d9eb05d2a
--- /dev/null
+++ b/keyboards/chibios_test/teensy_lc_onekey/config.h
@@ -0,0 +1,6 @@
+#ifndef KEYBOARDS_CHIBIOS_TEST_TEENSY_LC_ONEKEY_CONFIG_H_
+#define KEYBOARDS_CHIBIOS_TEST_TEENSY_LC_ONEKEY_CONFIG_H_
+
+#include "../config.h"
+
+#endif /* KEYBOARDS_CHIBIOS_TEST_TEENSY_LC_ONEKEY_CONFIG_H_ */
diff --git a/keyboards/chibios_test/teensy_lc_onekey/halconf.h b/keyboards/chibios_test/teensy_lc_onekey/halconf.h
new file mode 100644
index 000000000..b1d2cd550
--- /dev/null
+++ b/keyboards/chibios_test/teensy_lc_onekey/halconf.h
@@ -0,0 +1,187 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file templates/halconf.h
+ * @brief HAL configuration header.
+ * @details HAL configuration file, this file allows to enable or disable the
+ * various device drivers from your application. You may also use
+ * this file in order to override the device drivers default settings.
+ *
+ * @addtogroup HAL_CONF
+ * @{
+ */
+
+#ifndef _HALCONF_H_
+#define _HALCONF_H_
+
+#include "mcuconf.h"
+
+/**
+ * @brief Enables the PAL subsystem.
+ */
+#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__)
+#define HAL_USE_PAL TRUE
+#endif
+
+/**
+ * @brief Enables the ADC subsystem.
+ */
+#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__)
+#define HAL_USE_ADC FALSE
+#endif
+
+/**
+ * @brief Enables the CAN subsystem.
+ */
+#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__)
+#define HAL_USE_CAN FALSE
+#endif
+
+/**
+ * @brief Enables the DAC subsystem.
+ */
+#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__)
+#define HAL_USE_DAC FALSE
+#endif
+
+/**
+ * @brief Enables the EXT subsystem.
+ */
+#if !defined(HAL_USE_EXT) || defined(__DOXYGEN__)
+#define HAL_USE_EXT FALSE
+#endif
+
+/**
+ * @brief Enables the GPT subsystem.
+ */
+#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__)
+#define HAL_USE_GPT FALSE
+#endif
+
+/**
+ * @brief Enables the I2C subsystem.
+ */
+#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
+#define HAL_USE_I2C FALSE
+#endif
+
+/**
+ * @brief Enables the I2S subsystem.
+ */
+#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__)
+#define HAL_USE_I2S FALSE
+#endif
+
+/**
+ * @brief Enables the ICU subsystem.
+ */
+#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__)
+#define HAL_USE_ICU FALSE
+#endif
+
+/**
+ * @brief Enables the MAC subsystem.
+ */
+#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__)
+#define HAL_USE_MAC FALSE
+#endif
+
+/**
+ * @brief Enables the MMC_SPI subsystem.
+ */
+#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_MMC_SPI FALSE
+#endif
+
+/**
+ * @brief Enables the PWM subsystem.
+ */
+#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__)
+#define HAL_USE_PWM FALSE
+#endif
+
+/**
+ * @brief Enables the RTC subsystem.
+ */
+#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
+#define HAL_USE_RTC FALSE
+#endif
+
+/**
+ * @brief Enables the SDC subsystem.
+ */
+#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__)
+#define HAL_USE_SDC FALSE
+#endif
+
+/**
+ * @brief Enables the SERIAL subsystem.
+ */
+#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL FALSE
+#endif
+
+/**
+ * @brief Enables the SERIAL over USB subsystem.
+ */
+#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL_USB FALSE
+#endif
+
+/**
+ * @brief Enables the SPI subsystem.
+ */
+#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_SPI FALSE
+#endif
+
+/**
+ * @brief Enables the UART subsystem.
+ */
+#if !defined(HAL_USE_UART) || defined(__DOXYGEN__)
+#define HAL_USE_UART FALSE
+#endif
+
+/**
+ * @brief Enables the USB subsystem.
+ */
+#if !defined(HAL_USE_USB) || defined(__DOXYGEN__)
+#define HAL_USE_USB TRUE
+#endif
+
+/**
+ * @brief Enables the WDG subsystem.
+ */
+#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__)
+#define HAL_USE_WDG FALSE
+#endif
+
+/*===========================================================================*/
+/* USB driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__)
+#define USB_USE_WAIT TRUE
+#endif
+
+#endif /* _HALCONF_H_ */
+
+/** @} */
diff --git a/keyboards/chibios_test/teensy_lc_onekey/instructions.md b/keyboards/chibios_test/teensy_lc_onekey/instructions.md
new file mode 100644
index 000000000..16886a015
--- /dev/null
+++ b/keyboards/chibios_test/teensy_lc_onekey/instructions.md
@@ -0,0 +1,82 @@
+# Teensy LC, 3.0, 3.1, 3.2 support
+
+These ARM Teensies are now supported through [ChibiOS](http://chibios.org).
+
+You'll need to install an ARM toolchain, for instance from [gcc ARM embedded](https://launchpad.net/gcc-arm-embedded) website, or using your favourite package manager. After installing, you should be able to run `arm-none-eabi-gcc -v` in the command prompt and get sensible output. This toolchain is used instead of `avr-gcc`, which is only for AVR chips. Naturally you'll also need the usual development tools (e.g. `make`), just as in the AVR setting.
+
+Next, you'll need ChibiOS. For Teensies, you'll need code from two repositories: [chibios-main](https://github.com/ChibiOS/ChibiOS) and [chibios-contrib](https://github.com/ChibiOS/ChibiOS). If you're not using git, you can just download a [zip of chibios from here](https://github.com/ChibiOS/ChibiOS/archive/a7df9a891067621e8e1a5c2a2c0ceada82403afe.zip), unpack the zip, and rename/move the unpacked directory (named `ChibiOS-<long_hash_here>`) to `tmk_core/tool/chibios/chibios` (so that the file `tmk_core/tool/chibios/chibios/license.txt` exists). Now the same procedure with a [zip of chibios-contrib from here](https://github.com/ChibiOS/ChibiOS-Contrib/archive/e1311c4db6cd366cf760673f769e925741ac0ad3.zip): unpack and move `ChibiOS-Contrib-<long_hash_here>` to `tmk_core/tool/chibios/chibios-contrib`.
+
+(If you're using git, you can just clone the two repos: [chibios](https://github.com/ChibiOS/ChibiOS) and [chibios-contrib](https://github.com/ChibiOS/ChibiOS-Contrib). However - be warned that things may be somewhat out-of-sync (updates at different rates), so you may need to hunt a bit for the right commits.)
+
+(Why do we need chibios-contrib? Well, the main repo focuses on STM32 chips, and Freescale/NXP Kinetis chips are supported via the Contrib repository.)
+
+This should be it. Running `make` in `keyboard/teensy_lc_onekey` should create a working firmware in `build/`, called `ch.hex`.
+
+For more notes about the ChibiOS backend in TMK, see `tmk_core/protocol/chibios/README.md`.
+
+## About this onekey example
+
+It's set up for Teensy LC. To use 3.x, you'll need to edit the `Makefile` (and comment out one line in `mcuconf.h`). A sample makefile for Teensy 3.0 is provided as `Makefile.3.0`, can be used without renaming with `make -f Makefile.3.0`. Similarly for Teensy 3.2, there's `Makefile.3.2`.
+
+## Credits
+
+TMK itself is written by hasu, original sources [here](https://github.com/tmk/tmk_keyboard).
+
+The USB support for Kinetis MCUs is due to RedoX. His ChibiOS fork is also [on github](https://github.com/RedoXyde/ChibiOS); but it doesn't include Teensy LC definitions.
+
+## Features that are not implemented yet
+
+Currently only the more fancy suspend features are not there (power saving during suspend). The rest should work fine (reports either way are welcome).
+
+# Matrix programming notes
+
+The notes below explain what commands can be used to examine and set the status of Teensy pins.
+
+## ChibiOS pin manipulation basics
+
+### Pins
+
+Each pin sits on a "port", each of which comprises at most 32 individual pins.
+So for instance "PTC5" from Kinetis manual/datasheet refers to port C (or GPIOA), pin 5. Most functions dealing with pins take 2 parameters which specify the pin -- the first being the port, the second being the pin number.
+
+Within ChibiOS, there are definitions which simplify this a bit for the Teensies. `TEENSY_PINn_IOPORT` represents the port of the MCU's pin connected Teensy's PIN `n`, and `TEENSY_PINn` represents its MCU's pin number.
+
+### Mode
+
+A MCU pin can be in several modes. The basic command to set a pin mode is
+
+ palSetPadMode(TEENSY_PINn_IOPORT, TEENSY_PINn, PAL_MODE_INPUT_PULLUP);
+
+The last parameter is the mode. For keyboards, the usual ones that are used are `PAL_MODE_INPUT_PULLUP` (input with a pullup), `PAL_MODE_INPUT_PULLDOWN` (input with a pulldown), `PAL_MODE_INPUT` (input floating, a.k.a. Hi-Z), `PAL_MODE_OUTPUT_PUSHPULL` (output in the Arduino sense -- can be then set HIGH or LOW).
+
+### Setting
+
+Pins are set HIGH (after they've been put into `OUTPUT_PUSHPULL` mode) by
+
+ palSetPad(TEENSY_PINn_IOPORT, TEENSY_PINn);
+
+or set LOW by
+
+ palClearPad(TEENSY_PINn_IOPORT, TEENSY_PINn);
+
+Toggling can be done with
+
+ palTogglePad(TEENSY_PINn_IOPORT, TEENSY_PINn);
+
+Alternatively, you can use
+
+ palWritePad(TEENSY_PINn_IOPORT, TEENSY_PINn, bit);
+
+where `bit` is either `PAL_LOW` or `PAL_HIGH` (i.e. `0` or `1`).
+
+### Reading
+
+Reading pin status is done with
+
+ palReadPad(TEENSY_PINn_IOPORT, TEENSY_PINn);
+
+The function returns either `PAL_HIGH` (actually `1`) or `PAL_LOW` (actually `0`).
+
+### Further docs
+
+All the commands that are available for pin manipulation through ChibiOS HAL are documented in [ChibiOS PAL driver docs](http://chibios.sourceforge.net/docs3/hal/group___p_a_l.html).
diff --git a/keyboards/chibios_test/teensy_lc_onekey/led.c b/keyboards/chibios_test/teensy_lc_onekey/led.c
new file mode 100644
index 000000000..dfa60c107
--- /dev/null
+++ b/keyboards/chibios_test/teensy_lc_onekey/led.c
@@ -0,0 +1,32 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "hal.h"
+
+#include "led.h"
+
+
+void led_set(uint8_t usb_led) {
+ if (usb_led & (1<<USB_LED_CAPS_LOCK)) {
+ // output high
+ palSetPadMode(TEENSY_PIN13_IOPORT, TEENSY_PIN13, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPad(TEENSY_PIN13_IOPORT, TEENSY_PIN13);
+ } else {
+ // Hi-Z
+ palSetPadMode(TEENSY_PIN13_IOPORT, TEENSY_PIN13, PAL_MODE_INPUT);
+ }
+}
diff --git a/keyboards/chibios_test/teensy_lc_onekey/matrix.c b/keyboards/chibios_test/teensy_lc_onekey/matrix.c
new file mode 100644
index 000000000..7dab04f02
--- /dev/null
+++ b/keyboards/chibios_test/teensy_lc_onekey/matrix.c
@@ -0,0 +1,163 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "ch.h"
+#include "hal.h"
+
+/*
+ * scan matrix
+ */
+#include "print.h"
+#include "debug.h"
+#include "util.h"
+#include "matrix.h"
+#include "wait.h"
+
+#ifndef DEBOUNCE
+# define DEBOUNCE 5
+#endif
+static uint8_t debouncing = DEBOUNCE;
+
+/* matrix state(1:on, 0:off) */
+static matrix_row_t matrix[MATRIX_ROWS];
+static matrix_row_t matrix_debouncing[MATRIX_ROWS];
+
+static matrix_row_t read_cols(void);
+static void init_cols(void);
+static void unselect_rows(void);
+static void select_row(uint8_t row);
+
+
+inline
+uint8_t matrix_rows(void)
+{
+ return MATRIX_ROWS;
+}
+
+inline
+uint8_t matrix_cols(void)
+{
+ return MATRIX_COLS;
+}
+
+#define LED_ON() do { palSetPad(TEENSY_PIN13_IOPORT, TEENSY_PIN13) ;} while (0)
+#define LED_OFF() do { palClearPad(TEENSY_PIN13_IOPORT, TEENSY_PIN13); } while (0)
+#define LED_TGL() do { palTogglePad(TEENSY_PIN13_IOPORT, TEENSY_PIN13); } while (0)
+
+void matrix_init(void)
+{
+ // initialize row and col
+ unselect_rows();
+ init_cols();
+
+ // initialize matrix state: all keys off
+ for (uint8_t i=0; i < MATRIX_ROWS; i++) {
+ matrix[i] = 0;
+ matrix_debouncing[i] = 0;
+ }
+
+ //debug
+ debug_matrix = true;
+ LED_ON();
+ wait_ms(500);
+ LED_OFF();
+}
+
+uint8_t matrix_scan(void)
+{
+ for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+ select_row(i);
+ wait_us(30); // without this wait read unstable value.
+ matrix_row_t cols = read_cols();
+ if (matrix_debouncing[i] != cols) {
+ matrix_debouncing[i] = cols;
+ if (debouncing) {
+ debug("bounce!: "); debug_hex(debouncing); debug("\n");
+ }
+ debouncing = DEBOUNCE;
+ }
+ unselect_rows();
+ }
+
+ if (debouncing) {
+ if (--debouncing) {
+ wait_ms(1);
+ } else {
+ for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+ matrix[i] = matrix_debouncing[i];
+ }
+ }
+ }
+
+ return 1;
+}
+
+inline
+bool matrix_is_on(uint8_t row, uint8_t col)
+{
+ return (matrix[row] & ((matrix_row_t)1<<col));
+}
+
+inline
+matrix_row_t matrix_get_row(uint8_t row)
+{
+ return matrix[row];
+}
+
+void matrix_print(void)
+{
+ print("\nr/c 0123456789ABCDEF\n");
+ for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
+ phex(row); print(": ");
+ pbin_reverse16(matrix_get_row(row));
+ print("\n");
+ }
+}
+
+/* Column pin configuration
+ */
+static void init_cols(void)
+{
+ // internal pull-up
+ palSetPadMode(TEENSY_PIN2_IOPORT, TEENSY_PIN2, PAL_MODE_INPUT_PULLUP);
+}
+
+/* Returns status of switches(1:on, 0:off) */
+static matrix_row_t read_cols(void)
+{
+ return ((palReadPad(TEENSY_PIN2_IOPORT, TEENSY_PIN2)==PAL_HIGH) ? 0 : (1<<0));
+ // | ((palReadPad(...)==PAL_HIGH) ? 0 : (1<<1))
+}
+
+/* Row pin configuration
+ */
+static void unselect_rows(void)
+{
+ palSetPadMode(TEENSY_PIN5_IOPORT, TEENSY_PIN5, PAL_MODE_INPUT); // hi-Z
+}
+
+static void select_row(uint8_t row)
+{
+ (void)row;
+ // Output low to select
+ switch (row) {
+ case 0:
+ palSetPadMode(TEENSY_PIN5_IOPORT, TEENSY_PIN5, PAL_MODE_OUTPUT_PUSHPULL);
+ palClearPad(TEENSY_PIN5_IOPORT, TEENSY_PIN5);
+ break;
+ }
+}
diff --git a/keyboards/chibios_test/teensy_lc_onekey/mcuconf.h b/keyboards/chibios_test/teensy_lc_onekey/mcuconf.h
new file mode 100644
index 000000000..c63659019
--- /dev/null
+++ b/keyboards/chibios_test/teensy_lc_onekey/mcuconf.h
@@ -0,0 +1,55 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#ifndef _MCUCONF_H_
+#define _MCUCONF_H_
+
+#define KL2x_MCUCONF
+
+/*
+ * HAL driver system settings.
+ */
+#if 1
+/* PEE mode - 48MHz system clock driven by (16 MHz) external crystal. */
+#define KINETIS_MCG_MODE KINETIS_MCG_MODE_PEE
+#define KINETIS_PLLCLK_FREQUENCY 96000000UL
+#define KINETIS_SYSCLK_FREQUENCY 48000000UL
+#endif
+
+#if 0
+/* crystal-less FEI mode - 48 MHz with internal 32.768 kHz crystal */
+#define KINETIS_MCG_MODE KINETIS_MCG_MODE_FEI
+#define KINETIS_MCG_FLL_DMX32 1 /* Fine-tune for 32.768 kHz */
+#define KINETIS_MCG_FLL_DRS 1 /* 1464x FLL factor */
+#define KINETIS_SYSCLK_FREQUENCY 47972352UL /* 32.768 kHz * 1464 (~48 MHz) */
+#define KINETIS_CLKDIV1_OUTDIV1 1 /* do not divide system clock */
+#endif
+
+/*
+ * SERIAL driver system settings.
+ */
+#define KINETIS_SERIAL_USE_UART0 TRUE
+
+/*
+ * USB driver settings
+ */
+#define KINETIS_USB_USE_USB0 TRUE
+/* Need to redefine this, since the default is for K20x */
+/* This is for Teensy LC; you should comment it out (or change to 5)
+ * for Teensy 3.x */
+#define KINETIS_USB_USB0_IRQ_PRIORITY 2
+
+#endif /* _MCUCONF_H_ */
diff --git a/keyboards/chibios_test/teensy_lc_onekey/teensy_lc_onekey.c b/keyboards/chibios_test/teensy_lc_onekey/teensy_lc_onekey.c
new file mode 100644
index 000000000..b6c432793
--- /dev/null
+++ b/keyboards/chibios_test/teensy_lc_onekey/teensy_lc_onekey.c
@@ -0,0 +1 @@
+#include "teensy_lc_onekey.h"
diff --git a/keyboards/chibios_test/teensy_lc_onekey/teensy_lc_onekey.h b/keyboards/chibios_test/teensy_lc_onekey/teensy_lc_onekey.h
new file mode 100644
index 000000000..ea1c84e2f
--- /dev/null
+++ b/keyboards/chibios_test/teensy_lc_onekey/teensy_lc_onekey.h
@@ -0,0 +1,4 @@
+#ifndef TEENSY_LC_ONEKEY_H
+#define TEENSY_LC_ONEKEY_H
+#include "chibios_test.h"
+#endif
diff --git a/keyboards/clueboard/Makefile b/keyboards/clueboard/Makefile
new file mode 100644
index 000000000..ccc01ea9a
--- /dev/null
+++ b/keyboards/clueboard/Makefile
@@ -0,0 +1,109 @@
+#----------------------------------------------------------------------------
+# On command line:
+#
+# make all = Make software.
+#
+# make clean = Clean out built project files.
+#
+# make coff = Convert ELF to AVR COFF.
+#
+# make extcoff = Convert ELF to AVR Extended COFF.
+#
+# make program = Download the hex file to the device.
+# Please customize your programmer settings(PROGRAM_CMD)
+#
+# make teensy = Download the hex file to the device, using teensy_loader_cli.
+# (must have teensy_loader_cli installed).
+#
+# make dfu = Download the hex file to the device, using dfu-programmer (must
+# have dfu-programmer installed).
+#
+# make flip = Download the hex file to the device, using Atmel FLIP (must
+# have Atmel FLIP installed).
+#
+# make dfu-ee = Download the eeprom file to the device, using dfu-programmer
+# (must have dfu-programmer installed).
+#
+# make flip-ee = Download the eeprom file to the device, using Atmel FLIP
+# (must have Atmel FLIP installed).
+#
+# make debug = Start either simulavr or avarice as specified for debugging,
+# with avr-gdb or avr-insight as the front end for debugging.
+#
+# make filename.s = Just compile filename.c into the assembler code only.
+#
+# make filename.i = Create a preprocessed source file for use in submitting
+# bug reports to the GCC project.
+#
+# To rebuild project do "make clean" then "make all".
+#----------------------------------------------------------------------------
+
+SUBPROJECT_DEFAULT = rev2
+
+# MCU name
+MCU = atmega32u4
+
+# Processor frequency.
+# This will define a symbol, F_CPU, in all source code files equal to the
+# processor frequency in Hz. You can then use this symbol in your source code to
+# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
+# automatically to create a 32-bit value in your source code.
+#
+# This will be an integer division of F_USB below, as it is sourced by
+# F_USB after it has run through any CPU prescalers. Note that this value
+# does not *change* the processor frequency - it should merely be updated to
+# reflect the processor speed set externally so that the code can use accurate
+# software delays.
+F_CPU = 16000000
+
+
+#
+# LUFA specific
+#
+# Target architecture (see library "Board Types" documentation).
+ARCH = AVR8
+
+# Input clock frequency.
+# This will define a symbol, F_USB, in all source code files equal to the
+# input clock frequency (before any prescaling is performed) in Hz. This value may
+# differ from F_CPU if prescaling is used on the latter, and is required as the
+# raw input clock is fed directly to the PLL sections of the AVR for high speed
+# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
+# at the end, this will be done automatically to create a 32-bit value in your
+# source code.
+#
+# If no clock division is performed on the input clock inside the AVR (via the
+# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
+F_USB = $(F_CPU)
+
+# Interrupt driven control endpoint task(+60)
+OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
+
+
+# Boot Section Size in *bytes*
+# Teensy halfKay 512
+# Teensy++ halfKay 1024
+# Atmel DFU loader 4096
+# LUFA bootloader 4096
+# USBaspLoader 2048
+OPT_DEFS += -DBOOTLOADER_SIZE=4096
+
+
+# Build Options
+# comment out to disable the options.
+#
+BOOTMAGIC_ENABLE ?= yes # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE ?= no # Mouse keys(+4700)
+EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450)
+CONSOLE_ENABLE ?= yes # Console for debug(+400)
+COMMAND_ENABLE ?= yes # Commands for debug and configuration
+NKRO_ENABLE ?= yes # USB Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+AUDIO_ENABLE ?= no
+RGBLIGHT_ENABLE ?= no # Enable keyboard underlight functionality
+MIDI_ENABLE ?= no # MIDI controls
+UNICODE_ENABLE ?= no # Unicode
+BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID
+
+ifndef QUANTUM_DIR
+ include ../../Makefile
+endif
diff --git a/keyboards/clueboard/clueboard.c b/keyboards/clueboard/clueboard.c
new file mode 100644
index 000000000..13195bda6
--- /dev/null
+++ b/keyboards/clueboard/clueboard.c
@@ -0,0 +1,17 @@
+#include "clueboard.h"
+
+void led_init_ports() {
+ // * Set our LED pins as output
+ DDRB |= (1<<4);
+}
+
+void led_set_kb(uint8_t usb_led) {
+ DDRF |= (1<<0);
+ if (usb_led & (1<<USB_LED_CAPS_LOCK)) {
+ // Turn capslock on
+ PORTF |= (1<<0);
+ } else {
+ // Turn capslock off
+ PORTF &= ~(1<<0);
+ }
+}
diff --git a/keyboards/clueboard/clueboard.h b/keyboards/clueboard/clueboard.h
new file mode 100644
index 000000000..4f2a3c1df
--- /dev/null
+++ b/keyboards/clueboard/clueboard.h
@@ -0,0 +1,13 @@
+#ifndef CLUEBOARD_H
+#define CLUEBOARD_H
+
+#ifdef SUBPROJECT_rev1
+ #include "rev1.h"
+#endif
+#ifdef SUBPROJECT_rev2
+ #include "rev2.h"
+#endif
+
+#include "quantum.h"
+
+#endif
diff --git a/keyboards/clueboard/config.h b/keyboards/clueboard/config.h
new file mode 100644
index 000000000..ceac80795
--- /dev/null
+++ b/keyboards/clueboard/config.h
@@ -0,0 +1,74 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "config_common.h"
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xC1ED
+#define MANUFACTURER Clueboard
+#define PRODUCT Clueboard
+#define DESCRIPTION QMK keyboard firmware for Clueboard
+
+/* COL2ROW or ROW2COL */
+#define DIODE_DIRECTION COL2ROW
+
+/* define if matrix has ghost */
+//#define MATRIX_HAS_GHOST
+
+/* Set 0 if debouncing isn't needed */
+#define DEBOUNCING_DELAY 5
+
+/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
+#define LOCKING_SUPPORT_ENABLE
+/* Locking resynchronize hack */
+#define LOCKING_RESYNC_ENABLE
+
+/* key combination for command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+/*
+ * Feature disable options
+ * These options are also useful to firmware size reduction.
+ */
+
+/* disable debug print */
+//#define NO_DEBUG
+
+/* disable print */
+//#define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+
+
+#ifdef SUBPROJECT_rev1
+ #include "rev1/config.h"
+#endif
+#ifdef SUBPROJECT_rev2
+ #include "rev2/config.h"
+#endif
+
+#endif
diff --git a/keyboards/clueboard/keymaps/default/keymap.c b/keyboards/clueboard/keymaps/default/keymap.c
new file mode 100644
index 000000000..89f71e83a
--- /dev/null
+++ b/keyboards/clueboard/keymaps/default/keymap.c
@@ -0,0 +1,180 @@
+#include "clueboard.h"
+
+// Used for SHIFT_ESC
+#define MODS_CTRL_MASK (MOD_BIT(KC_LSHIFT)|MOD_BIT(KC_RSHIFT))
+
+// Each layer gets a name for readability, which is then used in the keymap matrix below.
+// The underscores don't mean anything - you can have a layer called STUFF or any other name.
+// Layer names don't all need to be of the same length, obviously, and you can also skip them
+// entirely and just use numbers.
+#define _BL 0
+#define _FL 1
+#define _RS 2
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ /* Keymap _BL: (Base Layer) Default Layer
+ * ,--------------------------------------------------------------------------. ,----.
+ * |Esc~| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| \| BS| |PGUP|
+ * |--------------------------------------------------------------------------| |----|
+ * | Tab| Q| W| E| R| T| Y| U| I| O| P| [| ]| \| |PGDN|
+ * |--------------------------------------------------------------------------| `----'
+ * |Capslck| A| S| D| F| G| H| J| K| L| ;| '| # | Ent|
+ * |-----------------------------------------------------------------------------.
+ * |Shift| BS| Z| X| C| V| B| N| M| ,| .| /| BS|Shift| UP|
+ * |------------------------------------------------------------------------|----|----.
+ * | Ctrl| Gui| Alt| MHen| Space| Space| Hen| Alt| Ctrl| _FL|LEFT|DOWN|RGHT|
+ * `----------------------------------------------------------------------------------'
+ */
+[_BL] = KEYMAP(
+ F(0), KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_GRV, KC_BSPC, KC_PGUP, \
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_PGDN, \
+ KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_NUHS, KC_ENT, \
+ KC_LSFT, KC_NUBS, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RO, KC_RSFT, KC_UP, \
+ KC_LCTL, KC_LGUI, KC_LALT, KC_MHEN, KC_SPC,KC_SPC, KC_HENK, KC_RALT, KC_RCTL, MO(_FL), KC_LEFT, KC_DOWN, KC_RGHT),
+
+ /* Keymap _FL: Function Layer
+ * ,--------------------------------------------------------------------------. ,----.
+ * | `| F1| F2| F3| F4| F5| F6| F7| F8| F9| F10| F11| F12| | Del| |BLIN|
+ * |--------------------------------------------------------------------------| |----|
+ * | | | | | | | | |PScr|SLck|Paus| | | | |BLDE|
+ * |--------------------------------------------------------------------------| `----'
+ * | | | _RS| | | | | | | | | | | |
+ * |-----------------------------------------------------------------------------.
+ * | | | | | | | | | | | | | | |PGUP|
+ * |------------------------------------------------------------------------|----|----.
+ * | | | | | | | | | | _FL|HOME|PGDN| END|
+ * `----------------------------------------------------------------------------------'
+ */
+[_FL] = KEYMAP(
+ KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_TRNS, KC_DEL, BL_STEP, \
+ KC_TRNS, KC_TRNS, KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_PSCR,KC_SLCK, KC_PAUS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
+ KC_TRNS, KC_TRNS, MO(_RS),KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
+ KC_TRNS, KC_TRNS, KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PGUP, \
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, MO(_FL), KC_HOME, KC_PGDN, KC_END),
+
+ /* Keymap _RS: Reset layer
+ * ,--------------------------------------------------------------------------. ,----.
+ * | | | | | | | | | | | | | | | | | |
+ * |--------------------------------------------------------------------------| |----|
+ * | | | | |RESET| | | | | | | | | | | |
+ * |--------------------------------------------------------------------------| `----'
+ * | | | _RS| | | | | | | | | | | |
+ * |-----------------------------------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |------------------------------------------------------------------------|----|----.
+ * | | | | | | | | | | _FL| | | |
+ * `----------------------------------------------------------------------------------'
+ */
+[_RS] = KEYMAP(
+ #ifdef RGBLIGHT_ENABLE
+ KC_TRNS, KC_TRNS, KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, F(1), F(7), \
+ KC_TRNS, KC_TRNS, KC_TRNS,KC_TRNS,RESET, KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, F(8), \
+ KC_TRNS, KC_TRNS, MO(_RS),KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
+ MO(_FL), KC_TRNS, KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, MO(_FL), F(5), \
+ KC_TRNS, KC_TRNS, KC_TRNS,KC_TRNS, F(2), F(2), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, F(4), F(6), F(3)),
+ #else
+ KC_TRNS, KC_TRNS, KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
+ KC_TRNS, KC_TRNS, KC_TRNS,KC_TRNS,RESET, KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
+ KC_TRNS, KC_TRNS, MO(_RS),KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
+ KC_TRNS, KC_TRNS, KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, MO(_FL), KC_TRNS, KC_TRNS, KC_TRNS),
+ #endif
+};
+
+enum function_id {
+ SHIFT_ESC,
+ #ifdef RGBLIGHT_ENABLE
+ RGBLED_TOGGLE,
+ RGBLED_STEP_MODE,
+ RGBLED_INCREASE_HUE,
+ RGBLED_DECREASE_HUE,
+ RGBLED_INCREASE_SAT,
+ RGBLED_DECREASE_SAT,
+ RGBLED_INCREASE_VAL,
+ RGBLED_DECREASE_VAL
+ #endif
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [0] = ACTION_FUNCTION(SHIFT_ESC),
+ #ifdef RGBLIGHT_ENABLE
+ [1] = ACTION_FUNCTION(RGBLED_TOGGLE),
+ [2] = ACTION_FUNCTION(RGBLED_STEP_MODE),
+ [3] = ACTION_FUNCTION(RGBLED_INCREASE_HUE),
+ [4] = ACTION_FUNCTION(RGBLED_DECREASE_HUE),
+ [5] = ACTION_FUNCTION(RGBLED_INCREASE_SAT),
+ [6] = ACTION_FUNCTION(RGBLED_DECREASE_SAT),
+ [7] = ACTION_FUNCTION(RGBLED_INCREASE_VAL),
+ [8] = ACTION_FUNCTION(RGBLED_DECREASE_VAL),
+ #endif
+};
+
+void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) {
+ static uint8_t shift_esc_shift_mask;
+ switch (id) {
+ case SHIFT_ESC:
+ shift_esc_shift_mask = get_mods()&MODS_CTRL_MASK;
+ if (record->event.pressed) {
+ if (shift_esc_shift_mask) {
+ add_key(KC_GRV);
+ send_keyboard_report();
+ } else {
+ add_key(KC_ESC);
+ send_keyboard_report();
+ }
+ } else {
+ if (shift_esc_shift_mask) {
+ del_key(KC_GRV);
+ send_keyboard_report();
+ } else {
+ del_key(KC_ESC);
+ send_keyboard_report();
+ }
+ }
+ break;
+ //led operations
+ #ifdef RGBLIGHT_ENABLE
+ case RGBLED_TOGGLE:
+ if (record->event.pressed) {
+ rgblight_toggle();
+ }
+
+ break;
+ case RGBLED_INCREASE_HUE:
+ if (record->event.pressed) {
+ rgblight_increase_hue();
+ }
+ break;
+ case RGBLED_DECREASE_HUE:
+ if (record->event.pressed) {
+ rgblight_decrease_hue();
+ }
+ break;
+ case RGBLED_INCREASE_SAT:
+ if (record->event.pressed) {
+ rgblight_increase_sat();
+ }
+ break;
+ case RGBLED_DECREASE_SAT:
+ if (record->event.pressed) {
+ rgblight_decrease_sat();
+ }
+ break;
+ case RGBLED_INCREASE_VAL:
+ if (record->event.pressed) {
+ rgblight_increase_val();
+ }
+ break;
+ case RGBLED_DECREASE_VAL:
+ if (record->event.pressed) {
+ rgblight_decrease_val();
+ }
+ break;
+ case RGBLED_STEP_MODE:
+ if (record->event.pressed) {
+ rgblight_step();
+ }
+ break;
+ #endif
+ }
+}
diff --git a/keyboards/clueboard/keymaps/max/Makefile b/keyboards/clueboard/keymaps/max/Makefile
new file mode 100644
index 000000000..950dadf84
--- /dev/null
+++ b/keyboards/clueboard/keymaps/max/Makefile
@@ -0,0 +1,49 @@
+#----------------------------------------------------------------------------
+# On command line:
+#
+# make all = Make software.
+#
+# make clean = Clean out built project files.
+#
+# make coff = Convert ELF to AVR COFF.
+#
+# make extcoff = Convert ELF to AVR Extended COFF.
+#
+# make program = Download the hex file to the device.
+# Please customize your programmer settings(PROGRAM_CMD)
+#
+# make teensy = Download the hex file to the device, using teensy_loader_cli.
+# (must have teensy_loader_cli installed).
+#
+# make dfu = Download the hex file to the device, using dfu-programmer (must
+# have dfu-programmer installed).
+#
+# make flip = Download the hex file to the device, using Atmel FLIP (must
+# have Atmel FLIP installed).
+#
+# make dfu-ee = Download the eeprom file to the device, using dfu-programmer
+# (must have dfu-programmer installed).
+#
+# make flip-ee = Download the eeprom file to the device, using Atmel FLIP
+# (must have Atmel FLIP installed).
+#
+# make debug = Start either simulavr or avarice as specified for debugging,
+# with avr-gdb or avr-insight as the front end for debugging.
+#
+# make filename.s = Just compile filename.c into the assembler code only.
+#
+# make filename.i = Create a preprocessed source file for use in submitting
+# bug reports to the GCC project.
+#
+# To rebuild project do "make clean" then "make all".
+#----------------------------------------------------------------------------
+
+# Build Options
+# change to "no" to disable the options, or define them in the makefile.mk in
+# the appropriate keymap folder that will get included automatically
+#
+RGBLIGHT_ENABLE = yes # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/clueboard/keymaps/max/keymap.c b/keyboards/clueboard/keymaps/max/keymap.c
new file mode 100644
index 000000000..82c93401d
--- /dev/null
+++ b/keyboards/clueboard/keymaps/max/keymap.c
@@ -0,0 +1,143 @@
+#include "clueboard.h"
+
+// Used for SHIFT_ESC
+#define MODS_CTRL_MASK (MOD_BIT(KC_LSHIFT)|MOD_BIT(KC_RSHIFT))
+
+// Each layer gets a name for readability, which is then used in the keymap matrix below.
+// The underscores don't mean anything - you can have a layer called STUFF or any other name.
+// Layer names don't all need to be of the same length, obviously, and you can also skip them
+// entirely and just use numbers.
+#define _BL 0
+#define _FL 1
+#define _RS 2
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ /* Keymap _BL: (Base Layer) Default Layer
+ * ,--------------------------------------------------------------------------. ,----.
+ * | Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| ~| BS| |PgUp|
+ * |--------------------------------------------------------------------------| |----|
+ * | Tab| Q| W| E| R| T| Y| U| I| O| P| [| ]| \| |PgDn|
+ * |--------------------------------------------------------------------------| `----'
+ * |Capslck| A| S| D| F| G| H| J| K| L| ;| '| # | Ent|
+ * |-----------------------------------------------------------------------------.
+ * |Shift| BS| Z| X| C| V| B| N| M| ,| .| /| BS|Shift| Up|
+ * |------------------------------------------------------------------------|----|----.
+ * | Ctrl| Alt| Gui| MHen| Space| Space| Hen| Gui| Alt| Ctrl|Left|Down|Rght|
+ * `----------------------------------------------------------------------------------'
+ */
+[_BL] = KEYMAP(
+ KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_GRV, KC_BSPC, KC_PGUP, \
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_PGDN, \
+ KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_NUHS, KC_ENT, \
+ MO(_FL), KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, MO(_FL), KC_UP, \
+ KC_LCTL, KC_LALT, KC_LGUI,KC_MHEN, KC_SPC, KC_SPC, KC_HENK, KC_RGUI, KC_RALT, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT),
+
+ /* Keymap _FL: Function Layer
+ * ,--------------------------------------------------------------------------. ,----.
+ * | `| F1| F2| F3| F4| F5| F6| F7| F8| F9| F10| F11| F12| | Del| |BLIN|
+ * |--------------------------------------------------------------------------| |----|
+ * | | | | | | | | |PScr|SLck|Paus| | | | |BLDE|
+ * |--------------------------------------------------------------------------| `----'
+ * | | | _RS| | | | | | | | | | | |
+ * |-----------------------------------------------------------------------------.
+ * | | | | | | | | | | | | | | |PGUP|
+ * |------------------------------------------------------------------------|----|----.
+ * | | | | | | | | | | _FL|HOME|PGDN| END|
+ * `----------------------------------------------------------------------------------'
+ */
+[_FL] = KEYMAP(
+ KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_TRNS, KC_DEL, BL_STEP, \
+ KC_TRNS, KC_TRNS, KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_SLCK, KC_PAUS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
+ KC_TRNS, KC_TRNS, MO(_RS),KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
+ MO(_FL), KC_TRNS, KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, MO(_FL), KC_PGUP, \
+ KC_TRNS, KC_TRNS, KC_TRNS,KC_TRNS, KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_HOME, KC_PGDN, KC_END),
+
+ /* Keymap _RS: Reset/Underlight layer
+ * ,--------------------------------------------------------------------------. ,----.
+ * | | | | | | | | | | | | | | | | | |
+ * |--------------------------------------------------------------------------| |----|
+ * | | | | |RESET| | | | | | | | | | | |
+ * |--------------------------------------------------------------------------| `----'
+ * | | | _RS| | | | | | | | | | | |
+ * |-----------------------------------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |------------------------------------------------------------------------|----|----.
+ * | | | | | | | | | | _FL| | | |
+ * `----------------------------------------------------------------------------------'
+ */
+[_RS] = KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, F(0), F(6), \
+ KC_TRNS, KC_TRNS, KC_TRNS,KC_TRNS,RESET, KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, F(7), \
+ KC_TRNS, KC_TRNS, MO(_RS),KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
+ MO(_FL), KC_TRNS, KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, MO(_FL), F(4), \
+ KC_TRNS, KC_TRNS, KC_TRNS,KC_TRNS, F(1), F(1), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, F(3), F(5), F(2)),
+};
+
+enum function_id {
+ RGBLED_TOGGLE,
+ RGBLED_STEP_MODE,
+ RGBLED_INCREASE_HUE,
+ RGBLED_DECREASE_HUE,
+ RGBLED_INCREASE_SAT,
+ RGBLED_DECREASE_SAT,
+ RGBLED_INCREASE_VAL,
+ RGBLED_DECREASE_VAL,
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [0] = ACTION_FUNCTION(RGBLED_TOGGLE),
+ [1] = ACTION_FUNCTION(RGBLED_STEP_MODE),
+ [2] = ACTION_FUNCTION(RGBLED_INCREASE_HUE),
+ [3] = ACTION_FUNCTION(RGBLED_DECREASE_HUE),
+ [4] = ACTION_FUNCTION(RGBLED_INCREASE_SAT),
+ [5] = ACTION_FUNCTION(RGBLED_DECREASE_SAT),
+ [6] = ACTION_FUNCTION(RGBLED_INCREASE_VAL),
+ [7] = ACTION_FUNCTION(RGBLED_DECREASE_VAL),
+};
+
+void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) {
+ switch (id) {
+ case RGBLED_TOGGLE:
+ //led operations
+ if (record->event.pressed) {
+ rgblight_toggle();
+ }
+
+ break;
+ case RGBLED_INCREASE_HUE:
+ if (record->event.pressed) {
+ rgblight_increase_hue();
+ }
+ break;
+ case RGBLED_DECREASE_HUE:
+ if (record->event.pressed) {
+ rgblight_decrease_hue();
+ }
+ break;
+ case RGBLED_INCREASE_SAT:
+ if (record->event.pressed) {
+ rgblight_increase_sat();
+ }
+ break;
+ case RGBLED_DECREASE_SAT:
+ if (record->event.pressed) {
+ rgblight_decrease_sat();
+ }
+ break;
+ case RGBLED_INCREASE_VAL:
+ if (record->event.pressed) {
+ rgblight_increase_val();
+ }
+ break;
+ case RGBLED_DECREASE_VAL:
+ if (record->event.pressed) {
+ rgblight_decrease_val();
+ }
+ break;
+ case RGBLED_STEP_MODE:
+ if (record->event.pressed) {
+ rgblight_step();
+ }
+ break;
+ }
+}
diff --git a/keyboards/clueboard/keymaps/skully/keymap.c b/keyboards/clueboard/keymaps/skully/keymap.c
new file mode 100644
index 000000000..df6f054e0
--- /dev/null
+++ b/keyboards/clueboard/keymaps/skully/keymap.c
@@ -0,0 +1,108 @@
+#include "clueboard.h"
+
+// Used for SHIFT_ESC
+#define MODS_CTRL_MASK (MOD_BIT(KC_LSHIFT)|MOD_BIT(KC_RSHIFT))
+
+// Each layer gets a name for readability, which is then used in the keymap matrix below.
+// The underscores don't mean anything - you can have a layer called STUFF or any other name.
+// Layer names don't all need to be of the same length, obviously, and you can also skip them
+// entirely and just use numbers.
+#define _BL 0
+#define _FL 1
+#define _RS 2
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ /* Keymap _BL: (Base Layer) Default Layer
+ * ,--------------------------------------------------------------------------. ,----.
+ * |Esc~| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| \| BS| |PGUP|
+ * |--------------------------------------------------------------------------| |----|
+ * | Tab| Q| W| E| R| T| Y| U| I| O| P| [| ]| \| |PGDN|
+ * |--------------------------------------------------------------------------| `----'
+ * |Capslck| A| S| D| F| G| H| J| K| L| ;| '| # | Ent|
+ * |-----------------------------------------------------------------------------.
+ * |Shift| BS| Z| X| C| V| B| N| M| ,| .| /| BS|Shift| UP|
+ * |------------------------------------------------------------------------|----|----.
+ * | Ctrl| Gui| Alt| MHen| Space| Space| Hen| Alt| Ctrl| _FL|LEFT|DOWN|RGHT|
+ * `----------------------------------------------------------------------------------'
+ */
+[_BL] = KEYMAP(
+ F(0), KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_GRV, KC_BSPC, KC_PGUP, \
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_PGDN, \
+ KC_LCTL,KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_NUHS, KC_ENT, \
+ KC_LSFT,KC_NUBS,KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RO, KC_RSFT, KC_UP, \
+ KC_LCTL,KC_LALT,KC_LGUI,MO(_FL), KC_SPC, KC_SPC, MO(_FL), KC_RGUI, KC_RCTL, MO(_FL), KC_LEFT, KC_DOWN, KC_RGHT),
+
+ /* Keymap _FL: Function Layer
+ * ,--------------------------------------------------------------------------. ,----.
+ * | `| F1| F2| F3| F4| F5| F6| F7| F8| F9| F10| F11| F12| | Del| |BLIN|
+ * |--------------------------------------------------------------------------| |----|
+ * | | | | | | | | |PScr|SLck|Paus| | | | |BLDE|
+ * |--------------------------------------------------------------------------| `----'
+ * | | | _RS| | | | | | | | | | | |
+ * |-----------------------------------------------------------------------------.
+ * | | | | | | | | | | | | | | |PGUP|
+ * |------------------------------------------------------------------------|----|----.
+ * | | | | | | | | | | _FL|HOME|PGDN| END|
+ * `----------------------------------------------------------------------------------'
+ */
+[_FL] = KEYMAP(
+ KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_TRNS,KC_DEL, BL_STEP, \
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_PSCR,KC_SLCK,KC_PAUS,KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, \
+ KC_TRNS,KC_TRNS,MO(_RS),KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS, \
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS, KC_PGUP, \
+ KC_TRNS,KC_TRNS,KC_TRNS,MO(_FL), KC_TRNS,KC_TRNS, MO(_FL),KC_TRNS,KC_TRNS,MO(_FL),KC_HOME,KC_PGDN,KC_END),
+
+ /* Keymap _RS: Reset layer
+ * ,--------------------------------------------------------------------------. ,----.
+ * | | | | | | | | | | | | | | | | | |
+ * |--------------------------------------------------------------------------| |----|
+ * | | | | |RESET| | | | | | | | | | | |
+ * |--------------------------------------------------------------------------| `----'
+ * | | | _RS| | | | | | | | | | | |
+ * |-----------------------------------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |------------------------------------------------------------------------|----|----.
+ * | | | | | | | | | | _FL| | | |
+ * `----------------------------------------------------------------------------------'
+ */
+[_RS] = KEYMAP(
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, \
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,RESET, KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, \
+ KC_TRNS,KC_TRNS,MO(_RS),KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS, \
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, \
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS,KC_TRNS, KC_TRNS,KC_TRNS,KC_TRNS,MO(_FL),KC_TRNS, KC_TRNS, KC_TRNS),
+};
+
+enum function_id {
+ SHIFT_ESC,
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [0] = ACTION_FUNCTION(SHIFT_ESC),
+};
+
+void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) {
+ static uint8_t shift_esc_shift_mask;
+ switch (id) {
+ case SHIFT_ESC:
+ shift_esc_shift_mask = get_mods()&MODS_CTRL_MASK;
+ if (record->event.pressed) {
+ if (shift_esc_shift_mask) {
+ add_key(KC_GRV);
+ send_keyboard_report();
+ } else {
+ add_key(KC_ESC);
+ send_keyboard_report();
+ }
+ } else {
+ if (shift_esc_shift_mask) {
+ del_key(KC_GRV);
+ send_keyboard_report();
+ } else {
+ del_key(KC_ESC);
+ send_keyboard_report();
+ }
+ }
+ break;
+ }
+}
diff --git a/keyboards/clueboard/rev1/Makefile b/keyboards/clueboard/rev1/Makefile
new file mode 100644
index 000000000..80a942d06
--- /dev/null
+++ b/keyboards/clueboard/rev1/Makefile
@@ -0,0 +1,5 @@
+BACKLIGHT_ENABLE = no
+
+ifndef QUANTUM_DIR
+ include ../../../Makefile
+endif
diff --git a/keyboards/clueboard/rev1/config.h b/keyboards/clueboard/rev1/config.h
new file mode 100644
index 000000000..9bb58f56e
--- /dev/null
+++ b/keyboards/clueboard/rev1/config.h
@@ -0,0 +1,37 @@
+#ifndef REV2_CONFIG_H
+#define REV2_CONFIG_H
+
+#include "../config.h"
+
+#define PRODUCT_ID 0x2301
+#define DEVICE_VER 0x0003
+
+/* key matrix size */
+#define MATRIX_ROWS 5
+#define MATRIX_COLS 16
+
+// ROWS: Top to bottom, COLS: Left to right
+/* Column pin configuration
+* col: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+* pin: B3 F1 F4 F5 F6 C7 C6 B6 B5 B4 D7 D6 D4 F7 B0 B1
+*/
+#define MATRIX_COL_PINS { B3, F1, F4, F5, F6, C7, C6, B6, B5, B4, D7, D6, D4, F7, B0, B1 }
+/* Row pin configuration
+* row: 0 1 2 3 4
+* pin: D1 D0 D2 D5 D3
+*/
+#define MATRIX_ROW_PINS { D1, D0, D2, D5, D3 }
+#define UNUSED_PINS
+
+/* Underlight configuration
+ */
+#define ws2812_PORTREG PORTB
+#define ws2812_DDRREG DDRB
+#define ws2812_pin 2
+#define RGBLED_NUM 14 // Number of LEDs
+#define RGBLIGHT_HUE_STEP 10
+#define RGBLIGHT_SAT_STEP 17
+#define RGBLIGHT_VAL_STEP 17
+
+
+#endif \ No newline at end of file
diff --git a/keyboards/clueboard/rev1/rev1.c b/keyboards/clueboard/rev1/rev1.c
new file mode 100644
index 000000000..520a869e5
--- /dev/null
+++ b/keyboards/clueboard/rev1/rev1.c
@@ -0,0 +1 @@
+#include "rev1.h"
diff --git a/keyboards/clueboard/rev1/rev1.h b/keyboards/clueboard/rev1/rev1.h
new file mode 100644
index 000000000..abdfd079b
--- /dev/null
+++ b/keyboards/clueboard/rev1/rev1.h
@@ -0,0 +1,47 @@
+#ifndef REV1_H
+#define REV1_H
+
+#include "../clueboard.h"
+
+/* Clueboard matrix layout
+ * ,-----------------------------------------------------------. ,---.
+ * | 00| 01| 02| 03| 04| 05| 06| 07| 08| 09| 0A| 0B| 0C| 0D| 0E| | 0F|
+ * |-----------------------------------------------------------| |---|
+ * | 10| 11| 12| 13| 14| 15| 16| 17| 18| 19| 1A| 1B| 1C| 1D| | 1F|
+ * |-----------------------------------------------------------| `---'
+ * | 20| 21| 22| 23| 24| 25| 26| 27| 28| 29| 2A| 2B| 2C| 2D|
+ * |------------------------------------------------------------.
+ * | 30| 31| 32| 33| 34| 35| 36| 37| 38| 39| 3A| 3B| 3C| 3D|3E|
+ * |------------------------------------------------------------------.
+ * | 40| 41| 42| 43| 45| 46| 49| 4A| 4B| 4C| 4D| 4E| 4F|
+ * `------------------------------------------------------------------'
+ * ,-----------------------------------------------------------. ,---.
+ * | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Yen| BS| |Ins|
+ * |-----------------------------------------------------------| |---|
+ * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| |Del|
+ * |-----------------------------------------------------------| `---'
+ * |Caps | A| S| D| F| G| H| J| k| L| ;| '| # | Ent|
+ * |--------------------------------------------------------------.
+ * |Shift| \| Z| X| C| V| B| N| M| ,| .| /| \|Shift| Up|
+ * |------------------------------------------------------------------.
+ * |Ctrl|Alt|Gui |MHen| Space| Space|Henk|Gui |Ctrl| Fn|Left|Down|Rgt|
+ * `------------------------------------------------------------------'
+ */
+// The first section contains all of the arguements
+// The second converts the arguments into a two-dimensional array
+
+#define KEYMAP( \
+ k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0A, k0B, k0C, k0D, k0E, k0F, \
+ k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1A, k1B, k1C, k1D, k1F, \
+ k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2A, k2B, k2C, k2D, \
+ k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k3A, k3B, k3C, k3D, k3E, \
+ k40, k41, k42, k43, k45, k46, k49, k4A, k4B, k4C, k4D, k4E, k4F \
+) { \
+ { k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0A, k0B, k0C, k0D, k0E, k0F }, \
+ { k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1A, k1B, k1C, k1D, KC_NO, k1F }, \
+ { k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2A, k2B, k2C, k2D }, \
+ { k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k3A, k3B, k3C, k3D, k3E }, \
+ { k40, k41, k42, k43, KC_NO, k45, k46, KC_NO, KC_NO, k49, k4A, k4B, k4C, k4D, k4E, k4F } \
+}
+
+#endif
diff --git a/keyboards/clueboard/rev2/Makefile b/keyboards/clueboard/rev2/Makefile
new file mode 100644
index 000000000..cea967b79
--- /dev/null
+++ b/keyboards/clueboard/rev2/Makefile
@@ -0,0 +1,5 @@
+BACKLIGHT_ENABLE = yes
+
+ifndef QUANTUM_DIR
+ include ../../../Makefile
+endif
diff --git a/keyboards/clueboard/rev2/config.h b/keyboards/clueboard/rev2/config.h
new file mode 100644
index 000000000..e2f8336be
--- /dev/null
+++ b/keyboards/clueboard/rev2/config.h
@@ -0,0 +1,40 @@
+#ifndef REV2_CONFIG_H
+#define REV2_CONFIG_H
+
+#include "../config.h"
+
+#define PRODUCT_ID 0x2320
+#define DEVICE_VER 0x0001
+
+/* key matrix size */
+#define MATRIX_ROWS 10
+#define MATRIX_COLS 8
+
+// ROWS: Top to bottom, COLS: Left to right
+/* Row pin configuration
+* row: 0 1 2 3 4 5 6 7 8 9
+* pin: B2 C7 C6 B6 B5 B0 B3 D5 D3 D2
+*/
+#define MATRIX_ROW_PINS { B2, C7, C6, B6, B5, B0, B3, D5, D3, D2 }
+/* Column pin configuration
+ * col: 0 1 2 3 4 5 6 7
+ * pin: F0 F1 F4 F5 F6 F7 E6 B1
+ */
+#define MATRIX_COL_PINS { F0, F1, F4, F5, F6, F7, E6, B1 }
+#define UNUSED_PINS
+
+ /* Backlight configuration
+ */
+#define BACKLIGHT_LEVELS 1
+
+/* Underlight configuration
+ */
+#define ws2812_PORTREG PORTD
+#define ws2812_DDRREG DDRD
+#define ws2812_pin 7
+#define RGBLED_NUM 14 // Number of LEDs
+#define RGBLIGHT_HUE_STEP 10
+#define RGBLIGHT_SAT_STEP 17
+#define RGBLIGHT_VAL_STEP 17
+
+#endif \ No newline at end of file
diff --git a/keyboards/clueboard/rev2/rev2.c b/keyboards/clueboard/rev2/rev2.c
new file mode 100644
index 000000000..7a8ec368e
--- /dev/null
+++ b/keyboards/clueboard/rev2/rev2.c
@@ -0,0 +1,47 @@
+#include "rev2.h"
+#include <avr/io.h>
+#include "backlight.h"
+#include "print.h"
+
+void matrix_init_kb(void) {
+ // put your keyboard start-up code here
+ // runs once when the firmware starts up
+ matrix_init_user();
+ led_init_ports();
+
+ // JTAG disable for PORT F. write JTD bit twice within four cycles.
+ MCUCR |= (1<<JTD);
+ MCUCR |= (1<<JTD);
+}
+
+
+void matrix_scan_kb(void) {
+ matrix_scan_user();
+}
+
+void backlight_init_ports(void) {
+ print("init_backlight_pin()\n");
+ // Set our LED pins as output
+ DDRD |= (1<<6); // Esc
+ DDRB |= (1<<7); // Page Up
+ DDRD |= (1<<4); // Arrows
+
+ // Set our LED pins low
+ PORTD &= ~(1<<6); // Esc
+ PORTB &= ~(1<<7); // Page Up
+ PORTD &= ~(1<<4); // Arrows
+}
+
+void backlight_set(uint8_t level) {
+ if ( level == 0 ) {
+ // Turn off light
+ PORTD |= (1<<6); // Esc
+ PORTB |= (1<<7); // Page Up
+ PORTD |= (1<<4); // Arrows
+ } else {
+ // Turn on light
+ PORTD &= ~(1<<6); // Esc
+ PORTB &= ~(1<<7); // Page Up
+ PORTD &= ~(1<<4); // Arrows
+ }
+}
diff --git a/keyboards/clueboard/rev2/rev2.h b/keyboards/clueboard/rev2/rev2.h
new file mode 100644
index 000000000..912de405d
--- /dev/null
+++ b/keyboards/clueboard/rev2/rev2.h
@@ -0,0 +1,52 @@
+#ifndef REV2_H
+#define REV2_H
+
+#include "../clueboard.h"
+
+/* Clueboard matrix layout
+ * ,-----------------------------------------------------------. ,---.
+ * | 00| 01| 02| 03| 04| 05| 06| 07| 50| 51| 52| 53| 54| 55| 56| | 57|
+ * |-----------------------------------------------------------| |---|
+ * | 10| 11| 12| 13| 14| 15| 16| 17| 60| 61| 62| 63| 64| 65| | 67|
+ * |-----------------------------------------------------------| `---'
+ * | 20| 21| 22| 23| 24| 25| 26| 27| 70| 71| 72| 73| 74| 75|
+ * |------------------------------------------------------------.
+ * | 30| 31| 32| 33| 34| 35| 36| 37| 80| 81| 82| 83| 84| 85|86|
+ * |------------------------------------------------------------------.
+ * | 40| 41| 42| 43| 45| 46| 90| 91| 92| 93| 94| 95| 96|
+ * `------------------------------------------------------------------'
+ * ,-----------------------------------------------------------. ,---.
+ * | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Yen| BS| |Ins|
+ * |-----------------------------------------------------------| |---|
+ * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| |Del|
+ * |-----------------------------------------------------------| `---'
+ * |Caps | A| S| D| F| G| H| J| k| L| ;| '| # | Ent|
+ * |--------------------------------------------------------------.
+ * |Shift| \| Z| X| C| V| B| N| M| ,| .| /| \|Shift| Up|
+ * |------------------------------------------------------------------.
+ * |Ctrl|Alt|Gui |MHen| Space| Space|Henk|Gui |Ctrl| Fn|Left|Down|Rgt|
+ * `------------------------------------------------------------------'
+ */
+// The first section contains all of the arguments
+// The second converts the arguments into a two-dimensional array
+
+#define KEYMAP( \
+ k00, k01, k02, k03, k04, k05, k06, k07, k50, k51, k52, k53, k54, k55, k56, k57, \
+ k10, k11, k12, k13, k14, k15, k16, k17, k60, k61, k62, k63, k64, k65, k67, \
+ k20, k21, k22, k23, k24, k25, k26, k27, k70, k71, k72, k73, k74, k75, \
+ k30, k31, k32, k33, k34, k35, k36, k37, k80, k81, k82, k83, k84, k85, k86, \
+ k40, k41, k42, k43, k45, k46, k90, k92, k93, k94, k95, k96, k97 \
+) { \
+ { k00, k01, k02, k03, k04, k05, k06, k07 }, \
+ { k10, k11, k12, k13, k14, k15, k16, k17 }, \
+ { k20, k21, k22, k23, k24, k25, k26, k27 }, \
+ { k30, k31, k32, k33, k34, k35, k36, k37 }, \
+ { k40, k41, k42, k43, KC_NO, k45, k46, KC_NO }, \
+ { k50, k51, k52, k53, k54, k55, k56, k57 }, \
+ { k60, k61, k62, k63, k64, k65, KC_NO, k67 }, \
+ { k70, k71, k72, k73, k74, k75, KC_NO, KC_NO }, \
+ { k80, k81, k82, k83, k84, k85, k86, KC_NO }, \
+ { k90, KC_NO, k92, k93, k94, k95, k96, k97 } \
+}
+
+#endif
diff --git a/keyboards/clueboard2/Makefile b/keyboards/clueboard2/Makefile
new file mode 100644
index 000000000..e9367a90d
--- /dev/null
+++ b/keyboards/clueboard2/Makefile
@@ -0,0 +1,71 @@
+
+
+# MCU name
+#MCU = at90usb1287
+MCU = atmega32u4
+
+# Processor frequency.
+# This will define a symbol, F_CPU, in all source code files equal to the
+# processor frequency in Hz. You can then use this symbol in your source code to
+# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
+# automatically to create a 32-bit value in your source code.
+#
+# This will be an integer division of F_USB below, as it is sourced by
+# F_USB after it has run through any CPU prescalers. Note that this value
+# does not *change* the processor frequency - it should merely be updated to
+# reflect the processor speed set externally so that the code can use accurate
+# software delays.
+F_CPU = 16000000
+
+
+#
+# LUFA specific
+#
+# Target architecture (see library "Board Types" documentation).
+ARCH = AVR8
+
+# Input clock frequency.
+# This will define a symbol, F_USB, in all source code files equal to the
+# input clock frequency (before any prescaling is performed) in Hz. This value may
+# differ from F_CPU if prescaling is used on the latter, and is required as the
+# raw input clock is fed directly to the PLL sections of the AVR for high speed
+# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
+# at the end, this will be done automatically to create a 32-bit value in your
+# source code.
+#
+# If no clock division is performed on the input clock inside the AVR (via the
+# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
+F_USB = $(F_CPU)
+
+# Interrupt driven control endpoint task(+60)
+OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
+
+
+# Boot Section Size in *bytes*
+# Teensy halfKay 512
+# Teensy++ halfKay 1024
+# Atmel DFU loader 4096
+# LUFA bootloader 4096
+# USBaspLoader 2048
+OPT_DEFS += -DBOOTLOADER_SIZE=4096
+
+
+# Build Options
+# comment out to disable the options.
+#
+BOOTMAGIC_ENABLE ?= yes # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE ?= no # Mouse keys(+4700)
+EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450)
+CONSOLE_ENABLE ?= yes # Console for debug(+400)
+COMMAND_ENABLE ?= yes # Commands for debug and configuration
+NKRO_ENABLE ?= yes # USB Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+RGBLIGHT_ENABLE ?= no # Enable keyboard underlight functionality (+4870)
+BACKLIGHT_ENABLE ?= yes # Enable keyboard backlight functionality (+1150)
+MIDI_ENABLE ?= no # MIDI controls
+AUDIO_ENABLE ?= no
+UNICODE_ENABLE ?= no # Unicode
+BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID
+
+ifndef QUANTUM_DIR
+ include ../../Makefile
+endif
diff --git a/keyboards/clueboard2/clueboard2.c b/keyboards/clueboard2/clueboard2.c
new file mode 100644
index 000000000..d78ffed9b
--- /dev/null
+++ b/keyboards/clueboard2/clueboard2.c
@@ -0,0 +1,63 @@
+#include "clueboard2.h"
+
+void matrix_init_kb(void) {
+ // put your keyboard start-up code here
+ // runs once when the firmware starts up
+ matrix_init_user();
+ led_init_ports();
+
+ // JTAG disable for PORT F. write JTD bit twice within four cycles.
+ MCUCR |= (1<<JTD);
+ MCUCR |= (1<<JTD);
+};
+
+void led_init_ports() {
+ // * Set our LED pins as output
+ DDRB |= (1<<4);
+}
+
+void led_set_kb(uint8_t usb_led) {
+ if (usb_led & (1<<USB_LED_CAPS_LOCK)) {
+ // Turn capslock on
+ PORTB |= (1<<4);
+ } else {
+ // Turn capslock off
+ PORTB &= ~(1<<4);
+ }
+}
+
+/* Clueboard 2.0 LED locations:
+ *
+ * Capslock: B4, pull high to turn on
+ * LCtrl: Shared with Capslock, DO NOT INSTALL LED'S IN BOTH
+ * Page Up: B7, pull high to turn on
+ * Escape: D6, pull high to turn on
+ * Arrows: D4, pull high to turn on
+ */
+
+void backlight_init_ports(void) {
+ print("init_backlight_pin()\n");
+ // Set our LED pins as output
+ DDRD |= (1<<6); // Esc
+ DDRB |= (1<<7); // Page Up
+ DDRD |= (1<<4); // Arrows
+
+ // Set our LED pins low
+ PORTD &= ~(1<<6); // Esc
+ PORTB &= ~(1<<7); // Page Up
+ PORTD &= ~(1<<4); // Arrows
+}
+
+void backlight_set(uint8_t level) {
+ if ( level == 0 ) {
+ // Turn off light
+ PORTD |= (1<<6); // Esc
+ PORTB |= (1<<7); // Page Up
+ PORTD |= (1<<4); // Arrows
+ } else {
+ // Turn on light
+ PORTD &= ~(1<<6); // Esc
+ PORTB &= ~(1<<7); // Page Up
+ PORTD &= ~(1<<4); // Arrows
+ }
+}
diff --git a/keyboards/cluepad/Makefile b/keyboards/cluepad/Makefile
new file mode 100644
index 000000000..a331ff4dc
--- /dev/null
+++ b/keyboards/cluepad/Makefile
@@ -0,0 +1,70 @@
+
+# MCU name
+#MCU = at90usb1287
+MCU = atmega32u4
+
+# Processor frequency.
+# This will define a symbol, F_CPU, in all source code files equal to the
+# processor frequency in Hz. You can then use this symbol in your source code to
+# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
+# automatically to create a 32-bit value in your source code.
+#
+# This will be an integer division of F_USB below, as it is sourced by
+# F_USB after it has run through any CPU prescalers. Note that this value
+# does not *change* the processor frequency - it should merely be updated to
+# reflect the processor speed set externally so that the code can use accurate
+# software delays.
+F_CPU = 16000000
+
+
+#
+# LUFA specific
+#
+# Target architecture (see library "Board Types" documentation).
+ARCH = AVR8
+
+# Input clock frequency.
+# This will define a symbol, F_USB, in all source code files equal to the
+# input clock frequency (before any prescaling is performed) in Hz. This value may
+# differ from F_CPU if prescaling is used on the latter, and is required as the
+# raw input clock is fed directly to the PLL sections of the AVR for high speed
+# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
+# at the end, this will be done automatically to create a 32-bit value in your
+# source code.
+#
+# If no clock division is performed on the input clock inside the AVR (via the
+# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
+F_USB = $(F_CPU)
+
+# Interrupt driven control endpoint task(+60)
+OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
+
+
+# Boot Section Size in *bytes*
+# Teensy halfKay 512
+# Teensy++ halfKay 1024
+# Atmel DFU loader 4096
+# LUFA bootloader 4096
+# USBaspLoader 2048
+OPT_DEFS += -DBOOTLOADER_SIZE=4096
+
+
+# Build Options
+# comment out to disable the options.
+#
+BOOTMAGIC_ENABLE ?= yes # Virtual DIP switch configuration(+1000)
+# MOUSEKEY_ENABLE ?= yes # Mouse keys(+4700)
+# EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450)
+# CONSOLE_ENABLE ?= yes # Console for debug(+400)
+# COMMAND_ENABLE ?= yes # Commands for debug and configuration
+NKRO_ENABLE ?= yes # USB Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE ?= yes # Enable numpad's backlight functionality
+RGBLIGHT_ENABLE ?= yes
+# MIDI_ENABLE ?= YES # MIDI controls
+# UNICODE_ENABLE ?= YES # Unicode
+# BLUETOOTH_ENABLE ?= yes # Enable Bluetooth with the Adafruit EZ-Key HID
+
+
+ifndef QUANTUM_DIR
+ include ../../Makefile
+endif
diff --git a/keyboards/cluepad/cluepad.c b/keyboards/cluepad/cluepad.c
new file mode 100644
index 000000000..1867b617f
--- /dev/null
+++ b/keyboards/cluepad/cluepad.c
@@ -0,0 +1,60 @@
+#include "cluepad.h"
+
+int pwm_level;
+
+void matrix_init_kb(void) {
+ // put your keyboard start-up code here
+ // runs once when the firmware starts up
+ matrix_init_user();
+
+ // JTAG disable for PORT F. write JTD bit twice within four cycles.
+ MCUCR |= (1<<JTD);
+ MCUCR |= (1<<JTD);
+};
+
+void led_set_kb(uint8_t usb_led)
+{
+ print("led_set\n");
+}
+
+void backlight_init_ports(void)
+{
+ // Set C7 to output
+ DDRC |= (1<<7);
+
+ // Initialize the timer
+ TC4H = 0x03;
+ OCR4C = 0xFF;
+ TCCR4A = 0b10000010;
+ TCCR4B = 0b00000001;
+}
+
+void backlight_set(uint8_t level)
+{
+ // Determine the PWM level
+ switch (level)
+ {
+ case 0:
+ // 33%
+ pwm_level = 0x54;
+ break;
+ case 1:
+ // 66%
+ pwm_level = 0xA8;
+ break;
+ case 2:
+ // 100%
+ pwm_level = 0xFF;
+ break;
+ case 3:
+ // 0%
+ pwm_level = 0x00;
+ break;
+ default:
+ xprintf("Unknown level: %d\n", level);
+ }
+
+ // Write the PWM level to the timer
+ TC4H = pwm_level >> 8;
+ OCR4A = 0xFF & pwm_level;
+}
diff --git a/keyboards/cluepad/cluepad.h b/keyboards/cluepad/cluepad.h
new file mode 100644
index 000000000..5e4a5999e
--- /dev/null
+++ b/keyboards/cluepad/cluepad.h
@@ -0,0 +1,36 @@
+#ifndef CLUEPAD_H
+#define CLUEPAD_H
+
+#include "quantum.h"
+
+
+/* Cluepad matrix layout
+ * .-------------------.
+ * |NLCK| /| *| -|
+ * |-------------------|
+ * | 7| 8| 9| |
+ * |--------------| |
+ * | 4| 5| 6| +|
+ * |-------------------|
+ * | 1| 2| 3| |
+ * |--------------| |
+ * | 0| .| Ent|
+ * '-------------------'
+ */
+// The first section contains all of the arguments
+// The second converts the arguments into a two-dimensional array
+#define KEYMAP( \
+ k00, k01, k02, k03, \
+ k10, k11, k12, k13, \
+ k20, k21, k22, \
+ k30, k31, k32, k33, \
+ k40, k42 \
+) { \
+ { k00, k01, k02, k03, }, \
+ { k10, k11, k12, k13, }, \
+ { k20, k21, k22, KC_NO, }, \
+ { k30, k31, k32, k33, }, \
+ { k40, KC_NO, k42, KC_NO } \
+}
+
+#endif
diff --git a/keyboards/cluepad/config.h b/keyboards/cluepad/config.h
new file mode 100644
index 000000000..0955e0f70
--- /dev/null
+++ b/keyboards/cluepad/config.h
@@ -0,0 +1,101 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "config_common.h"
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xC1ED
+#define PRODUCT_ID 0x2312
+#define DEVICE_VER 0x0001
+#define MANUFACTURER Clueboard
+#define PRODUCT Cluepad with RGB Underlighting
+#define DESCRIPTION QMK keyboard firmware for Cluepad
+
+/* key matrix size */
+#define MATRIX_ROWS 5
+#define MATRIX_COLS 4
+
+// ROWS: Top to bottom, COLS: Left to right
+/* Row pin configuration
+* row: 0 1 2 3 4
+* pin:
+*/
+#define MATRIX_ROW_PINS { B0, D3, D5, D4, D6 }
+/* Column pin configuration
+ * col: 0 1 2 3
+ * pin: F4 E6 B1 D2
+ */
+#define MATRIX_COL_PINS { F4, E6, B1, D2 }
+#define UNUSED_PINS
+
+/* COL2ROW or ROW2COL */
+#define DIODE_DIRECTION COL2ROW
+
+/* define if matrix has ghost */
+//#define MATRIX_HAS_GHOST
+
+/* Set 0 if debouncing isn't needed */
+#define DEBOUNCING_DELAY 5
+
+/* Number of backlighting levels */
+#define BACKLIGHT_LEVELS 3
+
+/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
+#define LOCKING_SUPPORT_ENABLE
+/* Locking resynchronize hack */
+#define LOCKING_RESYNC_ENABLE
+
+/* key combination for command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+/* Underlight configuration
+ */
+ #define ws2812_PORTREG PORTF
+ #define ws2812_DDRREG DDRF
+ #define ws2812_pin 6
+ #define RGBLED_NUM 4 // Number of LEDs
+ #define RGBLIGHT_HUE_STEP 10
+ #define RGBLIGHT_SAT_STEP 17
+ #define RGBLIGHT_VAL_STEP 17
+
+/*
+ * Feature disable options
+ * These options are also useful to firmware size reduction.
+ */
+
+/* disable debug print */
+//#define NO_DEBUG
+
+/* Debug forcibly enabled */
+#define ALWAYS_DEBUG
+
+/* disable print */
+//#define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+
+#endif
diff --git a/keyboards/cluepad/keymaps/default/keymap.c b/keyboards/cluepad/keymaps/default/keymap.c
new file mode 100644
index 000000000..8ba49952f
--- /dev/null
+++ b/keyboards/cluepad/keymaps/default/keymap.c
@@ -0,0 +1,122 @@
+#include "cluepad.h"
+
+#include "backlight.h"
+#include "rgblight.h"
+
+// Each layer gets a name for readability, which is then used in the keymap matrix below.
+// The underscores don't mean anything - you can have a layer called STUFF or any other name.
+// Layer names don't all need to be of the same length, obviously, and you can also skip them
+// entirely and just use numbers.
+#define _BL 0
+#define _FL 1
+#define _RS 2
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ /* Keymap _BL: (Base Layer) Default Layer
+ * .-------------------.
+ * |NL F| /| *| -|
+ * |-------------------|
+ * | 7| 8| 9| |
+ * |--------------| |
+ * | 4| 5| 6| +|
+ * |-------------------|
+ * | 1| 2| 3| |
+ * |--------------| |
+ * | 0| .| Ent|
+ * '-------------------'
+ */
+[_BL] = KEYMAP(
+ LT(_FL, KC_NLCK), KC_PSLS, KC_PAST, KC_PMNS, \
+ KC_P7, KC_P8, KC_P9, KC_PPLS, \
+ KC_P4, KC_P5, KC_P6, \
+ KC_P1, KC_P2, KC_P3, KC_PENT, \
+ KC_P0, KC_PDOT),
+
+ /* Keymap _FL: Function Layer
+ * .-------------------.
+ * |NL F| | | Fn0|
+ * |-------------------|
+ * | | Fn4| | |
+ * |--------------| |
+ * | Fn3|BL_S| Fn2| Fn6|
+ * |-------------------|
+ * | | Fn5| | |
+ * |--------------| |
+ * | Fn1| | Fn7|
+ * '-------------------'
+ */
+[_FL] = KEYMAP(
+ LT(_FL, KC_NLCK), KC_TRNS, KC_TRNS, F(0), \
+ KC_TRNS, F(4), KC_TRNS, F(6), \
+ F(3), BL_STEP, F(2), \
+ KC_TRNS, F(5), KC_TRNS, F(7), \
+ F(1), KC_TRNS)
+};
+
+enum function_id {
+ RGBLED_TOGGLE,
+ RGBLED_STEP_MODE,
+ RGBLED_INCREASE_HUE,
+ RGBLED_DECREASE_HUE,
+ RGBLED_INCREASE_SAT,
+ RGBLED_DECREASE_SAT,
+ RGBLED_INCREASE_VAL,
+ RGBLED_DECREASE_VAL,
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [0] = ACTION_FUNCTION(RGBLED_TOGGLE),
+ [1] = ACTION_FUNCTION(RGBLED_STEP_MODE),
+ [2] = ACTION_FUNCTION(RGBLED_INCREASE_HUE),
+ [3] = ACTION_FUNCTION(RGBLED_DECREASE_HUE),
+ [4] = ACTION_FUNCTION(RGBLED_INCREASE_SAT),
+ [5] = ACTION_FUNCTION(RGBLED_DECREASE_SAT),
+ [6] = ACTION_FUNCTION(RGBLED_INCREASE_VAL),
+ [7] = ACTION_FUNCTION(RGBLED_DECREASE_VAL),
+};
+
+void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) {
+ switch (id) {
+ case RGBLED_TOGGLE:
+ if (record->event.pressed) {
+ rgblight_toggle();
+ }
+ break;
+ case RGBLED_INCREASE_HUE:
+ if (record->event.pressed) {
+ rgblight_increase_hue();
+ }
+ break;
+ case RGBLED_DECREASE_HUE:
+ if (record->event.pressed) {
+ rgblight_decrease_hue();
+ }
+ break;
+ case RGBLED_INCREASE_SAT:
+ if (record->event.pressed) {
+ rgblight_increase_sat();
+ }
+ break;
+ case RGBLED_DECREASE_SAT:
+ if (record->event.pressed) {
+ rgblight_decrease_sat();
+ }
+ break;
+ case RGBLED_INCREASE_VAL:
+ if (record->event.pressed) {
+ rgblight_increase_val();
+ }
+ break;
+ case RGBLED_DECREASE_VAL:
+ if (record->event.pressed) {
+ rgblight_decrease_val();
+ }
+ break;
+ case RGBLED_STEP_MODE:
+ if (record->event.pressed) {
+ rgblight_step();
+ }
+ break;
+ }
+}
+
diff --git a/keyboards/ergodox_ez/190hotfix.sh b/keyboards/ergodox_ez/190hotfix.sh
new file mode 100755
index 000000000..bdc3adce2
--- /dev/null
+++ b/keyboards/ergodox_ez/190hotfix.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+#a tool to fix broken keymaps as a result of pull request #190
+#changing the declaration of matrix_scan_user() and matrix_init_user()
+#
+#This script will save a copy of the specified keymap as keymap.c.bak
+#and then create a new keymap.c with the definion corrected.
+#this script must be run from the ergodox_ez directory
+if [ $# -ne 1 ]; then
+ echo $0: usage: ./190hotfix keymap_name
+ exit 1
+fi
+
+echo Saving backup as ./keymaps/$1/keymap.c.bak ...
+mv ./keymaps/$1/keymap.c ./keymaps/$1/keymap.c.bak
+
+echo Modifying ./keymaps/$1/keymap.c ...
+cat ./keymaps/$1/keymap.c.bak | sed -r 's/^void \* matrix_/void matrix_/'>./keymaps/$1/keymap.c
+
+echo Complete!
diff --git a/keyboards/ergodox_ez/Makefile b/keyboards/ergodox_ez/Makefile
new file mode 100644
index 000000000..54edaed6d
--- /dev/null
+++ b/keyboards/ergodox_ez/Makefile
@@ -0,0 +1,86 @@
+#----------------------------------------------------------------------------
+# On command line:
+#
+# make = Make software.
+#
+# make clean = Clean out built project files.
+#
+# That's pretty much all you need. To compile, always go make clean,
+# followed by make.
+#
+# For advanced users only:
+# make teensy = Download the hex file to the device, using teensy_loader_cli.
+# (must have teensy_loader_cli installed).
+#
+#----------------------------------------------------------------------------
+
+# # project specific files
+SRC = twimaster.c \
+ matrix.c
+
+# MCU name
+MCU = atmega32u4
+
+# Processor frequency.
+# This will define a symbol, F_CPU, in all source code files equal to the
+# processor frequency in Hz. You can then use this symbol in your source code to
+# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
+# automatically to create a 32-bit value in your source code.
+#
+# This will be an integer division of F_USB below, as it is sourced by
+# F_USB after it has run through any CPU prescalers. Note that this value
+# does not *change* the processor frequency - it should merely be updated to
+# reflect the processor speed set externally so that the code can use accurate
+# software delays.
+F_CPU = 16000000
+
+
+#
+# LUFA specific
+#
+# Target architecture (see library "Board Types" documentation).
+ARCH = AVR8
+
+# Input clock frequency.
+# This will define a symbol, F_USB, in all source code files equal to the
+# input clock frequency (before any prescaling is performed) in Hz. This value may
+# differ from F_CPU if prescaling is used on the latter, and is required as the
+# raw input clock is fed directly to the PLL sections of the AVR for high speed
+# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
+# at the end, this will be done automatically to create a 32-bit value in your
+# source code.
+#
+# If no clock division is performed on the input clock inside the AVR (via the
+# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
+F_USB = $(F_CPU)
+
+# Interrupt driven control endpoint task(+60)
+OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
+
+
+# Boot Section Size in *bytes*
+# Teensy halfKay 512
+# Teensy++ halfKay 1024
+# Atmel DFU loader 4096
+# LUFA bootloader 4096
+# USBaspLoader 2048
+OPT_DEFS += -DBOOTLOADER_SIZE=512
+
+
+# Build Options
+# comment out to disable the options.
+#
+BOOTMAGIC_ENABLE ?= no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE ?= yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450)
+CONSOLE_ENABLE ?= no # Console for debug(+400)
+COMMAND_ENABLE ?= yes # Commands for debug and configuration
+CUSTOM_MATRIX ?= yes # Custom matrix file for the ErgoDox EZ
+SLEEP_LED_ENABLE ?= yes # Breathing sleep LED during USB suspend
+NKRO_ENABLE ?= yes # USB Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+MIDI_ENABLE ?= no # MIDI controls
+UNICODE_ENABLE ?= yes # Unicode
+
+ifndef QUANTUM_DIR
+ include ../../Makefile
+endif
diff --git a/keyboards/ergodox_ez/config.h b/keyboards/ergodox_ez/config.h
new file mode 100644
index 000000000..2bb56731b
--- /dev/null
+++ b/keyboards/ergodox_ez/config.h
@@ -0,0 +1,84 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+Copyright 2013 Oleg Kostyuk <cub.uanic@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "config_common.h"
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x1307
+#define DEVICE_VER 0x0001
+#define MANUFACTURER ErgoDox EZ
+#define PRODUCT ErgoDox EZ
+#define DESCRIPTION QMK keyboard firmware for Ergodox EZ
+
+/* key matrix size */
+#define MATRIX_ROWS 14
+#define MATRIX_COLS 6
+
+#define MOUSEKEY_DELAY 100
+#define MOUSEKEY_INTERVAL 20
+#define MOUSEKEY_MAX_SPEED 3
+#define MOUSEKEY_TIME_TO_MAX 10
+
+#define TAPPING_TOGGLE 1
+
+/* define if matrix has ghost */
+//#define MATRIX_HAS_GHOST
+
+/* number of backlight levels */
+#define BACKLIGHT_LEVELS 3
+
+/* Set 0 if debouncing isn't needed */
+#define DEBOUNCE 5
+#define TAPPING_TERM 200
+#define IGNORE_MOD_TAP_INTERRUPT // this makes it possible to do rolling combos (zx) with keys that convert to other keys on hold (z becomes ctrl when you hold it, and when this option isn't enabled, z rapidly followed by x actually sends Ctrl-x. That's bad.)
+
+/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
+#define LOCKING_SUPPORT_ENABLE
+/* Locking resynchronize hack */
+#define LOCKING_RESYNC_ENABLE
+
+/* key combination for command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LCTL) | MOD_BIT(KC_RCTL)) || \
+ keyboard_report->mods == (MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)) \
+)
+
+/*
+ * Feature disable options
+ * These options are also useful to firmware size reduction.
+ */
+
+/* disable debug print */
+// #define NO_DEBUG
+
+/* disable print */
+// #define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+//#define DEBUG_MATRIX_SCAN_RATE
+
+#endif
diff --git a/keyboards/ergodox_ez/ergodox_ez.c b/keyboards/ergodox_ez/ergodox_ez.c
new file mode 100644
index 000000000..f0558d9f2
--- /dev/null
+++ b/keyboards/ergodox_ez/ergodox_ez.c
@@ -0,0 +1,85 @@
+#include "ergodox_ez.h"
+#include "i2cmaster.h"
+
+bool i2c_initialized = 0;
+uint8_t mcp23018_status = 0x20;
+
+void matrix_init_kb(void) {
+ // keyboard LEDs (see "PWM on ports OC1(A|B|C)" in "teensy-2-0.md")
+ TCCR1A = 0b10101001; // set and configure fast PWM
+ TCCR1B = 0b00001001; // set and configure fast PWM
+
+ // (tied to Vcc for hardware convenience)
+ DDRB &= ~(1<<4); // set B(4) as input
+ PORTB &= ~(1<<4); // set B(4) internal pull-up disabled
+
+ // unused pins - C7, D4, D5, D7, E6
+ // set as input with internal pull-ip enabled
+ DDRC &= ~(1<<7);
+ DDRD &= ~(1<<7 | 1<<5 | 1<<4);
+ DDRE &= ~(1<<6);
+ PORTC |= (1<<7);
+ PORTD |= (1<<7 | 1<<5 | 1<<4);
+ PORTE |= (1<<6);
+
+ ergodox_blink_all_leds();
+
+ matrix_init_user();
+}
+
+void ergodox_blink_all_leds(void)
+{
+ ergodox_led_all_off();
+ ergodox_led_all_set(LED_BRIGHTNESS_HI);
+ ergodox_right_led_1_on();
+ _delay_ms(50);
+ ergodox_right_led_2_on();
+ _delay_ms(50);
+ ergodox_right_led_3_on();
+ _delay_ms(50);
+ ergodox_right_led_1_off();
+ _delay_ms(50);
+ ergodox_right_led_2_off();
+ _delay_ms(50);
+ ergodox_right_led_3_off();
+ //ergodox_led_all_on();
+ //_delay_ms(333);
+ ergodox_led_all_off();
+}
+
+uint8_t init_mcp23018(void) {
+ mcp23018_status = 0x20;
+
+ // I2C subsystem
+ if (i2c_initialized == 0) {
+ i2c_init(); // on pins D(1,0)
+ i2c_initialized++;
+ _delay_ms(1000);
+ }
+
+ // set pin direction
+ // - unused : input : 1
+ // - input : input : 1
+ // - driving : output : 0
+ mcp23018_status = i2c_start(I2C_ADDR_WRITE); if (mcp23018_status) goto out;
+ mcp23018_status = i2c_write(IODIRA); if (mcp23018_status) goto out;
+ mcp23018_status = i2c_write(0b00000000); if (mcp23018_status) goto out;
+ mcp23018_status = i2c_write(0b00111111); if (mcp23018_status) goto out;
+ i2c_stop();
+
+ // set pull-up
+ // - unused : on : 1
+ // - input : on : 1
+ // - driving : off : 0
+ mcp23018_status = i2c_start(I2C_ADDR_WRITE); if (mcp23018_status) goto out;
+ mcp23018_status = i2c_write(GPPUA); if (mcp23018_status) goto out;
+ mcp23018_status = i2c_write(0b00000000); if (mcp23018_status) goto out;
+ mcp23018_status = i2c_write(0b00111111); if (mcp23018_status) goto out;
+
+out:
+ i2c_stop();
+
+ return mcp23018_status;
+}
+
+
diff --git a/keyboards/ergodox_ez/ergodox_ez.h b/keyboards/ergodox_ez/ergodox_ez.h
new file mode 100644
index 000000000..db4ec867b
--- /dev/null
+++ b/keyboards/ergodox_ez/ergodox_ez.h
@@ -0,0 +1,122 @@
+#ifndef ERGODOX_EZ_H
+#define ERGODOX_EZ_H
+
+#include "quantum.h"
+#include <stdint.h>
+#include <stdbool.h>
+#include "i2cmaster.h"
+#include <util/delay.h>
+
+#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
+#define CPU_16MHz 0x00
+
+// I2C aliases and register addresses (see "mcp23018.md")
+#define I2C_ADDR 0b0100000
+#define I2C_ADDR_WRITE ( (I2C_ADDR<<1) | I2C_WRITE )
+#define I2C_ADDR_READ ( (I2C_ADDR<<1) | I2C_READ )
+#define IODIRA 0x00 // i/o direction register
+#define IODIRB 0x01
+#define GPPUA 0x0C // GPIO pull-up resistor register
+#define GPPUB 0x0D
+#define GPIOA 0x12 // general purpose i/o port register (write modifies OLAT)
+#define GPIOB 0x13
+#define OLATA 0x14 // output latch register
+#define OLATB 0x15
+
+extern uint8_t mcp23018_status;
+
+void init_ergodox(void);
+void ergodox_blink_all_leds(void);
+uint8_t init_mcp23018(void);
+uint8_t ergodox_left_leds_update(void);
+
+#define LED_BRIGHTNESS_LO 15
+#define LED_BRIGHTNESS_HI 255
+
+
+inline void ergodox_board_led_on(void) { DDRD |= (1<<6); PORTD |= (1<<6); }
+inline void ergodox_right_led_1_on(void) { DDRB |= (1<<5); PORTB |= (1<<5); }
+inline void ergodox_right_led_2_on(void) { DDRB |= (1<<6); PORTB |= (1<<6); }
+inline void ergodox_right_led_3_on(void) { DDRB |= (1<<7); PORTB |= (1<<7); }
+inline void ergodox_right_led_on(uint8_t led) { DDRB |= (1<<(led+4)); PORTB |= (1<<(led+4)); }
+
+inline void ergodox_board_led_off(void) { DDRD &= ~(1<<6); PORTD &= ~(1<<6); }
+inline void ergodox_right_led_1_off(void) { DDRB &= ~(1<<5); PORTB &= ~(1<<5); }
+inline void ergodox_right_led_2_off(void) { DDRB &= ~(1<<6); PORTB &= ~(1<<6); }
+inline void ergodox_right_led_3_off(void) { DDRB &= ~(1<<7); PORTB &= ~(1<<7); }
+inline void ergodox_right_led_off(uint8_t led) { DDRB &= ~(1<<(led+4)); PORTB &= ~(1<<(led+4)); }
+
+inline void ergodox_led_all_on(void)
+{
+ ergodox_board_led_on();
+ ergodox_right_led_1_on();
+ ergodox_right_led_2_on();
+ ergodox_right_led_3_on();
+}
+
+inline void ergodox_led_all_off(void)
+{
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+}
+
+inline void ergodox_right_led_1_set(uint8_t n) { OCR1A = n; }
+inline void ergodox_right_led_2_set(uint8_t n) { OCR1B = n; }
+inline void ergodox_right_led_3_set(uint8_t n) { OCR1C = n; }
+inline void ergodox_right_led_set(uint8_t led, uint8_t n) {
+ (led == 1) ? (OCR1A = n) :
+ (led == 2) ? (OCR1B = n) :
+ (OCR1C = n);
+}
+
+inline void ergodox_led_all_set(uint8_t n)
+{
+ ergodox_right_led_1_set(n);
+ ergodox_right_led_2_set(n);
+ ergodox_right_led_3_set(n);
+}
+
+#define KEYMAP( \
+ \
+ /* left hand, spatial positions */ \
+ k00,k01,k02,k03,k04,k05,k06, \
+ k10,k11,k12,k13,k14,k15,k16, \
+ k20,k21,k22,k23,k24,k25, \
+ k30,k31,k32,k33,k34,k35,k36, \
+ k40,k41,k42,k43,k44, \
+ k55,k56, \
+ k54, \
+ k53,k52,k51, \
+ \
+ /* right hand, spatial positions */ \
+ k07,k08,k09,k0A,k0B,k0C,k0D, \
+ k17,k18,k19,k1A,k1B,k1C,k1D, \
+ k28,k29,k2A,k2B,k2C,k2D, \
+ k37,k38,k39,k3A,k3B,k3C,k3D, \
+ k49,k4A,k4B,k4C,k4D, \
+ k57,k58, \
+ k59, \
+ k5C,k5B,k5A ) \
+ \
+ /* matrix positions */ \
+ { \
+ { k00, k10, k20, k30, k40, KC_NO }, \
+ { k01, k11, k21, k31, k41, k51 }, \
+ { k02, k12, k22, k32, k42, k52 }, \
+ { k03, k13, k23, k33, k43, k53 }, \
+ { k04, k14, k24, k34, k44, k54 }, \
+ { k05, k15, k25, k35, KC_NO, k55 }, \
+ { k06, k16, KC_NO, k36, KC_NO, k56 }, \
+ \
+ { k07, k17, KC_NO, k37,KC_NO, k57 }, \
+ { k08, k18, k28, k38,KC_NO, k58 }, \
+ { k09, k19, k29, k39, k49, k59 }, \
+ { k0A, k1A, k2A, k3A, k4A, k5A }, \
+ { k0B, k1B, k2B, k3B, k4B, k5B }, \
+ { k0C, k1C, k2C, k3C, k4C, k5C }, \
+ { k0D, k1D, k2D, k3D, k4D, KC_NO } \
+ }
+
+#endif
diff --git a/keyboards/ergodox_ez/i2cmaster.h b/keyboards/ergodox_ez/i2cmaster.h
new file mode 100644
index 000000000..3917b9e6c
--- /dev/null
+++ b/keyboards/ergodox_ez/i2cmaster.h
@@ -0,0 +1,178 @@
+#ifndef _I2CMASTER_H
+#define _I2CMASTER_H 1
+/*************************************************************************
+* Title: C include file for the I2C master interface
+* (i2cmaster.S or twimaster.c)
+* Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury
+* File: $Id: i2cmaster.h,v 1.10 2005/03/06 22:39:57 Peter Exp $
+* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3
+* Target: any AVR device
+* Usage: see Doxygen manual
+**************************************************************************/
+
+#ifdef DOXYGEN
+/**
+ @defgroup pfleury_ic2master I2C Master library
+ @code #include <i2cmaster.h> @endcode
+
+ @brief I2C (TWI) Master Software Library
+
+ Basic routines for communicating with I2C slave devices. This single master
+ implementation is limited to one bus master on the I2C bus.
+
+ This I2c library is implemented as a compact assembler software implementation of the I2C protocol
+ which runs on any AVR (i2cmaster.S) and as a TWI hardware interface for all AVR with built-in TWI hardware (twimaster.c).
+ Since the API for these two implementations is exactly the same, an application can be linked either against the
+ software I2C implementation or the hardware I2C implementation.
+
+ Use 4.7k pull-up resistor on the SDA and SCL pin.
+
+ Adapt the SCL and SDA port and pin definitions and eventually the delay routine in the module
+ i2cmaster.S to your target when using the software I2C implementation !
+
+ Adjust the CPU clock frequence F_CPU in twimaster.c or in the Makfile when using the TWI hardware implementaion.
+
+ @note
+ The module i2cmaster.S is based on the Atmel Application Note AVR300, corrected and adapted
+ to GNU assembler and AVR-GCC C call interface.
+ Replaced the incorrect quarter period delays found in AVR300 with
+ half period delays.
+
+ @author Peter Fleury pfleury@gmx.ch http://jump.to/fleury
+
+ @par API Usage Example
+ The following code shows typical usage of this library, see example test_i2cmaster.c
+
+ @code
+
+ #include <i2cmaster.h>
+
+
+ #define Dev24C02 0xA2 // device address of EEPROM 24C02, see datasheet
+
+ int main(void)
+ {
+ unsigned char ret;
+
+ i2c_init(); // initialize I2C library
+
+ // write 0x75 to EEPROM address 5 (Byte Write)
+ i2c_start_wait(Dev24C02+I2C_WRITE); // set device address and write mode
+ i2c_write(0x05); // write address = 5
+ i2c_write(0x75); // write value 0x75 to EEPROM
+ i2c_stop(); // set stop conditon = release bus
+
+
+ // read previously written value back from EEPROM address 5
+ i2c_start_wait(Dev24C02+I2C_WRITE); // set device address and write mode
+
+ i2c_write(0x05); // write address = 5
+ i2c_rep_start(Dev24C02+I2C_READ); // set device address and read mode
+
+ ret = i2c_readNak(); // read one byte from EEPROM
+ i2c_stop();
+
+ for(;;);
+ }
+ @endcode
+
+*/
+#endif /* DOXYGEN */
+
+/**@{*/
+
+#if (__GNUC__ * 100 + __GNUC_MINOR__) < 304
+#error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !"
+#endif
+
+#include <avr/io.h>
+
+/** defines the data direction (reading from I2C device) in i2c_start(),i2c_rep_start() */
+#define I2C_READ 1
+
+/** defines the data direction (writing to I2C device) in i2c_start(),i2c_rep_start() */
+#define I2C_WRITE 0
+
+
+/**
+ @brief initialize the I2C master interace. Need to be called only once
+ @param void
+ @return none
+ */
+extern void i2c_init(void);
+
+
+/**
+ @brief Terminates the data transfer and releases the I2C bus
+ @param void
+ @return none
+ */
+extern void i2c_stop(void);
+
+
+/**
+ @brief Issues a start condition and sends address and transfer direction
+
+ @param addr address and transfer direction of I2C device
+ @retval 0 device accessible
+ @retval 1 failed to access device
+ */
+extern unsigned char i2c_start(unsigned char addr);
+
+
+/**
+ @brief Issues a repeated start condition and sends address and transfer direction
+
+ @param addr address and transfer direction of I2C device
+ @retval 0 device accessible
+ @retval 1 failed to access device
+ */
+extern unsigned char i2c_rep_start(unsigned char addr);
+
+
+/**
+ @brief Issues a start condition and sends address and transfer direction
+
+ If device is busy, use ack polling to wait until device ready
+ @param addr address and transfer direction of I2C device
+ @return none
+ */
+extern void i2c_start_wait(unsigned char addr);
+
+
+/**
+ @brief Send one byte to I2C device
+ @param data byte to be transfered
+ @retval 0 write successful
+ @retval 1 write failed
+ */
+extern unsigned char i2c_write(unsigned char data);
+
+
+/**
+ @brief read one byte from the I2C device, request more data from device
+ @return byte read from I2C device
+ */
+extern unsigned char i2c_readAck(void);
+
+/**
+ @brief read one byte from the I2C device, read is followed by a stop condition
+ @return byte read from I2C device
+ */
+extern unsigned char i2c_readNak(void);
+
+/**
+ @brief read one byte from the I2C device
+
+ Implemented as a macro, which calls either i2c_readAck or i2c_readNak
+
+ @param ack 1 send ack, request more data from device<br>
+ 0 send nak, read is followed by a stop condition
+ @return byte read from I2C device
+ */
+extern unsigned char i2c_read(unsigned char ack);
+#define i2c_read(ack) (ack) ? i2c_readAck() : i2c_readNak();
+
+
+/**@}*/
+#endif
diff --git a/keyboards/ergodox_ez/keymaps/ab/Makefile b/keyboards/ergodox_ez/keymaps/ab/Makefile
new file mode 100644
index 000000000..b673c5ce5
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/ab/Makefile
@@ -0,0 +1,9 @@
+# Having a file like this allows you to override Makefile definitions
+# for your own particular keymap
+
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+COMMAND_ENABLE = no # Commands for debug and configuration
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif
diff --git a/keyboards/ergodox_ez/keymaps/ab/keyboard-layout.json b/keyboards/ergodox_ez/keymaps/ab/keyboard-layout.json
new file mode 100644
index 000000000..e2badad4d
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/ab/keyboard-layout.json
@@ -0,0 +1,387 @@
+[
+ {
+ "name": "Beginner's Keymap for Ergodox-EZ",
+ "author": "Anand Babu Periasamy"
+ },
+ [
+ {
+ "x": 3.5
+ },
+ "#\n3\n\n\nF3",
+ {
+ "x": 10.5
+ },
+ ")\n0\n\n\nF10"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 2.5
+ },
+ "@\n2\n\n\nF2",
+ {
+ "x": 1
+ },
+ "$\n4\n\n\nF4",
+ {
+ "x": 8.5
+ },
+ "(\n9\n\n\nF9",
+ {
+ "x": 1
+ },
+ "_\n-\n\n\nF11"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 5.5
+ },
+ "%\n5\n\n\nF5",
+ "^\n6\n\n\nF6",
+ {
+ "x": 4.5
+ },
+ "&\n7\n\n\nF7",
+ "*\n8\n\n\nF8"
+ ],
+ [
+ {
+ "y": -0.875,
+ "w": 1.5
+ },
+ "~\n`\n\n\nEsc",
+ "!\n1\n\n\nF1",
+ {
+ "x": 14.5
+ },
+ "+\n=\n\n\nF12",
+ {
+ "a": 7,
+ "w": 1.5
+ },
+ "Backspace\n\n\n\nBackspace"
+ ],
+ [
+ {
+ "y": -0.375,
+ "x": 3.5
+ },
+ "E\n\n\n\n<i class=\"fa fa-caret-up\" aria-hidden=\"true\"></i>",
+ {
+ "x": 10.5
+ },
+ "I"
+ ],
+ [
+ {
+ "y": -0.8799999999999999,
+ "x": 2.5
+ },
+ "W"
+ ],
+ [
+ {
+ "y": -0.9950000000000001,
+ "x": 4.5,
+ "a": 4
+ },
+ "R",
+ {
+ "x": 8.5,
+ "a": 7
+ },
+ "U",
+ {
+ "x": 1
+ },
+ "O"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 5.5
+ },
+ "T",
+ {
+ "h": 1.5
+ },
+ "<i class=\"fa fa-chevron-circle-left\" aria-hidden=\"true\"></i>",
+ {
+ "x": 4.5,
+ "h": 1.5
+ },
+ "<i class=\"fa fa-chevron-circle-right\" aria-hidden=\"true\"></i>",
+ "Y"
+ ],
+ [
+ {
+ "y": -0.875,
+ "a": 6,
+ "w": 1.5
+ },
+ "Tab",
+ {
+ "a": 7
+ },
+ "Q",
+ {
+ "x": 14.5
+ },
+ "P",
+ {
+ "a": 4,
+ "w": 1.5
+ },
+ "|\n\\"
+ ],
+ [
+ {
+ "y": -0.375,
+ "x": 3.5,
+ "a": 7
+ },
+ "D\n\n\n\n<i class=\"fa fa-caret-down\" aria-hidden=\"true\"></i>",
+ {
+ "x": 10.5
+ },
+ "K"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 2.5
+ },
+ "S\n\n\n\n<i class=\"fa fa-caret-left\" aria-hidden=\"true\"></i>",
+ {
+ "x": 1,
+ "c": "#c4bcbc"
+ },
+ "F\n\n\n\n<i class=\"fa fa-caret-right\" aria-hidden=\"true\"></i>",
+ {
+ "x": 8.5
+ },
+ "J",
+ {
+ "x": 1,
+ "c": "#cccccc"
+ },
+ "L"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 5.5
+ },
+ "G",
+ {
+ "x": 6.5
+ },
+ "H"
+ ],
+ [
+ {
+ "y": -0.875,
+ "a": 4,
+ "fa": [
+ 0,
+ 0,
+ 0,
+ 2
+ ],
+ "w": 1.5
+ },
+ "\n\n\nCtrl\n\n\nCaps",
+ {
+ "a": 7
+ },
+ "A",
+ {
+ "x": 14.5,
+ "a": 4
+ },
+ ":\n;",
+ {
+ "a": 7,
+ "w": 1.5
+ },
+ "Enter"
+ ],
+ [
+ {
+ "y": -0.625,
+ "x": 6.5,
+ "h": 1.5
+ },
+ "PgDn",
+ {
+ "x": 4.5,
+ "h": 1.5
+ },
+ "PgUp"
+ ],
+ [
+ {
+ "y": -0.75,
+ "x": 3.5
+ },
+ "C\n\n\n\n<i class=\"fa fa-hand-o-up\" aria-hidden=\"true\"></i>",
+ {
+ "x": 10.5,
+ "a": 4
+ },
+ "<\n,"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 2.5,
+ "a": 7
+ },
+ "X\n\n\n\n<i class=\"fa fa-hand-o-left\" aria-hidden=\"true\"></i>",
+ {
+ "x": 1
+ },
+ "V\n\n\n\n<i class=\"fa fa-hand-o-right\" aria-hidden=\"true\"></i>",
+ {
+ "x": 8.5
+ },
+ "M",
+ {
+ "x": 1,
+ "a": 4
+ },
+ ">\n."
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 5.5,
+ "a": 7
+ },
+ "B",
+ {
+ "x": 6.5
+ },
+ "N"
+ ],
+ [
+ {
+ "y": -0.875,
+ "w": 1.5
+ },
+ "Shift",
+ "Z",
+ {
+ "x": 14.5,
+ "a": 4
+ },
+ "?\n/",
+ {
+ "w": 1.5
+ },
+ "\"\n'"
+ ],
+ [
+ {
+ "y": -0.375,
+ "x": 3.5,
+ "a": 7
+ },
+ "Alt\n\n\n\n<i class=\"fa fa-search-minus\" aria-hidden=\"true\"></i>",
+ {
+ "x": 10.5
+ },
+ "<i class=\"fa fa-long-arrow-down\" aria-hidden=\"true\"></i>\n\n\n\n<i class='fa fa-volume-down'></i>"
+ ],
+ [
+ {
+ "y": -0.875,
+ "x": 2.5
+ },
+ "<i class='fa fa-linux'></i>\n\n\n\n<i class=\"fa fa-search\" aria-hidden=\"true\"></i>",
+ {
+ "x": 1
+ },
+ "Alt\n\n\n\n<i class=\"fa fa-search-plus\" aria-hidden=\"true\"></i>",
+ {
+ "x": 8.5
+ },
+ "<i class=\"fa fa-long-arrow-left\" aria-hidden=\"true\"></i>\n\n\n\n<i class=\"fa fa-undo\" aria-hidden=\"true\"></i>",
+ {
+ "x": 1
+ },
+ "<i class=\"fa fa-long-arrow-up\" aria-hidden=\"true\"></i>\n\n\n\n<i class='fa fa-volume-up'></i>"
+ ],
+ [
+ {
+ "y": -0.75,
+ "x": 0.5
+ },
+ "Ctrl\n\n\n\n<i class='fa fa-download'></i>",
+ "Esc",
+ {
+ "x": 14.5
+ },
+ "<i class=\"fa fa-long-arrow-right\" aria-hidden=\"true\"></i>\n\n\n\n<i class='fa fa-volume-off'></i>",
+ "Fn"
+ ],
+ [
+ {
+ "r": 30,
+ "rx": 6.5,
+ "ry": 4.25,
+ "y": -1,
+ "x": 1
+ },
+ "<i class=\"fa fa-clone\" aria-hidden=\"true\"></i>",
+ "("
+ ],
+ [
+ {
+ "h": 2
+ },
+ "Space",
+ {
+ "h": 2
+ },
+ "Del",
+ "["
+ ],
+ [
+ {
+ "x": 2
+ },
+ "{"
+ ],
+ [
+ {
+ "r": -30,
+ "rx": 13,
+ "y": -1,
+ "x": -3
+ },
+ ")",
+ "<i class=\"fa fa-paste\" aria-hidden=\"true\"></i>"
+ ],
+ [
+ {
+ "x": -3
+ },
+ "]",
+ {
+ "h": 2
+ },
+ "Enter",
+ {
+ "h": 2
+ },
+ "<i class=\"fa fa-chevron-left\" aria-hidden=\"true\"></i>"
+ ],
+ [
+ {
+ "x": -3
+ },
+ "}"
+ ]
+] \ No newline at end of file
diff --git a/keyboards/ergodox_ez/keymaps/ab/keyboard-layout.png b/keyboards/ergodox_ez/keymaps/ab/keyboard-layout.png
new file mode 100644
index 000000000..740684461
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/ab/keyboard-layout.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/ab/keymap.c b/keyboards/ergodox_ez/keymaps/ab/keymap.c
new file mode 100644
index 000000000..df6f33460
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/ab/keymap.c
@@ -0,0 +1,155 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define BASE 0 // default layer
+#define FN1 1 // media layer
+
+#define CAPS_CTL CTL_T(KC_CAPS) // Caps on tap, Ctrl on hold.
+#define COPY LCTL(KC_V) // C-c Copy
+#define PASTE LCTL(KC_V) // C-v Paste
+#define ZM_NRM LCTL(KC_0) // C-0 Zoom Normal
+#define ZM_OUT LCTL(KC_MINS) // C-- Zoom Out
+#define ZM_IN LCTL(KC_PLUS) // C-+ Zoom In
+#define EM_UNDO LCTL(KC_UNDS) // C-_ Emacs Undo
+
+#define _MOB 1 // Mobile#
+#define _CUS1 2 // Custom macro 1
+#define _CUS2 3 // Custom macro 2
+
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | ` | 1 | 2 | 3 | 4 | 5 | 6 | | 7 | 8 | 9 | 0 | - | = | BSpace |
+ * |--------+------+------+------+------+------+------| |------+------+------+------+------+------+--------|
+ * | Tab | Q | W | E | R | T | Fwd | | Back | Y | U | I | O | P | \ |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * |Caps/Ctl| A | S | D | F | G |------| |------| H | J | K | L | ; | Enter |
+ * |--------+------+------+------+------+------| PgDn | | PgUp |------+------+------+------+------+--------|
+ * | LShift | Z | X | C | V | B | | | | N | M | , | . | / | ' |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | Ctrl | Esc | LGui | Alt | Alt | | Left | Dn | Up | Right| Fn |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | Copy | ( | | ) | Paste|
+ * ,------|------+------| |------+------+------.
+ * | | | [ | | ] | | |
+ * |Space | Del |------| |------| Enter|BSpace|
+ * | | | { | | } | | |
+ * `--------------------' `--------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+ [BASE] = KEYMAP( // layer 0 : default
+ // Left hand
+ KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6,
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_WBAK,
+ CAPS_CTL, KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_PGDN,
+ KC_LCTL, KC_ESC, KC_LGUI, KC_LALT, KC_LALT,
+ COPY, KC_LCBR,
+ KC_LPRN,
+ KC_SPC, KC_DEL, KC_LBRC,
+ // Right hand
+ KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC,
+ KC_WFWD, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSLS,
+ KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_ENT,
+ KC_PGUP, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_QUOT,
+ KC_LEFT, KC_DOWN, KC_UP, KC_RIGHT, TG(FN1),
+ KC_RCBR, PASTE,
+ KC_RPRN,
+ KC_RBRC, KC_ENT, KC_BSPC),
+/* Keymap 1: Fn Keys, media and mouse keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | Esc | F1 | F2 | F3 | F4 | F5 | F6 | | F7 | F8 | F9 | F10 | F11 | F12 | BSpace |
+ * |--------+------+------+------+------+------+------| |------+------+------+------+------+------+--------|
+ * | | | | MsUp | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | |MsLeft|MsDown|MsRght| |------| |------| | | | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | LClk | MClk | RClk | | | | | | | | | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * |Teensy| | ZmNrm| ZmOut| ZmIn | | Undo |VolDn |VolUp | Mute | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------+------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// FN1 Layer
+ [FN1] = KEYMAP(
+ // Left hand
+ KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN3, KC_BTN2, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, ZM_NRM, ZM_OUT, ZM_IN,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ RESET, KC_TRNS, KC_TRNS,
+ // Right hand
+ KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_BSPC,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
+ KC_TRNS, M(_MOB), KC_TRNS, M(_CUS1),M(_CUS2),KC_TRNS, KC_TRNS,
+ EM_UNDO, KC_VOLD, KC_VOLU, KC_MUTE, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+ ),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case _MOB: // Your mobile# here.
+ return MACRODOWN(T(1), T(2), T(3), T(MINS),
+ T(1), T(2), T(3), T(MINS),
+ T(1), T(2), T(3), T(4),
+ END);
+ case _CUS1: // Your custom macro 1
+ return MACRODOWN(T(E), T(M), T(A), T(C), T(S), T(SPC), END);
+ case _CUS2: // Your custom macro 2
+ return MACRODOWN(T(L), T(S), T(SPC), T(MINS), T(L), T(ENT), END);
+ };
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case 1:
+ ergodox_right_led_1_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/ab/readme.md b/keyboards/ergodox_ez/keymaps/ab/readme.md
new file mode 100644
index 000000000..6b1ac2be3
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/ab/readme.md
@@ -0,0 +1,21 @@
+# Beginner's keymap for Ergodox-EZ
+Beginner's keymap emulates standard QWERTY keyboard for beginners. Once you get comfortable with the Ergodox-EZ, you may fork this keymap and customize it for your own needs or find a suitable one from the community contributed keymaps.
+
+![Beginner's Keymap](keyboard-layout.png)
+
+#### Pros
+* Easier to switch between regular keyboards and Ergodox-EZ.
+* Easy on beginners. It has everything you need for your day to day usage.
+
+#### Cons
+* Keys are not ergonomically placed to take full advantage of Ergodox-EZ. Take a look at this [Default Keymap](https://github.com/jackhumbert/qmk_firmware/blob/master/keyboards/ergodox_ez/keymaps/default/readme.md)
+* While multiple layers are possible, beginner's keymap only uses one additional layer for mouse, function and volume keys.
+
+#### Notes
+* Ideally number key [6] should have started from the right-hand side of the keyboard. Doing so breaks the familiar QWERTY layout.
+* Quote key ['] should have been placed between [:] and [Enter]. Due to lack of key space, it is placed below [Enter].
+* Double [Alt] keys are placed adjacent to each other for convenience.
+* [CapsLock] also acts as [Ctrl] key when you press and hold. It is convenient for GNU Emacs users.
+* Additional bracket keys are placed in the center of the keyboard for programmer's convenience.
+
+
diff --git a/keyboards/ergodox_ez/keymaps/adnw_k_o_y/keymap.c b/keyboards/ergodox_ez/keymaps/adnw_k_o_y/keymap.c
new file mode 100644
index 000000000..052517d70
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/adnw_k_o_y/keymap.c
@@ -0,0 +1,185 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+#include "keymap_german.h"
+
+#define BASE 0 // default layer
+#define SYMB 1 // symbols
+#define MDIA 2 // media keys
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | = | 1 | 2 | 3 | 4 | 5 | LEFT | | RIGHT| 6 | 7 | 8 | 9 | 0 | - |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Del | K | . | O | , | Y | L1 | | L1 | V | G | C | L | ß | Z |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | BkSp | H | A | E | I | U |------| |------| D | T | R | N | S | F |
+ * |--------+------+------+------+------+------| Hyper| | Meh |------+------+------+------+------+--------|
+ * | LShift |X/Ctrl| Q | Ä | Ü | Ö | | | | B | P | W | M | J | RShift |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * |Grv/L1| '" |AltShf| Left | Right| | Up | Down | [ | ] | ~L1 |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | App | LGui | | Alt |Ctrl/Esc|
+ * ,------|------|------| |------+--------+------.
+ * | | | Home | | PgUp | | |
+ * | Space|Enter |------| |------| Tab |RShift|
+ * | | | End | | PgDn | | |
+ * `--------------------' `----------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_EQL, KC_1, KC_2, KC_3, KC_4, KC_5, KC_LEFT,
+ KC_DELT, DE_K, DE_DOT, DE_O, DE_COMM,DE_Y, TG(SYMB),
+ KC_BSPC, DE_H, DE_A, DE_E, DE_I, DE_U,
+ KC_LSFT, CTL_T(DE_X), DE_Q, DE_AE, DE_UE, DE_OE, ALL_T(KC_NO),
+ LT(SYMB,KC_GRV),KC_QUOT, LALT(KC_LSFT), KC_LEFT,KC_RGHT,
+ ALT_T(KC_APP), KC_LGUI,
+ KC_HOME,
+ KC_SPC,KC_ENT ,KC_END,
+ // right hand
+ KC_RGHT, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
+ TG(SYMB), DE_V, DE_G, DE_C, DE_L, DE_SS, DE_Z,
+ DE_D, DE_T, DE_R, DE_N, LT(MDIA, DE_S), GUI_T(KC_F),
+ MEH_T(KC_NO),KC_B, KC_P, KC_W, KC_M, CTL_T(KC_J), KC_RSFT,
+ KC_UP, KC_DOWN,KC_LBRC,KC_RBRC, KC_FN1,
+ KC_LALT, CTL_T(KC_ESC),
+ KC_PGUP,
+ KC_PGDN,KC_TAB, KC_RSFT
+ ),
+/* Keymap 1: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | . | 0 | = | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[SYMB] = KEYMAP(
+ // left hand
+ KC_TRNS,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS,KC_EXLM,KC_AT, KC_LCBR,KC_RCBR,KC_PIPE,KC_TRNS,
+ KC_TRNS,KC_HASH,KC_DLR, KC_LPRN,KC_RPRN,KC_GRV,
+ KC_TRNS,KC_PERC,KC_CIRC,KC_LBRC,KC_RBRC,KC_TILD,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_UP, KC_7, KC_8, KC_9, KC_ASTR, KC_F12,
+ KC_DOWN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS,
+ KC_TRNS, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS, KC_TRNS,
+ KC_TRNS,KC_DOT, KC_0, KC_EQL, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/* Keymap 2: Media and mouse keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | MsUp | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | |MsLeft|MsDown|MsRght| |------| |------| | | | | | Play |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | | | | Prev | Next | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | Lclk | Rclk | |VolUp |VolDn | Mute | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | |Brwser|
+ * | | |------| |------| |Back |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// MEDIA AND MOUSE
+[MDIA] = KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MPRV, KC_MNXT, KC_TRNS, KC_TRNS,
+ KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_WBAK
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(SYMB) // FN1 - Momentary Layer 1 (Symbols)
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case 1:
+ ergodox_right_led_1_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/adnw_k_o_y/readme.md b/keyboards/ergodox_ez/keymaps/adnw_k_o_y/readme.md
new file mode 100644
index 000000000..f0dd3815c
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/adnw_k_o_y/readme.md
@@ -0,0 +1,7 @@
+# Basic implementation for k.o,y variant of the adnw layout
+
+adnw is a layout optimised for usage with german and english language
+k.o,y is a variant of this layout
+http://www.adnw.de/index.php?n=Main.SeitlicheNachbaranschl%C3%A4ge
+
+The os must use the de_DE layout
diff --git a/keyboards/ergodox_ez/keymaps/alexjj/keymap.c b/keyboards/ergodox_ez/keymaps/alexjj/keymap.c
new file mode 100644
index 000000000..448f62da0
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/alexjj/keymap.c
@@ -0,0 +1,238 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define BASE 0 // default layer
+#define SYMB 1 // symbols
+#define MDIA 2 // media keys
+#define UNIC 3 // unicode entry layer
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | ESC | 1! | 2@ | 3# | 4$ | 5% | 6^ | | 7& | 8* | 9( | 0) | -_ | += | BkSp |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Tab | Q | W | E | R | T | { | | } | Y | U | I | O | P | |\ |
+ * |--------+------+------+------+------+------| [ | | ] |------+------+------+------+------+--------|
+ * | Win | A | S | D | F | G |------| |------| H | J | K | L | :; | '" |
+ * |--------+------+------+------+------+------| Home | | End |------+------+------+------+------+--------|
+ * | LShift |Z/Alt | X | C | V | B | | | | N | M | , | . | Alt | RShift |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * |LCtrl | COPY | PASTE| Left | Right| | Down | Up |Hyper | `~ | RCtrl |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * Hyper = Ctrl+Super+Alt+Shift | ~L3 | F5 | | F2 | ~L2 |
+ * ,------|------|------| |------+------+------.
+ * | | | PgUp | | Ins | | |
+ * | Enter| BkSp |------| |------| ~L1 |Space |
+ * | | | PgDn | | Del | | |
+ * `--------------------' `--------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6,
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_LBRC,
+ KC_LGUI, KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_LSFT, ALT_T(KC_Z), KC_X, KC_C, KC_V, KC_B, KC_HOME,
+ KC_LCTRL, LCTL(KC_C), LCTL(KC_V), KC_LEFT,KC_RGHT,
+ KC_FN3, KC_F5,
+ KC_PGUP,
+ KC_ENT,KC_BSPC,KC_PGDN,
+ // right hand
+ KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC,
+ KC_RBRC, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSLS,
+ KC_H, KC_J, KC_K, KC_L, KC_SCLN,KC_QUOT,
+ KC_END, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH, KC_RSFT,
+ KC_DOWN,KC_UP, ALL_T(KC_NO),KC_GRV, KC_RCTRL,
+ KC_F2, KC_FN2,
+ KC_INS,
+ KC_DELT,KC_FN1, KC_SPC
+ ),
+/* Keymap 1: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | F6 | | F7 | F8 | F9 | F10 | F11 | F12 |PrintScr|
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | £ | | | | | | . | 0 | = |Alt+F4|
+ * `----------------------------------' `----------------------------------'
+ * ↑ ,-------------. ,-------------.
+ * THERE! | | | | | |
+ * ,------|------|------| |------+------+------.
+ * CAD = Ctrl + Alt + Delete | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | CAD | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[SYMB] = KEYMAP(
+ // left hand
+ KC_TRNS,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6,
+ KC_TRNS,KC_EXLM,KC_AT, KC_LCBR,KC_RCBR,KC_PIPE,KC_TRNS,
+ KC_TRNS,KC_HASH,KC_DLR, KC_LPRN,KC_RPRN,KC_GRV,
+ KC_TRNS,KC_PERC,KC_CIRC,KC_LBRC,KC_RBRC,KC_TILD,KC_TRNS,
+ KC_TRNS,M(3),KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_PSCR,
+ KC_TRNS, KC_UP, KC_7, KC_8, KC_9, KC_ASTR, KC_TRNS,
+ KC_DOWN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS,
+ KC_TRNS, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS, KC_TRNS,
+ KC_TRNS,KC_DOT, KC_0, KC_EQL, LALT(KC_F4),
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ LCTL(LALT(KC_DEL)), KC_TRNS, KC_TRNS
+),
+/* Keymap 2: Media and mouse keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | TEENSY | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | MsUp | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | |MsLeft|MsDown|MsRght| |------| |------| | | | | | Play |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | | | | Prev | Next | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | Lclk | Rclk | |VolDn |VolUp | Mute | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | |Brwser|
+ * | | |------| |------| |Back |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// MEDIA AND MOUSE
+[MDIA] = KEYMAP(
+ RESET, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MPRV, KC_MNXT, KC_TRNS, KC_TRNS,
+ KC_VOLD, KC_VOLU, KC_MUTE, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_WBAK
+),
+/* Keymap 3: Unicode Entry
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | Alt | 1 | 2 | 3 | 4 | 5 | 6 | | 7 | 8 | 9 | 0 | + | + | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Alt | | | E | | | | | | | 7 | 8 | 9 | + | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | Alt | A | | D | F | |------| |------| | 4 | 5 | 6 | + | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | Alt | | | C | | B | | | | | 1 | 2 | 3 | + | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | Alt | Alt | Alt | | | | 0 | 0 | 0 | + | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * WINDOWS ONLY SETUP!! | ~L3 | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | Alt | Alt |------| |------| Alt | Alt |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[UNIC] = KEYMAP( // layer 3 : Unicode Entry
+ // left hand
+ KC_LALT, KC_P1, KC_P2, KC_P3, KC_P4, KC_P5, KC_P6,
+ KC_LALT, KC_TRNS, KC_TRNS, KC_E, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_LALT, KC_A, KC_TRNS, KC_D, KC_F, KC_TRNS,
+ KC_LALT, KC_TRNS, KC_TRNS, KC_C, KC_TRNS, KC_B, KC_TRNS,
+ KC_LALT, KC_LALT, KC_LALT, KC_TRNS,KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_LALT,KC_LALT, KC_TRNS,
+ // right hand
+ KC_P7, KC_P8, KC_P9, KC_P0, KC_PPLS,KC_PPLS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_P7, KC_P8, KC_P9, KC_PPLS, KC_TRNS,
+ KC_TRNS, KC_P4, KC_P5, KC_P6, KC_PPLS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_P1, KC_P2, KC_P3, KC_PPLS, KC_TRNS,
+ KC_P0, KC_P0, KC_P0, KC_PPLS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_LALT, KC_LALT
+ ),
+};
+
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(SYMB), // FN1 - Momentary Layer 1 (Symbols)
+ [2] = ACTION_LAYER_TAP_TOGGLE(MDIA), // FN2 - Momentary Layer 2 (Media)
+ [3] = ACTION_LAYER_TAP_TOGGLE(UNIC) // FN3 - Momentary Layer 3 (Unicode entry)
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ case 3: // this would trigger when you hit a key mapped as M(3)
+ if (record->event.pressed) {
+ return MACRO( I(255), D(LALT), T(P1), T(P5), T(P6), U(LALT), END );
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case 1:
+ ergodox_right_led_1_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ case 3:
+ ergodox_right_led_3_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/alexjj/readme.md b/keyboards/ergodox_ez/keymaps/alexjj/readme.md
new file mode 100644
index 000000000..239e32d39
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/alexjj/readme.md
@@ -0,0 +1,179 @@
+Englishman in New York
+===========================
+
+:microphone: :tea:
+
+About
+------
+
+After using the massdrop configurator to get the basics, I wanted to add a
+little extra to my ergodox. Notably the Hyper hotkey, the press and hold,
+and a way to have my beloved £ :pound: symbol available<sup>[1](#unicode)</sup>. Why not switch to a GB
+layout? Well the computers I use are US keymap'd and I can't always change
+that. Plus I've got used to 2/@ and 3/# and moving to the ergodox was hard
+enough. :sweat_smile:
+
+I started from the default and edited from there as I needed. It's somewhat
+similar to a regular layout, particularly R1 and shift/controls. I ended up
+with a few keys that were blank, so I'm testing out some shortcuts. Alt+F4 for
+quitting things in Windows, is one example, but I felt it was better placed on
+the 1st layer - in case of fat fingers.
+
+Layout
+-------
+
+![Layout](rl-layout.jpg "Isn't it lovely")
+
+### Base Layer
+
+```
+,--------------------------------------------------. ,--------------------------------------------------.
+| ESC | 1! | 2@ | 3# | 4$ | 5% | 6^ | | 7& | 8* | 9( | 0) | -_ | += | BkSp |
+|--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+| Tab | Q | W | E | R | T | { | | } | Y | U | I | O | P | |\ |
+|--------+------+------+------+------+------| [ | | ] |------+------+------+------+------+--------|
+| Win | A | S | D | F | G |------| |------| H | J | K | L | :; | '" |
+|--------+------+------+------+------+------| Home | | End |------+------+------+------+------+--------|
+| LShift |Z/Alt | X | C | V | B | | | | N | M | , | . | Alt | RShift |
+`--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ |LCtrl | COPY | PASTE| Left | Right| | Down | Up |Hyper | `~ | RCtrl |
+ `----------------------------------' `----------------------------------'
+ ,-------------. ,-------------.
+ Hyper = Ctrl+Super+Alt+Shift | ~L3 | F5 | | F2 | ~L2 |
+ ,------|------|------| |------+------+------.
+ | | | PgUp | | Ins | | |
+ | Enter| BkSp |------| |------| ~L1 |Space |
+ | | | PgDn | | Del | | |
+ `--------------------' `--------------------'
+```
+
+### Symbol Layer
+
+```
+,--------------------------------------------------. ,--------------------------------------------------.
+| | F1 | F2 | F3 | F4 | F5 | F6 | | F7 | F8 | F9 | F10 | F11 | F12 |PrintScr|
+|--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+| | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | |
+|--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+| | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
+|--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+| | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
+`--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ | | £ | | | | | | . | 0 | = |Alt+F4|
+ `----------------------------------' `----------------------------------'
+ ↑ ,-------------. ,-------------.
+ THERE! | | | | | |
+ ,------|------|------| |------+------+------.
+ CAD = Ctrl + Alt + Delete | | | | | | | |
+ | | |------| |------| | |
+ | | | | | CAD | | |
+ `--------------------' `--------------------'
+```
+### Media Layer
+
+Not touched this, not used either.
+
+```
+,--------------------------------------------------. ,--------------------------------------------------.
+| TEENSY | | | | | | | | | | | | | | |
+|--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+| | | | MsUp | | | | | | | | | | | |
+|--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+| | |MsLeft|MsDown|MsRght| |------| |------| | | | | | Play |
+|--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+| | | | | | | | | | | | Prev | Next | | |
+`--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ | | | | Lclk | Rclk | |VolDn |VolUp | Mute | | |
+ `----------------------------------' `----------------------------------'
+ ,-------------. ,-------------.
+ | | | | | |
+ ,------|------|------| |------+------+------.
+ | | | | | | |Brwser|
+ | | |------| |------| |Back |
+ | | | | | | | |
+ `--------------------' `--------------------'
+```
+### Unicode Layer
+
+Used to enter/test unicode input on Windows. All numbers are numpad keys.
+
+```
+,--------------------------------------------------. ,--------------------------------------------------.
+| Alt | 1 | 2 | 3 | 4 | 5 | 6 | | 7 | 8 | 9 | 0 | + | + | |
+|--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+| Alt | | | E | | | | | | | 7 | 8 | 9 | + | |
+|--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+| Alt | A | | D | F | |------| |------| | 4 | 5 | 6 | + | |
+|--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+| Alt | | | C | | B | | | | | 1 | 2 | 3 | + | |
+`--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ | Alt | Alt | Alt | | | | 0 | 0 | 0 | + | |
+ `----------------------------------' `----------------------------------'
+ ,-------------. ,-------------.
+ WINDOWS ONLY SETUP!! | ~L3 | | | | |
+ ,------|------|------| |------+------+------.
+ | | | | | | | |
+ | Alt | Alt |------| |------| Alt | Alt |
+ | | | | | | | |
+ `--------------------' `--------------------'
+```
+
+
+Usage
+------
+
+~L1 / L2 / L3 will momentarily switch to a layer if held and another key is pressed.
+If pressed and released will remain on layer until pressed again.
+
+### Unicode
+
+This layout is for Windows only. To enter a character Press and Hold Alt, type + and hex code then release Alt.
+
+Changelog
+-----------
+
+### [0.2.1] - 2016-04-05
+
+* Changed £ to alt code in Windows. Windows sucks at unicode.
+
+### [0.2.0] - 2016-03-27
+
+* Added unicode layer
+* Moved Copy/Paste to left hand side
+* Switched Enter and Space (again)
+* Added L3 (unicode layer) toggle
+* Removed Press and Hold for Alt on right hand size (/)
+* Swapped Volume Up/Down to match arrows
+* Tried fixing £ macro
+* Removed * in the matrix function things (upstream change)
+
+### [0.1.1] - 2016-03-23
+
+* Changed £ input to a macro
+
+
+### [0.1.0] - 2016-03-22
+
+After actually using the keyboard, I've made some changes:
+
+* Swapped Enter and Space
+* Moved backspace to thumb keys (top right still remains)
+* Added Ctrl+Alt+Delete
+* Added Teensy Reset on 2nd layer
+* Switched Up and Down
+* Changed copy/paste to be Ctrl+c and Ctrl+v as KC_COPY/PASTE didn't work (in Windows)
+* Moved ~L2 to replace +L1 after learning how the function works (notes above)
+* Hopefully fixed GBP symbol (unicode enabled in MakeFile)
+
+### [0.0.1] - 2016-03-21
+
+First version
+
+
+Issues
+-------
+
+Space for feedback and notes for future improvements
+
+----
+<sup><a name="unicode">1</a></sup>: For Windows only, and you have to edit the [registry](https://en.wikipedia.org/wiki/Unicode_input#Hexadecimal_code_input).
diff --git a/keyboards/ergodox_ez/keymaps/alexjj/rl-layout.jpg b/keyboards/ergodox_ez/keymaps/alexjj/rl-layout.jpg
new file mode 100644
index 000000000..e4e92bf46
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/alexjj/rl-layout.jpg
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/algernon/COPYING b/keyboards/ergodox_ez/keymaps/algernon/COPYING
new file mode 100644
index 000000000..94a9ed024
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/algernon/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/keyboards/ergodox_ez/keymaps/algernon/Makefile b/keyboards/ergodox_ez/keymaps/algernon/Makefile
new file mode 100644
index 000000000..cd7e9e9d2
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/algernon/Makefile
@@ -0,0 +1,26 @@
+BOOTMAGIC_ENABLE=no
+COMMAND_ENABLE=no
+SLEEP_LED_ENABLE=no
+UNICODE_ENABLE=no
+FORCE_NKRO ?= yes
+
+ifeq (${FORCE_NKRO},yes)
+OPT_DEFS += -DFORCE_NKRO
+endif
+
+KEYMAP_VERSION = $(shell \
+ if [ -d "${KEYMAP_PATH}/.git" ]; then \
+ cd "${KEYMAP_PATH}" && git describe --abbrev=6 --dirty --always --tags --match 'v*' 2>/dev/null; \
+ else echo QMK; fi)
+
+KEYMAP_BRANCH = $(shell \
+ if [ -d "${KEYMAP_PATH}/.git" ]; then \
+ cd "${KEYMAP_PATH}"; \
+ fi; \
+ git rev-parse --abbrev-ref HEAD 2>/dev/null)
+
+OPT_DEFS += -DKEYMAP_VERSION=\"$(KEYMAP_VERSION)\\\#$(KEYMAP_BRANCH)\"
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif
diff --git a/keyboards/ergodox_ez/keymaps/algernon/config.h b/keyboards/ergodox_ez/keymaps/algernon/config.h
new file mode 100644
index 000000000..9bb1025be
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/algernon/config.h
@@ -0,0 +1,27 @@
+#ifndef CONFIG_ALGERNON_H
+#define CONFIG_ALGERNON_H
+
+#include "../../config.h"
+
+#undef MOUSEKEY_TIME_TO_MAX
+#undef MOUSEKEY_MAX_SPEED
+
+#define MOUSEKEY_TIME_TO_MAX 1
+#define MOUSEKEY_MAX_SPEED 2
+
+#undef MOUSEKEY_DELAY
+#define MOUSEKEY_DELAY 0
+
+#undef MOUSEKEY_WHEEL_DELAY
+#define MOUSEKEY_WHEEL_DELAY 0
+
+#define ONESHOT_TAP_TOGGLE 2
+#define ONESHOT_TIMEOUT 3000
+
+#undef LOCKING_SUPPORT_ENABLE
+#undef LOCKING_RESYNC_ENABLE
+
+#undef LEADER_TIMEOUT
+#define LEADER_TIMEOUT 1000
+
+#endif
diff --git a/keyboards/ergodox_ez/keymaps/algernon/images/base-layer.png b/keyboards/ergodox_ez/keymaps/algernon/images/base-layer.png
new file mode 100644
index 000000000..c4e298b6b
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/algernon/images/base-layer.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/algernon/images/experimental-layer.png b/keyboards/ergodox_ez/keymaps/algernon/images/experimental-layer.png
new file mode 100644
index 000000000..81155851b
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/algernon/images/experimental-layer.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/algernon/images/hun-layer.png b/keyboards/ergodox_ez/keymaps/algernon/images/hun-layer.png
new file mode 100644
index 000000000..104a9544d
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/algernon/images/hun-layer.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/algernon/images/nav-n-media-layer.png b/keyboards/ergodox_ez/keymaps/algernon/images/nav-n-media-layer.png
new file mode 100644
index 000000000..16d29e124
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/algernon/images/nav-n-media-layer.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/algernon/images/one-handed-layer.png b/keyboards/ergodox_ez/keymaps/algernon/images/one-handed-layer.png
new file mode 100644
index 000000000..698d11e5f
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/algernon/images/one-handed-layer.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/algernon/images/steno-layer.png b/keyboards/ergodox_ez/keymaps/algernon/images/steno-layer.png
new file mode 100644
index 000000000..fe3c03c93
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/algernon/images/steno-layer.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/algernon/keymap.c b/keyboards/ergodox_ez/keymaps/algernon/keymap.c
new file mode 100644
index 000000000..2af3d5f8c
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/algernon/keymap.c
@@ -0,0 +1,1104 @@
+/*
+ * algernon's ErgoDox EZ layout, please see the readme.md file!
+ */
+
+#include "ergodox_ez.h"
+#include "led.h"
+#include "debug.h"
+#include "action_layer.h"
+#include "action_util.h"
+#include "mousekey.h"
+#include "timer.h"
+#include "keymap_plover.h"
+
+/* Layers */
+
+enum {
+ BASE = 0,
+ EXPRM,
+ ARRW,
+ APPSEL,
+ HUN,
+ NMDIA,
+ OHLFT,
+ OHRGT,
+ PLVR,
+};
+
+/* Macros */
+
+enum {
+ NONE = 0,
+ // Buttons that do extra stuff
+ A_GUI,
+ A_PLVR,
+ A_ESC,
+ A_MPN,
+
+ // Function / number keys
+ KF_1, // 1, F1
+ KF_2, // 2, F2
+ KF_3, // ...
+ KF_4,
+ KF_5,
+ KF_6,
+ KF_7,
+ KF_8,
+ KF_9,
+ KF_10,
+ KF_11, // =, F11
+
+ // Application select keys
+ APP_SLK, // Slack
+ APP_EMCS, // Emacs
+ APP_TERM, // Terminal
+ APP_CHRM, // Chrome
+ APP_MSIC, // Music
+
+ // Diagonal mouse movement
+ A_MUL,
+ A_MUR,
+ A_MDL,
+ A_MDR,
+
+ // Hungarian layer keys
+ HU_AA, // Á
+ HU_OO, // Ó
+ HU_EE, // É
+ HU_UU, // Ú
+ HU_II, // Í
+ HU_OE, // Ö
+ HU_UE, // Ü
+ HU_OEE, // Ő
+ HU_UEE, // Ű
+
+ // One-handed layout specials
+ OH_BSSPC,
+ OH_ENTSFT,
+ OH_BASE,
+ OH_LEFT,
+ OH_RIGHT,
+};
+
+/* Fn keys */
+
+enum {
+ F_BSE = 0,
+ F_HUN,
+ F_GUI,
+ F_SFT,
+ F_ALT,
+ F_CTRL
+};
+
+/* Custom keycodes */
+
+enum {
+ CT_CLN = 0x7101
+};
+
+/* States & timers */
+
+uint16_t gui_timer = 0;
+
+uint16_t kf_timers[12];
+
+uint16_t oh_base_timer = 0;
+uint16_t oh_bsspc_timer = 0;
+uint16_t oh_entsft_timer = 0;
+
+#define OH_BLINK_INTERVAL 500
+
+uint8_t oh_left_blink = 0;
+uint16_t oh_left_blink_timer = 0;
+uint8_t oh_right_blink = 0;
+uint16_t oh_right_blink_timer = 0;
+
+uint8_t ct_cln_count = 0;
+uint16_t ct_cln_timer = 0;
+
+/* The Keymap */
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+
+/* Keymap 0: Base Layer
+ *
+ * ,-----------------------------------------------------. ,-----------------------------------------------------.
+ * | `~ | 1 F1 | 2 F2 | 3 F3 | 4 F4 | 5 F5 | Plvr | | 1HND | 6 F6 | 7 F7 | 8 F8 | 9 F9 | 0 F10| F11 |
+ * |-----------+------+------+------+------+-------------| |------+------+------+------+------+------+-----------|
+ * | Next/Prev | ' | , | . | P | Y | [ | | ] | F | G | C | R | L | \ |
+ * |-----------+------+------+------+------+------| | | |------+------+------+------+------+-----------|
+ * | Tab | A | O | E | U | I |------| |------| D | H | T | N | S | = |
+ * |-----------+------+------+------+------+------| ( | | ) |------+------+------+------+------+-----------|
+ * | Play/Pause| / | Q | J | K | X | | | | B | M | W | V | Z | Stop |
+ * `-----------+------+------+------+------+-------------' `-------------+------+------+------+------+-----------'
+ * | | | Left | Up | : | | - | Down | Rght | | |
+ * `-----------------------------------' `-----------------------------------'
+ * ,-------------. ,-------------.
+ * | LAlt | GUI | | MDIA | ARRW |
+ * ,------|------|------| |------+------+------.
+ * | | | Ctrl | | LEAD | | |
+ * |Backsp|LShift|------| |------| Enter| Space|
+ * | | | ESC | | HUN | | |
+ * `--------------------' `--------------------'
+ */
+[BASE] = KEYMAP(
+// left hand
+ KC_GRV ,M(KF_1) ,M(KF_2) ,M(KF_3),M(KF_4),M(KF_5),M(A_PLVR)
+,M(A_MPN) ,KC_QUOT ,KC_COMM ,KC_DOT ,KC_P ,KC_Y ,KC_LBRC
+,KC_TAB ,KC_A ,KC_O ,KC_E ,KC_U ,KC_I
+,KC_MPLY ,KC_SLSH ,KC_Q ,KC_J ,KC_K ,KC_X ,KC_LPRN
+,KC_NO ,KC_NO ,KC_LEFT ,KC_UP ,CT_CLN
+
+ ,F(F_ALT),F(F_GUI)
+ ,F(F_CTRL)
+ ,KC_BSPC,F(F_SFT),M(A_ESC)
+
+ // right hand
+ ,M(OH_LEFT),M(KF_6),M(KF_7),M(KF_8),M(KF_9) ,M(KF_10) ,KC_F11
+ ,KC_RBRC ,KC_F ,KC_G ,KC_C ,KC_R ,KC_L ,KC_BSLS
+ ,KC_D ,KC_H ,KC_T ,KC_N ,KC_S ,KC_EQL
+ ,KC_RPRN ,KC_B ,KC_M ,KC_W ,KC_V ,KC_Z ,KC_MSTP
+ ,KC_MINS,KC_DOWN,KC_RGHT ,KC_NO ,KC_NO
+
+ ,OSL(NMDIA),OSL(ARRW)
+ ,KC_LEAD
+ ,F(F_HUN) ,KC_ENT ,KC_SPC
+ ),
+
+/* Keymap 1: Experimental layer
+ *
+ * ,-----------------------------------------------------. ,-----------------------------------------------------.
+ * | `~ | 1 F1 | 2 F2 | 3 F3 | 4 F4 | 5 F5 | Plvr | | 1HND | 6 F6 | 7 F7 | 8 F8 | 9 F9 | 0 F10| F11 |
+ * |-----------+------+------+------+------+-------------| |------+------+------+------+------+------+-----------|
+ * | Next/Prev | ' | , | . | P | Y | [ | | ] | L | F | C | R | J | = |
+ * |-----------+------+------+------+------+------| | | |------+------+------+------+------+-----------|
+ * | Tab | A | O | E | U | I |------| |------| D | H | T | N | S | \ |
+ * |-----------+------+------+------+------+------| ( | | ) |------+------+------+------+------+-----------|
+ * | Play/Pause| Z | G | V | K | X | | | | Q | M | W | B | / | Stop |
+ * `-----------+------+------+------+------+-------------' `-------------+------+------+------+------+-----------'
+ * | | | Left | Up | : | | - | Down | Rght | | |
+ * `-----------------------------------' `-----------------------------------'
+ * ,-------------. ,-------------.
+ * | LAlt | GUI | | MDIA | ARRW |
+ * ,------|------|------| |------+------+------.
+ * | | | Ctrl | | LEAD | | |
+ * |Backsp|LShift|------| |------| Enter| Space|
+ * | | | ESC | | HUN | | |
+ * `--------------------' `--------------------'
+ */
+[EXPRM] = KEYMAP(
+// left hand
+ KC_GRV ,M(KF_1) ,M(KF_2) ,M(KF_3),M(KF_4),M(KF_5),M(A_PLVR)
+,M(A_MPN) ,KC_QUOT ,KC_COMM ,KC_DOT ,KC_P ,KC_Y ,KC_LBRC
+,KC_TAB ,KC_A ,KC_O ,KC_E ,KC_U ,KC_I
+,KC_MPLY ,KC_Z ,KC_G ,KC_V ,KC_K ,KC_X ,KC_LPRN
+,KC_NO ,KC_NO ,KC_LEFT ,KC_UP ,CT_CLN
+
+ ,F(F_ALT),F(F_GUI)
+ ,F(F_CTRL)
+ ,KC_BSPC,F(F_SFT),M(A_ESC)
+
+ // right hand
+ ,M(OH_LEFT),M(KF_6),M(KF_7),M(KF_8),M(KF_9) ,M(KF_10) ,KC_F11
+ ,KC_RBRC ,KC_L ,KC_F ,KC_C ,KC_R ,KC_J ,KC_BSLS
+ ,KC_D ,KC_H ,KC_T ,KC_N ,KC_S ,KC_EQL
+ ,KC_RPRN ,KC_Q ,KC_M ,KC_W ,KC_B ,KC_SLSH ,KC_MSTP
+ ,KC_MINS,KC_DOWN,KC_RGHT ,KC_NO ,KC_NO
+
+ ,OSL(NMDIA),OSL(ARRW)
+ ,KC_LEAD
+ ,F(F_HUN) ,KC_ENT ,KC_SPC
+ ),
+
+/* Keymap 2: Arrow layer
+ *
+ * ,-----------------------------------------------------. ,-----------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |-----------+------+------+------+------+-------------| |------+------+------+------+------+------+-----------|
+ * | | | | | | | | | | | | | | | |
+ * |-----------+------+------+------+------+------| | | |------+------+------+------+------+-----------|
+ * | | | | | | |------| |------| | | | | | |
+ * |-----------+------+------+------+------+------| | | |------+------+------+------+------+-----------|
+ * | | | | | | | | | | | | | | | |
+ * `-----------+------+------+------+------+-------------' `-------------+------+------+------+------+-----------'
+ * | | | Home | PgUp | | | | PgDn | End | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+
+[ARRW] = KEYMAP(
+// left hand
+ KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+,KC_TRNS ,KC_TRNS ,KC_HOME ,KC_PGUP ,KC_TRNS
+
+ ,KC_TRNS ,KC_TRNS
+ ,KC_TRNS
+ ,KC_TRNS ,KC_TRNS ,KC_TRNS
+
+ // right hand
+ ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+ ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+ ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+ ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+ ,KC_TRNS ,KC_PGDN ,KC_END ,KC_TRNS ,KC_TRNS
+
+ ,KC_TRNS ,KC_TRNS
+ ,KC_TRNS
+ ,KC_TRNS ,KC_TRNS ,KC_TRNS
+ ),
+
+/* Keymap 3: Application select layer
+ *
+ * ,-----------------------------------------------------. ,-----------------------------------------------------.
+ * | |Music |Slack |Emacs |Term |Chrome| | | | | | | | | |
+ * |-----------+------+------+------+------+-------------| |------+------+------+------+------+------+-----------|
+ * | | | | | | | | | | | | | | | |
+ * |-----------+------+------+------+------+------| | | |------+------+------+------+------+-----------|
+ * | | | | | | |------| |------| | | | | | |
+ * |-----------+------+------+------+------+------| | | |------+------+------+------+------+-----------|
+ * | | | | | | | | | | | | | | | |
+ * `-----------+------+------+------+------+-------------' `-------------+------+------+------+------+-----------'
+ * | | | | | | | | | | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+
+[APPSEL] = KEYMAP(
+// left hand
+ KC_TRNS ,M(APP_MSIC),M(APP_SLK),M(APP_EMCS),M(APP_TERM),M(APP_CHRM),KC_TRNS
+,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+
+ ,KC_TRNS ,KC_TRNS
+ ,KC_TRNS
+ ,KC_TRNS ,KC_TRNS ,KC_TRNS
+
+ // right hand
+ ,KC_TRNS ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_TRNS
+ ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+ ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+ ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+ ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+
+ ,KC_TRNS ,KC_TRNS
+ ,KC_TRNS
+ ,KC_TRNS ,KC_TRNS ,KC_TRNS
+ ),
+
+
+/* Keymap 4: Hungarian Layer
+ *
+ * ,-----------------------------------------------------. ,-----------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |-----------+------+------+------+------+-------------| |------+------+------+------+------+------+-----------|
+ * | | | Ő | | Ű | | | | | | | | | | |
+ * |-----------+------+------+------+------+------| | | |------+------+------+------+------+-----------|
+ * | | Á | Ó | É | Ú | Í |------| |------| | | | | | |
+ * |-----------+------+------+------+------+------| | | |------+------+------+------+------+-----------|
+ * | | | Ö | | Ü | | | | | | | | | | |
+ * `-----------+------+------+------+------+-------------' `-------------+------+------+------+------+-----------'
+ * | | | | | | | | | | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | BASE | | |
+ * `--------------------' `--------------------'
+ */
+
+[HUN] = KEYMAP(
+// left hand
+ KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO
+,KC_NO ,KC_NO ,M(HU_OEE),KC_NO ,M(HU_UEE),KC_NO ,KC_NO
+,KC_NO ,M(HU_AA),M(HU_OO) ,M(HU_EE),M(HU_UU) ,M(HU_II)
+,KC_NO ,KC_NO ,M(HU_OE) ,KC_NO ,M(HU_UE) ,KC_NO ,KC_NO
+,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO
+
+ ,KC_NO ,KC_NO
+ ,KC_NO
+ ,KC_NO ,KC_TRNS ,KC_TRNS
+
+ // right hand
+ ,KC_TRNS ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO
+ ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO
+ ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO
+ ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO
+ ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO
+
+ ,KC_NO ,KC_NO
+ ,KC_NO
+ ,F(F_BSE),KC_TRNS ,KC_TRNS
+ ),
+
+/* Keymap 5: Navigation & Media layer
+ *
+ * ,-----------------------------------------------------. ,-----------------------------------------------------.
+ * | MS Slow | | | | | |ScrLCK| |ScrLCK| | | | | | |
+ * |-----------+------+------+------+------+-------------| |------+------+------+------+------+------+-----------|
+ * | MS Normal | | Home | Up | PgUp | | | |Scroll| |MsUpL | MsUp |MsUpR | |PrintScreen|
+ * |-----------+------+------+------+------+------| | | Up |------+------+------+------+------+-----------|
+ * | MS Fast | | Left | Down | Right| |------| |------| |MsLeft| MsDn |MsRght| | |
+ * |-----------+------+------+------+------+------| | |Scroll|------+------+------+------+------+-----------|
+ * | Play/Pause| | End | Down | PgDn | | | | Down | |MsDnL | MsDn |MsDnR | | Stop |
+ * `-----------+------+------+------+------+-------------' `-------------+------+------+------+------+-----------'
+ * | | | | | | | | | | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | Mute | VlUp | | BASE | MClk |
+ * ,------|------|------| |------+------+------.
+ * | | | VlDn | | Prev |Left |Right |
+ * | SPC | Enter|------| |------| Click| Click|
+ * | | | ESC | | Next | | |
+ * `--------------------' `--------------------'
+ */
+[NMDIA] = KEYMAP(
+// left hand
+ KC_ACL0 ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,LGUI(KC_L)
+,KC_ACL1 ,KC_NO ,KC_HOME ,KC_UP ,KC_PGUP ,KC_NO ,KC_NO
+,KC_ACL2 ,KC_NO ,KC_LEFT ,KC_DOWN ,KC_RIGHT,KC_NO
+,KC_MPLY ,KC_NO ,KC_END ,KC_DOWN ,KC_PGDN ,KC_NO ,KC_NO
+,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO
+ ,KC_MUTE ,KC_VOLU
+ ,KC_VOLD
+ ,KC_SPC,KC_ENTER,M(A_ESC)
+
+ // right hand
+ ,LGUI(KC_L),KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO
+ ,KC_WH_U ,KC_NO ,M(A_MUL),KC_MS_U ,M(A_MUR),KC_NO ,KC_PSCR
+ ,KC_NO ,KC_MS_L ,KC_MS_D ,KC_MS_R ,KC_NO ,KC_NO
+ ,KC_WH_D ,KC_NO ,M(A_MDL),KC_MS_D ,M(A_MDR),KC_NO ,KC_MSTP
+ ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO
+
+ ,KC_TRNS ,KC_MS_BTN3
+ ,KC_MPRV
+ ,KC_MNXT ,KC_BTN1 ,KC_BTN2
+ ),
+
+/* Keymap 6: One-handed, left side
+ *
+ * ,-----------------------------------------------------.
+ * | `~ | 1 F1 | 2 F2 | 3 F3 | 4 F4 | 5 F5 |A BSE|
+ * |-----------+------+------+------+------+-------------|
+ * | Tab | ' | , | . | P | Y | [ |
+ * |-----------+------+------+------+------+------| |
+ * | - | A | O | E | U | I |------|
+ * |-----------+------+------+------+------+------| ( |
+ * | Play/Pause| ; | Q | J | K | X | |
+ * `-----------+------+------+------+------+-------------'
+ * | Home | End | Down | Up | ESC |
+ * `-----------------------------------'
+ * ,-------------.
+ * | LAlt | GUI |
+ * ,------|------|------|
+ * |BackSp|LShift| Ctrl |
+ * | | |------|
+ * |Space |Enter |OTHER |
+ * `--------------------'
+ */
+[OHLFT] = KEYMAP(
+// left hand
+ KC_GRV ,M(KF_1) ,M(KF_2) ,M(KF_3) ,M(KF_4) ,M(KF_5) ,M(OH_BASE)
+,KC_TAB ,KC_QUOT ,KC_COMM ,KC_DOT ,KC_P ,KC_Y ,KC_LBRC
+,KC_MINS ,KC_A ,KC_O ,KC_E ,KC_U ,KC_I
+,KC_MPLY ,KC_SCLN ,KC_Q ,KC_J ,KC_K ,KC_X ,KC_LPRN
+,KC_HOME ,KC_END ,KC_DOWN ,KC_UP ,M(A_ESC)
+
+ ,KC_TRNS ,KC_TRNS
+ ,KC_TRNS
+ ,M(OH_BSSPC),M(OH_ENTSFT),M(OH_RIGHT)
+
+ // right hand
+ ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO
+ ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO
+ ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO
+ ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO
+ ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO
+
+ ,KC_NO ,KC_NO
+ ,KC_NO
+ ,KC_NO ,KC_NO ,KC_NO
+ ),
+
+/* Keymap 7: One-handed, right side
+ *
+ * ,-----------------------------------------------------.
+ * | = F11 | 0 F10| 9 F9 | 8 F8 | 7 F7 | 6 F6 |A BSE|
+ * |-----------+------+------+------+------+-------------|
+ * | / | L | R | C | G | F | ] |
+ * |-----------+------+------+------+------+------| |
+ * | \ | S | N | T | H | D |------|
+ * |-----------+------+------+------+------+------| ) |
+ * | Stop | Z | V | W | M | B | |
+ * `-----------+------+------+------+------+-------------'
+ * | PgDn | PgUp | Right| Left | ESC |
+ * `-----------------------------------'
+ * ,-------------.
+ * | LAlt | GUI |
+ * ,------|------|------|
+ * |BackSp|LShift| Ctrl |
+ * | | |------|
+ * |Space |Enter |OTHER |
+ * `--------------------'
+ */
+[OHRGT] = KEYMAP(
+// left hand
+ M(KF_11) ,M(KF_10) ,M(KF_9) ,M(KF_8) ,M(KF_7) ,M(KF_6) ,M(OH_BASE)
+,KC_SLSH ,KC_L ,KC_R ,KC_C ,KC_G ,KC_F ,KC_RBRC
+,KC_BSLS ,KC_S ,KC_N ,KC_T ,KC_H ,KC_D
+,KC_MSTP ,KC_Z ,KC_V ,KC_W ,KC_M ,KC_B ,KC_RPRN
+,KC_PGDN ,KC_PGUP ,KC_RGHT ,KC_LEFT ,M(A_ESC)
+
+ ,KC_TRNS ,KC_TRNS
+ ,KC_TRNS
+ ,M(OH_BSSPC),M(OH_ENTSFT),M(OH_LEFT)
+
+ // right hand
+ ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO
+ ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO
+ ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO
+ ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO
+ ,KC_NO ,KC_NO ,KC_NO ,KC_NO ,KC_NO
+
+ ,KC_NO ,KC_NO
+ ,KC_NO
+ ,KC_NO ,KC_NO ,KC_NO
+ ),
+
+/* Keymap 8: Steno for Plover
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | BASE | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | # | # | # | # | # | # | | # | # | # | # | # | # | # |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | T | P | H | |------| |------| | F | P | L | T | D |
+ * |--------+ S +------+------+------+ * | * | | * | * +------+------+------+------+--------|
+ * | | | K | W | R | | | | | | R | B | G | S | Z |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | | | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | A | O |------| |------| E | U |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+
+[PLVR] = KEYMAP(
+// left hand
+KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, M(A_PLVR),
+KC_NO, PV_NUM, PV_NUM, PV_NUM, PV_NUM, PV_NUM, PV_NUM,
+KC_NO, PV_LS, PV_LT, PV_LP, PV_LH, PV_STAR,
+KC_NO, PV_LS, PV_LK, PV_LW, PV_LR, PV_STAR, PV_STAR,
+KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+ KC_NO, KC_NO,
+ KC_NO,
+ PV_A, PV_O, KC_NO,
+
+ // right hand
+ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+ PV_NUM, PV_NUM, PV_NUM, PV_NUM, PV_NUM, PV_NUM, PV_NUM,
+ PV_STAR, PV_RF, PV_RP, PV_RL, PV_RT, PV_RD,
+ PV_STAR, PV_STAR, PV_RR, PV_RB, PV_RG, PV_RS, PV_RZ,
+ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+ KC_NO, KC_NO,
+ KC_NO,
+ KC_NO,PV_E, PV_U
+ ),
+
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [F_BSE] = ACTION_LAYER_CLEAR(ON_PRESS)
+ ,[F_HUN] = ACTION_LAYER_INVERT(HUN, ON_PRESS)
+ ,[F_GUI] = ACTION_MACRO_TAP(A_GUI)
+ ,[F_SFT] = ACTION_MODS_ONESHOT (MOD_LSFT)
+ ,[F_ALT] = ACTION_MODS_ONESHOT (MOD_LALT)
+ ,[F_CTRL] = ACTION_MODS_ONESHOT (MOD_LCTL)
+};
+
+void toggle_steno(int pressed)
+{
+ uint8_t layer = biton32(layer_state);
+
+ if (pressed) {
+ if (layer != PLVR) layer_on(PLVR); else layer_off(PLVR);
+
+ register_code(PV_LP);
+ register_code(PV_LH);
+ register_code(PV_LR);
+ register_code(PV_O);
+ register_code(PV_RL);
+ register_code(PV_RG);
+ } else {
+ unregister_code(PV_LP);
+ unregister_code(PV_LH);
+ unregister_code(PV_LR);
+ unregister_code(PV_O);
+ unregister_code(PV_RL);
+ unregister_code(PV_RG);
+ }
+}
+
+macro_t *ang_do_hun (keyrecord_t *record, uint16_t accent, uint16_t hun_char)
+{
+ uint8_t need_shift = 0;
+ uint8_t hold_shift = 0;
+
+ if (!record->event.pressed)
+ return MACRO_NONE;
+
+ layer_off (HUN);
+
+ if (keyboard_report->mods & MOD_BIT (KC_LSFT)) {
+ hold_shift = 1;
+ need_shift = 1;
+ unregister_code (KC_LSFT);
+ }
+ if ((get_oneshot_mods () & MOD_BIT(KC_LSFT)) && !has_oneshot_mods_timed_out ()) {
+ need_shift = 1;
+ hold_shift = 0;
+ unregister_code (KC_LSFT);
+ }
+
+ clear_oneshot_mods ();
+
+ register_code (KC_RALT);
+ unregister_code (KC_RALT);
+ if (accent == (KC_DQT)) {
+ register_code (KC_RSFT);
+ }
+ register_code (accent);
+ unregister_code (accent);
+ if (need_shift && accent != (KC_DQT)) {
+ register_code (KC_RSFT);
+ } else if (accent == (KC_DQT) && !need_shift) {
+ unregister_code (KC_RSFT);
+ }
+ register_code (hun_char);
+ unregister_code (hun_char);
+ if (need_shift || accent == (KC_DQT))
+ unregister_code (KC_RSFT);
+ if (hold_shift)
+ register_code (KC_LSFT);
+
+ return MACRO_NONE;
+}
+
+void ang_handle_kf (keyrecord_t *record, uint8_t id)
+{
+ uint8_t code = id - KF_1;
+
+ if (record->event.pressed) {
+ kf_timers[code] = timer_read ();
+ } else {
+ uint8_t kc;
+
+ if (timer_elapsed (kf_timers[code]) > TAPPING_TERM) {
+ // Long press
+ kc = KC_F1 + code;
+ } else {
+ if (id == KF_11)
+ kc = KC_EQL;
+ else
+ kc = KC_1 + code;
+ }
+
+ register_code (kc);
+ unregister_code (kc);
+ }
+}
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ switch(id) {
+ case A_ESC:
+ if (record->event.pressed) {
+ if ((get_oneshot_mods ()) && !has_oneshot_mods_timed_out ()) {
+ clear_oneshot_mods ();
+ } else {
+ register_code (KC_ESC);
+ }
+ layer_off (HUN);
+ } else {
+ unregister_code (KC_ESC);
+ }
+ break;
+
+ case A_MPN:
+ if (record->event.pressed) {
+ if (keyboard_report->mods & MOD_BIT(KC_LSFT) ||
+ ((get_oneshot_mods() & MOD_BIT(KC_LSFT)) && !has_oneshot_mods_timed_out())) {
+ int oneshot = ((get_oneshot_mods() & MOD_BIT(KC_LSFT)) && !has_oneshot_mods_timed_out());
+
+ if (oneshot)
+ clear_oneshot_mods ();
+ unregister_code (KC_LSFT);
+
+ register_code (KC_MPRV);
+ unregister_code (KC_MPRV);
+
+ if (!oneshot)
+ register_code (KC_LSFT);
+ } else {
+ return MACRO (T(MNXT), END);
+ }
+ }
+ break;
+
+ /* Hungarian layer */
+ case HU_AA:
+ return ang_do_hun (record, KC_QUOT, KC_A);
+ case HU_OO:
+ return ang_do_hun (record, KC_QUOT, KC_O);
+ case HU_EE:
+ return ang_do_hun (record, KC_QUOT, KC_E);
+ case HU_UU:
+ return ang_do_hun (record, KC_QUOT, KC_U);
+ case HU_II:
+ return ang_do_hun (record, KC_QUOT, KC_I);
+ case HU_OE:
+ return ang_do_hun (record, KC_DQT, KC_O);
+ case HU_UE:
+ return ang_do_hun (record, KC_DQT, KC_U);
+ case HU_OEE:
+ return ang_do_hun (record, KC_EQL, KC_O);
+ case HU_UEE:
+ return ang_do_hun (record, KC_EQL, KC_U);
+
+ /* Mouse movement */
+ case A_MUL:
+ if (record->event.pressed) {
+ mousekey_on(KC_MS_UP);
+ mousekey_on(KC_MS_LEFT);
+ } else {
+ mousekey_off(KC_MS_UP);
+ mousekey_off(KC_MS_LEFT);
+ }
+ mousekey_send();
+ break;
+
+ case A_MUR:
+ if (record->event.pressed) {
+ mousekey_on(KC_MS_UP);
+ mousekey_on(KC_MS_RIGHT);
+ } else {
+ mousekey_off(KC_MS_UP);
+ mousekey_off(KC_MS_RIGHT);
+ }
+ mousekey_send();
+ break;
+
+ case A_MDL:
+ if (record->event.pressed) {
+ mousekey_on(KC_MS_DOWN);
+ mousekey_on(KC_MS_LEFT);
+ } else {
+ mousekey_off(KC_MS_DOWN);
+ mousekey_off(KC_MS_LEFT);
+ }
+ mousekey_send();
+ break;
+
+ case A_MDR:
+ if (record->event.pressed) {
+ mousekey_on(KC_MS_DOWN);
+ mousekey_on(KC_MS_RIGHT);
+ } else {
+ mousekey_off(KC_MS_DOWN);
+ mousekey_off(KC_MS_RIGHT);
+ }
+ mousekey_send();
+ break;
+
+ /* Plover base */
+ case A_PLVR:
+ toggle_steno(record->event.pressed);
+ break;
+
+ /* GUI & AppSel */
+ case A_GUI:
+ if (record->event.pressed) {
+ register_code (KC_LGUI);
+ if (record->tap.count && !record->tap.interrupted) {
+ if (record->tap.count >= 2) {
+ register_code (KC_W);
+ layer_on (APPSEL);
+ set_oneshot_layer (APPSEL, ONESHOT_START);
+ }
+ } else {
+ record->tap.count = 0;
+ }
+ gui_timer = 0;
+ } else {
+ if (record->tap.count >= 2)
+ {
+ unregister_code (KC_W);
+ clear_oneshot_layer_state (ONESHOT_PRESSED);
+ }
+ gui_timer = timer_read ();
+ }
+ break;
+
+ case APP_SLK:
+ return MACRODOWN(T(S), T(L), T(A), T(C), T(K), T(ENT), END);
+
+ case APP_EMCS:
+ return MACRODOWN(T(E), T(M), T(A), T(C), T(S), T(ENT), END);
+
+ case APP_TERM:
+ return MACRODOWN(T(T), T(E), T(R), T(M), T(ENT), END);
+
+ case APP_CHRM:
+ return MACRODOWN(T(C), T(H), T(R), T(O), T(M), T(ENT), END);
+
+ case APP_MSIC:
+ return MACRODOWN(T(R), T(H), T(Y), T(T), T(H), T(M), T(B), T(O), T(X), T(ENT), END);
+
+ /* Function keys */
+ case KF_1 ... KF_11:
+ ang_handle_kf (record, id);
+ break;
+
+ /* 1HAND layout */
+ case OH_BASE:
+ if (record->event.pressed) {
+ oh_base_timer = timer_read ();
+ } else {
+ if (timer_elapsed (oh_base_timer) > TAPPING_TERM) {
+ layer_clear ();
+ } else {
+ return MACRO (T(APP), END);
+ }
+ }
+ break;
+
+ case OH_BSSPC:
+ if (record->event.pressed) {
+ oh_bsspc_timer = timer_read ();
+ } else {
+ if (timer_elapsed (oh_bsspc_timer) > TAPPING_TERM) {
+ return MACRO (T(BSPC), END);
+ } else {
+ return MACRO (T(SPC), END);
+ }
+ }
+ break;
+
+ case OH_ENTSFT:
+ if (record->event.pressed) {
+ oh_entsft_timer = timer_read ();
+ } else {
+ if (timer_elapsed (oh_entsft_timer) > TAPPING_TERM) {
+ if (keyboard_report->mods & MOD_BIT(KC_LSFT))
+ unregister_code (KC_LSFT);
+ else
+ register_code (KC_LSFT);
+ } else {
+ return MACRO (T(ENT), END);
+ }
+ }
+ break;
+
+ case OH_LEFT:
+ if (record->event.pressed) {
+ layer_move (OHLFT);
+ oh_left_blink = 1;
+ oh_left_blink_timer = timer_read ();
+ ergodox_right_led_1_on ();
+ }
+ break;
+
+ case OH_RIGHT:
+ if (record->event.pressed) {
+ layer_move (OHRGT);
+ oh_right_blink = 1;
+ oh_right_blink_timer = timer_read ();
+ ergodox_right_led_3_on ();
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+ ergodox_led_all_on();
+ for (int i = LED_BRIGHTNESS_HI; i > LED_BRIGHTNESS_LO; i--) {
+ ergodox_led_all_set (i);
+ _delay_ms (5);
+ }
+ _delay_ms(1000);
+ for (int i = LED_BRIGHTNESS_LO; i > 0; i--) {
+ ergodox_led_all_set (i);
+ _delay_ms (10);
+ }
+ ergodox_led_all_off();
+};
+
+LEADER_EXTERNS();
+
+void ang_do_unicode (void) {
+ register_code (KC_RCTL);
+ register_code (KC_RSFT);
+ register_code (KC_U);
+ unregister_code (KC_U);
+ unregister_code (KC_RSFT);
+ unregister_code (KC_RCTL);
+ _delay_ms (100);
+}
+
+void ang_tap (uint16_t codes[]) {
+ for (int i = 0; codes[i] != 0; i++) {
+ register_code (codes[i]);
+ unregister_code (codes[i]);
+ _delay_ms (50);
+ }
+}
+
+#define TAP_ONCE(code) \
+ register_code (code); \
+ unregister_code (code)
+
+uint8_t is_exp = 0;
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+ uint8_t layer = biton32(layer_state);
+
+ if (gui_timer && timer_elapsed (gui_timer) > TAPPING_TERM)
+ unregister_code (KC_LGUI);
+
+ if (ct_cln_timer && timer_elapsed (ct_cln_timer) > TAPPING_TERM) {
+ if (ct_cln_count == 1) {
+ register_code (KC_RSFT);
+ register_code (KC_SCLN);
+ unregister_code (KC_SCLN);
+ unregister_code (KC_RSFT);
+ } else if (ct_cln_count == 2) {
+ register_code (KC_SCLN);
+ unregister_code (KC_SCLN);
+ }
+
+ ct_cln_count = 0;
+ ct_cln_timer = 0;
+ }
+
+ if (layer != OHLFT)
+ oh_left_blink = 0;
+ if (layer != OHRGT)
+ oh_right_blink = 0;
+
+ if (layer == HUN) {
+ ergodox_right_led_2_on();
+ ergodox_right_led_3_on();
+ } else if (layer == NMDIA) {
+ ergodox_right_led_1_on();
+ ergodox_right_led_2_on();
+ } else if (layer == PLVR) {
+ ergodox_right_led_1_on ();
+ ergodox_right_led_2_on ();
+ ergodox_right_led_3_on ();
+ } else if (layer == EXPRM) {
+ ergodox_right_led_1_on ();
+ ergodox_right_led_2_on ();
+ ergodox_right_led_3_on ();
+
+ ergodox_right_led_2_set (LED_BRIGHTNESS_HI);
+ }
+
+ if (layer == OHLFT || layer == OHRGT) {
+ ergodox_right_led_2_on();
+
+ if (oh_left_blink) {
+ if (timer_elapsed (oh_left_blink_timer) > OH_BLINK_INTERVAL) {
+ if ((keyboard_report->mods & MOD_BIT(KC_LSFT)) == 0)
+ ergodox_right_led_1_off ();
+ }
+ if (timer_elapsed (oh_left_blink_timer) > OH_BLINK_INTERVAL * 2) {
+ ergodox_right_led_1_on ();
+ oh_left_blink_timer = timer_read ();
+ }
+ }
+
+ if (oh_right_blink) {
+ if (timer_elapsed (oh_right_blink_timer) > OH_BLINK_INTERVAL) {
+ if ((keyboard_report->mods & MOD_BIT(KC_LCTRL)) == 0)
+ ergodox_right_led_3_off ();
+ }
+ if (timer_elapsed (oh_right_blink_timer) > OH_BLINK_INTERVAL * 2) {
+ ergodox_right_led_3_on ();
+ oh_right_blink_timer = timer_read ();
+ }
+ }
+ }
+
+ if (keyboard_report->mods & MOD_BIT(KC_LSFT) ||
+ ((get_oneshot_mods() & MOD_BIT(KC_LSFT)) && !has_oneshot_mods_timed_out())) {
+ ergodox_right_led_1_set (LED_BRIGHTNESS_HI);
+ ergodox_right_led_1_on ();
+ } else {
+ ergodox_right_led_1_set (LED_BRIGHTNESS_LO);
+ if (layer != OHLFT && layer != NMDIA && layer != PLVR && layer != EXPRM)
+ ergodox_right_led_1_off ();
+ }
+
+ if (keyboard_report->mods & MOD_BIT(KC_LALT) ||
+ ((get_oneshot_mods() & MOD_BIT(KC_LALT)) && !has_oneshot_mods_timed_out())) {
+ ergodox_right_led_2_set (LED_BRIGHTNESS_HI);
+ ergodox_right_led_2_on ();
+ } else {
+ ergodox_right_led_2_set (LED_BRIGHTNESS_LO);
+ if (layer != OHRGT && layer != HUN && layer != OHLFT && layer != NMDIA && layer != PLVR && layer != EXPRM)
+ ergodox_right_led_2_off ();
+ }
+
+ if (keyboard_report->mods & MOD_BIT(KC_LCTRL) ||
+ ((get_oneshot_mods() & MOD_BIT(KC_LCTRL)) && !has_oneshot_mods_timed_out())) {
+ ergodox_right_led_3_set (LED_BRIGHTNESS_HI);
+ ergodox_right_led_3_on ();
+ } else {
+ ergodox_right_led_3_set (LED_BRIGHTNESS_LO);
+ if (layer != OHRGT && layer != HUN && layer != PLVR && layer != EXPRM)
+ ergodox_right_led_3_off ();
+ }
+
+ LEADER_DICTIONARY() {
+ leading = false;
+ leader_end ();
+
+ SEQ_ONE_KEY (KC_U) {
+ ang_do_unicode ();
+ }
+
+ SEQ_ONE_KEY (KC_V) {
+ SEND_STRING (QMK_KEYBOARD "/" QMK_KEYMAP " @ (" QMK_VERSION "/" KEYMAP_VERSION ")");
+ }
+
+ SEQ_ONE_KEY (KC_L) {
+ /* λ */
+ ang_do_unicode ();
+
+ uint16_t codes[] = {KC_0, KC_3, KC_B, KC_B, KC_ENT, 0};
+ ang_tap (codes);
+ }
+
+ SEQ_ONE_KEY (KC_Y) {
+ uint16_t codes[] = {KC_BSLS, KC_O, KC_SLSH, 0};
+ ang_tap (codes);
+ }
+
+ SEQ_ONE_KEY (KC_S) {
+ ang_do_unicode (); TAP_ONCE (KC_A); TAP_ONCE (KC_F); TAP_ONCE (KC_SPC);
+ TAP_ONCE (KC_BSLS);
+ register_code (KC_RSFT); TAP_ONCE (KC_MINS); TAP_ONCE (KC_9); unregister_code (KC_RSFT);
+ ang_do_unicode (); TAP_ONCE (KC_3); TAP_ONCE (KC_0); TAP_ONCE (KC_C); TAP_ONCE (KC_4); TAP_ONCE (KC_SPC);
+ register_code (KC_RSFT); TAP_ONCE (KC_0); TAP_ONCE (KC_MINS); unregister_code (KC_RSFT);
+ TAP_ONCE (KC_SLSH);
+ ang_do_unicode (); TAP_ONCE (KC_A); TAP_ONCE (KC_F); TAP_ONCE (KC_SPC);
+ }
+
+ SEQ_TWO_KEYS (KC_W, KC_M) {
+ register_code (KC_LALT);
+ register_code (KC_F2);
+ unregister_code (KC_F2);
+ unregister_code (KC_LALT);
+
+ _delay_ms (1000);
+
+ uint16_t codes[] = {KC_M, KC_A, KC_X, KC_MINS, KC_F, KC_O, KC_C, KC_U, KC_S, KC_E, KC_D, KC_ENT, 0};
+ ang_tap (codes);
+ register_code (KC_LGUI);
+ register_code (KC_UP);
+ unregister_code (KC_UP);
+ unregister_code (KC_LGUI);
+ }
+
+ SEQ_ONE_KEY (KC_E) {
+ if (is_exp == 0) {
+ default_layer_and (0);
+ default_layer_or ((1 << EXPRM));
+ is_exp = 1;
+
+ ergodox_led_all_off ();
+ ergodox_right_led_3_on ();
+ _delay_ms (100);
+ ergodox_right_led_2_on ();
+ _delay_ms (100);
+ ergodox_right_led_3_off ();
+ ergodox_right_led_1_on ();
+ _delay_ms (100);
+ ergodox_right_led_2_off ();
+ _delay_ms (100);
+ ergodox_right_led_1_off ();
+ } else {
+ is_exp = 0;
+ default_layer_and (0);
+ default_layer_or (1 << BASE);
+
+ ergodox_led_all_off ();
+ ergodox_right_led_1_on ();
+ _delay_ms (100);
+ ergodox_right_led_2_on ();
+ _delay_ms (100);
+ ergodox_right_led_1_off ();
+ ergodox_right_led_3_on ();
+ _delay_ms (100);
+ ergodox_right_led_2_off ();
+ _delay_ms (100);
+ ergodox_right_led_3_off ();
+ }
+ }
+ }
+}
+
+bool process_record_user (uint16_t keycode, keyrecord_t *record) {
+ switch(keycode) {
+ case CT_CLN:
+ if (record->event.pressed) {
+ ct_cln_count++;
+ ct_cln_timer = timer_read ();
+ } else {
+ }
+ return false;
+ break;
+
+ default:
+ if (ct_cln_count == 1) {
+ register_code (KC_RSFT);
+ register_code (KC_SCLN);
+ unregister_code (KC_SCLN);
+ unregister_code (KC_RSFT);
+ } else if (ct_cln_count == 2) {
+ register_code (KC_SCLN);
+ unregister_code (KC_SCLN);
+ }
+ ct_cln_count = 0;
+ ct_cln_timer = 0;
+ break;
+ }
+
+ return true;
+}
diff --git a/keyboards/ergodox_ez/keymaps/algernon/readme.md b/keyboards/ergodox_ez/keymaps/algernon/readme.md
new file mode 100644
index 000000000..6b7e8fa2e
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/algernon/readme.md
@@ -0,0 +1,230 @@
+algernon's layout
+=======================
+
+This is an unconventional layout for the ErgoDox EZ. For more details about the
+history of the layout, see my
+[blog posts about my ErgoDox journey][blog-ergodox].
+
+ [blog-ergodox]: https://asylum.madhouse-project.org/blog/tags/ergodox/
+
+Some of the things in the layout only work when one uses Spacemacs and GNOME
+under Linux. Your mileage may vary.
+
+## Table of Contents
+
+* [Layouts](#layouts)
+ - [Base layer](#base-layer)
+ - [Experimental layer](#experimental-layer)
+ - [Hungarian layer](#hungarian-layer)
+ - [Navigation and media layer](#navigation-and-media-layer)
+ - [One-handed layer](#one-handed-layer)
+ - [Steno layer](#steno-layer)
+ - [LED states](#led-states)
+* [Building](#building)
+ - [Using on Windows](#using-on-windows)
+* [Changelog](#changelog)
+* [License](#license)
+
+# Layouts
+
+## Base layer
+
+[![Base layer](images/base-layer.png)](http://www.keyboard-layout-editor.com/#/gists/28f7eb305fdbff943613e1dc7aa9e82b)
+
+At its core, this is a Dvorak layout, with some minor changes. The more
+interesting parts are how certain keys behave:
+
+* The keys on the number row double as function keys, when held for a bit longer
+ than an usual tap. This allows me to use the function keys without having to
+ switch layers.
+* The `Shift`, `Alt`, and `Control` modifiers are one-shot. When tapped, they
+ are considered active for the next key press only. When double tapped, they
+ toggle on, until a third, single tap sometime later. When held, they act as
+ expected. My usual pattern is that I use these for the next keypress only, so
+ this behaviour is perfect. If I need them held, I'll just double-tap.
+* The `GUI` key is special, because when I double-tap it, it sends `GUI + w`,
+ which pops up an application selector. It also switches to a one-shot layer,
+ where the number row on the left half turns into app selector macros, for the
+ most common things I usually want to switch to. Otherwise it behaves as on a
+ normal layout.
+* The `ESC` key also doubles as a one-shot cancel key: if tapped while any of
+ the one-shot modifiers are in-flight (as in, single-tapped, and not expired
+ yet), it cancels all one-shot modifiers. It also cancels the **Hun** layer, if
+ active. Otherwise it sends the usual keycode.
+* The **Media**, **Arrow**, and **Hun** layer keys are one-shot, the **1Hand**
+ and **STENO** keys are toggles.
+* Toggling the **Arrow** layer toggles between the cursor arrows and the paging
+ keys on the bottom row.
+* Tapping the `:` key once yields `:`, tapping it twice yields `;`.
+* The **Lead** key allows me to type in a sequence of keys, and trigger some
+ actions:
+ - `LEAD u` enters unicode input mode, by sending the GTK+ key sequence that
+ does this.
+ - `LEAD l` uses the unicode input method to enter a `λ`.
+ - `LEAD s` does a lot of magic to type in a shruggie: `¯\_(ツ)_/¯`
+ - `LEAD y` types `\o/`.
+ - `LEAD w m` maximises the currently focused window.
+ - `LEAD e` makes the [experimental layer](#experimental-layer) the default.
+ - `LEAD v` prints the firmware version, the keyboard and the keymap.
+
+## Experimental layer
+
+[![Experimental layer](images/experimental-layer.png)](http://www.keyboard-layout-editor.com/#/gists/6ff50bf71248e05aab5b3fec4fae3d08)
+
+While using the standard Dvorak layout, I encountered a number of
+inconveniences, and on this layer, I am playing with ideas to make the layout
+feel better. Initially, it was based on [Capewell-Dvorak][cpd], but that too,
+had shortcomings I was not happy with. So now this is something inbetween, with
+own observations thrown in. How it works out in the long run remains to be seen.
+
+ [cpd]: http://www.michaelcapewell.com/projects/keyboard/layout_capewell-dvorak.htm
+
+## Hungarian layer
+
+[![Hungarian layer](images/hun-layer.png)](http://www.keyboard-layout-editor.com/#/gists/b160f6ec90d58c127c114c89f66e9dc9)
+
+On this layer, the accented characters are at the same position as their base
+variant. For some, which can have other diatribes, the long one is on top,
+short's on bottom. Tapping any of the accented characters takes us back to the
+base layer.
+
+## Navigation and media layer
+
+[![Navigation and media layer](images/nav-n-media-layer.png)](http://www.keyboard-layout-editor.com/#/gists/c59c453f9fe1a3238ba1494e7e5c6892)
+
+This layer is primarily for navigating with the cursor or the mouse, and some
+media things.
+
+## One-handed layer
+
+[![One-handed layer](images/one-handed-layer.png)](http://www.keyboard-layout-editor.com/#/gists/edff2495135955b8963198dace7f7ece)
+
+The one-handed layer is used in situations where the right hand is occupied, by
+mousing around, for example. Tapping the `OTHER` key switches which side is
+active. For the most part, keys remain in their usual position. When the right
+half is active, keys are mirrored to the left half.
+
+The differences are as follows:
+
+* The `ESC` key has been moved to the bottom row, so the `OTHER` key is easier
+ to tap.
+* Most keys on the thumb cluster now have dual uses, and these do not change
+ when switching sides:
+ - The `Space`/`Backspace` key sends `Space` on tap, `Backspace` when held
+ for longer than a normal tap.
+ - The `Enter`/`Shift` key sends `Enter` on short-tap, `Shift` on long-tap.
+* The `Apps`/`BASE` key can be used to go back to the base layer, by
+ long-tapping it. A short-tap will send the `App` key, as usual.
+
+## Steno layer
+
+[![Steno layer for Plover](images/steno-layer.png)](http://www.keyboard-layout-editor.com/#/gists/401ef9a84369e47c57f9aedcf0a0d667)
+
+This is to be used with [Plover](http://www.openstenoproject.org/plover/),
+nothing really fancy here. The **STENO** key toggles the layer on and off, and
+sends the toggle command to Plover too.
+
+## LED states
+
+The primary purpose of the LEDs is to show the modifier status, a secondary, to
+show which layer is active. Each modifier, `Shift`, `Alt` and `Control` each
+have their designated LEDs: the *red*, *green* and *blue*, respectively. When a
+modifier is in a one-shot state, the respective LED will turn on with a dimmer
+light. If the modifier is toggled on, the brightness of the LED turns full.
+
+For the layers, the following rules apply:
+
+* When the [Experimental layer](#experimental-layer) is toggled on, LEDs will
+ light up from left to right in a sequence, then turn off. When the layer is
+ toggled off, the LEDs light up and turn off in the other direction. No LEDs
+ are on while the layer is active.
+* When the [Hungarian layer](#hungarian-layer) is active, the *green* and *blue*
+ LEDs are on.
+* When the [Navigation and media layer](#navigation-and-media-layer) is active,
+ the *red* and *green* ones are on.
+* When the [One-handed layer](#one-handed-layer) is active, the *green* LED is
+ on and bright, and either the *red* or the *blue* one is going to slowly
+ blink, depending on the currently active side.
+* For the [Steno layer](#steno-layer), all LEDs will be turned on.
+
+Unless noted otherwise, the layers use a dim light for the LEDs, while modifiers
+use a stronger one, and modifiers override any layer preferences. For example,
+when on the one-handed layer, with the left side active (*red* light blinking),
+if `Shift` is on, the *red* light will be constantly on.
+
+# Building
+
+To make my workflow easier, this layout is maintained in
+[its own repository][algernon:ez-layout]. To build it, you will need the
+[QMK][qmk] firmware checked out, and this repo either checked out to something
+like `keyboards/ergodox_ez/algernon-master`. One way to achieve that is this:
+
+ [algernon:ez-layout]: https://github.com/algernon/ergodox-layout
+ [qmk]: https://github.com/jackhumbert/qmk_firmware
+
+```
+$ git clone https://github.com/jackhumbert/qmk_firmware.git
+$ cd qmk_firmware
+$ git clone https://github.com/algernon/ergodox-layout.git \
+ keyboards/ergodox_ez/keymaps/algernon-master
+$ make KEYBOARD=ergodox_ez KEYMAP=algernon-master
+```
+
+From time to time, updates may be submitted back to the QMK repository. If you
+are reading it there, you can build the firmware like any other firmware
+included with it (assuming you are in the root directory of the firmware):
+
+```
+$ make KEYBOARD=ergodox_ez KEYMAP=algernon
+```
+
+## Using on Windows
+
+The keymap default to forcing NKRO, which seems to upset Windows, and except the
+modifiers, none of them work. If you experience this problem, recompile the
+firmware with `FORCE_NKRO=no` added to the `make` command line.
+
+# Changelog
+
+## v1.2 - 2016-06-22
+
+* The forced NKRO mode can be easily toggled off at compile-time, to make the
+ firmware compatible with [certain operating systems](#using-on-windows).
+* The `:;` key has changed behaviour: to access the `;` symbol, the key needs to
+ be double-tapped, instead of shifted.
+* The `=` and `\` keys were swapped, `=` moved to the home row, on both the
+ [base](#base-layer) and the [experimental](#experimental-layer) layers.
+* The arrow and navigation keys were redone, they are now more accessible, but
+ the navigation keys require an extra tap to access.
+* The **Emacs** layer is gone, replaced by a simplified
+ [navigation and media](#navigation-and-media-layer) layer.
+* `LEAD v` types the firmware version, and the keymap version.
+* On the [experimental](#experimental-layer) layer, the `L` and `Q`, and the `K`
+ and `G` keys were swapped.
+* The [Steno](#steno-layer) layer gained a few more `#` and `*` keys, to make it
+ easier on my fingers.
+
+## v1.1 - 2016-06-14
+
+* The keyboard starts in NKRO mode, bootmagic and other things are disabled.
+* A [Steno](#steno-layer) layer was added, to be used with Plover.
+* An [experimental](#experimental-layer) layer was added, something halfway
+ between Dvorak and Capewell-Dvorak. A work in progress.
+* `LEAD y` types `\o/`.
+* Some keys on the [Base](#base-layer) layer have been moved around:
+ - `?` moved to the left pinky, left of `Q`.
+ - `=` shifted one row down, but `F11` stayed where it was.
+ - `-` on the left half was replaced by `Tab`.
+ - `Tab`'s original position is taken by a `Media Next`/`Media Prev` key.
+ - `:` now inputs `;` when shifted.
+* `ESC` cancels the [Hungarian](#hungarian-layer) layer too, not just modifiers.
+
+## v1.0 - 2016-05-26
+
+Initial version.
+
+# License
+
+The layout, being a derivative of the original TMK firmware which is under the
+GPL-2+, this layout is under the GPL as well, but GPL-3+, rather than the older
+version.
diff --git a/keyboards/ergodox_ez/keymaps/algernon/tools/max-focused b/keyboards/ergodox_ez/keymaps/algernon/tools/max-focused
new file mode 100755
index 000000000..4d5220aa8
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/algernon/tools/max-focused
@@ -0,0 +1,5 @@
+#! /bin/sh
+WIN="$(xdotool getactivewindow)"
+wmctrl -i -r ${WIN} -b remove,maximized_vert,maximized_horz
+xdotool windowsize ${WIN} 100% 100%
+wmctrl -i -r ${WIN} -b add,maximized_vert,maximized_horz
diff --git a/keyboards/ergodox_ez/keymaps/andrew_osx/keymap.c b/keyboards/ergodox_ez/keymaps/andrew_osx/keymap.c
new file mode 100644
index 000000000..48257d23a
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/andrew_osx/keymap.c
@@ -0,0 +1,187 @@
+// Netable differences vs. the default firmware for the ErgoDox EZ:
+// 1. The Cmd key is now on the right side, making Cmd+Space easier.
+// 2. The media keys work on OSX (But not on Windows).
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define BASE 0 // default layer
+#define SYMB 1 // symbols
+#define MDIA 2 // media keys
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | = | 1 | 2 | 3 | 4 | 5 | '" | | '" | 6 | 7 | 8 | 9 | 0 | BkSp |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Tab | Q | W | E | R | T | ~L1 | | ~L1 | Y | U | I | O | P | - |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * |Ctrl/Esc| A | S | D | F | G |------| |------| H | J | K | L |; / L2| / |
+ * |--------+------+------+------+------+------| Hyper| | Meh |------+------+------+------+------+--------|
+ * | LShift |Z/Ctrl| X | C | V | B | | | | N | M | , | . |//Ctrl| RShift |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * |Grv/L1| Alt |AltShf| Left | Right| | Up | Down | [ | ] | L1 |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | App | LGui | | Esc |Ctrl/Esc|
+ * ,------|------|------| |------+--------+------.
+ * | | | ( | | { | | |
+ * | Space| LGui |------| |------| RGui |Enter |
+ * | | | ) | | } | | |
+ * `--------------------' `----------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_EQL, KC_1, KC_2, KC_3, KC_4, KC_5, KC_QUOT,
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_FN1,
+ CTL_T(KC_ESC), KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_LSFT, CTL_T(KC_Z), KC_X, KC_C, KC_V, KC_B, ALL_T(KC_NO),
+ LT(SYMB,KC_GRV),KC_LALT, LALT(KC_LSFT), KC_LEFT,KC_RGHT,
+ ALT_T(KC_APP), KC_LGUI,
+ KC_LPRN,
+ KC_SPC,KC_LGUI,KC_RPRN,
+ // right hand
+ KC_QUOT, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC,
+ KC_FN1, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_MINS,
+ KC_H, KC_J, KC_K, KC_L, LT(MDIA, KC_SCLN),KC_BSLS,
+ MEH_T(KC_NO),KC_N, KC_M, KC_COMM,KC_DOT, CTL_T(KC_SLSH), KC_RSFT,
+ KC_UP, KC_DOWN,KC_LBRC,KC_RBRC, TG(1),
+ KC_ESC, CTL_T(KC_ESC),
+ KC_LCBR,
+ KC_RCBR,KC_RGUI, KC_ENT
+ ),
+/* Keymap 1: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | . | 0 | = | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[SYMB] = KEYMAP(
+ // left hand
+ KC_TRNS,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS,KC_EXLM,KC_AT, KC_LCBR,KC_RCBR,KC_PIPE,KC_TRNS,
+ KC_TRNS,KC_HASH,KC_DLR, KC_LPRN,KC_RPRN,KC_GRV,
+ KC_TRNS,KC_PERC,KC_CIRC,KC_LBRC,KC_RBRC,KC_TILD,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_UP, KC_7, KC_8, KC_9, KC_ASTR, KC_F12,
+ KC_DOWN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS,
+ KC_TRNS, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS, KC_TRNS,
+ KC_TRNS,KC_DOT, KC_0, KC_EQL, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/* Keymap 2: Media and mouse keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | MsUp | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | |MsLeft|MsDown|MsRght| |------| |------| | | | | | Play |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | | | | Prev | Next | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | Lclk | Rclk | |VolUp |VolDn | Mute | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | |Brwser|
+ * | | |------| |------| |Back |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// MEDIA AND MOUSE
+KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MPRV, KC_MNXT, KC_TRNS, KC_TRNS,
+ KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_WBAK
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(SYMB) // FN1 - Momentary Layer 1 (Symbols)
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case 1:
+ ergodox_right_led_1_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/bepo/bepo.png b/keyboards/ergodox_ez/keymaps/bepo/bepo.png
new file mode 100644
index 000000000..3df7aa609
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/bepo/bepo.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/bepo/keymap.c b/keyboards/ergodox_ez/keymaps/bepo/keymap.c
new file mode 100644
index 000000000..921a94d63
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/bepo/keymap.c
@@ -0,0 +1,311 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+#include "keymap_bepo.h"
+
+#define BASE 0 // default layer
+#define QWER 1 // qwerty compat layer
+#define SQWER 2 // shifted qwerty compat layer
+#define AQWER 3 // alted qwerty compat layer
+#define FNAV 4 // function / navigation keys
+#define NUM 5 // numeric keypad keys
+#define MSE 6 // mouse keys
+
+#define KP_00 0
+#define CA_Fx 1
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Base layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | $ | " | < | > | ( | ) |Delete| |ScroLo| @ | + | - | / | * | = |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | % | B |E_ACUT| P | O |E_GRAV|Backsp| |CapsLo| ^ | V | D | L | J | Z |
+ * |--------+------+------+------+------+------| ace | | |------+------+------+------+------+--------|
+ * | W | A | U | I | E | , |------| |------| C | T | S | R | N | M |
+ * |--------+------+------+------+------+------| Tab | | NumLo|------+------+------+------+------+--------|
+ * | E_CIRC |A_GRAV| Y | X | . | K | | | | ' | Q | G | H | F | C_CEDIL|
+ * `--------+------+------+------+------+-------------,-------------. ,-------------`-------------+------+------+------+------+--------'
+ * |QWERTY| |LSuper| LCtrl| LAlt| |Escape| L_Mse| | |Insert| | AltGr| RCtrl|RSuper|PrntSc| Pause|
+ * `----------------------------------' ,------|------|------| |------+------+------. `----------------------------------'
+ * | | | L_Num| | CA_Fx| | |
+ * | Space|LShift|------| |------|RShift|Enter |
+ * | | |L_FNav| |L_FNav| | |
+ * `--------------------' `--------------------'
+ */
+[BASE] = KEYMAP(
+// Left hand
+BP_DOLLAR, BP_DQOT, BP_LGIL, BP_RGIL, BP_LPRN, BP_RPRN, KC_DEL,
+BP_PERCENT, BP_B, BP_E_ACUTE, BP_P, BP_O, BP_E_GRAVE, KC_BSPC,
+BP_W, BP_A, BP_U, BP_I, BP_E, BP_COMMA,
+BP_ECRC, BP_A_GRAVE, BP_Y, BP_X, BP_DOT, BP_K, KC_TAB,
+TG(QWER), KC_NO, KC_LGUI, KC_LCTL, KC_LALT,
+ KC_ESC, MO(MSE),
+ MO(NUM),
+ KC_SPC, KC_LSHIFT, MO(FNAV),
+// Right hand
+ KC_SLCK, BP_AT, BP_PLUS, BP_MINUS, BP_SLASH, BP_ASTR, BP_EQUAL,
+ KC_CAPSLOCK, BP_DCRC, BP_V, BP_D, BP_L, BP_J, BP_Z,
+ BP_C, BP_T, BP_S, BP_R, BP_N, BP_M,
+ KC_NUMLOCK, BP_APOS, BP_Q, BP_G, BP_H, BP_F, BP_CCED,
+ BP_ALGR, KC_RCTL, KC_RGUI, KC_PSCREEN, KC_PAUSE,
+KC_NO, KC_INS,
+M(CA_Fx),
+MO(FNAV), KC_RSHIFT, KC_ENTER),
+/* Keymap 1: QWERTY system compatibility layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | $ | " | < | > | ( | ) |Delete| |ScroLo| @ | + | - | / | * | = |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | % | b | e | p | o | e |Backsp| |CapsLo| ^ | v | d | l | j | z |
+ * |--------+------+------+------+------+------| ace | | |------+------+------+------+------+--------|
+ * | w | a | u | i | e | , |------| |------| c | t | s | r | n | m |
+ * |--------+------+------+------+------+------| Tab | | NumLo|------+------+------+------+------+--------|
+ * | e | a | y | x | . | k | | | | ' | q | g | h | f | c |
+ * `--------+------+------+------+------+-------------,-------------. ,-------------`-------------+------+------+------+------+--------'
+ * | BEPO | |LSuper| LCtrl| LAlt| |Escape| L_Mse| | |Insert| | AltGr| RCtrl|RSuper|PrntSc| Pause|
+ * `----------------------------------' ,------|------|------| |------+------+------. `----------------------------------'
+ * | | | L_Num| | | | |
+ * | Space|LShift|------| |------|RShift|Enter |
+ * | | |L_FNav| |L_FNav| | |
+ * `--------------------' `--------------------'
+ */
+[QWER] = KEYMAP(
+// Left hand
+KC_DOLLAR, S(KC_QUOT), S(KC_COMM), S(KC_DOT), KC_LPRN, KC_RPRN, KC_DEL,
+KC_PERCENT, KC_B, KC_E, KC_P, KC_O, KC_E, KC_BSPC,
+KC_W, KC_A, KC_U, KC_I, KC_E, KC_COMMA,
+KC_E, KC_A, KC_Y, KC_X, KC_DOT, KC_K, KC_TAB,
+KC_TRNS, KC_NO, KC_LGUI, KC_LCTL, KC_LALT,
+ KC_ESC, MO(MSE),
+ MO(NUM),
+ KC_SPC, MO(SQWER), MO(FNAV),
+// Right hand
+ KC_SLCK, KC_AT, KC_PLUS, KC_MINUS, KC_SLASH, KC_ASTR, KC_EQUAL,
+ KC_CAPSLOCK, KC_CIRC, KC_V, KC_D, KC_L, KC_J, KC_Z,
+ KC_C, KC_T, KC_S, KC_R, KC_N, KC_M,
+ KC_NUMLOCK, KC_QUOT, KC_Q, KC_G, KC_H, KC_F, KC_C,
+ MO(AQWER), KC_RCTL, KC_RGUI, KC_PSCREEN, KC_PAUSE,
+KC_NO, KC_INS,
+KC_TRNS,
+MO(FNAV), MO(SQWER), KC_ENTER),
+/* Keymap 2: QWERTY shifted system compatibility layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | # | 1 | 2 | 3 | 4 | 5 |Delete| |ScroLo| 6 | 7 | 8 | 9 | 0 | = |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | ` | B | E | P | O | E |Backsp| |CapsLo| ! | V | D | L | J | Z |
+ * |--------+------+------+------+------+------| ace | | |------+------+------+------+------+--------|
+ * | W | A | U | I | E | ; |------| |------| C | T | S | R | N | M |
+ * |--------+------+------+------+------+------| Tab | | NumLo|------+------+------+------+------+--------|
+ * | E | A | Y | X | : | K | | | | ? | Q | G | H | F | C |
+ * `--------+------+------+------+------+-------------,-------------. ,-------------`-------------+------+------+------+------+--------'
+ * | BEPO | |LSuper| LCtrl| LAlt| |Escape| L_Mse| | |Insert| | AltGr| RCtrl|RSuper|PrntSc| Pause|
+ * `----------------------------------' ,------|------|------| |------+------+------. `----------------------------------'
+ * | | | L_Num| | | | |
+ * | Space|LShift|------| |------|RShift|Enter |
+ * | | |L_FNav| |L_FNav| | |
+ * `--------------------' `--------------------'
+ */
+[SQWER] = KEYMAP(
+// Left hand
+KC_HASH, KC_1, KC_2, KC_3, KC_4, KC_5, KC_TRNS,
+KC_GRV, S(KC_B), S(KC_E), S(KC_P), S(KC_O), S(KC_E), KC_TRNS,
+S(KC_W), S(KC_A), S(KC_U), S(KC_I), S(KC_E), KC_SCOLON,
+S(KC_E), S(KC_A), S(KC_Y), S(KC_X), KC_COLON, S(KC_K), S(KC_TAB),
+KC_TRNS, KC_TRNS, S(KC_LGUI), S(KC_LCTL), S(KC_LALT),
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+// Right hand
+ KC_TRNS, KC_6, KC_7, KC_8, KC_9, KC_0, KC_TRNS,
+ KC_TRNS, KC_EXLM, S(KC_V), S(KC_D), S(KC_L), S(KC_J), S(KC_Z),
+ S(KC_C), S(KC_T), S(KC_S), S(KC_R), S(KC_N), S(KC_M),
+ KC_TRNS, S(KC_SLASH), S(KC_Q), S(KC_G), S(KC_H), S(KC_F), S(KC_C),
+ S(KC_RALT), S(KC_RCTL), S(KC_RGUI), KC_TRNS, KC_TRNS,
+KC_TRNS, KC_TRNS,
+KC_TRNS,
+KC_TRNS, KC_TRNS, KC_TRNS),
+/* Keymap 3: QWERTY alted system compatibility layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | $ | " | < | > | [ | ] |Delete| |ScroLo| @ | + | - | / | * | = |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | % | | | e | & | o | e |Backsp| |CapsLo| ^ | v | d | l | j | z |
+ * |--------+------+------+------+------+------| ace | | |------+------+------+------+------+--------|
+ * | w | a | u | i | € | , |------| |------| c | t | s | r | n | m |
+ * |--------+------+------+------+------+------| Tab | | NumLo|------+------+------+------+------+--------|
+ * | e | \ | { | } | . | ~ | | | | ' | q | g | h | f | c |
+ * `--------+------+------+------+------+-------------,-------------. ,-------------`-------------+------+------+------+------+--------'
+ * | BEPO | |LSuper| LCtrl| LAlt| |Escape| L_Mse| | |Insert| | AltGr| RCtrl|RSuper|PrntSc| Pause|
+ * `----------------------------------' ,------|------|------| |------+------+------. `----------------------------------'
+ * | | | L_Num| | | | |
+ * | _ |LShift|------| |------|RShift|Enter |
+ * | | |L_FNav| |L_FNav| | |
+ * `--------------------' `--------------------'
+ */
+[AQWER] = KEYMAP(
+// Left hand
+KC_DOLLAR, S(KC_QUOT), S(KC_COMM), S(KC_DOT), KC_LBRC, KC_RBRC, KC_DEL,
+KC_PERCENT, KC_PIPE, KC_E, KC_AMPR, KC_O, KC_E, KC_BSPC,
+KC_W, KC_A, KC_U, KC_I, RALT(KC_5), KC_COMMA,
+KC_E, KC_BSLASH, KC_LCBR, KC_RCBR, KC_DOT, KC_TILDE, KC_TAB,
+KC_TRNS, KC_NO, KC_LGUI, KC_LCTL, KC_LALT,
+ KC_ESC, MO(MSE),
+ MO(NUM),
+ KC_UNDS, MO(SQWER), MO(FNAV),
+// Right hand
+ KC_SLCK, KC_AT, KC_PLUS, KC_MINUS, KC_SLASH, KC_ASTR, KC_EQUAL,
+ KC_CAPSLOCK, KC_CIRC, KC_V, KC_D, KC_L, KC_J, KC_Z,
+ KC_C, KC_T, KC_S, KC_R, KC_N, KC_M,
+ KC_NUMLOCK, KC_QUOT, KC_Q, KC_G, KC_H, KC_F, KC_C,
+ KC_TRNS, KC_RCTL, KC_RGUI, KC_PSCREEN, KC_PAUSE,
+KC_NO, KC_INS,
+KC_TRNS,
+MO(FNAV), MO(SQWER), KC_ENTER),
+/* Keymap 4: function / navigation layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 |VolMut| | | F6 | F7 | F8 | F9 | F10 | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | | | |VolDwn| | | PgUp | Home | Up | End | F11 | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | |------| |------| PgDn | Left | Down | Right| F12 | |
+ * |--------+------+------+------+------+------| VolUp| | |------+------+------+------+------+--------|
+ * | | Undo | Cut | Copy | Paste| | | | | | | | | | |
+ * `--------+------+------+------+------+-------------,-------------. ,-------------`-------------+------+------+------+------+--------'
+ * | | | | | | | | | | | | | | | | | |
+ * `----------------------------------' ,------|------|------| |------+------+------. `----------------------------------'
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+[FNAV] = KEYMAP(
+// Left hand
+KC_NO, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_MUTE,
+KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_VOLU,
+KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+KC_NO, KC_UNDO, KC_CUT, KC_COPY, KC_PASTE, KC_NO, KC_VOLD,
+KC_NO, KC_NO, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_NO, KC_NO,
+ KC_NO,
+ KC_NO, KC_TRNS, KC_TRNS,
+// Right hand
+ KC_NO, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_NO,
+ KC_NO, KC_PGUP, KC_HOME, KC_UP, KC_END, KC_F11, KC_NO,
+ KC_PGDOWN, KC_LEFT, KC_DOWN, KC_RIGHT, KC_F12, KC_NO,
+ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_NO, KC_NO,
+KC_NO, KC_NO,
+KC_TRNS,
+KC_TRNS, KC_TRNS, KC_NO),
+/* Keymap 5: numeric layer, sends keypad codes
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | + | - | / | * | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | | | | | | | | 7 | 8 | 9 | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | |------| |------| | 4 | 5 | 6 | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | | | 1 | 2 | 3 | | |
+ * `--------+------+------+------+------+-------------,-------------. ,-------------`-------------+------+------+------+------+--------'
+ * | | | | | | | | | | | | | 0 | 00 | . | | |
+ * `----------------------------------' ,------|------|------| |------+------+------. `----------------------------------'
+ * | | | | | | | |
+ * | | |------| |------| | Enter|
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+[NUM] = KEYMAP(
+// Left hand
+KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+KC_NO, KC_NO, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_NO, KC_NO,
+ KC_TRNS,
+ KC_NO, KC_TRNS, KC_NO,
+// Right hand
+ KC_NO, KC_NO, KC_KP_PLUS, KC_KP_MINUS, KC_KP_SLASH, KC_KP_ASTERISK, KC_NO,
+ KC_NO, KC_NO, KC_KP_7, KC_KP_8, KC_KP_9, KC_NO, KC_NO,
+ KC_NO, KC_KP_4, KC_KP_5, KC_KP_6, KC_NO, KC_NO,
+ KC_NO, KC_NO, KC_KP_1, KC_KP_2, KC_KP_3, KC_NO, KC_NO,
+ KC_KP_0, M(KP_00), KC_KP_COMMA, KC_NO, KC_NO,
+KC_NO, KC_NO,
+KC_NO,
+KC_NO, KC_TRNS, KC_KP_ENTER),
+/* Keymap 6: mouse layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | | | | | | | |LClick| Up |RClick| WhUp | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | |------| |------| | Left | Down | Right|WhDown| |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | | | | | | | |
+ * `--------+------+------+------+------+-------------,-------------. ,-------------`-------------+------+------+------+------+--------'
+ * | | | | | | | | | | | | | | | | | |
+ * `----------------------------------' ,------|------|------| |------+------+------. `----------------------------------'
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+[MSE] = KEYMAP(
+// Left hand
+KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+KC_NO, KC_NO, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_NO, KC_TRNS,
+ KC_NO,
+ KC_NO, KC_TRNS, KC_NO,
+// Right hand
+ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+ KC_NO, KC_NO, KC_MS_BTN1, KC_MS_UP, KC_MS_BTN2, KC_MS_WH_UP, KC_NO,
+ KC_NO, KC_MS_LEFT, KC_MS_DOWN, KC_MS_RIGHT, KC_MS_WH_DOWN, KC_NO,
+ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_NO, KC_NO,
+KC_NO, KC_NO,
+KC_NO,
+KC_NO, KC_TRNS, KC_NO)
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ switch(id) {
+ case KP_00:
+ if (record->event.pressed) {
+ return MACRO( T(KP_0), D(KP_0), END );
+ } else {
+ return MACRO( U(KP_0), END );
+ }
+ break;
+ case CA_Fx:
+ if (record->event.pressed) {
+ layer_on(FNAV);
+ return MACRO( D(LALT), D(LCTL), END );
+ } else {
+ layer_off(FNAV);
+ return MACRO( U(LCTL), U(LALT), END );
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+};
diff --git a/keyboards/ergodox_ez/keymaps/bepo/readme.md b/keyboards/ergodox_ez/keymaps/bepo/readme.md
new file mode 100644
index 000000000..4a18cd80f
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/bepo/readme.md
@@ -0,0 +1,34 @@
+# BEPO keymap for the ErgoDox
+
+This keymap has been made for the BEPO layout (http://bepo.fr), which is an ergonomic french keyboard layout based on Dvorak rules. As it's made for french people, the following of this readme will be in french.
+
+# Disposition BÉPO pour l'ErgoDox
+
+Cette keymap a été pensée pour la disposition BÉPO (http://bepo.fr), qui est une disposition de clavier francophone, ergonomique et libre, élaborée selon la méthode Dvorak. L'adaptation de cette disposition à l'ErgoDox a été réalisée en conservant les points forts du clavier TypeMatrix 2030 (très répandu dans la communauté bépo, avec un excellent rapport ergonomie / prix) voir en réglant certains de ses défauts (3 colonnes pour l'auriculaire droit et touche "Ê") et en apportant son lot de nouveautés (compatibilité avec les systèmes azerty et qwerty).
+
+Particularités
+--------------
+
+Touches de repos des pouces : "espace" à gauche et "entrée" à droite.
+
+Placement des touches de combinaison ("Shift", "Alt", "Ctrl"...) adapté aux pouces, et permettant de conserver chaque doigt pour les rangées de lettres auxquelles ils sont assignés sans avoir à changer la touche de combinaison de côté (exemple : "A" majuscule puis "M" majuscule avec les auriculaires et un seul appui d'une touche "Shift").
+
+Les touches "Alt" et "Alt Gr" sont accessibles avec les pouces sur la rangée du bas comme sur la TypeMatrix 2030, avec une symétrie gauche / droite.
+
+Les touches "Ctrl" sont placées sur la même ligne que les touche "Alt" et "Alt Gr" comme sur un clavier clasique, elles sont accessibles aux pouces sur la rangée du bas (moins éloigné que le groupe de touches de pouces pour des petites mains).
+
+Les touches "Backspace" et "Delete" sont placées comme sur la TypeMatrix 2030, du côté gauche uniquement (pour laisser celles de la main droite servir de {caps,num,scroll}lock puisqu'elles ont des LED).
+
+La touche "Tab" est placée comme sur la TypeMatrix 2020.
+
+Meilleure symétrie et accessibilité que la TypeMatrix 2030 : les touches "W" et "%" ont dû être déplacées du côté gauche en raison du nombre de touches de l'ErgoDox, mais l'auriculaire droit ne gère maintenant que deux colonnes de touches au lieu de trois. La touche "Ê" redevient accessible sur la même rangée que les autres lettres, comme sur un clavier classique en disposition bépo. Les lettres, chiffres et symboles sont tous regroupés sur 4 lignes et 6 colonnes pour chaque main, et la première rangée de lettres à la main gauche conserve une identité visuelle "BÉPO".
+
+Touche de fonction permettant de saisir les touches F1 à F12, les touches F1 à F10 sont placées de façon logique par rapport aux chiffres 1 à 0. Cette même touche permet l'accès aux touches directionnelles sans déplacer la main droite. Les touches "Home" et "End" sont placées de la même façon que sur une TypeMatrix 2030 par rapport aux touches directionnelles. Les touches "Page Up" et "Page Down" sont également accessibles facilement sans déplacer la main droite. Les fonctions "VolUp" et "VolDown" sont placées comme sur la TypeMatrix 2030, avec la fonction "Mute" juste au dessus. Les fonctions "Undo", "Cut", "Copy" et "Paste" sont placées côte à côte comme elles le seraient sur un clavier QWERTY en combinaison avec la touche "Ctrl" (à l'emplacement des lettres "Z", "X", "C" et "V"). Par rapport au layout "SpaceFN", l'utilisation d'une touche de fonction dédiée au pouce permet de ne pas ajouter de latence, et la touche espace reste compatible avec les jeux (action au moment de l'appui et possibilité d'appui long).
+
+Touche de fonction permettant l'accès au pavé numérique comme sur la TypeMatrix 2030, mais sans avoir à déplacer la main droite : avec les doigts sur la rangée de repos, possibilité de saisir les chiffres "4", "5" et "6" comme sur un pavé numérique classique. Le double "0" de la TypeMatrix a été conservé, et gagne une possibilité de répétition en simples "0".
+
+L'appui sur une touche permet de basculer en mode BEPO sur un système configuré pour un clavier QWERTY. Cette compatibilité n'est pas parfaite (pas encore de gestion des accents mais ça devrait être faisable avec une disposition en qwerty international, et les combinaisons de touches ne sont pas toutes supportées puisque le clavier traduit déjà certaines touches en combinaisons) mais reste pratique pour une saisie de texte occasionnelle.
+
+TODO : couche de compatibilité pour utiliser la disposition BÉPO sur un système configuré pour un clavier AZERTY.
+
+> Olivier Smedts <olivier@gid0.org>
diff --git a/keyboards/ergodox_ez/keymaps/coderkun_neo2/Makefile b/keyboards/ergodox_ez/keymaps/coderkun_neo2/Makefile
new file mode 100644
index 000000000..e7b2d0a65
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/coderkun_neo2/Makefile
@@ -0,0 +1 @@
+UNICODE_ENABLE = yes \ No newline at end of file
diff --git a/keyboards/ergodox_ez/keymaps/coderkun_neo2/keymap.c b/keyboards/ergodox_ez/keymaps/coderkun_neo2/keymap.c
new file mode 100644
index 000000000..d25e2b995
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/coderkun_neo2/keymap.c
@@ -0,0 +1,274 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+#include "keymap_neo2.h"
+
+// Layer names
+#define BASE 0 // default layer
+#define PMQ 1 // poor man’s QWERTZ
+#define PMN 2 // poor man’s Neo
+#define FMU 3 // FMU layer
+#define NHL 4 // Neo’s software layer 4 rebuilt in Hardware
+
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Layer 0: default
+ * ┌───────┬─────┬─────┬─────┬─────┬─────┬─────┐ ┌─────┬─────┬─────┬─────┬─────┬─────┬───────┐
+ * │ TAB │ 1 │ 2 │ 3 │ 4 │ 5 │ ` │ │ ´ │ 6 │ 7 │ 8 │ 9 │ 0 │ BKSPC │
+ * ├───────┼─────┼─────┼─────┼─────┼─────┼─────┤ ├─────┼─────┼─────┼─────┼─────┼─────┼───────┤
+ * │ Y │ X │ V │ L │ C │ W │ HOM │ │ END │ K │ H │ G │ F │ Q │ ß │
+ * ├───────┼─────┼─────┼─────╆─────╅─────┤ E │ │ ├─────╆─────╅─────┼─────┼─────┼───────┤
+ * │ Mod3 │ U │ I │ A │ E │ O ├─────┤ ├─────┤ S │ N │ R │ T │ D │ Mod3 │
+ * ├───────┼─────┼─────┼─────╄─────╃─────┤ TL2 │ │ TL3 ├─────╄─────╃─────┼─────┼─────┼───────┤
+ * │ LSHFT │ Ü │ Ö │ Ä │ P │ Z │ │ │ │ B │ M │ , │ . │ J │ Shift │
+ * └─┬─────┼─────┼─────┼─────┼─────┼─────┴─────┘ └─────┴─────┼─────┼─────┼─────┼─────┼─────┬─┘
+ * │ CTL │ ALT │ MO1 │ Win │ Mod4│ │ Mod4│ Win │ MO1 │ Alt │ CTL │
+ * └─────┴─────┴─────┴─────┴─────┘ ┌─────┬─────┐ ┌─────┬─────┐ └─────┴─────┴─────┴─────┴─────┘
+ * │ ← │ ↑ │ │ ↓ │ → │
+ * ┌─────┼─────┼─────┤ ├─────┼─────┼─────┐
+ * │ │ │ ─ │ │ ─ │ │ │
+ * │ SPC │ RTN ├─────┤ ├─────┤ RTN │ SPC │
+ * │ │ │ HYP │ │ MEH │ │ │
+ * └─────┴─────┴─────┘ └─────┴─────┴─────┘
+ */
+[BASE] = KEYMAP(
+ // left hand
+ KC_TAB, KC_1, KC_2, KC_3, KC_4, KC_5, KC_EQL,
+ NEO_Y, NEO_X, NEO_V, NEO_L, NEO_C, NEO_W, KC_HOME,
+ NEO_L1_L, NEO_U, NEO_I, NEO_A, NEO_E, NEO_O,
+ KC_LSFT, NEO_UE, NEO_OE, NEO_AE, NEO_P, NEO_Z, TG(PMQ),
+ KC_LCTL, KC_LALT,MO(FMU),KC_LGUI,NEO_L2_L,
+ KC_LEFT, KC_UP,
+ KC_MINS,
+ KC_SPC, KC_ENT, ALL_T(KC_NO),
+ // right hand
+ DE_ACUT, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC,
+ KC_END, NEO_K, NEO_H, NEO_G, NEO_F, NEO_Q, NEO_SS,
+ NEO_S, NEO_N, NEO_R, NEO_T, NEO_D, NEO_L1_R,
+ TG(PMN), NEO_B, NEO_M, KC_COMM,KC_DOT, NEO_J, KC_RSFT,
+ NEO_L2_R,KC_RGUI,MO(FMU),KC_RALT,KC_RCTL,
+ KC_DOWN, KC_RGHT,
+ KC_MINS,
+ MEH_T(KC_NO),KC_ENT,KC_SPC
+ ),
+
+/* Layer 1: poor man’s QWERTZ
+ * based on kaimi’s layout
+ * ┌───────┬─────┬─────┬─────┬─────┬─────┬─────┐ ┌─────┬─────┬─────┬─────┬─────┬─────┬───────┐
+ * │ TAB │ 1 │ 2 │ 3 │ 4 │ 5 │ ` │ │ ´ │ 6 │ 7 │ 8 │ 9 │ 0 │ BKSPC │
+ * ├───────┼─────┼─────┼─────┼─────┼─────┼─────┤ ├─────┼─────┼─────┼─────┼─────┼─────┼───────┤
+ * │ C │ P │ T │ F │ K │ L │ HOM │ │ END │ B │ A │ S │ G │ V │ Y │
+ * ├───────┼─────┼─────┼─────╆─────╅─────┤ E │ │ ├─────╆─────╅─────┼─────┼─────┼───────┤
+ * │ Mod3 │ D │ H │ Ö │ O │ I ├─────┤ ├─────┤ U │ - │ Z │ E │ X │ Mod3 │
+ * ├───────┼─────┼─────┼─────╄─────╃─────┤(TL2)│ │(TL3)├─────╄─────╃─────┼─────┼─────┼───────┤
+ * │ LSHFT │ Ä │ Q │ R │ W │ N │ │ │ │ J │ M │ , │ . │ ẞ │ Shift │
+ * └─┬─────┼─────┼─────┼─────┼─────┼─────┴─────┘ └─────┴─────┼─────┼─────┼─────┼─────┼─────┬─┘
+ * │ CTL │ ALT │ MO1 │ Win │ MO4 │ │ M04 │ Win │ MO1 │ Alt │ CTL │
+ * └─────┴─────┴─────┴─────┴─────┘ ┌─────┬─────┐ ┌─────┬─────┐ └─────┴─────┴─────┴─────┴─────┘
+ * │ ← │ ↑ │ │ ↓ │ → │
+ * ┌─────┼─────┼─────┤ ├─────┼─────┼─────┐
+ * │ │ │ ─ │ │ ─ │ │ │
+ * │ SPC │ RTN ├─────┤ ├─────┤ RTN │ SPC │
+ * │ │ │ HYP │ │ MEH │ │ │
+ * └─────┴─────┴─────┘ └─────┴─────┴─────┘
+ */
+[PMQ] = KEYMAP(
+ // left hand
+ KC_TAB, KC_1, KC_2, KC_3, KC_4, KC_5, KC_EQL,
+ DE_C, DE_P, DE_T, DE_F, DE_K, DE_L, KC_HOME,
+ NEO_L1_L, DE_D, DE_H, DE_OE, DE_O, DE_I,
+ KC_LSFT, DE_AE, DE_Q, DE_R, DE_W, DE_N, KC_TRNS,
+ KC_LCTL, KC_LALT,MO(FMU),KC_LGUI,MO(NHL),
+ KC_LEFT, KC_UP,
+ KC_MINS,
+ KC_SPC, KC_ENT, ALL_T(KC_NO),
+ // right hand
+ DE_ACUT, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC,
+ KC_END, DE_B, DE_A, DE_S, DE_G, DE_V, DE_Y,
+ DE_U, DE_MINS,DE_Z, DE_E, DE_X, NEO_L1_R,
+ KC_TRNS, DE_J, DE_M, DE_COMM,DE_DOT, DE_SS, KC_RSFT,
+ MO(NHL),KC_RGUI,MO(FMU),KC_RALT,KC_RCTL,
+ KC_DOWN, KC_RGHT,
+ KC_MINS,
+ MEH_T(KC_NO),KC_ENT,KC_SPC
+ ),
+
+/* Layer 2: poor man’s Neo
+ * based on kaimi’s layout
+ * ┌───────┬─────┬─────┬─────┬─────┬─────┬─────┐ ┌─────┬─────┬─────┬─────┬─────┬─────┬───────┐
+ * │ TAB │ 1 │ 2 │ 3 │ 4 │ 5 │ ` │ │ ´ │ 6 │ 7 │ 8 │ 9 │ 0 │ BKSPC │
+ * ├───────┼─────┼─────┼─────┼─────┼─────┼─────┤ ├─────┼─────┼─────┼─────┼─────┼─────┼───────┤
+ * │ Y │ X │ V │ L │ C │ W │ HOM │ │ END │ K │ H │ G │ F │ Q │ ß │
+ * ├───────┼─────┼─────┼─────╆─────╅─────┤ E │ │ ├─────╆─────╅─────┼─────┼─────┼───────┤
+ * │ Mod3 │ U │ I │ A │ E │ O ├─────┤ ├─────┤ S │ N │ R │ T │ D │ Mod3 │
+ * ├───────┼─────┼─────┼─────╄─────╃─────┤(TL2)│ │(TL3)├─────╄─────╃─────┼─────┼─────┼───────┤
+ * │ LSHFT │ Ü │ Ö │ Ä │ P │ Z │ │ │ │ B │ M │ , │ . │ J │ Shift │
+ * └─┬─────┼─────┼─────┼─────┼─────┼─────┴─────┘ └─────┴─────┼─────┼─────┼─────┼─────┼─────┬─┘
+ * │ CTL │ ALT │ MO1 │ Win │ MO4 │ │ M04 │ Win │ MO1 │ Alt │ CTL │
+ * └─────┴─────┴─────┴─────┴─────┘ ┌─────┬─────┐ ┌─────┬─────┐ └─────┴─────┴─────┴─────┴─────┘
+ * │ ← │ ↑ │ │ ↓ │ → │
+ * ┌─────┼─────┼─────┤ ├─────┼─────┼─────┐
+ * │ │ │ ─ │ │ ─ │ │ │
+ * │ SPC │ RTN ├─────┤ ├─────┤ RTN │ SPC │
+ * │ │ │ HYP │ │ MEH │ │ │
+ * └─────┴─────┴─────┘ └─────┴─────┴─────┘
+ */
+[PMN] = KEYMAP(
+ KC_TAB, KC_1, KC_2, KC_3, KC_4, KC_5, KC_EQL,
+ DE_Y, DE_X, DE_V, DE_L, DE_C, DE_W, KC_HOME,
+ KC_NO, DE_U, DE_I, DE_A, DE_E, DE_O,
+ KC_LSFT, DE_UE, DE_OE, DE_AE, DE_P, DE_Z, KC_TRNS,
+ KC_LCTL, KC_LALT,MO(FMU),KC_LGUI,MO(NHL),
+ KC_LEFT, KC_UP,
+ KC_MINS,
+ KC_SPC, KC_ENT, ALL_T(KC_NO),
+ // right hand
+ DE_ACUT, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC,
+ KC_END, DE_K, DE_H, DE_G, DE_F, DE_Q, DE_SS,
+ DE_S, DE_N, DE_R, DE_T, DE_D, KC_NO,
+ KC_TRNS, DE_B, DE_M, KC_COMM,KC_DOT, DE_J, KC_RSFT,
+ MO(NHL),KC_RGUI,MO(FMU),KC_RALT,KC_RCTL,
+ KC_DOWN, KC_RGHT,
+ KC_MINS,
+ MEH_T(KC_NO),KC_ENT,KC_SPC
+ ),
+
+/* Layer 3: F-keys, Mouse and Unicode
+ * ┌───────┬─────┬─────┬─────┬─────┬─────┬─────┐ ┌─────┬─────┬─────┬─────┬─────┬─────┬───────┐
+ * │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
+ * ├───────┼─────┼─────┼─────┼─────┼─────┼─────┤ ├─────┼─────┼─────┼─────┼─────┼─────┼───────┤
+ * │ │ │ │ │ ✕ │ │ │ │ │ │ F9 │ F10 │ F11 │ F12 │ │
+ * ├───────┼─────┼─────┼─────╆─────╅─────┤ │ │ ├─────╆─────╅─────┼─────┼─────┼───────┤
+ * │ │ │ │ │ ✓ │ ├─────┤ ├─────┤ │ F5 │ F6 │ F7 │ F8 │ │
+ * ├───────┼─────┼─────┼─────╄─────╃─────┤ │ │ ├─────╄─────╃─────┼─────┼─────┼───────┤
+ * │ │ │ │ │ │ │ │ │ │ │ F1 │ F2 │ F3 │ F4 │ │
+ * └─┬─────┼─────┼─────┼─────┼─────┼─────┴─────┘ └─────┴─────┼─────┼─────┼─────┼─────┼─────┬─┘
+ * │ │ │(MO1)│ │ │ │ │ │(MO1)│ │ │
+ * └─────┴─────┴─────┴─────┴─────┘ ┌─────┬─────┐ ┌─────┬─────┐ └─────┴─────┴─────┴─────┴─────┘
+ * │ Ms← │ Ms↑ │ │ Ms↓ │ Ms→ │
+ * ┌─────┼─────┼─────┤ ├─────┼─────┼─────┐
+ * │ │ │ MLC │ │ MRC │ │ │
+ * │ │ ├─────┤ ├─────┤ │ │
+ * │ │ │ │ │ │ │ │
+ * └─────┴─────┴─────┘ └─────┴─────┴─────┘
+ */
+[FMU] = KEYMAP(
+ // left hand
+ KC_TRNS, KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS, KC_TRNS,KC_TRNS,KC_TRNS,UC(0x2713),KC_TRNS,KC_TRNS,
+ KC_TRNS, KC_TRNS,KC_TRNS,KC_TRNS,UC(0x2715),KC_TRNS,
+ KC_TRNS, KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS, KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_MS_L, KC_MS_U,
+ KC_BTN1,
+ KC_TRNS,KC_TRNS, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS, KC_TRNS,KC_F9, KC_F10, KC_F11, KC_F12, KC_TRNS,
+ KC_TRNS,KC_F5, KC_F6, KC_F7, KC_F8, KC_TRNS,
+ KC_TRNS, KC_TRNS,KC_F1, KC_F2, KC_F3, KC_F4, KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_MS_D, KC_MS_R,
+ KC_BTN2,
+ KC_TRNS, KC_TRNS,KC_TRNS
+ ),
+
+/* Layer 4: Neo’s software layer 4 rebuilt in Hardware
+ * based on kaimi’s layout
+ * ┌───────┬─────┬─────┬─────┬─────┬─────┬─────┐ ┌─────┬─────┬─────┬─────┬─────┬─────┬───────┐
+ * │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
+ * ├───────┼─────┼─────┼─────┼─────┼─────┼─────┤ ├─────┼─────┼─────┼─────┼─────┼─────┼───────┤
+ * │ │ PgUp│ BSpc│ ↑ │ Del │ PgDn│ │ │ │ │ 7 │ 8 │ 9 │ + │ − │
+ * ├───────┼─────┼─────┼─────╆─────╅─────┤ │ │ ├─────╆─────╅─────┼─────┼─────┼───────┤
+ * │ │ Home│ ← │ ↓ │ → │ End ├─────┤ ├─────┤ │ 4 │ 5 │ 6 │ , │ . │
+ * ├───────┼─────┼─────┼─────╄─────╃─────┤(TL2)│ │(TL3)├─────╄─────╃─────┼─────┼─────┼───────┤
+ * │ │ Esc │ Tab │ Ins │ Ret │ Undo│ │ │ │ │ 1 │ 2 │ 3 │ │ │
+ * └─┬─────┼─────┼─────┼─────┼─────┼─────┴─────┘ └─────┴─────┼─────┼─────┼─────┼─────┼─────┬─┘
+ * │ │ │(MO1)│ │(MO4)│ │(MO4)│ │(MO1)│ │ │
+ * └─────┴─────┴─────┴─────┴─────┘ ┌─────┬─────┐ ┌─────┬─────┐ └─────┴─────┴─────┴─────┴─────┘
+ * │ │ │ │ │ │
+ * ┌─────┼─────┼─────┤ ├─────┼─────┼─────┐
+ * │ │ │ │ │ │ │ │
+ * │ │ ├─────┤ ├─────┤ │ │
+ * │ │ │ │ │ │ │ │
+ * └─────┴─────┴─────┘ └─────┴─────┴─────┘
+ */
+[NHL] = KEYMAP(
+ // left hand
+ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+ KC_NO, KC_PGUP,KC_BSPC,KC_UP, KC_DELT,KC_PGDN,KC_NO,
+ KC_NO, KC_HOME,KC_LEFT,KC_DOWN,KC_RGHT,KC_END,
+ KC_NO, KC_ESC, KC_TAB, KC_INS, KC_ENT, KC_UNDO,KC_TRNS,
+ KC_NO, KC_NO, KC_TRNS,KC_NO, KC_TRNS,
+ KC_NO, KC_NO,
+ KC_NO,
+ KC_NO, KC_NO, KC_NO,
+ // right hand
+ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+ KC_NO, KC_NO, KC_7, KC_8, KC_9, DE_PLUS,DE_MINS,
+ KC_NO, KC_4, KC_5, KC_6, KC_COMM,KC_DOT,
+ KC_TRNS, KC_NO, KC_1, KC_2, KC_3, KC_NO, KC_NO,
+ KC_TRNS,KC_NO, KC_TRNS,KC_NO, KC_NO,
+ KC_NO, KC_NO,
+ KC_NO,
+ KC_NO, KC_NO, KC_NO
+ ),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [BASE] = ACTION_FUNCTION(BASE),
+ [PMQ] = ACTION_FUNCTION(PMQ),
+ [PMN] = ACTION_FUNCTION(PMN),
+ [FMU] = ACTION_LAYER_TAP_TOGGLE(FMU),
+ [NHL] = ACTION_LAYER_TAP_TOGGLE(NHL)
+};
+
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ }
+ else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+
+ return MACRO_NONE;
+};
+
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+};
+
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void)
+{
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ case FMU:
+ ergodox_right_led_1_on();
+ break;
+ case PMQ:
+ ergodox_right_led_2_on();
+ break;
+ case PMN:
+ ergodox_right_led_3_on();
+ break;
+ default:
+ ergodox_board_led_off();
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/coderkun_neo2/readme.md b/keyboards/ergodox_ez/keymaps/coderkun_neo2/readme.md
new file mode 100644
index 000000000..2a4d3a535
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/coderkun_neo2/readme.md
@@ -0,0 +1,31 @@
+# coderkun’s Neo2 layout for the ErgoDox EZ
+
+The idea of this layout is to use it for [Neo2](http://www.neo-layout.org) but also provide layers to use QWERTZ with activated Neo driver and to use (basic) Neo when no driver is available (standard QWERTZ driver is active) (e. g. on other computers, in virtual machines) and to make heavily use of thumb keys.
+
+The main goal of the default layer is to provide a complete symmetric layout with each modifier equally placed for both hands (mirror, of course).
+
+It also features a layer for additional keys like F-keys (F1 – F12), some mouse keys and (hopefully in the near future) some useful Unicode symbols.
+
+
+## Layers
+
+0. Default layer for Neo2
+1. Poor man’s QWERTZ
+2. Poor man’s Neo
+3. F-keys, mouse keys und Unicode symbols
+4. Neo’s software layers 4 rebuilt in hardware
+
+
+## Build
+
+1. Enable Unicode in Makefile
+
+ ```
+ UNICODE_ENABLE = yes
+ ```
+2. Build as usual
+
+ ```
+ make clean
+ make KEYMAP=coderkun_neo2
+ ```
diff --git a/keyboards/ergodox_ez/keymaps/colemak/keymap.c b/keyboards/ergodox_ez/keymaps/colemak/keymap.c
new file mode 100644
index 000000000..9601726f7
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/colemak/keymap.c
@@ -0,0 +1,184 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define BASE 0 // default layer
+#define SYMB 1 // symbols
+#define MDIA 2 // media keys
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | = | 1 | 2 | 3 | 4 | 5 | LEFT | | RIGHT| 6 | 7 | 8 | 9 | 0 | - |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Del | Q | W | F | P | G | L1 | | L1 | J | L | U | Y | ; | \ |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | BkSp | A | R | S | T | D |------| |------| H | N | E | I |O / L2| ' |
+ * |--------+------+------+------+------+------| Hyper| | Meh |------+------+------+------+------+--------|
+ * | LShift |Z/Ctrl| X | C | V | B | | | | K | M | , | . |//Ctrl| RShift |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * |Grv/L1| '" |AltShf| Left | Right| | Up | Down | [ | ] | ~L1 |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | App | LGui | | Alt |Ctrl/Esc|
+ * ,------|------|------| |------+--------+------.
+ * | | | Home | | PgUp | | |
+ * | Space|Backsp|------| |------| Tab |Enter |
+ * | |ace | End | | PgDn | | |
+ * `--------------------' `----------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_EQL, KC_1, KC_2, KC_3, KC_4, KC_5, KC_LEFT,
+ KC_DELT, KC_Q, KC_W, KC_F, KC_P, KC_G, TG(SYMB),
+ KC_BSPC, KC_A, KC_R, KC_S, KC_T, KC_D,
+ KC_LSFT, CTL_T(KC_Z), KC_X, KC_C, KC_V, KC_B, ALL_T(KC_NO),
+ LT(SYMB,KC_GRV),KC_QUOT, LALT(KC_LSFT), KC_LEFT,KC_RGHT,
+ ALT_T(KC_APP), KC_LGUI,
+ KC_HOME,
+ KC_SPC,KC_BSPC,KC_END,
+ // right hand
+ KC_RGHT, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
+ TG(SYMB), KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_BSLS,
+ KC_H, KC_N, KC_E, KC_I, LT(MDIA, KC_O), KC_QUOT,
+ MEH_T(KC_NO),KC_K, KC_M, KC_COMM,KC_DOT, CTL_T(KC_SLSH), KC_RSFT,
+ KC_UP, KC_DOWN,KC_LBRC,KC_RBRC, KC_FN1,
+ KC_LALT, CTL_T(KC_ESC),
+ KC_PGUP,
+ KC_PGDN,KC_TAB, KC_ENT
+ ),
+/* Keymap 1: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | . | 0 | = | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[SYMB] = KEYMAP(
+ // left hand
+ KC_TRNS,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS,KC_EXLM,KC_AT, KC_LCBR,KC_RCBR,KC_PIPE,KC_TRNS,
+ KC_TRNS,KC_HASH,KC_DLR, KC_LPRN,KC_RPRN,KC_GRV,
+ KC_TRNS,KC_PERC,KC_CIRC,KC_LBRC,KC_RBRC,KC_TILD,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_UP, KC_7, KC_8, KC_9, KC_ASTR, KC_F12,
+ KC_DOWN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS,
+ KC_TRNS, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS, KC_TRNS,
+ KC_TRNS,KC_DOT, KC_0, KC_EQL, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/* Keymap 2: Media and mouse keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | MsUp | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | |MsLeft|MsDown|MsRght| |------| |------| | | | | | Play |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | | | | Prev | Next | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | Lclk | Rclk | |VolUp |VolDn | Mute | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | |Brwser|
+ * | | |------| |------| |Back |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// MEDIA AND MOUSE
+[MDIA] = KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MPRV, KC_MNXT, KC_TRNS, KC_TRNS,
+ KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_WBAK
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(SYMB) // FN1 - Momentary Layer 1 (Symbols)
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case 1:
+ ergodox_right_led_1_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/colemak/readme.md b/keyboards/ergodox_ez/keymaps/colemak/readme.md
new file mode 100644
index 000000000..e28b2f085
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/colemak/readme.md
@@ -0,0 +1,4 @@
+# ErgoDox EZ Colemak Configuration
+
+Colemak layout with same layers as default ergodox ez keymap.
+
diff --git a/keyboards/ergodox_ez/keymaps/colemak_osx_pc_no/keyboard-layout.png b/keyboards/ergodox_ez/keymaps/colemak_osx_pc_no/keyboard-layout.png
new file mode 100644
index 000000000..57df5a1f9
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/colemak_osx_pc_no/keyboard-layout.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/colemak_osx_pc_no/keymap.c b/keyboards/ergodox_ez/keymaps/colemak_osx_pc_no/keymap.c
new file mode 100644
index 000000000..3b74d266f
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/colemak_osx_pc_no/keymap.c
@@ -0,0 +1,264 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+#include "keymap_norwegian.h"
+
+#define BASE 0 // default layer
+#define BASE_MAC 1 // default layer mac
+#define NUMB_SYMB 2 // numbers and symbols
+#define NUMB_SYMB_MAC 3 // numbers and symbols mac
+#define FUNCTION 4 // function keys
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+
+/* Keymap 0: Basic layer PC
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | \ | [ | ] | { | } | * |Mac/PC| | ^ | $ | ( | ) | < | > | @ |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | ? | Q | W | F | P | G | " | | ' | J | L | U | Y | Å | Æ |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | : | A | R | S | T | D |------| |------| H | N | E | I | O | Ø |
+ * |--------+------+------+------+------+------| ; | | = |------+------+------+------+------+--------|
+ * | ! | Z | X | C | V | B | | | | K | M | RIGHT| DOWN | UP | _ |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | Func | Lclk | Rclk | TAB |,/CTRL| | LEFT | Esc | ` | # | Num |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,--------------.
+ * | & | | | |Insert| / |
+ * ,------|------|------| |------+-------+------.
+ * | | | + | | Del | | |
+ * | Shift| ./Spc|------| |------| Enter |Space|
+ * | | |-/Alt | | Bspc | | |
+ * `--------------------' `---------------------'
+ */
+[BASE] = KEYMAP(
+ // left hand
+ NO_BSLS, NO_LBRC, NO_RBRC, NO_LCBR, NO_RCBR, NO_ASTR, TG(1),
+ NO_QUES, KC_Q, KC_W, KC_F, KC_P, KC_G, NO_QUO2,
+ NO_COLN, KC_A, KC_R, KC_S, KC_T, KC_D,
+ KC_EXLM, KC_Z, KC_X, KC_C, KC_V, KC_B, NO_SCLN,
+ MO(4), KC_BTN1, KC_BTN2, KC_TAB,GUI_T(KC_COMMA),
+ NO_AMP, NO_PIPE,
+ NO_PLUS,
+ KC_FN1,CTL_T(KC_DOT),ALT_T(NO_MINS),
+ // right hand
+ KC_FN5, NO_DLR, NO_LPRN, NO_RPRN ,KC_FN3, KC_FN4,NO_AT,
+ NO_APOS, KC_J, KC_L, KC_U, KC_Y, NO_AA, NO_AE ,
+ KC_H, KC_N, KC_E, KC_I, KC_O, NO_OSLH,
+ NO_EQL, KC_K, KC_M, KC_RIGHT, KC_DOWN, KC_UP, NO_UNDS,
+ KC_LEFT, KC_ESC, KC_FN7, KC_HASH, MO(2),
+ KC_INSERT, NO_SLSH,
+ KC_DELT,
+ KC_BSPC,KC_ENT,KC_SPC
+ ),
+/* Keymap 1: Basic layer MACS (Same as pc, except for cmd/ctrl, which are swapped)
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | \ | | | { | } | | | | | $ | | | < | > | @ |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| | | ' |------+------+------+------+------+--------|
+ * | | | | | | |------| |------| | | | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | | | | | | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | Func | | | |,/Ctrl| | | | ` | | Num |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | |./Cmd |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+[BASE_MAC] = KEYMAP(
+ NO_BSLS_MAC, KC_TRNS,KC_TRNS, NO_LCBR_MAC,NO_RCBR_MAC, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS , KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, CTL_T(KC_COMMA),
+ KC_TRNS, NO_PIPE_MAC,
+ KC_TRNS,
+ KC_TRNS,GUI_T(KC_DOT) , KC_TRNS,
+ // right hand
+ KC_TRNS, NO_DLR_MAC, KC_TRNS,KC_TRNS,KC_FN8, KC_FN9,NO_AT_MAC,
+ NO_APOS_MAC, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, NO_GRV_MAC, KC_TRNS, MO(3),
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+
+/* Keymap 2: Number ++ layer pc
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | | % | | | | | | ~ | ´ | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | 3 | 2 | 1 | 0 | |------| |------| | 5 | 6 | 7 | 8 | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | 4 | | | | | | 9 | END | PGDWN| PGUP | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | HOME | | | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+[NUMB_SYMB] = KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,KC_TRNS,KC_PERC, KC_TRNS , KC_TRNS,
+ KC_TRNS, KC_3 , KC_2 , KC_1 , KC_0 , KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_4, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_FN2, KC_FN6 , KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_5, KC_6, KC_7, KC_8, KC_TRNS,
+ KC_TRNS, KC_HOME, KC_9, KC_END, KC_PGDN, KC_PGUP, KC_TRNS,
+ KC_HOME, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+
+/* Keymap 3: Number ++ layer mac. Some keys have to be repeated from the pc symbol layer, since transient keys inherit from the layer we jump from, not the layer above.
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | | % | | | | | | ~ | ´ | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | 3 | 2 | 1 | 0 | |------| |------| | 5 | 6 | 7 | 8 | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | 4 | | | | | | 9 | END | PGDWN| PGUP | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | HOME | | | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+[NUMB_SYMB_MAC] = KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,KC_TRNS,KC_PERC, KC_TRNS , KC_TRNS,
+ KC_TRNS, KC_3 , KC_2 , KC_1 , KC_0 , KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_4, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS , KC_TRNS, KC_TRNS , KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_FN2, KC_FN10, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_5, KC_6, KC_7, KC_8, KC_TRNS,
+ KC_TRNS, KC_HOME, KC_9, KC_END, KC_PGDN, KC_PGUP, KC_TRNS,
+ KC_HOME, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+
+/* Keymap 4: Function layer mac + pc
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | F3 | F2 | F1 | | |------| |------| | F5 | F6 | F7 | F8 | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | F4 | | | | | | F9 | F10 | F11 | F12 | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | | | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+[FUNCTION] = KEYMAP(
+ KC_5, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS , KC_TRNS,
+ KC_TRNS, KC_F3 , KC_F2 , KC_F1 , KC_TRNS , KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_F4, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_F5, KC_F6, KC_F7, KC_F8, KC_TRNS,
+ KC_TRNS, NO_TILD, KC_F9, KC_F10, KC_F11, KC_F12, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+)
+};
+
+enum macro_id {
+ TILDE_NO, LESS_NO, GRTR_NO, CIRC_NO, ACUT_NO, GRV_NO, LESS_NO_MAC, GRTR_NO_MAC, ACUT_NO_MAC
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_MODS_ONESHOT(MOD_LSFT), // Sticky shift light. Tap for the next keypress to be shifted. Hold for regular shift.
+ [2] = ACTION_MACRO(TILDE_NO), // Completed ~ character(pc and mac), no space needed.
+ [3] = ACTION_MACRO(LESS_NO), // < completed on keypress down, to avoid shifting the next character if it is not released first.
+ [4] = ACTION_MACRO(GRTR_NO), // > completed on keypress down, to avoid shifting the next character if it is not released first.
+ [5] = ACTION_MACRO(CIRC_NO), // Completed ^ character, no space needed.
+ [6] = ACTION_MACRO(ACUT_NO), // Completed ´ character, no space needed.
+ [7] = ACTION_MACRO(GRV_NO), // Completed ` character, no space needed.
+ [8] = ACTION_MACRO(LESS_NO_MAC), // < completed on keypress down, to avoid same button problem when typing <> quickly
+ [9] = ACTION_MACRO(GRTR_NO_MAC), // > completed on keypress down, to avoid same button problem when typing <> quickly
+ [10] = ACTION_MACRO(ACUT_NO_MAC), // Completed ´ character, no space needed
+};
+
+
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ keyevent_t event = record->event;
+
+ switch (id) {
+ case TILDE_NO:
+ return (event.pressed ? MACRO( D(RALT), T(RBRC), U(RALT), T(SPC), END ) : MACRO_NONE);
+ case LESS_NO:
+ return (event.pressed ? MACRO( T(NUBS), END ) : MACRO_NONE);
+ case GRTR_NO:
+ return (event.pressed ? MACRO( D(LSFT), T(NUBS), U(LSFT), END ) : MACRO_NONE);
+ case CIRC_NO:
+ return (event.pressed ? MACRO( D(LSFT), T(RBRC), U(LSFT), T(SPC), END ) : MACRO_NONE);
+ case ACUT_NO:
+ return (event.pressed ? MACRO( D(RALT), T(EQL), U(RALT), T(SPC), END ) : MACRO_NONE);
+ case GRV_NO:
+ return (event.pressed ? MACRO( D(LSFT), T(EQL), T(SPC), U(LSFT), END ) : MACRO_NONE);
+ case LESS_NO_MAC:
+ return (event.pressed ? MACRO( T(GRV), END ) : MACRO_NONE);
+ case GRTR_NO_MAC:
+ return (event.pressed ? MACRO( D(LSFT), T(GRV), U(LSFT), END ) : MACRO_NONE);
+ case ACUT_NO_MAC:
+ return (event.pressed ? MACRO( T(EQL), T(SPC), END ) : MACRO_NONE);
+ }
+ return MACRO_NONE;
+};
diff --git a/keyboards/ergodox_ez/keymaps/colemak_osx_pc_no/readme.md b/keyboards/ergodox_ez/keymaps/colemak_osx_pc_no/readme.md
new file mode 100644
index 000000000..48f095cae
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/colemak_osx_pc_no/readme.md
@@ -0,0 +1,23 @@
+# Norwegian Colemak setup with osx/pc toggle
+
+## Motivation
+I wanted a Norwegian Colemak setup that worked in a similar way on both my Mac and PC. I also wanted it to translate from a standard Norwegian keyboard OS setup.
+
+## Overview
+The setup is created to be programmer friendly.
+- Most of the symbols used in code can be activated without using layers or shift key.
+- You can reach the IDE/OS shortcut activators(Ctrl, Win/Cmd, Alt, Shift) with the thumb.
+- Navigation is prioritized, arrows are right below the home row.
+
+## PC/Mac toggle
+The default setup is for Norwegian keyboard setting(not colemak variants) on a PC(Windows or Linux). Use the Mac/PC toggle button to switch between OSX and PC setup. The settings will be reverted to PC setup each time you restart/connect the keyboard.
+
+## Layers
+Numbers and function buttons are on their own layers. The easiest way to switch layers(at least with my hands) in this setup, is to push your hand right below the little finger, on the layer switches. You will then have all your fingers free to type numbers or press function buttons.
+
+## Shift-key
+Tap for the next character to be shifted, hold down for regular shift functionality
+
+## Layout
+
+![keyboard-layout](keyboard-layout.png)
diff --git a/keyboards/ergodox_ez/keymaps/csharp_dev/csharp_dev.png b/keyboards/ergodox_ez/keymaps/csharp_dev/csharp_dev.png
new file mode 100644
index 000000000..6fba568fc
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/csharp_dev/csharp_dev.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/csharp_dev/csharp_dev_legend.png b/keyboards/ergodox_ez/keymaps/csharp_dev/csharp_dev_legend.png
new file mode 100644
index 000000000..b0a1c513c
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/csharp_dev/csharp_dev_legend.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/csharp_dev/keymap.c b/keyboards/ergodox_ez/keymaps/csharp_dev/keymap.c
new file mode 100644
index 000000000..e9648ede7
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/csharp_dev/keymap.c
@@ -0,0 +1,239 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define BASE 0 // default layer
+#define FKEYS 1 // F keys + macros
+
+#define MACRO_PUBLIC 10
+#define MACRO_PRIVATE 11
+
+#define MACRO_STATIC 12
+#define MACRO_CONST 13
+
+#define MACRO_VOID 14
+#define MACRO_VAR 15
+#define MACRO_STRING 16
+
+#define MACRO_INT 17
+#define MACRO_FLOAT 18
+#define MACRO_BOOL 19
+
+#define MACRO_RETURN 20
+#define MACRO_NULL 21
+#define MACRO_BREAK 22
+
+#define MACRO_TODO 23
+#define MACRO_NEW 24
+#define MACRO_PARENTHESE 25
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | ( | 1 | 2 | 3 | 4 | 5 | " | | Save | 6 | 7 | 8 | 9 | 0 | [ |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | ) | Q | W | E | R | T |Bkspa | | Del | Y | U | I | O | P | ] |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | { | A | S | D | F | G |------| |------| H | J | K | L | _ | Redo |
+ * |--------+------+------+------+------+------| / | | ; |------+------+------+------+------+--------|
+ * | } |Z~Alt | X | C | V | B | | | | N | M | ' | ! | ? | Undo |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * |Tab~CL| < | > | | | & | | = | + | - | * | L1 |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * |. ~L1 | , | |Home |End~L1|
+ * ,------|------|------| |------+------+------.
+ * | | | Copy | | UP | | |
+ * | Enter| Space|------| |------| Space|Enter |
+ * | ~WIN | ~LSFT| Past | | DOWN | ~LSFT| ~WIN |
+ * `--------------------' `--------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_LPRN, KC_1, KC_2, KC_3, KC_4, KC_5, LSFT(KC_QUOTE),
+ KC_RPRN, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_BSPACE,
+ KC_LCBR, KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_RCBR, ALT_T(KC_Z), KC_X, KC_C, KC_V, KC_B, KC_SLASH,
+ CTL_T(KC_TAB), LSFT(KC_COMMA),LSFT(KC_DOT),KC_PIPE,KC_AMPR,
+ LT(1,KC_DOT), KC_COMM,
+ LCTL(KC_C),
+ GUI_T(KC_ENTER),SFT_T(KC_SPACE),LCTL(KC_V),
+ // right hand
+ LCTL(KC_S) , KC_6, KC_7, KC_8, KC_9, KC_0, KC_LBRACKET,
+ KC_DELETE, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_RBRACKET,
+ KC_H, KC_J, KC_K, KC_L, KC_UNDS,LCTL(KC_Y),
+ KC_SCOLON,KC_N, KC_M, KC_QUOTE ,KC_EXLM , LSFT(KC_SLASH), LCTL(KC_Z),
+ KC_EQUAL,KC_PLUS , KC_MINUS,KC_ASTR , TG(1),
+ KC_HOME, LT(1,KC_END),
+ KC_UP,
+ KC_DOWN,SFT_T(KC_SPACE), GUI_T(KC_ENTER)
+ ),
+
+/* Keymap 1: F keys + macros
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | ESC | F1 | F2 | F3 | F4 | F5 | ` | | Calc | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Tab |Public|Static|string|int |return| | | |//TODO| | | | | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | |Privat|Const |var |float |null |------| |------|new | | | | | |
+ * |--------+------+------+------+------+------| \ | | ~ |------+------+------+------+------+--------|
+ * | | | |void |bool |break;| | | |(); | | | | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | WIN | Alt | | | | PgUp | PgDw | Ins | PtSc | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | Cut | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| Left | Right|
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// FKEYS + MACROS
+[FKEYS] = KEYMAP(
+ // left hand
+ KC_ESCAPE,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_GRAVE,
+ KC_TAB,M(MACRO_PUBLIC),M(MACRO_STATIC), M(MACRO_STRING),M(MACRO_INT),M(MACRO_RETURN),KC_TRNS,
+ KC_TRNS,M(MACRO_PRIVATE),M(MACRO_CONST), M(MACRO_VAR),M(MACRO_FLOAT),M(MACRO_NULL),
+ KC_TRNS,KC_TRNS,KC_TRNS,M(MACRO_VOID),M(MACRO_BOOL),M(MACRO_BREAK),KC_BSLASH,
+ KC_TRNS,KC_LGUI,KC_LALT,KC_TRNS,KC_TRNS,
+ KC_TRNS,LCTL(KC_X),
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_CALCULATOR, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, M(MACRO_TODO), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_F12,
+ M(MACRO_NEW), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TILD, M(MACRO_PARENTHESE), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_PGUP,KC_PGDOWN, KC_INSERT, KC_PSCREEN, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_LEFT, KC_RIGHT
+),
+
+
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(FKEYS) // FN1 - Momentary Layer 1
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case MACRO_PUBLIC:
+ if (record->event.pressed) {
+ return MACRO( T(P), T(U), T(B), T(L), T(I), T(C), T(SPACE),END);
+ }
+ break;
+ case MACRO_PRIVATE:
+ if (record->event.pressed) {
+ return MACRO( T(P), T(R), T(I), T(V), T(A), T(T), T(E), T(SPACE),END);
+ }
+ break;
+ case MACRO_STATIC:
+ if (record->event.pressed) {
+ return MACRO( T(S), T(T), T(A), T(T), T(I), T(C), T(SPACE), END);
+ }
+ break;
+ case MACRO_CONST:
+ if (record->event.pressed) {
+ return MACRO( T(C), T(O), T(N), T(S), T(T), T(SPACE), END);
+ }
+ break;
+ case MACRO_VOID:
+ if (record->event.pressed) {
+ return MACRO( T(V), T(O), T(I), T(D), T(SPACE), END);
+ }
+ break;
+ case MACRO_VAR:
+ if (record->event.pressed) {
+ return MACRO( T(V), T(A), T(R), T(SPACE), END);
+ }
+ break;
+ case MACRO_STRING:
+ if (record->event.pressed) {
+ return MACRO( T(S), T(T), T(R), T(I), T(N), T(G), T(SPACE), END);
+ }
+ break;
+ case MACRO_BOOL:
+ if (record->event.pressed) {
+ return MACRO( T(B), T(O), T(O), T(L), T(SPACE), END);
+ }
+ break;
+ case MACRO_INT:
+ if (record->event.pressed) {
+ return MACRO( T(I), T(N), T(T), T(SPACE), END);
+ }
+ break;
+ case MACRO_FLOAT:
+ if (record->event.pressed) {
+ return MACRO( T(F), T(L), T(O), T(A),T(T),T(SPACE), END);
+ }
+ break;
+ case MACRO_RETURN:
+ if (record->event.pressed) {
+ return MACRO( T(R), T(E), T(T), T(U),T(R),T(N), END);
+ }
+ break;
+ case MACRO_NULL:
+ if (record->event.pressed) {
+ return MACRO( T(N), T(U), T(L), T(L), END);
+ }
+ case MACRO_BREAK:
+ if (record->event.pressed) {
+ return MACRO( T(B), T(R), T(E), T(A), T(K), T(SCOLON), END);
+ }
+ break;
+ case MACRO_TODO:
+ if (record->event.pressed) {
+ return MACRO( T(SLASH), T(SLASH), D(LSHIFT) ,T(T), T(O), T(D), T(O),U(LSHIFT), T(SPACE),END);
+ }
+ break;
+ case MACRO_NEW:
+ if (record->event.pressed) {
+ return MACRO( T(N), T(E), T(W), T(SPACE), END);
+ }
+ break;
+ case MACRO_PARENTHESE:
+ if (record->event.pressed) {
+ return MACRO( D(LSHIFT),T(9), T(0),U(LSHIFT), T(SCOLON), END);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case 1:
+ ergodox_right_led_1_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/csharp_dev/readme.md b/keyboards/ergodox_ez/keymaps/csharp_dev/readme.md
new file mode 100644
index 000000000..96af077ad
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/csharp_dev/readme.md
@@ -0,0 +1,47 @@
+# ErgoDox EZ C# Developer configuration
+
+## Changelog
+
+* Feb 12, 2016 (V1):
+ * First version commit
+* Mar 20, 2016 (V2):
+ * Removed "Classic QWERTY" layer, inverted GUI and SHIFT on Hold for Space and Enter
+
+## About
+This layout was conceived in an attempt to optimise keyboard layout for developers (C# more specifically, but it can work with most of other languages), and limit the keys required to perform the most frequent actions.
+
+I came to the realization that my main tool as a developer, the qwerty keyboard was something that did not evolved at its core in almost 150 years.
+There are a lot of reasons to this, and it would be a massive entreprise to change a standard so strongly anchored, but I wanted to give it a try and see how would look an input device dedicated to developers, more specifically a C# developer in my case.
+The biggest flaw in standard QWERTY keyboards was that I always needed to perform key combination to access commonly used characters or actions. Think about it a minute, how many times a day do you press a modifier key such as Ctrl or Shift, it's insane and could be so easily optimized to require only one key press.
+
+Then I came across the ErgoDox EZ project, that allowed a full customization of its firmware, and a unique 2 parts design.
+
+![CSharpDev](csharp_dev_legend.png)
+
+## Layout design principles
+* No key combination required for the most common input characters ( (),[],{},<> ... )
+* No key combination required for the most common actions (copy/paste/undo/save)
+* Regroup characters by usage ( + - * = ...)
+* Easy access to the most commonly used characters: ; / " . ,
+* Preregistered macro for the most common C# langage instructions: public / private / string / int / float ...
+
+## Why is it specific to C Sharp
+I defined the characters priority based on their usage in C# language, most of this characters are also used in other coding languages but it may require some tweaking.
+For example there is no direct access to ~ or $ keys which can be very common in some languages.
+Note it is also specific to Windows environement as the shortcut used in action keys would not work on Mac Os
+
+## In usage
+It was relatively easy to get used to the layout, but it's hard for me to define how easy it was as I was getting used to a blank Ergodox keyboard at the same time.
+Still it's extremely satisfying to Save your file with just one easily accessible key or to have one big key to end your code line ( ; )
+
+## Improvements
+This layout was shared after a bunch of iterations and only once I was happy with it.
+Still there are many way to improve or iterate on this:
+* Make it language agnostic
+* Check and compile language's keyboard's heatmaps to statistically define keys priority (e.g. https://dzone.com/articles/most-pressed-keys-various )
+* QWERTY is still not the most efficient typing layout, I would like to create a Dvorak based similar layout in a near futur
+
+## Issues
+One of the issues encountered while creating this layout was that I did not find a way to have a key to send a modifier on hold, and a key combination while pressed (e.g. I can't set a Key to do Save (Ctrl + S) when pressed and Shift modifier when hold )
+
+
diff --git a/keyboards/ergodox_ez/keymaps/dave/keymap.c b/keyboards/ergodox_ez/keymaps/dave/keymap.c
new file mode 100644
index 000000000..e9480af3e
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/dave/keymap.c
@@ -0,0 +1,199 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define BASE 0 // default layer
+#define PROG 1 // programming
+#define NAVI 2 // navigation
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | Esc | 1 | 2 | 3 | 4 | 5 | 6 | | 6 | 7 | 8 | 9 | 0 | - | BkSpce |
+ * |--------+------+------+------+------+------+------| |------+------+------+------+------+------+--------|
+ * | Tab | Q | W | E | R | T | Y | | G | Y | U | I | O | P | Enter |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | LCtrl | A | S | D | F | G |------| |------| H | J | K | L | ; | Enter |
+ * |--------+------+------+------+------+------| H | | B |------+------+------+------+------+--------|
+ * | LShift | Z | X | C | V | B | | | | N | M | , | . | / | RShift |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * |`/Ctrl| \ | | | LAlt | | RAlt | [ | ] | |'/Ctrl|
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | PrtS | PrtS | | CtAl | CtAl |
+ * ,------+------+------| |------+------+------.
+ * | | | L1 | | L1 | | |
+ * | Spce | ~L2 +------| |------+ ~L1 | Spce |
+ * | | | LGui | | RGui | | |
+ * `--------------------' `--------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6,
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y,
+ KC_LCTRL, KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_H,
+ CTL_T(KC_GRV),KC_NUBS,KC_NO, KC_NO, KC_LALT,
+ KC_PSCREEN, KC_PSCREEN,
+ TO(PROG, ON_PRESS),
+ KC_SPC, MO(NAVI), KC_LGUI,
+ // right hand
+ KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_BSPC,
+ KC_G, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_ENTER,
+ KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_ENTER,
+ KC_B, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH, KC_RSFT,
+ KC_RALT,KC_LBRC,KC_RBRC,KC_NO, CTL_T(KC_QUOT),
+ MT(0x5, KC_NO), MT(0x5, KC_NO),
+ TO(PROG, ON_PRESS),
+ KC_RGUI, MO(PROG), KC_SPC
+ ),
+
+/* Keymap 1: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | K/ | K* | K- | = |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | ! | @ | ( | ) | | | | | | | K7 | K8 | K9 | K+ | # |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | # | $ | { | } | ` |------| |------| | K4 | K5 | K6 | K+ | ' |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | % | ^ | [ | ] | ~ | | | | | K1 | K2 | K3 | K= | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | K0 | K0 | K. | K= | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | L2 | | L2 | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// PROGRAMMING
+[PROG] = KEYMAP(
+ // left hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_EXLM, KC_AT, KC_LCBR, KC_RCBR, KC_PIPE, KC_TRNS,
+ KC_TRNS, KC_HASH, KC_DLR, KC_LPRN, KC_RPRN, KC_GRV,
+ KC_TRNS, KC_PERC, KC_CIRC, KC_LBRC, KC_RBRC, KC_TILD, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ TO(NAVI, ON_PRESS),
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_NO, KC_PSLS, KC_PAST, KC_PMNS, KC_EQUAL,
+ KC_TRNS, KC_TRNS, KC_P7, KC_P8, KC_P9, KC_PPLS, KC_NUHS,
+ KC_TRNS, KC_P4, KC_P5, KC_P6, KC_PPLS, KC_QUOT,
+ KC_TRNS, KC_TRNS, KC_P1, KC_P2, KC_P3, KC_PENT, KC_TRNS,
+ KC_P0, KC_P0, KC_PDOT, KC_PENT, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ TO(NAVI, ON_PRESS),
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+
+/* Keymap 2: Navigation and system keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | F6 | | F7 | F8 | F9 | F10 | F11 | F12 | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | Home | Up | End | Ins | PgUp | | | | | | Ins | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | Left | Down | Rght | Del | PgDn |------| |------| | Back | Del | Fwrd | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | Lclk | MsUp | Rclk | | | | | | | Prev | Play | Next | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | MsLt | MsDn | MsRt | | |VolDn | Mute |VolUp | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | L0 | | L0 | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// NAVIGATION
+[NAVI] = KEYMAP(
+ KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6,
+ KC_TRNS, KC_HOME, KC_UP, KC_END, KC_INS, KC_PGUP, KC_TRNS,
+ KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_DELT, KC_PGDN,
+ KC_TRNS, KC_BTN1, KC_MS_U, KC_BTN2, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ TO(BASE, ON_PRESS),
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_INS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_WBAK, KC_DELT, KC_WFWD, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MPRV, KC_MPLY, KC_MNXT, KC_TRNS, KC_TRNS,
+ KC_VOLD, KC_MUTE, KC_VOLU, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ TO(BASE, ON_PRESS),
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ //[1] = ACTION_LAYER_TAP_TOGGLE(PROG), // FN1 - Momentary Layer 1 (Symbols)
+ //[2] = ACTION_LAYER_TAP_TOGGLE(NAVI) // FN2 - Momentary Layer 2 (Navigation)
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+ /* leds is a static array holding the current brightness of each of the
+ * three keyboard LEDs. It's 4 long simply to avoid the ugliness of +1s and
+ * -1s in the code below, and because wasting a byte really doesn't matter
+ * that much (no, it *doesn't*, stop whinging!). Note that because it's
+ * static it'll maintain state across invocations of this routine.
+ */
+ static uint8_t leds[4];
+ uint8_t led;
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+
+ /* Loop over each LED/layer */
+ for (led = 1; led <= 3; ++led) {
+ /* If the current layer matches the current LED, increment its
+ * brightness by 1 up to a maximum of 255. If the current layer doesn't
+ * match, decrement its brightness by 1 down to a minimum of zero.
+ */
+ leds[led] += (layer == led) ?
+ (leds[led] < 255 ? 1 : 0):
+ (leds[led] > 0 ? -1 : 0);
+ /* Set LED state according to the new brightness */
+ if (leds[led]) {
+ ergodox_right_led_on(led);
+ ergodox_right_led_set(led, leds[led]);
+ }
+ else {
+ ergodox_right_led_off(led);
+ }
+ }
+
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/dave/readme.md b/keyboards/ergodox_ez/keymaps/dave/readme.md
new file mode 100644
index 000000000..aa0f9bd19
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/dave/readme.md
@@ -0,0 +1,38 @@
+This keymap is my preferred layout (after a certain amount of experimentation).
+The rationale behind the design is as follows:
+
+I grew up typing from a very early age and thus never learned the "correct" way
+to touch type (essentially, I'm self-taught). As a, result my fingers don't
+tend to stay on the "home keys" and occasionally my right hand wants to type
+keys that are on the left of the keyboard, and vice versa.
+
+Hence, despite liking the idea of split keyboards in principle, I've never been
+able to get on with them because the split simply doesn't work with my style of
+typing. The Ergodox solves this neatly by virtue of having a few extra keys in
+the "middle" of the keyboard which I can utilise for deliberate redundancy.
+Thus in this keymap there are two "6" keys (one on the left, one on the right)
+and likewise Y, H, G, and B are all duplicated to enable one-handed patterns
+that I use frequently (e.g. "byobu" with the right hand, "yes" with the left,
+etc.).
+
+I occasionally use the numeric pad for data entry, thus this is duplicated
+under the natural home position of the right hand in layer 1 (activated by
+holding one of the right thumb buttons), while the cursor keys are duplicated
+under the classic WASD gaming layout of the left hand in layer 2 (activated by
+holding one of the left thumb buttons). Various other useful keys also appear
+in these layers (brackets and symbols for coding in layer 1, navigation and
+F-keys in layer 2, etc.).
+
+Finally, modifier keys like Ctrl, Shift, and Alt, along with Backspace and
+Enter are all in traditional locations in an effort to reuse existing muscle
+memory as much as possible (keys like =, #, and ' are in layer 1). The layout
+maps are in the comments of keymap_dave.c so I won't bother duplicating them
+here.
+
+Oh, and the LEDs are rather pimped ... because I could!
+
+Anyway, although I'm sure this keymap won't be to many people's taste you might
+find some interesting ideas in here for your own layouts. Do tweet me
+(@waveform80) if you have any questions / suggestions / bugs.
+
+Dave.
diff --git a/keyboards/ergodox_ez/keymaps/default/default.png b/keyboards/ergodox_ez/keymaps/default/default.png
new file mode 100644
index 000000000..6575f7b5e
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/default/default.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/default/default_highres.png b/keyboards/ergodox_ez/keymaps/default/default_highres.png
new file mode 100644
index 000000000..7d9f045f4
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/default/default_highres.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/default/keymap.c b/keyboards/ergodox_ez/keymaps/default/keymap.c
new file mode 100644
index 000000000..b48a54a43
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/default/keymap.c
@@ -0,0 +1,182 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define BASE 0 // default layer
+#define SYMB 1 // symbols
+#define MDIA 2 // media keys
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | = | 1 | 2 | 3 | 4 | 5 | LEFT | | RIGHT| 6 | 7 | 8 | 9 | 0 | - |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Del | Q | W | E | R | T | L1 | | L1 | Y | U | I | O | P | \ |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | BkSp | A | S | D | F | G |------| |------| H | J | K | L |; / L2|' / Cmd |
+ * |--------+------+------+------+------+------| Hyper| | Meh |------+------+------+------+------+--------|
+ * | LShift |Z/Ctrl| X | C | V | B | | | | N | M | , | . |//Ctrl| RShift |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * |Grv/L1| '" |AltShf| Left | Right| | Up | Down | [ | ] | ~L1 |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | App | LGui | | Alt |Ctrl/Esc|
+ * ,------|------|------| |------+--------+------.
+ * | | | Home | | PgUp | | |
+ * | Space|Backsp|------| |------| Tab |Enter |
+ * | |ace | End | | PgDn | | |
+ * `--------------------' `----------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_EQL, KC_1, KC_2, KC_3, KC_4, KC_5, KC_LEFT,
+ KC_DELT, KC_Q, KC_W, KC_E, KC_R, KC_T, TG(SYMB),
+ KC_BSPC, KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_LSFT, CTL_T(KC_Z), KC_X, KC_C, KC_V, KC_B, ALL_T(KC_NO),
+ LT(SYMB,KC_GRV),KC_QUOT, LALT(KC_LSFT), KC_LEFT,KC_RGHT,
+ ALT_T(KC_APP), KC_LGUI,
+ KC_HOME,
+ KC_SPC,KC_BSPC,KC_END,
+ // right hand
+ KC_RGHT, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
+ TG(SYMB), KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSLS,
+ KC_H, KC_J, KC_K, KC_L, LT(MDIA, KC_SCLN),GUI_T(KC_QUOT),
+ MEH_T(KC_NO),KC_N, KC_M, KC_COMM,KC_DOT, CTL_T(KC_SLSH), KC_RSFT,
+ KC_UP, KC_DOWN,KC_LBRC,KC_RBRC, KC_FN1,
+ KC_LALT, CTL_T(KC_ESC),
+ KC_PGUP,
+ KC_PGDN,KC_TAB, KC_ENT
+ ),
+/* Keymap 1: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * |Version | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | . | 0 | = | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[SYMB] = KEYMAP(
+ // left hand
+ M(0), KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS,KC_EXLM,KC_AT, KC_LCBR,KC_RCBR,KC_PIPE,KC_TRNS,
+ KC_TRNS,KC_HASH,KC_DLR, KC_LPRN,KC_RPRN,KC_GRV,
+ KC_TRNS,KC_PERC,KC_CIRC,KC_LBRC,KC_RBRC,KC_TILD,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_UP, KC_7, KC_8, KC_9, KC_ASTR, KC_F12,
+ KC_DOWN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS,
+ KC_TRNS, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS, KC_TRNS,
+ KC_TRNS,KC_DOT, KC_0, KC_EQL, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/* Keymap 2: Media and mouse keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | MsUp | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | |MsLeft|MsDown|MsRght| |------| |------| | | | | | Play |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | | | | Prev | Next | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | Lclk | Rclk | |VolUp |VolDn | Mute | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | |Brwser|
+ * | | |------| |------| |Back |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// MEDIA AND MOUSE
+[MDIA] = KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MPRV, KC_MNXT, KC_TRNS, KC_TRNS,
+ KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_WBAK
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(SYMB) // FN1 - Momentary Layer 1 (Symbols)
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ SEND_STRING (QMK_KEYBOARD "/" QMK_KEYMAP " @ " QMK_VERSION);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case 1:
+ ergodox_right_led_1_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/default/readme.md b/keyboards/ergodox_ez/keymaps/default/readme.md
new file mode 100644
index 000000000..8f6dba45e
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/default/readme.md
@@ -0,0 +1,10 @@
+# ErgoDox EZ Default Configuration
+
+## Changelog
+
+* Feb 2, 2016 (V1.1):
+ * Made the right-hand quote key double as Cmd/Win on hold. So you get ' when you tap it, " when you tap it with Shift, and Cmd or Win when you hold it. You can then use it as a modifier, or just press and hold it for a moment (and then let go) to send a single Cmd or Win keystroke (handy for opening the Start menu on Windows).
+
+This is what we ship with out of the factory. :) The image says it all:
+
+![Default](default_highres.png)
diff --git a/keyboards/ergodox_ez/keymaps/default_osx/default_osx_highres.png b/keyboards/ergodox_ez/keymaps/default_osx/default_osx_highres.png
new file mode 100644
index 000000000..04f46bbd5
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/default_osx/default_osx_highres.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/default_osx/keymap.c b/keyboards/ergodox_ez/keymaps/default_osx/keymap.c
new file mode 100644
index 000000000..c57ffbb88
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/default_osx/keymap.c
@@ -0,0 +1,187 @@
+// Netable differences vs. the default firmware for the ErgoDox EZ:
+// 1. The Cmd key is now on the right side, making Cmd+Space easier.
+// 2. The media keys work on OSX (But not on Windows).
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define BASE 0 // default layer
+#define SYMB 1 // symbols
+#define MDIA 2 // media keys
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | = | 1 | 2 | 3 | 4 | 5 | LEFT | | RIGHT| 6 | 7 | 8 | 9 | 0 | - |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Del | Q | W | E | R | T | L1 | | L1 | Y | U | I | O | P | \ |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | BkSp | A | S | D | F | G |------| |------| H | J | K | L |; / L2| LGui |
+ * |--------+------+------+------+------+------| Hyper| | Meh |------+------+------+------+------+--------|
+ * | LShift |Z/Ctrl| X | C | V | B | | | | N | M | , | . |//Ctrl| RShift |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * |Grv/L1| '" |AltShf| Left | Right| | Up | Down | [ | ] | ~L1 |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | App | LGui | | Alt |Ctrl/Esc|
+ * ,------|------|------| |------+--------+------.
+ * | | | Home | | PgUp | | |
+ * | Space|Backsp|------| |------| Tab |Enter |
+ * | |ace | End | | PgDn | | |
+ * `--------------------' `----------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_EQL, KC_1, KC_2, KC_3, KC_4, KC_5, KC_LEFT,
+ KC_DELT, KC_Q, KC_W, KC_E, KC_R, KC_T, TG(SYMB),
+ KC_BSPC, KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_LSFT, CTL_T(KC_Z), KC_X, KC_C, KC_V, KC_B, ALL_T(KC_NO),
+ LT(SYMB,KC_GRV),KC_QUOT, LALT(KC_LSFT), KC_LEFT,KC_RGHT,
+ ALT_T(KC_APP), KC_LGUI,
+ KC_HOME,
+ KC_SPC,KC_BSPC,KC_END,
+ // right hand
+ KC_RGHT, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
+ TG(SYMB), KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSLS,
+ KC_H, KC_J, KC_K, KC_L, LT(MDIA, KC_SCLN),KC_LGUI,
+ MEH_T(KC_NO),KC_N, KC_M, KC_COMM,KC_DOT, CTL_T(KC_SLSH), KC_RSFT,
+ KC_UP, KC_DOWN,KC_LBRC,KC_RBRC, KC_FN1,
+ KC_LALT, CTL_T(KC_ESC),
+ KC_PGUP,
+ KC_PGDN,KC_TAB, KC_ENT
+ ),
+/* Keymap 1: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | . | 0 | = | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[SYMB] = KEYMAP(
+ // left hand
+ KC_TRNS,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS,KC_EXLM,KC_AT, KC_LCBR,KC_RCBR,KC_PIPE,KC_TRNS,
+ KC_TRNS,KC_HASH,KC_DLR, KC_LPRN,KC_RPRN,KC_GRV,
+ KC_TRNS,KC_PERC,KC_CIRC,KC_LBRC,KC_RBRC,KC_TILD,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_UP, KC_7, KC_8, KC_9, KC_ASTR, KC_F12,
+ KC_DOWN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS,
+ KC_TRNS, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS, KC_TRNS,
+ KC_TRNS,KC_DOT, KC_0, KC_EQL, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/* Keymap 2: Media and mouse keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | MsUp | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | |MsLeft|MsDown|MsRght| |------| |------| | | | | | Play |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | | | | Prev | Next | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | Lclk | Rclk | |VolUp |VolDn | Mute | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | |Brwser|
+ * | | |------| |------| |Back |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// MEDIA AND MOUSE
+[MDIA] = KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MPRV, KC_MNXT, KC_TRNS, KC_TRNS,
+ KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_WBAK
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(SYMB) // FN1 - Momentary Layer 1 (Symbols)
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case 1:
+ ergodox_right_led_1_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/default_osx/readme.md b/keyboards/ergodox_ez/keymaps/default_osx/readme.md
new file mode 100644
index 000000000..aa749aac9
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/default_osx/readme.md
@@ -0,0 +1,8 @@
+# The OSX Friendly Version of the Default Firmware
+
+So, I took the default firmware and just made a couple of tweaks that make it easier to use with OS X:
+
+1. The Cmd key is now on the right side, making Cmd+Space easier.
+2. The media keys work on OSX (But not on Windows).
+
+![default osx](default_osx_highres.png)
diff --git a/keyboards/ergodox_ez/keymaps/dragon788/keymap.c b/keyboards/ergodox_ez/keymaps/dragon788/keymap.c
new file mode 100644
index 000000000..3aec8c6cf
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/dragon788/keymap.c
@@ -0,0 +1,229 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define BASE 0 // default layer
+#define SYMB 1 // symbols
+#define MDIA 2 // media keys
+#define PLVR 3 // Plover layer
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | = | 1 | 2 | 3 | 4 | 5 | LGui | |Plover| 6 | 7 | 8 | 9 | 0 | - |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Tab | Q | W | E | R | T | L1 | | L2 | Y | U | I | O | P | \ |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * |Esc/Ctrl| A | S | D | F | G |------| |------| H | J | K | L | ; | '"/Ctrl|
+ * |--------+------+------+------+------+------| Hyper| | Meh |------+------+------+------+------+--------|
+ * | LShift | Z | X | C | V | B | | | | N | M | , | . | / | RShift |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | ~L1 | Grv | '" | Left |Rgt/L2| | Up/L2| Down | [ | ] | ~L1 |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | App | Home | | PgUp |Ctrl/Esc|
+ * ,------|------|------| |------+--------+------.
+ * | | | End | | PgDn | | |
+ * |Backsp|Delete|------| |------| Enter |Space |
+ * | ace | | LAlt | |TabCtl| | |
+ * `--------------------' `----------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_EQL, KC_1, KC_2, KC_3, KC_4, KC_5, KC_LGUI,
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, TG(1),
+ CTL_T(KC_ESC), KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, ALL_T(KC_NO),
+ KC_FN1, KC_GRV, KC_QUOT,KC_LEFT, LT(MDIA, KC_RGHT),
+ KC_APP, KC_HOME,
+ KC_END,
+ KC_BSPC,KC_DELT,KC_LALT,
+ // right hand
+ TG(3), KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
+ TG(2), KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSLS,
+ KC_H, KC_J, KC_K, KC_L, KC_SCLN, CTL_T(KC_QUOT),
+ MEH_T(KC_NO),KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH, KC_RSFT,
+ LT(MDIA, KC_UP), KC_DOWN,KC_LBRC,KC_RBRC, KC_FN1,
+ KC_PGUP, CTL_T(KC_ESC),
+ KC_PGDN,
+ CTL_T(KC_TAB),KC_ENT, KC_SPC
+ ),
+/* Keymap 1: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | . | 0 | = | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | Calc |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[SYMB] = KEYMAP(
+ // left hand
+ KC_TRNS,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS,KC_EXLM,KC_AT, KC_LCBR,KC_RCBR,KC_PIPE,KC_TRNS,
+ KC_TRNS,KC_HASH,KC_DLR, KC_LPRN,KC_RPRN,KC_GRV,
+ KC_TRNS,KC_PERC,KC_CIRC,KC_LBRC,KC_RBRC,KC_TILD,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_UP, KC_7, KC_8, KC_9, KC_ASTR, KC_F12,
+ KC_DOWN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS,
+ KC_TRNS, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS, KC_TRNS,
+ KC_TRNS,KC_DOT, KC_0, KC_EQL, KC_TRNS,
+ KC_TRNS, KC_CALC,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/* Keymap 2: Media and mouse keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | Rclk | Lclk | | | | | | Lclk | Rclk | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | |MsLeft| MsUp |MsDown|MsRght|------| |------|MsLeft|MsDown| MsUp |MsRght| | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | | | | | | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | Lclk | Rclk | | | | | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | Prev | |VolUp | |
+ * ,------|------|------| |------+------+------.
+ * | | | Play | | Mute |Brwser|Brwser|
+ * | Lclk | Rclk |------| |------|Fwd |Back |
+ * | | | Next | |VolDn | | |
+ * `--------------------' `--------------------'
+ */
+// MEDIA AND MOUSE
+KEYMAP(
+ RESET, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN2, KC_BTN1, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_U, KC_MS_D, KC_MS_R,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_MPRV,
+ KC_MPLY,
+ KC_BTN1, KC_BTN2, KC_MNXT,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_MS_L, KC_MS_D, KC_MS_U, KC_MS_R, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_VOLU, KC_TRNS,
+ KC_MUTE,
+ KC_VOLD, KC_WBAK, KC_WFWD
+),
+
+/* Keymap 4: Steno for Plover from https://github.com/shayneholmes/tmk_keyboard/commit/11290f8489013018f778627db725160c745e75bd
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | 1 | 2 | 3 | 4 | 5 | | | | 6 | 7 | 8 | 9 | 0 | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | q | w | e | r | t |------| |------| y | u | i | o | p | [ |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | a | s | d | f | g | | | | h | j | k | l | ; | ' |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | | | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | c | v |------| |------| n | m |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+
+[PLVR] = KEYMAP( // layout: layer 4: Steno for Plover
+ // left hand
+ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+ KC_NO, KC_1, KC_2, KC_3, KC_4, KC_5, KC_NO,
+ KC_NO, KC_Q, KC_W, KC_E, KC_R, KC_T,
+ KC_NO, KC_A, KC_S, KC_D, KC_F, KC_G, KC_NO,
+ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+ KC_FN4, KC_NO,
+ KC_NO,
+ KC_C, KC_V, KC_NO,
+ // right hand
+ KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_TRNS,
+ KC_NO, KC_6, KC_7, KC_8, KC_9, KC_0, KC_TRNS,
+ KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC,
+ KC_NO, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT,
+ KC_TRNS, KC_TRNS, KC_NO, KC_NO, KC_NO,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_NO, KC_N, KC_M
+),
+
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(SYMB) // FN1 - Momentary Layer 1 (Symbols)
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case 1:
+ ergodox_right_led_1_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/dvorak/dvorak.png b/keyboards/ergodox_ez/keymaps/dvorak/dvorak.png
new file mode 100644
index 000000000..cb8316309
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/dvorak/dvorak.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/dvorak/keymap.c b/keyboards/ergodox_ez/keymaps/dvorak/keymap.c
new file mode 100644
index 000000000..22947327d
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/dvorak/keymap.c
@@ -0,0 +1,184 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define BASE 0 // default layer
+#define SYMB 1 // symbols
+#define MDIA 2 // media keys
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | = | 1 | 2 | 3 | 4 | 5 | LEFT | | RIGHT| 6 | 7 | 8 | 9 | 0 | \ |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Del | ' | , | . | P | Y | L1 | | L1 | F | G | C | R | L | / |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | BkSp | A | O | E | U | I |------| |------| D | H | T | N |S / L2| - |
+ * |--------+------+------+------+------+------| Hyper| | Meh |------+------+------+------+------+--------|
+ * | LShift |:/Ctrl| Q | J | K | X | | | | B | M | W | V |Z/Ctrl| RShift |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * |Grv/L1| '" |AltShf| Left | Right| | Up | Down | [ | ] | ~L1 |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | App | LGui | | Alt |Ctrl/Esc|
+ * ,------|------|------| |------+--------+------.
+ * | | | Home | | PgUp | | |
+ * | Space|Backsp|------| |------| Tab |Enter |
+ * | |ace | End | | PgDn | | |
+ * `--------------------' `----------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_EQL, KC_1, KC_2, KC_3, KC_4, KC_5, KC_LEFT,
+ KC_DELT, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, TG(1),
+ KC_BSPC, KC_A, KC_O, KC_E, KC_U, KC_I,
+ KC_LSFT, CTL_T(KC_SCLN), KC_Q, KC_J, KC_K, KC_X, ALL_T(KC_NO),
+ LT(SYMB,KC_GRV),KC_QUOT, LALT(KC_LSFT), KC_LEFT,KC_RGHT,
+ ALT_T(KC_APP), KC_LGUI,
+ KC_HOME,
+ KC_SPC,KC_BSPC,KC_END,
+ // right hand
+ KC_RGHT, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSLS,
+ TG(1), KC_F, KC_G, KC_C, KC_R, KC_L, KC_SLSH,
+ KC_D, KC_H, KC_T, KC_N, LT(MDIA, KC_S), KC_MINS,
+ MEH_T(KC_NO),KC_B, KC_M, KC_W, KC_V, CTL_T(KC_Z), KC_RSFT,
+ KC_UP, KC_DOWN,KC_LBRC,KC_RBRC, KC_FN1,
+ KC_LALT, CTL_T(KC_ESC),
+ KC_PGUP,
+ KC_PGDN,KC_TAB, KC_ENT
+ ),
+/* Keymap 1: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | . | 0 | = | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[SYMB] = KEYMAP(
+ // left hand
+ KC_TRNS,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS,KC_EXLM,KC_AT, KC_LCBR,KC_RCBR,KC_PIPE,KC_TRNS,
+ KC_TRNS,KC_HASH,KC_DLR, KC_LPRN,KC_RPRN,KC_GRV,
+ KC_TRNS,KC_PERC,KC_CIRC,KC_LBRC,KC_RBRC,KC_TILD,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_UP, KC_7, KC_8, KC_9, KC_ASTR, KC_F12,
+ KC_DOWN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS,
+ KC_TRNS, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS, KC_TRNS,
+ KC_TRNS,KC_DOT, KC_0, KC_EQL, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/* Keymap 2: Media and mouse keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | MsUp | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | |MsLeft|MsDown|MsRght| |------| |------| | | | | | Play |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | | | | Prev | Next | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | Lclk | Rclk | |VolUp |VolDn | Mute | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | |Brwser|
+ * | | |------| |------| |Back |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// MEDIA AND MOUSE
+KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MPRV, KC_MNXT, KC_TRNS, KC_TRNS,
+ KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_WBAK
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(SYMB) // FN1 - Momentary Layer 1 (Symbols)
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case 1:
+ ergodox_right_led_1_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/dvorak_intl_squisher/keyboard-layout0.png b/keyboards/ergodox_ez/keymaps/dvorak_intl_squisher/keyboard-layout0.png
new file mode 100644
index 000000000..6a36f9bfa
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/dvorak_intl_squisher/keyboard-layout0.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/dvorak_intl_squisher/keyboard-layout1.png b/keyboards/ergodox_ez/keymaps/dvorak_intl_squisher/keyboard-layout1.png
new file mode 100644
index 000000000..c6e6d913c
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/dvorak_intl_squisher/keyboard-layout1.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/dvorak_intl_squisher/keyboard-layout2.png b/keyboards/ergodox_ez/keymaps/dvorak_intl_squisher/keyboard-layout2.png
new file mode 100644
index 000000000..23f56ff4c
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/dvorak_intl_squisher/keyboard-layout2.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/dvorak_intl_squisher/keymap.c b/keyboards/ergodox_ez/keymaps/dvorak_intl_squisher/keymap.c
new file mode 100644
index 000000000..82f55b4bc
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/dvorak_intl_squisher/keymap.c
@@ -0,0 +1,185 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define BASE 0 // default layer
+#define SYMB 1 // symbols
+#define MDIA 2 // media keys
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | = | 1 | 2 | 3 | 4 | 5 | BrBck| | Play | 6 | 7 | 8 | 9 | 0 | \ / L2 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Esc | ' | , | . | P | Y | Del | | Ins | F | G | C | R | L | / |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | BkSp | A | O | E | U | I |------| |------| D | H | T | N | S | - |
+ * |--------+------+------+------+------+------| Hyper| | Meh |------+------+------+------+------+--------|
+ * | LShift |:/Ctrl| Q | J | K | X | | | | B | M | W | V |Z/Ctrl| RShift |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * |Grv/L1| LAlt | LGui | Left | Right| | Up | Down | [ | ] | ~L1 |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,---------------.
+ * | App | L1 | | L2 |PrntScr |
+ * ,------|------|------| |------+--------+------.
+ * | | | Home | | PgUp | | |
+ * | Space| Tab |------| |------| AltShf |Enter |
+ * | | | End | | PgDn | | |
+ * `--------------------' `----------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_EQL, KC_1, KC_2, KC_3, KC_4, KC_5, KC_WBAK,
+ KC_ESC, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, KC_DELT,
+ KC_BSPC, KC_A, KC_O, KC_E, KC_U, KC_I,
+ KC_LSFT, CTL_T(KC_SCLN), KC_Q, KC_J, KC_K, KC_X, ALL_T(KC_NO),
+ LT(SYMB,KC_GRV),KC_LALT, KC_LGUI, KC_LEFT,KC_RGHT,
+ CTL_T(KC_APP), TG(1),
+ KC_HOME,
+ KC_SPC,KC_TAB,KC_END,
+ // right hand
+ KC_MPLY, KC_6, KC_7, KC_8, KC_9, KC_0, LT(MDIA, KC_BSLS),
+ KC_INS, KC_F, KC_G, KC_C, KC_R, KC_L, KC_SLSH,
+ KC_D, KC_H, KC_T, KC_N, KC_S, KC_MINS,
+ MEH_T(KC_NO),KC_B, KC_M, KC_W, KC_V, CTL_T(KC_Z), KC_RSFT,
+ KC_UP, KC_DOWN,KC_LBRC,KC_RBRC, KC_FN1,
+ TG(2), KC_PSCREEN,
+ KC_PGUP,
+ KC_PGDN,RALT(KC_RSFT), KC_ENT
+ ),
+/* Keymap 1: Symbol & Media Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | Prev | Next | | | . | 0 | = | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | |VolUp | | |
+ * | | |------| |------| Mute | |
+ * | | | | |VolDn | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[SYMB] = KEYMAP(
+ // left hand
+ KC_TRNS,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS,KC_EXLM,KC_AT, KC_LCBR,KC_RCBR,KC_PIPE,KC_TRNS,
+ KC_TRNS,KC_HASH,KC_DLR, KC_LPRN,KC_RPRN,KC_GRV,
+ KC_TRNS,KC_PERC,KC_CIRC,KC_LBRC,KC_RBRC,KC_TILD,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_MPRV,KC_MNXT,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_UP, KC_7, KC_8, KC_9, KC_ASTR, KC_F12,
+ KC_DOWN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS,
+ KC_TRNS, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS, KC_TRNS,
+ KC_TRNS,KC_DOT, KC_0, KC_EQL, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_VOLU,
+ KC_VOLD, KC_MUTE, KC_TRNS
+),
+/* Keymap 2: QWERTY Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | Q | W | E | R | T | | | | Y | U | I | O | P | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | A | S | D | F | G |------| |------| H | J | K | L | ; | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | |Z/Ctrl| X | C | V | B | | | | N | M | , | . |//Ctrl| |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | | | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// MEDIA AND MOUSE
+KEYMAP( // layer 0 : default
+ // left hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_TRNS,
+ KC_TRNS, KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_TRNS, CTL_T(KC_Z), KC_X, KC_C, KC_V, KC_B, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_TRNS,
+ KC_H, KC_J, KC_K, KC_L, LT(MDIA, KC_SCLN),KC_TRNS,
+ KC_TRNS, KC_N, KC_M, KC_COMM,KC_DOT, CTL_T(KC_SLSH), KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+ ),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(SYMB) // FN1 - Momentary Layer 1 (Symbols)
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case 1:
+ ergodox_right_led_1_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/dvorak_intl_squisher/readme.md b/keyboards/ergodox_ez/keymaps/dvorak_intl_squisher/readme.md
new file mode 100644
index 000000000..984106ff4
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/dvorak_intl_squisher/readme.md
@@ -0,0 +1,29 @@
+# ErgoDox EZ Dvorak International Squisher
+
+Dvorak layout adjusted with several (linux) applications in mind:
+
+* Easier Escape for VIM
+* Windows/Super key for awesome WM
+* Alt+Shift for international characters
+* PrintScreen for sys-rq
+* Insert for the X11 clip-board
+
+Major layer changes:
+
+* Common multimedia keys are integrated into layer 0, less common into layer 1
+* No mouse keys
+* Layer 2 is qwerty (for easier gaming & less fortunate keyboard users)
+
+Known issues:
+
+* Alt+Shift does not work reliably (depends on the X11 kb layout? Not
+ entirely clear...)
+
+![layer0](keyboard-layout0.png)
+![layer1](keyboard-layout1.png)
+![layer2](keyboard-layout2.png)
+
+## Changelog
+
+* 2016-03-29
+ * Initial release
diff --git a/keyboards/ergodox_ez/keymaps/dvorak_spanish/keymap.c b/keyboards/ergodox_ez/keymaps/dvorak_spanish/keymap.c
new file mode 100755
index 000000000..6eb864b44
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/dvorak_spanish/keymap.c
@@ -0,0 +1,284 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+/******************************************************************************************
+ * SPANISH DVORAK LAYOUT (see http://djelibeibi.unex.es/dvorak/)
+ * Layer 1: auxiliary keys
+ * Layer 2: full qwerty layout
+ ******************************************************************************************
+ * IMPORTANT: Software layout must be set to SPANISH QWERTY to work properly
+ *****************************************************************************************/
+
+// LAYERS
+#define BASE 0 // dvorak layout (default)
+#define AUX 1 // auxiliary keys
+#define QWERTY 2 // qwerty layout
+
+// MACROS
+#define OBRACE 0 // key { or shift
+#define CBRACE 1 // key } or shift
+#define OBRACK 2 // key [ or left alt
+#define CBRACK 3 // key ] or left alt
+#define CAPS 4 // caps lock
+
+// LEDS
+#define USB_LED_NUM_LOCK 0
+#define USB_LED_CAPS_LOCK 1
+#define USB_LED_SCROLL_LOCK 2
+#define USB_LED_COMPOSE 3
+#define USB_LED_KANA 4
+
+// TIMERS
+#define KEY_TAP_FAST 85
+#define KEY_TAP_SLOW 95
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Base layer
+ * Keys with double values (like Esc/Ctrl) correspond to the 'tapped' key and the 'held' key, respectively
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | \ | 1 | 2 | 3 | 4 | 5 | <> | | ¡ | 6 | 7 | 8 | 9 | 0 | ' |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | F1/~L1 | . | , | Ñ | P | Y |MEH_T | | L1 | F | G | C | H | L |ALL_T/+ |
+ * |--------+------+------+------+------+------| DEL | | ~L1 |------+------+------+------+------+--------|
+ * |Esc/Ctrl| A | O | E | U | I |------| |------| D | R | T | N | S |'/RCtrl |
+ * |--------+------+------+------+------+------| LGUI | | RALT |------+------+------+------+------+--------|
+ * | {/LSft | - | Q | J | K | X | | | | B | M | W | V | Z | }/RSft |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * |[/LALT| HOME |PGDOWN| PGUP | END | | LEFT | DOWN | UP |RIGHT |]/LALT|
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * |F5/CAG|F6/~L1| |F7/~L1|F8/CAG|
+ * ,------|------|------| |------+--------+------.
+ * | | |F4/CA | |F11/CA| | |
+ * | ENTER| TAB |------| |------| BSPC | SPACE|
+ * | | |F3/SA | |F12/SA| | |
+ * `--------------------' `----------------------'
+ * CAG = CTRL-ALT-GUI
+ * CA = CTRL-ALT
+ * SA = SHIFT-ALT
+ *
+ */
+[BASE] = KEYMAP(
+ // left hand
+ KC_GRAVE, KC_1, KC_2, KC_3, KC_4, KC_5, KC_NONUS_BSLASH,
+ LT(AUX, KC_F1), KC_DOT, KC_COMM,KC_SCLN,KC_P, KC_Y, MEH_T(KC_DEL),
+ CTL_T(KC_ESC), KC_A, KC_O, KC_E, KC_U, KC_I,
+ M(OBRACE), KC_SLSH,KC_Q, KC_J, KC_K, KC_X, KC_LGUI,
+ M(OBRACK), KC_HOME,KC_PGDN,KC_PGUP,KC_END,
+ LCAG_T(KC_F5), LT(AUX, KC_F6),
+ MT((MOD_LALT | MOD_LCTL), KC_F4),
+ KC_ENT,KC_TAB,MT((MOD_LALT | MOD_LSFT), KC_F3),
+ // right hand
+ KC_EQL, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINUS,
+ KC_FN1, KC_F, KC_G, KC_C, KC_H, KC_L, ALL_T(KC_RBRACKET),
+ KC_D, KC_R, KC_T, KC_N, KC_S, CTL_T(KC_QUOTE),
+ KC_RALT, KC_B, KC_M, KC_W, KC_V, KC_Z, M(CBRACE),
+ KC_LEFT,KC_DOWN,KC_UP, KC_RGHT,M(CBRACK),
+ LT(AUX, KC_F7), LCAG_T(KC_F8),
+ MT((MOD_LALT | MOD_LCTL), KC_F11),
+ MT((MOD_LALT | MOD_LSFT), KC_F12),KC_BSPC, KC_SPC
+ ),
+/* Keymap 1: Aux layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | SLEEP | PWR | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | < | > | MsUp | | | | | ~L0 | | 7 | 8 | 9 | * | `^ |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | |MsLeft|MsDown|MsRght| |------| |------| | 4 | 5 | 6 | + | Ç |
+ * |--------+------+------+------+------+------| | |PSCR |------+------+------+------+------+--------|
+ * |CAPSLOCK| | | | | | | | | | 1 | 2 | 3 | / | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * |CTRL-S|CTRL-Z|CTRL-X|CTRL-C|CTRL-V| | | . | 0 | = | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | Play |
+ * ,------|------|------| |------+------+------.
+ * | | | | | VolUp| | |
+ * | Lclk | Rclk |------| |------| Prev | Next |
+ * | | | L2 | | VolDn| | |
+ * `--------------------' `--------------------'
+ */
+[AUX] = KEYMAP(
+ // left hand
+ KC_NO , KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_SLEP,
+ KC_TRNS, KC_NONUS_BSLASH, LSFT(KC_NONUS_BSLASH), KC_MS_U, KC_NO, KC_NO, KC_NO,
+ KC_NO , KC_NO, KC_MS_L, KC_MS_D, KC_MS_R, KC_NO ,
+ M(CAPS), KC_NO, KC_NO , KC_NO , KC_NO , KC_NO , KC_NO,
+ LCTL(KC_S), LCTL(KC_Z), LCTL(KC_X), LCTL(KC_C), LCTL(KC_V),
+ KC_NO , KC_TRNS,
+ KC_NO,
+ KC_BTN1, KC_BTN2, TG(QWERTY),
+ // right hand
+ KC_PWR, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_NO, KC_7, KC_8, KC_9, KC_PAST, KC_LBRACKET,
+ KC_NO, KC_4, KC_5, KC_6, KC_PPLS, KC_BSLASH,
+ KC_PSCR, KC_NO, KC_1, KC_2, KC_3, KC_PSLS, KC_NO,
+ KC_NO ,KC_DOT, KC_0, KC_PEQL, KC_NO,
+ KC_TRNS, KC_MPLY,
+ KC_VOLU,
+ KC_VOLD, KC_MPRV, KC_MNXT
+),
+/* Keymap 2: QWERTY layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | \ | 1 | 2 | 3 | 4 | 5 | <> | | ¡ | 6 | 7 | 8 | 9 | 0 | ' |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | TRANS | Q | W | E | R | T |MEH_T | | TRANS| Y | U | I | O | P |ALL_T/+ |
+ * |--------+------+------+------+------+------| DEL | | |------+------+------+------+------+--------|
+ * |Esc/Ctrl| A | S | D | F | G |------| |------| H | J | K | L | Ñ |'/RCtrl |
+ * |--------+------+------+------+------+------| LGUI | | RALT |------+------+------+------+------+--------|
+ * | {/LSft | Z | X | C | V | B | | | | N | M | , | . | - | }/RSft |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * |[/LALT| HOME |PGDOWN| PGUP | END | | LEFT | DOWN | UP |RIGHT |]/LALT|
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * |F5/CAG| TRANS| | TRANS|F8/CAG|
+ * ,------|------|------| |------+--------+------.
+ * | | |F4/CA | |F11/CA| | |
+ * | ENTER| TAB |------| |------| BSPC | SPACE|
+ * | | | TRANS| |F12/SA| | |
+ * `--------------------' `----------------------'
+ * CAG = CTRL-ALT-GUI
+ * CA = CTRL-ALT
+ * SA = SHIFT-ALT
+ *
+ */
+[QWERTY] = KEYMAP(
+ // left hand
+ KC_GRAVE, KC_1, KC_2, KC_3, KC_4, KC_5, KC_NONUS_BSLASH,
+ KC_TRNS, KC_Q, KC_W, KC_E, KC_R, KC_T, MEH_T(KC_DEL),
+ CTL_T(KC_ESC), KC_A, KC_S, KC_D, KC_F, KC_G,
+ M(OBRACE), KC_Z, KC_X, KC_C, KC_V, KC_B, KC_LGUI,
+ M(OBRACK), KC_HOME,KC_PGDN,KC_PGUP,KC_END,
+ LCAG_T(KC_F5), KC_TRNS,
+ MT((MOD_LALT | MOD_LCTL), KC_F4),
+ KC_ENT,KC_TAB,KC_TRNS,
+ // right hand
+ KC_EQL, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINUS,
+ KC_TRNS, KC_Y, KC_U, KC_I, KC_O, KC_P, ALL_T(KC_RBRACKET),
+ KC_H, KC_J, KC_K, KC_L, KC_SCLN,CTL_T(KC_QUOTE),
+ KC_RALT, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH,M(CBRACE),
+ KC_LEFT,KC_DOWN,KC_UP, KC_RGHT,M(CBRACK),
+ KC_TRNS, LCAG_T(KC_F8),
+ MT((MOD_LALT | MOD_LCTL), KC_F11),
+ MT((MOD_LALT | MOD_LSFT), KC_F12),KC_BSPC, KC_SPC
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(AUX) // FN1 - Momentary Layer 1 (Aux)
+};
+
+static uint16_t key_timer;
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ switch(id) {
+ case OBRACE: {
+ if (record->event.pressed) {
+ key_timer = timer_read();
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ if (timer_elapsed(key_timer) < KEY_TAP_SLOW) {
+ register_code(KC_RALT);
+ register_code(KC_QUOTE);
+ unregister_code(KC_QUOTE);
+ unregister_code(KC_RALT);
+ }
+ }
+ break;
+ }
+ case CBRACE: {
+ if (record->event.pressed) {
+ key_timer = timer_read();
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ if (timer_elapsed(key_timer) < KEY_TAP_SLOW) {
+ register_code(KC_RALT);
+ register_code(KC_BSLS);
+ unregister_code(KC_BSLS);
+ unregister_code(KC_RALT);
+ }
+ }
+ break;
+ }
+ case OBRACK: {
+ if (record->event.pressed) {
+ key_timer = timer_read();
+ register_code(KC_LALT);
+ } else {
+ unregister_code(KC_LALT);
+ if (timer_elapsed(key_timer) < KEY_TAP_SLOW) {
+ register_code(KC_RALT);
+ register_code(KC_LBRACKET);
+ unregister_code(KC_LBRACKET);
+ unregister_code(KC_RALT);
+ }
+ }
+ break;
+ }
+ case CBRACK: {
+ if (record->event.pressed) {
+ key_timer = timer_read();
+ register_code(KC_LALT);
+ } else {
+ unregister_code(KC_LALT);
+ if (timer_elapsed(key_timer) < KEY_TAP_SLOW) {
+ register_code(KC_RALT);
+ register_code(KC_RBRACKET);
+ unregister_code(KC_RBRACKET);
+ unregister_code(KC_RALT);
+ }
+ }
+ break;
+ }
+ case CAPS: {
+ if (record->event.pressed) {
+ register_code(KC_CAPSLOCK);
+ } else {
+ unregister_code(KC_CAPSLOCK);
+ }
+ break;
+ }
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ case 1:
+ ergodox_right_led_3_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+ // Turn the caps lock led on
+ if (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) {
+ ergodox_right_led_1_on();
+ }
+
+}
+
diff --git a/keyboards/ergodox_ez/keymaps/dvorak_spanish/readme.md b/keyboards/ergodox_ez/keymaps/dvorak_spanish/readme.md
new file mode 100644
index 000000000..e075e3cd7
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/dvorak_spanish/readme.md
@@ -0,0 +1,99 @@
+# Ergodox Spanish Dvorak Layout
+ * See spanish dvorak layout [here](http://djelibeibi.unex.es/dvorak/)
+ * Software layout must be set to SPANISH QWERTY to work properly
+
+## Keymap Layers
+ - L0: spanish dvorak with some customizations (see layout below)
+ - L1: auxiliary keys (includes qwerty shortcuts, numpad...)
+ - L2: qwerty layout with customizations
+
+
+### Keymap 0: Base layer
+Keys with double values (like Esc/Ctrl) correspond to the 'tapped' key and the 'held' key, respectively
+
+<pre><code>
+
+,--------------------------------------------------. ,--------------------------------------------------.
+| \ | 1 | 2 | 3 | 4 | 5 | <> | | ¡ | 6 | 7 | 8 | 9 | 0 | ' |
+|--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+| F1/~L1 | . | , | Ñ | P | Y |MEH_T | | L1 | F | G | C | H | L |ALL_T/+ |
+|--------+------+------+------+------+------| DEL | | ~L1 |------+------+------+------+------+--------|
+|Esc/Ctrl| A | O | E | U | I |------| |------| D | R | T | N | S |'/RCtrl |
+|--------+------+------+------+------+------| LGUI | | RALT |------+------+------+------+------+--------|
+| {/LSft | - | Q | J | K | X | | | | B | M | W | V | Z | }/RSft |
+'--------+------+------+------+------+-------------' '-------------+------+------+------+------+--------'
+ |[/LALT| HOME |PGDOWN| PGUP | END | | LEFT | DOWN | UP |RIGHT |]/LALT|
+ '----------------------------------' '----------------------------------'
+ ,-------------. ,-------------.
+ |F5/CAG|F6/~L1| |F7/~L1|F8/CAG|
+ ,------|------|------| |------+--------+------.
+ | | |F4/CA | |F11/CA| | |
+ | ENTER| TAB |------| |------| BSPC | SPACE|
+ | | |F3/SA | |F12/SA| | |
+ '--------------------' '----------------------'
+ CAG = CTRL-ALT-GUI
+ CA = CTRL-ALT
+ SA = SHIFT-ALT
+
+</pre></code>
+
+### Keymap 1: Aux layer
+
+<pre><code>
+
+,--------------------------------------------------. ,--------------------------------------------------.
+| | F1 | F2 | F3 | F4 | F5 | SLEEP| | PWR | F6 | F7 | F8 | F9 | F10 | F11 |
+|--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+| | < | > | MsUp | | | | | ~L0 | | 7 | 8 | 9 | * | '^ |
+|--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+| | |MsLeft|MsDown|MsRght| |------| |------| | 4 | 5 | 6 | + | Ç |
+|--------+------+------+------+------+------| | |PSCR |------+------+------+------+------+--------|
+|CAPSLOCK| | | | | | | | | | 1 | 2 | 3 | / | |
+'--------+------+------+------+------+-------------' '-------------+------+------+------+------+--------'
+ |CTRL-S|CTRL-Z|CTRL-X|CTRL-C|CTRL-V| | | . | 0 | = | |
+ '----------------------------------' '----------------------------------'
+ ,-------------. ,-------------.
+ | | | | | Play |
+ ,------|------|------| |------+------+------.
+ | | | | | VolUp| | |
+ | Lclk | Rclk |------| |------| Prev | Next |
+ | | | L2 | | VolDn| | |
+ '--------------------' '--------------------'
+
+</pre></code>
+
+### Keymap 2: QWERTY layer
+
+<pre><code>
+
+,--------------------------------------------------. ,--------------------------------------------------.
+| \ | 1 | 2 | 3 | 4 | 5 | <> | | ¡ | 6 | 7 | 8 | 9 | 0 | ' |
+|--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+| TRANS | Q | W | E | R | T |MEH_T | | TRANS| Y | U | I | O | P |ALL_T/+ |
+|--------+------+------+------+------+------| DEL | | |------+------+------+------+------+--------|
+|Esc/Ctrl| A | S | D | F | G |------| |------| H | J | K | L | Ñ |'/RCtrl |
+|--------+------+------+------+------+------| LGUI | | RALT |------+------+------+------+------+--------|
+| {/LSft | Z | X | C | V | B | | | | N | M | , | . | - | }/RSft |
+'--------+------+------+------+------+-------------' '-------------+------+------+------+------+--------'
+ |[/LALT| HOME |PGDOWN| PGUP | END | | LEFT | DOWN | UP |RIGHT |]/LALT|
+ '----------------------------------' '----------------------------------'
+ ,-------------. ,-------------.
+ |F5/CAG| TRANS| | TRANS|F8/CAG|
+ ,------|------|------| |------+--------+------.
+ | | |F4/CA | |F11/CA| | |
+ | ENTER| TAB |------| |------| BSPC | SPACE|
+ | | | TRANS| |F12/SA| | |
+ '--------------------' '----------------------'
+ CAG = CTRL-ALT-GUI
+ CA = CTRL-ALT
+ SA = SHIFT-ALT
+
+</pre></code>
+
+
+## Generation of .hex file
+> [Download scripts from here](https://github.com/johgh/keyboard/tree/master/ergodox)
+
+> Execute install.sh and generate.sh scripts.
+
+> Flash with `teensy_loader` binary (should be installed from previous step)
diff --git a/keyboards/ergodox_ez/keymaps/emacs_osx_dk/default_highres.png b/keyboards/ergodox_ez/keymaps/emacs_osx_dk/default_highres.png
new file mode 100644
index 000000000..1d2583740
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/emacs_osx_dk/default_highres.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/emacs_osx_dk/keymap.c b/keyboards/ergodox_ez/keymaps/emacs_osx_dk/keymap.c
new file mode 100644
index 000000000..1d8e66a08
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/emacs_osx_dk/keymap.c
@@ -0,0 +1,184 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define BASE 0 // default layer
+#define SYMB 1 // symbols
+#define MDIA 2 // media keys
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | Grv | 1 | 2 | 3 | 4 | 5 | L1 | | L2 | 6 | 7 | 8 | 9 | 0 | = |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Tab | Q | W | E | R | T | [ | | ] | Y | U | I | O | P | - |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | \/LCtrl| A | S | D | F | G |------| |------| H | J | K | L | ; |'/RCtrl |
+ * |--------+------+------+------+------+------| RAlt | | RAlt |------+------+------+------+------+--------|
+ * | LShift | Z | X | C | V | B | | | | N | M | , | . | / | RShift |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | ~L1 | LCtrl| Left| Right| LAlt | | LAlt | Up | Down | RCtrl| ~L2 |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | Del | Ins | | Esc | App |
+ * ,------|------|------| |------+--------+------.
+ * | | | Home | | PgUp | | |
+ * | Space|Backsp|------| |------| LGui |Enter |
+ * | |ace | End | | PgDn | | |
+ * `--------------------' `----------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, TG(SYMB),
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_LBRC,
+ CTL_T(KC_BSLS), KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_RALT,
+ MO(SYMB), KC_LCTRL, KC_LEFT,KC_RGHT,KC_LALT,
+ KC_DELT,KC_INS,
+ KC_HOME,
+ KC_SPC,KC_BSPC,KC_END,
+ // right hand
+ TG(MDIA), KC_6, KC_7, KC_8, KC_9, KC_0, KC_EQL,
+ KC_RBRC, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_MINS,
+ KC_H, KC_J, KC_K, KC_L, KC_SCLN, CTL_T(KC_QUOT),
+ KC_RALT, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH, KC_RSFT,
+ KC_LALT,KC_UP, KC_DOWN,KC_RCTRL, MO(MDIA),
+ KC_ESC, KC_APP,
+ KC_PGUP,
+ KC_PGDN, KC_LGUI, KC_ENT
+ ),
+/* Keymap 1: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | 0 | 0 | . | = | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[SYMB] = KEYMAP(
+ // left hand
+ KC_TRNS,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS,KC_EXLM,KC_AT, KC_LCBR,KC_RCBR,KC_PIPE,KC_TRNS,
+ KC_TRNS,KC_HASH,KC_DLR, KC_LPRN,KC_RPRN,KC_GRV,
+ KC_TRNS,KC_PERC,KC_CIRC,KC_LBRC,KC_RBRC,KC_TILD,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_UP, KC_7, KC_8, KC_9, KC_ASTR, KC_F12,
+ KC_DOWN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS,
+ KC_TRNS, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS, KC_TRNS,
+ KC_0, KC_0, KC_DOT, KC_EQL, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/* Keymap 2: Media and mouse keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | MsUp | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | |MsLeft|MsDown|MsRght| |------| |------| | | | | | Play |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | | | | Prev | Next | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | Lclk | Rclk | |VolUp |VolDn | Mute | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | |Brwser|
+ * | | |------| |------| |Back |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// MEDIA AND MOUSE
+[MDIA] = KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MPRV, KC_MNXT, KC_TRNS, KC_TRNS,
+ KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_WBAK
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(SYMB) // FN1 - Momentary Layer 1 (Symbols)
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case 1:
+ ergodox_right_led_1_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/emacs_osx_dk/readme.md b/keyboards/ergodox_ez/keymaps/emacs_osx_dk/readme.md
new file mode 100644
index 000000000..4839988d9
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/emacs_osx_dk/readme.md
@@ -0,0 +1,10 @@
+# ErgoDox EZ Emacs-OSX-DeadKeys Configuration
+
+Since I'm an Emacs user, ctrl keys are very important and gets a placement where the usual caps_lock is. There
+are an extra pair of ctrls, just in case there where problems with the holding one's, but not as comfortable.
+
+Gui button takes a predominant place on the thumb cluster, as I'm using a mac os x and it relies heavily on it.
+
+Finally there is also two Right Alts to easily access to accented letters of the spanish alphabet.
+
+![Default](default_highres.png)
diff --git a/keyboards/ergodox_ez/keymaps/erez_experimental/Makefile b/keyboards/ergodox_ez/keymaps/erez_experimental/Makefile
new file mode 100644
index 000000000..b673c5ce5
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/erez_experimental/Makefile
@@ -0,0 +1,9 @@
+# Having a file like this allows you to override Makefile definitions
+# for your own particular keymap
+
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+COMMAND_ENABLE = no # Commands for debug and configuration
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif
diff --git a/keyboards/ergodox_ez/keymaps/erez_experimental/config.h b/keyboards/ergodox_ez/keymaps/erez_experimental/config.h
new file mode 100644
index 000000000..e5d7fe188
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/erez_experimental/config.h
@@ -0,0 +1,12 @@
+#ifndef CONFIG_USER_H
+#define CONFIG_USER_H
+
+#include "../../config.h"
+
+#define ONESHOT_TAP_TOGGLE 2
+#define ONESHOT_TIMEOUT 300
+
+#undef LEADER_TIMEOUT
+#define LEADER_TIMEOUT 300
+
+#endif
diff --git a/keyboards/ergodox_ez/keymaps/erez_experimental/keymap.c b/keyboards/ergodox_ez/keymaps/erez_experimental/keymap.c
new file mode 100644
index 000000000..04ad2a816
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/erez_experimental/keymap.c
@@ -0,0 +1,199 @@
+#include <keymap_extras/keymap_colemak.h>
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define BASE 0 // default layer
+#define SYMB 1 // symbols
+#define MDIA 2 // media keys
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | = | 1 | 2 | 3 | 4 | 5 | LEFT | | RIGHT| 6 | 7 | 8 | 9 | 0 | - |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Del | Q | W | E | R | T | L1 | | L1 | Y | U | I | O | P | \ |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | BkSp | A | S | D | F | G |------| |------| H | Alt/J| K | L |; / L2| LGui/' |
+ * |--------+------+------+------+------+------| Hyper| | Meh |------+------+------+------+------+--------|
+ * |LShift/(|Z/Ctrl| X | C | V | B | [ | | ] | N | M | , | . |//Ctrl|RShift/)|
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * |Grv/L1| '" |AltShf| Left | Right| | Up | Down | [ | ] | -/L1 |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | App | LGui | | Alt |Ctrl/Esc|
+ * ,------|------|------| |------+--------+------.
+ * | | | Home | | PgUp | | |
+ * | Space|Leader|------| |------| Tab/L1 |Enter |
+ * | | | End | | PgDn | | |
+ * `--------------------' `----------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_EQL, KC_1, KC_2, KC_3, KC_4, KC_5, KC_LEFT,
+ KC_DELT, KC_Q, KC_W, KC_E, KC_R, KC_T, TG(SYMB),
+ KC_BSPC, KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_LSPO, CTL_T(KC_Z), KC_X, KC_C, KC_V, KC_B, ALL_T(KC_LBRC),
+ LT(SYMB,KC_GRV),KC_QUOT, LALT(KC_LSFT), KC_LEFT, KC_RGHT,
+ ALT_T(KC_APP), KC_LGUI,
+ KC_HOME,
+ KC_SPC,KC_LEAD,KC_END,
+ // right hand
+ KC_RGHT, KC_6,KC_7, KC_8, KC_9, KC_0, KC_MINS,
+ TG(SYMB), KC_Y,KC_U, KC_I, KC_O, KC_P, KC_BSLS,
+ KC_H,ALT_T(KC_J),KC_K, KC_L, LT(MDIA,KC_SCLN),GUI_T(KC_QUOT),
+ MEH_T(KC_RBRC),KC_N,KC_M, KC_COMM,KC_DOT, CTL_T(KC_SLSH), KC_RSPC,
+ KC_UP, KC_DOWN,KC_LBRC,KC_RBRC, LT(SYMB,KC_MINS),
+ KC_LALT, CTL_T(KC_ESC),
+ KC_PGUP,
+ KC_PGDN,LT(SYMB, KC_TAB), KC_ENT
+ ),
+/* Keymap 1: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | | | | | | | | | | | | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | 1 | 2 | 3 | 4 | 5 |------| |------| & | _ | - | ; | + | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | 6 | 7 | 8 | 9 | 0 | | | | | | @ | = | % | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | |NxtTab|PrvTab| | | | | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[SYMB] = KEYMAP(
+ // left hand
+ KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS, KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_1, KC_2, KC_3, KC_4, KC_5,
+ KC_TRNS, KC_6, KC_7, KC_8, KC_9, KC_0, KC_TRNS,
+ KC_TRNS, KC_TRNS,KC_TRNS,LCTL(KC_PGUP), LCTL(KC_PGDN),
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_F12,
+ KC_AMPR, KC_UNDS, KC_MINS, CM_SCLN, KC_PLUS, KC_TRNS,
+ KC_TRNS, KC_PIPE, KC_AT, KC_EQL, KC_PERC, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/* Keymap 2: Media and mouse keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | PgUp | Home | End | PgDn | |------| |------| | | | | | Play |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | | | | Prev | Next | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | |VolUp |VolDn | Mute | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | |Brwser|
+ * | | |------| |------| |Back |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// MEDIA AND MOUSE
+[MDIA] = KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_PGUP, KC_HOME, KC_END, KC_PGDN, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MPRV, KC_MNXT, KC_TRNS, KC_TRNS,
+ KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_WBAK
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(SYMB), // FN1 - Momentary Layer 1 (Symbols)
+ [2] = ACTION_MACRO_TAP(0), // Eric Tang's Famous Macro!
+ [3] = ACTION_MACRO_TAP(1) // Eric Tang's Famous Macro!
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+LEADER_EXTERNS();
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case 1:
+ ergodox_right_led_1_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+ LEADER_DICTIONARY() {
+ leading = false;
+ leader_end();
+
+ SEQ_ONE_KEY(KC_W) {
+ register_code(KC_LALT);
+ register_code(KC_F4);
+ unregister_code(KC_F4);
+ unregister_code(KC_LALT);
+ }
+ SEQ_ONE_KEY(KC_O) {
+ register_code(KC_LCTL);
+ register_code(KC_LSFT);
+ register_code(KC_O);
+ unregister_code(KC_O);
+ unregister_code(KC_LSFT);
+ unregister_code(KC_LCTL);
+ }
+ }
+}
+
diff --git a/keyboards/ergodox_ez/keymaps/erez_experimental/readme.md b/keyboards/ergodox_ez/keymaps/erez_experimental/readme.md
new file mode 100644
index 000000000..66acfa187
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/erez_experimental/readme.md
@@ -0,0 +1,51 @@
+# Erez's experimental layout
+
+This is my personal layout which I use to test out ideas which may or may not make it onto the default layout we ship with. It's based off the default layout, with various tweaks.
+
+Changelog:
+
+## May 24, 2016:
+
+* Implements Leader key example
+ * Leader, W sends Alt-F4
+ * Leader, O sends Ctrl-shift-o (a shortcut I use in FrontApp)
+
+## May 8, 2016:
+
+* Makes bottom-right key send minus/underscore when tapped, L1 temporary toggle when held
+* Tweaked the positions of the numbers on the symbol layer. Basically, 12345 are now directly under their number-row counterparts in layer 0. You can imagine pulling the number row down to the home row. And 67890 are directly under 12345 - so it's a matter of just adding 5 and going to the next row (1+5 = 6, 2+5 = 7 and so on).
+* Tweaks media/nav layer
+ * Removes mouse control, as I don't use it
+ * Makes left home row keys PgUp, Home, End, PgDn
+
+## Apr 29, 2016:
+
+* Tweaks the Hyper and Meh key to send brackets when tapped
+* Turns bottom-right key into a minus/underscore (easy to reach with the right pinky)
+
+## Apr 25, 2016:
+
+* Made it so that the right and left Shift keys send opening and closing parens ( ) when tapped
+
+## Feb 11, 2016:
+
+* Updated ASCII legend for thumb clusters
+* Made it so outer left-hand thumb key is L1 momentary toggle
+* Added % and @ to L1
+* Swapped positions for _ and - on L1
+
+## Feb 5, 2016:
+
+* A whole new design for the symbol layer. Specifically:
+ * Put the minus, underscore, and semicolon right in the homerow for the right hand
+ * Parens are in better places for me
+ * The arrow keys now send Ctrl-PgUp and Ctrl-PgDn, for switching browser tabs with the arrows when in symbol layer
+ * Tab (right-hand outer thumb key) now does double duty to toggle symbol layer when held down
+ * Backspace (left-hand outer thumb key) now just toggles symbol layer (I wasn't using it as a backspace)
+
+
+## Jan 19, 2016:
+
+* Made J into dual-action key (Alt when held down), to make Alt-tab more ergonomic.
+* Made ' into dual-action key (Win/Cmd when held down).
+
diff --git a/keyboards/ergodox_ez/keymaps/german-kinergo/keymap.c b/keyboards/ergodox_ez/keymaps/german-kinergo/keymap.c
new file mode 100644
index 000000000..b1cecf0dd
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/german-kinergo/keymap.c
@@ -0,0 +1,210 @@
+// German keymap derived from "german", but more closely resembling the German layout of the Kinesis Ergo Elan.
+//
+// chschmitz, 2016-01-27
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+#include "keymap_german.h"
+
+// Layer names
+#define BASE 0 // default layer
+#define SYMB 1 // symbol layer
+#define MDIA 2 // media keys
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * X'es mark the spots where this is different from the "german" layout which it is based on.
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * |X Esc X| 1 | 2 | 3 | 4 | 5 |X ` X| |XPRSCX| 6 | 7 | 8 | 9 | 0 | ß |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * |X Tab X| Q | W | E | R | T |X L1 X| |X L1 X| Z | U | I | O | P | Ü |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | Caps | A | S | D | F | G |------| |------| H | J | K | L | Ö | Ä/L2 |
+ * |--------+------+------+------+------+------|X L2 X| |X L2 X|------+------+------+------+------+--------|
+ * | LShift | Y | X | C | V | B | | | | N | M | , | . |X - X| RShift |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * |XLGuiX|X ^ X|X < X|XLEFTX|XRIGHT| |XDownX|X Up X|X # X|X + X|XRGuiX|
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * |XCTRLX|XALTX | | Alt |Ctrl/Esc|
+ * ,------+------+------| |------+--------+------.
+ * |XXX |XXX | Home | | PgUp |XXX |XXX |
+ * | Bkspc|Del |------| |------| Enter | Space|
+ * | | | End | | PgDn | | |
+ * `--------------------' `----------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, DE_ACUT,
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, MO(1),
+ KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_LSFT, DE_Y, KC_X, KC_C, KC_V, KC_B, MO(2),
+ KC_LGUI, DE_CIRC, DE_LESS, KC_LEFT, KC_RIGHT,
+ KC_LCTRL, KC_LALT,
+ KC_HOME,
+ KC_BSPC,KC_DELT,KC_END,
+ // right hand
+ KC_PSCREEN, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
+ MO(1), DE_Z, KC_U, KC_I, KC_O, KC_P, DE_UE,
+ KC_H, KC_J, KC_K, KC_L, DE_OE, LT(MDIA,DE_AE),
+ MO(2), KC_N, KC_M, KC_COMM, KC_DOT, DE_MINS, KC_RSFT,
+ KC_DOWN, KC_UP, DE_HASH, DE_PLUS, KC_RGUI,
+ KC_RALT, KC_RCTRL,
+ KC_PGUP,
+ KC_PGDN, KC_ENT, KC_SPC
+ ),
+// [BASE] = KEYMAP( // layer 0 : default
+// // left hand
+// KC_CIRC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_MPLY,
+// KC_DELT, KC_Q, KC_W, KC_E, KC_R, KC_T, TG(1),
+// KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G,
+// KC_LSFT, DE_Y, KC_X, KC_C, KC_V, KC_B, ALL_T(KC_NO),
+// LT(SYMB,DE_LESS),CTL_T(DE_HASH), DE_ACUT, DE_MINS, DE_PLUS,
+// ALT_T(KC_APP), KC_LGUI,
+// KC_HOME,
+// KC_SPC,KC_BSPC,KC_END,
+// // right hand
+// KC_MNXT, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
+// TG(2), DE_Z, KC_U, KC_I, KC_O, KC_P, DE_UE,
+// KC_H, KC_J, KC_K, KC_L, DE_OE, LT(MDIA,DE_AE),
+// MEH_T(KC_NO),KC_N, KC_M, KC_COMM, KC_DOT, CTL_T(DE_MINS), KC_RSFT,
+// KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, KC_FN1,
+// KC_LALT,CTL_T(KC_ESC),
+// KC_PGUP,
+// KC_PGDN,KC_TAB, KC_ENT
+// ),
+/* Keymap 1: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | . | 0 | = | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[SYMB] = KEYMAP(
+ // left hand
+ KC_TRNS,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS,DE_EXLM,DE_AT, DE_LCBR,DE_RCBR,DE_PIPE,KC_TRNS,
+ KC_TRNS,DE_HASH,DE_DLR, DE_LPRN,DE_RPRN,DE_GRV,
+ KC_TRNS,DE_PERC,DE_CIRC,DE_LBRC,DE_RBRC,DE_TILD,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_UP, KC_7, KC_8, KC_9, DE_ASTR, KC_F12,
+ KC_DOWN, KC_4, KC_5, KC_6, DE_PLUS, KC_TRNS,
+ KC_TRNS, DE_AMPR, KC_1, KC_2, KC_3, DE_BSLS, KC_TRNS,
+ KC_TRNS,KC_DOT, KC_0, DE_EQL, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/* Keymap 2: Media and mouse keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | Lclk | MsUp | Rclk | | | | | |VolDwn| Mute |VolUp | | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | Btn4 |MsLeft|MsDown|MsRght| Btn5 |------| |------| | Prev | Stop | Play | Next | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | |WhRght|WhDown| WhUp |WhLeft|WhClk | | | |BwSrch|BwBack|BwHome|BwRefr|BwFwd | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | |MsAcl0|MsAcl1|MsAcl2| | | | | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | |Brwser|Brwser|
+ * | Lclk | Rclk |------| |------|Back |Forwd |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// MEDIA AND MOUSE
+[MDIA] = KEYMAP(
+ KC_TRNS, KC_F1 , KC_F2 , KC_F3 , KC_F4 , KC_F5 , KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_BTN1, KC_MS_U, KC_BTN2, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_BTN4, KC_MS_L, KC_MS_D, KC_MS_R, KC_BTN5,
+ KC_TRNS, KC_WH_L, KC_WH_D, KC_WH_U, KC_WH_R, KC_BTN3, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_ACL0, KC_ACL1, KC_ACL2,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_BTN1, KC_BTN2, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6 , KC_F7 , KC_F8 , KC_F9 , KC_F10 , KC_F11,
+ KC_TRNS, KC_TRNS, KC_VOLD, KC_MUTE, KC_VOLU, KC_TRNS, KC_F12,
+ KC_TRNS, KC_MPRV, KC_MSTP, KC_MPLY, KC_MNXT, KC_TRNS,
+ KC_TRNS, KC_WSCH, KC_WBAK, KC_WHOM, KC_WREF, KC_WFWD, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_WBAK, KC_WFWD
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(SYMB) // FN1 - Momentary Layer 1 (Symbols)
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ case SYMB:
+ ergodox_right_led_1_on();
+ break;
+ case MDIA:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ ergodox_board_led_off();
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/german-kinergo/layout-code.png b/keyboards/ergodox_ez/keymaps/german-kinergo/layout-code.png
new file mode 100644
index 000000000..a0ef551e1
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/german-kinergo/layout-code.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/german-kinergo/layout-media.png b/keyboards/ergodox_ez/keymaps/german-kinergo/layout-media.png
new file mode 100644
index 000000000..56aea1dca
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/german-kinergo/layout-media.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/german-kinergo/layout.png b/keyboards/ergodox_ez/keymaps/german-kinergo/layout.png
new file mode 100644
index 000000000..76a1aa5d7
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/german-kinergo/layout.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/german-kinergo/readme.md b/keyboards/ergodox_ez/keymaps/german-kinergo/readme.md
new file mode 100644
index 000000000..557d85a8a
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/german-kinergo/readme.md
@@ -0,0 +1,35 @@
+# German Layout for the ErgoDox
+
+This layout is inspired by the "kinesis-qwerty-mod" from benblazak's
+[ergodox-firmware](https://github.com/benblazak/ergodox-firmware), as well as by the "german" layout from the
+[qmk_firmware](https://github.com/jackhumbert/qmk_firmware).
+The goal was to have a layout that is pretty close to an ordinary German
+keyboard, so I don't have to make adjustments on the operating system level
+and I keep some of the muscle memory to use a regular keyboard.
+
+Modifications I made with regard to the aforementioned layouts:
+
+* The key layout is pretty close to the layout of a German Kinesis Ergo Elan.
+ The only exception I made is that I reversed the "up" and "down" cursor keys,
+ since that feels more natural to me.
+
+* All layer changes are "momentary", i.e. they only last as long as the respective key is pressed.
+
+* I sacrificed the Hyper and Meh keys, which I don't use, and put layer change keys in their place.
+
+* I added a PrintScreen key which I use quite regularly for screenshots.
+
+## Default Layer
+
+![Layout of the default layer](layout.png "Layout of the default layer")
+
+## Code Layer
+
+![Layout of the code layer](layout-code.png "Layout of the code layer")
+
+## Media Layer
+
+![Layout of the media layer](layout-media.png "Layout of the media layer")
+
+Christoph Schmitz &lt;schm4704 at web dot de&gt;
+2016-01-28
diff --git a/keyboards/ergodox_ez/keymaps/german-manuneo/compile_keymap.py b/keyboards/ergodox_ez/keymaps/german-manuneo/compile_keymap.py
new file mode 100644
index 000000000..7076a6ecb
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/german-manuneo/compile_keymap.py
@@ -0,0 +1,710 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""Compiler for keymap.c files
+
+This scrip will generate a keymap.c file from a simple
+markdown file with a specific layout.
+
+Usage:
+ python compile_keymap.py INPUT_PATH [OUTPUT_PATH]
+"""
+from __future__ import division
+from __future__ import print_function
+from __future__ import absolute_import
+from __future__ import unicode_literals
+
+import os
+import io
+import re
+import sys
+import json
+import unicodedata
+import collections
+import itertools as it
+
+PY2 = sys.version_info.major == 2
+
+if PY2:
+ chr = unichr
+
+
+KEYBOARD_LAYOUTS = {
+ # These map positions in the parsed layout to
+ # positions in the KEYMAP MATRIX
+ 'ergodox_ez': [
+ [ 0, 1, 2, 3, 4, 5, 6], [38, 39, 40, 41, 42, 43, 44],
+ [ 7, 8, 9, 10, 11, 12, 13], [45, 46, 47, 48, 49, 50, 51],
+ [14, 15, 16, 17, 18, 19 ], [ 52, 53, 54, 55, 56, 57],
+ [20, 21, 22, 23, 24, 25, 26], [58, 59, 60, 61, 62, 63, 64],
+ [27, 28, 29, 30, 31 ], [ 65, 66, 67, 68, 69],
+ [ 32, 33], [70, 71 ],
+ [ 34], [72 ],
+ [ 35, 36, 37], [73, 74, 75 ],
+ ]
+}
+
+ROW_INDENTS = {
+ 'ergodox_ez': [0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 5, 0, 6, 0, 4, 0]
+}
+
+BLANK_LAYOUTS = [
+# Compact Layout
+"""
+.------------------------------------.------------------------------------.
+| | | | | | | | | | | | | | |
+!-----+----+----+----+----+----------!-----+----+----+----+----+----+-----!
+| | | | | | | | | | | | | | |
+!-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+| | | | | | |-----!-----! | | | | | |
+!-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+| | | | | | | | | | | | | | |
+'-----+----+----+----+----+----------'----------+----+----+----+----+-----'
+ | | | | | | ! | | | | |
+ '------------------------' '------------------------'
+ .-----------. .-----------.
+ | | | ! | |
+ .-----+-----+-----! !-----+-----+-----.
+ ! ! | | ! | ! !
+ ! ! !-----! !-----! ! !
+ | | | | ! | | |
+ '-----------------' '-----------------'
+""",
+
+# Wide Layout
+"""
+.---------------------------------------------. .---------------------------------------------.
+| | | | | | | | ! | | | | | | |
+!-------+-----+-----+-----+-----+-------------! !-------+-----+-----+-----+-----+-----+-------!
+| | | | | | | | ! | | | | | | |
+!-------+-----+-----+-----x-----x-----! ! ! !-----x-----x-----+-----+-----+-------!
+| | | | | | |-------! !-------! | | | | | |
+!-------+-----+-----+-----x-----x-----! ! ! !-----x-----x-----+-----+-----+-------!
+| | | | | | | | ! | | | | | | |
+'-------+-----+-----+-----+-----+-------------' '-------------+-----+-----+-----+-----+-------'
+ | | | | | | ! | | | | |
+ '------------------------------' '------------------------------'
+ .---------------. .---------------.
+ | | | ! | |
+ .-------+-------+-------! !-------+-------+-------.
+ ! ! | | ! | ! !
+ ! ! !-------! !-------! ! !
+ | | | | ! | | |
+ '-----------------------' '-----------------------'
+""",
+]
+
+
+DEFAULT_CONFIG = {
+ "keymaps_includes": [
+ "keymap_common.h",
+ ],
+ 'filler': "-+.'!:x",
+ 'separator': "|",
+ 'default_key_prefix': ["KC_"],
+}
+
+
+SECTIONS = [
+ 'layout_config',
+ 'layers',
+]
+
+
+# Markdown Parsing
+
+ONELINE_COMMENT_RE = re.compile(r"""
+ ^ # comment must be at the start of the line
+ \s* # arbitrary whitespace
+ // # start of the comment
+ (.*) # the comment
+ $ # until the end of line
+""", re.MULTILINE | re.VERBOSE
+)
+
+INLINE_COMMENT_RE = re.compile(r"""
+ ([\,\"\[\]\{\}\d]) # anythig that might end a expression
+ \s+ # comment must be preceded by whitespace
+ // # start of the comment
+ \s # and succeded by whitespace
+ (?:[^\"\]\}\{\[]*) # the comment (except things which might be json)
+ $ # until the end of line
+""", re.MULTILINE | re.VERBOSE)
+
+TRAILING_COMMA_RE = re.compile(r"""
+ , # the comma
+ (?:\s*) # arbitrary whitespace
+ $ # only works if the trailing comma is followed by newline
+ (\s*) # arbitrary whitespace
+ ([\]\}]) # end of an array or object
+""", re.MULTILINE | re.VERBOSE)
+
+
+def loads(raw_data):
+ if isinstance(raw_data, bytes):
+ raw_data = raw_data.decode('utf-8')
+
+ raw_data = ONELINE_COMMENT_RE.sub(r"", raw_data)
+ raw_data = INLINE_COMMENT_RE.sub(r"\1", raw_data)
+ raw_data = TRAILING_COMMA_RE.sub(r"\1\2", raw_data)
+ return json.loads(raw_data)
+
+
+def parse_config(path):
+ def reset_section():
+ section.update({
+ 'name': section.get('name', ""),
+ 'sub_name': "",
+ 'start_line': -1,
+ 'end_line': -1,
+ 'code_lines': [],
+ })
+
+ def start_section(line_index, line):
+ end_section()
+ if line.startswith("# "):
+ name = line[2:]
+ elif line.startswith("## "):
+ name = line[3:]
+ else:
+ name = ""
+
+ name = name.strip().replace(" ", "_").lower()
+ if name in SECTIONS:
+ section['name'] = name
+ else:
+ section['sub_name'] = name
+ section['start_line'] = line_index
+
+ def end_section():
+ if section['start_line'] >= 0:
+ if section['name'] == 'layout_config':
+ config.update(loads("\n".join(
+ section['code_lines']
+ )))
+ elif section['sub_name'].startswith('layer'):
+ layer_name = section['sub_name']
+ config['layer_lines'][layer_name] = section['code_lines']
+
+ reset_section()
+
+ def amend_section(line_index, line):
+ section['end_line'] = line_index
+ section['code_lines'].append(line)
+
+ config = DEFAULT_CONFIG.copy()
+ config.update({
+ 'layer_lines': collections.OrderedDict(),
+ 'macro_ids': {'UM'},
+ 'unicode_macros': {},
+ })
+
+ section = {}
+ reset_section()
+
+ with io.open(path, encoding="utf-8") as fh:
+ for i, line in enumerate(fh):
+ if line.startswith("#"):
+ start_section(i, line)
+ elif line.startswith(" "):
+ amend_section(i, line[4:])
+ else:
+ # TODO: maybe parse description
+ pass
+
+ end_section()
+ assert 'layout' in config
+ return config
+
+# header file parsing
+
+IF0_RE = re.compile(r"""
+ ^
+ #if 0
+ $.*?
+ #endif
+""", re.MULTILINE | re.DOTALL | re.VERBOSE)
+
+
+COMMENT_RE = re.compile(r"""
+ /\*
+ .*?
+ \*/"
+""", re.MULTILINE | re.DOTALL | re.VERBOSE)
+
+
+def read_header_file(path):
+ with io.open(path, encoding="utf-8") as fh:
+ data = fh.read()
+ data, _ = COMMENT_RE.subn("", data)
+ data, _ = IF0_RE.subn("", data)
+ return data
+
+
+def regex_partial(re_str_fmt, flags):
+ def partial(*args, **kwargs):
+ re_str = re_str_fmt.format(*args, **kwargs)
+ return re.compile(re_str, flags)
+ return partial
+
+
+KEYDEF_REP = regex_partial(r"""
+ #define
+ \s
+ (
+ (?:{}) # the prefixes
+ (?:\w+) # the key name
+ ) # capture group end
+""", re.MULTILINE | re.DOTALL | re.VERBOSE)
+
+
+ENUM_RE = re.compile(r"""
+ (
+ enum
+ \s\w+\s
+ \{
+ .*? # the enum content
+ \}
+ ;
+ ) # capture group end
+""", re.MULTILINE | re.DOTALL | re.VERBOSE)
+
+
+ENUM_KEY_REP = regex_partial(r"""
+ (
+ {} # the prefixes
+ \w+ # the key name
+ ) # capture group end
+""", re.MULTILINE | re.DOTALL | re.VERBOSE)
+
+
+def parse_keydefs(config, data):
+ prefix_options = "|".join(config['key_prefixes'])
+ keydef_re = KEYDEF_REP(prefix_options)
+ enum_key_re = ENUM_KEY_REP(prefix_options)
+ for match in keydef_re.finditer(data):
+ yield match.groups()[0]
+
+ for enum_match in ENUM_RE.finditer(data):
+ enum = enum_match.groups()[0]
+ for key_match in enum_key_re.finditer(enum):
+ yield key_match.groups()[0]
+
+
+def parse_valid_keys(config, out_path):
+ basepath = os.path.abspath(os.path.join(os.path.dirname(out_path)))
+ dirpaths = []
+ subpaths = []
+ while len(subpaths) < 6:
+ path = os.path.join(basepath, *subpaths)
+ dirpaths.append(path)
+ dirpaths.append(os.path.join(path, "tmk_core", "common"))
+ dirpaths.append(os.path.join(path, "quantum"))
+ subpaths.append('..')
+
+ includes = set(config['keymaps_includes'])
+ includes.add("keycode.h")
+
+ valid_keycodes = set()
+ for dirpath, include in it.product(dirpaths, includes):
+ include_path = os.path.join(dirpath, include)
+ if os.path.exists(include_path):
+ header_data = read_header_file(include_path)
+ valid_keycodes.update(
+ parse_keydefs(config, header_data)
+ )
+ return valid_keycodes
+
+
+# Keymap Parsing
+
+def iter_raw_codes(layer_lines, filler, separator):
+ filler_re = re.compile("[" + filler + " ]")
+ for line in layer_lines:
+ line, _ = filler_re.subn("", line.strip())
+ if not line:
+ continue
+ codes = line.split(separator)
+ for code in codes[1:-1]:
+ yield code
+
+
+def iter_indexed_codes(raw_codes, key_indexes):
+ key_rows = {}
+ key_indexes_flat = []
+
+ for row_index, key_indexes in enumerate(key_indexes):
+ for key_index in key_indexes:
+ key_rows[key_index] = row_index
+ key_indexes_flat.extend(key_indexes)
+ assert len(raw_codes) == len(key_indexes_flat)
+ for raw_code, key_index in zip(raw_codes, key_indexes_flat):
+ # we keep track of the row mostly for layout purposes
+ yield raw_code, key_index, key_rows[key_index]
+
+
+LAYER_CHANGE_RE = re.compile(r"""
+ (DF|TG|MO)\(\d+\)
+""", re.VERBOSE)
+
+
+MACRO_RE = re.compile(r"""
+ M\(\w+\)
+""", re.VERBOSE)
+
+
+UNICODE_RE = re.compile(r"""
+ U[0-9A-F]{4}
+""", re.VERBOSE)
+
+
+NON_CODE = re.compile(r"""
+ ^[^A-Z0-9_]$
+""", re.VERBOSE)
+
+
+def parse_uni_code(raw_code):
+ macro_id = "UC_" + (
+ unicodedata.name(raw_code)
+ .replace(" ", "_")
+ .replace("-", "_")
+ )
+ code = "M({})".format(macro_id)
+ uc_hex = "{:04X}".format(ord(raw_code))
+ return code, macro_id, uc_hex
+
+
+def parse_key_code(raw_code, key_prefixes, valid_keycodes):
+ if raw_code in valid_keycodes:
+ return raw_code
+
+ for prefix in key_prefixes:
+ code = prefix + raw_code
+ if code in valid_keycodes:
+ return code
+
+
+def parse_code(raw_code, key_prefixes, valid_keycodes):
+ if not raw_code:
+ return 'KC_TRNS', None, None
+
+ if LAYER_CHANGE_RE.match(raw_code):
+ return raw_code, None, None
+
+ if MACRO_RE.match(raw_code):
+ macro_id = raw_code[2:-1]
+ return raw_code, macro_id, None
+
+ if UNICODE_RE.match(raw_code):
+ hex_code = raw_code[1:]
+ return parse_uni_code(chr(int(hex_code, 16)))
+
+ if NON_CODE.match(raw_code):
+ return parse_uni_code(raw_code)
+
+ code = parse_key_code(raw_code, key_prefixes, valid_keycodes)
+ return code, None, None
+
+
+def parse_keymap(config, key_indexes, layer_lines, valid_keycodes):
+ keymap = {}
+ raw_codes = list(iter_raw_codes(
+ layer_lines, config['filler'], config['separator']
+ ))
+ indexed_codes = iter_indexed_codes(raw_codes, key_indexes)
+ key_prefixes = config['key_prefixes']
+ for raw_code, key_index, row_index in indexed_codes:
+ code, macro_id, uc_hex = parse_code(
+ raw_code, key_prefixes, valid_keycodes
+ )
+ # TODO: line numbers for invalid codes
+ err_msg = "Could not parse key '{}' on row {}".format(
+ raw_code, row_index
+ )
+ assert code is not None, err_msg
+ # print(repr(raw_code), repr(code), macro_id, uc_hex)
+ if macro_id:
+ config['macro_ids'].add(macro_id)
+ if uc_hex:
+ config['unicode_macros'][macro_id] = uc_hex
+ keymap[key_index] = (code, row_index)
+ return keymap
+
+
+def parse_keymaps(config, valid_keycodes):
+ keymaps = collections.OrderedDict()
+ key_indexes = config.get(
+ 'key_indexes', KEYBOARD_LAYOUTS[config['layout']]
+ )
+ # TODO: maybe validate key_indexes
+
+ for layer_name, layer_lines, in config['layer_lines'].items():
+ keymaps[layer_name] = parse_keymap(
+ config, key_indexes, layer_lines, valid_keycodes
+ )
+ return keymaps
+
+# keymap.c output
+
+USERCODE = """
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ case L1:
+ ergodox_right_led_1_on();
+ break;
+ case L2:
+ ergodox_right_led_2_on();
+ break;
+ case L3:
+ ergodox_right_led_3_on();
+ break;
+ case L4:
+ ergodox_right_led_1_on();
+ ergodox_right_led_2_on();
+ break;
+ case L5:
+ ergodox_right_led_1_on();
+ ergodox_right_led_3_on();
+ break;
+ // case L6:
+ // ergodox_right_led_2_on();
+ // ergodox_right_led_3_on();
+ // break;
+ // case L7:
+ // ergodox_right_led_1_on();
+ // ergodox_right_led_2_on();
+ // ergodox_right_led_3_on();
+ // break;
+ default:
+ ergodox_board_led_off();
+ break;
+ }
+};
+"""
+
+MACROCODE = """
+#define UC_MODE_WIN 0
+#define UC_MODE_LINUX 1
+#define UC_MODE_OSX 2
+
+// TODO: allow default mode to be configured
+static uint16_t unicode_mode = UC_MODE_WIN;
+
+uint16_t hextokeycode(uint8_t hex) {{
+ if (hex == 0x0) {{
+ return KC_P0;
+ }}
+ if (hex < 0xA) {{
+ return KC_P1 + (hex - 0x1);
+ }}
+ return KC_A + (hex - 0xA);
+}}
+
+void unicode_action_function(uint16_t hi, uint16_t lo) {{
+ switch (unicode_mode) {{
+ case UC_MODE_WIN:
+ register_code(KC_LALT);
+
+ register_code(KC_PPLS);
+ unregister_code(KC_PPLS);
+
+ register_code(hextokeycode((hi & 0xF0) >> 4));
+ unregister_code(hextokeycode((hi & 0xF0) >> 4));
+ register_code(hextokeycode((hi & 0x0F)));
+ unregister_code(hextokeycode((hi & 0x0F)));
+ register_code(hextokeycode((lo & 0xF0) >> 4));
+ unregister_code(hextokeycode((lo & 0xF0) >> 4));
+ register_code(hextokeycode((lo & 0x0F)));
+ unregister_code(hextokeycode((lo & 0x0F)));
+
+ unregister_code(KC_LALT);
+ break;
+ case UC_MODE_LINUX:
+ register_code(KC_LCTL);
+ register_code(KC_LSFT);
+
+ register_code(KC_U);
+ unregister_code(KC_U);
+
+ register_code(hextokeycode((hi & 0xF0) >> 4));
+ unregister_code(hextokeycode((hi & 0xF0) >> 4));
+ register_code(hextokeycode((hi & 0x0F)));
+ unregister_code(hextokeycode((hi & 0x0F)));
+ register_code(hextokeycode((lo & 0xF0) >> 4));
+ unregister_code(hextokeycode((lo & 0xF0) >> 4));
+ register_code(hextokeycode((lo & 0x0F)));
+ unregister_code(hextokeycode((lo & 0x0F)));
+
+ unregister_code(KC_LCTL);
+ unregister_code(KC_LSFT);
+ break;
+ case UC_MODE_OSX:
+ break;
+ }}
+}}
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) {{
+ if (!record->event.pressed) {{
+ return MACRO_NONE;
+ }}
+ // MACRODOWN only works in this function
+ switch(id) {{
+ case UM:
+ unicode_mode = (unicode_mode + 1) % 2;
+ break;
+{macro_cases}
+{unicode_macro_cases}
+ default:
+ break;
+ }}
+ return MACRO_NONE;
+}};
+"""
+
+
+UNICODE_MACRO_TEMPLATE = """
+case {macro_id}:
+ unicode_action_function(0x{hi:02x}, 0x{lo:02x});
+ break;
+""".strip()
+
+
+def unicode_macro_cases(config):
+ for macro_id, uc_hex in config['unicode_macros'].items():
+ hi = int(uc_hex, 16) >> 8
+ lo = int(uc_hex, 16) & 0xFF
+ unimacro_keys = ", ".join(
+ "T({})".format(
+ "KP_" + digit if digit.isdigit() else digit
+ ) for digit in uc_hex
+ )
+ yield UNICODE_MACRO_TEMPLATE.format(
+ macro_id=macro_id, hi=hi, lo=lo
+ )
+
+
+def iter_keymap_lines(keymap, row_indents=None):
+ col_widths = {}
+ col = 0
+ # first pass, figure out the column widths
+ prev_row_index = None
+ for code, row_index in keymap.values():
+ if row_index != prev_row_index:
+ col = 0
+ if row_indents:
+ col = row_indents[row_index]
+ col_widths[col] = max(len(code), col_widths.get(col, 0))
+ prev_row_index = row_index
+ col += 1
+
+ # second pass, yield the cell values
+ col = 0
+ prev_row_index = None
+ for key_index in sorted(keymap):
+ code, row_index = keymap[key_index]
+ if row_index != prev_row_index:
+ col = 0
+ yield "\n"
+ if row_indents:
+ for indent_col in range(row_indents[row_index]):
+ pad = " " * (col_widths[indent_col] - 4)
+ yield (" /*-*/" + pad)
+ col = row_indents[row_index]
+ else:
+ yield pad
+ yield " {}".format(code)
+ if key_index < len(keymap) - 1:
+ yield ","
+ # This will be yielded on the next iteration when
+ # we know that we're not at the end of a line.
+ pad = " " * (col_widths[col] - len(code))
+ prev_row_index = row_index
+ col += 1
+
+
+def iter_keymap_parts(config, keymaps):
+ # includes
+ for include_path in config['keymaps_includes']:
+ yield '#include "{}"\n'.format(include_path)
+
+ yield "\n"
+
+ # definitions
+ for i, macro_id in enumerate(sorted(config['macro_ids'])):
+ yield "#define {} {}\n".format(macro_id, i)
+
+ yield "\n"
+
+ for i, layer_name in enumerate(config['layer_lines']):
+ yield '#define L{0:<3} {0:<5} // {1}\n'.format(i, layer_name)
+
+ yield "\n"
+
+ # keymaps
+ yield "const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {\n"
+
+ for i, layer_name in enumerate(config['layer_lines']):
+ # comment
+ layer_lines = config['layer_lines'][layer_name]
+ prefixed_lines = " * " + " * ".join(layer_lines)
+ yield "/*\n{} */\n".format(prefixed_lines)
+
+ # keymap codes
+ keymap = keymaps[layer_name]
+ row_indents = ROW_INDENTS.get(config['layout'])
+ keymap_lines = "".join(iter_keymap_lines(keymap, row_indents))
+ yield "[L{0}] = KEYMAP({1}\n),\n".format(i, keymap_lines)
+
+ yield "};\n\n"
+
+ # no idea what this is for
+ yield "const uint16_t PROGMEM fn_actions[] = {};\n"
+
+ # macros
+ yield MACROCODE.format(
+ macro_cases="",
+ unicode_macro_cases="\n".join(unicode_macro_cases(config)),
+ )
+
+ # TODO: dynamically create blinking lights
+ yield USERCODE
+
+
+def main(argv=sys.argv[1:]):
+ if not argv or '-h' in argv or '--help' in argv:
+ print(__doc__)
+ return 0
+
+ in_path = os.path.abspath(argv[0])
+ if not os.path.exists(in_path):
+ print("No such file '{}'".format(in_path))
+ return 1
+
+ if len(argv) > 1:
+ out_path = os.path.abspath(argv[1])
+ else:
+ dirname = os.path.dirname(in_path)
+ out_path = os.path.join(dirname, "keymap.c")
+
+ config = parse_config(in_path)
+ valid_keys = parse_valid_keys(config, out_path)
+ keymaps = parse_keymaps(config, valid_keys)
+
+ with io.open(out_path, mode="w", encoding="utf-8") as fh:
+ for part in iter_keymap_parts(config, keymaps):
+ fh.write(part)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/keyboards/ergodox_ez/keymaps/german-manuneo/keymap.c b/keyboards/ergodox_ez/keymaps/german-manuneo/keymap.c
new file mode 100644
index 000000000..5fcc14d51
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/german-manuneo/keymap.c
@@ -0,0 +1,783 @@
+#include "ergodox_ez.h"
+#include "action_layer.h"
+#include "keymap.h"
+#include "keymap_german.h"
+
+#define UC_ASYMPTOTICALLY_EQUAL_TO 0
+#define UC_DIVISION_SIGN 1
+#define UC_DOWNWARDS_ARROW 2
+#define UC_ELEMENT_OF 3
+#define UC_EMPTY_SET 4
+#define UC_FOR_ALL 5
+#define UC_GREEK_CAPITAL_LETTER_ALPHA 6
+#define UC_GREEK_CAPITAL_LETTER_BETA 7
+#define UC_GREEK_CAPITAL_LETTER_CHI 8
+#define UC_GREEK_CAPITAL_LETTER_DELTA 9
+#define UC_GREEK_CAPITAL_LETTER_EPSILON 10
+#define UC_GREEK_CAPITAL_LETTER_ETA 11
+#define UC_GREEK_CAPITAL_LETTER_GAMMA 12
+#define UC_GREEK_CAPITAL_LETTER_IOTA 13
+#define UC_GREEK_CAPITAL_LETTER_KAPPA 14
+#define UC_GREEK_CAPITAL_LETTER_LAMDA 15
+#define UC_GREEK_CAPITAL_LETTER_MU 16
+#define UC_GREEK_CAPITAL_LETTER_NU 17
+#define UC_GREEK_CAPITAL_LETTER_OMEGA 18
+#define UC_GREEK_CAPITAL_LETTER_OMICRON 19
+#define UC_GREEK_CAPITAL_LETTER_PHI 20
+#define UC_GREEK_CAPITAL_LETTER_PI 21
+#define UC_GREEK_CAPITAL_LETTER_PSI 22
+#define UC_GREEK_CAPITAL_LETTER_RHO 23
+#define UC_GREEK_CAPITAL_LETTER_SIGMA 24
+#define UC_GREEK_CAPITAL_LETTER_TAU 25
+#define UC_GREEK_CAPITAL_LETTER_THETA 26
+#define UC_GREEK_CAPITAL_LETTER_UPSILON 27
+#define UC_GREEK_CAPITAL_LETTER_XI 28
+#define UC_GREEK_CAPITAL_LETTER_ZETA 29
+#define UC_GREEK_SMALL_LETTER_ALPHA 30
+#define UC_GREEK_SMALL_LETTER_BETA 31
+#define UC_GREEK_SMALL_LETTER_CHI 32
+#define UC_GREEK_SMALL_LETTER_DELTA 33
+#define UC_GREEK_SMALL_LETTER_EPSILON 34
+#define UC_GREEK_SMALL_LETTER_ETA 35
+#define UC_GREEK_SMALL_LETTER_FINAL_SIGMA 36
+#define UC_GREEK_SMALL_LETTER_GAMMA 37
+#define UC_GREEK_SMALL_LETTER_IOTA 38
+#define UC_GREEK_SMALL_LETTER_KAPPA 39
+#define UC_GREEK_SMALL_LETTER_LAMDA 40
+#define UC_GREEK_SMALL_LETTER_MU 41
+#define UC_GREEK_SMALL_LETTER_NU 42
+#define UC_GREEK_SMALL_LETTER_OMEGA 43
+#define UC_GREEK_SMALL_LETTER_OMICRON 44
+#define UC_GREEK_SMALL_LETTER_PHI 45
+#define UC_GREEK_SMALL_LETTER_PI 46
+#define UC_GREEK_SMALL_LETTER_PSI 47
+#define UC_GREEK_SMALL_LETTER_RHO 48
+#define UC_GREEK_SMALL_LETTER_SIGMA 49
+#define UC_GREEK_SMALL_LETTER_TAU 50
+#define UC_GREEK_SMALL_LETTER_THETA 51
+#define UC_GREEK_SMALL_LETTER_UPSILON 52
+#define UC_GREEK_SMALL_LETTER_XI 53
+#define UC_GREEK_SMALL_LETTER_ZETA 54
+#define UC_INFINITY 55
+#define UC_LEFTWARDS_ARROW 56
+#define UC_MULTIPLICATION_SIGN 57
+#define UC_NOT_AN_ELEMENT_OF 58
+#define UC_NOT_EQUAL_TO 59
+#define UC_PLUS_MINUS_SIGN 60
+#define UC_RIGHTWARDS_ARROW 61
+#define UC_SUBSCRIPT_EIGHT 62
+#define UC_SUBSCRIPT_FIVE 63
+#define UC_SUBSCRIPT_FOUR 64
+#define UC_SUBSCRIPT_NINE 65
+#define UC_SUBSCRIPT_ONE 66
+#define UC_SUBSCRIPT_SEVEN 67
+#define UC_SUBSCRIPT_SIX 68
+#define UC_SUBSCRIPT_THREE 69
+#define UC_SUBSCRIPT_TWO 70
+#define UC_SUBSCRIPT_ZERO 71
+#define UC_SUPERSCRIPT_EIGHT 72
+#define UC_SUPERSCRIPT_FIVE 73
+#define UC_SUPERSCRIPT_FOUR 74
+#define UC_SUPERSCRIPT_LATIN_SMALL_LETTER_N 75
+#define UC_SUPERSCRIPT_NINE 76
+#define UC_SUPERSCRIPT_ONE 77
+#define UC_SUPERSCRIPT_SEVEN 78
+#define UC_SUPERSCRIPT_SIX 79
+#define UC_SUPERSCRIPT_THREE 80
+#define UC_SUPERSCRIPT_TWO 81
+#define UC_SUPERSCRIPT_ZERO 82
+#define UC_THERE_DOES_NOT_EXIST 83
+#define UC_THERE_EXISTS 84
+#define UC_UPWARDS_ARROW 85
+#define UC_VULGAR_FRACTION_ONE_EIGHTH 86
+#define UC_VULGAR_FRACTION_ONE_FIFTH 87
+#define UC_VULGAR_FRACTION_ONE_HALF 88
+#define UC_VULGAR_FRACTION_ONE_QUARTER 89
+#define UC_VULGAR_FRACTION_ONE_SIXTH 90
+#define UC_VULGAR_FRACTION_ONE_THIRD 91
+#define UC_VULGAR_FRACTION_THREE_QUARTERS 92
+#define UC_VULGAR_FRACTION_TWO_THIRDS 93
+#define UM 94
+
+#define L0 0 // layer_0
+#define L1 1 // layer_1
+#define L2 2 // layer_2
+#define L3 3 // layer_3
+#define L4 4 // layer_4
+#define L5 5 // layer_5
+#define L6 6 // layer_6
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/*
+ * .------------------------------------.------------------------------------.
+ * |MO(5)| 1 | 2 | 3 | 4 | 5 |ACUT | GRV | 6 | 7 | 8 | 9 | 0 |CIRC |
+ * !-----+----+----+----+----+----------!-----+----+----+----+----+----+-----!
+ * |MO(4)| X | P | F | W | G |HOME |TG(2)| H | J | K | L | Q | Z |
+ * !-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+ * |MO(1)| U | I | A | E | O |-----!-----! S | N | R | T | D | SS |
+ * !-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+ * |MO(3)| UE | OE | AE | C | V |END | TAB | B | M |COMM| DOT| UP | Y |
+ * '-----+----+----+----+----+----------'----------+----+----+----+----+-----'
+ * | | |LGUI|LALT|LCTL| !RCTL|RALT|LEFT|DOWN|RGHT|
+ * '------------------------' '------------------------'
+ * .-----------. .-----------.
+ * |INS |TG(2)| !M(UM)|DELT |
+ * .-----+-----+-----! !-----+-----+-----.
+ * ! ! | APP | ! PGUP| ! !
+ * ! ! !-----! !-----! ! !
+ * |BSPC |LSFT | ESC | ! PGDN|ENTER|SPACE|
+ * '-----------------' '-----------------'
+ */
+[L0] = KEYMAP(
+ MO(5), DE_1, DE_2, DE_3, DE_4, DE_5, DE_ACUT,
+ MO(4), DE_X, DE_P, DE_F, DE_W, DE_G, KC_HOME,
+ MO(1), DE_U, DE_I, DE_A, DE_E, DE_O,
+ MO(3), DE_UE, DE_OE, DE_AE, DE_C, DE_V, KC_END,
+ KC_TRNS, KC_TRNS, KC_LGUI, KC_LALT, KC_LCTL,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_INS, TG(2),
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_APP,
+ /*-*/ /*-*/ /*-*/ /*-*/ KC_BSPC, KC_LSFT, KC_ESC,
+ DE_GRV, DE_6, DE_7, DE_8, DE_9, DE_0, DE_CIRC,
+ TG(2), DE_H, DE_J, DE_K, DE_L, DE_Q, DE_Z,
+ /*-*/ DE_S, DE_N, DE_R, DE_T, DE_D, DE_SS,
+ KC_TAB, DE_B, DE_M, DE_COMM, DE_DOT, KC_UP, DE_Y,
+ /*-*/ /*-*/ KC_RCTL, KC_RALT, KC_LEFT, KC_DOWN, KC_RGHT,
+ M(UM), KC_DELT,
+ KC_PGUP,
+ KC_PGDN, KC_ENTER, KC_SPACE
+),
+/*
+ * .------------------------------------.------------------------------------.
+ * | |EXLM|DQOT|PARA| | | | | | | | |RING| |
+ * !-----+----+----+----+----+----------!-----+----+----+----+----+----+-----!
+ * | |ASTR|PIPE|SLSH|LCBR|RCBR| | |HASH|LESS|MORE| |DQOT| |
+ * !-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+ * | |UNDS|MINS|AMPR|LBRC|RBRC|-----!-----!DLR |LPRN|RPRN|TILD|QUOT| QST |
+ * !-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+ * | | |PLUS|EQL | | | | |BSLS|PERC|SCLN|COLN| ↑ | |
+ * '-----+----+----+----+----+----------'----------+----+----+----+----+-----'
+ * | | | | | | ! | | ← | ↓ | → |
+ * '------------------------' '------------------------'
+ * .-----------. .-----------.
+ * | | | ! | |
+ * .-----+-----+-----! !-----+-----+-----.
+ * ! ! | | ! | ! !
+ * ! ! !-----! !-----! ! !
+ * | | | | ! | | |
+ * '-----------------' '-----------------'
+ */
+[L1] = KEYMAP(
+ KC_TRNS, DE_EXLM, DE_DQOT, DE_PARA, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, DE_ASTR, DE_PIPE, DE_SLSH, DE_LCBR, DE_RCBR, KC_TRNS,
+ KC_TRNS, DE_UNDS, DE_MINS, DE_AMPR, DE_LBRC, DE_RBRC,
+ KC_TRNS, KC_TRNS, DE_PLUS, DE_EQL, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, DE_RING, KC_TRNS,
+ KC_TRNS, DE_HASH, DE_LESS, DE_MORE, KC_TRNS, DE_DQOT, KC_TRNS,
+ /*-*/ DE_DLR, DE_LPRN, DE_RPRN, DE_TILD, DE_QUOT, DE_QST,
+ KC_TRNS, DE_BSLS, DE_PERC, DE_SCLN, DE_COLN, M(UC_UPWARDS_ARROW), KC_TRNS,
+ /*-*/ /*-*/ KC_TRNS, KC_TRNS, M(UC_LEFTWARDS_ARROW), M(UC_DOWNWARDS_ARROW), M(UC_RIGHTWARDS_ARROW),
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/*
+ * .------------------------------------.------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | F11 | F12 | F6 | F7 | F8 | F9 |F10 |PEQL |
+ * !-----+----+----+----+----+----------!-----+----+----+----+----+----+-----!
+ * | | | | | | | | | | P7 | P8 | P9 |PAST|PSLS |
+ * !-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+ * | | | | | | |-----!-----! | P4 | P5 | P6 |PMNS|PMNS |
+ * !-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+ * | | | | | | | | NLCK| | P1 | P2 | P3 |PPLS|PPLS |
+ * '-----+----+----+----+----+----------'----------+----+----+----+----+-----'
+ * | | | | | | ! P0 |PCMM|PDOT|PENT|PENT|
+ * '------------------------' '------------------------'
+ * .-----------. .-----------.
+ * | | | ! | |
+ * .-----+-----+-----! !-----+-----+-----.
+ * ! ! | | ! | ! !
+ * ! ! !-----! !-----! ! !
+ * | | | | ! | | |
+ * '-----------------' '-----------------'
+ */
+[L2] = KEYMAP(
+ KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F11,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_F12, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_PEQL,
+ KC_TRNS, KC_TRNS, KC_P7, KC_P8, KC_P9, KC_PAST, KC_PSLS,
+ /*-*/ KC_TRNS, KC_P4, KC_P5, KC_P6, KC_PMNS, KC_PMNS,
+ KC_NLCK, KC_TRNS, KC_P1, KC_P2, KC_P3, KC_PPLS, KC_PPLS,
+ /*-*/ /*-*/ KC_P0, KC_PCMM, KC_PDOT, KC_PENT, KC_PENT,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/*
+ * .------------------------------------.------------------------------------.
+ * | | ¹ | ² | ³ | ⁴ | ⁵ | ∀ | | ⁶ | ⁷ | ⁸ | ⁹ | ⁰ | |
+ * !-----+----+----+----+----+----------!-----+----+----+----+----+----+-----!
+ * | | × | ½ | ÷ | ¼ | ⅕ | | | ⅙ | | ⅛ | | | |
+ * !-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+ * | | | ± | AT |EURO| ∅ |-----!-----! ∞ | ⁿ | ∃ | ∈ | | |
+ * !-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+ * | | ⅓ | ≠ | ⅔ | ¾ | ≃ | | |EXLM| | ∄ | ∉ | | |
+ * '-----+----+----+----+----+----------'----------+----+----+----+----+-----'
+ * | | | | | | ! | | | | |
+ * '------------------------' '------------------------'
+ * .-----------. .-----------.
+ * | | | ! | |
+ * .-----+-----+-----! !-----+-----+-----.
+ * ! ! | | ! | ! !
+ * ! ! !-----! !-----! ! !
+ * | | | | ! | | |
+ * '-----------------' '-----------------'
+ */
+[L3] = KEYMAP(
+ KC_TRNS, M(UC_SUPERSCRIPT_ONE), M(UC_SUPERSCRIPT_TWO), M(UC_SUPERSCRIPT_THREE), M(UC_SUPERSCRIPT_FOUR), M(UC_SUPERSCRIPT_FIVE), M(UC_FOR_ALL),
+ KC_TRNS, M(UC_MULTIPLICATION_SIGN), M(UC_VULGAR_FRACTION_ONE_HALF), M(UC_DIVISION_SIGN), M(UC_VULGAR_FRACTION_ONE_QUARTER), M(UC_VULGAR_FRACTION_ONE_FIFTH), KC_TRNS,
+ KC_TRNS, KC_TRNS, M(UC_PLUS_MINUS_SIGN), DE_AT, DE_EURO, M(UC_EMPTY_SET),
+ KC_TRNS, M(UC_VULGAR_FRACTION_ONE_THIRD), M(UC_NOT_EQUAL_TO), M(UC_VULGAR_FRACTION_TWO_THIRDS), M(UC_VULGAR_FRACTION_THREE_QUARTERS), M(UC_ASYMPTOTICALLY_EQUAL_TO), KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, M(UC_SUPERSCRIPT_SIX), M(UC_SUPERSCRIPT_SEVEN), M(UC_SUPERSCRIPT_EIGHT), M(UC_SUPERSCRIPT_NINE), M(UC_SUPERSCRIPT_ZERO), KC_TRNS,
+ KC_TRNS, M(UC_VULGAR_FRACTION_ONE_SIXTH), KC_TRNS, M(UC_VULGAR_FRACTION_ONE_EIGHTH), KC_TRNS, KC_TRNS, KC_TRNS,
+ /*-*/ M(UC_INFINITY), M(UC_SUPERSCRIPT_LATIN_SMALL_LETTER_N), M(UC_THERE_EXISTS), M(UC_ELEMENT_OF), KC_TRNS, KC_TRNS,
+ KC_TRNS, DE_EXLM, KC_TRNS, M(UC_THERE_DOES_NOT_EXIST), M(UC_NOT_AN_ELEMENT_OF), KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/*
+ * .------------------------------------.------------------------------------.
+ * | | ₁ | ₂ | ₃ | ₄ | ₅ | | | ₆ | ₇ | ₈ | ₉ | ₀ | |
+ * !-----+----+----+----+----+----------!-----+----+----+----+----+----+-----!
+ * | | χ | π | φ | ω | γ | | | η | ξ | κ | λ | | ζ |
+ * !-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+ * | | υ | ι | α | ε | ο |-----!-----! σ | ν | ρ | τ | δ | ς |
+ * !-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+ * | | | θ | | | | | | β | μ | | | | ψ |
+ * '-----+----+----+----+----+----------'----------+----+----+----+----+-----'
+ * | | | | | | ! | | | | |
+ * '------------------------' '------------------------'
+ * .-----------. .-----------.
+ * | | | ! | |
+ * .-----+-----+-----! !-----+-----+-----.
+ * ! ! | | ! | ! !
+ * ! ! !-----! !-----! ! !
+ * | | | | ! | | |
+ * '-----------------' '-----------------'
+ */
+[L4] = KEYMAP(
+ KC_TRNS, M(UC_SUBSCRIPT_ONE), M(UC_SUBSCRIPT_TWO), M(UC_SUBSCRIPT_THREE), M(UC_SUBSCRIPT_FOUR), M(UC_SUBSCRIPT_FIVE), KC_TRNS,
+ KC_TRNS, M(UC_GREEK_SMALL_LETTER_CHI), M(UC_GREEK_SMALL_LETTER_PI), M(UC_GREEK_SMALL_LETTER_PHI), M(UC_GREEK_SMALL_LETTER_OMEGA), M(UC_GREEK_SMALL_LETTER_GAMMA), KC_TRNS,
+ KC_TRNS, M(UC_GREEK_SMALL_LETTER_UPSILON), M(UC_GREEK_SMALL_LETTER_IOTA), M(UC_GREEK_SMALL_LETTER_ALPHA), M(UC_GREEK_SMALL_LETTER_EPSILON), M(UC_GREEK_SMALL_LETTER_OMICRON),
+ KC_TRNS, KC_TRNS, M(UC_GREEK_SMALL_LETTER_THETA), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, M(UC_SUBSCRIPT_SIX), M(UC_SUBSCRIPT_SEVEN), M(UC_SUBSCRIPT_EIGHT), M(UC_SUBSCRIPT_NINE), M(UC_SUBSCRIPT_ZERO), KC_TRNS,
+ KC_TRNS, M(UC_GREEK_SMALL_LETTER_ETA), M(UC_GREEK_SMALL_LETTER_XI), M(UC_GREEK_SMALL_LETTER_KAPPA), M(UC_GREEK_SMALL_LETTER_LAMDA), KC_TRNS, M(UC_GREEK_SMALL_LETTER_ZETA),
+ /*-*/ M(UC_GREEK_SMALL_LETTER_SIGMA), M(UC_GREEK_SMALL_LETTER_NU), M(UC_GREEK_SMALL_LETTER_RHO), M(UC_GREEK_SMALL_LETTER_TAU), M(UC_GREEK_SMALL_LETTER_DELTA), M(UC_GREEK_SMALL_LETTER_FINAL_SIGMA),
+ KC_TRNS, M(UC_GREEK_SMALL_LETTER_BETA), M(UC_GREEK_SMALL_LETTER_MU), KC_TRNS, KC_TRNS, KC_TRNS, M(UC_GREEK_SMALL_LETTER_PSI),
+ /*-*/ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/*
+ * .------------------------------------.------------------------------------.
+ * | | | | | | | | | | | | | | |
+ * !-----+----+----+----+----+----------!-----+----+----+----+----+----+-----!
+ * | | Χ | Π | Φ | Ω | Γ | | | Η | Ξ | Κ | Λ | | Ζ |
+ * !-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+ * | | Υ | Ι | Α | Ε | Ο |-----!-----! Σ | Ν | Ρ | Τ | Δ | |
+ * !-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+ * | | | Θ | | | | | | Β | Μ | | | | Ψ |
+ * '-----+----+----+----+----+----------'----------+----+----+----+----+-----'
+ * | | | | | | ! | | | | |
+ * '------------------------' '------------------------'
+ * .-----------. .-----------.
+ * | | | ! | |
+ * .-----+-----+-----! !-----+-----+-----.
+ * ! ! | | ! | ! !
+ * ! ! !-----! !-----! ! !
+ * | | | | ! | | |
+ * '-----------------' '-----------------'
+ */
+[L5] = KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, M(UC_GREEK_CAPITAL_LETTER_CHI), M(UC_GREEK_CAPITAL_LETTER_PI), M(UC_GREEK_CAPITAL_LETTER_PHI), M(UC_GREEK_CAPITAL_LETTER_OMEGA), M(UC_GREEK_CAPITAL_LETTER_GAMMA), KC_TRNS,
+ KC_TRNS, M(UC_GREEK_CAPITAL_LETTER_UPSILON), M(UC_GREEK_CAPITAL_LETTER_IOTA), M(UC_GREEK_CAPITAL_LETTER_ALPHA), M(UC_GREEK_CAPITAL_LETTER_EPSILON), M(UC_GREEK_CAPITAL_LETTER_OMICRON),
+ KC_TRNS, KC_TRNS, M(UC_GREEK_CAPITAL_LETTER_THETA), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, M(UC_GREEK_CAPITAL_LETTER_ETA), M(UC_GREEK_CAPITAL_LETTER_XI), M(UC_GREEK_CAPITAL_LETTER_KAPPA), M(UC_GREEK_CAPITAL_LETTER_LAMDA), KC_TRNS, M(UC_GREEK_CAPITAL_LETTER_ZETA),
+ /*-*/ M(UC_GREEK_CAPITAL_LETTER_SIGMA), M(UC_GREEK_CAPITAL_LETTER_NU), M(UC_GREEK_CAPITAL_LETTER_RHO), M(UC_GREEK_CAPITAL_LETTER_TAU), M(UC_GREEK_CAPITAL_LETTER_DELTA), KC_TRNS,
+ KC_TRNS, M(UC_GREEK_CAPITAL_LETTER_BETA), M(UC_GREEK_CAPITAL_LETTER_MU), KC_TRNS, KC_TRNS, KC_TRNS, M(UC_GREEK_CAPITAL_LETTER_PSI),
+ /*-*/ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/*
+ * .------------------------------------.------------------------------------.
+ * | | | | | | | | | | | | | | |
+ * !-----+----+----+----+----+----------!-----+----+----+----+----+----+-----!
+ * | | | | | | | | | | | | | | |
+ * !-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+ * | | | | | | |-----!-----! | | | | | |
+ * !-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+ * | | | | | | | | | | | | | | |
+ * '-----+----+----+----+----+----------'----------+----+----+----+----+-----'
+ * | | | | | | ! | | | | |
+ * '------------------------' '------------------------'
+ * .-----------. .-----------.
+ * | | | ! | |
+ * .-----+-----+-----! !-----+-----+-----.
+ * ! ! | | ! | ! !
+ * ! ! !-----! !-----! ! !
+ * | | | | ! | | |
+ * '-----------------' '-----------------'
+ */
+[L6] = KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {};
+
+#define UC_MODE_WIN 0
+#define UC_MODE_LINUX 1
+#define UC_MODE_OSX 2
+
+// TODO: allow default mode to be configured
+static uint16_t unicode_mode = UC_MODE_WIN;
+
+uint16_t hextokeycode(uint8_t hex) {
+ if (hex == 0x0) {
+ return KC_P0;
+ }
+ if (hex < 0xA) {
+ return KC_P1 + (hex - 0x1);
+ }
+ return KC_A + (hex - 0xA);
+}
+
+void unicode_action_function(uint16_t hi, uint16_t lo) {
+ switch (unicode_mode) {
+ case UC_MODE_WIN:
+ register_code(KC_LALT);
+
+ register_code(KC_PPLS);
+ unregister_code(KC_PPLS);
+
+ register_code(hextokeycode((hi & 0xF0) >> 4));
+ unregister_code(hextokeycode((hi & 0xF0) >> 4));
+ register_code(hextokeycode((hi & 0x0F)));
+ unregister_code(hextokeycode((hi & 0x0F)));
+ register_code(hextokeycode((lo & 0xF0) >> 4));
+ unregister_code(hextokeycode((lo & 0xF0) >> 4));
+ register_code(hextokeycode((lo & 0x0F)));
+ unregister_code(hextokeycode((lo & 0x0F)));
+
+ unregister_code(KC_LALT);
+ break;
+ case UC_MODE_LINUX:
+ register_code(KC_LCTL);
+ register_code(KC_LSFT);
+
+ register_code(KC_U);
+ unregister_code(KC_U);
+
+ register_code(hextokeycode((hi & 0xF0) >> 4));
+ unregister_code(hextokeycode((hi & 0xF0) >> 4));
+ register_code(hextokeycode((hi & 0x0F)));
+ unregister_code(hextokeycode((hi & 0x0F)));
+ register_code(hextokeycode((lo & 0xF0) >> 4));
+ unregister_code(hextokeycode((lo & 0xF0) >> 4));
+ register_code(hextokeycode((lo & 0x0F)));
+ unregister_code(hextokeycode((lo & 0x0F)));
+
+ unregister_code(KC_LCTL);
+ unregister_code(KC_LSFT);
+ break;
+ case UC_MODE_OSX:
+ break;
+ }
+}
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) {
+ if (!record->event.pressed) {
+ return MACRO_NONE;
+ }
+ // MACRODOWN only works in this function
+ switch(id) {
+ case UM:
+ unicode_mode = (unicode_mode + 1) % 2;
+ break;
+
+case UC_GREEK_SMALL_LETTER_OMICRON:
+ unicode_action_function(0x03, 0xbf);
+ break;
+case UC_LEFTWARDS_ARROW:
+ unicode_action_function(0x21, 0x90);
+ break;
+case UC_GREEK_CAPITAL_LETTER_RHO:
+ unicode_action_function(0x03, 0xa1);
+ break;
+case UC_SUBSCRIPT_THREE:
+ unicode_action_function(0x20, 0x83);
+ break;
+case UC_VULGAR_FRACTION_ONE_EIGHTH:
+ unicode_action_function(0x21, 0x5b);
+ break;
+case UC_GREEK_SMALL_LETTER_LAMDA:
+ unicode_action_function(0x03, 0xbb);
+ break;
+case UC_VULGAR_FRACTION_ONE_THIRD:
+ unicode_action_function(0x21, 0x53);
+ break;
+case UC_GREEK_SMALL_LETTER_XI:
+ unicode_action_function(0x03, 0xbe);
+ break;
+case UC_THERE_DOES_NOT_EXIST:
+ unicode_action_function(0x22, 0x04);
+ break;
+case UC_SUPERSCRIPT_ONE:
+ unicode_action_function(0x00, 0xb9);
+ break;
+case UC_GREEK_SMALL_LETTER_BETA:
+ unicode_action_function(0x03, 0xb2);
+ break;
+case UC_SUBSCRIPT_FIVE:
+ unicode_action_function(0x20, 0x85);
+ break;
+case UC_GREEK_CAPITAL_LETTER_IOTA:
+ unicode_action_function(0x03, 0x99);
+ break;
+case UC_VULGAR_FRACTION_ONE_FIFTH:
+ unicode_action_function(0x21, 0x55);
+ break;
+case UC_GREEK_SMALL_LETTER_PSI:
+ unicode_action_function(0x03, 0xc8);
+ break;
+case UC_SUBSCRIPT_NINE:
+ unicode_action_function(0x20, 0x89);
+ break;
+case UC_SUPERSCRIPT_FOUR:
+ unicode_action_function(0x20, 0x74);
+ break;
+case UC_RIGHTWARDS_ARROW:
+ unicode_action_function(0x21, 0x92);
+ break;
+case UC_SUPERSCRIPT_SIX:
+ unicode_action_function(0x20, 0x76);
+ break;
+case UC_DOWNWARDS_ARROW:
+ unicode_action_function(0x21, 0x93);
+ break;
+case UC_GREEK_SMALL_LETTER_PI:
+ unicode_action_function(0x03, 0xc0);
+ break;
+case UC_SUPERSCRIPT_TWO:
+ unicode_action_function(0x00, 0xb2);
+ break;
+case UC_GREEK_CAPITAL_LETTER_OMEGA:
+ unicode_action_function(0x03, 0xa9);
+ break;
+case UC_GREEK_CAPITAL_LETTER_PSI:
+ unicode_action_function(0x03, 0xa8);
+ break;
+case UC_SUBSCRIPT_FOUR:
+ unicode_action_function(0x20, 0x84);
+ break;
+case UC_GREEK_CAPITAL_LETTER_NU:
+ unicode_action_function(0x03, 0x9d);
+ break;
+case UC_DIVISION_SIGN:
+ unicode_action_function(0x00, 0xf7);
+ break;
+case UC_GREEK_SMALL_LETTER_SIGMA:
+ unicode_action_function(0x03, 0xc3);
+ break;
+case UC_GREEK_SMALL_LETTER_RHO:
+ unicode_action_function(0x03, 0xc1);
+ break;
+case UC_VULGAR_FRACTION_ONE_SIXTH:
+ unicode_action_function(0x21, 0x59);
+ break;
+case UC_GREEK_SMALL_LETTER_GAMMA:
+ unicode_action_function(0x03, 0xb3);
+ break;
+case UC_VULGAR_FRACTION_TWO_THIRDS:
+ unicode_action_function(0x21, 0x54);
+ break;
+case UC_GREEK_SMALL_LETTER_NU:
+ unicode_action_function(0x03, 0xbd);
+ break;
+case UC_GREEK_SMALL_LETTER_ZETA:
+ unicode_action_function(0x03, 0xb6);
+ break;
+case UC_GREEK_SMALL_LETTER_EPSILON:
+ unicode_action_function(0x03, 0xb5);
+ break;
+case UC_GREEK_SMALL_LETTER_KAPPA:
+ unicode_action_function(0x03, 0xba);
+ break;
+case UC_SUPERSCRIPT_SEVEN:
+ unicode_action_function(0x20, 0x77);
+ break;
+case UC_GREEK_CAPITAL_LETTER_PI:
+ unicode_action_function(0x03, 0xa0);
+ break;
+case UC_GREEK_SMALL_LETTER_FINAL_SIGMA:
+ unicode_action_function(0x03, 0xc2);
+ break;
+case UC_GREEK_CAPITAL_LETTER_XI:
+ unicode_action_function(0x03, 0x9e);
+ break;
+case UC_GREEK_SMALL_LETTER_THETA:
+ unicode_action_function(0x03, 0xb8);
+ break;
+case UC_GREEK_SMALL_LETTER_ETA:
+ unicode_action_function(0x03, 0xb7);
+ break;
+case UC_SUBSCRIPT_TWO:
+ unicode_action_function(0x20, 0x82);
+ break;
+case UC_ASYMPTOTICALLY_EQUAL_TO:
+ unicode_action_function(0x22, 0x43);
+ break;
+case UC_GREEK_SMALL_LETTER_ALPHA:
+ unicode_action_function(0x03, 0xb1);
+ break;
+case UC_GREEK_CAPITAL_LETTER_PHI:
+ unicode_action_function(0x03, 0xa6);
+ break;
+case UC_GREEK_SMALL_LETTER_PHI:
+ unicode_action_function(0x03, 0xc6);
+ break;
+case UC_INFINITY:
+ unicode_action_function(0x22, 0x1e);
+ break;
+case UC_GREEK_CAPITAL_LETTER_OMICRON:
+ unicode_action_function(0x03, 0x9f);
+ break;
+case UC_ELEMENT_OF:
+ unicode_action_function(0x22, 0x08);
+ break;
+case UC_MULTIPLICATION_SIGN:
+ unicode_action_function(0x00, 0xd7);
+ break;
+case UC_SUBSCRIPT_ZERO:
+ unicode_action_function(0x20, 0x80);
+ break;
+case UC_GREEK_CAPITAL_LETTER_SIGMA:
+ unicode_action_function(0x03, 0xa3);
+ break;
+case UC_GREEK_SMALL_LETTER_OMEGA:
+ unicode_action_function(0x03, 0xc9);
+ break;
+case UC_SUBSCRIPT_ONE:
+ unicode_action_function(0x20, 0x81);
+ break;
+case UC_GREEK_CAPITAL_LETTER_ZETA:
+ unicode_action_function(0x03, 0x96);
+ break;
+case UC_GREEK_SMALL_LETTER_TAU:
+ unicode_action_function(0x03, 0xc4);
+ break;
+case UC_SUPERSCRIPT_FIVE:
+ unicode_action_function(0x20, 0x75);
+ break;
+case UC_THERE_EXISTS:
+ unicode_action_function(0x22, 0x03);
+ break;
+case UC_PLUS_MINUS_SIGN:
+ unicode_action_function(0x00, 0xb1);
+ break;
+case UC_VULGAR_FRACTION_THREE_QUARTERS:
+ unicode_action_function(0x00, 0xbe);
+ break;
+case UC_SUPERSCRIPT_THREE:
+ unicode_action_function(0x00, 0xb3);
+ break;
+case UC_EMPTY_SET:
+ unicode_action_function(0x22, 0x05);
+ break;
+case UC_UPWARDS_ARROW:
+ unicode_action_function(0x21, 0x91);
+ break;
+case UC_SUPERSCRIPT_NINE:
+ unicode_action_function(0x20, 0x79);
+ break;
+case UC_GREEK_SMALL_LETTER_DELTA:
+ unicode_action_function(0x03, 0xb4);
+ break;
+case UC_GREEK_SMALL_LETTER_MU:
+ unicode_action_function(0x03, 0xbc);
+ break;
+case UC_GREEK_CAPITAL_LETTER_KAPPA:
+ unicode_action_function(0x03, 0x9a);
+ break;
+case UC_SUBSCRIPT_EIGHT:
+ unicode_action_function(0x20, 0x88);
+ break;
+case UC_GREEK_CAPITAL_LETTER_ALPHA:
+ unicode_action_function(0x03, 0x91);
+ break;
+case UC_SUBSCRIPT_SEVEN:
+ unicode_action_function(0x20, 0x87);
+ break;
+case UC_GREEK_CAPITAL_LETTER_BETA:
+ unicode_action_function(0x03, 0x92);
+ break;
+case UC_GREEK_CAPITAL_LETTER_ETA:
+ unicode_action_function(0x03, 0x97);
+ break;
+case UC_SUPERSCRIPT_EIGHT:
+ unicode_action_function(0x20, 0x78);
+ break;
+case UC_SUPERSCRIPT_ZERO:
+ unicode_action_function(0x20, 0x70);
+ break;
+case UC_NOT_AN_ELEMENT_OF:
+ unicode_action_function(0x22, 0x09);
+ break;
+case UC_GREEK_SMALL_LETTER_UPSILON:
+ unicode_action_function(0x03, 0xc5);
+ break;
+case UC_NOT_EQUAL_TO:
+ unicode_action_function(0x22, 0x60);
+ break;
+case UC_GREEK_CAPITAL_LETTER_CHI:
+ unicode_action_function(0x03, 0xa7);
+ break;
+case UC_FOR_ALL:
+ unicode_action_function(0x22, 0x00);
+ break;
+case UC_GREEK_CAPITAL_LETTER_TAU:
+ unicode_action_function(0x03, 0xa4);
+ break;
+case UC_VULGAR_FRACTION_ONE_QUARTER:
+ unicode_action_function(0x00, 0xbc);
+ break;
+case UC_GREEK_SMALL_LETTER_CHI:
+ unicode_action_function(0x03, 0xc7);
+ break;
+case UC_GREEK_CAPITAL_LETTER_THETA:
+ unicode_action_function(0x03, 0x98);
+ break;
+case UC_GREEK_SMALL_LETTER_IOTA:
+ unicode_action_function(0x03, 0xb9);
+ break;
+case UC_GREEK_CAPITAL_LETTER_LAMDA:
+ unicode_action_function(0x03, 0x9b);
+ break;
+case UC_SUPERSCRIPT_LATIN_SMALL_LETTER_N:
+ unicode_action_function(0x20, 0x7f);
+ break;
+case UC_GREEK_CAPITAL_LETTER_UPSILON:
+ unicode_action_function(0x03, 0xa5);
+ break;
+case UC_GREEK_CAPITAL_LETTER_MU:
+ unicode_action_function(0x03, 0x9c);
+ break;
+case UC_GREEK_CAPITAL_LETTER_EPSILON:
+ unicode_action_function(0x03, 0x95);
+ break;
+case UC_GREEK_CAPITAL_LETTER_GAMMA:
+ unicode_action_function(0x03, 0x93);
+ break;
+case UC_SUBSCRIPT_SIX:
+ unicode_action_function(0x20, 0x86);
+ break;
+case UC_GREEK_CAPITAL_LETTER_DELTA:
+ unicode_action_function(0x03, 0x94);
+ break;
+case UC_VULGAR_FRACTION_ONE_HALF:
+ unicode_action_function(0x00, 0xbd);
+ break;
+ default:
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ case L1:
+ ergodox_right_led_1_on();
+ break;
+ case L2:
+ ergodox_right_led_2_on();
+ break;
+ case L3:
+ ergodox_right_led_3_on();
+ break;
+ case L4:
+ ergodox_right_led_1_on();
+ ergodox_right_led_2_on();
+ break;
+ case L5:
+ ergodox_right_led_1_on();
+ ergodox_right_led_3_on();
+ break;
+ // case L6:
+ // ergodox_right_led_2_on();
+ // ergodox_right_led_3_on();
+ // break;
+ // case L7:
+ // ergodox_right_led_1_on();
+ // ergodox_right_led_2_on();
+ // ergodox_right_led_3_on();
+ // break;
+ default:
+ ergodox_board_led_off();
+ break;
+ }
+};
diff --git a/keyboards/ergodox_ez/keymaps/german-manuneo/keymap.md b/keyboards/ergodox_ez/keymaps/german-manuneo/keymap.md
new file mode 100644
index 000000000..2c9e0a837
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/german-manuneo/keymap.md
@@ -0,0 +1,188 @@
+# ManuNeo Ergodox Keyboard Layout
+
+Compile this file to a `keymap.c` file using `compile_keymap.py`
+
+ python compile_keymap.py keymaps/german-manuneo/keymap.md
+
+Tested with python 2.7 and python 3.4
+
+
+# Layout Config
+
+ {
+ "layout": "ergodox_ez",
+ "keymaps_includes": [
+ "ergodox_ez.h",
+ "action_layer.h",
+ "keymap_common.h",
+ "keymap_extras/keymap_german.h",
+ ],
+ "key_prefixes": ["DE_", "KC_"],
+ "macros": {
+ // TODO: implement macros
+ // "MUC": "",
+ },
+ // TODO: implement default unicode mode
+ }
+
+
+# Layers
+
+
+## Layer 0
+
+ .------------------------------------.------------------------------------.
+ |MO(5)| 1 | 2 | 3 | 4 | 5 |ACUT | GRV | 6 | 7 | 8 | 9 | 0 |CIRC |
+ !-----+----+----+----+----+----------!-----+----+----+----+----+----+-----!
+ |MO(4)| X | P | F | W | G |HOME |TG(2)| H | J | K | L | Q | Z |
+ !-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+ |MO(1)| U | I | A | E | O |-----!-----! S | N | R | T | D | SS |
+ !-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+ |MO(3)| UE | OE | AE | C | V |END | TAB | B | M |COMM| DOT| UP | Y |
+ '-----+----+----+----+----+----------'----------+----+----+----+----+-----'
+ | | |LGUI|LALT|LCTL| !RCTL|RALT|LEFT|DOWN|RGHT|
+ '------------------------' '------------------------'
+ .-----------. .-----------.
+ |INS |TG(2)| !M(UM)|DELT |
+ .-----+-----+-----! !-----+-----+-----.
+ ! ! | APP | ! PGUP| ! !
+ ! ! !-----! !-----! ! !
+ |BSPC |LSFT | ESC | ! PGDN|ENTER|SPACE|
+ '-----------------' '-----------------'
+
+
+## Layer 1
+
+ .------------------------------------.------------------------------------.
+ | |EXLM|DQOT|PARA| | | | | | | | |RING| |
+ !-----+----+----+----+----+----------!-----+----+----+----+----+----+-----!
+ | |ASTR|PIPE|SLSH|LCBR|RCBR| | |HASH|LESS|MORE| |DQOT| |
+ !-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+ | |UNDS|MINS|AMPR|LBRC|RBRC|-----!-----!DLR |LPRN|RPRN|TILD|QUOT| QST |
+ !-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+ | | |PLUS|EQL | | | | |BSLS|PERC|SCLN|COLN| ↑ | |
+ '-----+----+----+----+----+----------'----------+----+----+----+----+-----'
+ | | | | | | ! | | ← | ↓ | → |
+ '------------------------' '------------------------'
+ .-----------. .-----------.
+ | | | ! | |
+ .-----+-----+-----! !-----+-----+-----.
+ ! ! | | ! | ! !
+ ! ! !-----! !-----! ! !
+ | | | | ! | | |
+ '-----------------' '-----------------'
+
+
+## Layer 2
+
+ .------------------------------------.------------------------------------.
+ | | F1 | F2 | F3 | F4 | F5 | F11 | F12 | F6 | F7 | F8 | F9 |F10 |PEQL |
+ !-----+----+----+----+----+----------!-----+----+----+----+----+----+-----!
+ | | | | | | | | | | P7 | P8 | P9 |PAST|PSLS |
+ !-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+ | | | | | | |-----!-----! | P4 | P5 | P6 |PMNS|PMNS |
+ !-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+ | | | | | | | | NLCK| | P1 | P2 | P3 |PPLS|PPLS |
+ '-----+----+----+----+----+----------'----------+----+----+----+----+-----'
+ | | | | | | ! P0 |PCMM|PDOT|PENT|PENT|
+ '------------------------' '------------------------'
+ .-----------. .-----------.
+ | | | ! | |
+ .-----+-----+-----! !-----+-----+-----.
+ ! ! | | ! | ! !
+ ! ! !-----! !-----! ! !
+ | | | | ! | | |
+ '-----------------' '-----------------'
+
+
+
+## Layer 3
+
+http://symbolcodes.tlt.psu.edu/bylanguage/mathchart.html
+
+ .------------------------------------.------------------------------------.
+ | | ¹ | ² | ³ | ⁴ | ⁵ | ∀ | | ⁶ | ⁷ | ⁸ | ⁹ | ⁰ | |
+ !-----+----+----+----+----+----------!-----+----+----+----+----+----+-----!
+ | | × | ½ | ÷ | ¼ | ⅕ | | | ⅙ | | ⅛ | | | |
+ !-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+ | | | ± | AT |EURO| ∅ |-----!-----! ∞ | ⁿ | ∃ | ∈ | | |
+ !-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+ | | ⅓ | ≠ | ⅔ | ¾ | ≃ | | |EXLM| | ∄ | ∉ | | |
+ '-----+----+----+----+----+----------'----------+----+----+----+----+-----'
+ | | | | | | ! | | | | |
+ '------------------------' '------------------------'
+ .-----------. .-----------.
+ | | | ! | |
+ .-----+-----+-----! !-----+-----+-----.
+ ! ! | | ! | ! !
+ ! ! !-----! !-----! ! !
+ | | | | ! | | |
+ '-----------------' '-----------------'
+
+
+## Layer 4
+
+
+ .------------------------------------.------------------------------------.
+ | | ₁ | ₂ | ₃ | ₄ | ₅ | | | ₆ | ₇ | ₈ | ₉ | ₀ | |
+ !-----+----+----+----+----+----------!-----+----+----+----+----+----+-----!
+ | | χ | π | φ | ω | γ | | | η | ξ | κ | λ | | ζ |
+ !-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+ | | υ | ι | α | ε | ο |-----!-----! σ | ν | ρ | τ | δ | ς |
+ !-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+ | | | θ | | | | | | β | μ | | | | ψ |
+ '-----+----+----+----+----+----------'----------+----+----+----+----+-----'
+ | | | | | | ! | | | | |
+ '------------------------' '------------------------'
+ .-----------. .-----------.
+ | | | ! | |
+ .-----+-----+-----! !-----+-----+-----.
+ ! ! | | ! | ! !
+ ! ! !-----! !-----! ! !
+ | | | | ! | | |
+ '-----------------' '-----------------'
+
+
+## Layer 5
+
+ .------------------------------------.------------------------------------.
+ | | | | | | | | | | | | | | |
+ !-----+----+----+----+----+----------!-----+----+----+----+----+----+-----!
+ | | Χ | Π | Φ | Ω | Γ | | | Η | Ξ | Κ | Λ | | Ζ |
+ !-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+ | | Υ | Ι | Α | Ε | Ο |-----!-----! Σ | Ν | Ρ | Τ | Δ | |
+ !-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+ | | | Θ | | | | | | Β | Μ | | | | Ψ |
+ '-----+----+----+----+----+----------'----------+----+----+----+----+-----'
+ | | | | | | ! | | | | |
+ '------------------------' '------------------------'
+ .-----------. .-----------.
+ | | | ! | |
+ .-----+-----+-----! !-----+-----+-----.
+ ! ! | | ! | ! !
+ ! ! !-----! !-----! ! !
+ | | | | ! | | |
+ '-----------------' '-----------------'
+
+
+## Layer 6
+
+ .------------------------------------.------------------------------------.
+ | | | | | | | | | | | | | | |
+ !-----+----+----+----+----+----------!-----+----+----+----+----+----+-----!
+ | | | | | | | | | | | | | | |
+ !-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+ | | | | | | |-----!-----! | | | | | |
+ !-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+ | | | | | | | | | | | | | | |
+ '-----+----+----+----+----+----------'----------+----+----+----+----+-----'
+ | | | | | | ! | | | | |
+ '------------------------' '------------------------'
+ .-----------. .-----------.
+ | | | ! | |
+ .-----+-----+-----! !-----+-----+-----.
+ ! ! | | ! | ! !
+ ! ! !-----! !-----! ! !
+ | | | | ! | | |
+ '-----------------' '-----------------'
+
diff --git a/keyboards/ergodox_ez/keymaps/german/keymap.c b/keyboards/ergodox_ez/keymaps/german/keymap.c
new file mode 100644
index 000000000..3eab51f0e
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/german/keymap.c
@@ -0,0 +1,185 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+#include "keymap_german.h"
+
+// Layer names
+#define BASE 0 // default layer
+#define SYMB 1 // symbol layer
+#define MDIA 2 // media keys
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | ^ | 1 | 2 | 3 | 4 | 5 | Play | | Next | 6 | 7 | 8 | 9 | 0 | ß |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Del | Q | W | E | R | T | L1 | | L2 | Z | U | I | O | P | Ü |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | Caps | A | S | D | F | G |------| |------| H | J | K | L | Ö | Ä/L2 |
+ * |--------+------+------+------+------+------| Hyper| | Meh |------+------+------+------+------+--------|
+ * | LShift | Y | X | C | V | B | | | | N | M | , | . |-/Ctrl| RShift |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | </L1 |#/Ctrl| ´ | - | + | | Right| Down | Up | Left | ~L1 |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | App | LGui | | Alt |Ctrl/Esc|
+ * ,------+------+------| |------+--------+------.
+ * | | | Home | | PgUp | | |
+ * | Space|Backsp|------| |------| Tab |Enter |
+ * | |ace | End | | PgDn | | |
+ * `--------------------' `----------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_CIRC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_MPLY,
+ KC_DELT, KC_Q, KC_W, KC_E, KC_R, KC_T, TG(1),
+ KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_LSFT, DE_Y, KC_X, KC_C, KC_V, KC_B, ALL_T(KC_NO),
+ LT(SYMB,DE_LESS),CTL_T(DE_HASH), DE_ACUT, DE_MINS, DE_PLUS,
+ ALT_T(KC_APP), KC_LGUI,
+ KC_HOME,
+ KC_SPC,KC_BSPC,KC_END,
+ // right hand
+ KC_MNXT, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
+ TG(2), DE_Z, KC_U, KC_I, KC_O, KC_P, DE_UE,
+ KC_H, KC_J, KC_K, KC_L, DE_OE, LT(MDIA,DE_AE),
+ MEH_T(KC_NO),KC_N, KC_M, KC_COMM, KC_DOT, CTL_T(DE_MINS), KC_RSFT,
+ KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, KC_FN1,
+ KC_LALT,CTL_T(KC_ESC),
+ KC_PGUP,
+ KC_PGDN,KC_TAB, KC_ENT
+ ),
+/* Keymap 1: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | . | 0 | = | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[SYMB] = KEYMAP(
+ // left hand
+ KC_TRNS,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS,DE_EXLM,DE_AT, DE_LCBR,DE_RCBR,DE_PIPE,KC_TRNS,
+ KC_TRNS,DE_HASH,DE_DLR, DE_LPRN,DE_RPRN,DE_GRV,
+ KC_TRNS,DE_PERC,DE_CIRC,DE_LBRC,DE_RBRC,DE_TILD,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_UP, KC_7, KC_8, KC_9, DE_ASTR, KC_F12,
+ KC_DOWN, KC_4, KC_5, KC_6, DE_PLUS, KC_TRNS,
+ KC_TRNS, DE_AMPR, KC_1, KC_2, KC_3, DE_BSLS, KC_TRNS,
+ KC_TRNS,KC_DOT, KC_0, DE_EQL, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/* Keymap 2: Media and mouse keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | Lclk | MsUp | Rclk | | | | | |VolDwn| Mute |VolUp | | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | Btn4 |MsLeft|MsDown|MsRght| Btn5 |------| |------| | Prev | Stop | Play | Next | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | |WhRght|WhDown| WhUp |WhLeft|WhClk | | | |BwSrch|BwBack|BwHome|BwRefr|BwFwd | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | |MsAcl0|MsAcl1|MsAcl2| | | | | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | |Brwser|Brwser|
+ * | Lclk | Rclk |------| |------|Back |Forwd |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// MEDIA AND MOUSE
+[MDIA] = KEYMAP(
+ KC_TRNS, KC_F1 , KC_F2 , KC_F3 , KC_F4 , KC_F5 , KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_BTN1, KC_MS_U, KC_BTN2, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_BTN4, KC_MS_L, KC_MS_D, KC_MS_R, KC_BTN5,
+ KC_TRNS, KC_WH_L, KC_WH_D, KC_WH_U, KC_WH_R, KC_BTN3, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_ACL0, KC_ACL1, KC_ACL2,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_BTN1, KC_BTN2, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6 , KC_F7 , KC_F8 , KC_F9 , KC_F10 , KC_F11,
+ KC_TRNS, KC_TRNS, KC_VOLD, KC_MUTE, KC_VOLU, KC_TRNS, KC_F12,
+ KC_TRNS, KC_MPRV, KC_MSTP, KC_MPLY, KC_MNXT, KC_TRNS,
+ KC_TRNS, KC_WSCH, KC_WBAK, KC_WHOM, KC_WREF, KC_WFWD, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_WBAK, KC_WFWD
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(SYMB) // FN1 - Momentary Layer 1 (Symbols)
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ case SYMB:
+ ergodox_right_led_1_on();
+ break;
+ case MDIA:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ ergodox_board_led_off();
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/j3rn/keymap.c b/keyboards/ergodox_ez/keymaps/j3rn/keymap.c
new file mode 100644
index 000000000..6e271321d
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/j3rn/keymap.c
@@ -0,0 +1,187 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define BASE 0 // default layer
+#define SYMB 1 // symbols
+#define MDIA 2 // media keys
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | Grv | 1 | 2 | 3 | 4 | 5 | [ | | ] | 6 | 7 | 8 | 9 | 0 | BkSp |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Tab | Q | W | E | R | T | - | | = | Y | U | I | O | P | \ |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * |Ctrl/Esc|A / L2| S | D | F | G |------| |------| H | J | K | L | ; | ' |
+ * |--------+------+------+------+------+------| Hyper| | Meh |------+------+------+------+------+--------|
+ * | LShift |Z/Ctrl| X | C | V | B | | | | N | M | , | . |//Ctrl| RShift |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | ~L1 | ~L2 |AltShf| Left | Right| | Up | Down | [ | ] | ~L1 |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | App | Home | | PgUp |Ctrl/Esc|
+ * ,------|------|------| |------+--------+------.
+ * | | | End | | PgDn | | |
+ * |Space | LGui |------| |------| Tab |Enter |
+ * | | |Shift | | Alt | | |
+ * `--------------------' `----------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_LBRC,
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_MINS,
+ CTL_T(KC_ESC), LT(MDIA, KC_A),KC_S, KC_D, KC_F, KC_G,
+ KC_LSFT, CTL_T(KC_Z), KC_X, KC_C, KC_V, KC_B, ALL_T(KC_NO),
+ KC_FN1, KC_FN2, LALT(KC_LSFT), KC_LEFT,KC_RGHT,
+
+ ALT_T(KC_APP), KC_HOME,
+ KC_END,
+ KC_SPC, KC_LGUI, KC_LSHIFT,
+ // right hand
+ KC_RBRC, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC,
+ KC_EQL, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSLS,
+ KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT,
+ MEH_T(KC_NO),KC_N, KC_M, KC_COMM,KC_DOT, CTL_T(KC_SLSH), KC_RSFT,
+ KC_UP, KC_DOWN,KC_LBRC,KC_RBRC, KC_FN1,
+
+ KC_PGUP, CTL_T(KC_ESC),
+ KC_PGDN,
+ KC_LALT, KC_TAB, KC_ENT
+ ),
+/* Keymap 1: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | . | 0 | = | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[SYMB] = KEYMAP(
+ // left hand
+ KC_TRNS,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS,KC_EXLM,KC_AT, KC_LCBR,KC_RCBR,KC_PIPE,KC_TRNS,
+ KC_TRNS,KC_HASH,KC_DLR, KC_LPRN,KC_RPRN,KC_GRV,
+ KC_TRNS,KC_PERC,KC_CIRC,KC_LBRC,KC_RBRC,KC_TILD,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_UP, KC_7, KC_8, KC_9, KC_ASTR, KC_F12,
+ KC_DOWN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS,
+ KC_TRNS, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS, KC_TRNS,
+ KC_TRNS,KC_DOT, KC_0, KC_EQL, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/* Keymap 2: Media and mouse keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | | | | | | | | | Lclk | Rclk | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | |------| |------|MsLeft|MsDown| MsUp |MsRght| | Play |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | | | | Prev | Next | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | |VolUp |VolDn | Mute | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | |Brwser|
+ * | | |------| |------| |Back |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// MEDIA AND MOUSE
+[MDIA] = KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2, KC_TRNS, KC_TRNS,
+ KC_MS_L, KC_MS_D, KC_MS_U, KC_MS_R, KC_TRNS, KC_MPLY,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MPRV, KC_MNXT, KC_TRNS, KC_TRNS,
+ KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_WBAK
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(SYMB), // FN1 - Momentary Layer 1 (Symbols)
+ [2] = ACTION_LAYER_TAP_TOGGLE(MDIA) // FN2 - Momentary Layer 2 (Media)
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case 1:
+ ergodox_right_led_1_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/j3rn/readme.md b/keyboards/ergodox_ez/keymaps/j3rn/readme.md
new file mode 100644
index 000000000..fc4b64042
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/j3rn/readme.md
@@ -0,0 +1,29 @@
+# J3RN's Mac-centric ErgoDox EZ keymap
+
+## Motivation
+
+Essentially, I wanted to switch to a layout that was less jarring than the default ErgoDox EZ layout, and did not require finger gymnastics to perform common OS X shortcuts (most of which involve the CMD (LGui) key).
+
+## How is it different from the default ErgoDox EZ layout?
+
+This layout more closely resembles that of the Mac keyboard, and has some other goodness baked in. Here is a rundown of what that means:
+
+### Mac-like changes
+
+- **The key to the left of "1" is "~" instead of "=".**
+- **The key to the right of "0" is Backspace instead of "-"** (misleadingly labeled "delete" on the Mac's keyboard). There was no room to fit in "-" and "=" between "0" and Backspace, unfortunately.
+- **The key to the left of "Q" is Tab instead of Delete.**
+- **The rightmost big key on the left thumb is CMD (LGui) instead of Backspace.**
+
+### Other changes
+
+- **The button to the left of "A" is Ctrl/Esc instead of Backspace.** This is actually how I have the keyboard on my Macbook set up to be, since it's loads more convenient than a CAPS LOCK key. This is the Ctrl key I find myself using most.
+- **Mouse uses Vim-style navigation**. To activate "Media mode," hold the 'a' key. This allows you to move the mouse around with hjkl just like in Vim. Additionally, right and left click are the conveniently placed 'i' and 'o' keys.
+- **The key to the right of "5" and the key to left of "6" are "[" and "]", respectively, instead of Left and Right.** There is a more convenient set of Left and Right already present. Truth be told, I don't really use these keys, as they are a stretch to reach.
+- **The Toggle L1 keys have been replaced by the otherwise displaced "-" and "=".** They are laid out, left-to-right, in the same order as on the Mac keyboard. Honestly, they are not terribly conveniently placed, and their placement might change in a later version. I found that I did not toggle L1 frequently at all, and found using the momentary keys to access L1 to fit my workflow better.
+- **The "~"/L1 key in the bottom-left is now just momentary L1.** The "~" key was moved to the top-left as mentioned before, and I like to keep my multi-use keys to a minimum due to the latency for them to switch from "press" to "hold."
+- **The Home and End buttons have been shifted up on the left thumb, and Shift inserted below them.** This makes doing Shift-5 and other such combinations less painful.
+- **The Page Up and Page Down buttons have been shifted up on the right thumb, and Alt was moved from above them to below them.** I use Alt more than Page Up or Page Down (mostly in terminal applications), and thought that it deserved a more accessible location.
+
+
+**I'm always open to feedback and/or suggestions!**
diff --git a/keyboards/ergodox_ez/keymaps/jack/keymap.c b/keyboards/ergodox_ez/keymaps/jack/keymap.c
new file mode 100644
index 000000000..80bf9d535
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/jack/keymap.c
@@ -0,0 +1,118 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+// TODO: Define layer names that make sense for the ErgoDox EZ.
+#define BASE 0 // default layer
+#define SYMB 1 // symbols
+#define MDIA 2 // media keys
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_NO, KC_1, KC_2, KC_3, KC_4, KC_5, KC_NO,
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_NO,
+ KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_NO,
+ KC_NO, KC_LCTL, KC_LALT,KC_LGUI, MO(2),
+ ALT_T(KC_APP), KC_LGUI,
+ KC_HOME,
+ KC_SPC,KC_SPC,KC_END,
+ // right hand
+ KC_NO, KC_6, KC_7, KC_8, KC_9, KC_0, KC_NO,
+ KC_NO, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC,
+ KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT,
+ KC_NO, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH, KC_ENT,
+ MO(1), KC_LEFT,KC_DOWN,KC_UP, KC_RGHT,
+ KC_NO, KC_NO,
+ KC_PGUP,
+ KC_PGDN, KC_SPC,KC_SPC
+ ),
+[SYMB] = KEYMAP(
+ // left hand
+ KC_TRNS,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_TRNS,
+ KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5,
+ KC_TRNS, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC,
+ KC_F6, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS,
+ KC_TRNS, KC_F12, KC_NO, KC_NO, KC_NO, RESET, KC_TRNS,
+ KC_TRNS, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+[MDIA] = KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_TRNS,
+ KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5,
+ KC_TRNS, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_BSPC,
+ KC_F6, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE,
+ KC_TRNS, KC_F12, KC_NO, KC_NO, KC_NO, RESET, KC_TRNS,
+ KC_TRNS, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(SYMB) // FN1 - Momentary Layer 1 (Symbols)
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case 1:
+ ergodox_right_led_1_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/jacobono/img/colemak-default-layer.png b/keyboards/ergodox_ez/keymaps/jacobono/img/colemak-default-layer.png
new file mode 100644
index 000000000..06f63c496
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/jacobono/img/colemak-default-layer.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/jacobono/img/number-dpad-layer.png b/keyboards/ergodox_ez/keymaps/jacobono/img/number-dpad-layer.png
new file mode 100644
index 000000000..4dd718278
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/jacobono/img/number-dpad-layer.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/jacobono/img/symbol-layer.png b/keyboards/ergodox_ez/keymaps/jacobono/img/symbol-layer.png
new file mode 100644
index 000000000..ee224cf0c
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/jacobono/img/symbol-layer.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/jacobono/keymap.c b/keyboards/ergodox_ez/keymaps/jacobono/keymap.c
new file mode 100644
index 000000000..6b19800af
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/jacobono/keymap.c
@@ -0,0 +1,273 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define COLEMAK 0 // new colemak layout
+#define QWERTY 1 // default layer
+#define SYMB 2 // symbols
+#define NUMPAD 3 // number pad
+#define MDIA 4 // media keys
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ /* Keymap 0: Basic COLEMAK layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | 1 | 2 | 3 | 4 | 5 | LEFT | | RIGHT| 6 | 7 | 8 | 9 | 0 | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Tab | Q | W | F | P | G | | | | J | L | U | Y | ; | TAB |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | BkSp | A | R | S | T | D |------| |------| H | N | E | I | O | DEL |
+ * |--------+------+------+------+------+------| | LGUI(TAB)------+------+------+------+------+--------|
+ * | LShift |Z/Ctrl| X | C | V | B | | | | K | M | , | . |//Ctrl| RShift |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | L1 | | | UP |MO(L2)| |MO(L2)| Down | | ALT | RGUI |
+ * `----------------------------------' `------------------------------------'
+ * ,-------------. ,---------------.
+ * | LGUI | App | |Ctrl/Esc| Alt |
+ * ,------|------|------| |--------+--------+------.
+ * | | |QUKSL | | QUKSL | | |
+ * |Space |ENTER |------| |--------| ENTER |Space |
+ * | | |MO(L3)| | MO(L3) | | |
+ * `--------------------' `------------------------'
+ */
+
+ // If it accepts an argument (i.e, is a function), it doesn't need KC_.
+ // Otherwise, it needs KC_*
+ [COLEMAK] = KEYMAP( // layer 0 : Colemak layout default layer
+ // left hand
+ KC_TRNS, KC_1, KC_2, KC_3, KC_4, KC_5, KC_LEFT,
+ KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_TRNS,
+ KC_BSPC, KC_A, KC_R, KC_S, KC_T, KC_D,
+ KC_LSFT, CTL_T(KC_Z), KC_X, KC_C, KC_V, KC_B, KC_TRNS,
+ TG(QWERTY), KC_TRNS, KC_TRNS,KC_UP, MO(SYMB),
+ KC_LGUI, KC_APP,
+ LGUI(S(KC_SPC)),
+ KC_SPC,KC_ENT,MO(NUMPAD),
+ // right hand
+ KC_RGHT, KC_6, KC_7, KC_8, KC_9, KC_0, KC_DELT,
+ KC_TRNS, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_TAB,
+ KC_H, KC_N, KC_E, KC_I, KC_O, KC_DEL,
+ LGUI(KC_TAB), KC_K, KC_M, KC_COMM, KC_DOT, CTL_T(KC_SLSH), KC_RSFT,
+ MO(SYMB), KC_DOWN, KC_TRNS, KC_RALT, KC_RGUI,
+ CTL_T(KC_ESC), KC_LALT,
+ LGUI(S(KC_SPC)),
+ MO(NUMPAD), KC_ENT, KC_SPC),
+
+ /* Keymap 1: Basic QWERTY layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | BkSp | 1 | 2 | 3 | 4 | 5 | LEFT | | RIGHT| 6 | 7 | 8 | 9 | 0 | DEL |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Tab | Q | W | E | R | T | L0 | | L0 | Y | U | I | O | P | \ |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | Ctrl | A | S | D | F | G |------| |------| H | J | K | L |; / L4| CTRL |
+ * |--------+------+------+------+------+------| Alt | | Alt |------+------+------+------+------+--------|
+ * | LShift |Z/Ctrl| X | C | V | B | | | | N | M | , | . |//Ctrl| RShift |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * |Grv/L3| '" |AltShf| Left |MO(L2)| |MO(L2)| Down | [ | ] | ~L3 |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,---------------.
+ * | Tab | BkSp | | Alt |Ctrl/Esc|
+ * ,------|------|------| |------+--------+------.
+ * | | | Home | | PgUp | | |
+ * | Space| LGUI |------| |------| RGUI |Enter |
+ * | | | End | | PgDn | | |
+ * `--------------------' `----------------------'
+ */
+ // If it accepts an argument (i.e, is a function), it doesn't need KC_.
+ // Otherwise, it needs KC_*
+ [QWERTY] = KEYMAP( // layer 1
+ // left hand
+ KC_BSPC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_LEFT,
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_TRNS,
+ KC_LCTRL, KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_LSFT, CTL_T(KC_Z), KC_X, KC_C, KC_V, KC_B, KC_LALT,
+ KC_TRNS, KC_QUOT, LALT(KC_LSFT), KC_LEFT, MO(SYMB),
+ KC_TAB, KC_DELT,
+ KC_HOME,
+ KC_SPC, KC_LGUI, KC_END,
+ // right hand
+ KC_RGHT, KC_6, KC_7, KC_8, KC_9, KC_0, KC_DELT,
+ KC_TRNS, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSLS,
+ KC_H, KC_J, KC_K, KC_L, LT(MDIA, KC_SCLN), KC_RCTRL,
+ KC_RALT, KC_N, KC_M, KC_COMM, KC_DOT, CTL_T(KC_SLSH), KC_RSFT,
+ MO(SYMB), KC_DOWN, KC_LBRC, KC_RBRC, KC_FN1,
+ KC_LALT, CTL_T(KC_ESC),
+ KC_PGUP,
+ KC_PGDN, KC_RGUI, KC_ENT),
+
+
+ /* Keymap 2: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | @ | * | = | _ | | | | ~ | { | } | # | : | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | ! | + | - | " |------| |------| " | ( | ) | ' | ` | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | % | ^ | $ | & | | | | ; | [ | ] | \ | / | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | | | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+ // SYMBOL
+ [SYMB] = KEYMAP(
+ // left hand
+ KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_AT, KC_ASTR, KC_EQL, KC_UNDS, KC_TRNS,
+ KC_TRNS, KC_PIPE, KC_EXLM, KC_PLUS, KC_MINS, S(KC_QUOTE),
+ KC_TRNS, KC_TRNS, KC_PERC, KC_CIRC, KC_DLR, KC_AMPR, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_TILD, KC_LCBR, KC_RCBR, KC_HASH, S(KC_SCLN), KC_F12,
+ S(KC_QUOTE),KC_LPRN, KC_RPRN, KC_QUOTE, KC_GRV, KC_TRNS,
+ KC_TRNS, KC_SCLN, KC_LBRC, KC_RBRC, KC_BSLS, KC_SLSH, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS),
+
+ /* Keymap 3: Numpad Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | UP | | | | | | $ | 7 | 8 | 9 | + | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | LEFT | DOWN | RIGHT| |------| |------| = | 4 | 5 | 6 | - | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | | | 1 | 2 | 3 | * | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | , | 0 | . | / | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+ // Numpad
+ [NUMPAD] = KEYMAP(
+ // left hand
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_UP,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_LEFT,KC_DOWN,KC_RIGHT,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_DLR, KC_7, KC_8, KC_9, KC_PLUS, KC_TRNS,
+ KC_EQL, KC_4, KC_5, KC_6, KC_MINS, KC_TRNS,
+ KC_TRNS, KC_AMPR, KC_1, KC_2, KC_3, KC_ASTR, KC_TRNS,
+ KC_COMMA,KC_0, KC_DOT, KC_SLSH, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS),
+
+ /* Keymap 4: Media and mouse keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | MsUp | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | |MsLeft|MsDown|MsRght| |------| |------| | | | | | Play |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | | | | Prev | Next | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | Lclk | Rclk | |VolUp |VolDn | Mute | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | |Brwser|
+ * | | |------| |------| |Back |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+ // MEDIA AND MOUSE
+ KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MPRV, KC_MNXT, KC_TRNS, KC_TRNS,
+ KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_WBAK),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(SYMB) // FN1 - Momentary Layer 1 (Symbols)
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case 1:
+ ergodox_right_led_1_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/jacobono/readme.md b/keyboards/ergodox_ez/keymaps/jacobono/readme.md
new file mode 100644
index 000000000..48de0509f
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/jacobono/readme.md
@@ -0,0 +1,34 @@
+# Default Layer #
+
+I'm using the colemak layer -- customized a bit to work a bit better when using spacemacs as my editor.
+
+![default-layer](img/colemak-default-layer.png)
+
+## Special Keys ##
+
+`SC1` => `LGUI + TAB`
+
+`SC2` => `LGUI + SPACE + TAB`
+
+`L1` => Switch to QWERTY Layout
+
+`T(L2)` => Toggle Symbol Layer
+
+`T(L3)` => Toggle Number and D-Pad Layer
+
+# QWERTY #
+
+Nothing special here -- just need this layer tucked away for the `WASD`. Which is literally the only reason I use it.
+Just have the same button to toggle back to colemak.
+
+# Symbol Layer #
+
+![symbol-layer](img/symbol-layer.png)
+
+This is just putting matching closing symbols next to each other -- useful when editing lisp.
+
+# Number and D-Pad Layer #
+
+Just a basic number layer with a D-PAD on the other side.
+
+![number-dpad-layer](img/number-dpad-layer.png)
diff --git a/keyboards/ergodox_ez/keymaps/jgarr/keymap.c b/keyboards/ergodox_ez/keymaps/jgarr/keymap.c
new file mode 100644
index 000000000..a3ad2040f
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/jgarr/keymap.c
@@ -0,0 +1,184 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define BASE 0 // default layer
+#define SYMB 1 // symbols
+#define MDIA 2 // media keys
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,-----------------------------------------------------.
+ * | Grv | 1 | 2 | 3 | 4 | 5 | Del | |Backspace| 6 | 7 | 8 | 9 | 0 | \ |
+ * |--------+------+------+------+------+-------------| |---------+------+------+------+------+------+--------|
+ * | Tab | ' | , | . | P | Y | L1 | | L1 | F | G | C | R | L | / |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * |Ctrl/Esc| A | O | E | U | I |------| |---------| D | H | T | N |S / L2| - |
+ * |--------+------+------+------+------+------| Hyper| | Meh |------+------+------+------+------+--------|
+ * | LShift |:/Ctrl| Q | J | K | X | | | | B | M | W | V |Z/Ctrl| RShift |
+ * `--------+------+------+------+------+-------------' `----------------+------+------+------+------+--------'
+ * | Ctrl | LGui | Alt | Left | Right| | Up | Down | [ | ] | = |
+ * `----------------------------------' `----------------------------------'
+ * ,--------------. ,-------------.
+ * | AltShf| LGui | | Alt | ~L1 |
+ * ,------|-------|------| |------+--------+------.
+ * | | | Home | | PgUp | | |
+ * | Space|Backsp |------| |------| Enter |Space |
+ * | |ace | End | | PgDn | | |
+ * `---------------------' `----------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_DELT,
+ KC_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, TG(1),
+ CTL_T(KC_ESC), KC_A, KC_O, KC_E, KC_U, KC_I,
+ KC_LSFT, CTL_T(KC_SCLN), KC_Q, KC_J, KC_K, KC_X, ALL_T(KC_NO),
+ KC_LCTL, KC_LGUI, KC_LALT, KC_LEFT, KC_RGHT,
+ LALT(KC_LSFT), KC_LGUI,
+ KC_HOME,
+ KC_SPC,KC_BSPC,KC_END,
+ // right hand
+ KC_BSPC, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSLS,
+ TG(1), KC_F, KC_G, KC_C, KC_R, KC_L, KC_SLSH,
+ KC_D, KC_H, KC_T, KC_N, LT(MDIA, KC_S), KC_MINS,
+ MEH_T(KC_NO),KC_B, KC_M, KC_W, KC_V, CTL_T(KC_Z), KC_RSFT,
+ KC_UP, KC_DOWN,KC_LBRC,KC_RBRC, KC_EQL,
+ KC_LALT, KC_FN1,
+ KC_PGUP,
+ KC_PGDN,KC_ENT, KC_SPC
+ ),
+/* Keymap 1: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | . | 0 | = | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[SYMB] = KEYMAP(
+ // left hand
+ KC_TRNS,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS,KC_EXLM,KC_AT, KC_LCBR,KC_RCBR,KC_PIPE,KC_TRNS,
+ KC_TRNS,KC_HASH,KC_DLR, KC_LPRN,KC_RPRN,KC_GRV,
+ KC_TRNS,KC_PERC,KC_CIRC,KC_LBRC,KC_RBRC,KC_TILD,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_UP, KC_7, KC_8, KC_9, KC_ASTR, KC_F12,
+ KC_DOWN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS,
+ KC_TRNS, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS, KC_TRNS,
+ KC_TRNS,KC_DOT, KC_0, KC_EQL, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/* Keymap 2: Media and mouse keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | MsUp | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | |MsLeft|MsDown|MsRght| |------| |------| | | | | | Play |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | | | | Prev | Next | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | Lclk | Rclk | |VolUp |VolDn | Mute | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | |Brwser|
+ * | | |------| |------| |Back |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// MEDIA AND MOUSE
+KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MPRV, KC_MNXT, KC_TRNS, KC_TRNS,
+ KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_WBAK
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(SYMB) // FN1 - Momentary Layer 1 (Symbols)
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case 1:
+ ergodox_right_led_1_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/kastyle/keymap.c b/keyboards/ergodox_ez/keymaps/kastyle/keymap.c
new file mode 100644
index 000000000..3982e0a19
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/kastyle/keymap.c
@@ -0,0 +1,184 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define BASE 0 // default layer
+#define SYMB 1 // symbols
+#define MDIA 2 // media keys
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | = | 1 | 2 | 3 | 4 | 5 | LGUI | | App | 6 | 7 | 8 | 9 | 0 | - |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Tab | Q | W | E | R | T | L1 | | L1 | Y | U | I | O | P | \ |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | LCtrl | A | S | D | F | G |------| |------| H | J | K | L |; / L2| ' |
+ * |--------+------+------+------+------+------| Hyper| | Meh |------+------+------+------+------+--------|
+ * | LShift |Z/Ctrl| X | C | V | B | | | | N | M | , | . |//Ctrl| RShift |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * |Grv/L1| '" |AltShf| Left | Right| | Up | Down | [ | ] | ~L1 |
+ * `----------------------------------' `----------------------------------'
+ * ,---------------. ,---------------.
+ * |Ctrl/Esc| Alt | | Alt |Ctrl/Esc|
+ * ,------|--------|------| |------+--------+------.
+ * | | | Home | | PgUp | | |
+ * |Backsp| Del |------| |------| Enter | Space|
+ * | | | End | | PgDn | | |
+ * `----------------------' `----------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_EQL, KC_1, KC_2, KC_3, KC_4, KC_5, KC_LGUI,
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, TG(1),
+ KC_LCTL, KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_LSFT, CTL_T(KC_Z), KC_X, KC_C, KC_V, KC_B, ALL_T(KC_NO),
+ LT(SYMB,KC_GRV),KC_QUOT, LALT(KC_LSFT), KC_LEFT,KC_RGHT,
+ CTL_T(KC_ESC), ALT_T(KC_APP),
+ KC_HOME,
+ KC_BSPC,KC_DEL,KC_END,
+ // right hand
+ KC_APP, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
+ TG(1), KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSLS,
+ KC_H, KC_J, KC_K, KC_L, LT(MDIA, KC_SCLN),KC_QUOT,
+ MEH_T(KC_NO),KC_N, KC_M, KC_COMM,KC_DOT, CTL_T(KC_SLSH), KC_RSFT,
+ KC_UP, KC_DOWN,KC_LBRC,KC_RBRC, KC_FN1,
+ KC_LALT, CTL_T(KC_ESC),
+ KC_PGUP,
+ KC_PGDN,KC_ENT, KC_SPC
+ ),
+/* Keymap 1: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | . | 0 | = | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[SYMB] = KEYMAP(
+ // left hand
+ KC_TRNS,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS,KC_EXLM,KC_AT, KC_LCBR,KC_RCBR,KC_PIPE,KC_TRNS,
+ KC_TRNS,KC_HASH,KC_DLR, KC_LPRN,KC_RPRN,KC_GRV,
+ KC_TRNS,KC_PERC,KC_CIRC,KC_LBRC,KC_RBRC,KC_TILD,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_UP, KC_7, KC_8, KC_9, KC_ASTR, KC_F12,
+ KC_DOWN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS,
+ KC_TRNS, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS, KC_TRNS,
+ KC_TRNS,KC_DOT, KC_0, KC_EQL, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/* Keymap 2: Media and mouse keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | MsUp | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | |MsLeft|MsDown|MsRght| |------| |------| | | | | | Play |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | | | | Prev | Next | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | Lclk | Rclk | |VolUp |VolDn | Mute | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | |Brwser|
+ * | | |------| |------| |Back |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// MEDIA AND MOUSE
+KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MPRV, KC_MNXT, KC_TRNS, KC_TRNS,
+ KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_WBAK
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(SYMB) // FN1 - Momentary Layer 1 (Symbols)
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case 1:
+ ergodox_right_led_1_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/kines-ish/keymap.c b/keyboards/ergodox_ez/keymaps/kines-ish/keymap.c
new file mode 100644
index 000000000..5063c99f2
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/kines-ish/keymap.c
@@ -0,0 +1,184 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define BASE 0 // default layer
+#define SYMB 1 // symbols
+#define MDIA 2 // media keys
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | = | 1 | 2 | 3 | 4 | 5 | LEFT | | RIGHT| 6 | 7 | 8 | 9 | 0 | - |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Tab | Q | W | E | R | T | L1 | | L1 | Y | U | I | O | P | \ |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | Caps | A | S | D | F | G |------| |------| H | J | K | L | ; | ' |
+ * |--------+------+------+------+------+------| Hyper| | Meh |------+------+------+------+------+--------|
+ * | LShift | Z | X | C | V | B | | | | N | M | , | . | / | RShift |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | Esc | Grv |Insert| Left | Right| | Up | Down | [ | ] | L2 |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | Ctrl | Alt | | LGui | Ctrl |
+ * ,------|------|------| |------+------+------.
+ * | | | Home | | PgUp | | |
+ * |Backsp| Del |------| |------| Enter| Space|
+ * |ace | | End | | PgDn | | |
+ * `--------------------' `--------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_EQL, KC_1, KC_2, KC_3, KC_4, KC_5, KC_LEFT,
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, TG(SYMB),
+ KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, ALL_T(KC_NO),
+ KC_ESC, KC_GRV, KC_INS, KC_LEFT, KC_RGHT,
+ KC_LCTL,KC_LALT,
+ KC_HOME,
+ KC_BSPC,KC_DEL,KC_END,
+ // right hand
+ KC_RGHT, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
+ TG(SYMB), KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSLS,
+ KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT,
+ MEH_T(KC_NO),KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH, KC_RSFT,
+ KC_UP, KC_DOWN,KC_LBRC,KC_RBRC, KC_FN2,
+ KC_LGUI, KC_RCTL,
+ KC_PGUP,
+ KC_PGDN, KC_ENT, KC_SPC
+ ),
+/* Keymap 1: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | PrScr | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | ScrLk | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | Pause | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | . | 0 | = | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[SYMB] = KEYMAP(
+ // left hand
+ KC_PSCR,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_SLCK,KC_EXLM,KC_AT, KC_LCBR,KC_RCBR,KC_PIPE,KC_TRNS,
+ KC_PAUS,KC_HASH,KC_DLR, KC_LPRN,KC_RPRN,KC_GRV,
+ KC_TRNS,KC_PERC,KC_CIRC,KC_LBRC,KC_RBRC,KC_TILD,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_UP, KC_7, KC_8, KC_9, KC_ASTR, KC_F12,
+ KC_DOWN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS,
+ KC_TRNS, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS, KC_TRNS,
+ KC_TRNS,KC_DOT, KC_0, KC_EQL, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/* Keymap 2: Media and mouse keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | MsUp | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | |MsLeft|MsDown|MsRght| |------| |------| | | | | | Play |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | | | | Prev | Next | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | Lclk | Rclk | |VolUp |VolDn | Mute | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | |Brwser|
+ * | | |------| |------| |Back |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// MEDIA AND MOUSE
+[MDIA] = KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MPRV, KC_MNXT, KC_TRNS, KC_TRNS,
+ KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_WBAK
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(SYMB) // FN1 - Momentary Layer 1 (Symbols)
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case 1:
+ ergodox_right_led_1_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/kines-ish/readme.md b/keyboards/ergodox_ez/keymaps/kines-ish/readme.md
new file mode 100644
index 000000000..5d39a0590
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/kines-ish/readme.md
@@ -0,0 +1,19 @@
+This keymap attempts to match the Kinesis Contoured (aka Advantage) default
+layout as closely as possible. See
+http://www.kinesis-ergo.com/wp-content/uploads/2013/06/advantage_layout_win.pdf
+
+Apart from the obvious mappings, this keymap also:
+
+* removes the dual-purpose momentary layer/normal keys: Z, /, and Grv;
+ because the author--coming from a Kinesis keyboard--finds the delays and
+ accidental modifiers to be more disconcerting than helpful.
+
+* puts Esc in the bottom left since there's no place for it in the top
+ left to match the Kinesis.
+
+* changes the bottom-right key into an L2 toggle since there's otherwise no
+ way to get to L2.
+
+* adds PrScr, ScrLk and Pause to the L1 keymap, down the left side, since
+ they're present on the Kinesis but not available in the default
+ ergodox_ez keymap.
diff --git a/keyboards/ergodox_ez/keymaps/mpiechotka/keymap.c b/keyboards/ergodox_ez/keymaps/mpiechotka/keymap.c
new file mode 100644
index 000000000..5bfef5995
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/mpiechotka/keymap.c
@@ -0,0 +1,276 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+#include "keymap_colemak.h"
+
+enum {
+ BASE = 0,
+ BASE_CM,
+ SYMB,
+ MACR
+};
+
+enum {
+ LWIN = 1,
+ PC1,
+ PC2,
+ PC3,
+ PC4,
+ DL_BASE,
+ DL_BASE_CM,
+};
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0a: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | = | 1 | 2 | 3 | 4 | 5 | LEFT | | RIGHT| 6 | 7 | 8 | 9 | 0 | - |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Del | Q | W | F | P | G | L1 | | L1 | J | L | U | Y | ; | \ |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | Esc | A | R | S | T | D |------| |------| H | N | E | I | O | ' |
+ * |--------+------+------+------+------+------| = | | - |------+------+------+------+------+--------|
+ * | LShift |Z/Ctrl| X | C | V | B | | | | K | M | , | . |//Ctrl| RShift |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * |Grv/L1| '" |AltShf| Left | Right| | Up | Down | [ | ] | ~L1 |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | LAlt | LGui | | LAlt | RAlt |
+ * ,------|------|------| |------+--------+------.
+ * | |Backsp| Home | | PgUp | | |
+ * | Space|ace/ |------| |------| Tab/ |Enter/|
+ * | /Shft|Ctrl | 1) | | 2) | Ctrl |Shift |
+ * `--------------------' `----------------------'
+ *
+ * 1) End/L1
+ * 2) PgDown/L2
+ */
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_EQL, KC_1, KC_2, KC_3, KC_4, KC_5, KC_LEFT,
+ KC_DELT, KC_Q, KC_W, KC_F, KC_P, KC_G, TG(SYMB),
+ KC_ESC, KC_A, KC_R, KC_S, KC_T, KC_D,
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_EQL,
+ LT(SYMB,KC_GRV),KC_QUOT, LALT(KC_LSFT), KC_LEFT, KC_RGHT,
+ KC_LALT, F(LWIN),
+ KC_HOME,
+ SFT_T(KC_SPC),CTL_T(KC_BSPC),LT(SYMB, KC_END),
+ // right hand
+ KC_RGHT, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
+ TG(SYMB), KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_BSLS,
+ KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT,
+ KC_MINS, KC_K, KC_M, KC_COMM,KC_DOT, CTL_T(KC_SLSH), KC_RSFT,
+ KC_UP, KC_DOWN,KC_LBRC,KC_RBRC, LT(SYMB,KC_NO),
+ KC_LALT, KC_RALT,
+ KC_PGUP,
+ LT(MACR,KC_PGDN),CTL_T(KC_TAB), SFT_T(KC_ENT)
+ ),
+/* Keymap 0b: Basic layer (Colemak keycodes or QWERTY)
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | = | 1 | 2 | 3 | 4 | 5 | LEFT | | RIGHT| 6 | 7 | 8 | 9 | 0 | - |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Del | Q | W | F | P | G | L1 | | L1 | J | L | U | Y | ; | \ |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | Esc | A | R | S | T | D |------| |------| H | N | E | I | O | ' |
+ * |--------+------+------+------+------+------| = | | - |------+------+------+------+------+--------|
+ * | LShift |Z/Ctrl| X | C | V | B | | | | K | M | , | . |//Ctrl| RShift |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * |Grv/L1| '" |AltShf| Left | Right| | Up | Down | [ | ] | ~L1 |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | LAlt | LGui | | LAlt | RAlt |
+ * ,------|------|------| |------+--------+------.
+ * | |Backsp| Home | | PgUp | | |
+ * | Space|ace/ |------| |------| Tab/ |Enter/|
+ * | /Shft|Ctrl | 1) | | 2) | Ctrl |Shift |
+ * `--------------------' `----------------------'
+ *
+ * 1) End/L1
+ * 2) PgDown/L2
+ */
+[BASE_CM] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_EQL, KC_1, KC_2, KC_3, KC_4, KC_5, KC_LEFT,
+ KC_DELT, CM_Q, CM_W, CM_F, CM_P, CM_G, TG(SYMB),
+ KC_ESC, CM_A, CM_R, CM_S, CM_T, CM_D,
+ KC_LSFT, CM_Z, CM_X, CM_C, CM_V, CM_B, KC_EQL,
+ LT(SYMB,KC_GRV),KC_QUOT, LALT(KC_LSFT), KC_LEFT, KC_RGHT,
+ KC_LALT, F(LWIN),
+ KC_HOME,
+ SFT_T(KC_SPC),CTL_T(KC_BSPC),LT(SYMB, KC_END),
+ // right hand
+ KC_RGHT, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
+ TG(SYMB), CM_J, CM_L, CM_U, CM_Y, KC_P, /*CM_SCLN*/ KC_BSLS,
+ CM_H, CM_N, CM_E, CM_I, CM_O, KC_QUOT,
+ KC_MINS, CM_K, CM_M, CM_COMM,CM_DOT, CTL_T(CM_SLSH), KC_RSFT,
+ KC_UP, KC_DOWN,KC_LBRC,KC_RBRC, LT(SYMB,KC_NO),
+ KC_LALT, KC_RALT,
+ KC_PGUP,
+ LT(MACR,KC_PGDN),CTL_T(KC_TAB), SFT_T(KC_ENT)
+ ),
+/* Keymap 1: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | . | 0 | = | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[SYMB] = KEYMAP(
+ // left hand
+ KC_TRNS,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS,KC_EXLM,KC_AT, KC_LCBR,KC_RCBR,KC_PIPE,KC_TRNS,
+ KC_TRNS,KC_HASH,KC_DLR, KC_LPRN,KC_RPRN,KC_GRV,
+ KC_TRNS,KC_PERC,KC_CIRC,KC_LBRC,KC_RBRC,KC_TILD,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_UP, KC_7, KC_8, KC_9, KC_ASTR, KC_F12,
+ KC_DOWN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS,
+ KC_TRNS, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS, KC_TRNS,
+ KC_TRNS,KC_DOT, KC_0, KC_EQL, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/* Keymap 2: Macros
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | DLa | DLb | | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | PC1 | PC2 | PC3 | PC4 | |------| |------| | | | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | | | | | | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | | | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// MACROS
+[MACR] = KEYMAP(
+ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+ KC_NO, F(DL_BASE),F(DL_BASE_CM),KC_NO, KC_NO, KC_NO, KC_NO,
+ KC_NO, F(PC1), F(PC2), F(PC3), F(PC4), KC_NO,
+ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [LWIN] = ACTION_MACRO(LWIN),
+ [PC1] = ACTION_MACRO(PC1),
+ [PC2] = ACTION_MACRO(PC2),
+ [PC3] = ACTION_MACRO(PC3),
+ [PC4] = ACTION_MACRO(PC4),
+ [DL_BASE] = ACTION_DEFAULT_LAYER_SET(BASE),
+ [DL_BASE_CM] = ACTION_DEFAULT_LAYER_SET(BASE_CM)
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ case LWIN:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ unregister_code(KC_RSFT);
+ register_code(KC_LGUI);
+ } else {
+ unregister_code(KC_LGUI);
+ }
+ break;
+ case PC1:
+ if (!record->event.pressed) {
+ return MACRO(T(SLCK), W(50), T(SLCK), W(50), T(1), W(50), T(ENT), END);
+ }
+ break;
+ case PC2:
+ if (!record->event.pressed) {
+ return MACRO(T(SLCK), W(50), T(SLCK), W(50), T(2), W(50), T(ENT), END);
+ }
+ break;
+ case PC3:
+ if (!record->event.pressed) {
+ return MACRO(T(SLCK), W(50), T(SLCK), W(50), T(3), W(50), T(ENT), END);
+ }
+ break;
+ case PC4:
+ if (!record->event.pressed) {
+ return MACRO(T(SLCK), W(50), T(SLCK), W(50), T(4), W(50), T(ENT), END);
+ }
+ break;
+ }
+ return MACRO_NONE;
+}
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case SYMB:
+ ergodox_right_led_1_on();
+ break;
+ case MACR:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ // none
+ break;
+ }
+};
diff --git a/keyboards/ergodox_ez/keymaps/mpiechotka/readme.md b/keyboards/ergodox_ez/keymaps/mpiechotka/readme.md
new file mode 100644
index 000000000..785400d1d
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/mpiechotka/readme.md
@@ -0,0 +1,6 @@
+# ErgoDox EZ mpiechotka Configuration
+
+Modification of ErgoDox EZ Colemak layout with additional QWERTY/software Colemak layer and change of the special keys.
+
+
+
diff --git a/keyboards/ergodox_ez/keymaps/msc/img/code_layer.png b/keyboards/ergodox_ez/keymaps/msc/img/code_layer.png
new file mode 100644
index 000000000..7b5efaae7
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/msc/img/code_layer.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/msc/img/main_layer.png b/keyboards/ergodox_ez/keymaps/msc/img/main_layer.png
new file mode 100644
index 000000000..65f92dda1
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/msc/img/main_layer.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/msc/img/media_layer.png b/keyboards/ergodox_ez/keymaps/msc/img/media_layer.png
new file mode 100644
index 000000000..a69799b07
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/msc/img/media_layer.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/msc/keymap.c b/keyboards/ergodox_ez/keymaps/msc/keymap.c
new file mode 100644
index 000000000..e567e513f
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/msc/keymap.c
@@ -0,0 +1,184 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define BASE 0 // default layer
+#define SYMB 1 // symbols
+#define MDIA 2 // media keys
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | = | 1 | 2 | 3 | 4 | 5 | LEFT | | RIGHT| 6 | 7 | 8 | 9 | 0 | - |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Del | Q | W | E | R | T | L1 | | L1 | Y | U | I | O | P | \ |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | BkSp | A | S | D | F | G |------| |------| H | J | K | L | ; |' / Cmd |
+ * |--------+------+------+------+------+------| Hyper| | Meh |------+------+------+------+------+--------|
+ * | LShift |Z/Ctrl| X | C | V | B | | | | N | M | , | . |//Ctrl| RShift |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | Cmd | Alt |AltShf| Left | Right| | Left | Down | Up |Right | L2 |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | App | LGui | | Alt |Ctrl/Esc|
+ * ,------|------|------| |------+--------+------.
+ * | | | Home | | PgUp | | |
+ * | Space|Backsp|------| |------| Tab |Enter |
+ * | |ace | End | | PgDn | | |
+ * `--------------------' `----------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_EQL, KC_1, KC_2, KC_3, KC_4, KC_5, KC_LEFT,
+ KC_DELT, KC_Q, KC_W, KC_E, KC_R, KC_T, TG(SYMB),
+ KC_BSPC, KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_LSFT, CTL_T(KC_Z), KC_X, KC_C, KC_V, KC_B, ALL_T(KC_NO),
+ KC_LGUI,KC_LALT, LALT(KC_LSFT), KC_LEFT,KC_RGHT,
+ ALT_T(KC_APP), KC_LGUI,
+ KC_HOME,
+ KC_SPC,KC_BSPC,KC_END,
+ // right hand
+ KC_RGHT, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
+ TG(SYMB), KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSLS,
+ KC_H, KC_J, KC_K, KC_L, KC_SCLN,GUI_T(KC_QUOT),
+ MEH_T(KC_NO),KC_N, KC_M, KC_COMM,KC_DOT, CTL_T(KC_SLSH), KC_RSFT,
+ KC_LEFT, KC_DOWN, KC_UP, KC_RIGHT, TG(MDIA),
+ KC_LALT, CTL_T(KC_ESC),
+ KC_PGUP,
+ KC_PGDN,KC_TAB, KC_ENT
+ ),
+/* Keymap 1: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | . | 0 | = | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[SYMB] = KEYMAP(
+ // left hand
+ KC_TRNS,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS,KC_EXLM,KC_AT, KC_LCBR,KC_RCBR,KC_PIPE,KC_TRNS,
+ KC_TRNS,KC_HASH,KC_DLR, KC_LPRN,KC_RPRN,KC_GRV,
+ KC_TRNS,KC_PERC,KC_CIRC,KC_LBRC,KC_RBRC,KC_TILD,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_UP, KC_7, KC_8, KC_9, KC_ASTR, KC_F12,
+ KC_DOWN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS,
+ KC_TRNS, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS, KC_TRNS,
+ KC_TRNS,KC_DOT, KC_0, KC_EQL, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/* Keymap 2: Media and mouse keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | MsUp | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | |MsLeft|MsDown|MsRght| |------| |------| | | | | | Play |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | | | Mute | | | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | Prev |VolDn |VolUp | Next | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | |Brwser|
+ * | Lclk | Rclk |------| |------| |Back |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// MEDIA AND MOUSE
+[MDIA] = KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_BTN1, KC_BTN2, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
+ KC_TRNS, KC_TRNS, KC_MUTE, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_MPRV, KC_VOLD, KC_VOLU, KC_MNXT, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_WBAK
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(SYMB) // FN1 - Momentary Layer 1 (Symbols)
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case 1:
+ ergodox_right_led_1_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/msc/readme.md b/keyboards/ergodox_ez/keymaps/msc/readme.md
new file mode 100644
index 000000000..0d14fcbd2
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/msc/readme.md
@@ -0,0 +1,32 @@
+# MSC Configuration
+
+### Based mostly on the ErgoDox EZ default layout with optimizations for coding on osx.
+
+#### Expecting the user to rely on Coder Layer this keymap removes some of the duplicate symbol keys in the lower portions of the board and replaces them with arrow keys and modifiers. The Media Layer is also updated to match the change in the arrow keys and the left and right click buttons are moved under the thumb position. The Media layer is now reached with toggle button in the lower right.
+
+### Main Layer
+
+![Main Layer](img/main_layer.png)
+
+### Code Layer
+
+![Code Layer](img/code_layer.png)
+
+### Media Layer
+
+![Media Layer](img/media_layer.png)
+
+## Changelog
+
+Version 1.0
+
+- Changed the temp code layer key in the bottom right to toggle media layer
+- Changed the temp media key to only be ";"
+- Changed right hand bottom row to match vim home row nav directions
+- Changed media keys to match arrow key changes
+- Changed media left and right click to spacebar and backspace locations
+- Changed bottom left to Cmd
+- Changed single quote on left bottom row to alt
+
+#### Coming Soon:
+- A new layer for Blender editing with a focus on left hand shortcut and a righthand num pad to control the view in Blender.
diff --git a/keyboards/ergodox_ez/keymaps/naps62/keymap.c b/keyboards/ergodox_ez/keymaps/naps62/keymap.c
new file mode 100644
index 000000000..d8c28423c
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/naps62/keymap.c
@@ -0,0 +1,187 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define BASE 0 // default layer
+#define SYMB 1 // symbols
+#define MDIA 2 // media keys
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | Esc | 1 ! | 2 @ | 3 # | 4 $ | 5 % | Lang | | Esc | 6 ^ | 7 & | 8 * | 9 ( | 0 ) | Bckspc |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Tab | Q | W | E | R | T | L2 | | L2 | Y | U | I | O | P | \ | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | Ctrl | A | S | D | F | G |------| |------| H | J | K | L | ; : | ' " |
+ * |--------+------+------+------+------+------| L1 | | L1 |------+------+------+------+------+--------|
+ * | LShift | Z | X | C | V | B | | | | N | M | , < | . > | / ? | - _ |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | L1 | ` ~ | ' " | \ | | L2 | | { | } | [ { | ] } | L1 |
+ * `----------------------------------' `----------------------------------'
+ * ,--------------. ,---------------.
+ * | Home | End | | PgUp |Insert |
+ * ,------|-------|------| |-------+-------+------.
+ * | | | LGui | | Del | | |
+ * | Space| Alt |------| |-------| Enter |Space |
+ * | | | LGui | | Bcsp | | |
+ * `---------------------' `----------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, LGUI(KC_SPC),
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, MO(2),
+ KC_LCTL, KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, MO(1),
+ MO(1), KC_GRV, KC_QUOT, KC_BSLS, MO(2),
+
+ KC_HOME, KC_END,
+ KC_LGUI,
+ KC_SPC, KC_LALT, KC_LGUI,
+
+ // right hand
+ KC_ESC, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC,
+ MO(2), KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSLS,
+ KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT,
+ MO(1), KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_MINS,
+ KC_LCBR, KC_RCBR, KC_LBRC, KC_RBRC, MO(1),
+
+ KC_PGUP, KC_INS,
+ KC_DEL,
+ KC_BSPC, KC_ENT, KC_SPC
+),
+/* Keymap 1: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | = | . | 0 | - | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[SYMB] = KEYMAP(
+ // left hand
+ KC_TRNS,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS,KC_EXLM,KC_AT, KC_LCBR,KC_RCBR,KC_PIPE,KC_TRNS,
+ KC_TRNS,KC_HASH,KC_DLR, KC_LPRN,KC_RPRN,KC_GRV,
+ KC_TRNS,KC_PERC,KC_CIRC,KC_LBRC,KC_RBRC,KC_TILD,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_UP, KC_7, KC_8, KC_9, KC_ASTR, KC_F12,
+ KC_DOWN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS,
+ KC_TRNS, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS, KC_TRNS,
+ KC_EQL,KC_DOT, KC_0, KC_MINS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/* Keymap 2: Media and mouse keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | |GuiUp | Expl | | Term | | | | | | | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | |GuiLft|GuiDwn|GuiRgt| | |------| |------| Left | Down | Up |Right | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | |Browsr| | | | |VolDwn|VolUp | Mute | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | Lclk | Rclk | | Play | Prev | Next | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | |Brwser|Brwser|
+ * | Lclk | Rclk |------| |------|Fwd |Back |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// MEDIA AND MOUSE
+KEYMAP(
+ RESET, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, LGUI(KC_W), LGUI(KC_E), KC_BTN1, LGUI(KC_T), KC_TRNS,
+ KC_TRNS, LGUI(KC_A), LGUI(KC_S), LGUI(KC_D), KC_MS_D, KC_MS_R,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_BTN1, KC_BTN2, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_LEFT, KC_DOWN, KC_UP, KC_RIGHT, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_VOLD, KC_VOLU, KC_MUTE, KC_TRNS, KC_TRNS,
+ KC_MPLY, KC_MPRV, KC_MNXT, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_WBAK, KC_WFWD
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(SYMB) // FN1 - Momentary Layer 1 (Symbols)
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case 1:
+ ergodox_right_led_1_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/naps62/readme.md b/keyboards/ergodox_ez/keymaps/naps62/readme.md
new file mode 100644
index 000000000..14728e4cc
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/naps62/readme.md
@@ -0,0 +1,29 @@
+# ErgoDox EZ naps62 Configuration
+
+## Motivation
+
+I wanted a layout that suited my Linux & Vim usage. I also didn't like the lack of efficient access to some of the more common special characters used in programming.
+
+## Key features / changes
+
+### Base Layer (L1)
+
+* **No `MT(mod, kc)` keys (modifier when pressed, key when tapped).** Those keys work with a global timeout. When a key press is shorter than the timeout, it's considered a tap, otherwise it's a hold. I couldn't find any particular timeout that would work for me. I need to use mods extremely fast, but also want the confort of using them more slowly in other occasions. So I gave up on this feature altogether.
+* **Direct access to `{}[]`.** When programming, these are used extremely often. I was still getting used to the coder layer, and I prefer the arrows on the home row, so I used the bottom-right keys for this.
+* **Layer keys everywhere.** I either use my little finger or my index finger to go to L1, whichever is more confortable in any given situation. L2 is not used while coding/writing, so I don't need an extremely-optimized access to it.
+* **Lang key.** This is nothing more than `Super-Space` combo, which in my systems (both Linux & Windows) is the shortcut to change the keyboard language. I'm Portuguese, so I often cycle between US layout for coding, and PT layout for writing.
+* **Special chars on the right-most column.** I only use Ctrl & Shift keys on the left side, so I used the right keys to include some of the more useful special characters as well.
+
+### Coder Layer (L2)
+
+* The `=` and `-` signs where nowhere to be found. `-` was already on the base layer, but it's still useful to have a fully-featured NumPad on the coder layer.
+
+### Media Layer (L3)
+
+* **Better media keys**. Why was Play/Pause so far away? And where was Mute? I put all my media keys close to each other, including the missing ones
+* **Arrow keys on home row.** I use vim, so I'm always on my home row. I use this sometimes to get around, but not as often as to need them on the base row. I'm fine with them here
+* I don't use mouse keys. They're still set up, and I made some changes as an experiment, but I mostly forgot they exist by now.
+
+## Author
+
+[Miguel Palhas](https://github.com/naps62)
diff --git a/keyboards/ergodox_ez/keymaps/ordinary/keymap.c b/keyboards/ergodox_ez/keymaps/ordinary/keymap.c
new file mode 100644
index 000000000..778cbc63c
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/ordinary/keymap.c
@@ -0,0 +1,454 @@
+#include "ergodox_ez.h"
+#include "led.h"
+#include "debug.h"
+#include "action_layer.h"
+#include "action_util.h"
+#include "mousekey.h"
+
+#define BASE 0 // default layer
+#define SYMB 1 // symbols layer
+#define MDIA 2 // media layer
+#define SPEC 3 // special layer
+
+#define LCaps 10 // left caps-shift key
+#define LSymb 11 // left symbol-shift key
+#define LMdia 12 // left media-shift key
+#define LSpec 13 // left special-shift key
+#define RCaps 14 // right caps-shift key
+#define RSymb 15 // right symbol-shift key
+#define RMdia 16 // right media-shift key
+#define RSpec 17 // right special-shift key
+
+#define MUL 20 // mouse up left
+#define MUR 21 // mouse up right
+#define MDL 22 // mouse down left
+#define MDR 23 // mouse down right
+
+/*
+ * The Ordinary Layout for the Ergodox EZ keyboard, v4
+ *
+ * Modifications from default by Nicholas Keene ergodoxez@nicholaskeene.com
+ *
+ * No rights reserved. This software is in the public domain.
+ * Credit me if you are friendly but if you're a jerk don't bother.
+ *
+ * Details: readme.md
+ * https://github.com/nrrkeene/qmk_firmware/tree/master/keyboard/ergodox_ez/keymaps/ordinary
+ */
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+
+/******* Base Layer ********************************************************************************************************
+ *
+ * ,------------------------------------------------------. ,------------------------------------------------------.
+ * | Special `~ | 1 | 2 | 3 | 4 | 5 | ESC | | - | 6 | 7 | 8 | 9 | 0 | =+ Special |
+ * |------------+------+------+------+------+-------------| |------+------+------+------+------+------+------------|
+ * | Media Tab | Q | W | E | R | T | [ | | ] | Y | U | I | O | P | \| Media |
+ * |------------+------+------+------+------+------| | | |------+------+------+------+------+------------|
+ * | Symbol | A | S | D | F | G |------| |------| H | J | K | L | ; | '" Symbol |
+ * |------------+------+------+------+------+------|Shift | | Tab |------+------+------+------+------+------------|
+ * | Capitals | Z | X | C | V | B | -Tab | | | N | M | , | . | / | Capitals |
+ * `------------+------+------+------+------+-------------' `-------------+------+------+------+------+------------'
+ * | LCtrl | Meh |Hyper | LAlt | LGui | | RGui | RAlt | Hyper| Meh | RCtrl |
+ * `-----------------------------------' `-----------------------------------'
+ * ,-------------. ,-------------.
+ * | Home | End | | Left | Right|
+ * ,------|------|------| |------+------+------.
+ * | | | PgUp | | Up | | |
+ * |Backsp| Del |------| |------| Enter| Space|
+ * | | | PgDn | | Down | | |
+ * `--------------------' `--------------------'
+ */
+[BASE] = KEYMAP(
+// left hand
+ F(LSpec),KC_1,KC_2,KC_3 ,KC_4 ,KC_5 ,KC_ESC
+,F(LMdia) ,KC_Q ,KC_W ,KC_E ,KC_R ,KC_T ,KC_LBRC
+,M(LSymb) ,KC_A ,KC_S ,KC_D ,KC_F ,KC_G
+,M(LCaps) ,KC_Z ,KC_X ,KC_C ,KC_V ,KC_B ,LSFT(KC_TAB)
+,KC_LCTL ,KC_MEH ,KC_HYPR,KC_LALT,KC_LGUI
+ ,KC_HOME,KC_END
+ ,KC_PGUP
+ ,KC_BSPC,KC_DEL ,KC_PGDN
+ // right hand
+ ,KC_MINS ,KC_6 ,KC_7 ,KC_8 ,KC_9 ,KC_0 ,F(RSpec)
+ ,KC_RBRC ,KC_Y ,KC_U ,KC_I ,KC_O ,KC_P ,F(RMdia)
+ ,KC_H ,KC_J ,KC_K ,KC_L ,KC_SCLN ,F(RSymb)
+ ,KC_TAB ,KC_N ,KC_M ,KC_COMM,KC_DOT ,KC_SLSH ,M(RCaps)
+ ,KC_RGUI,KC_RALT,KC_HYPR ,KC_MEH ,KC_RCTL
+ ,KC_LEFT ,KC_RGHT
+ ,KC_UP
+ ,KC_DOWN ,KC_ENT ,KC_SPC
+ ),
+
+/******* Symbols Layer *****************************************************************************************************
+ *
+ * ,-----------------------------------------------------. ,-----------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | Esc | | - | F6 | F7 | F8 | F9 | F10 | |
+ * |-----------+------+------+------+------+-------------| |------+------+------+------+------+------+-----------|
+ * | | ! | @ | { | } | & | < | | > | | | 7 | 8 | 9 | / | |
+ * |-----------+------+------+------+------+------| | | |------+------+------+------+------+-----------|
+ * | | # | $ | ( | ) | ` |------| |------| / | 4 | 5 | 6 | * | |
+ * |-----------+------+------+------+------+------| Tab | | Shift|------+------+------+------+------+-----------|
+ * | | % | ^ | [ | ] | ~ | | | -Tab| \ | 1 | 2 | 3 | - | |
+ * `-----------+------+------+------+------+-------------' `-------------+------+------+------+------+-----------'
+ * | LCtrl | Meh |Hyper | LAlt | LGui | |RGui/0|RAlt/.|Hypr/=|Meh/+ |RCtrl/Ent|
+ * `-----------------------------------' `-------------------------------------'
+ * ,-------------. ,-------------.
+ * | Left | Right| | Home | End |
+ * ,------|------|------| |------+------+------.
+ * | | | Up | | PgUp | | |
+ * |Space |Enter |------| |------|BackSp| Del |
+ * | | | Down | | PgDn | | |
+ * `--------------------' `--------------------'
+ */
+[SYMB] = KEYMAP(
+// left hand
+ KC_TRNS ,KC_F1 ,KC_F2 ,KC_F3 ,KC_F4 ,KC_F5 ,KC_ESC
+,KC_TRNS ,KC_EXLM ,KC_AT ,KC_LCBR ,KC_RCBR ,KC_AMPR ,LSFT(KC_COMM)
+,KC_TRNS ,KC_HASH ,KC_DLR ,KC_LPRN ,KC_RPRN ,KC_GRV
+,KC_TRNS ,KC_PERC ,KC_CIRC ,KC_LBRC ,KC_RBRC ,KC_TILD ,KC_TAB
+,KC_LCTL ,KC_MEH ,KC_HYPR,KC_LALT ,KC_LGUI
+ ,KC_LEFT ,KC_RGHT
+ ,KC_UP
+ ,KC_SPC ,KC_ENT ,KC_DOWN
+ // right hand
+ ,KC_MINS ,KC_F6 ,KC_F7 ,KC_F8 ,KC_F9 ,KC_F10 ,KC_TRNS
+ ,LSFT(KC_DOT),KC_PIPE ,KC_7 ,KC_8 ,KC_9 ,KC_SLSH ,KC_TRNS
+ ,KC_SLSH ,KC_4 ,KC_5 ,KC_6 ,KC_ASTR ,KC_TRNS
+ ,LSFT(KC_TAB),KC_BSLS ,KC_1 ,KC_2 ,KC_3 ,KC_MINS ,KC_TRNS
+ ,GUI_T(KC_0),ALT_T(KC_DOT),ALL_T(KC_EQL),MEH_T(KC_PLUS),CTL_T(KC_ENT)
+ ,KC_HOME ,KC_END
+ ,KC_PGUP
+ ,KC_PGDN ,KC_BSPC ,KC_DEL
+),
+
+/******* Media Layer *******************************************************************************************************
+ *
+ * ,---------------------------------------------------------------. ,---------------------------------------------------------------.
+ * | | F11 | F12 | F13 | F14 | F15 | Esc | | | F16 | F17 | F18 | F19 | F20 | |
+ * |------+---------+---------+---------+---------+----------------| |------+---------+---------+---------+---------+---------+------|
+ * | |Shut Down|MouseUpLf|Mouse Up |MouseUpRg|Volume Up|Scroll| |Scroll|PrintScrn| Home | Up | PgUp | Mail | |
+ * |------+---------+---------+---------+---------+---------| Up | | Up |---------+---------+---------+---------+---------+------|
+ * | | Sleep |MouseLeft|MouseDown|MouseRght|Volume Dn|------| |------| Num Lock| Left | Down | Right | MyComp | |
+ * |------+---------+---------+---------+---------+---------|Scroll| |Scroll|---------+---------+---------+---------+---------+------|
+ * | | |MouseDnLf|MouseDown|MouseDnRg| Mute | Down | | Down | | End | Down | PgDn | | |
+ * `------+---------+---------+---------+---------+----------------' `----------------+---------+---------+---------+---------+------'
+ * |LCtrl| Meh | MClick | LClick | R Click| |Cmd/Insrt|Optn/Del | Hyper | Meh |RCtrl|
+ * `---------------------------------------------' `---------------------------------------------'
+ * ,-------------. ,-------------.
+ * | Stop |Refrsh| | Prev | Next |
+ * ,------|------|------| |------+------+------.
+ * |Brwser|Brwser|Search| |VolUp | | |
+ * |Back | Fwd |------| |------| Stop | Play-|
+ * | | | Home | |VolDn | | Pause|
+ * `--------------------' `--------------------'
+ */
+[MDIA] = KEYMAP(
+// left hand
+ KC_TRNS ,KC_F11 ,KC_F12 ,KC_F13 ,KC_F14 ,KC_F15 ,KC_ESC
+,KC_TRNS ,KC_POWER ,M(MUL) ,KC_MS_U ,M(MUR) ,KC_VOLU ,KC_WH_U
+,KC_TRNS ,KC_SLEP ,KC_MS_L ,KC_MS_D ,KC_MS_R ,KC_VOLD
+,KC_TRNS ,KC_NO ,M(MDL) ,KC_MS_D ,M(MDR) ,KC_MUTE ,KC_WH_D
+,KC_LCTL ,KC_MEH ,KC_BTN3 ,KC_BTN1 ,KC_BTN2
+ ,KC_WSTP ,KC_WREF
+ ,KC_WSCH
+ ,KC_WBAK ,KC_NO ,KC_WHOM
+ // right hand
+ ,KC_NO ,KC_F16 ,KC_F17 ,KC_F18 ,KC_F19 ,KC_F20 ,KC_TRNS
+ ,KC_WH_U ,KC_PSCR ,KC_HOME ,KC_UP ,KC_PGUP ,KC_MAIL ,KC_TRNS
+ ,KC_NLCK ,KC_LEFT ,KC_DOWN ,KC_RIGHT,KC_MYCM ,KC_TRNS
+ ,KC_WH_D ,KC_NO ,KC_END ,KC_DOWN ,KC_PGDN ,KC_NO ,KC_TRNS
+ ,GUI_T(KC_INS),ALT_T(KC_DEL),KC_HYPR ,KC_MEH ,KC_RCTL
+ ,KC_MPRV ,KC_MNXT
+ ,KC_VOLU
+ ,KC_VOLD ,KC_MSTP ,KC_MPLY
+),
+
+/******* Special Layer *****************************************************************************************************
+ *
+ * ,-----------------------------------------------------. ,-----------------------------------------------------.
+ * | | Esc | | | | | | | | | | | | Bspc | |
+ * |-----------+------+------+------+------+-------------| |------+------+------+------+------+------+-----------|
+ * | | | | | | | | | | | | | | | |
+ * |-----------+------+------+------+------+------| | | |------+------+------+------+------+-----------|
+ * | | | | | | |------| |------| | | | | | |
+ * |-----------+------+------+------+------+------| | | |------+------+------+------+------+-----------|
+ * | | | | | | | | | | | | | | | RShift |
+ * `-----------+------+------+------+------+-------------' `-------------+------+------+------+------+-----------'
+ * | | | | | | | | | | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+[SPEC] = KEYMAP(
+// left hand
+ KC_TRNS ,KC_ESC ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+
+ ,KC_TRNS ,KC_TRNS
+ ,KC_TRNS
+ ,KC_TRNS,KC_TRNS ,KC_TRNS
+ // right hand
+ ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_BSPC ,KC_TRNS
+ ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+ ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+ ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_RSFT
+ ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS ,KC_TRNS
+
+ ,KC_TRNS ,KC_TRNS
+ ,KC_TRNS
+ ,KC_TRNS ,KC_TRNS ,KC_TRNS
+ )
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ // the faux shift keys are implemented as macro taps
+ [LCaps] = ACTION_MACRO_TAP(LCaps)
+ ,[LSymb] = ACTION_MACRO_TAP(LSymb)
+ ,[LMdia] = ACTION_MACRO_TAP(LMdia)
+ ,[LSpec] = ACTION_MACRO_TAP(LSpec)
+ ,[RCaps] = ACTION_MACRO_TAP(RCaps)
+ ,[RSymb] = ACTION_MACRO_TAP(RSymb)
+ ,[RMdia] = ACTION_MACRO_TAP(RMdia)
+ ,[RSpec] = ACTION_MACRO_TAP(RSpec)
+};
+
+uint16_t caps_shift = 0;
+uint16_t symb_shift = 0;
+uint16_t mdia_shift = 0;
+
+bool symb_lock = false;
+bool mdia_lock = false;
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ switch(id) {
+ // There are two shift keys for each layer so we increment a layer_shift var when one
+ // is pressed and decrement when one is released. If both are pressed at the same time
+ // then the layer is locked (or unlocked). The shift counts are bound between 0 and 2
+ // only because sometimes rapid pressing led to irregular events; this way the states
+ // are self healing during use.
+
+ case LCaps: // both caps-shift keys trigger Left Shift
+ case RCaps: // so they don't interfere with the magic combo
+ if (record->event.pressed && !record->tap.count) {
+ if(++caps_shift > 2) caps_shift = 2;
+ if(caps_shift == 2) {
+ register_code(KC_CAPS);
+ unregister_code(KC_CAPS);
+ } else if(caps_shift == 1) {
+ register_code(KC_LSFT);
+ }
+ } else {
+ if(--caps_shift < 0) caps_shift = 0;
+ if(caps_shift == 0) unregister_code(KC_LSFT);
+ }
+ break;
+
+ case LSymb:
+ if (record->event.pressed) {
+ if(++symb_shift > 2) symb_shift = 2;
+ if(symb_shift == 2) {
+ symb_lock = !symb_lock;
+ } else if(symb_shift == 1) {
+ layer_on(SYMB);
+ }
+ } else {
+ if(--symb_shift < 0) symb_shift = 0;
+ if((symb_shift == 0) && (!symb_lock)) layer_off(SYMB);
+ }
+ break;
+
+ case LMdia:
+ if (record->event.pressed) {
+ if (record->tap.count && (!mdia_shift) && (!mdia_lock)) {
+ register_code(KC_TAB);
+ } else {
+ if(++mdia_shift > 2) mdia_shift = 2;
+ if(mdia_shift == 2) {
+ mdia_lock = !mdia_lock;
+ } else if(mdia_shift == 1) {
+ layer_on(MDIA);
+ }
+ }
+ } else {
+ if(record->tap.count && (!mdia_shift) && (!mdia_lock)) {
+ unregister_code(KC_TAB);
+ } else {
+ if(--mdia_shift < 0) mdia_shift = 0;
+ if((!mdia_shift) && (!mdia_lock)) layer_off(MDIA);
+ }
+ }
+ break;
+
+ case LSpec:
+ if (record->event.pressed) {
+ if (record->tap.count && !record->tap.interrupted) {
+ register_code(KC_GRV);
+ } else {
+ layer_on(SPEC);
+ }
+ } else {
+ if(record->tap.count && !record->tap.interrupted) {
+ unregister_code(KC_GRV);
+ } else {
+ layer_off(SPEC);
+ }
+ }
+ break;
+
+ case RSymb:
+ if (record->event.pressed) {
+ if (record->tap.count && (!symb_shift) && (!symb_lock)) {
+ register_code(KC_QUOT);
+ } else {
+ if(++symb_shift > 2) symb_shift = 2;
+ if(symb_shift == 2) {
+ symb_lock = !symb_lock;
+ } else if(symb_shift == 1) {
+ layer_on(SYMB);
+ }
+ }
+ } else {
+ if(record->tap.count && symb_shift == 0) {
+ unregister_code(KC_QUOT);
+ } else {
+ if(--symb_shift < 0) symb_shift = 0;
+ if((!symb_shift) && (!symb_lock)) layer_off(SYMB);
+ }
+ }
+ break;
+
+ case RMdia:
+ if (record->event.pressed) {
+ if (record->tap.count && (!mdia_shift) && (!mdia_lock)) {
+ register_code(KC_BSLS);
+ } else {
+ if(++mdia_shift > 2) mdia_shift = 2;
+ if(mdia_shift == 2) {
+ mdia_lock = !mdia_lock;
+ } else if(mdia_shift == 1) {
+ layer_on(MDIA);
+ }
+ }
+ } else {
+ if(record->tap.count && (!mdia_shift) && (!mdia_lock)) {
+ unregister_code(KC_BSLS);
+ } else {
+ if(--mdia_shift < 0) mdia_shift = 0;
+ if((!mdia_shift) && (!mdia_lock)) layer_off(MDIA);
+ }
+ }
+ break;
+
+ case RSpec:
+ if (record->event.pressed) {
+ if (record->tap.count && !record->tap.interrupted) {
+ register_code(KC_EQL);
+ } else {
+ layer_on(SPEC);
+ }
+ } else {
+ if(record->tap.count && !record->tap.interrupted) {
+ unregister_code(KC_EQL);
+ } else {
+ layer_off(SPEC);
+ }
+ }
+ break;
+
+ // mouse diagonals
+
+ case MUL: // mouse up left
+ if (record->event.pressed) {
+ mousekey_on(KC_MS_UP);
+ mousekey_on(KC_MS_LEFT);
+ mousekey_send();
+ } else {
+ mousekey_off(KC_MS_UP);
+ mousekey_off(KC_MS_LEFT);
+ mousekey_send();
+ }
+ break;
+
+ case MUR: // mouse up right
+ if (record->event.pressed) {
+ mousekey_on(KC_MS_UP);
+ mousekey_on(KC_MS_RIGHT);
+ mousekey_send();
+ } else {
+ mousekey_off(KC_MS_UP);
+ mousekey_off(KC_MS_RIGHT);
+ mousekey_send();
+ }
+ break;
+
+ case MDL: // mouse down left
+ if (record->event.pressed) {
+ mousekey_on(KC_MS_DOWN);
+ mousekey_on(KC_MS_LEFT);
+ mousekey_send();
+ } else {
+ mousekey_off(KC_MS_DOWN);
+ mousekey_off(KC_MS_LEFT);
+ mousekey_send();
+ }
+ break;
+
+ case MDR: // mouse down right
+ if (record->event.pressed) {
+ mousekey_on(KC_MS_DOWN);
+ mousekey_on(KC_MS_RIGHT);
+ mousekey_send();
+ } else {
+ mousekey_off(KC_MS_DOWN);
+ mousekey_off(KC_MS_RIGHT);
+ mousekey_send();
+ }
+ break;
+
+ default:
+ // none
+ break;
+ }
+
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+ // shift or caps lock turns on red light
+ if(caps_shift || (keyboard_report->mods & MOD_BIT(KC_RSFT)) || (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK))) {
+ ergodox_right_led_1_on();
+ } else {
+ ergodox_right_led_1_off();
+ }
+
+ // Symbol layer turns on green light
+ if(layer_state & (1UL<<SYMB)) {
+ ergodox_right_led_2_on();
+ } else {
+ ergodox_right_led_2_off();
+ }
+
+ // Media layer turns on blue light
+ if(layer_state & (1UL<<MDIA)) {
+ ergodox_right_led_3_on();
+ } else {
+ ergodox_right_led_3_off();
+ }
+};
+
diff --git a/keyboards/ergodox_ez/keymaps/ordinary/ordinary-base.png b/keyboards/ergodox_ez/keymaps/ordinary/ordinary-base.png
new file mode 100644
index 000000000..9c561a10a
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/ordinary/ordinary-base.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/ordinary/ordinary-base.txt b/keyboards/ergodox_ez/keymaps/ordinary/ordinary-base.txt
new file mode 100644
index 000000000..25731ea2e
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/ordinary/ordinary-base.txt
@@ -0,0 +1,27 @@
+[{x:3.5},"#\n3",{x:10.5},"*\n8"],
+[{y:-0.875,x:2.5},"@\n2",{x:1},"$\n4",{x:8.5},"&\n7",{x:1},"(\n9"],
+[{y:-0.875,x:5.5},"%\n5",{c:"#ff4444"},"Esc",{x:4.5,c:"#cccccc"},"_\n\n\n\n\n\n-","^\n6"],
+[{y:-0.875,c:"#2277ff",w:1.5},"Special\n\n~\n\n\n\nShift\n`",{c:"#cccccc"},"!\n1",{x:14.5},")\n0",{c:"#2277ff",w:1.5},"+\n\nSpecial\n\n\n\n=\nShift"],
+[{y:-0.375,x:3.5,c:"#cccccc"},"E",{x:10.5},"I"],
+[{y:-0.875,x:2.5},"W",{x:1},"R",{x:8.5},"U",{x:1},"O"],
+[{y:-0.875,x:5.5},"T",{h:1.5},"{\n\n\n\n\n\n[",{x:4.5,h:1.5},"}\n\n\n\n\n\n]","Y"],
+[{y:-0.875,c:"#2277ff",w:1.5},"Media\n\nTab\n\n\n\nShift",{c:"#cccccc"},"Q",{x:14.5},"P",{c:"#2277ff",w:1.5},"|\n\\\nMedia\n\n\n\n\nShift"],
+[{y:-0.375,x:3.5,c:"#cccccc"},"D",{x:10.5},"K"],
+[{y:-0.875,x:2.5},"S",{x:1},"F",{x:8.5},"J",{x:1},"L"],
+[{y:-0.875,x:5.5},"G",{x:6.5},"H"],
+[{y:-0.875,c:"#2277ff",w:1.5},"Symbols\n\n\n\n\n\nShift",{c:"#cccccc"},"A",{x:14.5},":\n;",{c:"#2277ff",w:1.5},"\"\n'\nSymbols\n\n\n\n\nShift"],
+[{y:-0.625,x:6.5,c:"#54d6de",fa:[0,0,0,1],h:1.5},"< Tab\n\n\nShift Tab",{x:4.5,h:1.5},"Tab >\n\n\nTab"],
+[{y:-0.75,x:3.5,c:"#cccccc"},"C",{x:10.5},"<\n,"],
+[{y:-0.875,x:2.5},"X",{x:1},"V",{x:8.5},"M",{x:1},">\n."],
+[{y:-0.875,x:5.5},"B",{x:6.5},"N"],
+[{y:-0.875,c:"#2277ff",w:1.5},"Capitals\n\n\n\n\n\nShift",{c:"#cccccc"},"Z",{x:14.5},"?\n/",{c:"#2277ff",w:1.5},"\n\nCapitals\n\n\n\n\nShift"],
+[{y:-0.375,x:3.5,c:"#77aaff"},"Option\n\n\nLAlt",{x:10.5},"Option\n\n\nRAlt"],
+[{y:-0.875,x:2.5},"Hyper",{x:1},"Cmd\n\n\nSuper",{x:8.5},"Cmd\n\n\nSuper",{x:1},"Hyper"],
+[{y:-0.75,x:0.5},"Ctrl\n\n\nLCtrl","Meh",{x:14.5},"Meh","Ctrl\n\n\nRCtrl"],
+[{r:30,rx:6.5,ry:4.25,y:-1,x:1,c:"#54d6de"},"Home","End"],
+[{h:2},"< Del\n\n\nBackspace",{h:2},"Del >\n\n\nDelete","Page\n\n\n\n\n\nUp"],
+[{x:2},"Page\n\n\n\n\n\nDown"],
+[{r:-30,rx:13,y:-1,x:-3},"Left","Right"],
+[{x:-3},"Up",{h:2},"Enter",{h:2},"Space"],
+[{x:-3},"Down"]
+
diff --git a/keyboards/ergodox_ez/keymaps/ordinary/ordinary-media.png b/keyboards/ergodox_ez/keymaps/ordinary/ordinary-media.png
new file mode 100644
index 000000000..99e5ed80b
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/ordinary/ordinary-media.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/ordinary/ordinary-media.txt b/keyboards/ergodox_ez/keymaps/ordinary/ordinary-media.txt
new file mode 100644
index 000000000..4eccc9f35
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/ordinary/ordinary-media.txt
@@ -0,0 +1,27 @@
+[{x:3.5,c:"#99de2a"},"F13",{x:10.5},"F18"],
+[{y:-0.875,x:2.5},"F12",{x:1},"F14",{x:8.5},"F17",{x:1},"F19"],
+[{y:-0.875,x:5.5},"F15",{c:"#ff4444"},"Esc",{x:4.5,c:"#737373",a:7},"",{c:"#99de2a",a:4},"F16"],
+[{y:-0.875,c:"#2277ff",w:1.5},"Special\n\n\n\n\n\nShift",{c:"#99de2a"},"F11",{x:14.5},"F20",{c:"#2277ff",w:1.5},"\n\nSpecial\n\n\n\n\nShift"],
+[{y:-0.375,x:3.5,c:"#ff8500"},"Mouse\n\n\n\n\n\nUp",{x:10.5},"Cursor\n\n\n\n\n\nUp"],
+[{y:-0.875,x:2.5},"Mouse\n\n\n\n\n\nUpLeft",{x:1},"Mouse\n\n\n\n\n\nUpRgt",{x:8.5,c:"#ffb063"},"Home",{x:1},"Page\n\n\n\n\n\nUp"],
+[{y:-0.875,x:5.5,c:"#e6e067"},"Vol\n\n\n\n\n\nUp",{c:"#ffb063",h:1.5},"Scroll\n\n\n\n\n\nUp",{x:4.5,h:1.5},"Scroll\n\n\n\n\n\nUp",{c:"#e6e067"},"Print\n\n\n\n\n\nScreen"],
+[{y:-0.875,c:"#000000",t:"#ff0000",w:1.5},"Media\n\n\n\n\n\nShift",{c:"#e6e067",t:"#000000"},"Shut\n\n\n\n\n\nDown",{x:14.5},"Mail",{c:"#000000",t:"#ff0000",w:1.5},"\n\nMedia\n\n\n\n\nShift"],
+[{y:-0.375,x:3.5,c:"#ff8500",t:"#000000"},"Mouse\n\n\n\n\n\nDown",{x:10.5},"Cursor\n\n\n\n\n\nDown"],
+[{y:-0.875,x:2.5},"Mouse\n\n\n\n\n\nLeft",{x:1},"Mouse\n\n\n\n\n\nRight",{x:8.5},"Cursor\n\n\n\n\n\nLeft",{x:1},"Cursor\n\n\n\n\n\nRight"],
+[{y:-0.875,x:5.5,c:"#e6e067"},"Vol\n\n\n\n\n\nDown",{x:6.5},"Num\n\n\n\n\n\nLock"],
+[{y:-0.875,c:"#2277ff",w:1.5},"Symbols\n\n\n\n\n\nShift",{c:"#e6e067"},"Sleep",{x:14.5},"My\n\n\n\n\n\nComp",{c:"#2277ff",w:1.5},"\n\nSymbols\n\n\n\n\nShift"],
+[{y:-0.625,x:6.5,c:"#ffb063",h:1.5},"Scroll\n\n\n\n\n\nDown",{x:4.5,h:1.5},"Scroll\n\n\n\n\n\nDown"],
+[{y:-0.75,x:3.5,c:"#ff8500"},"Mouse\n\n\n\n\n\nDown",{x:10.5},"Cursor\n\n\n\n\n\nDown"],
+[{y:-0.875,x:2.5},"Mouse\n\n\n\n\n\nDnLeft",{x:1},"Mouse\n\n\n\n\n\nDnRgt",{x:8.5,c:"#ffb063"},"End",{x:1},"Page\n\n\n\n\n\nDown"],
+[{y:-0.875,x:5.5,c:"#e6e067"},"Mute",{x:6.5,c:"#737373",a:7},""],
+[{y:-0.875,c:"#2277ff",a:4,w:1.5},"Capitals\n\n\n\n\n\nShift",{c:"#737373",a:7},"",{x:14.5},"",{c:"#2277ff",a:4,w:1.5},"\n\nCapitals\n\n\n\n\nShift"],
+[{y:-0.375,x:3.5,c:"#ff8500"},"Middle\n\n\n\n\n\nClick",{x:10.5,c:"#ffb063",fa:[0,0,0,1]},"Delete\n\n\nOption"],
+[{y:-0.875,x:2.5,c:"#ff8500"},"Left\n\n\n\n\n\nClick",{x:1},"Right\n\n\n\n\n\nClick",{x:8.5,c:"#ffb063"},"Insert\n\n\nCmd",{x:1,c:"#77aaff"},"Hyper"],
+[{y:-0.75,x:0.5},"Ctrl\n\n\nLCtrl","Meh",{x:14.5},"Meh","Crtl\n\n\nRCtrl"],
+[{r:30,rx:6.5,ry:4.25,y:-1,x:1,c:"#ccbb00"},"Stop\n\n\nBrowser","Reload\n\n\nBrowser"],
+[{h:2},"< Web\n\n\nBrowser",{h:2},"Web >\n\n\nBrowser","Search\n\n\nBrowser"],
+[{x:2},"Home\n\n\nBrowser"],
+[{r:-30,rx:13,y:-1,x:-3},"Prev\n\n\nAudio\n\n\nTrack","Next\n\n\nAudio\n\n\nTrack"],
+[{x:-3,c:"#e6e067"},"Vol\n\n\n\n\n\nUp",{c:"#ccbb00",h:2},"Stop\n\n\nAudio",{h:2},"Play\n\n\nAudio\n\n\nPause"],
+[{x:-3,c:"#e6e067"},"Vol\n\n\n\n\n\nDown"]
+
diff --git a/keyboards/ergodox_ez/keymaps/ordinary/ordinary-special.png b/keyboards/ergodox_ez/keymaps/ordinary/ordinary-special.png
new file mode 100644
index 000000000..6eecf447e
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/ordinary/ordinary-special.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/ordinary/ordinary-special.txt b/keyboards/ergodox_ez/keymaps/ordinary/ordinary-special.txt
new file mode 100644
index 000000000..a08827c6d
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/ordinary/ordinary-special.txt
@@ -0,0 +1,27 @@
+[{x:3.5,a:7},"",{x:10.5},""],
+[{y:-0.875,x:2.5},"",{x:1},"",{x:8.5},"",{x:1},""],
+[{y:-0.875,x:5.5},"",{c:"#ff4444",a:4},"Esc",{x:4.5,c:"#cccccc",a:7},"",""],
+[{y:-0.875,c:"#000000",t:"#ff0000",a:4,w:1.5},"Special\n\n\n\n\n\nShift",{c:"#ff4444",t:"#000000"},"Esc",{x:14.5,c:"#54d6de"},"Back\n\n\n\n\n\nspace",{c:"#000000",t:"#ff0000",w:1.5},"\n\nSpecial\n\n\n\n\nShift"],
+[{y:-0.375,x:3.5,c:"#cccccc",t:"#000000",a:7},"",{x:10.5},""],
+[{y:-0.875,x:2.5},"",{x:1},"",{x:8.5},"",{x:1},""],
+[{y:-0.875,x:5.5},"",{h:1.5},"",{x:4.5,h:1.5},"",""],
+[{y:-0.875,w:1.5},"","",{x:14.5},"",{w:1.5},""],
+[{y:-0.375,x:3.5},"",{x:10.5},""],
+[{y:-0.875,x:2.5},"",{x:1},"",{x:8.5},"",{x:1},""],
+[{y:-0.875,x:5.5},"",{x:6.5},""],
+[{y:-0.875,w:1.5},"","",{x:14.5},"",{w:1.5},""],
+[{y:-0.625,x:6.5,h:1.5},"",{x:4.5,h:1.5},""],
+[{y:-0.75,x:3.5},"",{x:10.5},""],
+[{y:-0.875,x:2.5},"",{x:1},"",{x:8.5},"",{x:1},""],
+[{y:-0.875,x:5.5},"",{x:6.5},""],
+[{y:-0.875,w:1.5},"","",{x:14.5},"",{c:"#2277ff",w:1.5},"RShift"],
+[{y:-0.375,x:3.5,c:"#cccccc"},"",{x:10.5},""],
+[{y:-0.875,x:2.5},"",{x:1},"",{x:8.5},"",{x:1},""],
+[{y:-0.75,x:0.5},"","",{x:14.5},"",""],
+[{r:30,rx:6.5,ry:4.25,y:-1,x:1},"",""],
+[{h:2},"",{h:2},"",""],
+[{x:2},""],
+[{r:-30,rx:13,y:-1,x:-3},"",""],
+[{x:-3},"",{h:2},"",{h:2},""],
+[{x:-3},""]
+
diff --git a/keyboards/ergodox_ez/keymaps/ordinary/ordinary-symbol.png b/keyboards/ergodox_ez/keymaps/ordinary/ordinary-symbol.png
new file mode 100644
index 000000000..e4de64a96
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/ordinary/ordinary-symbol.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/ordinary/ordinary-symbol.txt b/keyboards/ergodox_ez/keymaps/ordinary/ordinary-symbol.txt
new file mode 100644
index 000000000..e199f5c59
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/ordinary/ordinary-symbol.txt
@@ -0,0 +1,27 @@
+[{x:3.5,c:"#99de2a"},"F3",{x:10.5},"F8"],
+[{y:-0.875,x:2.5},"F2",{x:1},"F4",{x:8.5},"F7",{x:1},"F9"],
+[{y:-0.875,x:5.5},"F5",{c:"#ff4444"},"Esc",{x:4.5,c:"#bbddbb"},"_\n\n\n\n\n\n-",{c:"#99de2a"},"F6"],
+[{y:-0.875,c:"#2277ff",w:1.5},"Special\n\n\n\n\n\nShift",{c:"#99de2a"},"F1",{x:14.5},"F10",{c:"#2277ff",w:1.5},"\n\nSpecial\n\n\n\n\nShift"],
+[{y:-0.375,x:3.5,c:"#bbddbb"},"{",{x:10.5,c:"#89b087"},"8"],
+[{y:-0.875,x:2.5,c:"#bbddbb"},"@",{x:1},"}",{x:8.5,c:"#89b087"},"7",{x:1},"9"],
+[{y:-0.875,x:5.5,c:"#bbddbb"},"&",{h:1.5},"<",{x:4.5,h:1.5},">","|"],
+[{y:-0.875,c:"#2277ff",w:1.5},"Media\n\n\n\n\n\nShift",{c:"#bbddbb"},"!",{x:14.5,c:"#89b087"},"/",{c:"#2277ff",w:1.5},"\n\nMedia\n\n\n\n\nShift"],
+[{y:-0.375,x:3.5,c:"#bbddbb"},"(",{x:10.5,c:"#89b087"},"5"],
+[{y:-0.875,x:2.5,c:"#bbddbb"},"$",{x:1},")",{x:8.5,c:"#89b087"},"4",{x:1},"6"],
+[{y:-0.875,x:5.5,c:"#bbddbb"},"`",{x:6.5},"/"],
+[{y:-0.875,c:"#000000",t:"#ff0000",w:1.5},"Symbols\n\n\n\n\n\nShift",{c:"#bbddbb",t:"#000000"},"#",{x:14.5,c:"#89b087"},"*",{c:"#000000",t:"#ff0000",w:1.5},"\n\nSymbols\n\n\n\n\nShift"],
+[{y:-0.625,x:6.5,c:"#54d6de",t:"#000000",fa:[0,0,0,1],h:1.5},"Tab >\n\n\nTab",{x:4.5,h:1.5},"< Tab\n\n\nShift Tab"],
+[{y:-0.75,x:3.5,c:"#bbddbb"},"[",{x:10.5,c:"#89b087"},"2"],
+[{y:-0.875,x:2.5,c:"#bbddbb"},"^",{x:1},"]",{x:8.5,c:"#89b087"},"1",{x:1},"3"],
+[{y:-0.875,x:5.5,c:"#bbddbb"},"~",{x:6.5},"\\"],
+[{y:-0.875,c:"#2277ff",w:1.5},"Capitals\n\n\n\n\n\nShift",{c:"#bbddbb"},"%",{x:14.5,c:"#89b087"},"-",{c:"#2277ff",w:1.5},"\n\nCapitals\n\n\n\n\nShift"],
+[{y:-0.375,x:3.5,c:"#77aaff"},"Option\n\n\nLAlt",{x:10.5,c:"#89b087"},".\n\n\nOption"],
+[{y:-0.875,x:2.5,c:"#77aaff"},"Hyper",{x:1},"Cmd\n\n\nSuper",{x:8.5,c:"#89b087"},"0\n\n\nCmd",{x:1},"=\n\n\nHyper"],
+[{y:-0.75,x:0.5,c:"#77aaff"},"Ctrl\n\n\nLCtrl","Meh",{x:14.5,c:"#89b087"},"+\n\n\nMeh","Enter\n\n\nCtrl"],
+[{r:30,rx:6.5,ry:4.25,y:-1,x:1,c:"#54d6de"},"Left","Right"],
+[{h:2},"Space",{h:2},"Enter","Up"],
+[{x:2},"Down"],
+[{r:-30,rx:13,y:-1,x:-3},"Home","End"],
+[{x:-3},"Page\n\n\n\n\n\nUp",{h:2},"< Del\n\n\nBackspace",{h:2},"Del >\n\n\nDelete"],
+[{x:-3},"Page\n\n\n\n\n\nDown"]
+
diff --git a/keyboards/ergodox_ez/keymaps/ordinary/readme.md b/keyboards/ergodox_ez/keymaps/ordinary/readme.md
new file mode 100644
index 000000000..6465cd79e
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/ordinary/readme.md
@@ -0,0 +1,103 @@
+# The Ordinary Layout, a familiar and powerful layout #
+
+The Ordinary Layout is intended to be unremarkably mundane and remarkably useful. This layout maintains most key positions from common QWERTY keyboards, and it features enhanced Symbol and Media layers compared to the default Ergodox EZ layout.
+
+The Ordinary Layout is supposed to look mostly like a normal keyboard, except in the ways that the Ergodox key arrangement is unique. The thumbs are responsible for space, enter, plus both forward and backward delete; with only a couple exceptions, all other keys are in the same place they are found on traditional keyboards.
+
+Nicholas Keene
+ordinarylayout@nicholaskeene.com
+no rights reserved, use for any purposes, credit me if you are a nice person
+
+## The Base Layout ##
+
+* The light blue keys are modifiers: traditional Control, Option, and Command keys, plus Hyper and Meh
+* The dark blue keys are Shift keys: Capitals Shift (traditional shift), Symbol Shift, and Media Shift; plus a Shift Lock key
+* Several dark blue keys double for entry of characters which would typically be in those locations
+* The turquoise keys are text navigation and manipulation
+* The red keys is Escape and it is always found in that location no matter what
+
+![Ordinary base layout](ordinary-base.png)
+
+This layout puts the modifier keys along the bottom of the keyboard where they are on most keyboards. They are in the regular order, with the addition of Hyper and Meh keys. The modifier keys are all in the same place on all layers, although some layers also assign symbols on those buttons. On the outside edges are the Shift keys. The traditional shift key is called Capitals Shift and it is in the normal location. Above that are Symbols Shift and Media Shift. Each Shift key momentarily switches the layout to that layer, and if you use the Shift Lock button you can lock the layout to that layer.
+
+Touch typists will also find tilde, tab, equals/plus, slash/pipe, and quote/double-quote sharing space on those Shift keys where they would probably be on a common keyboard. Other than the turquoise keys the only buttons which move to new locations are the Brackets and Dash and Escape. Most touch typists dont touch-type brackets or dash anyway so only Escape really requires retraining of muscle memory, and see below for the Special Escape Sequence.
+
+The four big turquoise keys are arranged differently than in the default Ergodox EZ layout. The Ordinary Layout here copies the design of the old Fingerworks TouchStream keyboard, but also reflects the natural presumptions of the author -- me! I type the space character with my right hand, and to me it makes sense for the two delete keys to be next to one another.
+
+The Forward Tab and Backward Tab keys are in their locations mostly because I ended up with two extra buttons and needed something to do with them. My muscle memory from using the Truly Ergonomic Keyboard makes me look for the Tab key with my right index finger, so it is handy to have this redundant Tab, and the idea with the Backward Tab key is that it becomes easy to navigate text fields in forms, or to indent/unindent code.
+
+## The Symbols Layer ##
+
+* The light green keys are the eponymous symbols
+* The bright green keys are F-Keys
+* The dark green keys constitute a number pad
+* The turquoise keys are the *reverse* of the turquoise keys on the base layer
+
+![Ordinary symbol layout](ordinary-symbol.png)
+
+The Ergodox EZ ships with the "Coder Layer" which I like to call the Symbols layer. There are some significant improvements in The Ordinary Layout over the default layout.
+
+The symbol keys are mostly the same as on the default layout, which did a good job in this regard, but with a few enhancements:
+
+* Angle brackets on this layer mean that curly, square, and angle brackets are all available on different layers of the same two buttons. Also, they mean that all kinds of brackets, including parentheses, are available on both the Base and Symbols layers.
+* The slash, backslash, and pipe characters are grouped together as a memory aid.
+* The & and | symbols are juxtaposed as a memory aid
+
+The number pad area here, in green, includes all four arithmetic operations in the same order found on most number pads and features an Enter key. The keycodes emitted here are normal numeric keycodes, not the number-pad specific keycodes emitted by most number pads, because this layout does not use a Num Lock key to switch the buttons between numeric keycodes and navigational keycodes. See the explanation in The Media Layout section about navigation using these same buttons.
+
+Finally, consider the turquoise text-nav keys. Here in the Symbols layer, these are *reversed* from the base layer, with the keys either mirrored or shifted. This is powerful! Often I find myself using the mouse with my right hand, and the left hand needs to press Enter. Instead of reaching the left hand over to the right side of the keyboard, now I simply tap Symbols to reverse the turquoise keys, and Enter is right where it should be.
+
+## The Media Layer ##
+
+* The dark orange keys on the left move the mouse cursor
+* The dark orange keys on the right move the text cursor
+* The light orange keys are for scrolling and paging
+* The bright green keys are more F-keys
+* The dark yellow keys signal Web and Audio applications
+* The light yellow keys signal the operating system
+* The dark gray keys do nothing in case you bump them by accident
+
+![Ordinary media layout](ordinary-media.png)
+
+This layer was inspired by the Media layer on the Ergodox EZ but takes it farther. The Fingerworks TouchStream keyboard had a very useful feature for controlling the text cursor easily and this layer does something similar. The left hand can move the mouse, the right hand moves the text cursor, in all four directions, in small or large increments. This greatly enhances navigation in text documents.
+
+Moreover, the orange keys on the right overlay the numberpad from the Symbols Layer, such that in the Media Layer the same keys can be used as if they were a number pad in navigational mode (Num Lock off). For instance, in traditional number pads the '3' key became 'Page Down', and so it is here. This means a user can do text navigation without moving either hand.
+
+Alas, the yellow keys have at best spotty success with common software. Good luck with those but don't expect too much.
+
+## Switching Between Layers ##
+
+In addition to Symbols and Media there is the Capitals layer which is exactly the same as pressing the shift key. Each layer is accessed by a shift key on each edge of the keyboard and corresponds to one of the three LEDs on the keyboard: Capitals (red), Symbols (green), Media (blue). The color of a layer illuminates when the layer is active.
+
+Shift buttons work in the expected way: press them and all of the keys switch to that layer; release them and the keys switch back to the base layer. If you press both of a pair of shift keys, the layer will lock on until you press both shift keys again. For instance, the widely and rightly loathed Caps Lock is engaged by pressing both Capitals Shift buttons. All the Shift keys work this way.
+
+Multiple layers can be turned on at once. The Capitals layer will affect characters on other layers to capitalize. Other layers, however, don't 'mix': Symbols blankets the base layout; Media blankets Symbols.
+
+## Special Sequences ##
+
+![Ordinary special layout](ordinary-special.png)
+
+### Escape ###
+
+The One True Location for the Escape key is segregated way up on the top left of the keyboard. The Ergodox does not have a physical button in such a location and the nearest one is home to the tilde (er, grave) which is commonly found there. In the Ordinary layout the Escape key is found on all layers in the prominent location in the corner next to the 5, whnich is easy to remember, and yet it isn't natural for those of us with muscle memory flicking our wrists up and to the left looking for Escape.
+
+The Ordinary layout offers as a consolation prize a Special sequence for Escape: Special Shift + 1. This is natural so you can tap the top left button, then the button next to it and get Escape. This gesture works in all layers.
+
+### Backspace ###
+
+At the top right corner of the Ergodox EZ you can a gesture similar to the special Escape sequence, using the 0 key, to produce a Backspace. Users of this keyboard and this layout are well advised to learn to use their thumbs for deleting text, but sometimes you are doing other computery things and just want to flick your digits up to the right and press backspace a bunch times.
+
+### RShift ###
+
+The Ordinary Layout locks layers by pressing both of a pair of shift keys. This interferes with the QMK firmware magic sequence, which is LShift+RShift. To work around this, both of the Capitals Shift keys produce a *Left Shift* keystroke. If for some reason a person needs *Right Shift* they can find it by pressing a Special Shift key, then the Capitals Shift key on the right side of the keyboard.
+
+****
+
+The Ordinary Layout for the Ergodox EZ keyboard, v4
+
+Modifications from default by Nicholas Keene ergodoxez@nicholaskeene.com
+
+No rights reserved. This software is in the public domain. Credit me if you are friendly but if you're a jerk don't bother.
+
+Details: readme.md
+ https://github.com/nrrkeene/qmk_firmware/tree/master/keyboard/ergodox_ez/keymaps/ordinary
diff --git a/keyboards/ergodox_ez/keymaps/osx_de/keymap.c b/keyboards/ergodox_ez/keymaps/osx_de/keymap.c
new file mode 100644
index 000000000..554813d7e
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/osx_de/keymap.c
@@ -0,0 +1,364 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+#include "keymap_german_osx.h"
+
+#define BASE 0
+#define SYMB 1
+#define MDIA 2
+#define SMLY 3
+#define NUMB 4
+#define EGOS 5
+
+#define M_CTRL_CMDV 0
+#define M_CTRL_CMDC 1
+#define M_MEH_SH_ACUT 2
+#define M_LGUI_SHFT 3
+#define M_CTL_SFT_HASH 4
+#define M_DE_OSX_CIRC_CTRLCMD 5
+#define M_DE_OSX_PLUS_CTRLALT 6
+#define SM_SMILE 7
+#define SM_SMIRK 8
+#define SM_CRY 9
+#define SM_SAD 10
+#define SM_HEART 11
+#define SM_LAUGH 12
+#define SM_KISS 13
+#define SM_FROWN 14
+#define M_TOGGLE_5 15
+
+//Layout keymap.c generated with ErgodoxLayoutGenerator V1.0BETA1
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[BASE]=KEYMAP(
+//left half
+ KC_ESC, DE_OSX_1, DE_OSX_2, DE_OSX_3, DE_OSX_4, DE_OSX_5, M(M_CTL_SFT_HASH),
+ KC_TAB, DE_OSX_Q, DE_OSX_W, DE_OSX_E, DE_OSX_R, DE_OSX_T, KC_LGUI,
+ KC_LALT, DE_OSX_A, DE_OSX_S, DE_OSX_D, DE_OSX_F, DE_OSX_G,
+ KC_LSFT, CTL_T(DE_OSX_Y), DE_OSX_X, DE_OSX_C, DE_OSX_V, DE_OSX_B, KC_LALT,
+ LT(SYMB,DE_OSX_LESS), M(M_DE_OSX_CIRC_CTRLCMD), M(M_DE_OSX_PLUS_CTRLALT), KC_UP, KC_DOWN,
+ M(M_MEH_SH_ACUT), TG(MDIA),
+ KC_HOME,
+ KC_BSPC, KC_DEL, LT(SMLY,KC_END),
+ //right half
+ M(M_CTL_SFT_HASH), DE_OSX_6, DE_OSX_7, DE_OSX_8, DE_OSX_9, DE_OSX_0, DE_OSX_SS,
+ KC_RGUI, DE_OSX_Z, DE_OSX_U, DE_OSX_I, DE_OSX_O, DE_OSX_P, DE_OSX_UE,
+ DE_OSX_H, DE_OSX_J, DE_OSX_K, DE_OSX_L, DE_OSX_OE, ALT_T(DE_OSX_AE),
+ KC_RALT, DE_OSX_N, DE_OSX_M, DE_OSX_COMM, DE_OSX_DOT, CTL_T(DE_OSX_MINS), KC_RSFT,
+ KC_LEFT, KC_RIGHT, LGUI(KC_LSFT), LALT(KC_LSFT), LT(SYMB,DE_OSX_PLUS),
+ TG(NUMB), ALL_T(DE_OSX_ACUT),
+ KC_PGUP,
+ KC_PGDN, KC_ENT, KC_SPC),
+[SYMB]=KEYMAP(
+//left half
+ KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS, DE_OSX_LESS, DE_OSX_MORE, DE_OSX_EXLM, DE_OSX_QST, KC_TRNS, KC_TRNS,
+ KC_TRNS, DE_OSX_HASH, DE_OSX_DLR, DE_OSX_BSLS, DE_OSX_SLSH, KC_DOT,
+ KC_TRNS, KC_TRNS, DE_OSX_LESS, DE_OSX_PERC, DE_OSX_PIPE, DE_OSX_TILD, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_DEL, KC_TRNS,
+ //right half
+ M(M_TOGGLE_5), KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, LALT(LSFT(KC_7)), LALT(KC_5), LALT(KC_6), DE_OSX_LESS, DE_OSX_MORE, DE_OSX_EXLM,
+ DE_OSX_SLSH, DE_OSX_LPRN, DE_OSX_RPRN, LALT(KC_8), LALT(KC_9), DE_OSX_HASH,
+ KC_TRNS, DE_OSX_PIPE, DE_OSX_TILD, DE_OSX_CIRC, KC_UP, DE_OSX_MINS, LSFT(KC_4),
+ DE_OSX_QUOT, KC_LEFT, KC_DOWN, KC_RIGHT, KC_TRNS,
+ KC_F13, KC_F12,
+ KC_F14,
+ KC_F15, KC_TRNS, KC_TRNS),
+[MDIA]=KEYMAP(
+//left half
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_BTN1, KC_MS_U, KC_BTN2, KC_WH_U, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_WH_D,
+ KC_TRNS, KC_TRNS, KC_WH_L, KC_WH_D, KC_WH_R, KC_BTN3, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ //right half
+ KC_MUTE, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_VOLU, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_VOLD, KC_TRNS, KC_MPRV, KC_MNXT, KC_UP, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_LEFT, KC_DOWN, KC_RIGHT,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_WBAK),
+[SMLY]=KEYMAP(
+//left half
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ //right half
+ M(SM_SMILE), M(SM_SMIRK), M(SM_LAUGH), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, M(SM_FROWN), M(SM_SAD), M(SM_CRY), KC_TRNS, KC_TRNS, KC_TRNS,
+ M(SM_HEART), M(SM_KISS), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS),
+[NUMB]=KEYMAP(
+//left half
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_UP, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ //right half
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_UP, KC_7, KC_8, KC_9, LSFT(KC_RBRC), KC_F12,
+ KC_DOWN, KC_4, KC_5, KC_6, KC_RBRC, DE_OSX_MINS,
+ KC_TRNS, LSFT(KC_6), KC_1, KC_2, KC_3, LSFT(KC_7), KC_TRNS,
+ KC_0, KC_DOT, KC_COMM, DE_OSX_EQL, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS),
+[EGOS]=KEYMAP(
+//left half
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_LSFT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_LCTL, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_F1, KC_F2,
+ KC_F3,
+ KC_SPC, KC_LCTL, KC_F4,
+ //right half
+ M(M_TOGGLE_5), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+static uint16_t start;
+switch(id) {
+case M_TOGGLE_5:
+//Macro: M_TOGGLE_5//-----------------------
+ if (record->event.pressed){
+ layer_state ^= (1<<5);
+ layer_state &= (1<<5);
+ }
+
+break;
+case M_CTRL_CMDC:
+//Macro: M_CTRL_CMDC//-----------------------
+if (record->event.pressed) {
+ start = timer_read();
+ return MACRO(D(LCTRL),END);
+ } else {
+ if (timer_elapsed(start) >150) {
+ return MACRO(U(LCTRL),END);
+ } else {
+ return MACRO(U(LCTRL),D(LGUI),T(C),U(LGUI),END);
+ }
+ }
+
+break;
+case M_DE_OSX_PLUS_CTRLALT:
+//Macro: M_DE_OSX_PLUS_CTRLALT//-----------------------
+if (record->event.pressed) {
+ start = timer_read();
+ return MACRO(D(LCTRL),D(LALT),END);
+ } else {
+ if (timer_elapsed(start) >150) {
+ return MACRO(U(LCTRL),U(LALT),END);
+ } else {
+ return MACRO(U(LCTRL),U(LALT),T(RBRC),END);
+ }
+ }
+
+break;
+case SM_KISS:
+//Macro: SM_KISS//-----------------------
+if (record->event.pressed) {
+ return MACRO(D(LSFT),T(DOT),U(LSFT),T(SLSH),D(LSFT),T(RBRC),U(LSFT),END);
+ }
+
+break;
+case SM_FROWN:
+//Macro: SM_FROWN//-----------------------
+if (record->event.pressed) {
+ return MACRO(D(LSFT),T(DOT),U(LSFT),T(SLSH),D(LALT),T(8),U(LALT),END);
+ }
+
+break;
+case SM_CRY:
+//Macro: SM_CRY//-----------------------
+if (record->event.pressed) {
+ return MACRO(D(LSFT),T(COMM),U(LSFT),T(SLSH),D(LSFT),T(8),U(LSFT),END);
+ }
+
+break;
+case SM_SMILE:
+//Macro: SM_SMILE//-----------------------
+if (record->event.pressed) {
+ return MACRO(D(LSFT),T(DOT),U(LSFT),T(SLSH),D(LSFT),T(9),U(LSFT),END);
+ }
+
+break;
+case SM_SMIRK:
+//Macro: SM_SMIRK//-----------------------
+if (record->event.pressed) {
+ return MACRO(D(LSFT),T(COMM),U(LSFT),T(SLSH),D(LSFT),T(9),U(LSFT),END);
+ }
+
+break;
+case M_LGUI_SHFT:
+//Macro: M_LGUI_SHFT//-----------------------
+if (record->event.pressed){
+ return MACRO(D(LGUI),D(LSFT),END);
+ }else{
+ return MACRO(U(LGUI),U(LSFT),END);
+ }
+
+break;
+case SM_HEART:
+//Macro: SM_HEART//-----------------------
+if (record->event.pressed) {
+ return MACRO(T(GRV),T(3),END);
+ }
+
+break;
+case SM_LAUGH:
+//Macro: SM_LAUGH//-----------------------
+if (record->event.pressed) {
+ return MACRO(D(LSFT),T(DOT),U(LSFT),T(SLSH),D(LSFT),T(D),U(LSFT),END);
+ }
+
+break;
+case M_CTL_SFT_HASH:
+//Macro: M_CTL_SFT_HASH//-----------------------
+if (record->event.pressed) {
+ start = timer_read();
+ return MACRO(D(LCTRL),D(LSFT),END);
+ } else {
+ if (timer_elapsed(start) >150) {
+ return MACRO(U(LCTRL),U(LSFT),END);
+ } else {
+ return MACRO(U(LCTRL),U(LSFT),T(BSLS),END);
+ }
+ }
+
+break;
+case SM_SAD:
+//Macro: SM_SAD//-----------------------
+if (record->event.pressed) {
+ return MACRO(D(LSFT),T(DOT),U(LSFT),T(SLSH),D(LSFT),T(8),U(LSFT),END);
+ }
+
+break;
+case M_DE_OSX_CIRC_CTRLCMD:
+//Macro: M_DE_OSX_CIRC_CTRLCMD//-----------------------
+if (record->event.pressed) {
+ start = timer_read();
+ return MACRO(D(LCTRL),D(LGUI),END);
+ } else {
+ if (timer_elapsed(start) >150) {
+ return MACRO(U(LCTRL),U(LGUI),END);
+ } else {
+ return MACRO(U(LCTRL),U(LGUI),T(NUBS),END);
+ }
+ }
+
+break;
+case M_CTRL_CMDV:
+//Macro: M_CTRL_CMDV//-----------------------
+if (record->event.pressed) {
+ start = timer_read();
+ return MACRO(D(LCTRL),END);
+ } else {
+ if (timer_elapsed(start) >150) {
+ return MACRO(U(LCTRL),END);
+ } else {
+ return MACRO(U(LCTRL),D(LGUI),T(V),U(LGUI),END);
+ }
+ }
+
+break;
+case M_MEH_SH_ACUT:
+//Macro: M_MEH_SH_ACUT//-----------------------
+if (record->event.pressed) {
+ start = timer_read();
+ return MACRO(D(LCTRL),D(LSFT),D(LALT),END);
+ } else {
+ if (timer_elapsed(start) >150) {
+ return MACRO(U(LCTRL),U(LSFT),U(LALT),END);
+ } else {
+ return MACRO(U(LCTRL),U(LALT),T(EQL),U(LSFT),END);
+ }
+ }
+
+break;
+}
+return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+uint8_t layer = biton32(layer_state);
+
+ergodox_board_led_off();
+ergodox_right_led_1_off();
+ergodox_right_led_2_off();
+ergodox_right_led_3_off();
+switch (layer) {
+
+ case SYMB:
+ ergodox_right_led_1_on();
+
+
+ break;
+ case MDIA:
+
+ ergodox_right_led_2_on();
+
+ break;
+ case SMLY:
+
+
+ ergodox_right_led_3_on();
+ break;
+ case NUMB:
+ ergodox_right_led_1_on();
+
+ ergodox_right_led_3_on();
+ break;
+ case EGOS:
+ ergodox_right_led_1_on();
+ ergodox_right_led_2_on();
+ ergodox_right_led_3_on();
+ break;
+default:
+// none
+break;
+}
+
+};
+
diff --git a/keyboards/ergodox_ez/keymaps/osx_de/osx_de_highres.png b/keyboards/ergodox_ez/keymaps/osx_de/osx_de_highres.png
new file mode 100644
index 000000000..d442a992c
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/osx_de/osx_de_highres.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/osx_de/readme.md b/keyboards/ergodox_ez/keymaps/osx_de/readme.md
new file mode 100644
index 000000000..5011a9dd6
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/osx_de/readme.md
@@ -0,0 +1,41 @@
+#Ergodox EZ für OSX
+
+Dies ist nur ein kleiner Tweak der bestehenden firmware für das ErgoDox-EZ-Keyboard. Leider passte das layout nicht wirklich für OSX, deswegen habe ich einige Anpassungen gemacht. Dabei wurden folgende features umgesetzt:
+
+- Die Umlaute sollten an einigermassen sinnvollen Plätzen liegen
+- der Umstieg sollte dadurch erleichtert werden, dass einige Tasten an ihren "normalen" Platz zurückgewandert sind. Z.B. ESC, Tab,...
+- die Leertaste ist jetzt auf der rechten seite, neben Enter. Dafür hat der linke Daumen nun Backspace und Delete.
+- die CMD- und Alt-Tasten sind in der Mitte einfach erreichbar.
+- es gibt eine neue Layer die für Spiele genutzt werden kann (egosooter wie Counter Strike). Dort liegen die wichtigsten Tasten auf der linken Seite, im Daumenblock z.B. space und ctrl sowie die F-Tasten 1-4. Diese Layer ist über die Symbollayer erreichbar.
+- Die Symbollayer wurde dahingehend angepasst, dass die klammern, etc nun auf beiden hälften der Tastatur zu finden sind
+- der Zehnerblock wurde in eine eigene Layer umgezogen
+- die Meh und Hyper-Tasten wurden in die Daumenblöcke umgezogen
+
+# Erstellt Mit Dem ErgodoxLayoutGenerator
+
+Der ErgodoxLayoutGenerator ist ein kleines Werkzeug, welches die Erstellung und Pflege der eigenen Keymaps erleichtern soll. Es ist in java geschrieben und kann [hier](https://github.com/sboesebeck/ErgodoxLayoutGenerator/releases) heruntergeladen werden. Damit das Tool funktioniert sollte das offizielle Oracle JDK in aktueller Version installiert sein.
+Die Dokumentation für den ELG kann man [hier](https://boesebeck.name/2016/04/16/ergodoxlayoutgenerator-documentation/) nachlesen (momentan leider nur in Englisch verfügbar).
+
+
+
+------------------------------
+
+# ErgoDox EZ for OSX
+
+This is only a little tweak of the existing default layout for the ErgoDox keyboard. Unfortunately the default layout did not work well with german OSX, so I created som adjustments. These were the features added and changed:
+
+- the umlaut-keys should be at their useful place more or less
+- the switching should be made more easy so some other keys (like tab, esc) were moved to their default place
+- the space key can now be used with both hands
+- the CMD- and ALT-Keys moved to the middle, can be reached more easily.
+- there is a new layer for using the cursor-keys, placed like on the default keyboard. This makes them useable for games also
+- the symbollayer now has only symbols
+- the number block was moved to a special layer
+- meh and hyper went down to the thumb block
+
+# Created Using the ErgodoxLayoutGenerator
+
+The ErgodoxLayoutGenerator (ELG) is a little tool, which makes the creation and maintenance of keycaps a lot easier. It was written in Java and can be downloaded [here](https://github.com/sboesebeck/ErgodoxLayoutGenerator/releases). To use the tool, you need to have a current version of Oracles JDK installed.
+
+The documentation of the ELG can be viewed [here](https://boesebeck.name/2016/04/16/ergodoxlayoutgenerator-documentation/).
+
diff --git a/keyboards/ergodox_ez/keymaps/osx_de_adnw_koy/keymap.c b/keyboards/ergodox_ez/keymaps/osx_de_adnw_koy/keymap.c
new file mode 100644
index 000000000..687a5cb8b
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/osx_de_adnw_koy/keymap.c
@@ -0,0 +1,174 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#include "keymap_neo2.h"
+#include "keymap_uk.h"
+#include "keymap_colemak.h"
+#include "keymap_french_osx.h"
+#include "keymap_nordic.h"
+#include "keymap_dvorak.h"
+#include "keymap_german.h"
+#include "keymap_norwegian.h"
+#include "keymap_fr_ch.h"
+#include "keymap_german_osx.h"
+#include "keymap_spanish.h"
+#include "keymap_bepo.h"
+
+#define BASE 0
+#define SYMB 1
+#define MDIA 2
+#define QWERTZ 3
+#define NUMB 4
+
+#define UNUSED 0
+
+//Layout keymap.c generated with ErgodoxLayoutGenerator V1.0BETA1
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[BASE]=KEYMAP(
+//left half
+ KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_LCTL,
+ KC_TAB, KC_K, KC_DOT, KC_O, KC_COMM, KC_Z, KC_LGUI,
+ TG(QWERTZ), KC_H, KC_A, KC_E, KC_I, KC_U,
+ KC_LSFT, CTL_T(KC_X), KC_Q, DE_AE, DE_UE, DE_OE, KC_LALT,
+ LT(SYMB,KC_GRV), DE_LESS, LALT(KC_LSFT), KC_LEFT, KC_RGHT,
+ TG(MDIA), MEH_T(LSFT(DE_ACUT)),
+ KC_HOME,
+ KC_BSPC, KC_DEL, KC_END,
+ //right half
+ KC_RCTL, KC_6, KC_7, KC_8, KC_9, KC_0, DE_OSX_MINS,
+ KC_RGUI, KC_V, KC_G, KC_C, KC_L, KC_MINS, KC_Y,
+ KC_D, KC_T, KC_R, KC_N, KC_S, LT(MDIA,KC_F),
+ KC_RALT, KC_B, KC_P, KC_W, KC_M, CTL_T(KC_J), KC_RSFT,
+ KC_UP, KC_DOWN, LGUI(KC_LSFT), KC_RBRC, LT(SYMB,KC_BSLS),
+ ALL_T(DE_ACUT), TG(NUMB),
+ KC_PGUP,
+ KC_PGDN, KC_ENT, KC_SPC),
+[SYMB]=KEYMAP(
+//left half
+ KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS, KC_GRV, LSFT(KC_GRV), DE_EXLM, DE_QST, KC_TRNS, KC_TRNS,
+ KC_TRNS, DE_HASH, DE_DLR, LALT(LSFT(KC_7)), DE_SLSH, KC_DOT,
+ KC_TRNS, KC_TRNS, DE_LESS, DE_PERC, LALT(KC_7), LALT(KC_N), KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_DEL, KC_TRNS,
+ //right half
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, LALT(LSFT(KC_7)), LALT(KC_5), LALT(KC_6), LALT(KC_7), DE_HASH, KC_F12,
+ DE_SLSH, DE_LPRN, DE_RPRN, LALT(KC_8), LALT(KC_9), KC_TRNS,
+ KC_TRNS, DE_AMPR, KC_GRV, LSFT(KC_GRV), DE_DQOT, DE_QUOT, DE_QST,
+ KC_TRNS, KC_DOT, KC_EXLM, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS),
+[MDIA]=KEYMAP(
+//left half
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
+ KC_TRNS, KC_WH_L, KC_WH_U, KC_WH_D, KC_WH_R, KC_BTN3, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ //right half
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MUTE, KC_MPRV, KC_MNXT, KC_UP, KC_TRNS,
+ KC_VOLU, KC_VOLD, KC_LEFT, KC_DOWN, KC_RIGHT,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_WBAK),
+[QWERTZ]=KEYMAP(
+//left half
+ KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, LGUI(KC_V),
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_LGUI,
+ KC_TRNS, KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_LSFT, CTL_T(KC_Z), KC_X, KC_C, KC_V, KC_B, KC_LALT,
+ LT(SYMB,KC_GRV), DE_LESS, LALT(KC_LSFT), KC_LEFT, KC_RGHT,
+ KC_TRNS, MEH_T(LSFT(DE_ACUT)),
+ KC_HOME,
+ KC_BSPC, KC_DEL, KC_END,
+ //right half
+ LGUI(KC_C), KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
+ KC_RGUI, KC_Y, KC_U, KC_I, KC_O, KC_P, DE_UE,
+ KC_H, KC_J, KC_K, KC_L, KC_SCLN, LT(MDIA,DE_AE),
+ KC_RALT, KC_N, KC_M, KC_COMM, KC_DOT, CTL_T(KC_SLSH), KC_RSFT,
+ KC_UP, KC_DOWN, LGUI(KC_LSFT), KC_RBRC, LT(SYMB,KC_BSLS),
+ ALL_T(DE_ACUT), KC_TRNS,
+ KC_PGUP,
+ KC_PGDN, KC_ENT, KC_SPC),
+[NUMB]=KEYMAP(
+//left half
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_UP, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ //right half
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_UP, KC_7, KC_8, KC_9, LSFT(KC_RBRC), KC_F12,
+ KC_DOWN, KC_4, KC_5, KC_6, KC_RBRC, KC_TRNS,
+ KC_TRNS, LSFT(KC_6), KC_1, KC_2, KC_3, LSFT(KC_7), KC_TRNS,
+ KC_0, KC_DOT, KC_0, KC_EQL, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+switch(id) {
+case UNUSED:
+//Macro: UNUSED//-----------------------
+
+
+
+
+
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+
+
+
+break;
+}
+return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+uint8_t layer = biton32(layer_state);
+
+ergodox_board_led_off();
+ergodox_right_led_1_off();
+ergodox_right_led_2_off();
+ergodox_right_led_3_off();
+switch (layer) {
+
+default:
+// none
+break;
+}
+
+};
+
diff --git a/keyboards/ergodox_ez/keymaps/osx_de_adnw_koy/osx_de_adnw_koy_highres.png b/keyboards/ergodox_ez/keymaps/osx_de_adnw_koy/osx_de_adnw_koy_highres.png
new file mode 100644
index 000000000..193aa339e
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/osx_de_adnw_koy/osx_de_adnw_koy_highres.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/osx_de_experimental/keymap.c b/keyboards/ergodox_ez/keymaps/osx_de_experimental/keymap.c
new file mode 100644
index 000000000..21d695894
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/osx_de_experimental/keymap.c
@@ -0,0 +1,597 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+#include "keymap_neo2.h"
+#include "keymap_uk.h"
+#include "keymap_colemak.h"
+#include "keymap_nordic.h"
+#include "keymap_dvorak.h"
+#include "keymap_german.h"
+#include "keymap_norwegian.h"
+#include "keymap_fr_ch.h"
+#include "keymap_german_osx.h"
+#include "keymap_spanish.h"
+#include "keymap_bepo.h"
+
+
+/**
+* This layout was generated using the ErgodoxLayoutGenerator (ELG). You can download it from https://github.com/sboesebeck/ErgodoxLayoutGenerator/releases
+* documentation about it can be found here https://boesebeck.name/2016/04/16/ergodoxlayoutgenerator-documentation/
+* Thanks to the team of Erez Zukerman for building the great Ergodox-EZ!
+*
+* use at own risk!
+**/
+
+#define BASE 0
+#define SYMB 1
+#define MDIA 2
+#define SMLY 3
+#define NUMB 4
+#define EGOS 5
+
+#define SMLY_TOG_QUOT 0
+
+#define M_TOGGLE_5 1
+
+#define TGH_NUM 2
+
+#define M_DE_OSX_PLUS_CTRLALT 3
+
+#define SM_KISS 4
+
+#define SM_FROWN 5
+
+#define SM_CRY 6
+
+#define SM_SMILE 7
+
+#define SM_SMIRK 8
+
+#define M_LGUI_SHFT 9
+
+#define SM_HEART 10
+
+#define TOG_HLD_MDIA 11
+
+#define SM_LAUGH 12
+
+#define SM_SAD 13
+
+#define M_DE_OSX_CIRC_CTRLCMD 14
+
+#define M_MEH_SH_ACUT 15
+
+
+//Layout keymap.c generated with ErgodoxLayoutGenerator V1.0BETA1
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/**
+* Layer: BASE
+* /-------------------//-------------------//-------------------//-------------------//-------------------//-------------------//-------------------/ /-------------------//-------------------//-------------------//-------------------//-------------------//-------------------//-------------------/
+* | ESC | 1 | 2 | 3 | 4 | 5 | Hold or toggle | | Hold or toggle | 6 | 7 | 8 | 9 | 0 | ß |
+* | | | | | | | Layer NUMB | | Layer MDIA | | | | | | |
+* /-------------------//-------------------//-------------------//-------------------//-------------------//-------------------//-------------------/ /-------------------//-------------------//-------------------//-------------------//-------------------//-------------------//-------------------/
+* | TAB | Q | W | E | R | T | Cmd | | Cmd | Z | U | I | O | P | Ü |
+* | | | | | | | | | | | | | | | |
+* /-------------------//-------------------//-------------------//-------------------//-------------------//-------------------/\-------------------\ \-------------------\/-------------------//-------------------//-------------------//-------------------//-------------------//-------------------/
+* | Alt | A | S | D | F | G | | H | J | K | L | Ö | Ä |
+* | | | | | | | | | | | | | ALT |
+* /-------------------//-------------------//-------------------//-------------------//-------------------//-------------------//-------------------/ /-------------------//-------------------//-------------------//-------------------//-------------------//-------------------//-------------------/
+* | Shift | Y | X | C | V | B | Alt | | Alt | N | M | , | . | - | Shift |
+* | | Ctrl | | | | | | | | | | | | Ctrl | |
+* \-------------------\\-------------------\\-------------------\\-------------------\\-------------------\\-------------------\\-------------------\ \-------------------\\-------------------\\-------------------\\-------------------\\-------------------\\-------------------\\-------------------\
+*
+*
+* /-------------------//-------------------//-------------------//-------------------//-------------------/ /-------------------//-------------------//-------------------//-------------------//-------------------/
+* | < | LongPress / Type | LongPress / Type | Shift+Ctrl | Type | | # | ACUT | CMD+Shift | ALT+Shift | + |
+* | SYMB | DE_OSX_CIRC_CTRLCMD| DE_OSX_PLUS_CTRAlt | | Toggle SMLY | | Meh | Hyper | | | SYMB |
+* \-------------------\\-------------------\\-------------------\\-------------------\/-------------------//-------------------/ /-------------------//-------------------/ \-------------------\\-------------------\\-------------------\\-------------------\\-------------------\
+* | HOME | END | | LEFT | RIGHT |
+* | | | | | |
+* \-------------------\/-------------------/ /-------------------/\-------------------\
+* | PGUP | | UP |
+* | | | |
+* /-------------------//-------------------//-------------------/ /-------------------//-------------------//-------------------/
+* | BSPC | DEL | PGDN | | DOWN | ENT | SPC |
+* | | | | | | | |
+* \-------------------\\-------------------\\-------------------\ \-------------------\\-------------------\\-------------------\
+*
+*
+**/
+[BASE]=KEYMAP(
+//left half
+ KC_ESC, DE_OSX_1, DE_OSX_2, DE_OSX_3, DE_OSX_4, DE_OSX_5, M(TGH_NUM),
+ KC_TAB, DE_OSX_Q, DE_OSX_W, DE_OSX_E, DE_OSX_R, DE_OSX_T, KC_LGUI,
+ KC_LALT, DE_OSX_A, DE_OSX_S, DE_OSX_D, DE_OSX_F, DE_OSX_G,
+ KC_LSFT, CTL_T(DE_OSX_Y), DE_OSX_X, DE_OSX_C, DE_OSX_V, DE_OSX_B, KC_LALT,
+ LT(SYMB,DE_OSX_LESS), M(M_DE_OSX_CIRC_CTRLCMD), M(M_DE_OSX_PLUS_CTRLALT), LSFT(KC_LCTRL), M(SMLY_TOG_QUOT),
+ KC_HOME, KC_END,
+ KC_PGUP,
+ KC_BSPC, KC_DEL, KC_PGDN,
+ //right half
+ M(TOG_HLD_MDIA), DE_OSX_6, DE_OSX_7, DE_OSX_8, DE_OSX_9, DE_OSX_0, DE_OSX_SS,
+ KC_RGUI, DE_OSX_Z, DE_OSX_U, DE_OSX_I, DE_OSX_O, DE_OSX_P, DE_OSX_UE,
+ DE_OSX_H, DE_OSX_J, DE_OSX_K, DE_OSX_L, DE_OSX_OE, ALT_T(DE_OSX_AE),
+ KC_RALT, DE_OSX_N, DE_OSX_M, DE_OSX_COMM, DE_OSX_DOT, CTL_T(DE_OSX_MINS), KC_RSFT,
+ MEH_T(DE_OSX_HASH), ALL_T(DE_OSX_ACUT), LGUI(KC_LSFT), LALT(KC_LSFT), LT(SYMB,DE_OSX_PLUS),
+ KC_LEFT, KC_RIGHT,
+ KC_UP,
+ KC_DOWN, KC_ENT, KC_SPC),
+/**
+* Layer: SYMB
+* /-----------//-----------//-----------//-----------//-----------//-----------//-----------/ /-----------//-----------//-----------//-----------//-----------//-----------//-----------/
+* | APPLICATION| F1 | F2 | F3 | F4 | F5 | F5 | | F6 | F6 | F7 | F8 | F9 | F10 | F11 |
+* | | | | | | | | | | | | | | | |
+* /-----------//-----------//-----------//-----------//-----------//-----------//-----------/ /-----------//-----------//-----------//-----------//-----------//-----------//-----------/
+* | | < | > | ! | ? | | | | | \ | [ | ] | < | > | ! |
+* | | | | | | | | | | | | | | | |
+* /-----------//-----------//-----------//-----------//-----------//-----------/\-----------\ \-----------\/-----------//-----------//-----------//-----------//-----------//-----------/
+* | | # | $ | \ | / | . | | / | ( | ) | { | } | # |
+* | | | | | | | | | | | | | |
+* /-----------//-----------//-----------//-----------//-----------//-----------//-----------/ /-----------//-----------//-----------//-----------//-----------//-----------//-----------/
+* | | | < | % | | | ~ | | | | | | ~ | | | | |
+* | | | | | | | | | | | | | | | |
+* \-----------\\-----------\\-----------\\-----------\\-----------\\-----------\\-----------\ \-----------\\-----------\\-----------\\-----------\\-----------\\-----------\\-----------\
+*
+*
+* /-----------//-----------//-----------//-----------//-----------/ /-----------//-----------//-----------//-----------//-----------/
+* | | | | | | | ' | DQOT | | Toggle 5 | |
+* | | | | | | | | | | | |
+* \-----------\\-----------\\-----------\\-----------\/-----------//-----------/ /-----------//-----------/ \-----------\\-----------\\-----------\\-----------\\-----------\
+* | | | | F13 | F12 |
+* | | | | | |
+* \-----------\/-----------/ /-----------/\-----------\
+* | | | F14 |
+* | | | |
+* /-----------//-----------//-----------/ /-----------//-----------//-----------/
+* | | DEL | | | F15 | | |
+* | | | | | | | |
+* \-----------\\-----------\\-----------\ \-----------\\-----------\\-----------\
+*
+*
+**/
+[SYMB]=KEYMAP(
+//left half
+ KC_APPLICATION, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F5,
+ KC_TRNS, DE_OSX_LESS, DE_OSX_MORE, DE_OSX_EXLM, DE_OSX_QST, KC_TRNS, KC_TRNS,
+ KC_TRNS, DE_OSX_HASH, DE_OSX_DLR, DE_OSX_BSLS, DE_OSX_SLSH, KC_DOT,
+ KC_TRNS, KC_TRNS, DE_OSX_LESS, DE_OSX_PERC, DE_OSX_PIPE, DE_OSX_TILD, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_DEL, KC_TRNS,
+ //right half
+ KC_F6, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, DE_OSX_BSLS, DE_OSX_LBRC, DE_OSX_RBRC, DE_OSX_LESS, DE_OSX_MORE, DE_OSX_EXLM,
+ DE_OSX_SLSH, DE_OSX_LPRN, DE_OSX_RPRN, DE_OSX_LCBR, DE_OSX_RCBR, DE_OSX_HASH,
+ KC_TRNS, DE_OSX_PIPE, DE_OSX_TILD, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ DE_OSX_QUOT, DE_OSX_DQOT, KC_TRNS, M(M_TOGGLE_5), KC_TRNS,
+ KC_F13, KC_F12,
+ KC_F14,
+ KC_F15, KC_TRNS, KC_TRNS),
+/**
+* Layer: MDIA
+* /-----//-----//-----//-----//-----//-----//-----/ /-----//-----//-----//-----//-----//-----//-----/
+* | | | | | | | | | | | | | | | |
+* | | | | | | | | | | | | | | | |
+* /-----//-----//-----//-----//-----//-----//-----/ /-----//-----//-----//-----//-----//-----//-----/
+* | | | BTN1 | U | BTN2 | U | | | | | | | | | |
+* | | | | | | | | | | | | | | | |
+* /-----//-----//-----//-----//-----//-----/\-----\ \-----\/-----//-----//-----//-----//-----//-----/
+* | | | L | D | R | D | | | | | | | |
+* | | | | | | | | | | | | | |
+* /-----//-----//-----//-----//-----//-----//-----/ /-----//-----//-----//-----//-----//-----//-----/
+* | | | L | D | R | BTN3 | | | | | | | | UP | |
+* | | | | | | | | | | | | | | | |
+* \-----\\-----\\-----\\-----\\-----\\-----\\-----\ \-----\\-----\\-----\\-----\\-----\\-----\\-----\
+*
+*
+* /-----//-----//-----//-----//-----/ /-----//-----//-----//-----//-----/
+* | | | | | | | | | LEFT | DOWN | RIGHT|
+* | | | | | | | | | | | |
+* \-----\\-----\\-----\\-----\/-----//-----/ /-----//-----/ \-----\\-----\\-----\\-----\\-----\
+* | | | | MPRV | MNXT |
+* | | | | | |
+* \-----\/-----/ /-----/\-----\
+* | | | VOLU |
+* | | | |
+* /-----//-----//-----/ /-----//-----//-----/
+* | | | | | VOLD | MUTE | MPLY |
+* | | | | | | | |
+* \-----\\-----\\-----\ \-----\\-----\\-----\
+*
+*
+**/
+[MDIA]=KEYMAP(
+//left half
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_BTN1, KC_MS_U, KC_BTN2, KC_WH_U, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_WH_D,
+ KC_TRNS, KC_TRNS, KC_WH_L, KC_WH_D, KC_WH_R, KC_BTN3, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ //right half
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_UP, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_LEFT, KC_DOWN, KC_RIGHT,
+ KC_MPRV, KC_MNXT,
+ KC_VOLU,
+ KC_VOLD, KC_MUTE, KC_MPLY),
+/**
+* Layer: SMLY
+* /--------//--------//--------//--------//--------//--------//--------/ /--------//--------//--------//--------//--------//--------//--------/
+* | | | | | | | | | Typing | Typing | Typing | | | | |
+* | | | | | | | | | SM_SMILE| SM_SMIRK| SM_LAUGH| | | | |
+* /--------//--------//--------//--------//--------//--------//--------/ /--------//--------//--------//--------//--------//--------//--------/
+* | | | | | | | | | | Typing | Typing | Typing | | | |
+* | | | | | | | | | | SM_FROWN| SM_SAD | SM_CRY | | | |
+* /--------//--------//--------//--------//--------//--------/\--------\ \--------\/--------//--------//--------//--------//--------//--------/
+* | | | | | | | | Typing | Typing | | | | |
+* | | | | | | | | SM_HEART| SM_KISS | | | | |
+* /--------//--------//--------//--------//--------//--------//--------/ /--------//--------//--------//--------//--------//--------//--------/
+* | | | | | | | | | | | | | | | |
+* | | | | | | | | | | | | | | | |
+* \--------\\--------\\--------\\--------\\--------\\--------\\--------\ \--------\\--------\\--------\\--------\\--------\\--------\\--------\
+*
+*
+* /--------//--------//--------//--------//--------/ /--------//--------//--------//--------//--------/
+* | | | | | | | | | | | |
+* | | | | | | | | | | | |
+* \--------\\--------\\--------\\--------\/--------//--------/ /--------//--------/ \--------\\--------\\--------\\--------\\--------\
+* | | | | | |
+* | | | | | |
+* \--------\/--------/ /--------/\--------\
+* | | | |
+* | | | |
+* /--------//--------//--------/ /--------//--------//--------/
+* | | | | | | | |
+* | | | | | | | |
+* \--------\\--------\\--------\ \--------\\--------\\--------\
+*
+*
+**/
+[SMLY]=KEYMAP(
+//left half
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ //right half
+ M(SM_SMILE), M(SM_SMIRK), M(SM_LAUGH), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, M(SM_FROWN), M(SM_SAD), M(SM_CRY), KC_TRNS, KC_TRNS, KC_TRNS,
+ M(SM_HEART), M(SM_KISS), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS),
+/**
+* Layer: NUMB
+* /----//----//----//----//----//----//----/ /----//----//----//----//----//----//----/
+* | | | | | | | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+* | | | | | | | | | | | | | | | |
+* /----//----//----//----//----//----//----/ /----//----//----//----//----//----//----/
+* | | | | UP | | | | | | / | 7 | 8 | 9 | * | F12 |
+* | | | | | | | | | | | | | | | |
+* /----//----//----//----//----//----/\----\ \----\/----//----//----//----//----//----/
+* | | | LEFT| DOWN| RGHT| | | / | 4 | 5 | 6 | + | - |
+* | | | | | | | | | | | | | |
+* /----//----//----//----//----//----//----/ /----//----//----//----//----//----//----/
+* | | | | | | | | | | % | 1 | 2 | 3 | | |
+* | | | | | | | | | | | | | | | |
+* \----\\----\\----\\----\\----\\----\\----\ \----\\----\\----\\----\\----\\----\\----\
+*
+*
+* /----//----//----//----//----/ /----//----//----//----//----/
+* | | | | | | | 0 | . | , | = | |
+* | | | | | | | | | | | |
+* \----\\----\\----\\----\/----//----/ /----//----/ \----\\----\\----\\----\\----\
+* | | | | | |
+* | | | | | |
+* \----\/----/ /----/\----\
+* | | | |
+* | | | |
+* /----//----//----/ /----//----//----/
+* | | | | | | | |
+* | | | | | | | |
+* \----\\----\\----\ \----\\----\\----\
+*
+*
+**/
+[NUMB]=KEYMAP(
+//left half
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_UP, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ //right half
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, DE_OSX_SLSH, KC_7, KC_8, KC_9, DE_OSX_ASTR, KC_F12,
+ DE_OSX_SLSH, KC_4, KC_5, KC_6, DE_OSX_PLUS, DE_OSX_MINS,
+ KC_TRNS, DE_OSX_PERC, KC_1, KC_2, KC_3, KC_TRNS, KC_TRNS,
+ KC_0, KC_DOT, KC_COMM, DE_OSX_EQL, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS),
+/**
+* Layer: EGOS
+* /--------//--------//--------//--------//--------//--------//--------/ /--------//--------//--------//--------//--------//--------//--------/
+* | | | | | | | | | | | | | | | |
+* | | | | | | | | | | | | | | | |
+* /--------//--------//--------//--------//--------//--------//--------/ /--------//--------//--------//--------//--------//--------//--------/
+* | | | | | | | | | | | | | | | |
+* | | | | | | | | | | | | | | | |
+* /--------//--------//--------//--------//--------//--------/\--------\ \--------\/--------//--------//--------//--------//--------//--------/
+* | Shift | | | | | | | | | | | | |
+* | | | | | | | | | | | | | |
+* /--------//--------//--------//--------//--------//--------//--------/ /--------//--------//--------//--------//--------//--------//--------/
+* | | | | | | | | | | | | | | | |
+* | | | | | | | | | | | | | | | |
+* \--------\\--------\\--------\\--------\\--------\\--------\\--------\ \--------\\--------\\--------\\--------\\--------\\--------\\--------\
+*
+*
+* /--------//--------//--------//--------//--------/ /--------//--------//--------//--------//--------/
+* | Ctrl | | | | | | | | | Toggle 5| |
+* | | | | | | | | | | | |
+* \--------\\--------\\--------\\--------\/--------//--------/ /--------//--------/ \--------\\--------\\--------\\--------\\--------\
+* | F1 | F2 | | | |
+* | | | | | |
+* \--------\/--------/ /--------/\--------\
+* | F3 | | |
+* | | | |
+* /--------//--------//--------/ /--------//--------//--------/
+* | SPC | Ctrl | F4 | | | | |
+* | | | | | | | |
+* \--------\\--------\\--------\ \--------\\--------\\--------\
+*
+*
+**/
+[EGOS]=KEYMAP(
+//left half
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_LSFT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_LCTL, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_F1, KC_F2,
+ KC_F3,
+ KC_SPC, KC_LCTL, KC_F4,
+ //right half
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, M(M_TOGGLE_5), KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+static uint16_t start;
+switch(id) {
+case SMLY_TOG_QUOT:
+//Macro: SMLY_TOG_QUOT//-----------------------
+if (record->event.pressed) {
+ start = timer_read();
+ layer_state ^= (1<<SMLY);
+ layer_state &= (1<<SMLY);
+ return MACRO_NONE; } else {
+ layer_state ^= (1<<SMLY);
+ layer_state &= (1<<SMLY);
+ if (timer_elapsed(start) >150) {
+ return MACRO_NONE;
+ } else {
+ return MACRO(DOWN(KC_LSFT),TYPE(DE_OSX_HASH),UP(KC_LSFT),END);
+ }
+ }
+
+break;
+case M_TOGGLE_5:
+//Macro: M_TOGGLE_5//-----------------------
+ if (record->event.pressed){
+ layer_state ^= (1<<5);
+ layer_state &= (1<<5);
+ }
+
+break;
+case TGH_NUM:
+//Macro: TGH_NUM//-----------------------
+if (record->event.pressed){
+ start = timer_read();
+ layer_state ^=(1<<NUMB);
+ layer_state &=(1<<NUMB);
+ } else {
+ if (timer_elapsed(start) > 150) {
+ layer_state^=(1<<NUMB);
+ layer_state&=(1<<NUMB);
+ }
+ }
+return MACRO_NONE;
+
+break;
+case M_DE_OSX_PLUS_CTRLALT:
+//Macro: M_DE_OSX_PLUS_CTRLALT//-----------------------
+if (record->event.pressed) {
+ start = timer_read();
+ return MACRO(DOWN(KC_LCTRL),DOWN(KC_LALT),END);
+ } else {
+ if (timer_elapsed(start) >150) {
+ return MACRO(U(LCTRL),U(LALT),END);
+ } else {
+ return MACRO(UP(KC_LCTRL),UP(KC_LALT),TYPE(KC_RBRC),END);
+ }
+ }
+
+break;
+case SM_KISS:
+//Macro: SM_KISS//-----------------------
+if (record->event.pressed) {
+ return MACRO(DOWN(KC_LSFT),TYPE(KC_DOT),UP(KC_LSFT),TYPE(KC_SLSH),DOWN(KC_LSFT),TYPE(KC_RBRC),UP(KC_LSFT),END);
+ }
+
+break;
+case SM_FROWN:
+//Macro: SM_FROWN//-----------------------
+if (record->event.pressed) {
+ return MACRO(DOWN(KC_LSFT),TYPE(KC_DOT),UP(KC_LSFT),TYPE(KC_SLSH),DOWN(KC_LALT),TYPE(KC_8),UP(KC_LALT),END);
+ }
+
+break;
+case SM_CRY:
+//Macro: SM_CRY//-----------------------
+if (record->event.pressed) {
+ return MACRO(DOWN(KC_LSFT),TYPE(KC_COMM),UP(KC_LSFT),TYPE(KC_SLSH),DOWN(KC_LSFT),TYPE(KC_8),UP(KC_LSFT),END);
+ }
+
+break;
+case SM_SMILE:
+//Macro: SM_SMILE//-----------------------
+if (record->event.pressed) {
+ return MACRO(DOWN(KC_LSFT),TYPE(KC_DOT),UP(KC_LSFT),TYPE(KC_SLSH),DOWN(KC_LSFT),TYPE(KC_9),UP(KC_LSFT),END);
+ }
+
+break;
+case SM_SMIRK:
+//Macro: SM_SMIRK//-----------------------
+if (record->event.pressed) {
+ return MACRO(DOWN(KC_LSFT),TYPE(KC_COMM),UP(KC_LSFT),TYPE(KC_SLSH),DOWN(KC_LSFT),TYPE(KC_9),UP(KC_LSFT),END);
+ }
+
+break;
+case M_LGUI_SHFT:
+//Macro: M_LGUI_SHFT//-----------------------
+if (record->event.pressed){
+ return MACRO(DOWN(KC_LGUI),DOWN(KC_LSFT),END);
+ }else{
+ return MACRO(UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),UP(KC_LGUI),UP(KC_LSFT),U(LGUI),U(LSFT),END);
+ }
+
+break;
+case SM_HEART:
+//Macro: SM_HEART//-----------------------
+if (record->event.pressed) {
+ return MACRO(TYPE(KC_GRV),TYPE(KC_3),END);
+ }
+
+break;
+case TOG_HLD_MDIA:
+//Macro: TOG_HLD_MDIA//-----------------------
+if (record->event.pressed){
+ start = timer_read();
+ layer_state ^=(1<<MDIA);
+ layer_state &=(1<<MDIA);
+ } else {
+ if (timer_elapsed(start) > 150) {
+ layer_state^=(1<<MDIA);
+ layer_state&=(1<<MDIA);
+ }
+ }
+return MACRO_NONE;
+
+break;
+case SM_LAUGH:
+//Macro: SM_LAUGH//-----------------------
+if (record->event.pressed) {
+ return MACRO(DOWN(KC_LSFT),TYPE(KC_DOT),UP(KC_LSFT),TYPE(KC_SLSH),DOWN(KC_LSFT),TYPE(KC_D),UP(KC_LSFT),END);
+ }
+
+break;
+case SM_SAD:
+//Macro: SM_SAD//-----------------------
+if (record->event.pressed) {
+ return MACRO(DOWN(KC_LSFT),TYPE(KC_DOT),UP(KC_LSFT),TYPE(KC_SLSH),DOWN(KC_LSFT),TYPE(KC_8),UP(KC_LSFT),END);
+ }
+
+break;
+case M_DE_OSX_CIRC_CTRLCMD:
+//Macro: M_DE_OSX_CIRC_CTRLCMD//-----------------------
+if (record->event.pressed) {
+ start = timer_read();
+ return MACRO(DOWN(KC_LCTRL),DOWN(KC_LGUI),END);
+ } else {
+ if (timer_elapsed(start) >150) {
+ return MACRO(U(LCTRL),U(LGUI),END);
+ } else {
+ return MACRO(UP(KC_LCTRL),UP(KC_LGUI),TYPE(KC_NUBS),END);
+ }
+ }
+
+break;
+case M_MEH_SH_ACUT:
+//Macro: M_MEH_SH_ACUT//-----------------------
+if (record->event.pressed) {
+ start = timer_read();
+ return MACRO(DOWN(KC_LCTRL),DOWN(KC_LSFT),DOWN(KC_LALT),END);
+ } else {
+ if (timer_elapsed(start) >150) {
+ return MACRO(U(LCTRL),U(LSFT),U(LALT),END);
+ } else {
+ return MACRO(UP(KC_LCTRL),UP(KC_LALT),TYPE(DE_OSX_ACUT),UP(KC_LSFT),END);
+ }
+ }
+
+break;
+}
+return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+uint8_t layer = biton32(layer_state);
+
+ergodox_board_led_off();
+ergodox_right_led_1_off();
+ergodox_right_led_2_off();
+ergodox_right_led_3_off();
+switch (layer) {
+
+ case SYMB:
+ ergodox_right_led_1_on();
+
+
+ break;
+ case MDIA:
+
+ ergodox_right_led_2_on();
+
+ break;
+ case NUMB:
+
+
+ ergodox_right_led_3_on();
+ break;
+ case EGOS:
+ ergodox_right_led_1_on();
+ ergodox_right_led_2_on();
+ ergodox_right_led_3_on();
+ break;
+default:
+// none
+break;
+}
+
+};
+
diff --git a/keyboards/ergodox_ez/keymaps/osx_de_experimental/osx_de_experimental_highres.png b/keyboards/ergodox_ez/keymaps/osx_de_experimental/osx_de_experimental_highres.png
new file mode 100644
index 000000000..031d874a7
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/osx_de_experimental/osx_de_experimental_highres.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/osx_de_experimental/readme.md b/keyboards/ergodox_ez/keymaps/osx_de_experimental/readme.md
new file mode 100644
index 000000000..e6a101841
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/osx_de_experimental/readme.md
@@ -0,0 +1,22 @@
+
+# Ergodox und Ergodox-EZ experimentelles Layout
+
+dieses layout ist experimentell und wird im Lufe der Zeit viele Änderungen und Verbesserungen durchlaufen. Falls diese sich als vorteilhaft erweisen, werden sie evtl. auch in das `osx_de` layout übernommen.
+
+
+
+# Erstellt Mit Dem ErgodoxLayoutGenerator
+
+Der ErgodoxLayoutGenerator (ELG) ist ein kleines Werkzeug, welches die Erstellung und Pflege der eigenen Keymaps erleichtern soll. Es ist in java geschrieben und kann [hier](https://github.com/sboesebeck/ErgodoxLayoutGenerator/releases) heruntergeladen werden. Damit das Tool funktioniert sollte das offizielle Oracle JDK in aktueller Version installiert sein.
+Die Dokumentation für den ELG kann man [hier](https://boesebeck.name/2016/04/16/ergodoxlayoutgenerator-documentation/) nachlesen (momentan leider nur in Englisch verfügbar).
+---------------------------------------------------------------------------------------------------------------------
+
+# Ergodox and Ergodox-EZ experimental layout
+
+This is an experimental layout which will undergo heavy changes over time. If changes prove to be good, they might also move into the `osx_de` layout.
+
+Created Using the ErgodoxLayoutGenerator
+
+The ErgodoxLayoutGenerator (ELG) is a little tool, which makes the creation and maintenance of keycaps a lot easier. It was written in Java and can be downloaded [here](https://github.com/sboesebeck/ErgodoxLayoutGenerator/releases). To use the tool, you need to have a current version of Oracles JDK installed.
+
+The documentation of the ELG can be viewed [here](https://boesebeck.name/2016/04/16/ergodoxlayoutgenerator-documentation/). \ No newline at end of file
diff --git a/keyboards/ergodox_ez/keymaps/osx_fr/keymap.c b/keyboards/ergodox_ez/keymaps/osx_fr/keymap.c
new file mode 100644
index 000000000..de951666d
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/osx_fr/keymap.c
@@ -0,0 +1,187 @@
+// French AZERTY version of the default_osx file
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+#include "keymap_french_osx.h"
+
+#define BASE 0 // default layer
+#define SYMB 1 // symbols
+#define MDIA 2 // media keys
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | - | & | é | " | ' | ( | LEFT | | RIGHT| § | è | ! | ç | à | ) |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Del | A | Z | E | R | T | L1 | | L1 | Y | U | I | O | P | ` |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | BkSp | Q | S | D | F | G |------| |------| H | J | K | L | M | LGui |
+ * |--------+------+------+------+------+------| Hyper| | Meh |------+------+------+------+------+--------|
+ * | LShift |W/Ctrl| X | C | V | B | | | | N | , |; / L2| : |=/Ctrl| RShift |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | ù /L1| < |AltShf| Left | Right| | Up | Down | ^ | $ | ~L1 |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,---------------.
+ * | App | LGui | | Alt |Ctrl/Esc|
+ * ,------|------|------| |------+--------+------.
+ * | | | Home | | PgUp | | |
+ * | Space|Backsp|------| |------| Tab |Enter |
+ * | |ace | End | | PgDn | | |
+ * `--------------------' `----------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ FR_MINS, FR_AMP, FR_EACU, FR_QUOT, FR_APOS, FR_LPRN, KC_LEFT,
+ KC_DELT, FR_A, FR_Z, KC_E, KC_R, KC_T, TG(1),
+ KC_BSPC, FR_Q, KC_S, KC_D, KC_F, KC_G,
+ KC_LSFT, CTL_T(FR_W), KC_X, KC_C, KC_V, KC_B, ALL_T(KC_NO),
+ LT(SYMB,FR_UGRV), FR_LESS, LALT(KC_LSFT), KC_LEFT, KC_RGHT,
+ ALT_T(KC_APP), KC_LGUI,
+ KC_HOME,
+ KC_SPC, KC_BSPC, KC_END,
+
+ // right hand
+ KC_RGHT, FR_SECT, FR_EGRV, FR_EXLM, FR_CCED, FR_AGRV, FR_RPRN,
+ TG(1), KC_Y, KC_U, KC_I, KC_O, KC_P, FR_GRV,
+ KC_H, KC_J, KC_K, KC_L, FR_M, KC_LGUI,
+ MEH_T(KC_NO), KC_N, FR_COMM, LT(MDIA, FR_SCLN), FR_COLN, CTL_T(FR_EQL), KC_RSFT,
+ KC_UP, KC_DOWN, KC_LBRC, KC_RBRC, KC_FN1,
+ KC_LALT, CTL_T(KC_ESC),
+ KC_PGUP,
+ KC_PGDN, KC_TAB, KC_ENT
+ ),
+/* Keymap 1: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | , | 0 | = | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[SYMB] = KEYMAP(
+ // left hand
+ KC_TRNS,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS,FR_EXLM,FR_AT, FR_LCBR,FR_RCBR,FR_PIPE,KC_TRNS,
+ KC_TRNS,FR_HASH,FR_DLR, FR_LPRN,FR_RPRN,FR_GRV,
+ KC_TRNS,FR_PERC,FR_CIRC,FR_LBRC,FR_RBRC,FR_TILD,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_UP, FR_7, FR_8, FR_9, FR_ASTR, KC_F12,
+ KC_DOWN, FR_4, FR_5, FR_6, FR_PLUS, KC_TRNS,
+ KC_TRNS, FR_AMP, FR_1, FR_2, FR_3, FR_BSLS, KC_TRNS,
+ KC_TRNS,FR_COMM, FR_0, FR_EQL, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/* Keymap 2: Media and mouse keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | MsUp | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | |MsLeft|MsDown|MsRght| |------| |------| | | | | | Play |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | | | | Prev | Next | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | Lclk | Rclk | |VolUp |VolDn | Mute | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | |Brwser|
+ * | | |------| |------| |Back |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// MEDIA AND MOUSE
+KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MPRV, KC_MNXT, KC_TRNS, KC_TRNS,
+ KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_WBAK
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(SYMB) // FN1 - Momentary Layer 1 (Symbols)
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case 1:
+ ergodox_right_led_1_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+}; \ No newline at end of file
diff --git a/keyboards/ergodox_ez/keymaps/osx_kinesis_pnut/keymap.c b/keyboards/ergodox_ez/keymaps/osx_kinesis_pnut/keymap.c
new file mode 100644
index 000000000..1032be549
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/osx_kinesis_pnut/keymap.c
@@ -0,0 +1,191 @@
+// Netable differences vs. the default firmware for the ErgoDox EZ:
+// 1. The Cmd key is now on the right side, making Cmd+Space easier.
+// 2. The media keys work on OSX (But not on Windows).
+// Wanted to map default layer of my EZ to my existing Kinesis Mapping.
+// Only default layer was remapped all others layers are standard Ergodox EZ
+// Very personal mapping of-course, but who knows a starting point for others.
+
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define BASE 0 // default layer
+#define SYMB 1 // symbols
+#define MDIA 2 // media keys
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | CapsL | 1 | 2 | 3 | 4 | 5 | LEFT | | RIGHT| 6 | 7 | 8 | 9 | 0 | - |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | TAB | Q | W | E | R | T | L1 | | L1 | Y | U | I | O | P | \ |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | ESC | A | S | D | F | G |------| |------| H | J | K | L |; / L2| '" |
+ * |--------+------+------+------+------+------| Hyper| | Meh |------+------+------+------+------+--------|
+ * | LShift |Z/Ctrl| X | C | V | B | | | | N | M | , | . |//Ctrl| RShift |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * |AltShf|Grv/L1| '" | Left | Right| | Up | Down | [ | ] | ~L1 |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | LGui | App | | Ctrl/Esc | RGui |
+ * ,------|------|------| |------+--------+------.
+ * | | | Home | | = | | |
+ * | Backs|Delete|------| |------| Enter |Space |
+ * | pace | | End | | TAB | | |
+ * `--------------------' `----------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_CAPSLOCK, KC_1, KC_2, KC_3, KC_4, KC_5, KC_LEFT,
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, TG(1),
+ KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_LSFT, CTL_T(KC_Z), KC_X, KC_C, KC_V, KC_B, ALL_T(KC_NO),
+ LALT(KC_LSFT), LT(SYMB,KC_GRV),KC_QUOT,KC_LEFT,KC_RGHT,
+ KC_LGUI, ALT_T(KC_APP),
+ KC_HOME,
+ KC_BSPC,KC_DELT,KC_END,
+ // right hand
+ KC_RGHT, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
+ TG(1), KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSLS,
+ KC_H, KC_J, KC_K, KC_L, LT(MDIA, KC_SCLN),KC_QUOTE,
+ MEH_T(KC_NO),KC_N, KC_M, KC_COMM,KC_DOT, CTL_T(KC_SLSH), KC_RSFT,
+ KC_UP, KC_DOWN,KC_LBRC,KC_RBRC, KC_FN1,
+ CTL_T(KC_ESC), KC_LGUI,
+ KC_EQL,
+ KC_TAB, KC_ENT, KC_SPC
+ ),
+/* Keymap 1: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | . | 0 | = | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[SYMB] = KEYMAP(
+ // left hand
+ KC_TRNS,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS,KC_EXLM,KC_AT, KC_LCBR,KC_RCBR,KC_PIPE,KC_TRNS,
+ KC_TRNS,KC_HASH,KC_DLR, KC_LPRN,KC_RPRN,KC_GRV,
+ KC_TRNS,KC_PERC,KC_CIRC,KC_LBRC,KC_RBRC,KC_TILD,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_UP, KC_7, KC_8, KC_9, KC_ASTR, KC_F12,
+ KC_DOWN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS,
+ KC_TRNS, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS, KC_TRNS,
+ KC_TRNS,KC_DOT, KC_0, KC_EQL, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/* Keymap 2: Media and mouse keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | MsUp | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | |MsLeft|MsDown|MsRght| |------| |------| | | | | | Play |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | | | | Prev | Next | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | Lclk | Rclk | |VolUp |VolDn | Mute | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | |Brwser|
+ * | | |------| |------| |Back |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// MEDIA AND MOUSE
+KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MPRV, KC_MNXT, KC_TRNS, KC_TRNS,
+ KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_WBAK
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(SYMB) // FN1 - Momentary Layer 1 (Symbols)
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case 1:
+ ergodox_right_led_1_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/plover/keymap.c b/keyboards/ergodox_ez/keymaps/plover/keymap.c
new file mode 100644
index 000000000..a991e6082
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/plover/keymap.c
@@ -0,0 +1,228 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define BASE 0 // default layer
+#define SYMB 1 // symbols
+#define MDIA 2 // media keys
+#define PLVR 3 // Plover layer
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | = | 1 | 2 | 3 | 4 | 5 | LGui | | RIGHT| 6 | 7 | 8 | 9 | 0 | - |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Tab | Q | W | E | R | T | L1 | |Plover| Y | U | I | O | P | \ |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | Esc | A | S | D | F | G |------| |------| H | J | K | L |; / L2| ' |
+ * |--------+------+------+------+------+------| Hyper| | Meh |------+------+------+------+------+--------|
+ * | LShift |Z/Ctrl| X | C | V | B | | | | N | M | , | . |//Ctrl| RShift |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * |Grv/L1| '" |AltShf| Left | Right| | Up | Down | [ | ] | ~L1 |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | App | Home | | Alt |Ctrl/Esc|
+ * ,------|------|------| |------+--------+------.
+ * | | | End | | PgUp | | |
+ * |Backsp|Delete|------| |------| Enter |Space |
+ * | ace | | LAlt | | PgDn | | |
+ * `--------------------' `----------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_EQL, KC_1, KC_2, KC_3, KC_4, KC_5, KC_LGUI,
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, TG(1),
+ KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_LSFT, CTL_T(KC_Z), KC_X, KC_C, KC_V, KC_B, ALL_T(KC_NO),
+ LT(SYMB,KC_GRV),KC_QUOT, LALT(KC_LSFT), KC_LEFT,KC_RGHT,
+ ALT_T(KC_APP), KC_HOME,
+ KC_END,
+ KC_BSPC,KC_DELT,KC_LALT,
+ // right hand
+ KC_RGHT, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
+ TG(3), KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSLS,
+ KC_H, KC_J, KC_K, KC_L, LT(MDIA, KC_SCLN),KC_QUOT,
+ MEH_T(KC_NO),KC_N, KC_M, KC_COMM,KC_DOT, CTL_T(KC_SLSH), KC_RSFT,
+ KC_UP, KC_DOWN,KC_LBRC,KC_RBRC, KC_FN1,
+ KC_LALT, CTL_T(KC_ESC),
+ KC_PGUP,
+ KC_PGDN,KC_ENT, KC_SPC
+ ),
+/* Keymap 1: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | . | 0 | = | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[SYMB] = KEYMAP(
+ // left hand
+ KC_TRNS,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS,KC_EXLM,KC_AT, KC_LCBR,KC_RCBR,KC_PIPE,KC_TRNS,
+ KC_TRNS,KC_HASH,KC_DLR, KC_LPRN,KC_RPRN,KC_GRV,
+ KC_TRNS,KC_PERC,KC_CIRC,KC_LBRC,KC_RBRC,KC_TILD,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_UP, KC_7, KC_8, KC_9, KC_ASTR, KC_F12,
+ KC_DOWN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS,
+ KC_TRNS, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS, KC_TRNS,
+ KC_TRNS,KC_DOT, KC_0, KC_EQL, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/* Keymap 2: Media and mouse keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | |------| |------|MsLeft|MsDown| MsUp |MsRght| | Play |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | | | | Prev | Next | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | Lclk | Rclk | |VolUp |VolDn | Mute | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | |Brwser|Brwser|
+ * | Lclk | Rclk |------| |------|Fwd |Back |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// MEDIA AND MOUSE
+KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_BTN1, KC_BTN2, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_MS_L, KC_MS_D, KC_MS_U, KC_MS_R, KC_TRNS, KC_MPLY,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MPRV, KC_MNXT, KC_TRNS, KC_TRNS,
+ KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_WBAK, KC_WFWD
+),
+
+/* Keymap 4: Steno for Plover from https://github.com/shayneholmes/tmk_keyboard/commit/11290f8489013018f778627db725160c745e75bd
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | 1 | 2 | 3 | 4 | 5 | | | | 6 | 7 | 8 | 9 | 0 | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | q | w | e | r | t |------| |------| y | u | i | o | p | [ |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | a | s | d | f | g | | | | h | j | k | l | ; | ' |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | | | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | c | v |------| |------| n | m |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+
+[PLVR] = KEYMAP( // layout: layer 4: Steno for Plover
+ // left hand
+ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+ KC_NO, KC_1, KC_2, KC_3, KC_4, KC_5, KC_NO,
+ KC_NO, KC_Q, KC_W, KC_E, KC_R, KC_T,
+ KC_NO, KC_A, KC_S, KC_D, KC_F, KC_G, KC_NO,
+ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+ KC_FN4, KC_NO,
+ KC_NO,
+ KC_C, KC_V, KC_NO,
+ // right hand
+ KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_TRNS,
+ KC_NO, KC_6, KC_7, KC_8, KC_9, KC_0, KC_TRNS,
+ KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC,
+ KC_NO, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT,
+ KC_TRNS, KC_TRNS, KC_NO, KC_NO, KC_NO,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_NO, KC_N, KC_M
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(SYMB) // FN1 - Momentary Layer 1 (Symbols)
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case 1:
+ ergodox_right_led_1_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/plums/keymap.c b/keyboards/ergodox_ez/keymaps/plums/keymap.c
new file mode 100644
index 000000000..46eb2e42b
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/plums/keymap.c
@@ -0,0 +1,229 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define BASE 0 // default layer
+#define SYMB 1 // symbols
+#define MDIA 2 // media keys
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | ` | 1 | 2 | 3 | 4 | 5 | F5 | |Hypr+M| 6 | 7 | 8 | 9 | 0 | Mute |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Tab | Q | W | E | R | T | [ | | ] | Y | U | I | O | P | \ |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | LGui | A | S | D | F | G |------| |------| H | J | K | L | ; | ' |
+ * |--------+------+------+------+------+------| SYMB | | MDIA |------+------+------+------+------+--------|
+ * | LShift | Z | X | C | V | B | | | | N | M | , | . | / | RShift |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * |Ca/Ctl| { | ( | | | : | | - | = | ) | } |C`/Ctl|
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | LGA | LAlt | | RAlt | Play |
+ * ,------|------|------| |------+------+------.
+ * | | | Home | | PgUp | | |
+ * |Backsp| Esc |------| |------|Enter |Space |
+ * |ace | | End | | PgDn | | |
+ * `--------------------' `--------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_F5,
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_LBRC,
+ KC_LGUI, KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, TG(SYMB),
+ F(0), KC_LCBR, KC_LPRN,KC_PIPE,KC_COLN,
+ LGUI(KC_LALT), KC_LALT,
+ KC_HOME,
+ KC_BSPC, KC_ESC, KC_END,
+ // right hand
+ HYPR(KC_M), KC_6, KC_7, KC_8, KC_9, KC_0, KC_MUTE,
+ KC_RBRC, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSLS,
+ KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT,
+ TG(MDIA), KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT,
+ KC_MINS, KC_EQL, KC_RPRN, KC_RCBR, F(1),
+ KC_RALT, KC_MPLY,
+ KC_PGUP,
+ KC_PGDN, KC_ENT, KC_SPC
+ ),
+/* Keymap 1: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | ! | @ | { | } | | | | | | | | | | | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | # | $ | ( | ) | ` |------| |------| Left | Down | Up | Right| | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | % | ^ | [ | ] | ~ | | | | | | | | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | | | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[SYMB] = KEYMAP(
+ // left hand
+ KC_TRNS,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS,KC_EXLM,KC_AT, KC_LCBR,KC_RCBR,KC_PIPE,KC_TRNS,
+ KC_TRNS,KC_HASH,KC_DLR, KC_LPRN,KC_RPRN,KC_GRV,
+ KC_TRNS,KC_PERC,KC_CIRC,KC_LBRC,KC_RBRC,KC_TILD,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_F12,
+ KC_LEFT, KC_DOWN, KC_UP, KC_RIGHT, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/* Keymap 2: Media and mouse keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | |------| |------|MsLeft|MsDown| MsUp |MsRght| | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | | | | | | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * |VolUp |VolDn | Prev | Next | | | LClk | RClk | | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// MEDIA AND MOUSE
+[MDIA] = KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_VOLU, KC_VOLD, KC_MPRV, KC_MNXT, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_MS_L, KC_MS_D, KC_MS_U, KC_MS_R, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_BTN1, KC_BTN2, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_WBAK
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [0] = ACTION_MACRO_TAP(0), // FN0 - Ctrl + a (For screen/tmux)
+ [1] = ACTION_MACRO_TAP(1) // FN1 - Ctrl + ` (For quake style console)
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) // this is the function signature -- just copy/paste it into your keymap file as it is.
+{
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ if (record->tap.count) {
+ if (record->tap.interrupted) {
+ record->tap.count = 0;
+ // hold press action
+ register_code(KC_LCTL);
+ } else {
+ // tap press action
+ return MACRO( D(LCTL), T(A), U(LCTL), END );
+ }
+ } else {
+ // hold press action
+ register_code(KC_LCTL);
+ }
+ } else {
+ if (record->tap.count) {
+ // tap release action
+ } else {
+ // hold release action
+ unregister_code(KC_LCTL);
+ }
+ record->tap.count = 0;
+ }
+ break;
+ case 1:
+ if (record->event.pressed) {
+ if (record->tap.count) {
+ if (record->tap.interrupted) {
+ record->tap.count = 0;
+ // hold press action
+ register_code(KC_RCTL);
+ } else {
+ // tap press action
+ return MACRO( DOWN(KC_RCTL), TYPE(KC_GRV), UP(KC_RCTL), END );
+ }
+ } else {
+ // hold press action
+ register_code(KC_RCTL);
+ }
+ } else {
+ if (record->tap.count) {
+ // tap release action
+ } else {
+ // hold release action
+ unregister_code(KC_RCTL);
+ }
+ record->tap.count = 0;
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case 1:
+ ergodox_right_led_1_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/plums/plums.png b/keyboards/ergodox_ez/keymaps/plums/plums.png
new file mode 100644
index 000000000..2f127c4ca
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/plums/plums.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/plums/readme.md b/keyboards/ergodox_ez/keymaps/plums/readme.md
new file mode 100644
index 000000000..b72329eef
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/plums/readme.md
@@ -0,0 +1,11 @@
+# ErgoDox EZ Plums Configuration
+
+## Changelog
+
+* Apr 23, 2016 (v0.1.0):
+ * Shortcut for iTerm2 quake style dropdown (Ctrl+`)
+ * Shortcut for screen/tmux (Ctrl+a)
+ * Shortcut for shush (Hyper+m)
+ * Combo modifier for LGUI + LALT
+
+![Plums](plums.png)
diff --git a/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-osx/keymap.c b/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-osx/keymap.c
new file mode 100644
index 000000000..a66971bef
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-osx/keymap.c
@@ -0,0 +1,46 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define BASE 0
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ [BASE] = KEYMAP(
+ KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_F5,
+ KC_TAB, KC_Q, KC_W, KC_D, KC_F, KC_K, KC_BSLS,
+ CTL_T(KC_ESC), KC_A, KC_S, KC_E, KC_T, KC_G,
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_LBRC,
+ KC_F1, KC_F2, KC_F3, KC_F4, KC_LGUI,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_VOLD, KC_MUTE,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_VOLU,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_BSPC, CTL_T(KC_ESC), KC_LALT,
+ //
+ /*-*/ KC_F6, KC_6, KC_7, KC_8, KC_9, KC_0, KC_EQL,
+ /*-*/ KC_NO, KC_J, KC_U, KC_R, KC_L, KC_SCLN, KC_MINS,
+ /*-*/ /*-*/ KC_Y, KC_N, KC_I, KC_O, KC_H, KC_ENT,
+ /*-*/ KC_RBRC, KC_P, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT,
+ /*-*/ /*-*/ /*-*/ KC_RGUI, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT,
+ KC_MPLY, KC_MNXT,
+ KC_MPRV,
+ KC_RALT, KC_QUOT, KC_SPC
+ )
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) {
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+};
diff --git a/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-osx/readme.md b/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-osx/readme.md
new file mode 100644
index 000000000..80475ab21
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-osx/readme.md
@@ -0,0 +1,28 @@
+# Roman's Layout
+
+There is only one layer based on [Norman layout](https://normanlayout.info/).
+
+Looking for multiple-layer layouts?
+
+- [Symbols, arrows, plover, HJKL arrows](../romanzolotarev-norman-plover-osx-hjkl/)
+- [Same with IJKL arrows](../romanzolotarev-norman-plover-osx/)
+
+[![keyboard-layout](romanzolotarev-norman-osx.png)](http://www.keyboard-layout-editor.com/#/gists/9e89d54f1ea6eeeb7dab1b2d19d28195)
+
+## Functional Keys
+
+- Tap `F1` to mute microphone via [Shush](http://mizage.com/shush/).
+- Tap `F2` to copy screenshot to the clipboard.
+- Hold `SHIFT` and tap `F2` to save screenshot as a file.
+- Tap `F3`, `F4`, `F5`, `F6` to resize a window via [Divvy](http://mizage.com/divvy/).
+
+## CTRL/ESC
+
+CTRL and ESC are frequently used in Vim.
+
+- Tap `CTRL/ESC` to send `ESC`.
+- Hold `CTRL/ESC` to use as `CTRL`.
+
+## Activate N-rollover
+
+- Hold left `SHIFT` and right `SHIRT` and then tap `N`.
diff --git a/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-osx/romanzolotarev-norman-osx.png b/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-osx/romanzolotarev-norman-osx.png
new file mode 100644
index 000000000..4b9433be2
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-osx/romanzolotarev-norman-osx.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-plover-osx-hjkl/keymap.c b/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-plover-osx-hjkl/keymap.c
new file mode 100644
index 000000000..7c9f67381
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-plover-osx-hjkl/keymap.c
@@ -0,0 +1,134 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define BASE 0
+#define SYMB 1
+#define PLVR 2
+#define ARRW 3
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ [BASE] = KEYMAP(
+ KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_F14,
+ KC_TAB, KC_Q, KC_W, KC_D, KC_F, KC_K, TG(PLVR),
+ CTL_T(KC_ESC), KC_A, KC_S, KC_E, KC_T, KC_G,
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_LBRC,
+ KC_F1, KC_F2, KC_F3, KC_LALT, KC_LGUI,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_VOLD, KC_MUTE,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_VOLU,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_BSPC, CTL_T(KC_ESC), KC_FN1,
+ //
+ /*-*/ KC_F15, KC_6, KC_7, KC_8, KC_9, KC_0, KC_EQL,
+ /*-*/ KC_BSLS, KC_J, KC_U, KC_R, KC_L, KC_SCLN, KC_MINS,
+ /*-*/ /*-*/ KC_Y, KC_N, KC_I, KC_O, KC_H, KC_ENT,
+ /*-*/ KC_RBRC, KC_P, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT,
+ /*-*/ /*-*/ /*-*/ KC_RGUI, KC_RALT, KC_F4, KC_F5, KC_F6,
+ KC_MPLY, KC_MNXT,
+ KC_MPRV,
+ KC_FN3, KC_QUOT, KC_SPC
+ ),
+ [SYMB] = KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_1, KC_2, KC_3, KC_4, KC_5, KC_TRNS,
+ KC_TRNS, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS,
+ //
+ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ /*-*/ KC_TRNS, KC_6, KC_7, KC_8, KC_9, KC_0, KC_TRNS,
+ /*-*/ /*-*/ KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_TRNS,
+ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+ ),
+ [PLVR] = KEYMAP(
+ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_TRNS,
+ KC_NO, KC_1, KC_2, KC_3, KC_4, KC_5, KC_TRNS,
+ KC_NO, KC_Q, KC_W, KC_E, KC_R, KC_T,
+ KC_NO, KC_A, KC_S, KC_D, KC_F, KC_G, KC_NO,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_NO, KC_NO,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ KC_C, KC_V, KC_NO,
+ //
+ /*-*/ KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+ /*-*/ KC_NO, KC_6, KC_7, KC_8, KC_9, KC_0, KC_NO,
+ /*-*/ /*-*/ KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC,
+ /*-*/ KC_NO, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT,
+ /*-*/ /*-*/ /*-*/ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_NO, KC_N, KC_M
+ ),
+ [ARRW] = KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_U, KC_MS_D, KC_MS_R,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS,
+ //
+ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, KC_TRNS, KC_TRNS,
+ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+ ),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [SYMB] = ACTION_LAYER_TAP_TOGGLE(SYMB), // FN1 - Momentary Symbols Layer
+ [PLVR] = ACTION_LAYER_TAP_TOGGLE(PLVR), // FN2 - Momentary Plover Layer
+ [ARRW] = ACTION_LAYER_TAP_TOGGLE(ARRW), // FN3 - Momentary Arrows Layer
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+ uint8_t layer = biton32(layer_state);
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ case SYMB:
+ ergodox_right_led_1_on();
+ break;
+ case PLVR:
+ ergodox_right_led_2_on();
+ break;
+ case ARRW:
+ ergodox_right_led_3_on();
+ break;
+ default:
+ break;
+ }
+};
diff --git a/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-plover-osx-hjkl/readme.md b/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-plover-osx-hjkl/readme.md
new file mode 100644
index 000000000..4188d2b50
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-plover-osx-hjkl/readme.md
@@ -0,0 +1,50 @@
+# Roman's Layout
+
+There are four layers:
+
+- **BASE** is [Norman layout](https://normanlayout.info/).
+- **SYMB** for numbers and symbols.
+- **PLVR** is optimized for [Plover](http://www.openstenoproject.org).
+- **ARRW** for navigation (same fingers for arrows as HJKL on QWERTY).
+
+Looking for IJKL arrows? [Here we
+go](../romanzolotarev-norman-plover-osx/).
+
+[![keyboard-layout](romanzolotarev-norman-plover-osx-hjkl.png)](rttp://www.keyboard-layout-editor.com/#/gists/56ffedceb0668dda47c993e7271563e0)
+
+## Switching
+
+- Tap `SYMB` to toggle **SYMB**.
+- Tap `ARRW` to toggle **ARRW**.
+- Hold `SYMB` (or `ARRW`) to activate **SYMB** (or **ARRW**) while holding.
+- Tap `PLVR` to toggle **PLVR**.
+
+## LEDs
+
+- Red: SYMB is on.
+- Green: PLVR is on.
+- Blue: ARRW is on.
+
+## Functional Keys
+
+- Tap `F1` to mute microphone via [Shush](http://mizage.com/shush/).
+- Tap `F2` to copy screenshot to the clipboard.
+- Hold `SHIFT` and tap `F2` to save screenshot as a file.
+- Tap `F3`, `F4`, `F5`, `F6` to resize a window via [Divvy](http://mizage.com/divvy/).
+- Tap `F14`, `F15` to adjust display brightness.
+
+**IMPORTANT**: If you have another keyboard connected via Bluetooth, then
+`F14` and `F15` will not work. Turn off that Bluetooth keyboard. Re-plug
+you ErgoDox. Enjoy!
+
+## CTRL/ESC
+
+Both of those keys are frequently used in Vim.
+
+- Tap `CTRL/ESC` to send `ESC`.
+- Hold `CTRL/ESC` to use as `CTRL`.
+
+## Activate N-rollover
+
+- While in **BASE** hold left `SHIFT` and right `SHIRT` and then tap `N`.
+- Then you can activate **PLVR** and use ErgoDox EZ for steno.
diff --git a/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-plover-osx-hjkl/romanzolotarev-norman-plover-osx-hjkl.png b/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-plover-osx-hjkl/romanzolotarev-norman-plover-osx-hjkl.png
new file mode 100644
index 000000000..cdc535f79
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-plover-osx-hjkl/romanzolotarev-norman-plover-osx-hjkl.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-plover-osx/keymap.c b/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-plover-osx/keymap.c
new file mode 100644
index 000000000..9971b834c
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-plover-osx/keymap.c
@@ -0,0 +1,134 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define BASE 0
+#define SYMB 1
+#define PLVR 2
+#define ARRW 3
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ [BASE] = KEYMAP(
+ KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_F14,
+ KC_TAB, KC_Q, KC_W, KC_D, KC_F, KC_K, TG(PLVR),
+ CTL_T(KC_ESC), KC_A, KC_S, KC_E, KC_T, KC_G,
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_LBRC,
+ KC_F1, KC_F2, KC_F3, KC_LALT, KC_LGUI,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_VOLD, KC_MUTE,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_VOLU,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_BSPC, CTL_T(KC_ESC), KC_FN1,
+ //
+ /*-*/ KC_F15, KC_6, KC_7, KC_8, KC_9, KC_0, KC_EQL,
+ /*-*/ KC_BSLS, KC_J, KC_U, KC_R, KC_L, KC_SCLN, KC_MINS,
+ /*-*/ /*-*/ KC_Y, KC_N, KC_I, KC_O, KC_H, KC_ENT,
+ /*-*/ KC_RBRC, KC_P, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT,
+ /*-*/ /*-*/ /*-*/ KC_RGUI, KC_RALT, KC_F4, KC_F5, KC_F6,
+ KC_MPLY, KC_MNXT,
+ KC_MPRV,
+ KC_FN3, KC_QUOT, KC_SPC
+ ),
+ [SYMB] = KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_1, KC_2, KC_3, KC_4, KC_5, KC_TRNS,
+ KC_TRNS, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS,
+ //
+ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ /*-*/ KC_TRNS, KC_6, KC_7, KC_8, KC_9, KC_0, KC_TRNS,
+ /*-*/ /*-*/ KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_TRNS,
+ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+ ),
+ [PLVR] = KEYMAP(
+ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_TRNS,
+ KC_NO, KC_1, KC_2, KC_3, KC_4, KC_5, KC_TRNS,
+ KC_NO, KC_Q, KC_W, KC_E, KC_R, KC_T,
+ KC_NO, KC_A, KC_S, KC_D, KC_F, KC_G, KC_NO,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_NO, KC_NO,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ KC_C, KC_V, KC_NO,
+ //
+ /*-*/ KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+ /*-*/ KC_NO, KC_6, KC_7, KC_8, KC_9, KC_0, KC_NO,
+ /*-*/ /*-*/ KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC,
+ /*-*/ KC_NO, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT,
+ /*-*/ /*-*/ /*-*/ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_NO, KC_N, KC_M
+ ),
+ [ARRW] = KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_BTN1, KC_MS_U, KC_BTN2, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS,
+ //
+ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS, KC_UP, KC_TRNS, KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS, KC_TRNS,
+ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+ ),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [SYMB] = ACTION_LAYER_TAP_TOGGLE(SYMB), // FN1 - Momentary Symbols Layer
+ [PLVR] = ACTION_LAYER_TAP_TOGGLE(PLVR), // FN2 - Momentary Plover Layer
+ [ARRW] = ACTION_LAYER_TAP_TOGGLE(ARRW), // FN3 - Momentary Arrows Layer
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+ uint8_t layer = biton32(layer_state);
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ case SYMB:
+ ergodox_right_led_1_on();
+ break;
+ case PLVR:
+ ergodox_right_led_2_on();
+ break;
+ case ARRW:
+ ergodox_right_led_3_on();
+ break;
+ default:
+ break;
+ }
+};
diff --git a/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-plover-osx/readme.md b/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-plover-osx/readme.md
new file mode 100644
index 000000000..804c52a76
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-plover-osx/readme.md
@@ -0,0 +1,50 @@
+# Roman's Layout
+
+There are four layers:
+
+- **BASE** is [Norman layout](https://normanlayout.info/).
+- **SYMB** for numbers and symbols.
+- **PLVR** is optimized for [Plover](http://www.openstenoproject.org).
+- **ARRW** for navigation (same fingers for arrows as IJKL on QWERTY).
+
+Looking for HJKL arrows? [Here we
+go](../romanzolotarev-norman-plover-osx-hjkl/).
+
+[![keyboard-layout](romanzolotarev-norman-plover-osx.png)](http://www.keyboard-layout-editor.com/#/gists/8ebcb701ecb763944417)
+
+## Switching
+
+- Tap `SYMB` to toggle **SYMB**.
+- Tap `ARRW` to toggle **ARRW**.
+- Hold `SYMB` (or `ARRW`) to activate **SYMB** (or **ARRW**) while holding.
+- Tap `PLVR` to toggle **PLVR**.
+
+## LEDs
+
+- Red: SYMB is on.
+- Green: PLVR is on.
+- Blue: ARRW is on.
+
+## Functional Keys
+
+- Tap `F1` to mute microphone via [Shush](http://mizage.com/shush/).
+- Tap `F2` to copy screenshot to the clipboard.
+- Hold `SHIFT` and tap `F2` to save screenshot as a file.
+- Tap `F3`, `F4`, `F5`, `F6` to resize a window via [Divvy](http://mizage.com/divvy/).
+- Tap `F14`, `F15` to adjust display brightness.
+
+**IMPORTANT**: If you have another keyboard connected via Bluetooth, then
+`F14` and `F15` will not work. Turn off that Bluetooth keyboard. Re-plug
+you ErgoDox. Enjoy!
+
+## CTRL/ESC
+
+Both of those keys are frequently used in Vim.
+
+- Tap `CTRL/ESC` to send `ESC`.
+- Hold `CTRL/ESC` to use as `CTRL`.
+
+## Activate N-rollover
+
+- While in **BASE** hold left `SHIFT` and right `SHIRT` and then tap `N`.
+- Then you can activate **PLVR** and use ErgoDox EZ for steno.
diff --git a/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-plover-osx/romanzolotarev-norman-plover-osx.png b/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-plover-osx/romanzolotarev-norman-plover-osx.png
new file mode 100644
index 000000000..10b0752be
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-plover-osx/romanzolotarev-norman-plover-osx.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-qwerty-osx/keymap.c b/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-qwerty-osx/keymap.c
new file mode 100644
index 000000000..dedac694e
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-qwerty-osx/keymap.c
@@ -0,0 +1,74 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define BASE 0
+#define QWRT 1
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ [BASE] = KEYMAP(
+ KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_F5,
+ KC_TAB, KC_Q, KC_W, KC_D, KC_F, KC_K, KC_BSLS,
+ KC_LCTL, KC_A, KC_S, KC_E, KC_T, KC_G,
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_LBRC,
+ KC_F1, KC_F2, KC_F3, KC_F4, KC_LGUI,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_VOLD, KC_MUTE,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_VOLU,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_BSPC, CTL_T(KC_ESC), KC_LALT,
+ //
+ /*-*/ KC_F6, KC_6, KC_7, KC_8, KC_9, KC_0, KC_EQL,
+ /*-*/ TG(QWRT), KC_J, KC_U, KC_R, KC_L, KC_SCLN, KC_MINS,
+ /*-*/ /*-*/ KC_Y, KC_N, KC_I, KC_O, KC_H, KC_ENT,
+ /*-*/ KC_RBRC, KC_P, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT,
+ /*-*/ /*-*/ /*-*/ KC_RGUI, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT,
+ KC_MPLY, KC_MNXT,
+ KC_MPRV,
+ KC_RALT, KC_QUOT, KC_SPC
+ ),
+ [QWRT] = KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_E, KC_R, KC_T, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_D, KC_F, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS,
+ /*-*/ /*-*/ /*-*/ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS,
+ //
+ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ /*-*/ KC_TRNS, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_TRNS,
+ /*-*/ /*-*/ KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_TRNS,
+ /*-*/ KC_TRNS, KC_N, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ /*-*/ /*-*/ /*-*/ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+ ),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) {
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+ uint8_t layer = biton32(layer_state);
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ case QWRT:
+ ergodox_right_led_1_on();
+ break;
+ default:
+ break;
+ }
+};
diff --git a/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-qwerty-osx/readme.md b/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-qwerty-osx/readme.md
new file mode 100644
index 000000000..0e78c130b
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-qwerty-osx/readme.md
@@ -0,0 +1,34 @@
+# Roman's Layout
+
+There are two layers:
+
+- **BASE** is [Norman layout](https://normanlayout.info/).
+- **QWRT** is QWERTY.
+
+[![keyboard-layout](romanzolotarev-norman-qwerty-osx.png)](http://www.keyboard-layout-editor.com/#/gists/3b236f450da474dc506a5a80390c3cc7)
+
+## Switching
+
+- Tap `QWRT` to toggle **QWRT**.
+
+## LEDs
+
+- Red: QWRT is on.
+
+## Functional Keys
+
+- Tap `F1` to mute microphone via [Shush](http://mizage.com/shush/).
+- Tap `F2` to copy screenshot to the clipboard.
+- Hold `SHIFT` and tap `F2` to save screenshot as a file.
+- Tap `F3`, `F4`, `F5`, `F6` to resize a window via [Divvy](http://mizage.com/divvy/).
+
+## CTRL/ESC
+
+Both CTRL and ESC are frequently used in Vim.
+
+- Tap `CTRL/ESC` to send `ESC`.
+- Hold `CTRL/ESC` to use as `CTRL`.
+
+## Activate N-rollover
+
+- Hold left `SHIFT` and right `SHIRT` and then tap `N`.
diff --git a/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-qwerty-osx/romanzolotarev-norman-qwerty-osx.png b/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-qwerty-osx/romanzolotarev-norman-qwerty-osx.png
new file mode 100644
index 000000000..34762ecb7
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/romanzolotarev-norman-qwerty-osx/romanzolotarev-norman-qwerty-osx.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/sneako/keymap.c b/keyboards/ergodox_ez/keymaps/sneako/keymap.c
new file mode 100644
index 000000000..0c6863102
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/sneako/keymap.c
@@ -0,0 +1,187 @@
+// Based on `default_osx`
+// Replace left Bksp with Ctrl/Esc
+// Remove the Ctrl from Z and /
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define BASE 0 // default layer
+#define SYMB 1 // symbols
+#define MDIA 2 // media keys
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | = | 1 | 2 | 3 | 4 | 5 | LEFT | | RIGHT| 6 | 7 | 8 | 9 | 0 | - |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Del | Q | W | E | R | T | L1 | | L1 | Y | U | I | O | P | \ |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * |Ctrl/Esc| A | S | D | F | G |------| |------| H | J | K | L |; / L2| LGui |
+ * |--------+------+------+------+------+------| Hyper| | Meh |------+------+------+------+------+--------|
+ * | LShift | Z | X | C | V | B | | | | N | M | , | . | / | RShift |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * |Grv/L1| '" |AltShf| Left | Right| | Up | Down | [ | ] | ~L1 |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | App | LGui | | Alt |Ctrl/Esc|
+ * ,------|------|------| |------+--------+------.
+ * | | | Home | | PgUp | | |
+ * | Space|Backsp|------| |------| Tab |Enter |
+ * | |ace | End | | PgDn | | |
+ * `--------------------' `----------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_EQL, KC_1, KC_2, KC_3, KC_4, KC_5, KC_LEFT,
+ KC_DELT, KC_Q, KC_W, KC_E, KC_R, KC_T, TG(1),
+ CTL_T(KC_ESC), KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, ALL_T(KC_NO),
+ LT(SYMB,KC_GRV),KC_QUOT, LALT(KC_LSFT), KC_LEFT,KC_RGHT,
+ ALT_T(KC_APP), KC_LGUI,
+ KC_HOME,
+ KC_SPC,KC_BSPC,KC_END,
+ // right hand
+ KC_RGHT, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
+ TG(1), KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSLS,
+ KC_H, KC_J, KC_K, KC_L, LT(MDIA, KC_SCLN),GUI_T(KC_QUOT),
+ MEH_T(KC_NO),KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH, KC_RSFT,
+ KC_UP, KC_DOWN,KC_LBRC,KC_RBRC, KC_FN1,
+ KC_LALT, CTL_T(KC_ESC),
+ KC_PGUP,
+ KC_PGDN,KC_TAB, KC_ENT
+ ),
+/* Keymap 1: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | . | 0 | = | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[SYMB] = KEYMAP(
+ // left hand
+ KC_TRNS,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS,KC_EXLM,KC_AT, KC_LCBR,KC_RCBR,KC_PIPE,KC_TRNS,
+ KC_TRNS,KC_HASH,KC_DLR, KC_LPRN,KC_RPRN,KC_GRV,
+ KC_TRNS,KC_PERC,KC_CIRC,KC_LBRC,KC_RBRC,KC_TILD,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_UP, KC_7, KC_8, KC_9, KC_ASTR, KC_F12,
+ KC_DOWN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS,
+ KC_TRNS, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS, KC_TRNS,
+ KC_TRNS,KC_DOT, KC_0, KC_EQL, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/* Keymap 2: Media and mouse keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | MsUp | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | |MsLeft|MsDown|MsRght| |------| |------| | | | | | Play |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | | | | Prev | Next | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | Lclk | Rclk | |VolUp |VolDn | Mute | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | |Brwser|
+ * | | |------| |------| |Back |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// MEDIA AND MOUSE
+KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MPRV, KC_MNXT, KC_TRNS, KC_TRNS,
+ KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_WBAK
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(SYMB) // FN1 - Momentary Layer 1 (Symbols)
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case 1:
+ ergodox_right_led_1_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/sneako/readme.md b/keyboards/ergodox_ez/keymaps/sneako/readme.md
new file mode 100644
index 000000000..8dd110ee6
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/sneako/readme.md
@@ -0,0 +1,6 @@
+# ergodox_keymap
+
+Based on the default Ergodox EZ firmware
+
+Replaced the left side Bksp with a Crtl/Esc, this really helps in vim.
+Removed the Ctrls from the Z and / keys.
diff --git a/keyboards/ergodox_ez/keymaps/software_neo2/keymap.c b/keyboards/ergodox_ez/keymaps/software_neo2/keymap.c
new file mode 100644
index 000000000..2eaba0d7d
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/software_neo2/keymap.c
@@ -0,0 +1,139 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+#include "keymap_neo2.h"
+
+// Layer names
+#define BASE 0 // default layer
+#define MDIA 1 // media keys
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | ^ | 1 | 2 | 3 | 4 | 5 | Play | | Next | 6 | 7 | 8 | 9 | 0 |BackSpce|
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Del | X | V | L | C | W | L1 | | L1 | K | H | G | F | Q | ß |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | Caps | U | I | A | E | O |------| |------| S | N | R | T | D | Y |
+ * |--------+------+------+------+------+------| Hyper| | Meh |------+------+------+------+------+--------|
+ * | LShift |Ü/Ctrl| Ö/C-S| Ä/Alt| P | Z | | | | B | M | , | . | J | RShift |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | L1 | Home | PgDn | PgUp | End | | Right| Down | Up | Left | Esc |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | App | LGui | | Alt |Ctrl/Esc|
+ * ,------+------+------| |------+--------+------.
+ * | | |NeoL2 | |NeoL2 | | |
+ * | Tab |Backsp|------| |------| Space |Enter |
+ * | |ace |NeoL1 | |NeoL1 | | |
+ * `--------------------' `----------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_CIRC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_MPLY,
+ KC_DELT, NEO_X, NEO_V, NEO_L, NEO_C, NEO_W, TG(1),
+ KC_CAPS, NEO_U, NEO_I, NEO_A, NEO_E, NEO_O,
+ KC_LSFT, CTL_T(NEO_UE), C_S_T(NEO_OE), ALT_T(NEO_AE), NEO_P, NEO_Z, ALL_T(KC_NO),
+ DE_LESS, KC_HOME, KC_PGDN, KC_PGUP, KC_END,
+ ALT_T(KC_APP),KC_LGUI,
+ NEO_L2_L,
+ KC_TAB,KC_BSPC,NEO_L1_L,
+ // right hand
+ KC_MNXT, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
+ TG(1), NEO_K, NEO_H, NEO_G, NEO_F, NEO_Q, NEO_SS,
+ NEO_S, NEO_N, NEO_R, NEO_T, NEO_D, NEO_Y,
+ MEH_T(KC_NO),NEO_B, NEO_M, KC_COMM, KC_DOT, NEO_J, KC_RSFT,
+ KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, KC_ESC,
+ KC_LALT,CTL_T(KC_ESC),
+ NEO_L2_R,
+ NEO_L1_R,KC_SPC, KC_ENT
+ ),
+/* Keymap 1: Media and mouse keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | Lclk | MsUp | Rclk | | | | | |VolDwn| Mute |VolUp | | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | Btn4 |MsLeft|MsDown|MsRght| Btn5 |------| |------| | Prev | Stop | Play | Next | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | |WhRght|WhDown| WhUp |WhLeft|WhClk | | | |BwSrch|BwBack|BwHome|BwRefr|BwFwd | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | |MsAcl0|MsAcl1|MsAcl2| | | | | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | |Brwser|Brwser|
+ * | Lclk | Rclk |------| |------|Back |Forwd |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// MEDIA AND MOUSE
+[MDIA] = KEYMAP(
+ KC_TRNS, KC_F1 , KC_F2 , KC_F3 , KC_F4 , KC_F5 , KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_BTN1, KC_MS_U, KC_BTN2, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_BTN4, KC_MS_L, KC_MS_D, KC_MS_R, KC_BTN5,
+ KC_TRNS, KC_WH_L, KC_WH_D, KC_WH_U, KC_WH_R, KC_BTN3, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_ACL0, KC_ACL1, KC_ACL2,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_BTN1, KC_BTN2, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6 , KC_F7 , KC_F8 , KC_F9 , KC_F10 , KC_F11,
+ KC_TRNS, KC_TRNS, KC_VOLD, KC_MUTE, KC_VOLU, KC_TRNS, KC_F12,
+ KC_TRNS, KC_MPRV, KC_MSTP, KC_MPLY, KC_MNXT, KC_TRNS,
+ KC_TRNS, KC_WSCH, KC_WBAK, KC_WHOM, KC_WREF, KC_WFWD, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_WBAK, KC_WFWD
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ /* [1] = ACTION_LAYER_TAP_TOGGLE(SYMB) // FN1 - Momentary Layer 1 (Symbols) */
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ case MDIA:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ ergodox_board_led_off();
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/supercoder/config_user.h b/keyboards/ergodox_ez/keymaps/supercoder/config_user.h
new file mode 100644
index 000000000..8da138372
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/supercoder/config_user.h
@@ -0,0 +1,9 @@
+#ifndef CONFIG_USER_H
+#define CONFIG_USER_H 1
+
+#include "config.h"
+
+#undef LOCKING_SUPPORT_ENABLE
+#undef LOCKING_RESYNC_ENABLE
+
+#endif
diff --git a/keyboards/ergodox_ez/keymaps/supercoder/images/layout.png b/keyboards/ergodox_ez/keymaps/supercoder/images/layout.png
new file mode 100644
index 000000000..c72958c6e
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/supercoder/images/layout.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/supercoder/images/supercoder_2000.jpg b/keyboards/ergodox_ez/keymaps/supercoder/images/supercoder_2000.jpg
new file mode 100644
index 000000000..d690eaf02
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/supercoder/images/supercoder_2000.jpg
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/supercoder/keymap.c b/keyboards/ergodox_ez/keymaps/supercoder/keymap.c
new file mode 100644
index 000000000..ca21d30fd
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/supercoder/keymap.c
@@ -0,0 +1,75 @@
+/*
+ * SuperCoder 2000 layout
+ */
+
+#include "ergodox_ez.h"
+
+/* Layers */
+
+#define SC2K 0 // default layer
+
+/* The Keymap */
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+
+ /* Keymap 0: Base Layer
+ *
+ * ,-----------------------------------------------------. ,-----------------------------------------------------.
+ * | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
+ * |-----------+------+------+------+------+-------------| |------+------+------+------+------+------+-----------|
+ * | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
+ * |-----------+------+------+------+------+------| | | |------+------+------+------+------+-----------|
+ * | 0 | 0 | 0 | 0 | 0 | 0 |------| |------| 1 | 1 | 1 | 1 | 1 | 1 |
+ * |-----------+------+------+------+------+------| 0 | | 1 |------+------+------+------+------+-----------|
+ * | 0 | 0 | 0 | 0 | 0 | 0 | | | | 1 | 1 | 1 | 1 | 1 | 1 |
+ * `-----------+------+------+------+------+-------------' `-------------+------+------+------+------+-----------'
+ * | 0 | 0 | 0 | 0 | 0 | | 1 | 1 | 1 | 1 | 1 |
+ * `-----------------------------------' `-----------------------------------'
+ * ,-------------. ,-------------.
+ * | DONE | DONE | | DONE | DONE |
+ * ,------|------|------| |------+------+------.
+ * | | | DONE | | DONE | | |
+ * | DONE | DONE |------| |------| DONE | DONE |
+ * | | | DONE | | DONE | | |
+ * `--------------------' `--------------------'
+ */
+[SC2K] = KEYMAP(
+ // left hand
+ KC_0 ,KC_0 ,KC_0 ,KC_0 ,KC_0 ,KC_0 ,KC_0
+,KC_0 ,KC_0 ,KC_0 ,KC_0 ,KC_0 ,KC_0 ,KC_0
+,KC_0 ,KC_0 ,KC_0 ,KC_0 ,KC_0 ,KC_0
+,KC_0 ,KC_0 ,KC_0 ,KC_0 ,KC_0 ,KC_0 ,KC_0
+,KC_0 ,KC_0 ,KC_0 ,KC_0 ,KC_0
+
+ ,KC_ENT ,KC_ENT
+ ,KC_ENT
+ ,KC_ENT ,KC_ENT ,KC_ENT
+
+ // right hand
+ ,KC_1 ,KC_1 ,KC_1 ,KC_1 ,KC_1 ,KC_1 ,KC_1
+ ,KC_1 ,KC_1 ,KC_1 ,KC_1 ,KC_1 ,KC_1 ,KC_1
+ ,KC_1 ,KC_1 ,KC_1 ,KC_1 ,KC_1 ,KC_1
+ ,KC_1 ,KC_1 ,KC_1 ,KC_1 ,KC_1 ,KC_1 ,KC_1
+ ,KC_1 ,KC_1 ,KC_1 ,KC_1 ,KC_1
+
+ ,KC_ENT ,KC_ENT
+ ,KC_ENT
+ ,KC_ENT ,KC_ENT ,KC_ENT
+ ),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+}
diff --git a/keyboards/ergodox_ez/keymaps/supercoder/makefile.mk b/keyboards/ergodox_ez/keymaps/supercoder/makefile.mk
new file mode 100644
index 000000000..41a195d9c
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/supercoder/makefile.mk
@@ -0,0 +1,6 @@
+BOOTMAGIC_ENABLE=no
+COMMAND_ENABLE=no
+SLEEP_LED_ENABLE=no
+UNICODE_ENABLE=no
+MOUSEKEY_ENABLE=no
+EXTRAKEY_ENABLE=no
diff --git a/keyboards/ergodox_ez/keymaps/supercoder/readme.md b/keyboards/ergodox_ez/keymaps/supercoder/readme.md
new file mode 100644
index 000000000..97bf7f583
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/supercoder/readme.md
@@ -0,0 +1,29 @@
+SuperCoder 2000 layout for the ErgoDox
+==================================================
+
+![SuperCoder 2000](images/supercoder_2000.jpg)
+
+Ever found yourself in need of entering binary codes rapidly? Ever wanted to use
+all ten fingers to do so? Ever felt your SuperCoder 2000 too limiting, by only
+having three buttons? We heard you! With this layout for the ErgoDox EZ, you
+will be able to tap in binary at an unparalleled speed and accuracy! Efficiency
+never seen before!
+
+Behold the Ultimate SuperCoder 2000 layout!
+
+![SuperCoder layout](images/layout.png)
+
+### To use it...
+
+To use this piece of top quality engineering, you can either
+[download the hex file][hex] we have prepared for you, or you can compile it on
+your own:
+
+ [hex]: https://raw.githubusercontent.com/algernon/ergodox-supercoder/master/supercoder.hex
+
+```
+$ git clone https://github.com/jackhumbert/qmk_firmware.git
+$ cd qmk_firmware/keyboards/ergodox_ez
+$ git clone https://github.com/algernon/ergodox-supercoder.git keymaps/supercoder
+$ make KEYMAP=supercoder
+```
diff --git a/keyboards/ergodox_ez/keymaps/techtomas/keymap.c b/keyboards/ergodox_ez/keymaps/techtomas/keymap.c
new file mode 100644
index 000000000..1ff6618b9
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/techtomas/keymap.c
@@ -0,0 +1,231 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define BASE 0 // default layer
+#define SYMB 1 // symbols
+#define APP 2 // app layer
+#define CNTL 3 // control layer
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | L2/` | 1 | 2 | 3 | 4 | 5 |CmdSpc| | - | 6 | 7 | 8 | 9 | 0 | = |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | MEH/Tab| Q | W | E | R | T | [ | | ] | Y | U | I | O | P | MEH/\ |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * |Hyp/Esc | A | S | D | F | G |------| |------| H | J | K | L | L2/; | Hyp/' |
+ * |--------+------+------+------+------+------| Tab | | STab |------+------+------+------+------+--------|
+ * | LShift | Z | X | C | V | B | | | | N | M | , | . | L2// | RShift |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * |L1/Lft|L3/Rht| LCtl | LAlt | LGui | | Rgui | Up | Dn | L3 | L1 |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | LCtl | LGui | |AltGui|ShfGui|
+ * ,-------|------|------| |------+--------+------.
+ * | | |L1/Hom| |L2/PUp| | |
+ * | Backsp|Delete|------| |------| Enter | Space |
+ * | | |L3/End| |L1/PDn| | |
+ * `--------------------' `-----------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ LT(APP,KC_GRV), KC_1, KC_2, KC_3, KC_4, KC_5, LGUI(KC_SPC),
+ MEH_T(KC_TAB), KC_Q, KC_W, KC_E, KC_R, KC_T, KC_LBRC,
+ ALL_T(KC_ESC), KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_TAB,
+ LT(SYMB,KC_LEFT), LT(CNTL,KC_RIGHT), KC_LCTL, KC_LALT, KC_LGUI,
+ KC_LCTL, KC_LGUI,
+ LT(SYMB,KC_HOME),
+ KC_BSPC, KC_DELETE, LT(CNTL,KC_END),
+ // right hand
+ KC_MINS, KC_6, KC_7, KC_8, KC_9, KC_0, KC_EQL,
+ KC_RBRC, KC_Y, KC_U, KC_I, KC_O, KC_P, MEH_T(KC_BSLS),
+ KC_H, KC_J, KC_K, KC_L, LT(APP,KC_SCLN), ALL_T(KC_QUOT),
+ S(KC_TAB), KC_N, KC_M, KC_COMM, KC_DOT, LT(APP,KC_SLSH), KC_RSFT,
+ KC_RGUI, KC_UP, KC_DOWN, KC_FN3, KC_FN1,
+ LALT(KC_LGUI), S(KC_LGUI),
+ LT(APP,KC_PGUP),
+ LT(SYMB,KC_PGDN), KC_ENT, KC_SPC
+ ),
+/* Keymap 1: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | Tab | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | ! | @ | { | } | | | < | | > | : | 7 | 8 | 9 | / | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | # | $ | ( | ) | ` |------| |------| ; | 4 | 5 | 6 | * | |
+ * |--------+------+------+------+------+------| F14 | | F15 |------+------+------+------+------+--------|
+ * | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | - | Entr |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | 0 | . | = | + | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[SYMB] = KEYMAP(
+ // left hand
+ KC_TRNS,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS,KC_EXLM,KC_AT, KC_LCBR,KC_RCBR,KC_PIPE,S(KC_COMM),
+ KC_TRNS,KC_HASH,KC_DLR, KC_LPRN,KC_RPRN,KC_GRV,
+ KC_TRNS,KC_PERC,KC_CIRC,KC_LBRC,KC_RBRC,KC_TILD,KC_F14,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TAB, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ S(KC_DOT), KC_COLN, KC_7, KC_8, KC_9, KC_BSLS, KC_F12,
+ KC_SCLN, KC_4, KC_5, KC_6, KC_ASTR, KC_TRNS,
+ KC_F15, KC_AMPR, KC_1, KC_2, KC_3, KC_MINS, KC_ENT,
+ KC_0, KC_DOT, KC_EQL, KC_PLUS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/* Keymap 2: App Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | CmdQ | CmdW | | | | Stab | | Play | Prev | Next | | |PrtSc | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | |------| |------| VolDn|VolUp | | | | |
+ * |--------+------+------+------+------+------| | | Mute |------+------+------+------+------+--------|
+ * | | CmdZ | CmdX | CmdC | CmdY | CtrlC| | | | | | | | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | | | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// Control
+[APP] = KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, LGUI(KC_Q), LGUI(KC_W), KC_TRNS, KC_TRNS, KC_TRNS, S(KC_TAB),
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, LGUI(KC_Z), LGUI(KC_X), LGUI(KC_C), LGUI(KC_V), LCTL(KC_C), KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_MPLY, KC_MPRV, KC_MNXT, KC_TRNS, KC_TRNS, KC_PSCR, KC_TRNS,
+ KC_VOLD, KC_VOLU, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_MUTE, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/* Keymap 3: Control Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | Pwr | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | MsUp | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | |MsLeft|MsDown|MsRght| Lclk |------| |------| Lft | Down | Up | Right| | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | Rclk | | | | | | | | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | | | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | Shift| | | Home | End |
+ * ,------|------|------| |------+------+------.
+ * | | | LAtl | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// Control
+[CNTL] = KEYMAP(
+ KC_PWR, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_BTN1,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN2, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_LSFT, KC_TRNS,
+ KC_LALT,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_LEFT, KC_DOWN, KC_UP, KC_RIGHT, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_HOME, KC_END,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(SYMB),
+ [2] = ACTION_LAYER_TAP_TOGGLE(APP),
+ [3] = ACTION_LAYER_TAP_TOGGLE(CNTL) // FN1 - Momentary Layer 1 (Symbols)
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case 1:
+ ergodox_right_led_1_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ case 3:
+ ergodox_right_led_3_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/techtomas/readme.md b/keyboards/ergodox_ez/keymaps/techtomas/readme.md
new file mode 100644
index 000000000..36e0591a8
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/techtomas/readme.md
@@ -0,0 +1,57 @@
+# Techtomas Configuration
+
+## Base Layer
+
+The base layer is a merge of what I liked with the default layout and the ordinary layout. The thumb cluster is more like the Kinesis advantage and the top row of the cluster is convient for use on the mac.
+
+* The Caps Lock postion handles [Hyper/Esc](http://brettterpstra.com/2012/12/08/a-useful-caps-lock-key/)
+* The Tab key toggles MEH.
+* The top vertical mods on the left and right are [ and ].
+* The bottom vertical mods on the left and right are tab and shift+tab
+* The HYPER and MEH key are made in the same location on the right side of the board as well. Using Keyboard Maestro for OS X makes one-handed shortcuts very easy.
+* Layer switching is focused around the thumb clusters plus some additional locations for convience.
+
+## Symbol Layer
+The symbol layer can be tap/toggled with the bottom right key and also toggled on the thumb clusters.
+
+The bottom two vertical mods are set to F14 and F15 which is the default for changing screen brightness on the mac
+
+## App Layer
+The app layer is used to control media playback and also some application shortcuts (OS X Focused).
+It can be toggled on the left board in the top left corner (tilde/grave) or using your pinky on the right side of the board using either ; or /.
+There is one additional toggle on the right thumb cluster for quick access to play and mute key combos.
+
+### Current App shortcuts defined
+* Q = CMD+Q
+* W = CMD+W
+* Z = CMD+Z
+* X = CMD+X
+* C = CMD+C
+* V = CMD+V
+* B = CTRL+C
+* P = Print Screen
+
+## Control Layer
+The control layer is meant to help easily navigate and select text. It can also be stacked ontop of the Symbol layer when needed.
+
+The right arrow key and End key toggle the control layer on the left board. There is also a tap toggle for the layer in the same position on the right side of the board.
+
+On the left board you have mouse control with left & right click in the location of the G and B keys.
+On the right board you have vim-style arrow keys using hjkl
+
+The left thumb cluster moves shift and alt within easy reach while holding the toggle (end). So far I've found this convient to navigate and skip around text when using the hjkl arrow keys. I found that it was easy to get the alt key stuck on depending on what key you released first so I added the PREVENT_STUCK_MODIFIERS to the config.h to help with that.
+
+## Changelog
+
+* May 4th, 2016 (v1.2):
+ * Moved layer toggles around to match my habbits of typing
+ * Enabled Prevent Stuck Modifers in my config.h (L3 + Alt on cluster would get stuck)
+ * Changed media layer to be more like an app layer with some quick shortcuts (mac centric)
+ * Moved around the base layer arrow keys so mod keys were more accesible
+
+* Apr 29, 2016 (V1.1):
+ * Added F14 and F15 to symbol layer
+ * Added control layer toggle to A key.
+
+* Apr 28, 2016 (V1.0):
+ * Modified config based on the default layout plus inspiration from the ordinary layout
diff --git a/keyboards/ergodox_ez/keymaps/tkuichooseyou/README.md b/keyboards/ergodox_ez/keymaps/tkuichooseyou/README.md
new file mode 100644
index 000000000..ab02fac2c
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/tkuichooseyou/README.md
@@ -0,0 +1,13 @@
+# Based on Default OSX
+I'm a vim and OSX user
+
+- Moved Hyper and Meh up, replaced with CMD
+ - Because I'm used to having symmetrical CMD keys on both hands
+- Changed left delete to Tab to match OSX
+- Changed left Backspace to CTRL/ESC for vim
+- Changed top left and top right arrow to `CMD+{` and `CMD+}`
+ - Useful for switching tabs in Safari, Xcode, etc.
+- Remove the Ctrl from Z and /
+- Remove CMD from right quote
+- Changed right Alt to Delete
+
diff --git a/keyboards/ergodox_ez/keymaps/tkuichooseyou/compiled.hex b/keyboards/ergodox_ez/keymaps/tkuichooseyou/compiled.hex
new file mode 100644
index 000000000..a8cf4527a
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/tkuichooseyou/compiled.hex
@@ -0,0 +1,1137 @@
+:100000000C947B020C94C2020C94C2020C94C202A7
+:100010000C94C2020C94C2020C94C2020C94C20250
+:100020000C94C2020C94C2020C94F70D0C94C90EED
+:100030000C94C2020C94C2020C94C2020C94C20230
+:100040000C94C2020C9486210C94C2020C94C2023D
+:100050000C94C2020C94681C0C94C2020C94C20250
+:100060000C94C2020C94C2020C94C2020C94C20200
+:100070000C94C2020C94C2020C94C2020C94C202F0
+:100080000C94C2020C94C2020C94C2020C94C202E0
+:100090000C94C2020C94C2020C94C2020C94C202D0
+:1000A0000C94C2020C94C2020C94C202360F580F78
+:1000B0004610580F46109D0FC00F461015102810FF
+:1000C000F712F712261326135C137C13AD14AD142C
+:1000D0008713AD14371437149E14AD14AD14A71440
+:1000E0004414441444144414441444144414441450
+:1000F0004414441444144414441444144414441440
+:10010000561463146A1471147B140000F0A12E00BD
+:100110002B002961E100354100001E00140004009D
+:100120001D0034004D001F001A0016001B00E104E2
+:100130002A00200008000700060050002C002100C3
+:100140001500090019004F004A00220017000A009C
+:100150000500000065642F0A006F0000E300000046
+:10016000E300300A00670000E30000004C002300B9
+:100170001C000B00110000002961240018000D0074
+:10018000100052004B0025000C000E0036005100FC
+:100190002800260012000F0037002F002B00270038
+:1001A00013003342380030004E002D00310034007F
+:1001B000E500C10000000100010001000100010094
+:1001C00000003A001E0220022202010001003B0052
+:1001D0001F0221022302010001003C002F0226021F
+:1001E0002F00010001003D00300227023000010015
+:1001F00001003E003102350035020000010001001F
+:1002000001000000010000000100010001000000E9
+:100210000100000001003F005200510024020000D4
+:1002200001004000240021001E00010001004100E7
+:10023000250022001F003700010042002600230095
+:10024000200027000100430025022E0231002E006D
+:100250000100440045000100010001000000010010
+:100260000100010001000100000001000100010087
+:1002700001000100010001000100F2000100010085
+:1002800001000100F000F1000100F4000100010094
+:100290000100F3000100F500010001000100010070
+:1002A0000100000001000100010000000100000049
+:1002B0000100010001000000010000000100010038
+:1002C0000100010001000000010001000100010027
+:1002D0000100A9000100010001000100AC00AA001A
+:1002E000B600010001000100AB00A8000100010000
+:1002F0000100010001000100010001000100AE0049
+:1003000001000100000016034500720067006F0045
+:1003100044006F007800200045005A0000001603DA
+:100320004500720067006F0044006F0078002000F5
+:1003300045005A0000000403090409026D0004018D
+:1003400000A0FA09040000010301010009211101C4
+:1003500000012240000705810308000A090401008A
+:100360000103010200092111010001224D000705CE
+:10037000820308000A0904020001030000000921A9
+:10038000110100012236000705830308000A090451
+:1003900003000103000000092111010001223900BE
+:1003A000070584031000011201100100000008ED90
+:1003B000FE071301000102000105010906A1010564
+:1003C0000719E029E7150025019508750181020547
+:1003D000081901290595057501910295017503918B
+:1003E0000105071900297715002501957875018108
+:1003F00002C005010980A101850216010026B7008F
+:100400001A01002AB700751095018100C0050C097A
+:1004100001A1018503160100269C021A01002A9CF5
+:1004200002751095018100C005010902A1010901B1
+:10043000A10005091901290515002501950575017A
+:10044000810295017503810105010930093115818A
+:10045000257F95027508810609381581257F95014C
+:1004600075088106050C0A38021581257F950175EE
+:10047000088106C0C005010906A101050719E02988
+:10048000E715002501950875018102950175088120
+:100490000105081901290595057501910295017558
+:1004A0000391010507190029FF150026FF00950695
+:1004B00075088100C000000000000000000000007E
+:1004C000010204060A0F17202C3A4A5D71879DB37A
+:1004D000C7DAE9F5FCFFFCF5E9DAC7B39D87715D82
+:1004E0004A3A2C20170F0A060402010000000000FF
+:1004F00000000000000011241FBECFEFDAE0DEBFD5
+:10050000CDBF04B603FE27C0809101029091020284
+:10051000A0910302B09104028730904BA740B04BEA
+:10052000D1F4109201021092020210920302109272
+:10053000040214BE84B7877F84BF0FB6F894A895D1
+:1005400080916000886180936000109260000FBE0F
+:10055000E0E0FFE3099511E0A0E0B1E0E6EBF6E4AE
+:1005600002C005900D92A433B107D9F712E0A4E3BD
+:10057000B1E001C01D92A130B107E1F70E943C0B30
+:100580000C9459230C9400001092B9008AE08093D7
+:10059000B800089594EA9093BC009091BC0097FF36
+:1005A000FCCF9091B900987F983021F0903111F0F4
+:1005B00081E008958093BB0084E88093BC00809123
+:1005C000BC0087FFFCCF8091B900887F883111F093
+:1005D000803471F780E0089584E98093BC008091B5
+:1005E000BC0084FDFCCF08958093BB0084E8809319
+:1005F000BC008091BC0087FFFCCF9091B900987F30
+:1006000081E0983209F480E0089584E88093BC008A
+:100610008091BC0087FFFCCF8091BB00089580B320
+:100620008C7080BB81B3836F81BB08958091010181
+:10063000811115C080E40E94CA02809301018111DA
+:100640000CC082E10E94F40280930101811105C077
+:100650008FEF0E94F402809301010E94EC0284B1AA
+:10066000807F84B985B1807F85B98AB1837F8AB95B
+:100670008BB1837F8BB93E98469808950E94E00421
+:10068000809301010E9416030E940F03A5E3B1E0CD
+:10069000E3E4F1E08EE08E0F11921D928E13FCCFF9
+:1006A0000C94CA040E94E004809301010E94160386
+:1006B0000E940F03A5E3B1E0E3E4F1E08EE08E0FCA
+:1006C00011921D928E13FCCF0895BF92CF92DF92AC
+:1006D000EF92FF920F931F93CF93DF9380910101CD
+:1006E000882379F0809134018F5F809334018111E8
+:1006F00008C00E94E00480930101811102C00E94A1
+:10070000720405E311E0C0E0D0E0DD24D39482E080
+:10071000C82EEE24E394F12CC730D10500F580916A
+:100720000101811164C080E40E94CA02809301012A
+:10073000811112C082E10E94F402809301018111B3
+:100740000BC0C7010C2E01C0880F0A94EAF78095F0
+:100750000E94F402809301010E94EC0248C0CA305A
+:10076000A1F028F4C83059F0C93061F005C0CC3090
+:1007700089F070F0CD3089F0209A289810C0219A25
+:1007800029980DC0229A2A980AC0239A2B9807C04C
+:10079000529A01C0539A5B9802C03E9A469890EADA
+:1007A0009A95F1F79FB1799902C082E001C080E08B
+:1007B00091709D25982B7C9902C084E001C080E057
+:1007C000892B7D9902C038E001C030E0832B7E99EF
+:1007D00002C020E101C020E0822B9FB19095991FBB
+:1007E0009927991F9295990F907E892B0FC0809120
+:1007F0000101811149C080E40E94CA028093010175
+:10080000882379F1B12C0E94EC028B2DF8019081A4
+:10081000981719F08083C09200010E941603219658
+:100820000F5F1F4FCE30D10509F076CF80910001C8
+:10083000882361F1815080930001882339F08FE98A
+:100840009FE00197F1F700C0000020C0A3E4B1E0F1
+:10085000E5E3F1E0CF01825F91919D938E13FCCF90
+:1008600015C083E10E94F402809301018111CACF77
+:1008700081E40E94CA02809301018111C3CF0E94CA
+:100880000503B82EB094BFCF80E0C0CF0E947004A3
+:1008900081E0DF91CF911F910F91FF90EF90DF905A
+:1008A000CF90BF900895E82FF0E0ED5BFE4F808180
+:1008B000089508950F931F93CF93DF93C3E4D1E07E
+:1008C00010E00C2F025F899190E00E948C1B180FA2
+:1008D0000C13F9CF812FDF91CF911F910F910895C4
+:1008E0000C94400556985E9825982D9826982E9839
+:1008F00027982F988FEF90E090938900809388003D
+:1009000090938B0080938A0090938D0080938C004D
+:10091000259A2D9A2FEF80E792E021508040904059
+:10092000E1F700C00000269A2E9A2FEF80E792E0B0
+:10093000215080409040E1F700C00000279A2F9A94
+:100940002FEF80E792E0215080409040E1F700C017
+:10095000000025982D982FEF80E792E021508040ED
+:100960009040E1F700C0000026982E982FEF80E716
+:1009700092E0215080409040E1F700C000002798AD
+:100980002F9856985E9825982D9826982E982798F7
+:100990002F98089589EA8093800089E080938100F0
+:1009A00024982C983F988AB18F748AB96E98479A88
+:1009B0008BB1806B8BB9769A0E9472040C943F05C0
+:1009C00080E2809301018091510181110EC00E944B
+:1009D000C40281E0809351012FEF83ED90E3215019
+:1009E00080409040E1F700C0000080E40E94CA020D
+:1009F0008093010181112EC00E94F40280930101B5
+:100A0000811128C00E94F40280930101811122C04B
+:100A10008FE30E94F4028093010181111BC00E94A8
+:100A2000EC0280E40E94CA0280930101811112C08D
+:100A30008CE00E94F4028093010181110BC00E949E
+:100A4000F40280930101811105C08FE30E94F4023A
+:100A5000809301010E94EC028091010108956111CF
+:100A60000BC0FC018281882321F085EE0E949B113E
+:100A700003C085EE0E94631280E090E0089508951F
+:100A80006091C2017091C3018091C4019091C50130
+:100A90000E94981B56985E9825982D9826982E9817
+:100AA00027982F98813019F0823021F00895259AE7
+:100AB0002D9A0895269A2E9A089581E0089581E04E
+:100AC00008950C945F050895282F882339F090E04D
+:100AD0002A3010F44D9608950697089587E290E025
+:100AE0000895AF92BF92DF92EF92FF920F931F9300
+:100AF000CF93DF938C01FC01C081D181CE010E9494
+:100B0000111ABE010E94E908EC01B8010E946105BA
+:100B1000882309F4D1C1F8018281882309F4C6C071
+:100B200080916201811127C0C431F0E7DF0709F02D
+:100B3000BDC10E94630581E0809362010E94321C66
+:100B400090936101809360011092550110925701BA
+:100B500010925601109259011092580110925B01A7
+:100B600010925A0110925D0110925C0110925F0187
+:100B700010925E01A1C180916001909161010E947B
+:100B80003E1C883C910570F480915501E82FF0E0FF
+:100B9000EE0FFF1FEA5AFE4FD183C0838F5F809311
+:100BA00055018AC1C13020E8D20708F451C0F801CC
+:100BB0008281882309F47EC05E01E894B7F88091B1
+:100BC0005401813079F050F08230C1F482EE0E94FD
+:100BD0009B1187E50E949B1187E50EC082EE0E9463
+:100BE0009B110CC080EE0E949B1181EE0E949B1114
+:100BF00088E10E949B1188E10E9463128CE0E82E3C
+:100C0000F12CC5010E2C02C0969587950A94E2F747
+:100C10008F700E946405D82E0E949B118D2D0E941A
+:100C20006312F4E0EF1AF1082CEFE2162FEFF20650
+:100C300041F780915401813029F010F0823041F465
+:100C400082EE04C080EE0E94631281EE0E94631265
+:100C5000C43180E7D80768F4C23090E7D90708F0BC
+:100C600046C0C115E0E7DE0771F0C130D047A1F101
+:100C70000CC1C33320E7D20709F4D8C0C433D0472E
+:100C800009F4EBC002C1F8018281882309F402C192
+:100C90000E941815FFEF24E38CE0F15020408040C3
+:100CA000E1F700C000000E948D1C06C1C13080E841
+:100CB000D80770F2C43120E7D20708F0B3C0C230C1
+:100CC00080E7D807A0F4C11590E7D90709F4E2C07E
+:100CD000C130D04709F0D9C0F8018281882309F4D6
+:100CE000D9C08091DF0181608093DF01E5C0F80108
+:100CF0008281882309F4CEC00E94E71C811102C0C2
+:100D00000E94CD1C0E94FA1C90E09093F301809306
+:100D1000F201C230F0E7DF0721F48091F201816037
+:100D20007AC0C33020E7D20721F48091F2018260BB
+:100D300072C0C43080E7D80721F48091F20184604A
+:100D40006AC0C53090E7D90719F48091F20127C035
+:100D5000C630E0E7DE0721F48091F20180615BC0DC
+:100D6000C730F0E7DF0721F48091F201806253C0C1
+:100D7000C83020E7D20721F48091F20180644BC093
+:100D8000C93080E7D80721F48091F201806843C020
+:100D9000CA3090E7D90729F48091F2018460886015
+:100DA0003AC0CB30E0E7DE0721F48091F2018E7F7C
+:100DB00032C0CC30F0E7DF0721F48091F2018D7F63
+:100DC0002AC0CD3020E7D20721F48091F2018B7F39
+:100DD00022C0CE3080E7D80719F48091F2011AC002
+:100DE0008091F201CF3090E7D90711F48F7E13C0C4
+:100DF000C031E0E7DE0711F48F7D0DC0C131F0E7AF
+:100E0000DF0711F48F7B07C0C231D04711F48F7711
+:100E100002C08B7F877F8093F2018091F2010E9454
+:100E2000FE1C4AC0C333F0E7DF07A1F4F80182815A
+:100E3000882321F01092520182E016C08091520165
+:100E4000811106C086E20E949B1186E20E94631215
+:100E500082E018C0C433D047C1F4F80182818823EE
+:100E600031F01092530180E20E94B21225C08091AD
+:100E70005301811106C087E20E949B1187E20E9404
+:100E8000631280E20E94B91217C081E08093520180
+:100E900080935301C801DF91CF911F910F91FF9073
+:100EA000EF90DF90BF90AF900C945D05C130F0E8FB
+:100EB000DF0708F081CECCCE80E0DF91CF911F918B
+:100EC0000F91FF90EF90DF90BF90AF90089526E0D4
+:100ED000729FF001112444E5849FE00DF11D11245F
+:100EE000E60FF11DEE0FFF1FE25FFE4F859194911B
+:100EF0000E94FB08811560E49607B0F5811570E348
+:100F0000970708F0DEC0803E9105D8F4803C91053B
+:100F100008F06CC0883A910578F4853A910508F09C
+:100F20006BC08130910509F452C108F40FC18430BF
+:100F3000910508F04CC10AC18B3B910508F467C0CC
+:100F400005C18F3F910509F048F4803F910508F0F5
+:100F5000ADC0883E910508F43AC1F8C0811520E281
+:100F6000920708F0A5C00895811543E5940790F411
+:100F7000811562E5960708F0C8C0811571E59707ED
+:100F800008F0BEC0811520E5920708F09DC09F7053
+:100F9000906A0895811545E59407D8F4811564E5B4
+:100FA000960708F0C8C0482F4695469570E2479FBF
+:100FB000A00111248370992721E030E0B90102C01B
+:100FC000660F771F8A95E2F7CB01842B952B9A68E1
+:100FD0000895811576E5970708F4B2C09C01305654
+:100FE0002115304108F0B2C09F70AEC0FC01EE0F79
+:100FF000FF1FE657F04062C0853A910509F4A9C089
+:10100000863A910509F0A8C082E890E40895883AEC
+:10101000910509F4A4C0893A910509F4A3C08A3A5C
+:10102000910509F4A2C08B3A910509F4A1C08C3A4C
+:10103000910509F4A0C08D3A910509F49FC0803B49
+:10104000910509F49EC08E3A910509F49DC08F3A2E
+:10105000910509F49CC0813B910509F49BC0823B3A
+:10106000910509F49AC0833B910509F499C0843B2A
+:10107000910509F498C0853B910509F497C0863B1A
+:10108000910509F496C0873B910509F495C0883B0A
+:10109000910509F494C0893B910509F493C08A3BFA
+:1010A000910509F492C080E094E408959065089554
+:1010B000FC01FF70EE0FFF1FE65FFE4F85919491DC
+:1010C00008959927906C0895482F437021E030E0EF
+:1010D00002C0220F331F4A95E2F73C68AC0164E07E
+:1010E000569547956A95E1F74370342B8F70869536
+:1010F000869560E2869FC0011124822B932B089570
+:10110000982F8827816F906A0895482F46954695B5
+:1011100070E2479FA00111248370992721E030E0FD
+:10112000B90102C0660F771F8A95E2F7CB01842BC5
+:10113000952B9C680895982F8827846F906A08954E
+:101140008F719927982F88279062089580E090E00A
+:10115000089581E890E4089583E890E4089582EE8C
+:1011600094E4089589EE94E408958AEE94E4089551
+:1011700085EB94E4089586EB94E4089587EB94E47A
+:1011800008958CEC94E408958DEC94E4089583E83C
+:1011900095E408958AE895E4089582E995E4089530
+:1011A00084E995E4089581E296E4089583E296E463
+:1011B000089584E296E4089585E296E4089586E22F
+:1011C00096E4089587E296E408958AE296E4089505
+:1011D000089596E0799FF001112494E5899FE00D30
+:1011E000F11D1124E60FF11DEE0FFF1FE25FFE4F10
+:1011F0008591949108958238910549F1B0F4813335
+:10120000910509F458C048F48932910509F44EC09B
+:101210008A32910509F454C008958533910509F483
+:1012200040C08933910599F00895833E910529F1D5
+:1012300038F4803E910591F0823E9105A1F0089529
+:10124000863E9105F9F0873E910531F10895209190
+:10125000F20120FD3AC021FD38C008958091F201CD
+:1012600080FD35C032C08091F20182FF32C0809192
+:10127000F20184FD30C083EE39C08091F20182FD1D
+:1012800028C0F5CF8091F20183FF27C08091F20141
+:1012900084FD21C087EE2AC08091F20183FD1DC02C
+:1012A000F5CF8091F20185FD1AC01BC08091F2013B
+:1012B00085FD17C014C08091F20186FD14C015C0D1
+:1012C0008091F20186FD11C00EC080EE0FC089E34F
+:1012D0000DC082EE0BC080E009C086EE07C089E237
+:1012E00005C085E303C08AE201C081E390E0089570
+:1012F00008950C947809809173010895CF93DF933A
+:1013000000D01F92CDB7DEB79C018091F8018430E8
+:1013100019F593E099833B832A839093E9008FEF3B
+:101320009091E800815095FD06C095ED9A95F1F7F2
+:1013300000008111F5CF8091E80085FF0DC040E0ED
+:1013400050E063E070E0CE0101960E94E70B8091CF
+:10135000E8008E778093E8000F900F900F90DF9158
+:10136000CF910895CF93DF9300D01F92CDB7DEB712
+:101370002091F801243021F522E029839B838A8380
+:1013800083E08093E9008FEF9091E800815095FD14
+:1013900006C095ED9A95F1F700008111F5CF809187
+:1013A000E80085FF0DC040E050E063E070E0CE0152
+:1013B00001960E94E70B8091E8008E778093E80009
+:1013C0000F900F900F90DF91CF9108952091F80129
+:1013D0002430F1F422E02093E9002FEF3091E8006F
+:1013E000215035FD06C035ED3A95F1F70000211189
+:1013F000F5CF2091E80025FF0BC040E050E065E00C
+:1014000070E00E94E70B8091E8008E778093E800FF
+:101410000895CF93DF93EC019091F801943009F097
+:1014200046C080910C018823D9F080910D0188235A
+:10143000B9F09093E9008FEF9091E800815095FD0D
+:1014400006C095E19A95F1F700008111F5CF8091E2
+:10145000E80085FF2CC040E050E060E170E017C07C
+:1014600081E08093E9008FEF9091E800815095FD35
+:1014700006C095ED9A95F1F700008111F5CF8091A6
+:10148000E80085FF14C040E050E068E070E0CE0165
+:101490000E94E70B8091E8008E778093E80080E15E
+:1014A000FE01A3E6B1E001900D928A95E1F7DF918C
+:1014B000CF9108958091F701811109C00E947C0DA0
+:1014C0000E94D90D8091E20084608093E20008952B
+:1014D0001092F701089508950C9473210E94231C23
+:1014E0000E9479210E947F100C94790942E061ECFE
+:1014F00081E00E94F60C42E061EC82E00E94F60C72
+:1015000042E061EC83E00E94F60C42E161EC84E091
+:101510000C94F60C8091FA01833009F455C030F434
+:10152000813071F0823009F48EC008958A3009F458
+:101530007AC08B3009F460C0893009F09CC020C0AB
+:101540008091F901813A09F096C08091E800877F87
+:101550008093E8008091FD019091FE01892B21F498
+:1015600060E183E691E003C060E080E090E070E03D
+:101570000E94320C8091E8008B778093E8000895F8
+:101580008091F901813209F076C08091FD0190913E
+:10159000FE01009719F0039709F06DC08091E800F3
+:1015A000877F8093E8008091E80082FD05C08091EC
+:1015B000F8018111F8CF5FC08091F1008093730131
+:1015C0008091E8008B7753C08091F901813A09F04E
+:1015D00052C08091FD019091FE01892B09F04BC012
+:1015E0008091E800877F8093E8008091E80080FF89
+:1015F000FCCF80910C0136C08091F9018132D9F580
+:101600008091FD019091FE01892BA9F58091E80060
+:10161000877F8093E8000E942B0D8091FB018093CF
+:101620000C010C9418158091F901813221F58091FB
+:10163000E800877F8093E8000E942B0D8091FC01D9
+:101640008093740108958091F901813AA1F4809109
+:10165000E800877F8093E8008091E80080FFFCCF5E
+:10166000809174018093F1008091E8008E778093DF
+:10167000E8000C942B0D089584B7877F84BF0FB6C4
+:10168000F894A89580916000886180936000109222
+:1016900060000FBE80E880936100109261000E949C
+:1016A000CE100E947C0D0E94D90D8091E2008460D2
+:1016B0008093E20078940E945F100E94D01082E034
+:1016C00091E00E947A100E9461218091F80185309A
+:1016D00069F40E94E81B8091F6018823B1F30E940F
+:1016E000151C882391F30E94D10BEFCF0E94D610D6
+:1016F000ECCF292F332723303105C9F064F4213092
+:10170000310581F02230310509F043C08DE690E0CB
+:101710002AE333E042C021323105F1F022323105B3
+:1017200041F137C082E190E027EA33E036C09927E3
+:101730008130910541F08230910541F0892B49F5C6
+:10174000E6E3F3E005C0EEE1F3E002C0E6E0F3E03B
+:10175000849190E09F0121C06430D8F4E62FF0E03E
+:10176000EE0FFF1FEE5DFE4F2081318189E090E09A
+:1017700014C0643070F470E0FB01EE0FFF1FE65EF2
+:10178000FE4F20813181FB01EA5EFE4F808190E0B7
+:1017900004C080E090E020E030E0FA013183208353
+:1017A000089580E189BD82E189BD09B400FEFDCFC5
+:1017B0008091D8008F7D8093D8008091E000826076
+:1017C0008093E0008091E00081FDFCCF0895CF92EE
+:1017D000DF92EF92FF920F931F93CF93DF93EC0171
+:1017E0008B016A010E944A0D811133C0C114D104DA
+:1017F00039F0F60180819181081B190BC80FD91FA0
+:10180000E12CF12C0115110519F18091E80085FDFD
+:1018100016C08091E8008E778093E800C114D1044F
+:1018200049F0F60180819181E80EF91EF182E08293
+:1018300085E00FC00E944A0D882321F30AC08991D8
+:101840008093F10001501109FFEFEF1AFF0ADACF80
+:1018500080E0DF91CF911F910F91FF90EF90DF908B
+:10186000CF9008952091FF0130910002261737078D
+:1018700048F06115710539F42091E8002E77209326
+:10188000E80001C0B90140E061157105A9F120919E
+:10189000F801222309F443C0253009F442C0209105
+:1018A000E80023FD40C02091E80022FD32C02091D5
+:1018B000E80020FFE9CF4091F3002091F20030E0F2
+:1018C000342BFC01CF016115710559F02830310529
+:1018D00040F481918093F100615071092F5F3F4F77
+:1018E000F1CF41E02830310509F040E02091E800D7
+:1018F0002E772093E800C8CF4111C9CF0AC080914C
+:10190000F801882361F0853061F08091E80083FD63
+:101910000AC08091E80082FFF2CF80E0089582E063
+:10192000089583E0089581E008952091FF013091AA
+:1019300000022617370748F06115710539F4209128
+:10194000E8002E772093E80001C0B901FC0120E0F7
+:101950006115710591F18091F801882309F440C067
+:10196000853009F43FC08091E80083FD3DC080913F
+:10197000E80082FD2FC08091E80080FFE9CF209130
+:10198000F3008091F20090E0922B6115710559F0FF
+:101990008830910540F424912093F10031966150F4
+:1019A00071090196F2CF21E0089709F020E08091BB
+:1019B000E8008E778093E800CBCF2111CCCF0AC00E
+:1019C0008091F801882361F0853061F08091E80012
+:1019D00083FD0AC08091E80082FFF2CF80E0089585
+:1019E00082E0089583E0089581E00895982F97306C
+:1019F00058F59093E900981739F07091EC00209118
+:101A0000ED005091F00003C0242F762F50E021FF0D
+:101A100019C03091EB003E7F3093EB003091ED0028
+:101A20003D7F3093ED003091EB0031603093EB005F
+:101A30007093EC002093ED005093F0002091EE00A5
+:101A400027FF07C09F5FD3CF8F708093E90081E0AD
+:101A5000089580E008958091F90187FF11C0809179
+:101A6000E80082FD05C08091F8018111F8CF11C016
+:101A70008091E8008B770BC08091F801882349F0B2
+:101A80008091E80080FFF8CF8091E8008E77809306
+:101A9000E80008952091E4003091E50095E640913A
+:101AA000EC00842F817040FF22C08091E80080FD0F
+:101AB0001CC08091F801882391F0853091F08091CD
+:101AC000EB0085FD10C04091E4005091E500421705
+:101AD000530729F39A01915011F784E0089582E0A9
+:101AE000089583E0089581E0089580E0089540918D
+:101AF000E80042FFDECF08950E94EA0D0E94F20D39
+:101B0000E0EEF0E0808181608083E8EDF0E08081AC
+:101B10008F77808319BCA7EDB0E08C918E7F8C937A
+:101B200080818F7E80831092F70108950F931F9319
+:101B3000CF93DF930E94EA0D0E94F20DC8EDD0E032
+:101B400088818F77888388818068888388818F7D6A
+:101B5000888319BC1092F8011092F4011092F601DA
+:101B60001092F50100EE10E0F80180818B7F8083F8
+:101B700088818160888342E060E080E00E94F60C0A
+:101B8000E1EEF0E080818E7F8083E2EEF0E0808104
+:101B900081608083808188608083F80180818E7F6E
+:101BA0008083888180618883DF91CF911F910F911D
+:101BB0000895E8EDF0E080818F7E8083E7EDF0E02E
+:101BC00080818160808384E082BF81E08093F7011F
+:101BD0000C94960DE8EDF0E080818E7F808310926A
+:101BE000E20008951092DA001092E10008951F9229
+:101BF0000F920FB60F9211242F933F934F935F9341
+:101C00006F937F938F939F93AF93BF93EF93FF93C4
+:101C10008091E10082FF0BC08091E20082FF07C04B
+:101C20008091E1008B7F8093E1000E945E108091A3
+:101C3000DA0080FF1FC08091D80080FF1BC0809118
+:101C4000DA008E7F8093DA008091D90080FF0DC08A
+:101C500080E189BD82E189BD09B400FEFDCF81E04C
+:101C60008093F8010E945A0A05C019BC1092F8012D
+:101C70000E94680A8091E10080FF19C08091E20013
+:101C800080FF15C08091E2008E7F8093E2008091FA
+:101C9000E20080618093E2008091D80080628093AE
+:101CA000D80019BC85E08093F8010E946C0A8091ED
+:101CB000E10084FF30C08091E20084FF2CC080E10D
+:101CC00089BD82E189BD09B400FEFDCF8091D800B5
+:101CD0008F7D8093D8008091E1008F7E8093E1001A
+:101CE0008091E2008F7E8093E2008091E20081602B
+:101CF0008093E2008091F401882311F084E007C012
+:101D00008091E30087FD02C081E001C083E0809301
+:101D1000F8010E946E0A8091E10083FF29C0809142
+:101D2000E20083FF25C08091E100877F8093E1007E
+:101D300082E08093F8011092F4018091E1008E7F9F
+:101D40008093E1008091E2008E7F8093E200809199
+:101D5000E20080618093E20042E060E080E00E9467
+:101D6000F60C8091F00088608093F0000E946B0A6E
+:101D7000FF91EF91BF91AF919F918F917F916F9163
+:101D80005F914F913F912F910F900FBE0F901F9039
+:101D900018951F920F920FB60F9211242F933F9315
+:101DA0004F935F936F937F938F939F93AF93BF9363
+:101DB000CF93DF93EF93FF93C091E900CF708091B1
+:101DC000EC00D82FD17080FDD0E81092E90080910E
+:101DD000F000877F8093F00078940E940D0F10929E
+:101DE000E9008091F00088608093F000CD2BCF70E7
+:101DF000C093E900FF91EF91DF91CF91BF91AF9137
+:101E00009F918F917F916F915F914F913F912F9112
+:101E10000F900FBE0F901F9018951F93CF93DF93D5
+:101E2000CDB7DEB7AA970FB6F894DEBF0FBECDBF11
+:101E3000E9EFF1E088E08E0F9091F10091938E131D
+:101E4000FBCF0E948A0A8091E80083FF1FC1809126
+:101E5000F9019091FA01492F50E04A30510508F0FC
+:101E600015C1FA01EA5AFF4F0C940A23803881F019
+:101E7000823809F00BC18091FD018F708093E900D9
+:101E80008091EB0085FB882780F91092E90006C05D
+:101E90008091F5019091F601911182609091E80096
+:101EA000977F9093E8008093F1001092F100C8C0F2
+:101EB000282F2D7F09F0EAC0882319F0823061F0C5
+:101EC000E5C08091FB01813009F0E0C0933009F05A
+:101ED00080E08093F6012BC08091FB01811127C027
+:101EE0008091FD018F7009F4D1C08093E9002091A9
+:101EF000EB0020FF1CC0933021F48091EB00806246
+:101F000014C09091EB0090619093EB0021E030E0E1
+:101F1000A90102C0440F551F8A95E2F74093EA00D9
+:101F20001092EA008091EB0088608093EB001092A1
+:101F3000E9008091E800877F86C08111A7C01091D9
+:101F4000FB011F778091E3008078812B8093E30071
+:101F50008091E800877F8093E8000E942B0D80919C
+:101F6000E80080FFFCCF8091E30080688093E3006D
+:101F7000111102C082E001C083E08093F80186C0A5
+:101F80008058823008F082C08091FB019091FC0162
+:101F90008C3D53E0950779F583E08A838AE2898353
+:101FA0004FB7F894DE01139620E03EE051E2E32FB4
+:101FB000F0E050935700E49120FF03C0E295EF70EA
+:101FC0003F5FEF708E2F90E0EA3010F0C79601C0AF
+:101FD000C0968D939D932F5F243149F74FBF809119
+:101FE000E800877F8093E8006AE270E0CE01019606
+:101FF0000E94320C14C0AE014F5F5F4F6091FD0133
+:102000000E94790BBC01892B09F440C09091E80033
+:10201000977F9093E80089819A810E94950C809126
+:10202000E8008B778093E80031C0803879F58091A3
+:10203000E800877F8093E8008091F4018093F100AD
+:102040008091E8008E778093E8000E942B0D1EC0DF
+:1020500081111CC09091FB019230C0F48091E80086
+:10206000877F8093E8009093F4010E942B0D80916C
+:10207000F401811106C08091E30087FD02C081E078
+:1020800001C084E08093F8010E94760A8091E80004
+:1020900083FF0AC08091E800877F8093E8008091E9
+:1020A000EB0080628093EB00AA960FB6F894DEBF37
+:1020B0000FBECDBFDF91CF911F9108950895CF93AB
+:1020C0008091F8018823A1F0C091E900CF70909130
+:1020D000EC00892F817090FD80E8C82B1092E900F8
+:1020E0008091E80083FD0E940D0FCF70C093E9003E
+:1020F000CF91089590937A01809379010895E091AA
+:102100007901F0917A01309721F00190F081E02D72
+:10211000099480E00895E0917901F0917A01309777
+:1021200021F00280F381E02D09940895E091790176
+:10213000F0917A01309721F00480F581E02D099427
+:10214000089520917701309178018217930771F0FB
+:102150009093780180937701E0917901F0917A0171
+:10216000309721F00680F781E02D099408952091A1
+:102170007501309176018217930771F09093760183
+:1021800080937501E0917901F0917A01309721F007
+:102190000084F185E02D0994089508950C94CD10E4
+:1021A0000E94291C0E943E030C94AF1C9F92AF9288
+:1021B000BF92CF92DF92EF92FF920F931F93CF9334
+:1021C000DF9300D000D000D0CDB7DEB70E9465030A
+:1021D0000DE010E0AA24A394B12C902E802F0E9431
+:1021E0005304980124583E4F6901F901F080F82604
+:1021F000A1F40150110988F78FEF89838A831B822C
+:102200000E94321C8160782F9D838C8349815A8182
+:102210006B818D810E946D112FC09091DF0191FF24
+:1022200004C08E830E9459048E8125E030E0A50110
+:10223000022E01C0440F0A94EAF7E42E4F21C1F0A8
+:1022400029839A828E2191E009F490E09B830E9479
+:10225000321C8160782F9D838C8349815A816B81E8
+:102260008D810E946D11F6018081E826E08204C014
+:1022700021503109E0F6BDCF0E947D1E10917B01F7
+:102280000E947F101817B9F00E947F1080937B0185
+:1022900026960FB6F894DEBF0FBECDBFDF91CF916B
+:1022A0001F910F91FF90EF90DF90CF90BF90AF9074
+:1022B0009F900C94790926960FB6F894DEBF0FBE56
+:1022C000CDBFDF91CF911F910F91FF90EF90DF90E5
+:1022D000CF90BF90AF909F900895CF93DF93CDB7ED
+:1022E000DEB72B970FB6F894DEBF0FBECDBF4F837E
+:1022F000588769877A878B87DE01119686E0FD0112
+:1023000011928A95E9F785E0FE01379601900D92CA
+:102310008A95E1F749815A816B817C818D819E810B
+:102320000E94B6172B960FB6F894DEBF0FBECDBF36
+:10233000DF91CF910895CF93882309F4C2C0C82FAD
+:10234000823859F40E947F1081FDBBC089E30E944E
+:10235000901A0E945D1B89E30CC0833879F40E94B7
+:102360007F1080FDAEC083E50E94901A0E945D1B25
+:1023700083E50E94D21ACF910C945D1B843859F4E6
+:102380000E947F1082FD9DC087E40E94901A0E94E7
+:102390005D1B87E4EECF8CEF8C0F813A48F48C2FD5
+:1023A0000E94C72081118DC08C2F0E94901AE3CF0C
+:1023B00080E28C0F883048F4C77081E001C0880F3C
+:1023C000CA95EAF70E94161BD6CF8BE58C0F833097
+:1023D00078F4C53A29F0C63A31F083E890E005C0B8
+:1023E00081E890E002C082E890E0CF910C94A110C7
+:1023F00088E58C0F833108F064C0C83A39F1C93AD6
+:1024000041F1CA3A49F1CB3A51F1CC3A59F1CD3ABE
+:1024100061F1C03B69F1CE3A71F1CF3A79F1C13B3C
+:1024200081F1C23B89F1C33B91F1C43B99F1C53BBA
+:10243000A1F1C63BA9F1C73BB1F1C83BB9F1C93B1A
+:10244000C1F1CA3BC9F180E090E038C082EE90E073
+:1024500035C089EE90E032C08AEE90E02FC085EB67
+:1024600090E02CC086EB90E029C087EB90E026C07E
+:102470008CEC90E023C08DEC90E020C083E891E0EC
+:102480001DC08AE891E01AC082E991E017C084E992
+:1024900091E014C081E292E011C083E292E00EC0AC
+:1024A00084E292E00BC085E292E008C086E292E00E
+:1024B00005C087E292E002C08AE292E0CF910C94DC
+:1024C000B710CF910895882309F44BC0823859F48E
+:1024D0000E947F1081FF45C089E30E94901A0E94EC
+:1024E0005D1B89E30CC0833871F40E947F1080FF6C
+:1024F00038C083E50E94901A0E945D1B83E50E940C
+:10250000D21A0C945D1B843859F40E947F1082FF0C
+:1025100028C087E40E94901A0E945D1B87E4EFCFD9
+:102520009CEF980F913A58F390E2980F983050F43E
+:10253000877091E001C0990F8A95EAF7892F0E9470
+:102540001C1BDFCF9BE5980F933020F480E090E0D8
+:102550000C94A110885A833120F480E090E00C9410
+:10256000B7100895882321F00E94161B0C945D1B60
+:102570000895882321F00E941C1B0C945D1B089574
+:102580007F928F929F92AF92BF92CF92DF92EF9203
+:10259000FF920F931F93CF93DF931F92CDB7DEB7B8
+:1025A0007C01C62E772EFC01058102950F701281E9
+:1025B00011110E94331B0E94891A882379F011237C
+:1025C00069F080E28C0D883048F082E00E94721A37
+:1025D0000E94891A91E0D82ED92601C0D12CE72D6E
+:1025E000E295EF70F0E0E05AFF4F0C940A23872D3C
+:1025F000807F072D0F70882311F00295007F112333
+:1026000089F0002309F490C180E28C0D883020F419
+:10261000802F0E94161B03C0802F0E94261B0E9441
+:102620005D1B82C18C2D0E946312002309F495C1A9
+:1026300080E28C0D883020F4802F0E941C1B03C088
+:10264000802F0E942C1B0E945D1B87C1972D907FBD
+:10265000872D8F70903211F08295807FCC2021F0F1
+:10266000F1E0CF16B1F01EC0112349F0002309F4A8
+:1026700014C1013009F011C10E94461B6EC1002334
+:1026800019F0013009F469C189830E94491B8981CD
+:102690000AC1112321F0023008F05FC1FEC0011110
+:1026A0005CC101C1112321F0002309F4F6C03CC133
+:1026B000002309F4F8C03EC1872D86958695837066
+:1026C00090E0009719F0019761F047C1112321F0C4
+:1026D0008C2D972D937002C080E090E00E94A11095
+:1026E0003CC1112321F08C2D972D937002C080E006
+:1026F00090E00E94B71031C18C2D112319F00E9477
+:10270000851D02C00E94ED1D0E94721E26C1872DEC
+:10271000837009F052C0111120C18C2D82958695CD
+:102720008770880F880F9C2D9F70892E912CA12C6B
+:10273000B12C082E04C0880C991CAA1CBB1C0A943E
+:10274000D2F7C4FE14C00FE010E020E030E0B90181
+:10275000A80104C0440F551F661F771F8A95D2F742
+:10276000CB01BA01609570958095909503C060E0AB
+:1027700070E0CB01272D26952695237030E022307E
+:10278000310569F02330310589F0682979298A29D2
+:102790009B292130310571F00E94FE18DEC06829A6
+:1027A00079298A299B290E941A19D7C00E94FE18EC
+:1027B000C501B4010E94E218D0C0112319F0872D81
+:1027C000817001C08695882309F4C7C08C2D82953D
+:1027D00086958770880F880F9C2D9F70892E912C6D
+:1027E000A12CB12C082E04C0880C991CAA1CBB1C5F
+:1027F0000A94D2F7C4FE14C00FE010E020E030E0ED
+:10280000B901A80104C0440F551F661F771F8A95A0
+:10281000D2F7CB01BA01609570958095909503C071
+:1028200060E070E0CB01272D269526952370422F7E
+:1028300050E04230510569F04330510589F0682974
+:1028400079298A299B294130510571F00E94D819B4
+:1028500084C0682979298A299B290E94F4197DC09E
+:102860000E94D819C501B4010E94BC1976C08C2DF4
+:1028700090E0FC01E05EF109E531F10508F050C09F
+:10288000E059FF4F0C940A230C2D0F70872D8F7188
+:10289000112331F00E945519802F0E94B2125DC0A1
+:1028A0000E947619802F0E94B91257C0112339F067
+:1028B000011153C0872D8F710E949B194EC00230A9
+:1028C00008F04BC0F7CF112339F0872D8F710E948C
+:1028D000551943C01123C9F3872D8F710E947619B2
+:1028E0003CC0112329F0872D8F710E94401935C0FB
+:1028F0000E94361932C0112351F0172D1F71812FFC
+:102900000E94551963E0812F0E94691A26C081E058
+:102910000E94721A023008F182E00E94721A1DC0F1
+:10292000112331F0002389F28C2D0E949B1115C0D8
+:10293000002391F28C2D0E9463120FC0472D4F701F
+:102940006C2DC7010E942F050E945A1806C0472D02
+:102950004F706C2DC7010E94E808DD20F9F00E943D
+:10296000651A80FD1BC0F70112820E945F1A0E9447
+:102970005519C7010E94DD140E945F1A0F90DF9164
+:10298000CF911F910F91FF90EF90DF90CF90BF906C
+:10299000AF909F908F907F900C9476190F90DF915D
+:1029A000CF911F910F91FF90EF90DF90CF90BF904C
+:1029B000AF909F908F907F9008950F931F93CF9328
+:1029C000DF93EC01888199812B813C81232BB9F025
+:1029D0009F3F11F48F3F99F0CE010E94710588232B
+:1029E00071F0688179818A810E945B1A8C010E9452
+:1029F000101A0E94D718B801CE010E94C012DF91B0
+:102A0000CF911F910F9108950E94331B0E94431B89
+:102A10000E94081B0E945D1B0E94231F0E94721EC1
+:102A200080E090E00E94A11080E090E00C94B7104C
+:102A30000E94231B0C9404150E94501A292F2295E2
+:102A40002F7030E02C3031054CF42A3031056CF415
+:102A50002250310922303105A8F407C02C3031054D
+:102A600069F02F30310551F00DC0803F69F018F446
+:102A7000803E40F409C0843F29F406C093FB8827B8
+:102A800080F9089580E0089581E00895CF93DF9361
+:102A900000D000D01F92CDB7DEB70F900F900F90EF
+:102AA0000F900F90DF91CF910895CF93DF9300D0D7
+:102AB00000D000D0CDB7DEB726960FB6F894DEBFB3
+:102AC0000FBECDBFDF91CF9108951F93CF93DF93BA
+:102AD000C0918A0116E080918B01C81799F0D0E06F
+:102AE0001C9FF0011D9FF00D1124E457FE4F408103
+:102AF000518162817381848195810E94551521964F
+:102B0000C770E9CFDF91CF911F9108954091BC012B
+:102B10005091BD016091BE017091BF018091C001D3
+:102B20009091C1010C9455158091C10182958F70CF
+:102B300009F054C08091BE01882309F44FC08091F0
+:102B40008A01A0918B016091BC017091BD014091FF
+:102B5000BF015091C001B6E08A1709F43FC090E070
+:102B600041155105C1F17F3F11F46F3FA1F1B89FAD
+:102B7000F001B99FF00D1124E457FE4F218172132B
+:102B80002AC02081621327C02281211124C0238101
+:102B900034812417350710F421503109241B350BDB
+:102BA000283C3105C0F42091C1012F702061209391
+:102BB000C10126E0289FF001299FF00D1124EF5656
+:102BC000FE4F80818F70806180838CEB91E00E944A
+:102BD000DD140C94651501968770BECF0895CF92D1
+:102BE000DF92EF92FF920F931F93CF93DF93CDB7B6
+:102BF000DEB762970FB6F894DEBF0FBECDBF8C0173
+:102C000085E0F801DE011D9601900D928A95E1F7AD
+:102C1000D8014C9111965C91119712966C91129774
+:102C20001396CD90DC9014973091BC017091BD014A
+:102C30008091BF019091C001009709F46BC17F3F63
+:102C400019F43F3F09F466C1E090BE01EE2009F49B
+:102C5000C0C02091C101C816D90628F0F601E81BB2
+:102C6000F90BCF0104C0809590958C0D9D1DFF241C
+:102C7000F394883C910578F0F12C207F09F0C6C0D0
+:102C80007C2DD98AC88A89890E9446158CEB91E0EF
+:102C90000E94DD14B1C0822F807F09F046C07513F9
+:102CA00014C0341312C0611110C02F702061209322
+:102CB000C1010E9486158CEB91E00E94DD14809189
+:102CC000C101D80115968C932EC0CD2819F15F3F14
+:102CD00011F44F3FF9F0F62E61111CC080918A016A
+:102CE00020918B0136E0821709F45AC090E0389F9A
+:102CF000F001399FF00D1124E457FE4F71815713F5
+:102D000006C07081471303C07281711103C0019620
+:102D10008770E9CFF62E662309F418C18091C101AE
+:102D200081608093C101F12C11C1751308C0341367
+:102D300006C0611104C08091C101D801C3C04D8794
+:102D40005E878D859E856A8B0E941C156A89882303
+:102D5000E1F16623D1F12091C101822F82958F701C
+:102D600090E0029774F08091BC019091BD0198872A
+:102D70008F831986DB86CA862C87CE0107960E9430
+:102D8000DD1486E0F801ACEBB1E001900D928A957C
+:102D9000E1F70E9494150E948615FF24F394D6C093
+:102DA0004D875E878D859E850E94501A292F22951A
+:102DB0002F7030E0223031050CF0BCC09F7009F05C
+:102DC000B6C0805E883008F4C1C0C8010E94DD141E
+:102DD000E4CFC816D90608F453C0F601E81BF90B76
+:102DE000CF01883C910508F450C0F12C7C2DD98A84
+:102DF000C88A89890E944615ECEBF1E086E0DF0184
+:102E00001D928A95E9F70E948615A0C0751314C01B
+:102E1000341312C0611110C08091C101F801858383
+:102E2000C8010E94DD1486E0ECEBF1E0DF011D92A9
+:102E30008A95E9F7FE2C8AC04D875E878D859E8531
+:102E40006A8B0E941C156A89882309F4BECF662309
+:102E500009F4BBCF2091C101822F82958F7090E041
+:102E600002970CF48ECF8091BC019091BD019A83A2
+:102E700089831B82DD82CC822E83CE0101967FCF97
+:102E8000809590958C0D9D1DACCFF62E662309F490
+:102E90009CCF75132EC034132CC02091C10120FD8E
+:102EA0001FC0822F82958F70D9F0D80115962C9370
+:102EB00015978F3049F08F5F982F9295907F822FD2
+:102EC0008F70892B15968C93C8010E94DD1486E0C3
+:102ED000F801ACEBB1E001900D928A95E1F793CF48
+:102EE00086E0F801ACEBB1E001900D928A95E1F734
+:102EF0002DC04D875E878D859E850E941C15811192
+:102F000040CF8091C10181608093C101C8010E94BE
+:102F1000DD141CC0662309F458CF4D875E878D856C
+:102F20009E850E941C15882309F44FCF2ACF81115A
+:102F300048CF0CC0243031050CF047CF9F7009F406
+:102F400040CFF8019581907F09F03BCF8F2D62969D
+:102F50000FB6F894DEBF0FBECDBFDF91CF911F91AA
+:102F60000F91FF90EF90DF90CF9008951F93CF9334
+:102F7000DF93CDB7DEB72C970FB6F894DEBF0FBE48
+:102F8000CDBF4F83588769877A878B879C87CE010F
+:102F900007960E94EF15882369F08F8198852A850E
+:102FA0003B85232BF1F19F3F09F063C08F3F09F070
+:102FB00060C037C086E0FE013796DE0111960190B1
+:102FC0000D928A95E1F76F817885EA85FB853097C8
+:102FD00041F17F3F11F46F3F21F120918B0130E0EF
+:102FE000C90101968770992740918A0150E08417A2
+:102FF000950709F447C069837A83FD83EC8396E0E3
+:10300000929FD001939FB00D1124A457BE4FFE0193
+:10301000319601900D929A95E1F780938B010E9471
+:10302000651516E080918A0190918B018917C1F195
+:10303000189FC001112484579E4F0E94EF158823CA
+:1030400079F1E0918A011E9FF0011124E457FE4FAF
+:103050004081518162817381848195810E945515DF
+:1030600080918A0190E001968770992780938A0168
+:10307000D9CF4F81588569857A858B859C850E943B
+:103080005515CFCF0E94181510928B0110928A010E
+:10309000ECEBF1E086E0DF011D928A95E9F7C1CF04
+:1030A0002C960FB6F894DEBF0FBECDBFDF91CF9147
+:1030B0001F910895EF92FF920F931F93CF93DF9389
+:1030C0008C01892B09F46CC0F12CEE24E394E80107
+:1030D0002196F8018491843740F4843008F051C07F
+:1030E000813081F0823019F15BC0853709F444C02A
+:1030F000A8F19CE7980F903708F052C08F770E9494
+:10310000631241C00E5F1F4FFE01C49180E28C0F1D
+:10311000883048F4C7708E2D01C0880FCA95EAF731
+:103120000E94361B14C08C2F0E949B112DC00E5F75
+:103130001F4FFE01C49180E28C0F883058F4C77095
+:103140008E2D01C0880FCA95EAF70E943C1B0E9491
+:103150005D1B1AC08C2F0E94631216C00E5F1F4F9A
+:10316000FE01C491CC2381F08FE99FE00197F1F734
+:1031700000C00000C150F6CF0E5F1F4FFE01F4905B
+:1031800003C00E949B118E018F2D882309F49FCFCD
+:10319000EFE9FFE03197F1F700C000008150F5CF73
+:1031A000DF91CF911F910F91FF90EF9008950895B7
+:1031B0006093C6017093C7018093C8019093C901C1
+:1031C0000C9404150F931F930091C6011091C70131
+:1031D0002091C8013091C901DC01CB01802B912BDA
+:1031E000A22BB32B8093C6019093C701A093C80173
+:1031F000B093C9011F910F910C9404150F931F9365
+:103200000091C6011091C7012091C8013091C901F8
+:10321000DC01CB0180239123A223B3238093C60139
+:103220009093C701A093C801B093C9011F910F915A
+:103230000C9404150F931F930091C6011091C701C0
+:103240002091C8013091C901DC01CB018027912771
+:10325000A227B3278093C6019093C701A093C8010A
+:10326000B093C9011F910F910C9404151092C201E3
+:103270001092C3011092C4011092C5010C94041560
+:1032800041E050E060E070E004C0440F551F661F4D
+:10329000771F8A95D2F74093C2015093C301609380
+:1032A000C4017093C5010C94041541E050E060E046
+:1032B00070E004C0440F551F661F771F8A95D2F730
+:1032C0008091C2019091C301A091C401B091C50148
+:1032D000482B592B6A2B7B2B4093C2015093C3017F
+:1032E0006093C4017093C5010C94041541E050E053
+:1032F00060E070E004C0440F551F661F771F8A9579
+:10330000D2F740955095609570958091C20190914B
+:10331000C301A091C401B091C501482359236A2378
+:103320007B234093C2015093C3016093C401709307
+:10333000C5010C94041541E050E060E070E004C069
+:10334000440F551F661F771F8A95D2F78091C201DF
+:103350009091C301A091C401B091C501482759279C
+:103360006A277B274093C2015093C3016093C40135
+:103370007093C5010C9404150F931F930091C20123
+:103380001091C3012091C4013091C501DC01CB0132
+:10339000802B912BA22BB32B8093C2019093C3015E
+:1033A000A093C401B093C5011F910F910C94041513
+:1033B0000F931F930091C2011091C3012091C4018A
+:1033C0003091C501DC01CB0180239123A223B323DB
+:1033D0008093C2019093C301A093C401B093C5012F
+:1033E0001F910F910C9404150F931F930091C2012C
+:1033F0001091C3012091C4013091C501DC01CB01C2
+:1034000080279127A227B3278093C2019093C301FD
+:10341000A093C401B093C5011F910F910C940415A2
+:103420000895CF92DF92EF92FF920F931F93CF9365
+:10343000DF938C01C090C601D090C701E090C80115
+:10344000F090C9018091C2019091C301A091C40183
+:10345000B091C501C82AD92AEA2AFB2ACFE1D0E0D7
+:10346000D701C6010C2E04C0B695A79597958795F0
+:103470000A94D2F780FF06C0B8018C2F0E9467071C
+:10348000019721F4219760F780E001C08C2FDF9134
+:10349000CF911F910F91FF90EF90DF90CF90089503
+:1034A000CF93DF93EC010E94111ABE010E946707BF
+:1034B000DF91CF910895CB010E94501A0895809119
+:1034C000CA0185958595859508958091CA01877073
+:1034D000089598E0899F90011124262B2093CA011A
+:1034E0000C9455192091CA01809582238093CA01BA
+:1034F000982F977069F430E0482F552747FD509575
+:103500002417350729F08595859585950C947619AE
+:1035100008959091CA01977081E009F480E00895C0
+:1035200090910C01992321F090910D01911109C006
+:1035300020910E0130910F01F90132969FEF40E08A
+:103540001FC0982F9695969596959F3050F5E091CF
+:103550000E01F0910F01E90FF11D877021E030E0BD
+:10356000A90102C0440F551F8A95E2F7CA01918153
+:10357000892B818308959F3F39F04F5F4E3041F092
+:1035800051915813F8CF0DC05111F7CF942FF5CFAB
+:103590009F3F39F0F901E90FF11D97FDFA958283FC
+:1035A0000895089590910C01992321F090910D01B7
+:1035B000911109C020910E0130910F01F90132964D
+:1035C000205F3F4F1FC0982F9695969596959F30F8
+:1035D000F0F4E0910E01F0910F01E90FF11D8770F9
+:1035E00021E030E0A90102C0440F551F8A95E2F79F
+:1035F000CA01809591818923818308953196E217CC
+:10360000F30729F090819813F9CF1082F7CF08952E
+:1036100081E090E0E0910E01F0910F01E80FF91FB9
+:103620001082019680319105A9F708959091DE01ED
+:10363000892B8093DE01089580959091DE01892386
+:103640008093DE0108951092DE0108959091DD01CE
+:10365000892B8093DD01089580959091DD01892368
+:103660008093DD0108951092DD0108959091DC01B1
+:10367000892B8093DC01089580959091DC0189234A
+:103680008093DC0108951092DC0108958093CB01B2
+:1036900008951092CB01089580910E0190910F0131
+:1036A000FC0131969C01205F3F4F80E09191911188
+:1036B0008F5FE217F307D1F70895E0910E01F091C3
+:1036C0000F018091DE018083E0910E01F0910F01E6
+:1036D00090818091DD01892B8083E0910E01F09132
+:1036E0000F0190818091DC01892B80838091CB0137
+:1036F000882361F0E0910E01F0910F019081892BF8
+:1037000080830E944C1B81111092CB0180910E018D
+:1037100090910F010C948B1020E0009739F0AC01D0
+:1037200041505109842395232F5FF7CF822F0895AD
+:10373000CF92DF92EF92FF926C01EE24FF24C1142E
+:10374000D104E104F10421F0C701B60120E101C078
+:1037500020E0C72ED82EE92EFF24C114D104E104A5
+:10376000F10419F0285FC701B6016B017C0154E038
+:10377000F694E794D794C7945A95D1F7C114D1041D
+:10378000E104F10419F02C5FC701B6016B017C0163
+:1037900042E0F694E794D794C7944A95D1F7C114C0
+:1037A000D104E104F10419F02E5FC701B601DC0178
+:1037B000CB01B695A79597958795892B8A2B8B2B4F
+:1037C00009F02F5F822FFF90EF90DF90CF90089548
+:1037D0008091F801843039F11092E00120E488E111
+:1037E00090E00FB6F894A895809360000FBE2093E8
+:1037F000600080E00E94790983B7817F846083BF85
+:1038000083B7816083BF7894889583B78E7F83BFA9
+:103810000FB6F894A895809160008861809360004D
+:10382000109260000FBE089508950E9452030E94F6
+:1038300065030E94141C0E945A0491E0811101C08A
+:1038400090E0892F08950E9418150E947F100C9413
+:10385000790982E084BD93E095BD9AEF97BD80938E
+:103860006E0008952FB7F8948091E1019091E201E4
+:10387000A091E301B091E4012FBF0895CF92DF92B0
+:10388000EF92FF920F931F932FB7F8944091E101AD
+:103890005091E2016091E3017091E4012FBF6A0150
+:1038A0007B01EE24FF248C0120E030E0C016D1061D
+:1038B000E206F30610F4415051099A01281B390B16
+:1038C000C9011F910F91FF90EF90DF90CF90089565
+:1038D0001F920F920FB60F9211248F939F93AF9365
+:1038E000BF938091E1019091E201A091E301B09139
+:1038F000E4010196A11DB11D8093E1019093E201C5
+:10390000A093E301B093E401BF91AF919F918F9198
+:103910000F900FBE0F901F9018950E947C0DF89489
+:103920002FEF87EA91E6215080409040E1F700C0F8
+:10393000000087E090EBDC0180930102909302028B
+:10394000A0930302B09304029CE088E10FB6F894C0
+:10395000A895809360000FBE90936000FFCF0E94F7
+:10396000E71C811102C00E94CD1C0E94F21C8093B2
+:10397000DF010E94FA1C90E09093F3018093F20122
+:1039800087FB882780F980930D010E94F61C682F21
+:1039900070E080E090E00C94D8186DEE7EEF80E04F
+:1039A00090E00E94432360E082E090E00E94322396
+:1039B00060E083E090E00E94322360E084E090E0E9
+:1039C0000E94322360E085E090E00C94322380E096
+:1039D00090E00E942C2321E08D3E9E4F09F020E0D4
+:1039E000822F089582E090E00C94242383E090E0FD
+:1039F0000C94242384E090E00C942423682F84E02A
+:103A000090E00C9432238091E70180FF0BC060911D
+:103A1000130185E0689FB001112475956795759530
+:103A200067952BC081FF09C06091130185E0689FF5
+:103A3000B00111247595679520C082FF07C0609181
+:103A4000130185E0689FB001112417C09091E8012F
+:103A50009923D1F060911201961788F720911301F4
+:103A600085E0289F90011124929FA001939F500D03
+:103A7000112470E0CA010E94F6226038710540F4FA
+:103A80006115710539F002C065E070E0862F089578
+:103A90008FE7089581E008958091E70180FF08C0D5
+:103AA0006091110170E0759567957595679521C0D6
+:103AB00081FF06C06091110170E07595679519C08E
+:103AC00082FF04C06091110170E010C09091E80184
+:103AD0009923C1F0609110019617A0F78091110110
+:103AE000899FC001112470E00E94F62260387105A0
+:103AF00028F46115710521F0862F08958FE7089548
+:103B000081E0089561E070E0F4CF803F21F40E94ED
+:103B1000031D819504C0813F29F40E94031D8093F9
+:103B2000EB010895823F21F40E94031D819504C09A
+:103B3000833F29F40E94031D8093EA010895893F81
+:103B400019F40E944C1D05C08A3F31F40E944C1D9F
+:103B500081958093EC0108958B3F21F40E944C1DC8
+:103B6000819504C08C3F29F40E944C1D8093ED0187
+:103B70000895843F21F48091E901816017C0853F59
+:103B800021F48091E901826011C0863F21F4809187
+:103B9000E90184600BC0873F21F48091E9018860CE
+:103BA00005C0883F31F48091E90180618093E9018B
+:103BB00008958D3F21F48091E70181600BC08E3F15
+:103BC00021F48091E701826005C08F3F29F4809144
+:103BD000E70184608093E7010895803F39F4809184
+:103BE000EB0187FF6CC01092EB0169C0813F29F4A3
+:103BF0008091EB011816BCF362C09091EA01823FFC
+:103C000029F497FF5CC01092EA0159C0833F19F470
+:103C10001916CCF354C0893F41F48091EC01181679
+:103C20000CF04DC01092EC014AC08A3F29F48091FB
+:103C3000EC0187FF44C0F6CF8B3F39F48091ED0152
+:103C400087FF3DC01092ED013AC08C3F29F480916E
+:103C5000ED011816BCF333C0843F21F48091E901D3
+:103C60008E7F17C0853F21F48091E9018D7F11C0BF
+:103C7000863F21F48091E9018B7F0BC0873F21F4BF
+:103C80008091E901877F05C0883F31F48091E90187
+:103C90008F7E8093E90113C08D3F21F48091E7016D
+:103CA0008E7F0BC08E3F21F48091E7018D7F05C090
+:103CB0008F3F29F48091E7018B7F8093E70180910A
+:103CC000EA0181110EC08091EB0181110AC080913F
+:103CD000EC01811106C08091ED01811102C01092AA
+:103CE000E801089589EE91E00E9496100E94321C2E
+:103CF0009093E6018093E50108951F93CF93DF939E
+:103D00008091E5019091E6010E943E1CAC019091EA
+:103D1000E801992321F02091140130E006C02091A0
+:103D200015018AE0289F900111244217530708F4D7
+:103D300086C08091EA01C091EB01D091EC01109115
+:103D4000ED01811107C0C11176C0D11174C01111EC
+:103D500072C075C09F3F19F09F5F9093E8011816DD
+:103D600024F40E94031D8093EA018091EA0187FFF9
+:103D700005C00E94031D81958093EA011C1624F45E
+:103D80000E94031D8093EB018091EB0187FF05C02A
+:103D90000E94031D81958093EB016091EA016623E7
+:103DA00039F1C091EB01CC2319F1772767FD7095AC
+:103DB000872F972F0E94FD2123E333E343E35FE343
+:103DC0000E9461220E94C5216093EA016C2F77272F
+:103DD00067FD7095872F972F0E94FD2123E333E322
+:103DE00043E35FE30E9461220E94C5216093EB01DF
+:103DF0001D1624F40E944C1D8093EC018091EC016F
+:103E000087FF05C00E944C1D81958093EC0111161F
+:103E100024F40E944C1D8093ED018091ED0187FFF9
+:103E200005C00E944C1D81958093ED01DF91CF91DB
+:103E30001F910C94721E9F3F09F08ECF96CFDF9199
+:103E4000CF911F910895E9EEF1E085E0DF011D9229
+:103E50008A95E9F71092E8011092E70108958330FE
+:103E600081F128F4813059F08230D1F00895853005
+:103E700009F449C0B8F1863009F456C0089580911C
+:103E80001501262F30E0280F311D2F3F310524F476
+:103E9000680F6093150108958FEF809315010895C1
+:103EA00080911401262F30E0280F311D2F3F31055E
+:103EB00024F4680F6093140108958FEF8093140128
+:103EC000089580911301262F30E0280F311D2F3FD8
+:103ED000310524F4680F6093130108958FEF8093E8
+:103EE0001301089580911201262F30E0280F311D13
+:103EF0002F3F310524F4680F6093120108958FEF6E
+:103F000080931201089580911101262F30E0280F2F
+:103F1000311D2F3F310524F4680F6093110108957E
+:103F20008FEF80931101089580911001262F30E0CA
+:103F3000280F311D2F3F310524F4680F60931001C5
+:103F400008958FEF809310010895833011F128F4C4
+:103F5000813049F0823091F00895853081F120F16F
+:103F60008630C1F1089580911501681720F4861BF1
+:103F70008093150108951092150108958091140100
+:103F8000681720F4861B8093140108951092140181
+:103F9000089580911301681720F4861B8093130104
+:103FA000089510921301089580911201681720F46A
+:103FB000861B80931201089510921201089580913A
+:103FC0001101681720F4861B809311010895109247
+:103FD0001101089580911001681720F4861B8093C9
+:103FE000100108951092100108950F931F938D31C1
+:103FF00009F471C008F045C0803109F485C008F5A6
+:10400000873009F46FC068F4863009F0ADC0809144
+:10401000DF01817F8E7F8093DF0181E08093EF015C
+:10402000A4C08B3009F49EC08E3009F09DC08091F1
+:10403000DF0182FB222720F991E0922790FB82F991
+:104040006CC0863109F48EC060F4813109F08CC0F7
+:104050000E94181590910D0181E0892780930D0130
+:1040600081C0893109F47EC08B3109F07DC0809117
+:10407000DF0181FB222720F991E0922790FB81F953
+:104080004CC0853309F466C048F4873209F462C035
+:1040900008F44FC0893209F45DC066C0833438F437
+:1040A0008A3308F044C0883309F45CC05DC08334AF
+:1040B00009F450C0883409F057C00E9418150FEF5A
+:1040C00013ED20E3015010402040E1F700C0000054
+:1040D0000E948D1C47C00E947F210E947F100E9479
+:1040E000790940C09091DF01892F8095817080FB14
+:1040F00090F929F0966098609093DF0136C0997F1F
+:10410000977F9093DF012EC08091DF0183FB2227F0
+:1041100020F991E0922790FB83F98093DF019923A6
+:1041200009F18091DF0181608093DF011BC0895319
+:1041300001C08D5141E050E060E070E08A019B01D8
+:1041400004C0000F111F221F331F8A95D2F7C90127
+:10415000B80104C061E070E080E090E00E94D818EF
+:104160000E94181581E001C080E01F910F91089511
+:1041700080E0089580E008958E518A3030F4E82F71
+:10418000F0E0E65DFE4F8081089580E00895CF93D2
+:10419000C82F8091EF01813079F018F08230E9F179
+:1041A00086C0E0910E01F0910F018081813169F0AC
+:1041B000823209F07EC009C0E0910E01F0910F013A
+:1041C0008081813111F0823261F48C2F0E94B820FD
+:1041D000811104C08C2F0E94F51F1DC081E090E06A
+:1041E0001AC08C2F0E94BA20811114C0C43179F0FA
+:1041F00048F4CB3079F0C03109F05FC082E08093A1
+:10420000EF0108C0C93219F0C83321F056C010922E
+:10421000EF0153C081E0817052C0C93281F110F5C5
+:10422000C43169F1A8F4C73009F045C08AE0809331
+:10423000150194E19093140193E0909313018093FE
+:10424000120188E08093110188E28093100133C04D
+:1042500082EE8C0F863078F58C2F0E94BC208093E4
+:10426000EE0129C0CE34E9F020F4CB3421F56AE028
+:1042700013C0C13579F0C235F1F461E00DC0809111
+:10428000EE01882319F01092EE0115C081E08093B1
+:10429000EF0115C061E006C08091EE010E942F1F62
+:1042A0000AC06AE08091EE010E94A51F04C010922E
+:1042B000EF0180E004C081E002C080E0ACCFCF918C
+:1042C0000895E1E8F0E080818860808380818160EA
+:1042D00080838FB7F89493E09093890090ED90934A
+:1042E00088008FBF0895EFE6F0E0808182608083D0
+:1042F0000895EFE6F0E080818D7F80830895EFE6FA
+:10430000F0E0908182E08927808308951F920F92C8
+:104310000FB60F9211242F933F934F935F936F9398
+:104320007F938F939F93AF93BF93EF93FF9380916E
+:10433000F0019091F10101969093F1018093F001C9
+:10434000811103C082E00E947909E091F101E695B4
+:10435000E695F0E0EB54FB4FE4918091F0018E1371
+:1043600003C080E00E947909FF91EF91BF91AF9166
+:104370009F918F917F916F915F914F913F912F917D
+:104380000F900FBE0F901F9018950E94CC2168943B
+:10439000B1110C945B2208950E94402288F09F572F
+:1043A00098F0B92F9927B751B0F0E1F0660F771F59
+:1043B000881F991F1AF0BA95C9F714C0B13091F04F
+:1043C0000E945A22B1E008950C945A22672F782F48
+:1043D0008827B85F39F0B93FCCF386957795679514
+:1043E000B395D9F73EF490958095709561957F4F80
+:1043F0008F4F9F4F0895E89409C097FB3EF4909526
+:104400008095709561957F4F8F4F9F4F9923A9F0AD
+:10441000F92F96E9BB279395F6958795779567953C
+:10442000B795F111F8CFFAF4BB0F11F460FF1BC080
+:104430006F5F7F4F8F4F9F4F16C0882311F096E913
+:1044400011C0772321F09EE8872F762F05C06623C1
+:1044500071F096E8862F70E060E02AF09A95660F7A
+:10446000771F881FDAF7880F9695879597F9089533
+:1044700057FD9058440F551F59F05F3F71F0479515
+:10448000880F97FB991F61F09F3F79F087950895FA
+:10449000121613061406551FF2CF4695F1DF08C019
+:1044A000161617061806991FF1CF86957105610536
+:1044B00008940895E894BB2766277727CB0197F9DE
+:1044C00008950E9474220C94E5220E94D72238F0AD
+:1044D0000E94DE2220F0952311F00C94CE220C9441
+:1044E000D42211240C945B220E94382270F3959FF1
+:1044F000C1F3950F50E0551F629FF001729FBB27DB
+:10450000F00DB11D639FAA27F00DB11DAA1F649F76
+:104510006627B00DA11D661F829F2227B00DA11D29
+:10452000621F739FB00DA11D621F839FA00D611DAF
+:10453000221F749F3327A00D611D231F849F600DD0
+:10454000211D822F762F6A2F11249F5750409AF0F9
+:10455000F1F088234AF0EE0FFF1FBB1F661F771F85
+:10456000881F91505040A9F79E3F510580F00C9450
+:10457000CE220C945B225F3FE4F3983ED4F3869501
+:1045800077956795B795F795E7959F5FC1F7FE2BF0
+:10459000880F911D9695879597F9089597F99F67CC
+:1045A00080E870E060E008959FEF80EC08950024BB
+:1045B0000A941616170618060906089500240A9488
+:1045C00012161306140605060895092E0394000C0E
+:1045D00011F4882352F0BB0F40F4BF2B11F460FF9D
+:1045E00004C06F5F7F4F8F4F9F4F089597FB072E3B
+:1045F00016F4009407D077FD09D00E94102307FC21
+:1046000005D03EF4909581959F4F089570956195E2
+:104610007F4F0895EE0FFF1F0590F491E02D099450
+:10462000AA1BBB1B51E107C0AA1FBB1FA617B707D8
+:1046300010F0A61BB70B881F991F5A95A9F78095F4
+:104640009095BC01CD010895F999FECF92BD81BD31
+:10465000F89A992780B50895A8E1B0E042E050E0CB
+:104660000C944B23262FF999FECF92BD81BDF89A69
+:10467000019700B4021631F020BD0FB6F894FA9AF3
+:10468000F99A0FBE08950196272F0E9433230C94A8
+:104690003223DC01CB01FC01F999FECF06C0F2BD4B
+:1046A000E1BDF89A319600B40D9241505040B8F7F0
+:0646B0000895F894FFCF0D
+:1046B60002207B09090AE609B2097E090101CC013B
+:1046C60028080A03140A404D363975042804F203F3
+:1046D600B9034C0365037E03970301020304050631
+:0446E60007080900B8
+:00000001FF
diff --git a/keyboards/ergodox_ez/keymaps/tkuichooseyou/keymap.c b/keyboards/ergodox_ez/keymaps/tkuichooseyou/keymap.c
new file mode 100644
index 000000000..87b77e42e
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/tkuichooseyou/keymap.c
@@ -0,0 +1,184 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define BASE 0 // default layer
+#define SYMB 1 // symbols
+#define MDIA 2 // media keys
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | = | 1 | 2 | 3 | 4 | 5 |CMD+{ | | CMD+}| 6 | 7 | 8 | 9 | 0 | - |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Tab | Q | W | E | R | T | Hyper| | Meh | Y | U | I | O | P | \ |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * |Ctrl/Esc| A | S | D | F | G |------| |------| H | J | K | L |; / L2| LGui |
+ * |--------+------+------+------+------+------| LGui | | LGui |------+------+------+------+------+--------|
+ * | LShift | Z | X | C | V | B | | | | N | M | , | . | / | RShift |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * |Grv/L1| '" |AltShf| Left | Right| | Up | Down | [ | ] | ~L1 |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | App | LGui | | Del |Ctrl/Esc|
+ * ,------|------|------| |------+--------+------.
+ * | | | Home | | PgUp | | |
+ * | Space|Backsp|------| |------| Tab |Enter |
+ * | |ace | End | | PgDn | | |
+ * `--------------------' `----------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_EQL, KC_1, KC_2, KC_3, KC_4, KC_5, LGUI(LSFT(KC_LBRC)),
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, ALL_T(KC_NO),
+ CTL_T(KC_ESC), KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_LGUI,
+ LT(SYMB,KC_GRV),KC_QUOT, LALT(KC_LSFT), KC_LEFT,KC_RGHT,
+ ALT_T(KC_APP), KC_LGUI,
+ KC_HOME,
+ KC_SPC,KC_BSPC,KC_END,
+ // right hand
+ LGUI(LSFT(KC_RBRC)), KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
+ MEH_T(KC_NO), KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSLS,
+ KC_H, KC_J, KC_K, KC_L, LT(MDIA, KC_SCLN),KC_QUOT,
+ KC_LGUI, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH, KC_RSFT,
+ KC_UP, KC_DOWN,KC_LBRC,KC_RBRC, KC_FN1,
+ KC_DELT, CTL_T(KC_ESC),
+ KC_PGUP,
+ KC_PGDN,KC_TAB, KC_ENT
+ ),
+/* Keymap 1: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | . | 0 | = | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[SYMB] = KEYMAP(
+ // left hand
+ KC_TRNS,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS,KC_EXLM,KC_AT, KC_LCBR,KC_RCBR,KC_PIPE,KC_TRNS,
+ KC_TRNS,KC_HASH,KC_DLR, KC_LPRN,KC_RPRN,KC_GRV,
+ KC_TRNS,KC_PERC,KC_CIRC,KC_LBRC,KC_RBRC,KC_TILD,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_UP, KC_7, KC_8, KC_9, KC_ASTR, KC_F12,
+ KC_DOWN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS,
+ KC_TRNS, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS, KC_TRNS,
+ KC_TRNS,KC_DOT, KC_0, KC_EQL, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/* Keymap 2: Media and mouse keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | MsUp | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | |MsLeft|MsDown|MsRght| |------| |------| | | | | | Play |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | | | | Prev | Next | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | Lclk | Rclk | |VolUp |VolDn | Mute | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | |Brwser|
+ * | | |------| |------| |Back |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// MEDIA AND MOUSE
+KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MPRV, KC_MNXT, KC_TRNS, KC_TRNS,
+ KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_WBAK
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(SYMB) // FN1 - Momentary Layer 1 (Symbols)
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case 1:
+ ergodox_right_led_1_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/tm2030/keymap.c b/keyboards/ergodox_ez/keymaps/tm2030/keymap.c
new file mode 100644
index 000000000..ca8075226
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/tm2030/keymap.c
@@ -0,0 +1,242 @@
+/* TypeMatrix-2030-like keymap */
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+#include "led.h"
+
+#define BASE 0 // default layer
+#define DVRK 1 // Dvorak layer
+#define NUMR 8 // numeric layer
+#define FNLR 9 // fn layer
+
+#define MDBL0 1
+#define MFNLR 2
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | ` | 1 | 2 | 3 | 4 | 5 | Del | | Del | 6 | 7 | 8 | 9 | 0 | ] |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Tab | Q | W | E | R | T |Backsp| |Backsp| Y | U | I | O | P | [ |
+ * |--------+------+------+------+------+------|ace | |ace |------+------+------+------+------+--------|
+ * | LShift | A | S | D | F | G |------| |------| H | J | K | L | ; | '/Shift|
+ * |--------+------+------+------+------+------|Enter | |Enter |------+------+------+------+------+--------|
+ * | LShift | Z | X | C | V | B | | | | N | M | , | . | / | \/Shift|
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * |LCtrl | fn | LGui | Play |App/Alt| | RAlt | - | Home | = |End/Ctl|
+ * `-----------------------------------' `-----------------------------------'
+ * ,--------------. ,-------------.
+ * |Esc/Alt| num | | Left |Right |
+ * ,------+-------+------| |------+------+------.
+ * | | | PgUp | | Up | | |
+ * |Space |LShift |------| |------|RShift|Space |
+ * | | | PgDn | | Down | | |
+ * `---------------------' `--------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_DELT,
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_BSPC,
+ KC_LSFT, KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_ENT,
+ KC_LCTL, M(MFNLR), KC_LGUI,KC_MPLY,ALT_T(KC_APP),
+
+ ALT_T(KC_ESC), TG(NUMR),
+ KC_PGUP,
+ KC_SPC, KC_LSFT, KC_PGDN,
+
+ // right hand
+ KC_DELT, KC_6, KC_7, KC_8, KC_9, KC_0, KC_RBRC,
+ KC_BSPC, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC,
+ KC_H, KC_J, KC_K, KC_L, KC_SCLN, SFT_T(KC_QUOT),
+ KC_ENT, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, SFT_T(KC_BSLS),
+ KC_RALT, KC_MINS, KC_HOME, KC_EQL, CTL_T(KC_END),
+
+ KC_LEFT, KC_RGHT,
+ KC_UP,
+ KC_DOWN, KC_RSFT, KC_SPC
+ ),
+/* Dvorak layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | ` | 1 | 2 | 3 | 4 | 5 | Del | | Del | 6 | 7 | 8 | 9 | 0 | = |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Tab | ' | , | . | P | Y |Backsp| |Backsp| F | G | C | R | L | / |
+ * |--------+------+------+------+------+------|ace | |ace |------+------+------+------+------+--------|
+ * | LShift | A | O | E | U | I |------| |------| D | H | T | N | S | -/Shift|
+ * |--------+------+------+------+------+------|Enter | |Enter |------+------+------+------+------+--------|
+ * | LShift | ; | Q | J | K | X | | | | B | M | W | V | Z | \/Shift|
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * |LCtrl | fn | LGui | Play |App/Alt| | RAlt | [ | Home | ] |End/Ctl|
+ * `-----------------------------------' `-----------------------------------'
+ * ,--------------. ,-------------.
+ * |Esc/Alt| num | | Left |Right |
+ * ,------+-------+------| |------+------+------.
+ * | | | PgUp | | Up | | |
+ * |Space |LShift |------| |------|RShift|Space |
+ * | | | PgDn | | Down | | |
+ * `---------------------' `--------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[DVRK] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_DELT,
+ KC_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, KC_BSPC,
+ KC_LSFT, KC_A, KC_O, KC_E, KC_U, KC_I,
+ KC_LSFT, KC_SCLN, KC_Q, KC_J, KC_K, KC_X, KC_ENT,
+ KC_LCTL, M(MFNLR), KC_LGUI, KC_MPLY, ALT_T(KC_APP),
+
+ ALT_T(KC_ESC), TG(NUMR),
+ KC_PGUP,
+ KC_SPC, KC_LSFT, KC_PGDN,
+
+ // right hand
+ KC_DELT, KC_6, KC_7, KC_8, KC_9, KC_0, KC_EQL,
+ KC_BSPC, KC_F, KC_G, KC_C, KC_R, KC_L, KC_SLSH,
+ KC_D, KC_H, KC_T, KC_N, KC_S, SFT_T(KC_MINS),
+ KC_ENT, KC_B, KC_M, KC_W, KC_V, KC_Z, SFT_T(KC_BSLS),
+ KC_RALT, KC_LBRC, KC_HOME, KC_RBRC, CTL_T(KC_END),
+
+ KC_LEFT, KC_RGHT,
+ KC_UP,
+ KC_DOWN, KC_RSFT, KC_SPC
+ ),
+/* Numeric Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | | | Tab | / | * | - |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | F6 | F7 | F8 | F9 | F10 | | | | | Home | 7 | 8 | 9 | + |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | F11 | F12 | | | |------| |------| Up | End | 4 | 5 | 6 | + |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | Left | Down | Right| 1 | 2 | 3 |KpEnter |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | 0 | 00 | . |Etr/Ctl|
+ * `----------------------------------' `-----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | |n.lock|c.lock|
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[NUMR] = KEYMAP(
+ // left hand
+ KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_TRNS,
+ KC_TRNS, KC_F11, KC_F12, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_TAB, KC_PSLS, KC_PAST, KC_PMNS,
+ KC_TRNS, KC_TRNS, KC_HOME, KC_P7, KC_P8, KC_P9, KC_PPLS,
+ KC_UP, KC_END, KC_P4, KC_P5, KC_P6, KC_PPLS,
+ KC_LEFT, KC_DOWN, KC_RGHT, KC_P1, KC_P2, KC_P3, KC_PENT,
+ KC_TRNS, KC_P0, M(MDBL0),KC_PDOT, CTL_T(KC_PENT),
+
+ KC_NLCK, KC_CAPS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/* fn layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | |Insert| |Insert|Eject |Power |Sleep | Wake |PrtScr|ScrollLk|
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | | | |VolUp | | | | | | | | Pause |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | Calc | Mail |Browsr|------| |------| | | | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | cut | copy |paste | Mute |VolDn | | | | | | | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | | | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | Next | | |
+ * | Mute | |------| |------| | |
+ * | | | | | Prev | | |
+ * `--------------------' `--------------------'
+ */
+// MEDIA AND MOUSE
+[FNLR] = KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_INS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_VOLU,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_CALC, KC_MAIL, KC_WHOM,
+ KC_TRNS, KC_TRNS, LSFT(KC_DELT),LCTL(KC_INS),LSFT(KC_INS), KC_MUTE, KC_VOLD,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_MUTE, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_INS, KC_EJCT, KC_PWR, KC_SLEP, KC_WAKE, KC_PSCR, KC_SLCK,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PAUS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+
+ KC_TRNS, KC_TRNS,
+ KC_MPRV,
+ KC_MNXT, KC_TRNS, KC_TRNS
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case MDBL0:
+ if (record->event.pressed) {
+ return MACRO( I(25), T(P0), T(P0), END );
+ }
+ break;
+ case MFNLR:
+ layer_invert(NUMR);
+ layer_invert(FNLR);
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ // led 1: numeric layer
+ if (layer_state & (1 << NUMR)) {
+ ergodox_right_led_1_on();
+ }
+ // led 2: Dvorak layer
+ if (default_layer_state == 1 << DVRK) {
+ ergodox_right_led_2_on();
+ }
+ // led 3: caps lock
+ if (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) {
+ ergodox_right_led_3_on();
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/tm2030/readme.md b/keyboards/ergodox_ez/keymaps/tm2030/readme.md
new file mode 100644
index 000000000..6cd794726
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/tm2030/readme.md
@@ -0,0 +1,136 @@
+# TypeMatrix™ 2030 inspired layout
+
+This is a [TypeMatrix™ 2030](http://typematrix.com/2030/features.php) inspired layout for the ErgoDox EZ. The _TypeMatrix_ is a nice small ergonomic keyboard with a matrix layout, and it provides several nice features like `enter`, `backspace` and `delete` at the center, bigger `shift` keys and international `cut`, `copy` and `paste` keys.
+
+The idea in this ErgoDox layout is to make it is as close as possible to the TM2030, such that it would be easy to switch between the TM and the ErgoDox. No _fancy_ features have been implemented, as this is intended to be a base for further customization if desired. Some keys have been duplicated in order to accomodate for most people.
+
+Most of the TM2030 features are supported except
+* automatic window switching (alt-tab key, at the left of the space key)
+* show desktop key (at the right of the space key)
+* 102/106 modes
+
+Dvorak mode is even supported by pressing [`Magic`](/TMK_readme.md#magic-commands)+`1` (`Magic` is by default `LShift`+`RShift`)
+
+Some keys had to be moved around to fit into the ErgoDox, especially the `F1`-`F12` keys and the arrow keys.
+
+## Base Layer
+This is the default layer, close to the TM with the following differences:
+
+ - Top row (with the `F`-keys) and rightmost column (with application shortcuts) are removed, the corresponding keys are displaced elsewhere.
+ - Bottom-left keys are reorganized on a single row as: `Ctrl`, `fn`, `Gui`, `Play`, `App`/`Alt`.
+ - `shuffle` and `desktop` are not supported.
+ - `right-shift` is moved on `'`, `\` and on the right thumb (the latter is actually the only _true_ `right-shift`, and must be used in the `Magic` key combination).
+ - `right-ctrl` is moved on `End`.
+ - `]` is moved in place of the dash (`-`).
+ - Dash (`-`) and `=` are moved on bottom right row.
+ - Arrows and `PgUp`/`PgDn` are moved on the thumbs.
+
+```
+,--------------------------------------------------. ,--------------------------------------------------.
+| ` | 1 | 2 | 3 | 4 | 5 | Del | | Del | 6 | 7 | 8 | 9 | 0 | ] |
+|--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+| Tab | Q | W | E | R | T |Backsp| |Backsp| Y | U | I | O | P | [ |
+|--------+------+------+------+------+------|ace | |ace |------+------+------+------+------+--------|
+| LShift | A | S | D | F | G |------| |------| H | J | K | L | ; | '/Shift|
+|--------+------+------+------+------+------|Enter | |Enter |------+------+------+------+------+--------|
+| LShift | Z | X | C | V | B | | | | N | M | , | . | / | \/Shift|
+`--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ |LCtrl | fn | LGui | Play |App/Alt| | RAlt | - | Home | = |End/Ctl|
+ `-----------------------------------' `-----------------------------------'
+ ,--------------. ,-------------.
+ |Esc/Alt| num | | Left |Right |
+ ,------+-------+------| |------+------+------.
+ | | | PgUp | | Up | | |
+ |Space |LShift |------| |------|RShift|Space |
+ | | | PgDn | | Down | | |
+ `---------------------' `--------------------'
+```
+
+### Layer Switching
+- Use `num` to toggle the Numeric Layer.
+- Hold `fn` to temporarily activate the Numeric & Fn Layers.
+
+As on the original TM 2030, when `num` layer is activated, holding `fn` disables it but enables the other `fn` keys.
+
+## Dvorak Layer
+Same as Layer 0 but with _Dvorak_ layout, to use with QWERTY OS layout.
+
+Enable Dvorak layout with [`Magic`](/TMK_readme.md#magic-commands)+`1` (`LShift`+`RShift`+`1`), disable with `Magic`-`0`.
+
+The middle (green) led indicates when the Dvorak layer is activated.
+
+ ,--------------------------------------------------. ,--------------------------------------------------.
+ | ` | 1 | 2 | 3 | 4 | 5 | Del | | Del | 6 | 7 | 8 | 9 | 0 | = |
+ |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ | Tab | ' | , | . | P | Y |Backsp| |Backsp| F | G | C | R | L | / |
+ |--------+------+------+------+------+------|ace | |ace |------+------+------+------+------+--------|
+ | LShift | A | O | E | U | I |------| |------| D | H | T | N | S | -/Shift|
+ |--------+------+------+------+------+------|Enter | |Enter |------+------+------+------+------+--------|
+ | LShift | ; | Q | J | K | X | | | | B | M | W | V | Z | \/Shift|
+ `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ |LCtrl | fn | LGui | Play |App/Alt| | RAlt | [ | Home | ] |End/Ctl|
+ `-----------------------------------' `-----------------------------------'
+ ,--------------. ,-------------.
+ |Esc/Alt| num | | Left |Right |
+ ,------+-------+------| |------+------+------.
+ | | | PgUp | | Up | | |
+ |Space |LShift |------| |------|RShift|Space |
+ | | | PgDn | | Down | | |
+ `---------------------' `--------------------'
+
+## Numeric Layer
+Numeric layer close to the TM when toggling `num`, with the following differences:
+
+- Numpad is displaced by 1 to the top left.
+- Arrows are displaced by 1 to the left.
+- Provides access to `F1`-`F12`, `caps-lock` and `num-lock`.
+
+The numeric layer is indicated with the left (red) led. Caps-lock is indicated with the right (blue) led.
+
+ ,--------------------------------------------------. ,--------------------------------------------------.
+ | | F1 | F2 | F3 | F4 | F5 | | | | | | Tab | / | * | - |
+ |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ | | F6 | F7 | F8 | F9 | F10 | | | | | Home | 7 | 8 | 9 | + |
+ |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ | | F11 | F12 | | | |------| |------| Up | End | 4 | 5 | 6 | + |
+ |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ | | | | | | | | | Left | Down | Right| 1 | 2 | 3 |KpEnter |
+ `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ | | | | | | | | 0 | 00 | . |Etr/Ctl|
+ `----------------------------------' `-----------------------------------'
+ ,-------------. ,-------------.
+ | | | |n.lock|c.lock|
+ ,------|------|------| |------+------+------.
+ | | | | | | | |
+ | | |------| |------| | |
+ | | | | | | | |
+ `--------------------' `--------------------'
+
+## Fn Layer
+Activated simultaneously with the Numeric layer when holding the `fn` key. As on the TM, it provides access to the following features:
+- `cut`, `copy` and `paste`
+- `volume up`, `volume down` and `mute` — as opposed to the TM, these are only on left hand
+- `previous track` and `next track`
+- `calculator`, `mail` and `browser home`
+- `insert`, `power`, `sleep`, `wake`, `print screen`, `scroll-lock` and `pause`
+
+Note: the `eject` key does not work due to jackhumbert/qmk_firmware#82
+
+ ,--------------------------------------------------. ,--------------------------------------------------.
+ | | | | | | |Insert| |Insert|Eject |Power |Sleep | Wake |PrtScr|ScrollLk|
+ |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ | | | | | | |VolUp | | | | | | | | Pause |
+ |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ | | | | Calc | Mail |Browsr|------| |------| | | | | | |
+ |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ | | | cut | copy |paste | Mute |VolDn | | | | | | | | |
+ `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ | | | | | | | | | | | |
+ `----------------------------------' `----------------------------------'
+ ,-------------. ,-------------.
+ | | | | | |
+ ,------|------|------| |------+------+------.
+ | | | | | Next | | |
+ | Mute | |------| |------| | |
+ | | | | | Prev | | |
+ `--------------------' `--------------------'
diff --git a/keyboards/ergodox_ez/keymaps/tonyabra_osx/keymap.c b/keyboards/ergodox_ez/keymaps/tonyabra_osx/keymap.c
new file mode 100644
index 000000000..87b9fb676
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/tonyabra_osx/keymap.c
@@ -0,0 +1,184 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define BASE 0 // default layer
+#define SYMB 1 // symbols
+#define MDIA 2 // media keys
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | Esc | 1 | 2 | 3 | 4 | 5 | = | | - | 6 | 7 | 8 | 9 | 0 | Enter |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Tab | Q | W | E | R | T | L1 | | L1 | Y | U | I | O | P | \ |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | BkSp | A | S | D | F | G |------| |------| H | J | K | L | ; | '" |
+ * |--------+------+------+------+------+------| LGui | | LGui |------+------+------+------+------+--------|
+ * | LShift | Z | X | C | V | B | | | | N | M | , | . | / | RShift |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | L1 | ` | { | } | '" | | Left | Up | Down | Right| L2 |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | Del | Alt | | Alt | Ctrl |
+ * ,------|------|------| |------+--------+------.
+ * | | | Home | | PgUp | | |
+ * | Space|Backsp|------| |------| Tab |Enter |
+ * | |ace | End | | PgDn | | |
+ * `--------------------' `----------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_EQL,
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, TG(SYMB),
+ KC_BSPC, KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_LGUI,
+ TG(SYMB), KC_GRV, KC_LBRC, KC_RBRC,KC_QUOT,
+ KC_DELT,KC_LALT,
+ KC_HOME,
+ KC_SPC,KC_BSPC,KC_END,
+ // right hand
+ KC_MINS, KC_6, KC_7, KC_8, KC_9, KC_0, KC_ENT,
+ TG(SYMB), KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSLS,
+ KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT,
+ KC_LGUI, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH, KC_RSFT,
+ KC_LEFT,KC_UP, KC_DOWN,KC_RIGHT, TG(MDIA),
+ KC_RALT, KC_RCTL,
+ KC_PGUP,
+ KC_PGDN,KC_TAB, KC_ENT
+ ),
+/* Keymap 1: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | . | 0 | = | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[SYMB] = KEYMAP(
+ // left hand
+ KC_TRNS,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS,KC_EXLM,KC_AT, KC_LCBR,KC_RCBR,KC_PIPE,KC_TRNS,
+ KC_TRNS,KC_HASH,KC_DLR, KC_LPRN,KC_RPRN,KC_GRV,
+ KC_TRNS,KC_PERC,KC_CIRC,KC_LBRC,KC_RBRC,KC_TILD,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_UP, KC_7, KC_8, KC_9, KC_ASTR, KC_F12,
+ KC_DOWN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS,
+ KC_TRNS, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS, KC_TRNS,
+ KC_TRNS,KC_DOT, KC_0, KC_EQL, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/* Keymap 2: Media and mouse keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | MsUp | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | |MsLeft|MsDown|MsRght| |------| |------| | | | | | Play |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | | | | Prev | Next | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | Lclk | Rclk | |VolUp |VolDn | Mute | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | |Brwser|
+ * | | |------| |------| |Back |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// MEDIA AND MOUSE
+[MDIA] = KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MPRV, KC_MNXT, KC_TRNS, KC_TRNS,
+ KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_WBAK
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(SYMB) // FN1 - Momentary Layer 1 (Symbols)
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case 1:
+ ergodox_right_led_1_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/tonyabra_osx/readme.md b/keyboards/ergodox_ez/keymaps/tonyabra_osx/readme.md
new file mode 100644
index 000000000..f9d76efc2
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/tonyabra_osx/readme.md
@@ -0,0 +1,5 @@
+# ErgoDox EZ OS X Simplified Configuration
+
+This keyboard configuration replaces the hyper and meh keys with the command key. It also removes all of the meta keys that require a "hold" because I found that I hesitate when I type, which can accidentally fire those combinations. On the upper left of the left hand, I mimicked the Mac placement of tab and escape, and on the upper right of the right hand, I placed an additional enter key for convenience when breezing through prompts.
+
+This is my standard working configuration for now, but I can see myself tweaking it as I use it more. I highly recommend you do the same. \ No newline at end of file
diff --git a/keyboards/ergodox_ez/keymaps/townk_osx/config.h b/keyboards/ergodox_ez/keymaps/townk_osx/config.h
new file mode 100644
index 000000000..58ba690af
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/townk_osx/config.h
@@ -0,0 +1,92 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+Copyright 2013 Oleg Kostyuk <cub.uanic@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "config_common.h"
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x1307
+#define DEVICE_VER 0x0001
+#define MANUFACTURER ErgoDox EZ
+#define PRODUCT ErgoDox EZ
+#define DESCRIPTION t.m.k. keyboard firmware for Ergodox
+
+/* key matrix size */
+#define MATRIX_ROWS 14
+#define MATRIX_COLS 6
+
+#define MOUSEKEY_DELAY 100
+#define MOUSEKEY_INTERVAL 20
+#define MOUSEKEY_MAX_SPEED 3
+#define MOUSEKEY_TIME_TO_MAX 10
+
+#define TAPPING_TOGGLE 1
+
+#define COLS (int []){ F1, F0, B0, C7, F4, F5, F6, F7, D4, D6, B4, D7 }
+#define ROWS (int []){ D0, D5, B5, B6 }
+
+/* COL2ROW or ROW2COL */
+#define DIODE_DIRECTION COL2ROW
+
+/* define if matrix has ghost */
+//#define MATRIX_HAS_GHOST
+
+/* number of backlight levels */
+#define BACKLIGHT_LEVELS 3
+
+/* Set 0 if debouncing isn't needed */
+#define DEBOUNCE 2
+#define TAPPING_TERM 200
+#define IGNORE_MOD_TAP_INTERRUPT // this makes it possible to do rolling combos (zx) with keys that convert to other keys on hold (z becomes ctrl when you hold it, and when this option isn't enabled, z rapidly followed by x actually sends Ctrl-x. That's bad.)
+
+/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
+#define LOCKING_SUPPORT_ENABLE
+/* Locking resynchronize hack */
+#define LOCKING_RESYNC_ENABLE
+
+/* key combination for command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LCTL) | MOD_BIT(KC_RCTL)) || \
+ keyboard_report->mods == (MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)) \
+)
+
+/*
+ * Feature disable options
+ * These options are also useful to firmware size reduction.
+ */
+
+/* disable debug print */
+// #define NO_DEBUG
+
+/* disable print */
+// #define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+//#define DEBUG_MATRIX_SCAN_RATE
+#define ONESHOT_TAP_TOGGLE 2
+#define ONESHOT_TIMEOUT 3000
+
+#endif
diff --git a/keyboards/ergodox_ez/keymaps/townk_osx/keymap.c b/keyboards/ergodox_ez/keymaps/townk_osx/keymap.c
new file mode 100644
index 000000000..07e58a491
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/townk_osx/keymap.c
@@ -0,0 +1,285 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+#include "action_util.h"
+#include "led.h"
+#include "keymap.h"
+#include "timer.h"
+
+/*
+
+# Why this Layout
+
+This layout was based on Kinesis layout and other ErgoDox user layouts
+available. It's target to be used on a MacOS but I'm pretty sure it can be
+addapted to Windows and/or Linux easily.
+
+## Function Key
+
+The `fn` key work almost like it would in any other keyboard with the exception
+it has a semi-sticky behavior. What does that mean?
+
+Well, if you press the `fn` and release it, the keyboard will be put on the
+_function layout_ and the next key stroke will be processed as if the `fn` key
+was pressed. Aftwards, the leyout get back to _normal_. If you hold `fn` and
+press any other key, when you release them, the keyboard leyout is back to
+_normal_.
+
+While pressing the `fn` with the left hand and strikeing the other keys on the
+right hand is farly easy, the same cannot being said for the other keys on the
+left side. So, instead of trying to do contorcionism with my left hand, I
+decided to do a semi-sticky version of `fn`. This way, I can press the `fn`
+key with my pinky, release it and press the `1` key to issue an `F1` to the
+operating system.
+
+## Key-Pad Key
+
+The `key pad` key is a layout switch key. If pressed, it will put the keyboard
+on the _key pad layout_ and stay there until key is pressed again.
+
+This is used to make the keyboard behave mostly like a **num pad keyboard**.
+
+## Notes
+- Regardless in which layout you are, keys from other layouts are not
+ accessible. This means that if you are on the _key pad layout_, the left hand
+ will be pretty much unusable.
+ Of course that like anything else, there are exceptions to this rule.
+ Modifiers should remain accessible throughout the layers.
+- The _shift key_ is, like the _function key_, also configured to have a sticky
+ behavior.
+- All sticky keys have a timeout of 3 seconds.
+
+*/
+#define BASE 0
+#define KEYPAD 1
+#define FN 2
+
+#define MACRO_TMUX_ESC 10
+#define MACRO_TMUX_PASTE 11
+#define MACRO_OSX_COPY 12
+#define MACRO_OSX_PASTE 13
+
+#define M_TESC M(MACRO_TMUX_ESC)
+#define M_TPASTE M(MACRO_TMUX_PASTE)
+#define M_OSXCPY M(MACRO_OSX_COPY)
+#define M_OSXPST M(MACRO_OSX_PASTE)
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Base Layer
+ *
+ * ,-----------------------------------------------------. ,-----------------------------------------------------.
+ * | `~ | 1 | 2 | 3 | 4 | 5 | ESC | | Pwr | 6 | 7 | 8 | 9 | 0 | - _ |
+ * |-----------+------+------+------+------+-------------| |------+------+------+------+------+------+-----------|
+ * | Tab | Q | W | E | R | T | F16 | | F17 | Y | U | I | O | P | = + |
+ * |-----------+------+------+------+------+------| Meh | | Meh |------+------+------+------+------+-----------|
+ * | \ (Ctrl) | A | S | D | F | G |------| |------| H | J | K | L | ; | ' " (Ctrl)|
+ * |-----------+------+------+------+------+------| F18 | | F19 |------+------+------+------+------+-----------|
+ * | LShift | Z | X | C | V | B | Hyper| | Hyper| N | M | , | . | / | RShift |
+ * `-----------+------+------+------+------+-------------' `-------------+------+------+------+------+-----------'
+ * | FN | KPAD |LCtrl | LAlt | LGui | | RGui | RAlt | RCtrl| KPAD | FN |
+ * `-----------------------------------' `-----------------------------------'
+ * ,-------------. ,-------------.
+ * | M(0) | M(1) | | M(2) | M(3) |
+ * ,------|------|------| |------+------+------.
+ * | | | Home | | PgUp | | |
+ * |Backsp| Del |------| |------| Enter| Space|
+ * | | | End | | PgDn | | |
+ * `--------------------' `--------------------'
+ *
+ * M(0) = Ctrk+A Esc
+ * (this is used to issue the Esc key to the Tmux application)
+ * M(1) = Ctrk+A P
+ * (this is used to issue the Paste key to the Tmux application)
+ * M(2) = Cmd+C
+ * M(3) = Cmd+V
+ */
+[BASE]=KEYMAP(//left half
+ KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_ESC,
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, MEH_T(KC_F16),
+ CTL_T(KC_BSLS), KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_FN2, KC_Z, KC_X, KC_C, KC_V, KC_B, ALL_T(KC_F18),
+ KC_FN1, TG(KEYPAD), KC_LCTRL, KC_LALT, KC_LGUI,
+ M_TESC, M_TPASTE,
+ KC_HOME,
+ KC_BSPC, KC_DELT, KC_END,
+ //right half
+ KC_POWER, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
+ MEH_T(KC_F17), KC_Y, KC_U, KC_I, KC_O, KC_P, KC_EQL,
+ KC_H, KC_J, KC_K, KC_L, KC_SCLN, CTL_T(KC_QUOT),
+ ALL_T(KC_F19), KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_FN2,
+ KC_RGUI, KC_RALT, CTL_T(KC_LBRC), KC_FN3, KC_FN1,
+ M_OSXCPY, M_OSXPST,
+ KC_PGUP,
+ KC_PGDN, KC_ENT, KC_SPC),
+
+/* Keymap 1: KeyPad Layer
+ *
+ * ,-----------------------------------------------------. ,-----------------------------------------------------.
+ * | | | LClk | RClk | MClk | | | | BTab | Clear| / | * | ^ | ( | |
+ * |-----------+------+------+------+------+-------------| |------+------+------+------+------+------+-----------|
+ * | M.Accel 2 | |ScrlUp| U |ScrlDn| | | | Tab | 7 | 8 | 9 | + | ) | |
+ * |-----------+------+------+------+------+------| | | |------+------+------+------+------+-----------|
+ * | M.Accel 1 | | L | D | R | |------| |------| 4 | 5 | 6 | - | | |
+ * |-----------+------+------+------+------+------| | |Return|------+------+------+------+------+-----------|
+ * | M.Accel 0 | |ScrlL | |ScrlR | | | | | 1 | 2 | 3 | = | | |
+ * `-----------+------+------+------+------+-------------' `-------------+------+------+------+------+-----------'
+ * | | XXXX | | | | | 0 | . | , | XXXX | |
+ * `-----------------------------------' `-----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | XXXX | |
+ * | | |------| |------| XXXX | |
+ * | | | | | | XXXX | |
+ * `--------------------' `--------------------'
+ */
+[KEYPAD]=KEYMAP(//left half
+ KC_NO, KC_NO, KC_MS_BTN1, KC_MS_BTN2, KC_MS_BTN3, KC_NO, KC_NO,
+ KC_MS_ACCEL2, KC_NO, KC_MS_WH_UP, KC_MS_U, KC_MS_WH_DOWN, KC_NO, KC_NO,
+ KC_MS_ACCEL1, KC_NO, KC_MS_L, KC_MS_D, KC_MS_R, KC_NO,
+ KC_MS_ACCEL0, KC_NO, KC_MS_WH_LEFT, KC_NO, KC_MS_WH_RIGHT, KC_NO, KC_NO,
+ KC_NO, KC_TRNS, KC_NO, KC_NO, KC_NO,
+ KC_NO, KC_NO,
+ KC_NO,
+ KC_NO, KC_NO, KC_NO,
+ //right half
+ LSFT(KC_TAB), KC_CLEAR, KC_KP_SLASH, KC_KP_ASTERISK, KC_CIRCUMFLEX, KC_LPRN, KC_NO,
+ KC_TAB, KC_KP_7, KC_KP_8, KC_KP_9, KC_KP_PLUS, KC_RPRN, KC_NO,
+ KC_KP_4, KC_KP_5, KC_KP_6, KC_KP_MINUS, KC_NO, KC_NO,
+ KC_KP_ENTER, KC_KP_1, KC_KP_2, KC_KP_3, KC_KP_EQUAL, KC_NO, KC_NO,
+ KC_KP_0, KC_KP_DOT, KC_KP_COMMA, KC_TRNS, KC_NO,
+ KC_NO, KC_NO,
+ KC_NO,
+ KC_NO, KC_TRNS, KC_NO),
+
+/* Keymap 2: Functions Layer
+ *
+ * ,-----------------------------------------------------. ,-----------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | F6 | | F7 | F8 | F9 | F10 | F11 | F12 | Vol. Up |
+ * |-----------+------+------+------+------+-------------| |------+------+------+------+------+------+-----------|
+ * | | Stop | Rw | Rec | FF | | XXXX | | XXXX | | | | | | Vol. Down |
+ * |-----------+------+------+------+------+------| XXXX | | XXXX |------+------+------+------+------+-----------|
+ * | CapsLock | Eject| Prev | Play | Next | |------| |------| Left | Down | Up | Right| | Mute |
+ * |-----------+------+------+------+------+------| XXXX | | XXXX |------+------+------+------+------+-----------|
+ * | L Shift | | | | | | XXXX | | XXXX | | | | | | R Shift |
+ * `-----------+------+------+------+------+-------------' `-------------+------+------+------+------+-----------'
+ * | XXXXX | | XXXX | XXXX | XXXX | | XXXX | XXXX | XXXX | | XXXXX |
+ * `-----------------------------------' `-----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ *
+ * XXX = These keys are transparent keys that, when pressed, they issue the key from the previous layer.
+ */
+[FN]=KEYMAP(//left half
+ KC_NO, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6,
+ KC_NO, KC_MEDIA_STOP, KC_MEDIA_REWIND, KC_MEDIA_SELECT, KC_MEDIA_FAST_FORWARD, KC_NO, KC_TRNS,
+ KC_CAPS, KC_MEDIA_EJECT, KC_MEDIA_PREV_TRACK, KC_MEDIA_PLAY_PAUSE, KC_MEDIA_NEXT_TRACK, KC_NO,
+ KC_LSFT, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_TRNS,
+ KC_TRNS, KC_NO, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_NO, KC_NO,
+ KC_NO,
+ KC_NO, KC_NO, KC_NO,
+ //right half
+ KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_VOLU,
+ KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_VOLD,
+ KC_LEFT, KC_DOWN, KC_UP, KC_RIGHT, KC_NO, KC_MUTE,
+ KC_TRNS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_RSFT,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_NO, KC_TRNS,
+ KC_NO, KC_NO,
+ KC_NO,
+ KC_NO, KC_NO, KC_NO)};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_ONESHOT(FN),
+ [2] = ACTION_MODS_ONESHOT(MOD_LSFT), // Sticky shift light. Tap for the next keypress to be shifted. Hold for regular shift.
+ [3] = ACTION_LAYER_TAP_KEY(KEYPAD, KC_RBRC),
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) {
+ // MACRODOWN only works in this function
+ switch(id) {
+ case MACRO_TMUX_ESC:
+ if (record->event.pressed) {
+ return MACRO(D(LCTRL), T(A), U(LCTRL), D(ESC), END);
+ }
+ return MACRO(U(ESC), END);
+ case MACRO_TMUX_PASTE:
+ if (record->event.pressed) {
+ return MACRO(D(LCTRL), T(A), U(LCTRL), D(P), END);
+ }
+ return MACRO(U(P), END);
+ case MACRO_OSX_COPY:
+ if (record->event.pressed) {
+ return MACRO(D(LGUI), D(C), END);
+ }
+ return MACRO(U(C), U(LGUI), END);
+ case MACRO_OSX_PASTE:
+ if (record->event.pressed) {
+ return MACRO(D(LGUI), D(V), END);
+ }
+ return MACRO(U(V), U(LGUI), END);
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+};
+
+uint8_t current_layer = BASE;
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_led_all_off();
+ ergodox_led_all_set(LED_BRIGHTNESS_LO);
+
+ switch (layer) {
+ case BASE:
+ current_layer = BASE;
+ break;
+ case KEYPAD:
+ current_layer = KEYPAD;
+ break;
+ default:
+ // none
+ break;
+ }
+
+ // layer leds
+ if (current_layer == KEYPAD) {
+ ergodox_right_led_3_on();
+ }
+
+ // capslock
+ if (host_keyboard_leds() & (3<<USB_LED_CAPS_LOCK)) {
+ ergodox_right_led_1_on();
+ }
+
+ // Temporary leds
+
+ // The function layer takes over other layers and we need to reflect that on the leds.
+ // If the current layer is the BASE, we simply turn on the FN led, but if the current
+ // layer is the KEYPAD, than we must turn it off before turning on the FN led.
+ if (layer == FN && !has_oneshot_layer_timed_out()) {
+ ergodox_right_led_3_off();
+ ergodox_right_led_2_on();
+ }
+
+ // if the shifted is pressed I show the case led in a brighter color. This is nice to
+ // differenciate the shift from the capslock.
+ // Notice that I make sure that we're not using the shift on a chord shortcut (pressing
+ // shift togather with other modifiers).
+ if((keyboard_report->mods & (MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)) && // is shift pressed and there is no other
+ !(keyboard_report->mods & (~MOD_BIT(KC_LSFT) & ~MOD_BIT(KC_RSFT)))) || // modifier being pressed as well
+ (get_oneshot_mods() & (MOD_BIT(KC_LSFT) | MOD_BIT(KC_RSFT)) && !has_oneshot_mods_timed_out())) { // or the one shot shift didn't timed out
+ ergodox_right_led_1_set(LED_BRIGHTNESS_HI);
+ ergodox_right_led_1_on();
+ }
+};
diff --git a/keyboards/ergodox_ez/keymaps/townk_osx/makefile.mk b/keyboards/ergodox_ez/keymaps/townk_osx/makefile.mk
new file mode 100644
index 000000000..e757557bd
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/townk_osx/makefile.mk
@@ -0,0 +1,4 @@
+# I don't want my keyboard blinking lights when is suppose to be asleep.
+SLEEP_LED_ENABLE = no
+
+CONFIG_H = keymaps/$(KEYMAP)/config.h
diff --git a/keyboards/ergodox_ez/keymaps/townk_osx/readme.md b/keyboards/ergodox_ez/keymaps/townk_osx/readme.md
new file mode 100644
index 000000000..c2853ca17
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/townk_osx/readme.md
@@ -0,0 +1,77 @@
+# Townk's Keymap
+
+Trying to take care of an enjury on my arm I borrow an ergonomic keyboard from
+a frient ([Kinesis Advantage](http://www.kinesis-ergo.com/shop/advantage-pro-for-pc-mac/)).
+
+I really enjoyed my time with it but there were some anoyancies:
+
+* The curvature on the keys bothered me since I'm a Vim user and using the
+ motion keys on my editor was awkard.
+* I had to spend too much time remapping the keyboard to make some symbol keys
+ more accessible to me.
+* The fact that my hands had to stay close to each other was a bit stressfull
+ to my sholders.
+
+After a long research I find out that Ergodox EZ would be perfect for my needs
+and purchase one. Before the keyboard even got in my hands I started to think
+on the layout I would use on it and soon enough I planed couple adjustments
+from the Kinesis I was using so far.
+
+## The layout
+
+Here are the layout mapping in images so you can have a glimpse on it:
+
+![Base Layout](townk_osx_base.png)
+![fn Layout](townk_osx_fn.png)
+![Keypad & Mouse Layout](townk_osx_keypad.png)
+
+Notice that, differently from the default behavior, my layer keys are not transparent
+by default, which means that if you press any non-labeled white key, nothing will be
+handled to the OS.
+
+### One shot keys
+
+It all started with the access to the function keys (F1, F2, F3...), since
+those keys are located on a different layer I needed a way to press them with
+minimal effort without disrupting my flow.
+
+For me, togglihg a layer to press a button and than toggle it back is a waste
+of time (although I admit it's a single tap from what I have), so I decided to
+do it as a one shot key. I could press it and the next pressed key would be
+handled by the target layer which just after it delivers the key to the OS it
+would get back to the previous layer.
+
+After setting up my layout to do just that I realized that occasionally I
+would stop myseld on the middle of the process and the one shot layer would be
+still triggered until I press any other key. So to prevent me from tapping
+keys I don't want I added a timeout of 3 seconds for the one shot actions.
+
+Ultimately I tested the shift key as a one shot one and really like it, so
+here you have it, all the one shot keys on my layout.
+
+## Glossary
+
+If you're not familiar with the Mac symbols used on some keys, here is a
+reference to them:
+
+| Symbol | Description |
+| :----: | ------------------- |
+| ⌘ | Command |
+| ⇪ | Caps Lock |
+| ⇧ | Shift |
+| ⌥ | Option (alt) |
+| ⎋ | Esc |
+| ⇥ | Tab forward |
+| ⇤ | Tab backward |
+| ⌃ | Control |
+| ␣ | Space |
+| ⌫ | Backspace |
+| ⌦ | Delete |
+| ⏎ | Enter |
+| ⌤ | Return |
+| ⌽ | Power on/off button |
+| ↖ | Home |
+| ↘ | End |
+| ⇞ | Page up |
+| ⇟ | Page down |
+| ⌧ | Clear |
diff --git a/keyboards/ergodox_ez/keymaps/townk_osx/townk_osx_base.png b/keyboards/ergodox_ez/keymaps/townk_osx/townk_osx_base.png
new file mode 100644
index 000000000..f9bc8b443
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/townk_osx/townk_osx_base.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/townk_osx/townk_osx_fn.png b/keyboards/ergodox_ez/keymaps/townk_osx/townk_osx_fn.png
new file mode 100644
index 000000000..983b72348
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/townk_osx/townk_osx_fn.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/townk_osx/townk_osx_keypad.png b/keyboards/ergodox_ez/keymaps/townk_osx/townk_osx_keypad.png
new file mode 100644
index 000000000..8f04b4327
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/townk_osx/townk_osx_keypad.png
Binary files differ
diff --git a/keyboards/ergodox_ez/keymaps/twey/keymap.c b/keyboards/ergodox_ez/keymaps/twey/keymap.c
new file mode 100644
index 000000000..019930f2a
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/twey/keymap.c
@@ -0,0 +1,221 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+#include "keymap_plover.h"
+
+#define BASE 0 // default layer
+#define SYMB 1 // symbols
+#define STEN 2 // steno
+#define MDIA 3 // media keys
+
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,---------------------------------------------------. ,---------------------------------------------------.
+ * | = | 1 | 2 | 3 | 4 | 5 | STEN | | NONE | 6 | 7 | 8 | 9 | 0 | \ |
+ * |--------+------+------+------+-------+-------------| |-------+------+------+------+------+------+--------|
+ * | Del | ' | , | . | P | Y | Esc | | Caps | F | G | C | R | L | / |
+ * |--------+------+------+------+-------+------| | | |------+------+------+------+------+--------|
+ * | BkSp | A | O | E | U | I |------| |-------| D | H | T | N | S | - |
+ * |--------+------+------+------+-------+------| Tab | | Enter |------+------+------+------+------+--------|
+ * | LShift | ; | Q | J | K | X | | | | B | M | W | V | Z | RShift |
+ * `--------+------+------+------+-------+-------------' `--------------+------+------+------+------+--------'
+ * | L1 | NONE | Grv | Left | Right | | Up | Down | [ | ] | L1 |
+ * `-----------------------------------' `----------------------------------'
+ * ,--------------. ,---------------.
+ * | PgUp | PgDn | | Home | End |
+ * ,------|-------|------| |-------+-------+------.
+ * | | | NONE | | AltGr | | |
+ * | Alt | Enter |------| |-------| Space | Ctrl |
+ * | | | Supr | | ~MDIA | | |
+ * `---------------------' `----------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_EQL, KC_1, KC_2, KC_3, KC_4, KC_5, M(0),
+ KC_DELT, KC_QUOT, KC_COMM,KC_DOT, KC_P, KC_Y, KC_ESC,
+ KC_BSPC, KC_A, KC_O, KC_E, KC_U, KC_I,
+ KC_LSFT, KC_SCLN, KC_Q, KC_J, KC_K, KC_X, KC_TAB,
+ MO(SYMB), KC_NO, KC_GRV, KC_LEFT,KC_RGHT,
+ KC_PGUP,KC_PGDN,
+ KC_NO,
+ KC_LALT,KC_ENT ,KC_LGUI,
+ // right hand
+ KC_NO, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSLS,
+ KC_CAPS, KC_F, KC_G, KC_C, KC_R, KC_L, KC_SLSH,
+ KC_D, KC_H, KC_T, KC_N, KC_S, KC_MINS,
+ KC_ENT, KC_B, KC_M, KC_W, KC_V, KC_Z , KC_RSFT,
+ KC_UP, KC_DOWN,KC_LBRC,KC_RBRC, MO(SYMB),
+ KC_HOME, KC_END,
+ KC_RALT,
+ MO(MDIA),KC_SPC,KC_RCTL
+ ),
+/* Keymap 1: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | ! | @ | { | } | | | | | | Up | 7 | 8 | 9 | * | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | # | $ | ( | ) | ` |------| |------| Down | 4 | 5 | 6 | + | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | % | ^ | [ | ] | ~ | | | | & | 1 | 2 | 3 | \ | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | . | 0 | = | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[SYMB] = KEYMAP(
+ // left hand
+ KC_TRNS,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS,KC_EXLM,KC_AT, KC_LCBR,KC_RCBR,KC_PIPE,KC_TRNS,
+ KC_TRNS,KC_HASH,KC_DLR, KC_LPRN,KC_RPRN,KC_GRV,
+ KC_TRNS,KC_PERC,KC_CIRC,KC_LBRC,KC_RBRC,KC_TILD,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_UP, KC_7, KC_8, KC_9, KC_ASTR, KC_F12,
+ KC_DOWN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS,
+ KC_TRNS, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS, KC_TRNS,
+ KC_TRNS,KC_DOT, KC_0, KC_EQL, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+
+[STEN] = KEYMAP( // layout: layer 2: Steno for Plover
+ // left hand
+ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_TRNS,
+ KC_NO, PV_NUM, PV_NUM, PV_NUM, PV_NUM, PV_NUM, PV_STAR,
+ KC_NO, PV_LS, PV_LT, PV_LP, PV_LH, PV_STAR,
+ KC_NO, PV_LS, PV_LK, PV_LW, PV_LR, PV_STAR, PV_STAR,
+ KC_TRNS,KC_NO, KC_NO, KC_TRNS, KC_TRNS,
+ KC_NO, KC_NO,
+ KC_NO,
+ PV_A, PV_O, KC_NO,
+ // right hand
+ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
+ PV_STAR, PV_NUM, PV_NUM, PV_NUM, PV_NUM, PV_NUM, PV_NUM,
+ PV_STAR, PV_RF, PV_RP, PV_RL, PV_RT, PV_RD,
+ PV_STAR, PV_STAR, PV_RR, PV_RB, PV_RG, PV_RS, PV_RZ,
+ KC_TRNS, KC_TRNS, KC_NO, KC_NO, KC_TRNS,
+ KC_NO, KC_NO,
+ KC_NO,
+ KC_TRNS,PV_E, PV_U
+),
+
+/* Keymap 3: Media and mouse keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | MsUp | | | | | | | Back | | Frwd | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | |MsLeft|MsDown|MsRght| |------| |------| | Prev | Play | Next | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | | | | | | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | Lclk | Rclk | |VolUp |VolDn | Mute | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// MEDIA AND MOUSE
+[MDIA] = KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_WBAK, KC_TRNS, KC_WFWD, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_MPRV, KC_MPLY, KC_MNXT, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_WBAK
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(MDIA) // FN1 - Momentary Layer 3 (Media)
+};
+
+void toggle_steno(int pressed)
+{
+ uint8_t layer = biton32(layer_state);
+
+ if (pressed) {
+ if (layer != STEN) layer_on(STEN); else layer_off(STEN);
+
+ register_code(PV_LP);
+ register_code(PV_LH);
+ register_code(PV_LR);
+ register_code(PV_O);
+ register_code(PV_RL);
+ register_code(PV_RG);
+ } else {
+ unregister_code(PV_LP);
+ unregister_code(PV_LH);
+ unregister_code(PV_LR);
+ unregister_code(PV_O);
+ unregister_code(PV_RL);
+ unregister_code(PV_RG);
+ }
+}
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ toggle_steno(record->event.pressed);
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+ uint32_t layer0 = layer_state & (1UL << 0),
+ layer1 = layer_state & (1UL << 1),
+ layer2 = layer_state & (1UL << 2),
+ layer3 = layer_state & (1UL << 3);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+
+ if (layer1) ergodox_right_led_1_on();
+ if (layer2) ergodox_right_led_2_on();
+ if (layer3) ergodox_right_led_3_on();
+};
diff --git a/keyboards/ergodox_ez/keymaps/twey/readme.md b/keyboards/ergodox_ez/keymaps/twey/readme.md
new file mode 100644
index 000000000..979e4261e
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/twey/readme.md
@@ -0,0 +1,17 @@
+# Twey's Home Configuration
+## Layers
+- Layer 0: Non-ANSI Dvorak layout, with modified modifiers — all
+ modifiers on thumb keys, as well as return and space.
+- Layer 1: Default symbol layout.
+- Layer 2: Plover-oriented stenography layer.
+- Layer 3: Extended media/mouse layout.
+
+## Unusual features
+The Plover key (top right key on the left half) also sends my Plover
+‘toggle’ chord (SH-FT) when pressed, as well as toggling the steno
+layer, so you can toggle between steno and typing modes with a single
+keypress.
+
+If you want to use this feature, you'll need to add the
+`commands.json` dictionary to your Plover dictionaries, or define the
+toggle stroke (`PHROLG`) yourself.
diff --git a/keyboards/ergodox_ez/keymaps/workman_osx_mdw/keymap.c b/keyboards/ergodox_ez/keymaps/workman_osx_mdw/keymap.c
new file mode 100644
index 000000000..8effa53b2
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/workman_osx_mdw/keymap.c
@@ -0,0 +1,366 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+// readme
+// This keyboard layout is based on the [Workman Dead layout](https://github.com/ojbucao/Workman/tree/master/mac#workman-dead-for-programmers), which uses the comma as a dead key to trigger a second layer.
+// Since I have more keys at my disposal on the ErgoDox, I moved the dead key to the bottom right. There are still a lot of
+// blanks so still discovering what I like.
+// If you aren't familiar with a dead key, the idea is that you tap the dead key which switches the layout. the next key you hit
+// triggers the key you pressed AND switches the layout back to the original. For now I do this with a super kludgey macro and I
+// look forward to learning about a more elegant way to do the same thing. Until then, this will have to do.
+
+
+// TODO: Define layer names that make sense for the ErgoDox EZ.
+#define BASE 0 // default layer
+#define SYMB 1 // symbols
+#define MDIA 2 // media keys
+#define DEAD 3 // dead version of the symbols layer
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | ` | 1 | 2 | 3 | 4 | 5 | LEFT | | RIGHT| 6 | 7 | 8 | 9 | 0 | - |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | Tab | Q | D | R | W | B | L1 | | L1 | J | F | U | P | ; | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | Hyper | A | S | H | T | G |------| |------| Y | N | E | O | I | ' |
+ * |--------+------+------+------+------+------| | | Meh |------+------+------+------+------+--------|
+ * | LShift | Z | X | M | C | V | | | | K | L | , | . |//Ctrl| RShift |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | CTRL | OPT | CMD | | Left | Down | Up | Right| L3 |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+--------+------.
+ * | | | Home | | PgUp | | |
+ * |Bckspc| Space|------| |------| Space |Enter |
+ * | | | End | | PgDn | | |
+ * `--------------------' `----------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_LEFT,
+ KC_TAB, KC_Q, KC_D, KC_R, KC_W, KC_B, TG(1),
+ ALL_T(KC_ESC), KC_A, KC_S, KC_H, KC_T, KC_G,
+ KC_LSFT, KC_Z, KC_X, KC_M, KC_C, KC_V, KC_NO,
+ KC_NO, KC_NO, KC_LCTL,KC_LALT,KC_LGUI,
+ KC_NO, KC_NO,
+ KC_HOME,
+ KC_BSPC,KC_SPC,KC_END,
+ // right hand
+ KC_RGHT, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
+ TG(1), KC_J, KC_F, KC_U, KC_P, KC_SCLN, KC_BSLS,
+ KC_Y, KC_N, KC_E, KC_O, KC_I, KC_QUOT,
+ MEH_T(KC_NO),KC_K, KC_L, KC_COMM,KC_DOT, CTL_T(KC_SLSH), KC_RSFT,
+ KC_LEFT,KC_DOWN,KC_UP, KC_RGHT, KC_FN4,
+ KC_NO, KC_NO,
+ KC_PGUP,
+ KC_PGDN,KC_SPC,KC_ENT
+ ),
+/* Keymap 1: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | % | & | ? | + | @ | | | | $ | _ | [ | ] | ! | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | / | ( | = | 0 | { |------| |------| } | 1 | * | ) | - | " |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | 6 | 7 | 8 | 9 | | | | | | \ | 2 | 3 | 4 | 5 | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | | | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[SYMB] = KEYMAP(
+ // left hand
+ KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS, KC_PERC, KC_AMPR, LSFT(KC_SLSH), LSFT(KC_EQL), KC_AT, KC_TRNS,
+ KC_TRNS, KC_SLSH, KC_LPRN, KC_EQL, KC_0, LSFT(KC_LBRC),
+ KC_TRNS, KC_6, KC_7, KC_8, KC_9, KC_PIPE, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_DLR, KC_UNDERSCORE, KC_LBRC, KC_RBRC, KC_EXLM, KC_F12,
+ KC_RCBR, KC_1, KC_ASTR, KC_RPRN, KC_MINS, KC_QUOT,
+ KC_TRNS, KC_SLSH, KC_2, KC_3, KC_4, KC_5, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+/* Keymap 2: Media and mouse keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | | | | | | | | | | | | | | |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | MsUp | | | | | | | | | | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | |MsLeft|MsDown|MsRght| |------| |------| | | | | | Play |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | | | | Prev | Next | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | Lclk | Rclk | |VolUp |VolDn | Mute | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | |Brwser|
+ * | | |------| |------| |Back |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// MEDIA AND MOUSE
+[MDIA] = KEYMAP(
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MS_U, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_BTN1, KC_BTN2,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_MPRV, KC_MNXT, KC_TRNS, KC_TRNS,
+ KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_WBAK
+),
+/* Keymap 4: Dead Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | % | & | ? | + | @ | | | | $ | _ | [ | ] | ! | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | / | ( | = | 0 | { |------| |------| } | 1 | * | ) | - | " |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | 6 | 7 | 8 | 9 | | | | | | \ | 2 | 3 | 4 | 5 | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | | | | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | | | |
+ * | | |------| |------| | |
+ * | | | | | | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[DEAD] = KEYMAP(
+ // left hand
+ KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS, M(100), M(101), M(102), M(103), M(104), KC_TRNS,
+ KC_TRNS, M(109), M(110), M(111), M(112), M(113),
+ KC_TRNS, M(120), M(121), M(122), M(123), M(124), KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, M(105), M(106), M(107), M(108), M(130), KC_F12,
+ M(114), M(115), M(116), M(117), M(118), M(119),
+ KC_TRNS, M(125), M(126), M(127), M(128), M(129), KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(SYMB), // FN1 - Momentary Layer 1 (Symbols)
+ [2] = ACTION_LAYER_ON(BASE,0), // FN2 - Go back to the base layer
+ [3] = ACTION_LAYER_ON(DEAD,0),
+ [4] = ACTION_LAYER_TOGGLE(DEAD),
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ case 100:
+ layer_clear();
+ return MACRODOWN(D(LSFT), T(5), U(LSFT), T(FN4), END);
+ break;
+ case 101:
+ layer_clear();
+ return MACRODOWN(D(LSFT), T(7), U(LSFT), T(FN4), END);
+ break;
+ case 102:
+ layer_clear();
+ return MACRODOWN(D(LSFT), T(SLSH), U(LSFT), T(FN4), END);
+ break;
+ case 103:
+ layer_clear();
+ return MACRODOWN(D(LSFT), T(EQL), U(LSFT), T(FN4), END);
+ break;
+ case 104:
+ layer_clear();
+ return MACRODOWN(D(LSFT), T(2), U(LSFT), T(FN4), END);
+ break;
+ case 105:
+ layer_clear();
+ return MACRODOWN(D(LSFT), T(4), U(LSFT), T(FN4), END);
+ break;
+ case 106:
+ layer_clear();
+ return MACRODOWN(D(LSFT), T(MINS), U(LSFT), T(FN4), END);
+ break;
+ case 107:
+ layer_clear();
+ return MACRODOWN(T(LBRC), T(FN4), END);
+ break;
+ case 108:
+ layer_clear();
+ return MACRODOWN(T(RBRC), T(FN4), END);
+ break;
+ case 130:
+ layer_clear();
+ return MACRODOWN(D(LSFT), T(1), U(LSFT), T(FN4), END);
+ break;
+ case 109:
+ layer_clear();
+ return MACRODOWN(T(SLSH), T(FN4), END);
+ break;
+ case 110:
+ layer_clear();
+ return MACRODOWN(D(LSFT), T(9), U(LSFT), T(FN4), END);
+ break;
+ case 111:
+ layer_clear();
+ return MACRODOWN(T(EQL), T(FN4), END);
+ break;
+ case 112:
+ layer_clear();
+ return MACRODOWN(T(0), T(FN4), END);
+ break;
+ case 113:
+ layer_clear();
+ return MACRODOWN(D(LSFT), T(LBRC), U(LSFT), T(FN4), END);
+ break;
+ case 114:
+ layer_clear();
+ return MACRODOWN(D(LSFT), T(RBRC), U(LSFT), T(FN4), END);
+ break;
+ case 115:
+ layer_clear();
+ return MACRODOWN(T(1), T(FN4), END);
+ break;
+ case 116:
+ layer_clear();
+ return MACRODOWN(D(LSFT), T(8), U(LSFT), T(FN4), END);
+ break;
+ case 117:
+ layer_clear();
+ return MACRODOWN(D(LSFT), T(0), U(LSFT), T(FN4), END);
+ break;
+ case 118:
+ layer_clear();
+ return MACRODOWN(T(MINS), T(FN4), END);
+ break;
+ case 119:
+ layer_clear();
+ return MACRODOWN(D(LSFT), T(QUOT), U(LSFT), T(FN4), END);
+ break;
+ case 120:
+ layer_clear();
+ return MACRODOWN(T(6), T(FN4), END);
+ break;
+ case 121:
+ layer_clear();
+ return MACRODOWN(T(7), T(FN4), END);
+ break;
+ case 122:
+ layer_clear();
+ return MACRODOWN(T(8), T(FN4), END);
+ break;
+ case 123:
+ layer_clear();
+ return MACRODOWN(T(9), T(FN4), END);
+ break;
+ case 124:
+ layer_clear();
+ return MACRODOWN(D(LSFT), T(BSLS), U(LSFT), T(FN4), END);
+ break;
+ case 125:
+ layer_clear();
+ return MACRODOWN(T(BSLS), T(FN4), END);
+ break;
+ case 126:
+ layer_clear();
+ return MACRODOWN(T(2), T(FN4), END);
+ break;
+ case 127:
+ layer_clear();
+ return MACRODOWN(T(3), T(FN4), END);
+ break;
+ case 128:
+ layer_clear();
+ return MACRODOWN(T(4), T(FN4), END);
+ break;
+ case 129:
+ layer_clear();
+ return MACRODOWN(T(5), T(FN4), END);
+ break;
+
+ default:
+ return MACRO_NONE;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case 1:
+ ergodox_right_led_1_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/zweihander-osx/keymap.c b/keyboards/ergodox_ez/keymaps/zweihander-osx/keymap.c
new file mode 100644
index 000000000..3444152bc
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/zweihander-osx/keymap.c
@@ -0,0 +1,233 @@
+#include "ergodox_ez.h"
+#include "debug.h"
+#include "action_layer.h"
+
+#define BASE 0 // default layer
+#define SYMB 1 // symbols
+#define MDIA 2 // media keys
+
+#define SGWK 0 // "sagewick", ⌘S ⌘⇥
+#define SGWF 1 // "sagewick freshly", ⌘S ⌘⇥ ⌘R
+#define BBED 2 // BBEdit
+#define TMNL 3 // Terminal
+#define SAFA 4 // Safari
+#define ALFRED_LEAD_TIME 100 // time, in milliseconds, to let Alfred come to the fore and accept keyboard input
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* Keymap 0: Basic layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | = | 1 | 2 | 3 | 4 | 5 | L1 | | L1 | 6 | 7 | 8 | 9 | 0 | - |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | ⌦ | Q | W | E | R | T | ~L1 | | ~L1 | Y | U | I | O | P | \ |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | ⌫ | A | S | D | F | G |------| |------| H | J | K | L |; / L2| ' / L⌘ |
+ * |--------+------+------+------+------+------| L⌘ | | L⌘ |------+------+------+------+------+--------|
+ * | L⇧ | Z | X | C | V | B | | | | N | M | , | . | / / ⌃| R⇧ |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | L⌃ | L⌥ | L⌘ | ← | → | | ↑ | ↓ | [ | ] | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,---------------.
+ * | `~ | '" | | ⎋ | ⌫ |
+ * ,------|------|------| |------+--------+------.
+ * | | | PgUp | | PgDn | | |
+ * | | ⌫ |------| |------| ⇥ |Enter |
+ * | | | L⌥ | | L⌃ | | |
+ * `--------------------' `----------------------'
+ */
+// If it accepts an argument (i.e, is a function), it doesn't need KC_.
+// Otherwise, it needs KC_*
+[BASE] = KEYMAP( // layer 0 : default
+ // left hand
+ KC_EQL, KC_1, KC_2, KC_3, KC_4, KC_5, TG(SYMB),
+ KC_DELT, KC_Q, KC_W, KC_E, KC_R, KC_T, MO(SYMB),
+ KC_BSPC, KC_A, KC_S, KC_D, KC_F, KC_G,
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_LGUI,
+ KC_LCTL, KC_LALT, KC_LGUI,KC_LEFT,KC_RGHT,
+ KC_GRV, KC_QUOT,
+ KC_PGUP,
+ KC_SPC,KC_BSPC,KC_LALT,
+ // right hand
+ TG(SYMB), KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,
+ MO(SYMB), KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSLS,
+ KC_H, KC_J, KC_K, KC_L, LT(MDIA, KC_SCLN),GUI_T(KC_QUOT),
+ KC_LGUI, KC_N, KC_M, KC_COMM,KC_DOT, CTL_T(KC_SLSH), KC_RSFT,
+ KC_UP, KC_DOWN,KC_LBRC,KC_RBRC, KC_SPC ,
+ KC_ESC, KC_BSPC,
+ KC_PGDN,
+ KC_LCTL, KC_TAB, KC_ENT
+ ),
+/* Keymap 1: Symbol Layer
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F1 | F2 | F3 | F4 | F5 | | | | F6 | F7 | F8 | F9 | F10 | F11 |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | [ | ] | { | } | " | | | | / | 7 | 8 | 9 | * | F12 |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | < | > | ( | ) | ' |------| |------| - | 4 | 5 | 6 | + | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | | | | | | & | 1 | 2 | 3 | = | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | | 0 | . | ← | → | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | | | Home | | |
+ * | | |------| |------| | |
+ * | | | | | End | | |
+ * `--------------------' `--------------------'
+ */
+// SYMBOLS
+[SYMB] = KEYMAP(
+ // left hand
+ KC_TRNS,KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_TRNS,
+ KC_TRNS,KC_LBRC,KC_RBRC,KC_LCBR,KC_RCBR,KC_DQUO,KC_TRNS,
+ KC_TRNS,KC_LABK,KC_RABK,KC_LPRN,KC_RPRN,KC_QUOT,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,
+ KC_TRNS,KC_TRNS,
+ KC_TRNS,
+ KC_TRNS,KC_TRNS,KC_TRNS,
+ // right hand
+ KC_TRNS, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
+ KC_TRNS, KC_SLSH, KC_7, KC_8, KC_9, KC_ASTR, KC_F12,
+ KC_MINS, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS,
+ KC_TRNS, KC_AMPR, KC_1, KC_2, KC_3, KC_EQL, KC_TRNS,
+ KC_0, KC_DOT, KC_LEFT, KC_RGHT, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_HOME,
+ KC_END , KC_TRNS, KC_TRNS
+),
+/* Keymap 2: Media keys
+ *
+ * ,--------------------------------------------------. ,--------------------------------------------------.
+ * | | F14 | F15 | | | | | | ⌘Q | ⌘W | ⌘⇧` | ⌘` | | | Power |
+ * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
+ * | | | | PgUp |⌘S⌘⇥⌘R| Term | | | | ⌘] | ⌥⌘↑ | ↑ | ⌥⌘↓ | | |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | |Safari| PgDn | | |------| |------| ⌘[ | ← | ↓ | → | | ⏯ |
+ * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
+ * | | | | | |BBEdit| | | |L⇧+Spc| Spc | ⏮ | ⏭ | | |
+ * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
+ * | | | | | | |VolUp |VolDn | Mute | | |
+ * `----------------------------------' `----------------------------------'
+ * ,-------------. ,-------------.
+ * | | | | | |
+ * ,------|------|------| |------+------+------.
+ * | | | Home | | End | | |
+ * | | |------| |------| ⌘C | ⌘V |
+ * | | | | | ⌘X | | |
+ * `--------------------' `--------------------'
+ */
+// MEDIA AND MOUSE
+[MDIA] = KEYMAP(
+ KC_TRNS, KC_F14 , KC_F15 , KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, /* F14 dims screen, F15 brightens */
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_PGUP, M(SGWF), M(TMNL), KC_TRNS,
+ KC_TRNS, KC_TRNS, M(SAFA), KC_PGDN, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, M(BBED), KC_TRNS,
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_HOME,
+ KC_TRNS, KC_TRNS, KC_TRNS,
+ // right hand
+ LGUI(KC_Q), LGUI(KC_W), LGUI(LSFT(KC_GRV)), LGUI(KC_GRV), KC_TRNS, KC_TRNS, KC_PWR,
+ KC_TRNS, LGUI(KC_RBRC), LGUI(LALT(KC_UP)), KC_UP , LGUI(LALT(KC_DOWN)), KC_TRNS, KC_TRNS,
+ LGUI(KC_LBRC), KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS, KC_MPLY,
+ KC_TRNS, LSFT(KC_SPC), KC_SPC , KC_MPRV, KC_MNXT, KC_TRNS, KC_TRNS,
+ KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS,
+ KC_TRNS, KC_TRNS,
+ KC_TRNS,
+ LGUI(KC_X), LGUI(KC_C), LGUI(KC_V)
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_TOGGLE(SYMB) // FN1 - Momentary Layer 1 (Symbols)
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case SGWK:
+ if (record->event.pressed) {
+ return MACRO(
+ I(10),
+ D(LGUI), T(S), U(LGUI),
+ D(LGUI), T(TAB), U(LGUI),
+ END);
+ }
+ break;
+ case SGWF:
+ if (record->event.pressed) {
+ return MACRO(
+ I(10),
+ D(LGUI), T(S), U(LGUI),
+ D(LGUI), T(TAB), U(LGUI),
+ D(LGUI), T(R), U(LGUI),
+ END);
+ }
+ break;
+ case BBED:
+ if (record->event.pressed) {
+ return MACRO(
+ I(10),
+ D(LALT), T(SPC), U(LALT), W(ALFRED_LEAD_TIME),
+ T(B), T(B), T(E), T(D), T(I), T(T),
+ T(ENT),
+ END);
+ }
+ break;
+ case TMNL:
+ if (record->event.pressed) {
+ return MACRO(
+ I(10),
+ D(LALT), T(SPC), U(LALT), W(ALFRED_LEAD_TIME),
+ T(T), T(E), T(R), T(M), T(I), T(N), T(A), T(L),
+ T(ENT),
+ END);
+ }
+ break;
+ case SAFA:
+ if (record->event.pressed) {
+ return MACRO(
+ I(10),
+ D(LALT), T(SPC), U(LALT), W(ALFRED_LEAD_TIME),
+ T(S), T(A), T(F), T(A), T(R), T(I),
+ T(ENT),
+ END);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ // TODO: Make this relevant to the ErgoDox EZ.
+ case 1:
+ ergodox_right_led_1_on();
+ break;
+ case 2:
+ ergodox_right_led_2_on();
+ break;
+ default:
+ // none
+ break;
+ }
+
+};
diff --git a/keyboards/ergodox_ez/keymaps/zweihander-osx/readme.markdown b/keyboards/ergodox_ez/keymaps/zweihander-osx/readme.markdown
new file mode 100644
index 000000000..7bce7c690
--- /dev/null
+++ b/keyboards/ergodox_ez/keymaps/zweihander-osx/readme.markdown
@@ -0,0 +1,45 @@
+# The Zweihander Layout
+
+NB: the backtick (\`) is special in Markdown. If I write ⌘\` in this readme, I mean “command-backtick”, not “command-backslash-backtick”.
+
+This layout is tuned for people who…
+
+
+## use OS X
+
+This layout doesn’t make any concessions for Windows use. While it should work fine in Windows, I’m not about to devote precious keyboard space to Windows-specific shortcuts.
+
+
+## mouse left-handed while doing other things with the right hand
+
+I tend to have my mouse in my left hand, but I like to use my other hand to make things go faster. I’ve added a bunch of buttons to the media layer to speed up browsing in Safari and Finder:
+
+- Close Window (⌘W)
+- Back (⌘[)
+- Forward (⌘])
+- Open and Close Parent Folder (⌥⌘↓)
+- Go Up and Close Just-Left Folder (⌥⌘↑)
+- Cycle through open windows in current application (⌘\` and ⌘⇧\`)
+- Cycle through tabs in current window (⌥⇥ and ⌥⇧⇥)
+- Space (page down in browsers; Quick Look in the Finder)
+- Shift-Space (page up in web browsers)
+
+Because moving letter-by-letter is way slower than moving word-by-word, I added Option (⌥) to the bottommost button on the left side. This key can be held easily while holding ; (activate media layer) and pressing J and L to move left and right by word.
+
+
+## use lots of modifier keys in OS X menu-item shortcuts
+
+I wanted to preserve the feel of a number of shortcuts that involve pressing lots of modifier keys at once; this is why the bottom left of the keyboard has shift, control, option, and command in the usual spaces. Further, some common shortcuts I press have a key on the right side of the keyboard. These shortcuts include:
+
+- Empty Trash Without Asking for Confirmation (⇧⌥⌘⌫)
+- Shut Down Without Asking for Confirmation (⇧⌥⌘ power)
+
+
+## use Emacs-style shortcuts
+
+I press C-a, C-e, and C-k all the time. It’s difficult to press these key combinations with the control key on the bottom left and I’m too quick on the draw for the control function on the / key to work reliably, so the bottommost thumb button on the right side is another control key.
+
+
+## use spreadsheets
+
+All the common spreadsheet operations (+-*/=) are now on the right side of the symbol layer.
diff --git a/keyboards/ergodox_ez/matrix.c b/keyboards/ergodox_ez/matrix.c
new file mode 100644
index 000000000..9c1efa1d0
--- /dev/null
+++ b/keyboards/ergodox_ez/matrix.c
@@ -0,0 +1,370 @@
+/*
+
+Note for ErgoDox EZ customizers: Here be dragons!
+This is not a file you want to be messing with.
+All of the interesting stuff for you is under keymaps/ :)
+Love, Erez
+
+Copyright 2013 Oleg Kostyuk <cub.uanic@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * scan matrix
+ */
+#include <stdint.h>
+#include <stdbool.h>
+#include <avr/io.h>
+#include "wait.h"
+#include "action_layer.h"
+#include "print.h"
+#include "debug.h"
+#include "util.h"
+#include "matrix.h"
+#include "ergodox_ez.h"
+#include "i2cmaster.h"
+#ifdef DEBUG_MATRIX_SCAN_RATE
+#include "timer.h"
+#endif
+
+#ifndef DEBOUNCE
+# define DEBOUNCE 5
+#endif
+static uint8_t debouncing = DEBOUNCE;
+
+/* matrix state(1:on, 0:off) */
+static matrix_row_t matrix[MATRIX_ROWS];
+static matrix_row_t matrix_debouncing[MATRIX_ROWS];
+
+static matrix_row_t read_cols(uint8_t row);
+static void init_cols(void);
+static void unselect_rows(void);
+static void select_row(uint8_t row);
+
+static uint8_t mcp23018_reset_loop;
+
+#ifdef DEBUG_MATRIX_SCAN_RATE
+uint32_t matrix_timer;
+uint32_t matrix_scan_count;
+#endif
+
+
+__attribute__ ((weak))
+void matrix_init_user(void) {}
+
+__attribute__ ((weak))
+void matrix_scan_user(void) {}
+
+__attribute__ ((weak))
+void matrix_init_kb(void) {
+ matrix_init_user();
+}
+
+__attribute__ ((weak))
+void matrix_scan_kb(void) {
+ matrix_scan_user();
+}
+
+inline
+uint8_t matrix_rows(void)
+{
+ return MATRIX_ROWS;
+}
+
+inline
+uint8_t matrix_cols(void)
+{
+ return MATRIX_COLS;
+}
+
+void matrix_init(void)
+{
+ // initialize row and col
+
+ mcp23018_status = init_mcp23018();
+
+
+ unselect_rows();
+ init_cols();
+
+ // initialize matrix state: all keys off
+ for (uint8_t i=0; i < MATRIX_ROWS; i++) {
+ matrix[i] = 0;
+ matrix_debouncing[i] = 0;
+ }
+
+#ifdef DEBUG_MATRIX_SCAN_RATE
+ matrix_timer = timer_read32();
+ matrix_scan_count = 0;
+#endif
+
+ matrix_init_kb();
+
+}
+
+void matrix_power_up(void) {
+ mcp23018_status = init_mcp23018();
+
+ unselect_rows();
+ init_cols();
+
+ // initialize matrix state: all keys off
+ for (uint8_t i=0; i < MATRIX_ROWS; i++) {
+ matrix[i] = 0;
+ matrix_debouncing[i] = 0;
+ }
+
+#ifdef DEBUG_MATRIX_SCAN_RATE
+ matrix_timer = timer_read32();
+ matrix_scan_count = 0;
+#endif
+
+}
+
+uint8_t matrix_scan(void)
+{
+ if (mcp23018_status) { // if there was an error
+ if (++mcp23018_reset_loop == 0) {
+ // since mcp23018_reset_loop is 8 bit - we'll try to reset once in 255 matrix scans
+ // this will be approx bit more frequent than once per second
+ print("trying to reset mcp23018\n");
+ mcp23018_status = init_mcp23018();
+ if (mcp23018_status) {
+ print("left side not responding\n");
+ } else {
+ print("left side attached\n");
+ ergodox_blink_all_leds();
+ }
+ }
+ }
+
+#ifdef DEBUG_MATRIX_SCAN_RATE
+ matrix_scan_count++;
+
+ uint32_t timer_now = timer_read32();
+ if (TIMER_DIFF_32(timer_now, matrix_timer)>1000) {
+ print("matrix scan frequency: ");
+ pdec(matrix_scan_count);
+ print("\n");
+
+ matrix_timer = timer_now;
+ matrix_scan_count = 0;
+ }
+#endif
+
+ for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+ select_row(i);
+ wait_us(30); // without this wait read unstable value.
+ matrix_row_t cols = read_cols(i);
+ if (matrix_debouncing[i] != cols) {
+ matrix_debouncing[i] = cols;
+ if (debouncing) {
+ debug("bounce!: "); debug_hex(debouncing); debug("\n");
+ }
+ debouncing = DEBOUNCE;
+ }
+ unselect_rows();
+ }
+
+ if (debouncing) {
+ if (--debouncing) {
+ wait_us(1);
+ } else {
+ for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+ matrix[i] = matrix_debouncing[i];
+ }
+ }
+ }
+
+ matrix_scan_quantum();
+
+ return 1;
+}
+
+bool matrix_is_modified(void)
+{
+ if (debouncing) return false;
+ return true;
+}
+
+inline
+bool matrix_is_on(uint8_t row, uint8_t col)
+{
+ return (matrix[row] & ((matrix_row_t)1<<col));
+}
+
+inline
+matrix_row_t matrix_get_row(uint8_t row)
+{
+ return matrix[row];
+}
+
+void matrix_print(void)
+{
+ print("\nr/c 0123456789ABCDEF\n");
+ for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
+ phex(row); print(": ");
+ pbin_reverse16(matrix_get_row(row));
+ print("\n");
+ }
+}
+
+uint8_t matrix_key_count(void)
+{
+ uint8_t count = 0;
+ for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+ count += bitpop16(matrix[i]);
+ }
+ return count;
+}
+
+/* Column pin configuration
+ *
+ * Teensy
+ * col: 0 1 2 3 4 5
+ * pin: F0 F1 F4 F5 F6 F7
+ *
+ * MCP23018
+ * col: 0 1 2 3 4 5
+ * pin: B5 B4 B3 B2 B1 B0
+ */
+static void init_cols(void)
+{
+ // init on mcp23018
+ // not needed, already done as part of init_mcp23018()
+
+ // init on teensy
+ // Input with pull-up(DDR:0, PORT:1)
+ DDRF &= ~(1<<7 | 1<<6 | 1<<5 | 1<<4 | 1<<1 | 1<<0);
+ PORTF |= (1<<7 | 1<<6 | 1<<5 | 1<<4 | 1<<1 | 1<<0);
+}
+
+static matrix_row_t read_cols(uint8_t row)
+{
+ if (row < 7) {
+ if (mcp23018_status) { // if there was an error
+ return 0;
+ } else {
+ uint8_t data = 0;
+ mcp23018_status = i2c_start(I2C_ADDR_WRITE); if (mcp23018_status) goto out;
+ mcp23018_status = i2c_write(GPIOB); if (mcp23018_status) goto out;
+ mcp23018_status = i2c_start(I2C_ADDR_READ); if (mcp23018_status) goto out;
+ data = i2c_readNak();
+ data = ~data;
+ out:
+ i2c_stop();
+ return data;
+ }
+ } else {
+ // read from teensy
+ return
+ (PINF&(1<<0) ? 0 : (1<<0)) |
+ (PINF&(1<<1) ? 0 : (1<<1)) |
+ (PINF&(1<<4) ? 0 : (1<<2)) |
+ (PINF&(1<<5) ? 0 : (1<<3)) |
+ (PINF&(1<<6) ? 0 : (1<<4)) |
+ (PINF&(1<<7) ? 0 : (1<<5)) ;
+ }
+}
+
+/* Row pin configuration
+ *
+ * Teensy
+ * row: 7 8 9 10 11 12 13
+ * pin: B0 B1 B2 B3 D2 D3 C6
+ *
+ * MCP23018
+ * row: 0 1 2 3 4 5 6
+ * pin: A0 A1 A2 A3 A4 A5 A6
+ */
+static void unselect_rows(void)
+{
+ // unselect on mcp23018
+ if (mcp23018_status) { // if there was an error
+ // do nothing
+ } else {
+ // set all rows hi-Z : 1
+ mcp23018_status = i2c_start(I2C_ADDR_WRITE); if (mcp23018_status) goto out;
+ mcp23018_status = i2c_write(GPIOA); if (mcp23018_status) goto out;
+ mcp23018_status = i2c_write( 0xFF
+ & ~(0<<7)
+ ); if (mcp23018_status) goto out;
+ out:
+ i2c_stop();
+ }
+
+ // unselect on teensy
+ // Hi-Z(DDR:0, PORT:0) to unselect
+ DDRB &= ~(1<<0 | 1<<1 | 1<<2 | 1<<3);
+ PORTB &= ~(1<<0 | 1<<1 | 1<<2 | 1<<3);
+ DDRD &= ~(1<<2 | 1<<3);
+ PORTD &= ~(1<<2 | 1<<3);
+ DDRC &= ~(1<<6);
+ PORTC &= ~(1<<6);
+}
+
+static void select_row(uint8_t row)
+{
+ if (row < 7) {
+ // select on mcp23018
+ if (mcp23018_status) { // if there was an error
+ // do nothing
+ } else {
+ // set active row low : 0
+ // set other rows hi-Z : 1
+ mcp23018_status = i2c_start(I2C_ADDR_WRITE); if (mcp23018_status) goto out;
+ mcp23018_status = i2c_write(GPIOA); if (mcp23018_status) goto out;
+ mcp23018_status = i2c_write( 0xFF & ~(1<<row)
+ & ~(0<<7)
+ ); if (mcp23018_status) goto out;
+ out:
+ i2c_stop();
+ }
+ } else {
+ // select on teensy
+ // Output low(DDR:1, PORT:0) to select
+ switch (row) {
+ case 7:
+ DDRB |= (1<<0);
+ PORTB &= ~(1<<0);
+ break;
+ case 8:
+ DDRB |= (1<<1);
+ PORTB &= ~(1<<1);
+ break;
+ case 9:
+ DDRB |= (1<<2);
+ PORTB &= ~(1<<2);
+ break;
+ case 10:
+ DDRB |= (1<<3);
+ PORTB &= ~(1<<3);
+ break;
+ case 11:
+ DDRD |= (1<<2);
+ PORTD &= ~(1<<3);
+ break;
+ case 12:
+ DDRD |= (1<<3);
+ PORTD &= ~(1<<3);
+ break;
+ case 13:
+ DDRC |= (1<<6);
+ PORTC &= ~(1<<6);
+ break;
+ }
+ }
+}
+
diff --git a/keyboards/ergodox_ez/readme.md b/keyboards/ergodox_ez/readme.md
new file mode 100644
index 000000000..67a5fb095
--- /dev/null
+++ b/keyboards/ergodox_ez/readme.md
@@ -0,0 +1,44 @@
+# Getting started
+
+There are two main ways you could customize the ErgoDox EZ.
+
+## The Easy Way: Use an existing firmware file and just flash it
+
+1. Download and install the [Teensy Loader](https://www.pjrc.com/teensy/loader.html). Some Linux distributions already provide a binary (may be called `teensy-loader-cli`), so you may prefer to use this.
+2. Find a firmware file you like. You can find a few if these in the keymaps subdirectory right here. The file you need ends with .hex, and you can look at its .c counterpart (or its PNG image) to see what you'll be getting. You can also use the [Massdrop configurator](https://keyboard-configurator.massdrop.com/ext/ergodox) to create a firmware Hex file you like.
+3. Download the firmware file
+4. Connect the keyboard, press its Reset button (gently insert a paperclip into the hole in the top-right corner) and flash it using the Teensy loader you installed on step 1 and the firmware you downloaded.
+
+## More technical: create your own totally custom firmware by editing the source files.
+
+This requires a little bit of familiarity with coding.
+
+1. Go to https://github.com/jackhumbert/qmk_firmware and read the readme at the base of this repository, top to bottom. Then come back here :)
+2. Clone the repository (download it)
+3. Set up a build environment as per [the build guide](/doc/BUILD_GUIDE.md)
+ - Using a Mac and have homebrew? just run `brew tap osx-cross/avr && brew install avr-libc`
+4. Copy `keyboards/ergodox_ez/keymaps/default/keymap.c` into `keymaps/your_name/keymap.c` (for example, `keymaps/german/keymap.c`)
+5. Edit this file, changing keycodes to your liking (see "Finding the keycodes you need" below). Try to edit the comments as well, so the "text graphics" represent your layout correctly. See below for more tips on sharing your work.
+6. Compile your firmware by running `make keymap=your_name`. For example, `make keymap=german`. This will result in a hex file, which will be called `ergodox_ez_your_name.hex`, e.g. `ergodox_ez_german.hex`.
+6. Flash this hex file using the [Teensy loader](https://www.pjrc.com/teensy/loader.html) as described in step 4 in the "Easy Way" above. If you prefer you can automatically flash the hex file after successfull build by running `make teensy keymap=your_name`.
+7. Submit your work as a pull request to this repository, so others can also use it. :) See below on specifics.
+
+Good luck! :)
+
+## Contributing your keymap
+
+The ErgoDox EZ firmware is open-source, so it would be wonderful to have your contribution! Within a very short time after launching we already amassed almost 20 user-contributed keymaps, with all sorts of creative improvements and tweaks. This is very valuable for people who aren't comfortable coding, but do want to customize their ErgoDox EZ. To make it easy for these people to use your layout, I recommend submitting your PR in the following format.
+
+1. All work goes inside your keymap subdirectory (`keymaps/german` in this example).
+2. `keymap.c` - this is your actual keymap file; please update the ASCII comments in the file so they correspond with what you did.
+3. `readme.md` - a readme file, which GitHub would display by default when people go to your directory. Explain what's different about your keymap, what you tweaked or how it works. No specific format to follow, just communicate what you did. :)
+4. Any graphics you wish to add. This is absolutely not a must. If you feel like it, you can use [Keyboard Layout Editor](http://keyboard-layout-editor.com) to make something and grab a screenshot, but it's really not a must. If you do have graphics, your readme can just embed the graphic as a link, just like I did with the default layout.
+
+
+## Finding the keycodes you need
+
+Let's say you want a certain key in your layout to send a colon; to figure out what keycode to use to make it do that, you're going to need `quantum/keymap_common.h`.
+
+That file contains a big list of all of the special, fancy keys (like, being able to send % on its own and whatnot).
+
+If you want to send a plain vanilla key, you can look up its code under `doc/keycode.txt`. That's where all the boring keys hang out.
diff --git a/keyboards/ergodox_ez/twimaster.c b/keyboards/ergodox_ez/twimaster.c
new file mode 100644
index 000000000..f91c08e6e
--- /dev/null
+++ b/keyboards/ergodox_ez/twimaster.c
@@ -0,0 +1,208 @@
+/*************************************************************************
+* Title: I2C master library using hardware TWI interface
+* Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury
+* File: $Id: twimaster.c,v 1.3 2005/07/02 11:14:21 Peter Exp $
+* Software: AVR-GCC 3.4.3 / avr-libc 1.2.3
+* Target: any AVR device with hardware TWI
+* Usage: API compatible with I2C Software Library i2cmaster.h
+**************************************************************************/
+#include <inttypes.h>
+#include <compat/twi.h>
+
+#include <i2cmaster.h>
+
+
+/* define CPU frequency in Mhz here if not defined in Makefile */
+#ifndef F_CPU
+#define F_CPU 16000000UL
+#endif
+
+/* I2C clock in Hz */
+#define SCL_CLOCK 400000L
+
+
+/*************************************************************************
+ Initialization of the I2C bus interface. Need to be called only once
+*************************************************************************/
+void i2c_init(void)
+{
+ /* initialize TWI clock
+ * minimal values in Bit Rate Register (TWBR) and minimal Prescaler
+ * bits in the TWI Status Register should give us maximal possible
+ * I2C bus speed - about 444 kHz
+ *
+ * for more details, see 20.5.2 in ATmega16/32 secification
+ */
+
+ TWSR = 0; /* no prescaler */
+ TWBR = 10; /* must be >= 10 for stable operation */
+
+}/* i2c_init */
+
+
+/*************************************************************************
+ Issues a start condition and sends address and transfer direction.
+ return 0 = device accessible, 1= failed to access device
+*************************************************************************/
+unsigned char i2c_start(unsigned char address)
+{
+ uint8_t twst;
+
+ // send START condition
+ TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
+
+ // wait until transmission completed
+ while(!(TWCR & (1<<TWINT)));
+
+ // check value of TWI Status Register. Mask prescaler bits.
+ twst = TW_STATUS & 0xF8;
+ if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;
+
+ // send device address
+ TWDR = address;
+ TWCR = (1<<TWINT) | (1<<TWEN);
+
+ // wail until transmission completed and ACK/NACK has been received
+ while(!(TWCR & (1<<TWINT)));
+
+ // check value of TWI Status Register. Mask prescaler bits.
+ twst = TW_STATUS & 0xF8;
+ if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;
+
+ return 0;
+
+}/* i2c_start */
+
+
+/*************************************************************************
+ Issues a start condition and sends address and transfer direction.
+ If device is busy, use ack polling to wait until device is ready
+
+ Input: address and transfer direction of I2C device
+*************************************************************************/
+void i2c_start_wait(unsigned char address)
+{
+ uint8_t twst;
+
+
+ while ( 1 )
+ {
+ // send START condition
+ TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
+
+ // wait until transmission completed
+ while(!(TWCR & (1<<TWINT)));
+
+ // check value of TWI Status Register. Mask prescaler bits.
+ twst = TW_STATUS & 0xF8;
+ if ( (twst != TW_START) && (twst != TW_REP_START)) continue;
+
+ // send device address
+ TWDR = address;
+ TWCR = (1<<TWINT) | (1<<TWEN);
+
+ // wail until transmission completed
+ while(!(TWCR & (1<<TWINT)));
+
+ // check value of TWI Status Register. Mask prescaler bits.
+ twst = TW_STATUS & 0xF8;
+ if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) )
+ {
+ /* device busy, send stop condition to terminate write operation */
+ TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
+
+ // wait until stop condition is executed and bus released
+ while(TWCR & (1<<TWSTO));
+
+ continue;
+ }
+ //if( twst != TW_MT_SLA_ACK) return 1;
+ break;
+ }
+
+}/* i2c_start_wait */
+
+
+/*************************************************************************
+ Issues a repeated start condition and sends address and transfer direction
+
+ Input: address and transfer direction of I2C device
+
+ Return: 0 device accessible
+ 1 failed to access device
+*************************************************************************/
+unsigned char i2c_rep_start(unsigned char address)
+{
+ return i2c_start( address );
+
+}/* i2c_rep_start */
+
+
+/*************************************************************************
+ Terminates the data transfer and releases the I2C bus
+*************************************************************************/
+void i2c_stop(void)
+{
+ /* send stop condition */
+ TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
+
+ // wait until stop condition is executed and bus released
+ while(TWCR & (1<<TWSTO));
+
+}/* i2c_stop */
+
+
+/*************************************************************************
+ Send one byte to I2C device
+
+ Input: byte to be transfered
+ Return: 0 write successful
+ 1 write failed
+*************************************************************************/
+unsigned char i2c_write( unsigned char data )
+{
+ uint8_t twst;
+
+ // send data to the previously addressed device
+ TWDR = data;
+ TWCR = (1<<TWINT) | (1<<TWEN);
+
+ // wait until transmission completed
+ while(!(TWCR & (1<<TWINT)));
+
+ // check value of TWI Status Register. Mask prescaler bits
+ twst = TW_STATUS & 0xF8;
+ if( twst != TW_MT_DATA_ACK) return 1;
+ return 0;
+
+}/* i2c_write */
+
+
+/*************************************************************************
+ Read one byte from the I2C device, request more data from device
+
+ Return: byte read from I2C device
+*************************************************************************/
+unsigned char i2c_readAck(void)
+{
+ TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
+ while(!(TWCR & (1<<TWINT)));
+
+ return TWDR;
+
+}/* i2c_readAck */
+
+
+/*************************************************************************
+ Read one byte from the I2C device, read is followed by a stop condition
+
+ Return: byte read from I2C device
+*************************************************************************/
+unsigned char i2c_readNak(void)
+{
+ TWCR = (1<<TWINT) | (1<<TWEN);
+ while(!(TWCR & (1<<TWINT)));
+
+ return TWDR;
+
+}/* i2c_readNak */
diff --git a/keyboards/ergodox_ez/util/compile_keymap.py b/keyboards/ergodox_ez/util/compile_keymap.py
new file mode 100644
index 000000000..7076a6ecb
--- /dev/null
+++ b/keyboards/ergodox_ez/util/compile_keymap.py
@@ -0,0 +1,710 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+"""Compiler for keymap.c files
+
+This scrip will generate a keymap.c file from a simple
+markdown file with a specific layout.
+
+Usage:
+ python compile_keymap.py INPUT_PATH [OUTPUT_PATH]
+"""
+from __future__ import division
+from __future__ import print_function
+from __future__ import absolute_import
+from __future__ import unicode_literals
+
+import os
+import io
+import re
+import sys
+import json
+import unicodedata
+import collections
+import itertools as it
+
+PY2 = sys.version_info.major == 2
+
+if PY2:
+ chr = unichr
+
+
+KEYBOARD_LAYOUTS = {
+ # These map positions in the parsed layout to
+ # positions in the KEYMAP MATRIX
+ 'ergodox_ez': [
+ [ 0, 1, 2, 3, 4, 5, 6], [38, 39, 40, 41, 42, 43, 44],
+ [ 7, 8, 9, 10, 11, 12, 13], [45, 46, 47, 48, 49, 50, 51],
+ [14, 15, 16, 17, 18, 19 ], [ 52, 53, 54, 55, 56, 57],
+ [20, 21, 22, 23, 24, 25, 26], [58, 59, 60, 61, 62, 63, 64],
+ [27, 28, 29, 30, 31 ], [ 65, 66, 67, 68, 69],
+ [ 32, 33], [70, 71 ],
+ [ 34], [72 ],
+ [ 35, 36, 37], [73, 74, 75 ],
+ ]
+}
+
+ROW_INDENTS = {
+ 'ergodox_ez': [0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 5, 0, 6, 0, 4, 0]
+}
+
+BLANK_LAYOUTS = [
+# Compact Layout
+"""
+.------------------------------------.------------------------------------.
+| | | | | | | | | | | | | | |
+!-----+----+----+----+----+----------!-----+----+----+----+----+----+-----!
+| | | | | | | | | | | | | | |
+!-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+| | | | | | |-----!-----! | | | | | |
+!-----+----+----+----x----x----! ! !----x----x----+----+----+-----!
+| | | | | | | | | | | | | | |
+'-----+----+----+----+----+----------'----------+----+----+----+----+-----'
+ | | | | | | ! | | | | |
+ '------------------------' '------------------------'
+ .-----------. .-----------.
+ | | | ! | |
+ .-----+-----+-----! !-----+-----+-----.
+ ! ! | | ! | ! !
+ ! ! !-----! !-----! ! !
+ | | | | ! | | |
+ '-----------------' '-----------------'
+""",
+
+# Wide Layout
+"""
+.---------------------------------------------. .---------------------------------------------.
+| | | | | | | | ! | | | | | | |
+!-------+-----+-----+-----+-----+-------------! !-------+-----+-----+-----+-----+-----+-------!
+| | | | | | | | ! | | | | | | |
+!-------+-----+-----+-----x-----x-----! ! ! !-----x-----x-----+-----+-----+-------!
+| | | | | | |-------! !-------! | | | | | |
+!-------+-----+-----+-----x-----x-----! ! ! !-----x-----x-----+-----+-----+-------!
+| | | | | | | | ! | | | | | | |
+'-------+-----+-----+-----+-----+-------------' '-------------+-----+-----+-----+-----+-------'
+ | | | | | | ! | | | | |
+ '------------------------------' '------------------------------'
+ .---------------. .---------------.
+ | | | ! | |
+ .-------+-------+-------! !-------+-------+-------.
+ ! ! | | ! | ! !
+ ! ! !-------! !-------! ! !
+ | | | | ! | | |
+ '-----------------------' '-----------------------'
+""",
+]
+
+
+DEFAULT_CONFIG = {
+ "keymaps_includes": [
+ "keymap_common.h",
+ ],
+ 'filler': "-+.'!:x",
+ 'separator': "|",
+ 'default_key_prefix': ["KC_"],
+}
+
+
+SECTIONS = [
+ 'layout_config',
+ 'layers',
+]
+
+
+# Markdown Parsing
+
+ONELINE_COMMENT_RE = re.compile(r"""
+ ^ # comment must be at the start of the line
+ \s* # arbitrary whitespace
+ // # start of the comment
+ (.*) # the comment
+ $ # until the end of line
+""", re.MULTILINE | re.VERBOSE
+)
+
+INLINE_COMMENT_RE = re.compile(r"""
+ ([\,\"\[\]\{\}\d]) # anythig that might end a expression
+ \s+ # comment must be preceded by whitespace
+ // # start of the comment
+ \s # and succeded by whitespace
+ (?:[^\"\]\}\{\[]*) # the comment (except things which might be json)
+ $ # until the end of line
+""", re.MULTILINE | re.VERBOSE)
+
+TRAILING_COMMA_RE = re.compile(r"""
+ , # the comma
+ (?:\s*) # arbitrary whitespace
+ $ # only works if the trailing comma is followed by newline
+ (\s*) # arbitrary whitespace
+ ([\]\}]) # end of an array or object
+""", re.MULTILINE | re.VERBOSE)
+
+
+def loads(raw_data):
+ if isinstance(raw_data, bytes):
+ raw_data = raw_data.decode('utf-8')
+
+ raw_data = ONELINE_COMMENT_RE.sub(r"", raw_data)
+ raw_data = INLINE_COMMENT_RE.sub(r"\1", raw_data)
+ raw_data = TRAILING_COMMA_RE.sub(r"\1\2", raw_data)
+ return json.loads(raw_data)
+
+
+def parse_config(path):
+ def reset_section():
+ section.update({
+ 'name': section.get('name', ""),
+ 'sub_name': "",
+ 'start_line': -1,
+ 'end_line': -1,
+ 'code_lines': [],
+ })
+
+ def start_section(line_index, line):
+ end_section()
+ if line.startswith("# "):
+ name = line[2:]
+ elif line.startswith("## "):
+ name = line[3:]
+ else:
+ name = ""
+
+ name = name.strip().replace(" ", "_").lower()
+ if name in SECTIONS:
+ section['name'] = name
+ else:
+ section['sub_name'] = name
+ section['start_line'] = line_index
+
+ def end_section():
+ if section['start_line'] >= 0:
+ if section['name'] == 'layout_config':
+ config.update(loads("\n".join(
+ section['code_lines']
+ )))
+ elif section['sub_name'].startswith('layer'):
+ layer_name = section['sub_name']
+ config['layer_lines'][layer_name] = section['code_lines']
+
+ reset_section()
+
+ def amend_section(line_index, line):
+ section['end_line'] = line_index
+ section['code_lines'].append(line)
+
+ config = DEFAULT_CONFIG.copy()
+ config.update({
+ 'layer_lines': collections.OrderedDict(),
+ 'macro_ids': {'UM'},
+ 'unicode_macros': {},
+ })
+
+ section = {}
+ reset_section()
+
+ with io.open(path, encoding="utf-8") as fh:
+ for i, line in enumerate(fh):
+ if line.startswith("#"):
+ start_section(i, line)
+ elif line.startswith(" "):
+ amend_section(i, line[4:])
+ else:
+ # TODO: maybe parse description
+ pass
+
+ end_section()
+ assert 'layout' in config
+ return config
+
+# header file parsing
+
+IF0_RE = re.compile(r"""
+ ^
+ #if 0
+ $.*?
+ #endif
+""", re.MULTILINE | re.DOTALL | re.VERBOSE)
+
+
+COMMENT_RE = re.compile(r"""
+ /\*
+ .*?
+ \*/"
+""", re.MULTILINE | re.DOTALL | re.VERBOSE)
+
+
+def read_header_file(path):
+ with io.open(path, encoding="utf-8") as fh:
+ data = fh.read()
+ data, _ = COMMENT_RE.subn("", data)
+ data, _ = IF0_RE.subn("", data)
+ return data
+
+
+def regex_partial(re_str_fmt, flags):
+ def partial(*args, **kwargs):
+ re_str = re_str_fmt.format(*args, **kwargs)
+ return re.compile(re_str, flags)
+ return partial
+
+
+KEYDEF_REP = regex_partial(r"""
+ #define
+ \s
+ (
+ (?:{}) # the prefixes
+ (?:\w+) # the key name
+ ) # capture group end
+""", re.MULTILINE | re.DOTALL | re.VERBOSE)
+
+
+ENUM_RE = re.compile(r"""
+ (
+ enum
+ \s\w+\s
+ \{
+ .*? # the enum content
+ \}
+ ;
+ ) # capture group end
+""", re.MULTILINE | re.DOTALL | re.VERBOSE)
+
+
+ENUM_KEY_REP = regex_partial(r"""
+ (
+ {} # the prefixes
+ \w+ # the key name
+ ) # capture group end
+""", re.MULTILINE | re.DOTALL | re.VERBOSE)
+
+
+def parse_keydefs(config, data):
+ prefix_options = "|".join(config['key_prefixes'])
+ keydef_re = KEYDEF_REP(prefix_options)
+ enum_key_re = ENUM_KEY_REP(prefix_options)
+ for match in keydef_re.finditer(data):
+ yield match.groups()[0]
+
+ for enum_match in ENUM_RE.finditer(data):
+ enum = enum_match.groups()[0]
+ for key_match in enum_key_re.finditer(enum):
+ yield key_match.groups()[0]
+
+
+def parse_valid_keys(config, out_path):
+ basepath = os.path.abspath(os.path.join(os.path.dirname(out_path)))
+ dirpaths = []
+ subpaths = []
+ while len(subpaths) < 6:
+ path = os.path.join(basepath, *subpaths)
+ dirpaths.append(path)
+ dirpaths.append(os.path.join(path, "tmk_core", "common"))
+ dirpaths.append(os.path.join(path, "quantum"))
+ subpaths.append('..')
+
+ includes = set(config['keymaps_includes'])
+ includes.add("keycode.h")
+
+ valid_keycodes = set()
+ for dirpath, include in it.product(dirpaths, includes):
+ include_path = os.path.join(dirpath, include)
+ if os.path.exists(include_path):
+ header_data = read_header_file(include_path)
+ valid_keycodes.update(
+ parse_keydefs(config, header_data)
+ )
+ return valid_keycodes
+
+
+# Keymap Parsing
+
+def iter_raw_codes(layer_lines, filler, separator):
+ filler_re = re.compile("[" + filler + " ]")
+ for line in layer_lines:
+ line, _ = filler_re.subn("", line.strip())
+ if not line:
+ continue
+ codes = line.split(separator)
+ for code in codes[1:-1]:
+ yield code
+
+
+def iter_indexed_codes(raw_codes, key_indexes):
+ key_rows = {}
+ key_indexes_flat = []
+
+ for row_index, key_indexes in enumerate(key_indexes):
+ for key_index in key_indexes:
+ key_rows[key_index] = row_index
+ key_indexes_flat.extend(key_indexes)
+ assert len(raw_codes) == len(key_indexes_flat)
+ for raw_code, key_index in zip(raw_codes, key_indexes_flat):
+ # we keep track of the row mostly for layout purposes
+ yield raw_code, key_index, key_rows[key_index]
+
+
+LAYER_CHANGE_RE = re.compile(r"""
+ (DF|TG|MO)\(\d+\)
+""", re.VERBOSE)
+
+
+MACRO_RE = re.compile(r"""
+ M\(\w+\)
+""", re.VERBOSE)
+
+
+UNICODE_RE = re.compile(r"""
+ U[0-9A-F]{4}
+""", re.VERBOSE)
+
+
+NON_CODE = re.compile(r"""
+ ^[^A-Z0-9_]$
+""", re.VERBOSE)
+
+
+def parse_uni_code(raw_code):
+ macro_id = "UC_" + (
+ unicodedata.name(raw_code)
+ .replace(" ", "_")
+ .replace("-", "_")
+ )
+ code = "M({})".format(macro_id)
+ uc_hex = "{:04X}".format(ord(raw_code))
+ return code, macro_id, uc_hex
+
+
+def parse_key_code(raw_code, key_prefixes, valid_keycodes):
+ if raw_code in valid_keycodes:
+ return raw_code
+
+ for prefix in key_prefixes:
+ code = prefix + raw_code
+ if code in valid_keycodes:
+ return code
+
+
+def parse_code(raw_code, key_prefixes, valid_keycodes):
+ if not raw_code:
+ return 'KC_TRNS', None, None
+
+ if LAYER_CHANGE_RE.match(raw_code):
+ return raw_code, None, None
+
+ if MACRO_RE.match(raw_code):
+ macro_id = raw_code[2:-1]
+ return raw_code, macro_id, None
+
+ if UNICODE_RE.match(raw_code):
+ hex_code = raw_code[1:]
+ return parse_uni_code(chr(int(hex_code, 16)))
+
+ if NON_CODE.match(raw_code):
+ return parse_uni_code(raw_code)
+
+ code = parse_key_code(raw_code, key_prefixes, valid_keycodes)
+ return code, None, None
+
+
+def parse_keymap(config, key_indexes, layer_lines, valid_keycodes):
+ keymap = {}
+ raw_codes = list(iter_raw_codes(
+ layer_lines, config['filler'], config['separator']
+ ))
+ indexed_codes = iter_indexed_codes(raw_codes, key_indexes)
+ key_prefixes = config['key_prefixes']
+ for raw_code, key_index, row_index in indexed_codes:
+ code, macro_id, uc_hex = parse_code(
+ raw_code, key_prefixes, valid_keycodes
+ )
+ # TODO: line numbers for invalid codes
+ err_msg = "Could not parse key '{}' on row {}".format(
+ raw_code, row_index
+ )
+ assert code is not None, err_msg
+ # print(repr(raw_code), repr(code), macro_id, uc_hex)
+ if macro_id:
+ config['macro_ids'].add(macro_id)
+ if uc_hex:
+ config['unicode_macros'][macro_id] = uc_hex
+ keymap[key_index] = (code, row_index)
+ return keymap
+
+
+def parse_keymaps(config, valid_keycodes):
+ keymaps = collections.OrderedDict()
+ key_indexes = config.get(
+ 'key_indexes', KEYBOARD_LAYOUTS[config['layout']]
+ )
+ # TODO: maybe validate key_indexes
+
+ for layer_name, layer_lines, in config['layer_lines'].items():
+ keymaps[layer_name] = parse_keymap(
+ config, key_indexes, layer_lines, valid_keycodes
+ )
+ return keymaps
+
+# keymap.c output
+
+USERCODE = """
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+
+};
+
+// Runs constantly in the background, in a loop.
+void matrix_scan_user(void) {
+ uint8_t layer = biton32(layer_state);
+
+ ergodox_board_led_off();
+ ergodox_right_led_1_off();
+ ergodox_right_led_2_off();
+ ergodox_right_led_3_off();
+ switch (layer) {
+ case L1:
+ ergodox_right_led_1_on();
+ break;
+ case L2:
+ ergodox_right_led_2_on();
+ break;
+ case L3:
+ ergodox_right_led_3_on();
+ break;
+ case L4:
+ ergodox_right_led_1_on();
+ ergodox_right_led_2_on();
+ break;
+ case L5:
+ ergodox_right_led_1_on();
+ ergodox_right_led_3_on();
+ break;
+ // case L6:
+ // ergodox_right_led_2_on();
+ // ergodox_right_led_3_on();
+ // break;
+ // case L7:
+ // ergodox_right_led_1_on();
+ // ergodox_right_led_2_on();
+ // ergodox_right_led_3_on();
+ // break;
+ default:
+ ergodox_board_led_off();
+ break;
+ }
+};
+"""
+
+MACROCODE = """
+#define UC_MODE_WIN 0
+#define UC_MODE_LINUX 1
+#define UC_MODE_OSX 2
+
+// TODO: allow default mode to be configured
+static uint16_t unicode_mode = UC_MODE_WIN;
+
+uint16_t hextokeycode(uint8_t hex) {{
+ if (hex == 0x0) {{
+ return KC_P0;
+ }}
+ if (hex < 0xA) {{
+ return KC_P1 + (hex - 0x1);
+ }}
+ return KC_A + (hex - 0xA);
+}}
+
+void unicode_action_function(uint16_t hi, uint16_t lo) {{
+ switch (unicode_mode) {{
+ case UC_MODE_WIN:
+ register_code(KC_LALT);
+
+ register_code(KC_PPLS);
+ unregister_code(KC_PPLS);
+
+ register_code(hextokeycode((hi & 0xF0) >> 4));
+ unregister_code(hextokeycode((hi & 0xF0) >> 4));
+ register_code(hextokeycode((hi & 0x0F)));
+ unregister_code(hextokeycode((hi & 0x0F)));
+ register_code(hextokeycode((lo & 0xF0) >> 4));
+ unregister_code(hextokeycode((lo & 0xF0) >> 4));
+ register_code(hextokeycode((lo & 0x0F)));
+ unregister_code(hextokeycode((lo & 0x0F)));
+
+ unregister_code(KC_LALT);
+ break;
+ case UC_MODE_LINUX:
+ register_code(KC_LCTL);
+ register_code(KC_LSFT);
+
+ register_code(KC_U);
+ unregister_code(KC_U);
+
+ register_code(hextokeycode((hi & 0xF0) >> 4));
+ unregister_code(hextokeycode((hi & 0xF0) >> 4));
+ register_code(hextokeycode((hi & 0x0F)));
+ unregister_code(hextokeycode((hi & 0x0F)));
+ register_code(hextokeycode((lo & 0xF0) >> 4));
+ unregister_code(hextokeycode((lo & 0xF0) >> 4));
+ register_code(hextokeycode((lo & 0x0F)));
+ unregister_code(hextokeycode((lo & 0x0F)));
+
+ unregister_code(KC_LCTL);
+ unregister_code(KC_LSFT);
+ break;
+ case UC_MODE_OSX:
+ break;
+ }}
+}}
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) {{
+ if (!record->event.pressed) {{
+ return MACRO_NONE;
+ }}
+ // MACRODOWN only works in this function
+ switch(id) {{
+ case UM:
+ unicode_mode = (unicode_mode + 1) % 2;
+ break;
+{macro_cases}
+{unicode_macro_cases}
+ default:
+ break;
+ }}
+ return MACRO_NONE;
+}};
+"""
+
+
+UNICODE_MACRO_TEMPLATE = """
+case {macro_id}:
+ unicode_action_function(0x{hi:02x}, 0x{lo:02x});
+ break;
+""".strip()
+
+
+def unicode_macro_cases(config):
+ for macro_id, uc_hex in config['unicode_macros'].items():
+ hi = int(uc_hex, 16) >> 8
+ lo = int(uc_hex, 16) & 0xFF
+ unimacro_keys = ", ".join(
+ "T({})".format(
+ "KP_" + digit if digit.isdigit() else digit
+ ) for digit in uc_hex
+ )
+ yield UNICODE_MACRO_TEMPLATE.format(
+ macro_id=macro_id, hi=hi, lo=lo
+ )
+
+
+def iter_keymap_lines(keymap, row_indents=None):
+ col_widths = {}
+ col = 0
+ # first pass, figure out the column widths
+ prev_row_index = None
+ for code, row_index in keymap.values():
+ if row_index != prev_row_index:
+ col = 0
+ if row_indents:
+ col = row_indents[row_index]
+ col_widths[col] = max(len(code), col_widths.get(col, 0))
+ prev_row_index = row_index
+ col += 1
+
+ # second pass, yield the cell values
+ col = 0
+ prev_row_index = None
+ for key_index in sorted(keymap):
+ code, row_index = keymap[key_index]
+ if row_index != prev_row_index:
+ col = 0
+ yield "\n"
+ if row_indents:
+ for indent_col in range(row_indents[row_index]):
+ pad = " " * (col_widths[indent_col] - 4)
+ yield (" /*-*/" + pad)
+ col = row_indents[row_index]
+ else:
+ yield pad
+ yield " {}".format(code)
+ if key_index < len(keymap) - 1:
+ yield ","
+ # This will be yielded on the next iteration when
+ # we know that we're not at the end of a line.
+ pad = " " * (col_widths[col] - len(code))
+ prev_row_index = row_index
+ col += 1
+
+
+def iter_keymap_parts(config, keymaps):
+ # includes
+ for include_path in config['keymaps_includes']:
+ yield '#include "{}"\n'.format(include_path)
+
+ yield "\n"
+
+ # definitions
+ for i, macro_id in enumerate(sorted(config['macro_ids'])):
+ yield "#define {} {}\n".format(macro_id, i)
+
+ yield "\n"
+
+ for i, layer_name in enumerate(config['layer_lines']):
+ yield '#define L{0:<3} {0:<5} // {1}\n'.format(i, layer_name)
+
+ yield "\n"
+
+ # keymaps
+ yield "const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {\n"
+
+ for i, layer_name in enumerate(config['layer_lines']):
+ # comment
+ layer_lines = config['layer_lines'][layer_name]
+ prefixed_lines = " * " + " * ".join(layer_lines)
+ yield "/*\n{} */\n".format(prefixed_lines)
+
+ # keymap codes
+ keymap = keymaps[layer_name]
+ row_indents = ROW_INDENTS.get(config['layout'])
+ keymap_lines = "".join(iter_keymap_lines(keymap, row_indents))
+ yield "[L{0}] = KEYMAP({1}\n),\n".format(i, keymap_lines)
+
+ yield "};\n\n"
+
+ # no idea what this is for
+ yield "const uint16_t PROGMEM fn_actions[] = {};\n"
+
+ # macros
+ yield MACROCODE.format(
+ macro_cases="",
+ unicode_macro_cases="\n".join(unicode_macro_cases(config)),
+ )
+
+ # TODO: dynamically create blinking lights
+ yield USERCODE
+
+
+def main(argv=sys.argv[1:]):
+ if not argv or '-h' in argv or '--help' in argv:
+ print(__doc__)
+ return 0
+
+ in_path = os.path.abspath(argv[0])
+ if not os.path.exists(in_path):
+ print("No such file '{}'".format(in_path))
+ return 1
+
+ if len(argv) > 1:
+ out_path = os.path.abspath(argv[1])
+ else:
+ dirname = os.path.dirname(in_path)
+ out_path = os.path.join(dirname, "keymap.c")
+
+ config = parse_config(in_path)
+ valid_keys = parse_valid_keys(config, out_path)
+ keymaps = parse_keymaps(config, valid_keys)
+
+ with io.open(out_path, mode="w", encoding="utf-8") as fh:
+ for part in iter_keymap_parts(config, keymaps):
+ fh.write(part)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/keyboards/ergodox_ez/util/readme.md b/keyboards/ergodox_ez/util/readme.md
new file mode 100644
index 000000000..26c5e5d99
--- /dev/null
+++ b/keyboards/ergodox_ez/util/readme.md
@@ -0,0 +1,3 @@
+# ErgoDox EZ Utilities
+
+The Python script in this directory, by [mbarkhau](https://github.com/mbarkhau) allows you to write out a basic ErgoDox EZ keymap using Markdown notation, and then transpile it to C, which you can then compile. It's experimental, but if you're not comfortable using C, it's a nice option.
diff --git a/keyboards/gh60/Makefile b/keyboards/gh60/Makefile
new file mode 100644
index 000000000..39a9cc0ae
--- /dev/null
+++ b/keyboards/gh60/Makefile
@@ -0,0 +1,74 @@
+
+
+# MCU name
+#MCU = at90usb1287
+MCU = atmega32u4
+
+# Processor frequency.
+# This will define a symbol, F_CPU, in all source code files equal to the
+# processor frequency in Hz. You can then use this symbol in your source code to
+# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
+# automatically to create a 32-bit value in your source code.
+#
+# This will be an integer division of F_USB below, as it is sourced by
+# F_USB after it has run through any CPU prescalers. Note that this value
+# does not *change* the processor frequency - it should merely be updated to
+# reflect the processor speed set externally so that the code can use accurate
+# software delays.
+F_CPU = 16000000
+
+
+#
+# LUFA specific
+#
+# Target architecture (see library "Board Types" documentation).
+ARCH = AVR8
+
+# Input clock frequency.
+# This will define a symbol, F_USB, in all source code files equal to the
+# input clock frequency (before any prescaling is performed) in Hz. This value may
+# differ from F_CPU if prescaling is used on the latter, and is required as the
+# raw input clock is fed directly to the PLL sections of the AVR for high speed
+# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
+# at the end, this will be done automatically to create a 32-bit value in your
+# source code.
+#
+# If no clock division is performed on the input clock inside the AVR (via the
+# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
+F_USB = $(F_CPU)
+
+# Interrupt driven control endpoint task(+60)
+OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
+
+
+# Boot Section Size in *bytes*
+# Teensy halfKay 512
+# Teensy++ halfKay 1024
+# Atmel DFU loader 4096
+# LUFA bootloader 4096
+# USBaspLoader 2048
+OPT_DEFS += -DBOOTLOADER_SIZE=4096
+
+
+# Build Options
+# comment out to disable the options.
+#
+BOOTMAGIC_ENABLE ?= yes # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE ?= yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450)
+# CONSOLE_ENABLE ?= yes # Console for debug(+400)
+# COMMAND_ENABLE ?= yes # Commands for debug and configuration
+KEYBOARD_LOCK_ENABLE ?= yes # Allow locking of keyboard via magic key
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+# SLEEP_LED_ENABLE ?= yes # Breathing sleep LED during USB suspend
+NKRO_ENABLE ?= yes # USB Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+# BACKLIGHT_ENABLE ?= yes # Enable keyboard backlight functionality
+# MIDI_ENABLE ?= YES # MIDI controls
+# UNICODE_ENABLE ?= YES # Unicode
+# BLUETOOTH_ENABLE ?= yes # Enable Bluetooth with the Adafruit EZ-Key HID
+
+
+ifndef QUANTUM_DIR
+ include ../../Makefile
+endif
+
diff --git a/keyboards/gh60/config.h b/keyboards/gh60/config.h
new file mode 100644
index 000000000..4813c4e78
--- /dev/null
+++ b/keyboards/gh60/config.h
@@ -0,0 +1,161 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "config_common.h"
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x6060
+#define DEVICE_VER 0x0001
+#define MANUFACTURER geekhack
+#define PRODUCT GH60
+#define DESCRIPTION t.m.k. keyboard firmware for GH60
+
+/* key matrix size */
+#define MATRIX_ROWS 5
+#define MATRIX_COLS 14
+
+/*
+ * Keyboard Matrix Assignments
+ *
+ * Change this to how you wired your keyboard
+ * COLS: AVR pins used for columns, left to right
+ * ROWS: AVR pins used for rows, top to bottom
+ * DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode)
+ * ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode)
+ *
+*/
+ #define MATRIX_ROW_PINS { D0, D1, D2, D3, D5 }
+// Rev A
+// #define MATRIX_COL_PINS { F0, F1, E6, C7, C6, B6, D4, B1, B0, B5, B4, D7, D6, B3 }
+// Rev B/C
+ #define MATRIX_COL_PINS { F0, F1, E6, C7, C6, B6, D4, B1, B7, B5, B4, D7, D6, B3 }
+#define UNUSED_PINS
+
+/* COL2ROW or ROW2COL */
+#define DIODE_DIRECTION COL2ROW
+
+/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
+#define DEBOUNCING_DELAY 5
+
+/* define if matrix has ghost (lacks anti-ghosting diodes) */
+//#define MATRIX_HAS_GHOST
+
+/* number of backlight levels */
+#define BACKLIGHT_LEVELS 3
+
+/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
+#define LOCKING_SUPPORT_ENABLE
+/* Locking resynchronize hack */
+#define LOCKING_RESYNC_ENABLE
+
+/*
+ * Force NKRO
+ *
+ * Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved
+ * state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the
+ * makefile for this to work.)
+ *
+ * If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N)
+ * until the next keyboard reset.
+ *
+ * NKRO may prevent your keystrokes from being detected in the BIOS, but it is
+ * fully operational during normal computer usage.
+ *
+ * For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N)
+ * or via bootmagic (hold SPACE+N while plugging in the keyboard). Once set by
+ * bootmagic, NKRO mode will always be enabled until it is toggled again during a
+ * power-up.
+ *
+ */
+//#define FORCE_NKRO
+
+/*
+ * Magic Key Options
+ *
+ * Magic keys are hotkey commands that allow control over firmware functions of
+ * the keyboard. They are best used in combination with the HID Listen program,
+ * found here: https://www.pjrc.com/teensy/hid_listen.html
+ *
+ * The options below allow the magic key functionality to be changed. This is
+ * useful if your keyboard/keypad is missing keys and you want magic key support.
+ *
+ */
+
+/* key combination for magic key command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+/* control how magic key switches layers */
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS true
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS true
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM false
+
+/* override magic key keymap */
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM
+//#define MAGIC_KEY_HELP1 H
+//#define MAGIC_KEY_HELP2 SLASH
+//#define MAGIC_KEY_DEBUG D
+//#define MAGIC_KEY_DEBUG_MATRIX X
+//#define MAGIC_KEY_DEBUG_KBD K
+//#define MAGIC_KEY_DEBUG_MOUSE M
+//#define MAGIC_KEY_VERSION V
+//#define MAGIC_KEY_STATUS S
+//#define MAGIC_KEY_CONSOLE C
+//#define MAGIC_KEY_LAYER0_ALT1 ESC
+//#define MAGIC_KEY_LAYER0_ALT2 GRAVE
+//#define MAGIC_KEY_LAYER0 0
+//#define MAGIC_KEY_LAYER1 1
+//#define MAGIC_KEY_LAYER2 2
+//#define MAGIC_KEY_LAYER3 3
+//#define MAGIC_KEY_LAYER4 4
+//#define MAGIC_KEY_LAYER5 5
+//#define MAGIC_KEY_LAYER6 6
+//#define MAGIC_KEY_LAYER7 7
+//#define MAGIC_KEY_LAYER8 8
+//#define MAGIC_KEY_LAYER9 9
+//#define MAGIC_KEY_BOOTLOADER PAUSE
+//#define MAGIC_KEY_LOCK CAPS
+//#define MAGIC_KEY_EEPROM E
+//#define MAGIC_KEY_NKRO N
+//#define MAGIC_KEY_SLEEP_LED Z
+
+/*
+ * Feature disable options
+ * These options are also useful to firmware size reduction.
+ */
+
+/* disable debug print */
+//#define NO_DEBUG
+
+/* disable print */
+//#define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+
+#endif
diff --git a/keyboards/gh60/gh60.c b/keyboards/gh60/gh60.c
new file mode 100644
index 000000000..255d87de9
--- /dev/null
+++ b/keyboards/gh60/gh60.c
@@ -0,0 +1,25 @@
+#include "gh60.h"
+
+void led_set_kb(uint8_t usb_led) {
+ // put your keyboard LED indicator (ex: Caps Lock LED) toggling code here
+
+ if (usb_led & (1<<USB_LED_CAPS_LOCK)) {
+ gh60_caps_led_on();
+ } else {
+ gh60_caps_led_off();
+ }
+
+ // if (usb_led & (1<<USB_LED_NUM_LOCK)) {
+ // gh60_esc_led_on();
+ // } else {
+ // gh60_esc_led_off();
+ // }
+
+ // if (usb_led & (1<<USB_LED_SCROLL_LOCK)) {
+ // gh60_fn_led_on();
+ // } else {
+ // gh60_fn_led_off();
+ // }
+
+ led_set_user(usb_led);
+}
diff --git a/keyboards/gh60/gh60.h b/keyboards/gh60/gh60.h
new file mode 100644
index 000000000..ca30562a4
--- /dev/null
+++ b/keyboards/gh60/gh60.h
@@ -0,0 +1,74 @@
+#ifndef GH60_H
+#define GH60_H
+
+#include "quantum.h"
+#include "led.h"
+
+/* GH60 LEDs
+ * GPIO pads
+ * 0 F7 WASD LEDs
+ * 1 F6 ESC LED
+ * 2 F5 FN LED
+ * 3 F4 POKER Arrow LEDs
+ * B2 Capslock LED
+ * B0 not connected
+ */
+inline void gh60_caps_led_on(void) { DDRB |= (1<<2); PORTB &= ~(1<<2); }
+inline void gh60_poker_leds_on(void) { DDRF |= (1<<4); PORTF &= ~(1<<4); }
+inline void gh60_fn_led_on(void) { DDRF |= (1<<5); PORTF &= ~(1<<5); }
+inline void gh60_esc_led_on(void) { DDRF |= (1<<6); PORTF &= ~(1<<6); }
+inline void gh60_wasd_leds_on(void) { DDRF |= (1<<7); PORTF &= ~(1<<7); }
+
+inline void gh60_caps_led_off(void) { DDRB &= ~(1<<2); PORTB &= ~(1<<2); }
+inline void gh60_poker_leds_off(void) { DDRF &= ~(1<<4); PORTF &= ~(1<<4); }
+inline void gh60_fn_led_off(void) { DDRF &= ~(1<<5); PORTF &= ~(1<<5); }
+inline void gh60_esc_led_off(void) { DDRF &= ~(1<<6); PORTF &= ~(1<<6); }
+inline void gh60_wasd_leds_off(void) { DDRF &= ~(1<<7); PORTF &= ~(1<<7); }
+
+/* GH60 keymap definition macro
+ * K2C, K31 and K3C are extra keys for ISO
+ */
+#define KEYMAP( \
+ K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, \
+ K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, \
+ K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, K2C, K2D, \
+ K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3C, K3D, \
+ K40, K41, K42, K45, K49, K4A, K4B, K4C, K4D \
+) { \
+ { KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07, KC_##K08, KC_##K09, KC_##K0A, KC_##K0B, KC_##K0C, KC_##K0D }, \
+ { KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_##K17, KC_##K18, KC_##K19, KC_##K1A, KC_##K1B, KC_##K1C, KC_##K1D }, \
+ { KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_##K27, KC_##K28, KC_##K29, KC_##K2A, KC_##K2B, KC_##K2C, KC_##K2D }, \
+ { KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36, KC_##K37, KC_##K38, KC_##K39, KC_##K3A, KC_##K3B, KC_##K3C, KC_##K3D }, \
+ { KC_##K40, KC_##K41, KC_##K42, KC_NO, KC_NO, KC_##K45, KC_NO, KC_NO, KC_NO, KC_##K49, KC_##K4A, KC_##K4B, KC_##K4C, KC_##K4D } \
+}
+
+/* ANSI valiant. No extra keys for ISO */
+#define KEYMAP_ANSI( \
+ K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, \
+ K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, \
+ K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, K2D, \
+ K30, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3D, \
+ K40, K41, K42, K45, K4A, K4B, K4C, K4D \
+) KEYMAP( \
+ K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, \
+ K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, \
+ K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, NO, K2D, \
+ K30, NO, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, NO, K3D, \
+ K40, K41, K42, K45, NO, K4A, K4B, K4C, K4D \
+)
+
+#define KEYMAP_HHKB( \
+ K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, K49,\
+ K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, \
+ K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, K2D, \
+ K30, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3D, K3C, \
+ K40, K41, K42, K45, K4A, K4B, K4C, K4D \
+) KEYMAP( \
+ K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, \
+ K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, \
+ K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, NO, K2D, \
+ K30, NO, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3C, K3D, \
+ K40, K41, K42, K45, K49, K4A, K4B, K4C, K4D \
+)
+
+#endif
diff --git a/keyboards/gh60/gh60revc.jpg b/keyboards/gh60/gh60revc.jpg
new file mode 100644
index 000000000..6c88ad244
--- /dev/null
+++ b/keyboards/gh60/gh60revc.jpg
Binary files differ
diff --git a/keyboards/gh60/keymaps/default/keymap.c b/keyboards/gh60/keymaps/default/keymap.c
new file mode 100644
index 000000000..3622be41b
--- /dev/null
+++ b/keyboards/gh60/keymaps/default/keymap.c
@@ -0,0 +1,69 @@
+#include "gh60.h"
+#include "action_layer.h"
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ /* 0: qwerty */
+ KEYMAP(
+ ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, GRV, \
+ TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSPC, \
+ CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT,NO, ENT, \
+ LSFT,FN1, Z, X, C, V, B, N, M, COMM,DOT, SLSH,FN0, RSFT, \
+ LCTL,LGUI,LALT, SPC, BSLS,RALT,RGUI,APP, RCTL),
+ /* 1: fn */
+ KEYMAP(
+ ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, TRNS, \
+ TRNS,TRNS,UP, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
+ TRNS,LEFT,DOWN,RGHT,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
+ TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
+ TRNS,TRNS,TRNS, TRNS, TRNS,TRNS,TRNS,TRNS,TRNS),
+ /* 2: arrows */
+ KEYMAP(
+ TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
+ TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
+ TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, \
+ TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,UP, \
+ TRNS,TRNS,TRNS, TRNS, TRNS,TRNS,LEFT,DOWN,RGHT),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [0] = ACTION_LAYER_MOMENTARY(1), // to Fn overlay
+ [1] = ACTION_LAYER_TOGGLE(2), // toggle arrow overlay
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+void matrix_scan_user(void) {
+
+//Layer LED indicators
+ uint32_t layer = layer_state;
+
+ if (layer & (1<<1)) {
+ gh60_wasd_leds_on();
+ gh60_fn_led_on();
+ } else {
+ gh60_wasd_leds_off();
+ gh60_fn_led_off();
+ }
+
+ if (layer & (1<<2)) {
+ gh60_poker_leds_on();
+ gh60_esc_led_on();
+ } else {
+ gh60_poker_leds_off();
+ gh60_esc_led_off();
+ }
+
+};
diff --git a/keyboards/gh60/pinout.txt b/keyboards/gh60/pinout.txt
new file mode 100644
index 000000000..3787f938e
--- /dev/null
+++ b/keyboards/gh60/pinout.txt
@@ -0,0 +1,18 @@
+ /* Column pin configuration
+ * col: 0 1 2 3 4 5 6 7 8 9 10 11 12 13
+ * pin: F0 F1 E6 C7 C6 B6 D4 B1 B7 B5 B4 D7 D6 B3 (Rev.C)
+ */
+
+ /* Row pin configuration
+ * row: 0 1 2 3 4
+ * pin: D0 D1 D2 D3 D5
+ */
+
+ GPIO pads
+ 0 F7 WASD LEDs
+ 1 F6 ESC LED
+ 2 F5 FN LED
+ 3 F4 POKER Arrow LEDs
+
+ B2 Capslock LED
+ B0 not connected \ No newline at end of file
diff --git a/keyboards/gh60/readme.md b/keyboards/gh60/readme.md
new file mode 100644
index 000000000..92302d507
--- /dev/null
+++ b/keyboards/gh60/readme.md
@@ -0,0 +1,60 @@
+## gh60 Rev C keyboard firmware
+
+![gh60 Rev C PCB](gh60revc.jpg)
+
+ /* Column pin configuration
+ * col: 0 1 2 3 4 5 6 7 8 9 10 11 12 13
+ * pin: F0 F1 E6 C7 C6 B6 D4 B1 B7 B5 B4 D7 D6 B3 (Rev.C)
+ */
+
+ /* Row pin configuration
+ * row: 0 1 2 3 4
+ * pin: D0 D1 D2 D3 D5
+ */
+
+ GPIO pads
+ 0 F7 WASD LEDs
+ 1 F6 ESC LED
+ 2 F5 FN LED
+ 3 F4 POKER Arrow LEDs
+
+ B2 Capslock LED
+ B0 not connected
+
+Functions to controls LED clusters
+
+ gh60_caps_led_on()
+ gh60_poker_leds_on()
+ gh60_fn_led_on()
+ gh60_esc_led_on()
+ gh60_wasd_leds_on()
+
+ gh60_caps_led_off()
+ gh60_poker_leds_off()
+ gh60_fn_led_off()
+ gh60_esc_led_off()
+ gh60_wasd_leds_off()
+
+======================
+
+## Quantum MK Firmware
+
+For the full Quantum feature list, see [the parent readme.md](/readme.md).
+
+## Building
+
+Download or clone the whole firmware and navigate to the keyboards/gh60_rev_c folder. Once your dev env is setup, you'll be able to type `make` to generate your .hex - you can then use the Teensy Loader to program your .hex file.
+
+Depending on which keymap you would like to use, you will have to compile slightly differently.
+
+### Default
+To build with the default keymap, simply run `make`.
+
+### Other Keymaps
+Several version of keymap are available in advance but you are recommended to define your favorite layout yourself. To define your own keymap create file named `<name>.c` in the keymaps folder, and see keymap document (you can find in top readme.md) and existent keymap files.
+
+To build the firmware binary hex file with a keymap just do `make` with `KEYMAP` option like:
+```
+$ make KEYMAP=[default|jack|<name>]
+```
+Keymaps follow the format **__\<name\>.c__** and are stored in the `keymaps` folder.
diff --git a/keyboards/handwired/Makefile b/keyboards/handwired/Makefile
new file mode 100644
index 000000000..57493a47c
--- /dev/null
+++ b/keyboards/handwired/Makefile
@@ -0,0 +1,3 @@
+ifndef QUANTUM_DIR
+ include ../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/handwired/fivethirteen/Makefile b/keyboards/handwired/fivethirteen/Makefile
new file mode 100644
index 000000000..711759917
--- /dev/null
+++ b/keyboards/handwired/fivethirteen/Makefile
@@ -0,0 +1,73 @@
+
+# MCU name
+MCU = atmega32u4
+
+# Processor frequency.
+# This will define a symbol, F_CPU, in all source code files equal to the
+# processor frequency in Hz. You can then use this symbol in your source code to
+# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
+# automatically to create a 32-bit value in your source code.
+#
+# This will be an integer division of F_USB below, as it is sourced by
+# F_USB after it has run through any CPU prescalers. Note that this value
+# does not *change* the processor frequency - it should merely be updated to
+# reflect the processor speed set externally so that the code can use accurate
+# software delays.
+F_CPU = 16000000
+
+
+#
+# LUFA specific
+#
+# Target architecture (see library "Board Types" documentation).
+ARCH = AVR8
+
+# Input clock frequency.
+# This will define a symbol, F_USB, in all source code files equal to the
+# input clock frequency (before any prescaling is performed) in Hz. This value may
+# differ from F_CPU if prescaling is used on the latter, and is required as the
+# raw input clock is fed directly to the PLL sections of the AVR for high speed
+# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
+# at the end, this will be done automatically to create a 32-bit value in your
+# source code.
+#
+# If no clock division is performed on the input clock inside the AVR (via the
+# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
+F_USB = $(F_CPU)
+
+# Interrupt driven control endpoint task(+60)
+OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
+
+
+# Boot Section Size in *bytes*
+# Teensy halfKay 512
+# Teensy++ halfKay 1024
+# Atmel DFU loader 4096
+# LUFA bootloader 4096
+# USBaspLoader 2048
+OPT_DEFS += -DBOOTLOADER_SIZE=512
+
+
+# Build Options
+# change yes to no to disable
+#
+BOOTMAGIC_ENABLE ?= no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE ?= yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450)
+CONSOLE_ENABLE ?= yes # Console for debug(+400)
+COMMAND_ENABLE ?= yes # Commands for debug and configuration
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE ?= no # Breathing sleep LED during USB suspend
+# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+NKRO_ENABLE ?= no # USB Nkey Rollover
+BACKLIGHT_ENABLE ?= no # Enable keyboard backlight functionality on B7 by default
+MIDI_ENABLE ?= no # MIDI controls
+UNICODE_ENABLE ?= no # Unicode
+BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID
+AUDIO_ENABLE ?= no # Audio output on port C6
+
+ifndef QUANTUM_DIR
+ include ../../../Makefile
+endif
+
+
diff --git a/keyboards/handwired/fivethirteen/README.md b/keyboards/handwired/fivethirteen/README.md
new file mode 100644
index 000000000..b2e13cd6d
--- /dev/null
+++ b/keyboards/handwired/fivethirteen/README.md
@@ -0,0 +1,28 @@
+fivethirteen keyboard firmware
+======================
+
+## Quantum MK Firmware
+
+For the full Quantum feature list, see [the parent readme.md](/doc/readme.md).
+
+## Building
+
+Download or clone the whole firmware and navigate to the keyboards/handwired/fivethirteen folder.
+Once your dev env is setup, you'll be able to type `make` to generate your .hex - you can then use
+the Teensy Loader to program your .hex file.
+
+Depending on which keymap you would like to use, you will have to compile slightly differently.
+
+### Default
+
+To build with the default keymap, simply run `make`.
+
+### Other Keymaps
+
+To build the firmware binary hex file with a keymap just do `make` with `keymap` option like:
+
+```
+$ make keymap=[default|jack|<name>]
+```
+
+Keymaps follow the format **__keymap.c__** and are stored in folders in the `keymaps` folder, eg `keymaps/my_keymap/`
diff --git a/keyboards/handwired/fivethirteen/config.h b/keyboards/handwired/fivethirteen/config.h
new file mode 100644
index 000000000..76596342b
--- /dev/null
+++ b/keyboards/handwired/fivethirteen/config.h
@@ -0,0 +1,162 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "config_common.h"
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x6060
+#define DEVICE_VER 0x0001
+#define MANUFACTURER rdg
+#define PRODUCT fivethirteen
+#define DESCRIPTION handwired 5x13 matrix keyboard
+
+/* key matrix size */
+#define MATRIX_ROWS 5
+#define MATRIX_COLS 13
+
+/*
+ * Keyboard Matrix Assignments
+ *
+ * Change this to how you wired your keyboard
+ * COLS: AVR pins used for columns, left to right
+ * ROWS: AVR pins used for rows, top to bottom
+ * DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode)
+ * ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode)
+ *
+*/
+#define MATRIX_ROW_PINS { F6, F7, B6, B5, B4 }
+#define MATRIX_COL_PINS { B0, B1, B2, B3, F0, D0, D1, D2, D3, C6, C7, D6, D7 }
+#define UNUSED_PINS
+
+/* COL2ROW or ROW2COL */
+#define DIODE_DIRECTION COL2ROW
+
+// #define BACKLIGHT_PIN B7
+// #define BACKLIGHT_BREATHING
+// #define BACKLIGHT_LEVELS 3
+
+
+/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
+#define DEBOUNCING_DELAY 5
+
+/* define if matrix has ghost (lacks anti-ghosting diodes) */
+//#define MATRIX_HAS_GHOST
+
+/* number of backlight levels */
+
+/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
+#define LOCKING_SUPPORT_ENABLE
+/* Locking resynchronize hack */
+#define LOCKING_RESYNC_ENABLE
+
+/*
+ * Force NKRO
+ *
+ * Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved
+ * state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the
+ * makefile for this to work.)
+ *
+ * If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N)
+ * until the next keyboard reset.
+ *
+ * NKRO may prevent your keystrokes from being detected in the BIOS, but it is
+ * fully operational during normal computer usage.
+ *
+ * For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N)
+ * or via bootmagic (hold SPACE+N while plugging in the keyboard). Once set by
+ * bootmagic, NKRO mode will always be enabled until it is toggled again during a
+ * power-up.
+ *
+ */
+//#define FORCE_NKRO
+
+/*
+ * Magic Key Options
+ *
+ * Magic keys are hotkey commands that allow control over firmware functions of
+ * the keyboard. They are best used in combination with the HID Listen program,
+ * found here: https://www.pjrc.com/teensy/hid_listen.html
+ *
+ * The options below allow the magic key functionality to be changed. This is
+ * useful if your keyboard/keypad is missing keys and you want magic key support.
+ *
+ */
+
+/* key combination for magic key command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+/* control how magic key switches layers */
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS true
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS true
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM false
+
+/* override magic key keymap */
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM
+//#define MAGIC_KEY_HELP1 H
+//#define MAGIC_KEY_HELP2 SLASH
+//#define MAGIC_KEY_DEBUG D
+//#define MAGIC_KEY_DEBUG_MATRIX X
+//#define MAGIC_KEY_DEBUG_KBD K
+//#define MAGIC_KEY_DEBUG_MOUSE M
+//#define MAGIC_KEY_VERSION V
+//#define MAGIC_KEY_STATUS S
+//#define MAGIC_KEY_CONSOLE C
+//#define MAGIC_KEY_LAYER0_ALT1 ESC
+//#define MAGIC_KEY_LAYER0_ALT2 GRAVE
+//#define MAGIC_KEY_LAYER0 0
+//#define MAGIC_KEY_LAYER1 1
+//#define MAGIC_KEY_LAYER2 2
+//#define MAGIC_KEY_LAYER3 3
+//#define MAGIC_KEY_LAYER4 4
+//#define MAGIC_KEY_LAYER5 5
+//#define MAGIC_KEY_LAYER6 6
+//#define MAGIC_KEY_LAYER7 7
+//#define MAGIC_KEY_LAYER8 8
+//#define MAGIC_KEY_LAYER9 9
+//#define MAGIC_KEY_BOOTLOADER PAUSE
+//#define MAGIC_KEY_LOCK CAPS
+//#define MAGIC_KEY_EEPROM E
+//#define MAGIC_KEY_NKRO N
+//#define MAGIC_KEY_SLEEP_LED Z
+
+/*
+ * Feature disable options
+ * These options are also useful to firmware size reduction.
+ */
+
+/* disable debug print */
+//#define NO_DEBUG
+
+/* disable print */
+//#define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+
+#endif
diff --git a/keyboards/handwired/fivethirteen/fivethirteen.c b/keyboards/handwired/fivethirteen/fivethirteen.c
new file mode 100644
index 000000000..4c16e72eb
--- /dev/null
+++ b/keyboards/handwired/fivethirteen/fivethirteen.c
@@ -0,0 +1,8 @@
+#include "fivethirteen.h"
+
+void matrix_init_kb(void) {
+ // put your keyboard start-up code here
+ // runs once when the firmware starts up
+
+ matrix_init_user();
+}
diff --git a/keyboards/handwired/fivethirteen/fivethirteen.h b/keyboards/handwired/fivethirteen/fivethirteen.h
new file mode 100644
index 000000000..faa6de737
--- /dev/null
+++ b/keyboards/handwired/fivethirteen/fivethirteen.h
@@ -0,0 +1,21 @@
+#ifndef FIVETHIRTEEN_H
+#define FIVETHIRTEEN_H
+
+#include "quantum.h"
+
+#define KEYMAP( \
+ k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k010, k011, k012, \
+ k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k110, k111, k112, \
+ k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k210, k211, k212, \
+ k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k310, k311, k312, \
+ k40, k41, k42, k43, k44, k46, k47, k48, k49, k410, k411, k412 \
+) \
+{ \
+ { k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k010, k011, k012 }, \
+ { k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k110, k111, k112 }, \
+ { k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k210, k211, k212 }, \
+ { k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k310, k311, k312 }, \
+ { k40, k41, k42, k43, k44, KC_NO, k46, k47, k48, k49, k410, k411, k412 } \
+}
+
+#endif
diff --git a/keyboards/handwired/fivethirteen/keymaps/default/keymap.c b/keyboards/handwired/fivethirteen/keymaps/default/keymap.c
new file mode 100644
index 000000000..d718510d5
--- /dev/null
+++ b/keyboards/handwired/fivethirteen/keymaps/default/keymap.c
@@ -0,0 +1,49 @@
+#include "fivethirteen.h"
+
+#define _______ KC_TRNS
+
+#define HDN 1
+#define OSY 2
+#define MOS 3
+#define CTL_ESC CTL_T(KC_ESC)
+#define SFT_BSP SFT_T(KC_BSPC)
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[0] = KEYMAP(
+ KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, \
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, \
+ CTL_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, \
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_UP, KC_BSLS, \
+ MO(MOS), KC_LCTL, KC_LALT, KC_LGUI, MO(HDN), KC_SPC , SFT_BSP, MO(OSY), MO(HDN), KC_LEFT, KC_DOWN, KC_RGHT \
+),
+[HDN] = KEYMAP(
+ _______, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, \
+ _______, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, _______, _______, \
+ _______, KC_TILD, KC_GRV, KC_BSLS, KC_PIPE, KC_MINS, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, KC_TILD, KC_GRV, _______, \
+ _______, _______, _______, _______, _______, _______, _______, KC_ENT, _______, _______, _______, KC_PGUP, _______, \
+ _______, _______, _______, _______, _______, KC_UNDS , KC_DEL, _______, _______, KC_HOME, KC_PGDN, KC_END \
+),
+[OSY] = KEYMAP(
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
+ _______, KC_VOLD, KC_VOLU, KC_MUTE, KC_PWR, _______, _______, _______, _______, _______, _______, _______, _______, \
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ \
+),
+[MOS] = KEYMAP(
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \
+ _______, _______, _______, _______, _______, _______, _______, KC_BTN1, KC_BTN2, _______, _______, _______, _______, \
+ _______, _______, _______, _______, _______, _______, KC_MS_L, KC_MS_D, KC_MS_U, KC_MS_R, _______, _______, _______, \
+ _______, _______, _______, _______, _______, _______, _______, KC_WH_D, KC_WH_U, _______, _______, _______, _______, \
+ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ \
+)
+};
+
+
+const uint16_t PROGMEM fn_actions[] = {
+
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) {
+ return MACRO_NONE;
+};
diff --git a/keyboards/handwired/handwired.c b/keyboards/handwired/handwired.c
new file mode 100644
index 000000000..feef8a919
--- /dev/null
+++ b/keyboards/handwired/handwired.c
@@ -0,0 +1 @@
+#include "handwired.h" \ No newline at end of file
diff --git a/keyboards/handwired/handwired.h b/keyboards/handwired/handwired.h
new file mode 100644
index 000000000..7a4a4835e
--- /dev/null
+++ b/keyboards/handwired/handwired.h
@@ -0,0 +1 @@
+#include "quantum.h" \ No newline at end of file
diff --git a/keyboards/handwired/onekey/Makefile b/keyboards/handwired/onekey/Makefile
new file mode 100644
index 000000000..c6d10856a
--- /dev/null
+++ b/keyboards/handwired/onekey/Makefile
@@ -0,0 +1,65 @@
+
+
+# MCU name
+MCU = atmega32u4
+
+# Processor frequency.
+# This will define a symbol, F_CPU, in all source code files equal to the
+# processor frequency in Hz. You can then use this symbol in your source code to
+# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
+# automatically to create a 32-bit value in your source code.
+#
+# This will be an integer division of F_USB below, as it is sourced by
+# F_USB after it has run through any CPU prescalers. Note that this value
+# does not *change* the processor frequency - it should merely be updated to
+# reflect the processor speed set externally so that the code can use accurate
+# software delays.
+F_CPU = 16000000
+
+
+#
+# LUFA specific
+#
+# Target architecture (see library "Board Types" documentation).
+ARCH = AVR8
+
+# Input clock frequency.
+# This will define a symbol, F_USB, in all source code files equal to the
+# input clock frequency (before any prescaling is performed) in Hz. This value may
+# differ from F_CPU if prescaling is used on the latter, and is required as the
+# raw input clock is fed directly to the PLL sections of the AVR for high speed
+# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
+# at the end, this will be done automatically to create a 32-bit value in your
+# source code.
+#
+# If no clock division is performed on the input clock inside the AVR (via the
+# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
+F_USB = $(F_CPU)
+
+# Interrupt driven control endpoint task(+60)
+OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
+
+
+# Boot Section Size in *bytes*
+# Teensy halfKay 512
+# Teensy++ halfKay 1024
+# Atmel DFU loader 4096
+# LUFA bootloader 4096
+# USBaspLoader 2048
+OPT_DEFS += -DBOOTLOADER_SIZE=4096
+
+
+# Build Options
+# comment out to disable the options.
+#
+BOOTMAGIC_ENABLE ?= no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE ?= yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450)
+CONSOLE_ENABLE ?= yes # Console for debug(+400)
+COMMAND_ENABLE ?= yes # Commands for debug and configuration
+#SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend
+#NKRO_ENABLE = yes # USB Nkey Rollover - not yet supported in LUFA
+
+ifndef QUANTUM_DIR
+ include ../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/handwired/onekey/config.h b/keyboards/handwired/onekey/config.h
new file mode 100644
index 000000000..c0a6b5839
--- /dev/null
+++ b/keyboards/handwired/onekey/config.h
@@ -0,0 +1,75 @@
+/*
+Copyright 2015 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "config_common.h"
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x6464
+#define DEVICE_VER 0x0001
+#define MANUFACTURER none
+#define PRODUCT onekey
+#define DESCRIPTION test board for qmk
+
+/* key matrix size */
+#define MATRIX_ROWS 1
+#define MATRIX_COLS 1
+
+#define MATRIX_COL_PINS { B0 }
+#define MATRIX_ROW_PINS { D0 }
+#define UNUSED_PINS
+
+/* define if matrix has ghost */
+//#define MATRIX_HAS_GHOST
+
+/* Set 0 if debouncing isn't needed */
+#define DEBOUNCE 5
+
+/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
+#define LOCKING_SUPPORT_ENABLE
+/* Locking resynchronize hack */
+#define LOCKING_RESYNC_ENABLE
+
+/* key combination for command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+
+
+/*
+ * Feature disable options
+ * These options are also useful to firmware size reduction.
+ */
+
+/* disable debug print */
+//#define NO_DEBUG
+
+/* disable print */
+//#define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+
+#endif
diff --git a/keyboards/handwired/onekey/keymaps/default/keymap.c b/keyboards/handwired/onekey/keymaps/default/keymap.c
new file mode 100644
index 000000000..756c4f51e
--- /dev/null
+++ b/keyboards/handwired/onekey/keymaps/default/keymap.c
@@ -0,0 +1,5 @@
+#include "onekey.h"
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ { KC_A }
+};
diff --git a/keyboards/handwired/onekey/onekey.c b/keyboards/handwired/onekey/onekey.c
new file mode 100644
index 000000000..c79e0120e
--- /dev/null
+++ b/keyboards/handwired/onekey/onekey.c
@@ -0,0 +1 @@
+#include "onekey.h" \ No newline at end of file
diff --git a/keyboards/handwired/onekey/onekey.h b/keyboards/handwired/onekey/onekey.h
new file mode 100644
index 000000000..7a4a4835e
--- /dev/null
+++ b/keyboards/handwired/onekey/onekey.h
@@ -0,0 +1 @@
+#include "quantum.h" \ No newline at end of file
diff --git a/keyboards/hhkb/Makefile b/keyboards/hhkb/Makefile
new file mode 100644
index 000000000..53eece396
--- /dev/null
+++ b/keyboards/hhkb/Makefile
@@ -0,0 +1,86 @@
+
+
+# project specific files
+SRC = matrix.c
+
+# MCU name
+#MCU = at90usb1287
+MCU = atmega32u4
+
+# Processor frequency.
+# This will define a symbol, F_CPU, in all source code files equal to the
+# processor frequency in Hz. You can then use this symbol in your source code to
+# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
+# automatically to create a 32-bit value in your source code.
+#
+# This will be an integer division of F_USB below, as it is sourced by
+# F_USB after it has run through any CPU prescalers. Note that this value
+# does not *change* the processor frequency - it should merely be updated to
+# reflect the processor speed set externally so that the code can use accurate
+# software delays.
+F_CPU = 16000000
+
+
+#
+# LUFA specific
+#
+# Target architecture (see library "Board Types" documentation).
+ARCH = AVR8
+
+# Input clock frequency.
+# This will define a symbol, F_USB, in all source code files equal to the
+# input clock frequency (before any prescaling is performed) in Hz. This value may
+# differ from F_CPU if prescaling is used on the latter, and is required as the
+# raw input clock is fed directly to the PLL sections of the AVR for high speed
+# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
+# at the end, this will be done automatically to create a 32-bit value in your
+# source code.
+#
+# If no clock division is performed on the input clock inside the AVR (via the
+# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
+F_USB = $(F_CPU)
+
+# Interrupt driven control endpoint task(+60)
+OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
+
+
+# Boot Section Size in *bytes*
+# Teensy halfKay 512
+# Teensy++ halfKay 1024
+# Atmel DFU loader 4096
+# LUFA bootloader 4096
+# USBaspLoader 2048
+#OPT_DEFS += -DBOOTLOADER_SIZE=4096
+
+# as per original hasu settings
+OPT_DEFS += -DBOOTLOADER_SIZE=512
+
+# Build Options
+# comment out to disable the options.
+#
+BOOTMAGIC_ENABLE ?= yes # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE ?= yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450)
+CONSOLE_ENABLE ?= yes # Console for debug(+400)
+COMMAND_ENABLE ?= yes # Commands for debug and configuration
+CUSTOM_MATRIX ?= yes # Custom matrix file for the HHKB
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+# SLEEP_LED_ENABLE ?= yes # Breathing sleep LED during USB suspend
+# NKRO_ENABLE ?= yes # USB Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+# BACKLIGHT_ENABLE ?= yes # Enable keyboard backlight functionality
+# MIDI_ENABLE ?= YES # MIDI controls
+# UNICODE_ENABLE ?= YES # Unicode
+# BLUETOOTH_ENABLE ?= yes # Enable Bluetooth with the Adafruit EZ-Key HID
+
+
+
+ifndef QUANTUM_DIR
+ include ../../Makefile
+endif
+
+debug-on: EXTRAFLAGS += -DDEBUG -DDEBUG_ACTION
+debug-on: all
+
+debug-off: EXTRAFLAGS += -DNO_DEBUG -DNO_PRINT
+debug-off: OPT_DEFS := $(filter-out -DCONSOLE_ENABLE,$(OPT_DEFS))
+debug-off: all
diff --git a/keyboards/hhkb/config.h b/keyboards/hhkb/config.h
new file mode 100644
index 000000000..ee66e4457
--- /dev/null
+++ b/keyboards/hhkb/config.h
@@ -0,0 +1,71 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "config_common.h"
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0xCAFE
+#define DEVICE_VER 0x0104
+#define MANUFACTURER q.m.k
+#define PRODUCT HHKB mod
+#define DESCRIPTION q.m.k keyboard firmware for HHKB
+
+/* key matrix size */
+#define MATRIX_ROWS 8
+#define MATRIX_COLS 8
+
+#define TAPPING_TERM 200
+
+/* number of backlight levels */
+#define BACKLIGHT_LEVELS 3
+
+/* Set 0 if debouncing isn't needed */
+#define DEBOUNCE 5
+
+/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
+//#define LOCKING_SUPPORT_ENABLE
+/* Locking resynchronize hack */
+//#define LOCKING_RESYNC_ENABLE
+
+/* key combination for command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+/*
+ * Feature disable options
+ * These options are also useful to firmware size reduction.
+*/
+
+/* disable debug print */
+//#define NO_DEBUG
+
+/* disable print */
+//#define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+
+#endif
diff --git a/keyboards/hhkb/hhkb.c b/keyboards/hhkb/hhkb.c
new file mode 100644
index 000000000..a9d35123f
--- /dev/null
+++ b/keyboards/hhkb/hhkb.c
@@ -0,0 +1 @@
+#include "hhkb.h" \ No newline at end of file
diff --git a/keyboards/hhkb/hhkb.h b/keyboards/hhkb/hhkb.h
new file mode 100644
index 000000000..cc756c456
--- /dev/null
+++ b/keyboards/hhkb/hhkb.h
@@ -0,0 +1,24 @@
+#ifndef HHKB_H
+#define HHKB_H
+
+#include "quantum.h"
+
+#define KEYMAP( \
+ K31, K30, K00, K10, K11, K20, K21, K40, K41, K60, K61, K70, K71, K50, K51, \
+ K32, K01, K02, K13, K12, K23, K22, K42, K43, K62, K63, K73, K72, K52, \
+ K33, K04, K03, K14, K15, K24, K25, K45, K44, K65, K64, K74, K53, \
+ K34, K05, K06, K07, K16, K17, K26, K46, K66, K76, K75, K55, K54, \
+ K35, K36, K37, K57, K56) \
+ \
+{ \
+ { K00, K01, K02, K03, K04, K05, K06, K07 }, \
+ { K10, K11, K12, K13, K14, K15, K16, K17 }, \
+ { K20, K21, K22, K23, K24, K25, K26, KC_NO }, \
+ { K30, K31, K32, K33, K34, K35, K36, K37 }, \
+ { K40, K41, K42, K43, K44, K45, K46, KC_NO }, \
+ { K50, K51, K52, K53, K54, K55, K56, K57 }, \
+ { K60, K61, K62, K63, K64, K65, K66, KC_NO }, \
+ { K70, K71, K72, K73, K74, K75, K76, KC_NO } \
+}
+
+#endif
diff --git a/keyboards/hhkb/hhkb_avr.h b/keyboards/hhkb/hhkb_avr.h
new file mode 100644
index 000000000..7ea6322c7
--- /dev/null
+++ b/keyboards/hhkb/hhkb_avr.h
@@ -0,0 +1,167 @@
+#ifndef HHKB_AVR_H
+#define HHKB_AVR_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <util/delay.h>
+
+
+// Timer resolution check
+#if (1000000/TIMER_RAW_FREQ > 20)
+# error "Timer resolution(>20us) is not enough for HHKB matrix scan tweak on V-USB."
+#endif
+
+
+/*
+ * HHKB Matrix I/O
+ *
+ * row: HC4051[A,B,C] selects scan row0-7
+ * row-ext: [En0,En1] row extention for JP
+ * col: LS145[A,B,C,D] selects scan col0-7 and enable(D)
+ * key: on: 0/off: 1
+ * prev: hysteresis control: assert(1) when previous key state is on
+ */
+
+
+#if defined(__AVR_ATmega32U4__)
+/*
+ * For TMK HHKB alt controller(ATMega32U4)
+ *
+ * row: PB0-2
+ * col: PB3-5,6
+ * key: PD7(pull-uped)
+ * prev: PB7
+ * power: PD4(L:off/H:on)
+ * row-ext: PC6,7 for HHKB JP(active low)
+ */
+static inline void KEY_ENABLE(void) { (PORTB &= ~(1<<6)); }
+static inline void KEY_UNABLE(void) { (PORTB |= (1<<6)); }
+static inline bool KEY_STATE(void) { return (PIND & (1<<7)); }
+static inline void KEY_PREV_ON(void) { (PORTB |= (1<<7)); }
+static inline void KEY_PREV_OFF(void) { (PORTB &= ~(1<<7)); }
+#ifdef HHKB_POWER_SAVING
+static inline void KEY_POWER_ON(void) {
+ DDRB = 0xFF; PORTB = 0x40; // change pins output
+ DDRD |= (1<<4); PORTD |= (1<<4); // MOS FET switch on
+ /* Without this wait you will miss or get false key events. */
+ _delay_ms(5); // wait for powering up
+}
+static inline void KEY_POWER_OFF(void) {
+ /* input with pull-up consumes less than without it when pin is open. */
+ DDRB = 0x00; PORTB = 0xFF; // change pins input with pull-up
+ DDRD |= (1<<4); PORTD &= ~(1<<4); // MOS FET switch off
+}
+static inline bool KEY_POWER_STATE(void) { return PORTD & (1<<4); }
+#else
+static inline void KEY_POWER_ON(void) {}
+static inline void KEY_POWER_OFF(void) {}
+static inline bool KEY_POWER_STATE(void) { return true; }
+#endif
+static inline void KEY_INIT(void)
+{
+ /* row,col,prev: output */
+ DDRB = 0xFF;
+ PORTB = 0x40; // unable
+ /* key: input with pull-up */
+ DDRD &= ~0x80;
+ PORTD |= 0x80;
+#ifdef HHKB_JP
+ /* row extention for HHKB JP */
+ DDRC |= (1<<6|1<<7);
+ PORTC |= (1<<6|1<<7);
+#endif
+ KEY_UNABLE();
+ KEY_PREV_OFF();
+
+ KEY_POWER_OFF();
+}
+static inline void KEY_SELECT(uint8_t ROW, uint8_t COL)
+{
+ PORTB = (PORTB & 0xC0) | (((COL) & 0x07)<<3) | ((ROW) & 0x07);
+#ifdef HHKB_JP
+ if ((ROW) & 0x08) PORTC = (PORTC & ~(1<<6|1<<7)) | (1<<6);
+ else PORTC = (PORTC & ~(1<<6|1<<7)) | (1<<7);
+#endif
+}
+
+
+#elif defined(__AVR_AT90USB1286__)
+/*
+ * For Teensy++(AT90USB1286)
+ *
+ * HHKB pro HHKB pro2
+ * row: PB0-2 (6-8) (5-7)
+ * col: PB3-5,6 (9-12) (8-11)
+ * key: PE6(pull-uped) (4) (3)
+ * prev: PE7 (5) (4)
+ *
+ * TODO: convert into 'staitc inline' function
+ */
+#define KEY_INIT() do { \
+ DDRB |= 0x7F; \
+ DDRE |= (1<<7); \
+ DDRE &= ~(1<<6); \
+ PORTE |= (1<<6); \
+} while (0)
+#define KEY_SELECT(ROW, COL) (PORTB = (PORTB & 0xC0) | \
+ (((COL) & 0x07)<<3) | \
+ ((ROW) & 0x07))
+#define KEY_ENABLE() (PORTB &= ~(1<<6))
+#define KEY_UNABLE() (PORTB |= (1<<6))
+#define KEY_STATE() (PINE & (1<<6))
+#define KEY_PREV_ON() (PORTE |= (1<<7))
+#define KEY_PREV_OFF() (PORTE &= ~(1<<7))
+#define KEY_POWER_ON()
+#define KEY_POWER_OFF()
+#define KEY_POWER_STATE() true
+
+
+#else
+# error "define code for matrix scan"
+#endif
+
+
+#if 0
+// For ATMega328P with V-USB
+//
+// #elif defined(__AVR_ATmega328P__)
+// Ports for V-USB
+// key: PB0(pull-uped)
+// prev: PB1
+// row: PB2-4
+// col: PC0-2,3
+// power: PB5(Low:on/Hi-z:off)
+#define KEY_INIT() do { \
+ DDRB |= 0x3E; \
+ DDRB &= ~(1<<0); \
+ PORTB |= 1<<0; \
+ DDRC |= 0x0F; \
+ KEY_UNABLE(); \
+ KEY_PREV_OFF(); \
+} while (0)
+#define KEY_SELECT(ROW, COL) do { \
+ PORTB = (PORTB & 0xE3) | ((ROW) & 0x07)<<2; \
+ PORTC = (PORTC & 0xF8) | ((COL) & 0x07); \
+} while (0)
+#define KEY_ENABLE() (PORTC &= ~(1<<3))
+#define KEY_UNABLE() (PORTC |= (1<<3))
+#define KEY_STATE() (PINB & (1<<0))
+#define KEY_PREV_ON() (PORTB |= (1<<1))
+#define KEY_PREV_OFF() (PORTB &= ~(1<<1))
+// Power supply switching
+#define KEY_POWER_ON() do { \
+ KEY_INIT(); \
+ PORTB &= ~(1<<5); \
+ _delay_ms(1); \
+} while (0)
+#define KEY_POWER_OFF() do { \
+ DDRB &= ~0x3F; \
+ PORTB &= ~0x3F; \
+ DDRC &= ~0x0F; \
+ PORTC &= ~0x0F; \
+} while (0)
+#endif
+
+#endif
diff --git a/keyboards/hhkb/keymaps/default/keymap.c b/keyboards/hhkb/keymaps/default/keymap.c
new file mode 100644
index 000000000..bd5dd8372
--- /dev/null
+++ b/keyboards/hhkb/keymaps/default/keymap.c
@@ -0,0 +1,78 @@
+/* -*- eval: (turn-on-orgtbl); -*-
+ * default HHKB Layout
+ */
+#include "hhkb.h"
+
+#define BASE 0
+#define HHKB 1
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+
+ /* BASE Level: Default Layer
+ |-------+---+---+---+---+---+---+---+---+---+---+-------+-----+-------+---|
+ | Esc | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | - | = | \ | ` |
+ |-------+---+---+---+---+---+---+---+---+---+---+-------+-----+-------+---|
+ | Tab | Q | W | E | R | T | Y | U | I | O | P | [ | ] | Backs | |
+ |-------+---+---+---+---+---+---+---+---+---+---+-------+-----+-------+---|
+ | Cont | A | S | D | F | G | H | J | K | L | ; | ' | Ent | | |
+ |-------+---+---+---+---+---+---+---+---+---+---+-------+-----+-------+---|
+ | Shift | Z | X | C | V | B | N | M | , | . | / | Shift | Fn0 | | |
+ |-------+---+---+---+---+---+---+---+---+---+---+-------+-----+-------+---|
+
+ |------+------+-----------------------+------+------|
+ | LAlt | LGUI | ******* Space ******* | RGUI | RAlt |
+ |------+------+-----------------------+------+------|
+ */
+
+ [BASE] = KEYMAP( // default layer
+ KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSLS, KC_GRV, \
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSPC, \
+ KC_LCTL, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, \
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, MO(HHKB), \
+ KC_LALT, KC_LGUI, /* */ KC_SPC, KC_RGUI, KC_RALT),
+
+
+
+ /* Layer HHKB: HHKB mode (HHKB Fn)
+ |------+-----+-----+-----+----+----+----+----+-----+-----+-----+-----+-------+-------+-----|
+ | Pwr | F1 | F2 | F3 | F4 | F5 | F6 | F7 | F8 | F9 | F10 | F11 | F12 | Ins | Del |
+ |------+-----+-----+-----+----+----+----+----+-----+-----+-----+-----+-------+-------+-----|
+ | Caps | | | | | | | | Psc | Slk | Pus | Up | | Backs | |
+ |------+-----+-----+-----+----+----+----+----+-----+-----+-----+-----+-------+-------+-----|
+ | | VoD | VoU | Mut | | | * | / | Hom | PgU | Lef | Rig | Enter | | |
+ |------+-----+-----+-----+----+----+----+----+-----+-----+-----+-----+-------+-------+-----|
+ | | | | | | | + | - | End | PgD | Dow | | | | |
+ |------+-----+-----+-----+----+----+----+----+-----+-----+-----+-----+-------+-------+-----|
+
+ |------+------+----------------------+------+------+
+ | **** | **** | ******************** | **** | **** |
+ |------+------+----------------------+------+------+
+
+ */
+
+ [HHKB] = KEYMAP(
+ KC_PWR, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_INS, KC_DEL, \
+ KC_CAPS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PSCR, KC_SLCK, KC_PAUS, KC_UP, KC_TRNS, KC_BSPC, \
+ KC_TRNS, KC_VOLD, KC_VOLU, KC_MUTE, KC_TRNS, KC_TRNS, KC_PAST, KC_PSLS, KC_HOME, KC_PGUP, KC_LEFT, KC_RGHT, KC_PENT, \
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PPLS, KC_PMNS, KC_END, KC_PGDN, KC_DOWN, KC_TRNS, KC_TRNS, \
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS)};
+
+
+const uint16_t PROGMEM fn_actions[] = {
+
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
diff --git a/keyboards/hhkb/keymaps/lxol/keymap.c b/keyboards/hhkb/keymaps/lxol/keymap.c
new file mode 100644
index 000000000..ccf1e0704
--- /dev/null
+++ b/keyboards/hhkb/keymaps/lxol/keymap.c
@@ -0,0 +1,208 @@
+/* -*- eval: (turn-on-orgtbl); -*-
+ * lxol HHKB Layout
+ */
+#include "hhkb.h"
+
+#define BASE 0
+#define WIN 1
+#define HHKB 2
+#define RGUILEV 3
+#define LGUILEV 4
+#define RALTLEV 5
+#define LALTLEV 6
+
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+
+ /* Layer 0: Default Layer
+ |--------+---+---+---+---+---+---+---+---+---+-----+-------+----------+-------+---|
+ | Esc | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | - | = | \ | ` |
+ |--------+---+---+---+---+---+---+---+---+---+-----+-------+----------+-------+---|
+ | Tab | Q | W | E | R | T | Y | U | I | O | P | [ | ] | Backs | |
+ |--------+---+---+---+---+---+---+---+---+---+-----+-------+----------+-------+---|
+ | Contro | A | S | D | F | G | H | J | K | L | ; | ' | RCtl/Ent | | |
+ |--------+---+---+---+---+---+---+---+---+---+-----+-------+----------+-------+---|
+ | Shift | Z | X | C | V | B | N | M | , | . | Fn2 | Shift | Fn0 | | |
+ |--------+---+---+---+---+---+---+---+---+---+-----+-------+----------+-------+---|
+
+ |------+------+-------+------+------|
+ | LAlt | LGUI | Space | RGUI | RAlt |
+ |------+------+-------+------+------|
+ */
+
+ [BASE] = KEYMAP( // layer 0 : default
+
+
+ KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSLS, KC_GRV, \
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSPC, \
+ KC_LCTL, LT(LALTLEV,KC_A), LT(LGUILEV,KC_S), KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, LT(RGUILEV,KC_L), LT(RALTLEV,KC_SCLN), KC_QUOT, KC_FN0, \
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, MO(HHKB), \
+ KC_LALT, KC_LGUI, KC_SPC, KC_RGUI, KC_RALT),
+
+
+
+ /* Layer 1: HHKB mode (HHKB Fn)
+ |------+-----+-----+-----+----+----+----+----+-----+-----+-----+-----+-------+-------+-----|
+ | Pwr | F1 | F2 | F3 | F4 | F5 | F6 | F7 | F8 | F9 | F10 | F11 | F12 | Ins | Del |
+ |------+-----+-----+-----+----+----+----+----+-----+-----+-----+-----+-------+-------+-----|
+ | Caps | | | | | | | | Psc | Slk | Pus | Up | | Backs | |
+ |------+-----+-----+-----+----+----+----+----+-----+-----+-----+-----+-------+-------+-----|
+ | | VoD | VoU | Mut | | | * | / | Hom | PgU | Lef | Rig | Enter | | |
+ |------+-----+-----+-----+----+----+----+----+-----+-----+-----+-----+-------+-------+-----|
+ | | | | | | | + | - | End | PgD | Dow | | | | |
+ |------+-----+-----+-----+----+----+----+----+-----+-----+-----+-----+-------+-------+-----|
+
+ |---+---+---+---+---|
+ | | | | | |
+ |---+---+---+---+---|
+ */
+
+ [HHKB] = KEYMAP(
+ KC_PWR, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_INS, KC_DEL, \
+ KC_CAPS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PSCR, KC_SLCK, KC_PAUS, KC_UP, KC_TRNS, KC_BSPC, \
+ KC_TRNS, KC_VOLD, KC_VOLU, KC_MUTE, KC_TRNS, KC_TRNS, KC_PAST, KC_PSLS, KC_HOME, KC_PGUP, KC_LEFT, KC_RGHT, KC_PENT, \
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PPLS, KC_PMNS, KC_END, KC_PGDN, KC_DOWN, KC_TRNS, KC_TRNS, \
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS),
+
+
+ /* Layer LGUI: All keys with RGUI modifier
+ |--------+---+---+---+---+---+---+---+---+---+-----+-------+----------+-------+---|
+ | Esc | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | - | = | \ | ` |
+ |--------+---+---+---+---+---+---+---+---+---+-----+-------+----------+-------+---|
+ | Tab | Q | W | E | R | T | Y | U | I | O | P | [ | ] | Backs | |
+ |--------+---+---+---+---+---+---+---+---+---+-----+-------+----------+-------+---|
+ | Contro | A | S | D | F | G | H | J | K | | ; | ' | RCtl/Ent | | |
+ |--------+---+---+---+---+---+---+---+---+---+-----+-------+----------+-------+---|
+ | Shift | Z | X | C | V | B | N | M | , | . | Fn2 | Shift | Fn0 | | |
+ |--------+---+---+---+---+---+---+---+---+---+-----+-------+----------+-------+---|
+
+ |------+------+-------+------+------|
+ | LAlt | LGUI | Space | RGUI | RAlt |
+ |------+------+-------+------+------|
+ */
+
+ [RGUILEV] = KEYMAP( // Right GUI layer by KC_L
+
+ RGUI(KC_ESC), RGUI(KC_1), RGUI(KC_2), RGUI(KC_3), RGUI(KC_4), RGUI(KC_5), RGUI(KC_6), RGUI(KC_7), RGUI(KC_8), RGUI(KC_9), RGUI(KC_0), RGUI(KC_MINS), RGUI(KC_EQL), RGUI(KC_BSLS), RGUI(KC_GRV), \
+ RGUI(KC_TAB), RGUI(KC_Q), RGUI(KC_W), RGUI(KC_E), RGUI(KC_R), RGUI(KC_T), RGUI(KC_Y), RGUI(KC_U), RGUI(KC_I), RGUI(KC_O), RGUI(KC_P), RGUI(KC_LBRC), RGUI(KC_RBRC), RGUI(KC_BSPC), \
+ RGUI(KC_LCTL), RGUI(KC_A), RGUI(KC_S), RGUI(KC_D), RGUI(KC_F), RGUI(KC_G), RGUI(KC_H), RGUI(KC_J), RGUI(KC_K), KC_TRNS, KC_TRNS, RGUI(KC_QUOT), KC_FN0, \
+ RGUI(KC_LSFT), RGUI(KC_Z), RGUI(KC_X), RGUI(KC_C), RGUI(KC_V), RGUI(KC_B), RGUI(KC_N), RGUI(KC_M), RGUI(KC_COMM), RGUI(KC_DOT), RGUI(KC_SLSH), RGUI(KC_RSFT), KC_TRNS, \
+ KC_LALT, KC_LGUI, RGUI(KC_SPC), KC_RGUI, KC_RALT),
+
+ /* Layer LGUI: All keys with LGUI modifier
+ |--------+---+---+---+---+---+---+---+---+---+-----+-------+----------+-------+---|
+ | Esc | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | - | = | \ | ` |
+ |--------+---+---+---+---+---+---+---+---+---+-----+-------+----------+-------+---|
+ | Tab | Q | W | E | R | T | Y | U | I | O | P | [ | ] | Backs | |
+ |--------+---+---+---+---+---+---+---+---+---+-----+-------+----------+-------+---|
+ | Contro | A | S | D | F | G | H | J | K | | ; | ' | RCtl/Ent | | |
+ |--------+---+---+---+---+---+---+---+---+---+-----+-------+----------+-------+---|
+ | Shift | Z | X | C | V | B | N | M | , | . | Fn2 | Shift | Fn0 | | |
+ |--------+---+---+---+---+---+---+---+---+---+-----+-------+----------+-------+---|
+
+ |------+------+-------+------+------|
+ | LAlt | LGUI | Space | LGUI | RAlt |
+ |------+------+-------+------+------|
+ */
+
+ [LGUILEV] = KEYMAP( // Right GUI layer by KC_L
+
+ LGUI(KC_ESC), LGUI(KC_1), LGUI(KC_2), LGUI(KC_3), LGUI(KC_4), LGUI(KC_5), LGUI(KC_6), LGUI(KC_7), LGUI(KC_8), LGUI(KC_9), LGUI(KC_0), LGUI(KC_MINS), LGUI(KC_EQL), LGUI(KC_BSLS), LGUI(KC_GRV), \
+ LGUI(KC_TAB), LGUI(KC_Q), LGUI(KC_W), LGUI(KC_E), LGUI(KC_R), LGUI(KC_T), LGUI(KC_Y), LGUI(KC_U), LGUI(KC_I), LGUI(KC_O), LGUI(KC_P), LGUI(KC_LBRC), LGUI(KC_RBRC), LGUI(KC_BSPC), \
+ LGUI(KC_LCTL), KC_TRNS, KC_TRNS, LGUI(KC_D), LGUI(KC_F), LGUI(KC_G), LGUI(KC_H), LGUI(KC_J), LGUI(KC_K), LGUI(KC_L), LGUI(KC_SCLN), LGUI(KC_QUOT), KC_FN0, \
+ KC_LSFT, LGUI(KC_Z), LGUI(KC_X), LGUI(KC_C), LGUI(KC_V), LGUI(KC_B), LGUI(KC_N), LGUI(KC_M), LGUI(KC_COMM), LGUI(KC_DOT), LGUI(KC_SLSH), KC_RSFT, KC_TRNS, \
+ KC_LALT, KC_LGUI, LGUI(KC_SPC), KC_LGUI, KC_RALT),
+
+ /* Layer LALT: All keys with RALT modifier
+ |--------+---+---+---+---+---+---+---+---+---+-----+-------+----------+-------+---|
+ | Esc | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | - | = | \ | ` |
+ |--------+---+---+---+---+---+---+---+---+---+-----+-------+----------+-------+---|
+ | Tab | Q | W | E | R | T | Y | U | I | O | P | [ | ] | Backs | |
+ |--------+---+---+---+---+---+---+---+---+---+-----+-------+----------+-------+---|
+ | Contro | A | S | D | F | G | H | J | K | | ; | ' | RCtl/Ent | | |
+ |--------+---+---+---+---+---+---+---+---+---+-----+-------+----------+-------+---|
+ | Shift | Z | X | C | V | B | N | M | , | . | Fn2 | Shift | Fn0 | | |
+ |--------+---+---+---+---+---+---+---+---+---+-----+-------+----------+-------+---|
+
+ |------+------+-------+------+------|
+ | LAlt | LGUI | Space | RGUI | RAlt |
+ |------+------+-------+------+------|
+ */
+
+ [RALTLEV] = KEYMAP( // Right ALT layer by KC_L
+
+ RALT(KC_ESC), RALT(KC_1), RALT(KC_2), RALT(KC_3), RALT(KC_4), RALT(KC_5), RALT(KC_6), RALT(KC_7), RALT(KC_8), RALT(KC_9), RALT(KC_0), RALT(KC_MINS), RALT(KC_EQL), RALT(KC_BSLS), RALT(KC_GRV), \
+ RALT(KC_TAB), RALT(KC_Q), RALT(KC_W), RALT(KC_E), RALT(KC_R), RALT(KC_T), RALT(KC_Y), RALT(KC_U), RALT(KC_I), RALT(KC_O), RALT(KC_P), RALT(KC_LBRC), RALT(KC_RBRC), RALT(KC_BSPC), \
+ RALT(KC_LCTL), RALT(KC_A), RALT(KC_S), RALT(KC_D), RALT(KC_F), RALT(KC_G), RALT(KC_H), RALT(KC_J), RALT(KC_K), KC_TRNS, KC_TRNS, RALT(KC_QUOT), KC_FN0, \
+ RALT(KC_LSFT), RALT(KC_Z), RALT(KC_X), RALT(KC_C), RALT(KC_V), RALT(KC_B), RALT(KC_N), RALT(KC_M), RALT(KC_COMM), RALT(KC_DOT), RALT(KC_SLSH), RALT(KC_RSFT), KC_TRNS, \
+ KC_LALT, KC_LGUI, RALT(KC_SPC), KC_RGUI, KC_RALT),
+
+ /* Layer LALT: All keys with LALT modifier
+ |--------+---+---+---+---+---+---+---+---+---+-----+-------+----------+-------+---|
+ | Esc | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | - | = | \ | ` |
+ |--------+---+---+---+---+---+---+---+---+---+-----+-------+----------+-------+---|
+ | Tab | Q | W | E | R | T | Y | U | I | O | P | [ | ] | Backs | |
+ |--------+---+---+---+---+---+---+---+---+---+-----+-------+----------+-------+---|
+ | Contro | A | S | D | F | G | H | J | K | | ; | ' | RCtl/Ent | | |
+ |--------+---+---+---+---+---+---+---+---+---+-----+-------+----------+-------+---|
+ | Shift | Z | X | C | V | B | N | M | , | . | Fn2 | Shift | Fn0 | | |
+ |--------+---+---+---+---+---+---+---+---+---+-----+-------+----------+-------+---|
+
+ |------+------+-------+------+------|
+ | LAlt | LGUI | Space | LGUI | RAlt |
+ |------+------+-------+------+------|
+ */
+
+ [LALTLEV] = KEYMAP( // Right ALT layer by KC_L
+
+ LALT(KC_ESC), LALT(KC_1), LALT(KC_2), LALT(KC_3), LALT(KC_4), LALT(KC_5), LALT(KC_6), LALT(KC_7), LALT(KC_8), LALT(KC_9), LALT(KC_0), LALT(KC_MINS), LALT(KC_EQL), LALT(KC_BSLS), LALT(KC_GRV), \
+ LALT(KC_TAB), LALT(KC_Q), LALT(KC_W), LALT(KC_E), LALT(KC_R), LALT(KC_T), LALT(KC_Y), LALT(KC_U), LALT(KC_I), LALT(KC_O), LALT(KC_P), LALT(KC_LBRC), LALT(KC_RBRC), LALT(KC_BSPC), \
+ LALT(KC_LCTL), KC_TRNS, KC_TRNS, LALT(KC_D), LALT(KC_F), LALT(KC_G), LALT(KC_H), LALT(KC_J), LALT(KC_K), LALT(KC_L), LALT(KC_SCLN), LALT(KC_QUOT), KC_FN0, \
+ KC_LSFT, LALT(KC_Z), LALT(KC_X), LALT(KC_C), LALT(KC_V), LALT(KC_B), LALT(KC_N), LALT(KC_M), LALT(KC_COMM), LALT(KC_DOT), LALT(KC_SLSH), KC_RSFT, KC_TRNS, \
+ KC_LALT, KC_LGUI, LALT(KC_SPC), KC_LGUI, KC_RALT),
+
+
+ /* Layer WIN: Win layer
+ |--------+---+---+---+---+---+---+---+---+---+---+-------+----------+-------+---|
+ | Esc | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | - | = | \ | ` |
+ |--------+---+---+---+---+---+---+---+---+---+---+-------+----------+-------+---|
+ | Tab | Q | W | E | R | T | Y | U | I | O | P | [ | ] | Backs | |
+ |--------+---+---+---+---+---+---+---+---+---+---+-------+----------+-------+---|
+ | Contro | A | S | D | F | G | H | J | K | L | ; | ' | RCtl/Ent | | |
+ |--------+---+---+---+---+---+---+---+---+---+---+-------+----------+-------+---|
+ | Shift | Z | X | C | V | B | N | M | , | . | / | Shift | Fn0 | | |
+ |--------+---+---+---+---+---+---+---+---+---+---+-------+----------+-------+---|
+
+ |------+------+-------+------+------|
+ | LGui | LAlt | Space | RGui | Ralt |
+ |------+------+-------+------+------|
+ */
+
+ [WIN] = KEYMAP( // BASE level with swapped GUI/ALT
+
+
+ KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSLS, KC_GRV, \
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSPC, \
+ KC_LCTL, LT(LGUILEV,KC_A), LT(LALTLEV,KC_S), KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, LT(RALTLEV,KC_L), LT(RGUILEV,KC_SCLN), KC_QUOT, KC_FN0, \
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, MO(HHKB), \
+ KC_RGUI, KC_RALT, KC_SPC, KC_RALT, KC_RGUI)};
+
+
+const uint16_t PROGMEM fn_actions[] = {
+ [0] = ACTION_MODS_TAP_KEY(MOD_RCTL, KC_ENT) // RControl with tap Enter*
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
diff --git a/keyboards/hhkb/matrix.c b/keyboards/hhkb/matrix.c
new file mode 100644
index 000000000..666b6f595
--- /dev/null
+++ b/keyboards/hhkb/matrix.c
@@ -0,0 +1,215 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * scan matrix
+ */
+#include <stdint.h>
+#include <stdbool.h>
+#include <util/delay.h>
+#include "print.h"
+#include "debug.h"
+#include "util.h"
+#include "timer.h"
+#include "matrix.h"
+#include "hhkb_avr.h"
+#include <avr/wdt.h>
+#include "suspend.h"
+#include "lufa.h"
+
+
+// matrix power saving
+#define MATRIX_POWER_SAVE 10000
+static uint32_t matrix_last_modified = 0;
+
+// matrix state buffer(1:on, 0:off)
+static matrix_row_t *matrix;
+static matrix_row_t *matrix_prev;
+static matrix_row_t _matrix0[MATRIX_ROWS];
+static matrix_row_t _matrix1[MATRIX_ROWS];
+
+
+inline
+uint8_t matrix_rows(void)
+{
+ return MATRIX_ROWS;
+}
+
+inline
+uint8_t matrix_cols(void)
+{
+ return MATRIX_COLS;
+}
+
+void matrix_init(void)
+{
+#ifdef DEBUG
+ debug_enable = true;
+ debug_keyboard = true;
+#endif
+
+ KEY_INIT();
+
+ // initialize matrix state: all keys off
+ for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00;
+ for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix1[i] = 0x00;
+ matrix = _matrix0;
+ matrix_prev = _matrix1;
+}
+
+__attribute__ ((weak))
+void matrix_scan_user(void) {
+}
+
+void matrix_scan_kb(void) {
+ matrix_scan_user();
+}
+
+uint8_t matrix_scan(void)
+{
+ uint8_t *tmp;
+
+ tmp = matrix_prev;
+ matrix_prev = matrix;
+ matrix = tmp;
+
+ // power on
+ if (!KEY_POWER_STATE()) KEY_POWER_ON();
+ for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
+ for (uint8_t col = 0; col < MATRIX_COLS; col++) {
+ KEY_SELECT(row, col);
+ _delay_us(5);
+
+ // Not sure this is needed. This just emulates HHKB controller's behaviour.
+ if (matrix_prev[row] & (1<<col)) {
+ KEY_PREV_ON();
+ }
+ _delay_us(10);
+
+ // NOTE: KEY_STATE is valid only in 20us after KEY_ENABLE.
+ // If V-USB interrupts in this section we could lose 40us or so
+ // and would read invalid value from KEY_STATE.
+ uint8_t last = TIMER_RAW;
+
+ KEY_ENABLE();
+
+ // Wait for KEY_STATE outputs its value.
+ // 1us was ok on one HHKB, but not worked on another.
+ // no wait doesn't work on Teensy++ with pro(1us works)
+ // no wait does work on tmk PCB(8MHz) with pro2
+ // 1us wait does work on both of above
+ // 1us wait doesn't work on tmk(16MHz)
+ // 5us wait does work on tmk(16MHz)
+ // 5us wait does work on tmk(16MHz/2)
+ // 5us wait does work on tmk(8MHz)
+ // 10us wait does work on Teensy++ with pro
+ // 10us wait does work on 328p+iwrap with pro
+ // 10us wait doesn't work on tmk PCB(8MHz) with pro2(very lagged scan)
+ _delay_us(5);
+
+ if (KEY_STATE()) {
+ matrix[row] &= ~(1<<col);
+ } else {
+ matrix[row] |= (1<<col);
+ }
+
+ // Ignore if this code region execution time elapses more than 20us.
+ // MEMO: 20[us] * (TIMER_RAW_FREQ / 1000000)[count per us]
+ // MEMO: then change above using this rule: a/(b/c) = a*1/(b/c) = a*(c/b)
+ if (TIMER_DIFF_RAW(TIMER_RAW, last) > 20/(1000000/TIMER_RAW_FREQ)) {
+ matrix[row] = matrix_prev[row];
+ }
+
+ _delay_us(5);
+ KEY_PREV_OFF();
+ KEY_UNABLE();
+
+ // NOTE: KEY_STATE keep its state in 20us after KEY_ENABLE.
+ // This takes 25us or more to make sure KEY_STATE returns to idle state.
+#ifdef HHKB_JP
+ // Looks like JP needs faster scan due to its twice larger matrix
+ // or it can drop keys in fast key typing
+ _delay_us(30);
+#else
+ _delay_us(75);
+#endif
+ }
+ if (matrix[row] ^ matrix_prev[row]) matrix_last_modified = timer_read32();
+ }
+ // power off
+ if (KEY_POWER_STATE() &&
+ (USB_DeviceState == DEVICE_STATE_Suspended ||
+ USB_DeviceState == DEVICE_STATE_Unattached ) &&
+ timer_elapsed32(matrix_last_modified) > MATRIX_POWER_SAVE) {
+ KEY_POWER_OFF();
+ suspend_power_down();
+ }
+
+ matrix_scan_quantum();
+
+ return 1;
+}
+
+bool matrix_is_modified(void)
+{
+ for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+ if (matrix[i] != matrix_prev[i])
+ return true;
+ }
+ return false;
+}
+
+inline
+bool matrix_has_ghost(void)
+{
+ return false;
+}
+
+inline
+bool matrix_is_on(uint8_t row, uint8_t col)
+{
+ return (matrix[row] & (1<<col));
+}
+
+inline
+matrix_row_t matrix_get_row(uint8_t row)
+{
+ return matrix[row];
+}
+
+void matrix_print(void)
+{
+ print("\nr/c 01234567\n");
+ for (uint8_t row = 0; row < matrix_rows(); row++) {
+ xprintf("%02X: %08b\n", row, bitrev(matrix_get_row(row)));
+ }
+}
+
+uint8_t matrix_key_count(void) {
+ uint8_t count = 0;
+ for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
+ count += bitpop16(matrix_get_row(r));
+ }
+ return count;
+}
+
+void matrix_power_up(void) {
+ KEY_POWER_ON();
+}
+void matrix_power_down(void) {
+ KEY_POWER_OFF();
+}
diff --git a/keyboards/hhkb/readme.md b/keyboards/hhkb/readme.md
new file mode 100644
index 000000000..39d49b32a
--- /dev/null
+++ b/keyboards/hhkb/readme.md
@@ -0,0 +1,180 @@
+hhkb_qmk keyboard firmware
+======================
+
+## Quantum MK Firmware
+
+You have access to a bunch of goodies! Check out the Makefile to enable/disable some of the features. Uncomment the `#` to enable them. Setting them to `no` does nothing and will only confuse future you.
+
+ BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
+ MIDI_ENABLE = yes # MIDI controls
+ # UNICODE_ENABLE = yes # Unicode support - this is commented out, just as an example. You have to use #, not //
+ BLUETOOTH_ENABLE = yes # Enable Bluetooth with the Adafruit EZ-Key HID
+
+## Quick aliases to common actions
+
+Your keymap can include shortcuts to common operations (called "function actions" in tmk).
+
+### Switching and toggling layers
+
+`MO(layer)` - momentary switch to *layer*. As soon as you let go of the key, the layer is deactivated and you pop back out to the previous layer. When you apply this to a key, that same key must be set as `KC_TRNS` on the destination layer. Otherwise, you won't make it back to the original layer when you release the key (and you'll get a keycode sent). You can only switch to layers *above* your current layer. If you're on layer 0 and you use `MO(1)`, that will switch to layer 1 just fine. But if you include `MO(3)` on layer 5, that won't do anything for you -- because layer 3 is lower than layer 5 on the stack.
+
+`LT(layer, kc)` - momentary switch to *layer* when held, and *kc* when tapped. Like `MO()`, this only works upwards in the layer stack (`layer` must be higher than the current layer).
+
+`TG(layer)` - toggles a layer on or off. As with `MO()`, you should set this key as `KC_TRNS` in the destination layer so that tapping it again actually toggles back to the original layer. Only works upwards in the layer stack.
+
+### Fun with modifier keys
+
+* `LSFT(kc)` - applies left Shift to *kc* (keycode) - `S(kc)` is an alias
+* `RSFT(kc)` - applies right Shift to *kc*
+* `LCTL(kc)` - applies left Control to *kc*
+* `RCTL(kc)` - applies right Control to *kc*
+* `LALT(kc)` - applies left Alt to *kc*
+* `RALT(kc)` - applies right Alt to *kc*
+* `LGUI(kc)` - applies left GUI (command/win) to *kc*
+* `RGUI(kc)` - applies right GUI (command/win) to *kc*
+
+You can also chain these, like this:
+
+ LALT(LCTL(KC_DEL)) -- this makes a key that sends Alt, Control, and Delete in a single keypress.
+
+The following shortcuts automatically add `LSFT()` to keycodes to get commonly used symbols. Their long names are also available and documented in `/quantum/keymap_common.h`.
+
+ KC_TILD ~
+ KC_EXLM !
+ KC_AT @
+ KC_HASH #
+ KC_DLR $
+ KC_PERC %
+ KC_CIRC ^
+ KC_AMPR &
+ KC_ASTR *
+ KC_LPRN (
+ KC_RPRN )
+ KC_UNDS _
+ KC_PLUS +
+ KC_LCBR {
+ KC_RCBR }
+ KC_PIPE |
+ KC_COLN :
+
+`MT(mod, kc)` - is *mod* (modifier key - MOD_LCTL, MOD_LSFT) when held, and *kc* when tapped. In other words, you can have a key that sends Esc (or the letter O or whatever) when you tap it, but works as a Control key or a Shift key when you hold it down.
+
+These are the values you can use for the `mod` in `MT()` (right-hand modifiers are not available):
+
+ * MOD_LCTL
+ * MOD_LSFT
+ * MOD_LALT
+ * MOD_LGUI
+
+These can also be combined like `MOD_LCTL | MOD_LSFT` e.g. `MT(MOD_LCTL | MOD_LSFT, KC_ESC)` which would activate Control and Shift when held, and send Escape when tapped.
+
+We've added shortcuts to make common modifier/tap (mod-tap) mappings more compact:
+
+ * `CTL_T(kc)` - is LCTL when held and *kc* when tapped
+ * `SFT_T(kc)` - is LSFT when held and *kc* when tapped
+ * `ALT_T(kc)` - is LALT when held and *kc* when tapped
+ * `GUI_T(kc)` - is LGUI when held and *kc* when tapped
+ * `ALL_T(kc)` - is Hyper (all mods) when held and *kc* when tapped. To read more about what you can do with a Hyper key, see [this blog post by Brett Terpstra](http://brettterpstra.com/2012/12/08/a-useful-caps-lock-key/)
+
+### Temporarily setting the default layer
+
+`DF(layer)` - sets default layer to *layer*. The default layer is the one at the "bottom" of the layer stack - the ultimate fallback layer. This currently does not persist over power loss. When you plug the keyboard back in, layer 0 will always be the default. It is theoretically possible to work around that, but that's not what `DF` does.
+
+### Remember: These are just aliases
+
+These functions work the same way that their `ACTION_*` functions do - they're just quick aliases. To dig into all of the tmk ACTION_* functions, please see the [TMK documentation](https://github.com/jackhumbert/qmk_firmware/blob/master/tmk_core/doc/keymap.md#2-action).
+
+Instead of using `FNx` when defining `ACTION_*` functions, you can use `F(x)` - the benefit here is being able to use more than 32 function actions (up to 4096), if you happen to need them.
+
+## Macro shortcuts: Send a whole string when pressing just one key
+
+Instead of using the `ACTION_MACRO` function, you can simply use `M(n)` to access macro *n* - *n* will get passed into the `action_get_macro` as the `id`, and you can use a switch statement to trigger it. This gets called on the keydown and keyup, so you'll need to use an if statement testing `record->event.pressed` (see keymap_default.c).
+
+```c
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) // this is the function signature -- just copy/paste it into your keymap file as it is.
+{
+ switch(id) {
+ case 0: // this would trigger when you hit a key mapped as M(0)
+ if (record->event.pressed) {
+ return MACRO( I(255), T(H), T(E), T(L), T(L), W(255), T(O), END ); // this sends the string 'hello' when the macro executes
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+```
+A macro can include the following commands:
+
+* I() change interval of stroke in milliseconds.
+* D() press key.
+* U() release key.
+* T() type key(press and release).
+* W() wait (milliseconds).
+* END end mark.
+
+So above you can see the stroke interval changed to 255ms between each keystroke, then a bunch of keys being typed, waits a while, then the macro ends.
+
+Note: Using macros to have your keyboard send passwords for you is a bad idea.
+
+### Additional keycode aliases for software-implemented layouts (Colemak, Dvorak, etc)
+
+Everything is assuming you're in Qwerty (in software) by default, but there is built-in support for using a Colemak or Dvorak layout by including this at the top of your keymap:
+
+ #include "keymap_<layout>.h"
+
+Where <layout> is "colemak" or "dvorak". After including this line, you will get access to:
+
+ * `CM_*` for all of the Colemak-equivalent characters
+ * `DV_*` for all of the Dvorak-equivalent characters
+
+These implementations assume you're using Colemak or Dvorak on your OS, not on your keyboard - this is referred to as a software-implemented layout. If your computer is in Qwerty and your keymap is in Colemak or Dvorak, this is referred to as a firmware-implemented layout, and you won't need these features.
+
+To give an example, if you're using software-implemented Colemak, and want to get an `F`, you would use `CM_F` - `KC_F` under these same circumstances would result in `T`.
+
+## Additional language support
+
+In `quantum/keymap_extras/`, you'll see various language files - these work the same way as the alternative layout ones do. Most are defined by their two letter country/language code followed by an underscore and a 4-letter abbreviation of its name. `FR_UGRV` which will result in a `ù` when using a software-implemented AZERTY layout. It's currently difficult to send such characters in just the firmware (but it's being worked on - see Unicode support).
+
+## Unicode support
+
+You can currently send 4 hex digits with your OS-specific modifier key (RALT for OSX with the "Unicode Hex Input" layout) - this is currently limited to supporting one OS at a time, and requires a recompile for switching. 8 digit hex codes are being worked on. The keycode function is `UC(n)`, where *n* is a 4 digit hexidecimal. Enable from the Makefile.
+
+## Other firmware shortcut keycodes
+
+* `RESET` - puts the MCU in DFU mode for flashing new firmware (with `make dfu`)
+* `DEBUG` - the firmware into debug mode - you'll need hid_listen to see things
+* `BL_ON` - turns the backlight on
+* `BL_OFF` - turns the backlight off
+* `BL_<n>` - sets the backlight to level *n*
+* `BL_INC` - increments the backlight level by one
+* `BL_DEC` - decrements the backlight level by one
+* `BL_TOGG` - toggles the backlight
+* `BL_STEP` - steps through the backlight levels
+
+Enable the backlight from the Makefile.
+
+## MIDI functionalty
+
+This is still a WIP, but check out `quantum/keymap_midi.c` to see what's happening. Enable from the Makefile.
+
+## Bluetooth functionality
+
+This requires [some hardware changes](https://www.reddit.com/r/MechanicalKeyboards/comments/3psx0q/the_planck_keyboard_with_bluetooth_guide_and/?ref=search_posts), but can be enabled via the Makefile. The firmware will still output characters via USB, so be aware of this when charging via a computer. It would make sense to have a switch on the Bluefruit to turn it off at will.
+
+## Building
+
+Download or clone the whole firmware and navigate to the keyboards/planck folder. Once your dev env is setup, you'll be able to type `make` to generate your .hex - you can then use `make dfu` to program your PCB once you hit the reset button.
+
+Depending on which keymap you would like to use, you will have to compile slightly differently.
+
+### Default
+To build with the default keymap, simply run `make`.
+
+### Other Keymaps
+Several version of keymap are available in advance but you are recommended to define your favorite layout yourself. To define your own keymap create a file in the keymaps folder named `<name>.c` and see keymap document (you can find in top readme.md) and existent keymap files.
+
+To build the firmware binary hex file with a keymap just do `make` with `KEYMAP` option like:
+```
+$ make KEYMAP=[default|jack|<name>]
+```
+Keymaps follow the format **__\<name\>.c__** and are stored in the `keymaps` folder.
diff --git a/keyboards/infinity_chibios/MEMO.txt b/keyboards/infinity_chibios/MEMO.txt
new file mode 100644
index 000000000..e2886aa00
--- /dev/null
+++ b/keyboards/infinity_chibios/MEMO.txt
@@ -0,0 +1,385 @@
+flabbergast's TMK/ChibiOS port
+==============================
+2015/10/16
+
+
+Build
+-----
+$ git clone -b chibios https://github.com/flabbergast/tmk_keyboard.git
+
+$ cd tmk_keyboard
+$ git submodule add -f -b kinetis https://github.com/flabbergast/ChibiOS.git tmk_core/tool/chibios/chibios
+or
+$ cd tmk_keyboard/tmk_core/tool/chibios
+$ git clone -b kinetis https://github.com/flabbergast/ChibiOS.git tmk_core/tool/chibios/chibios
+
+$ cd tmk_keyboard/keyboard/infinity_chibios
+$ make
+
+
+
+
+Chibios Configuration
+---------------------
+halconf.h: for HAL configuration
+ placed in project directory
+ read in chibios/os/hal/hal.mk
+ included in chibios/os/hal/include/hal.h
+mcuconf.h: for MCU configuration
+ placed in project directory
+ included in halconf.h
+
+
+Chibios Term
+------------
+PAL = Port Abstraction Layer
+ palWritePad
+ palReadPad
+ palSetPad
+ chibios/os/hal/include/pal.h
+
+LLD = Low Level Driver
+
+
+Makefile
+--------
+ # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
+ MCU_FAMILY = KINETIS
+ MCU_SERIES = KL2x
+
+ # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+ # or <this_dir>/ld/
+ MCU_LDSCRIPT = MKL26Z64
+
+ # - it should exist in <chibios>/os/common/ports/ARMCMx/compilers/GCC/mk/
+ MCU_STARTUP = kl2x
+
+ # Board: it should exist either in <chibios>/os/hal/boards/
+ # or <this_dir>/boards
+ BOARD = PJRC_TEENSY_LC
+
+ MCU = cortex-m0
+
+ # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
+ ARMV = 6
+
+
+halconf.h
+---------
+
+
+mcuconf.h
+---------
+
+
+chconf.h
+--------
+
+
+ld script
+---------
+--- ../../tmk_core/tool/chibios/chibios/os/common/ports/ARMCMx/compilers/GCC/ld/MKL26Z64.ld 2015-10-15 09:08:58.732904304 +0900
++++ ld/MKL26Z64.ld 2015-10-15 08:48:06.430215496 +0900
+@@ -27,7 +27,8 @@
+ {
+ flash0 : org = 0x00000000, len = 0xc0
+ flashcfg : org = 0x00000400, len = 0x10
+- flash : org = 0x00000410, len = 64k - 0x410
++ flash : org = 0x00000410, len = 62k - 0x410
++ eeprom_emu : org = 0x0000F800, len = 2k
+ ram : org = 0x1FFFF800, len = 8k
+ }
+
+@@ -35,6 +36,10 @@
+ __ram_size__ = LENGTH(ram);
+ __ram_end__ = __ram_start__ + __ram_size__;
+
++__eeprom_workarea_start__ = ORIGIN(eeprom_emu);
++__eeprom_workarea_size__ = LENGTH(eeprom_emu);
++__eeprom_workarea_end__ = __eeprom_workarea_start__ + __eeprom_workarea_size__;
++
+ SECTIONS
+ {
+ . = 0;
+
+
+
+Configuration/Startup for Infinity 60%
+--------------------------------------
+Configuration:
+
+
+Clock:
+Inifinity
+ FEI(FLL Engaged Internal) mode with core clock:48MHz, bus clock:48MHz, flash clock:24MHz
+ Clock dividor:
+ SIM_CLKDIV1[OUTDIV1] = 0 divide-by-1 for core clock
+ SIM_CLKDIV1[OUTDIV2] = 0 divide-by-1 for bus clock
+ SIM_CLKDIV1[OUTDIV4] = 1 divide-by-2 for flash clock
+ Internal reference clock:
+ MCG_C1[IREFS] = 1 Internal Reference Select for clock source for FLL
+ MCG_C1[IRCLKEN] = 1 Internal Reference Clock Enable
+ FLL multipilication:
+ MCG_C4[DMX32] = 1
+ MCG_C4[DRST_DRS] = 01 FLL factor 1464 * 32.768kHz = 48MHz
+
+chibios/os/hal/ports/KINETIS/K20x/hal_lld.c
+ k20x_clock_init(): called in __early_init() defined in board.c
+ disable watchdog and configure clock
+
+ configurable macros:
+ KINETIS_NO_INIT: whether init or not
+ KINETIS_MCG_MODE: clock mode
+ KINETIS_MCG_MODE_FEI
+ KINETIS_MCG_MODE_PEE
+ hal/ports/KINETIS/K20x/hal_lld.h
+
+
+chibios/os/hal/boards/FREESCALE_FREEDOM_K20D50M/board.h
+ PALConfig pal_default_config
+ boardInit()
+ __early_init()
+ macro definitions for board infos, freq and mcu type
+
+chibios/os/hal/boards/FREESCALE_FREEDOM_K20D50M/board.c
+
+USB
+
+
+Startup
+-------
+ common/ports/ARMCMx/GCC/crt0_v[67]m.s
+ Reset_Handler: startup code
+ common/ports/ARMCMx/GCC/crt1.c
+ __core_init(): weak
+ __early_init(): weak
+ __late_init(): weak
+ __default_exit(): weak
+ called from Reset_Handler of crt0
+ common/ports/ARMCMx/GCC/vector.c
+ common/ports/ARMCMx/GCC/ld/*.ld
+
+chibios/os/common/ports/ARMCMx/compilers/GCC/
+├── crt0_v6m.s
+├── crt0_v7m.s
+├── crt1.c
+├── ld
+│   ├── MK20DX128BLDR3.ld
+│   ├── MK20DX128BLDR4.ld
+│   ├── MK20DX128.ld
+│   ├── MK20DX256.ld
+│   ├── MKL25Z128.ld
+│   ├── MKL26Z128.ld
+│   ├── MKL26Z64.ld
+│   └── STM32L476xG.ld
+├── mk
+│   ├── startup_k20x5.mk
+│   ├── startup_k20x7.mk
+│   ├── startup_k20x.mk
+│   ├── startup_kl2x.mk
+│   └── startup_stm32l4xx.mk
+├── rules.ld
+├── rules.mk
+└── vectors.c
+
+chibios/os/hal/
+├── boards
+│   ├── FREESCALE_FREEDOM_K20D50M
+│   │   ├── board.c
+│   │   ├── board.h
+│   │   └── board.mk
+│   ├── MCHCK_K20
+│   │   ├── board.c
+│   │   ├── board.h
+│   │   └── board.mk
+│   ├── PJRC_TEENSY_3
+│   │   ├── board.c
+│   │   ├── board.h
+│   │   └── board.mk
+│   ├── PJRC_TEENSY_3_1
+│   │   ├── board.c
+│   │   ├── board.h
+│   │   └── board.mk
+│   ├── PJRC_TEENSY_LC
+│   │   ├── board.c
+│   │   ├── board.h
+│   │   └── board.mk
+│   ├── readme.txt
+│   ├── simulator
+│   │   ├── board.c
+│   │   ├── board.h
+│   │   └── board.mk
+│   ├── ST_NUCLEO_F030R8
+│   │   ├── board.c
+│   │   ├── board.h
+│   │   ├── board.mk
+│   │   └── cfg
+│   │   └── board.chcfg
+├── hal.mk
+├── include
+│   ├── adc.h
+│   ├── can.h
+│   ├── dac.h
+│   ├── ext.h
+│   ├── gpt.h
+│   ├── hal_channels.h
+│   ├── hal_files.h
+│   ├── hal.h
+│   ├── hal_ioblock.h
+│   ├── hal_mmcsd.h
+│   ├── hal_queues.h
+│   ├── hal_streams.h
+│   ├── i2c.h
+│   ├── i2s.h
+│   ├── icu.h
+│   ├── mac.h
+│   ├── mii.h
+│   ├── mmc_spi.h
+│   ├── pal.h
+│   ├── pwm.h
+│   ├── rtc.h
+│   ├── sdc.h
+│   ├── serial.h
+│   ├── serial_usb.h
+│   ├── spi.h
+│   ├── st.h
+│   ├── uart.h
+│   └── usb.h
+├── lib
+│   └── streams
+│   ├── chprintf.c
+│   ├── chprintf.h
+│   ├── memstreams.c
+│   ├── memstreams.h
+│   ├── nullstreams.c
+│   └── nullstreams.h
+├── osal
+│   ├── nil
+│   │   ├── osal.c
+│   │   ├── osal.h
+│   │   └── osal.mk
+│   ├── os-less
+│   │   └── ARMCMx
+│   │   ├── osal.c
+│   │   ├── osal.h
+│   │   └── osal.mk
+│   └── rt
+│   ├── osal.c
+│   ├── osal.h
+│   └── osal.mk
+├── ports
+│   ├── AVR
+│   ├── common
+│   │   └── ARMCMx
+│   │   ├── mpu.h
+│   │   ├── nvic.c
+│   │   └── nvic.h
+│   ├── KINETIS
+│   │   ├── K20x
+│   │   │   ├── hal_lld.c
+│   │   │   ├── hal_lld.h
+│   │   │   ├── kinetis_registry.h
+│   │   │   ├── platform.dox
+│   │   │   ├── platform.mk
+│   │   │   ├── pwm_lld.c
+│   │   │   ├── pwm_lld.h
+│   │   │   ├── spi_lld.c
+│   │   │   └── spi_lld.h
+│   │   ├── KL2x
+│   │   │   ├── hal_lld.c
+│   │   │   ├── hal_lld.h
+│   │   │   ├── kinetis_registry.h
+│   │   │   ├── platform.mk
+│   │   │   ├── pwm_lld.c
+│   │   │   └── pwm_lld.h
+│   │   ├── LLD
+│   │   │   ├── adc_lld.c
+│   │   │   ├── adc_lld.h
+│   │   │   ├── ext_lld.c
+│   │   │   ├── ext_lld.h
+│   │   │   ├── gpt_lld.c
+│   │   │   ├── gpt_lld.h
+│   │   │   ├── i2c_lld.c
+│   │   │   ├── i2c_lld.h
+│   │   │   ├── pal_lld.c
+│   │   │   ├── pal_lld.h
+│   │   │   ├── serial_lld.c
+│   │   │   ├── serial_lld.h
+│   │   │   ├── st_lld.c
+│   │   │   ├── st_lld.h
+│   │   │   ├── usb_lld.c
+│   │   │   └── usb_lld.h
+│   │   └── README.md
+│   ├── LPC
+│   ├── simulator
+│   └── STM32
+├── src
+│   ├── adc.c
+│   ├── can.c
+│   ├── dac.c
+│   ├── ext.c
+│   ├── gpt.c
+│   ├── hal.c
+│   ├── hal_mmcsd.c
+│   ├── hal_queues.c
+│   ├── i2c.c
+│   ├── i2s.c
+│   ├── icu.c
+│   ├── mac.c
+│   ├── mmc_spi.c
+│   ├── pal.c
+│   ├── pwm.c
+│   ├── rtc.c
+│   ├── sdc.c
+│   ├── serial.c
+│   ├── serial_usb.c
+│   ├── spi.c
+│   ├── st.c
+│   ├── uart.c
+│   └── usb.c
+└── templates
+ ├── adc_lld.c
+ ├── adc_lld.h
+ ├── can_lld.c
+ ├── can_lld.h
+ ├── dac_lld.c
+ ├── dac_lld.h
+ ├── ext_lld.c
+ ├── ext_lld.h
+ ├── gpt_lld.c
+ ├── gpt_lld.h
+ ├── halconf.h
+ ├── hal_lld.c
+ ├── hal_lld.h
+ ├── i2c_lld.c
+ ├── i2c_lld.h
+ ├── i2s_lld.c
+ ├── i2s_lld.h
+ ├── icu_lld.c
+ ├── icu_lld.h
+ ├── mac_lld.c
+ ├── mac_lld.h
+ ├── mcuconf.h
+ ├── osal
+ │   ├── osal.c
+ │   ├── osal.h
+ │   └── osal.mk
+ ├── pal_lld.c
+ ├── pal_lld.h
+ ├── platform.mk
+ ├── pwm_lld.c
+ ├── pwm_lld.h
+ ├── rtc_lld.c
+ ├── rtc_lld.h
+ ├── sdc_lld.c
+ ├── sdc_lld.h
+ ├── serial_lld.c
+ ├── serial_lld.h
+ ├── spi_lld.c
+ ├── spi_lld.h
+ ├── st_lld.c
+ ├── st_lld.h
+ ├── uart_lld.c
+ ├── uart_lld.h
+ ├── usb_lld.c
+ └── usb_lld.h
diff --git a/keyboards/infinity_chibios/Makefile b/keyboards/infinity_chibios/Makefile
new file mode 100644
index 000000000..649b43e64
--- /dev/null
+++ b/keyboards/infinity_chibios/Makefile
@@ -0,0 +1,70 @@
+# project specific files
+SRC = matrix.c \
+ led.c
+
+## chip/board settings
+# - the next two should match the directories in
+# <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
+# - For Teensies, FAMILY = KINETIS and SERIES is either
+# KL2x (LC) or K20x (3.0,3.1,3.2).
+# - For Infinity KB, SERIES = K20x
+MCU_FAMILY = KINETIS
+MCU_SERIES = K20x
+
+# Linker script to use
+# - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+# or <this_dir>/ld/
+# - NOTE: a custom ld script is needed for EEPROM on Teensy LC
+# - LDSCRIPT =
+# - MKL26Z64 for Teensy LC
+# - MK20DX128 for Teensy 3.0
+# - MK20DX256 for Teensy 3.1 and 3.2
+# - MK20DX128BLDR4 for Infinity with Kiibohd bootloader
+MCU_LDSCRIPT = MK20DX128BLDR4
+
+# Startup code to use
+# - it should exist in <chibios>/os/common/ports/ARMCMx/compilers/GCC/mk/
+# - STARTUP =
+# - kl2x for Teensy LC
+# - k20x5 for Teensy 3.0 and Infinity KB
+# - k20x7 for Teensy 3.1 and 3.2
+MCU_STARTUP = k20x5
+
+# Board: it should exist either in <chibios>/os/hal/boards/
+# or <this_dir>/boards
+# - BOARD =
+# - PJRC_TEENSY_LC for Teensy LC
+# - PJRC_TEENSY_3 for Teensy 3.0
+# - PJRC_TEENSY_3_1 for Teensy 3.1 or 3.2
+# - MCHCK_K20 for Infinity KB
+BOARD = MCHCK_K20
+
+# Cortex version
+# Teensy LC is cortex-m0; Teensy 3.x are cortex-m4
+MCU = cortex-m4
+
+# ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
+# I.e. 6 for Teensy LC; 7 for Teensy 3.x
+ARMV = 7
+
+# Vector table for application
+# 0x00000000-0x00001000 area is occupied by bootlaoder.*/
+# The CORTEX_VTOR... is needed only for MCHCK/Infinity KB
+OPT_DEFS = -DCORTEX_VTOR_INIT=0x00001000
+
+# Build Options
+# comment out to disable the options.
+#
+BOOTMAGIC_ENABLE ?= yes # Virtual DIP switch configuration
+## (Note that for BOOTMAGIC on Teensy LC you have to use a custom .ld script.)
+MOUSEKEY_ENABLE ?= yes # Mouse keys
+EXTRAKEY_ENABLE ?= yes # Audio control and System control
+CONSOLE_ENABLE ?= yes # Console for debug
+COMMAND_ENABLE ?= yes # Commands for debug and configuration
+SLEEP_LED_ENABLE ?= yes # Breathing sleep LED during USB suspend
+NKRO_ENABLE ?= yes # USB Nkey Rollover
+CUSTOM_MATRIX ?= yes # Custom matrix file
+
+ifndef QUANTUM_DIR
+ include ../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/infinity_chibios/bootloader_defs.h b/keyboards/infinity_chibios/bootloader_defs.h
new file mode 100644
index 000000000..c67153be6
--- /dev/null
+++ b/keyboards/infinity_chibios/bootloader_defs.h
@@ -0,0 +1 @@
+#define KIIBOHD_BOOTLOADER
diff --git a/keyboards/infinity_chibios/chconf.h b/keyboards/infinity_chibios/chconf.h
new file mode 100644
index 000000000..b886c383b
--- /dev/null
+++ b/keyboards/infinity_chibios/chconf.h
@@ -0,0 +1,524 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file templates/chconf.h
+ * @brief Configuration file template.
+ * @details A copy of this file must be placed in each project directory, it
+ * contains the application specific kernel settings.
+ *
+ * @addtogroup config
+ * @details Kernel related settings and hooks.
+ * @{
+ */
+
+#ifndef CHCONF_H
+#define CHCONF_H
+
+#define _CHIBIOS_RT_CONF_
+
+/*===========================================================================*/
+/**
+ * @name System timers settings
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief System time counter resolution.
+ * @note Allowed values are 16 or 32 bits.
+ */
+#define CH_CFG_ST_RESOLUTION 32
+
+/**
+ * @brief System tick frequency.
+ * @details Frequency of the system timer that drives the system ticks. This
+ * setting also defines the system tick time unit.
+ */
+#define CH_CFG_ST_FREQUENCY 1000
+
+/**
+ * @brief Time delta constant for the tick-less mode.
+ * @note If this value is zero then the system uses the classic
+ * periodic tick. This value represents the minimum number
+ * of ticks that is safe to specify in a timeout directive.
+ * The value one is not valid, timeouts are rounded up to
+ * this value.
+ */
+#define CH_CFG_ST_TIMEDELTA 0
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Kernel parameters and options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Round robin interval.
+ * @details This constant is the number of system ticks allowed for the
+ * threads before preemption occurs. Setting this value to zero
+ * disables the preemption for threads with equal priority and the
+ * round robin becomes cooperative. Note that higher priority
+ * threads can still preempt, the kernel is always preemptive.
+ * @note Disabling the round robin preemption makes the kernel more compact
+ * and generally faster.
+ * @note The round robin preemption is not supported in tickless mode and
+ * must be set to zero in that case.
+ */
+#define CH_CFG_TIME_QUANTUM 20
+
+/**
+ * @brief Managed RAM size.
+ * @details Size of the RAM area to be managed by the OS. If set to zero
+ * then the whole available RAM is used. The core memory is made
+ * available to the heap allocator and/or can be used directly through
+ * the simplified core memory allocator.
+ *
+ * @note In order to let the OS manage the whole RAM the linker script must
+ * provide the @p __heap_base__ and @p __heap_end__ symbols.
+ * @note Requires @p CH_CFG_USE_MEMCORE.
+ */
+#define CH_CFG_MEMCORE_SIZE 0
+
+/**
+ * @brief Idle thread automatic spawn suppression.
+ * @details When this option is activated the function @p chSysInit()
+ * does not spawn the idle thread. The application @p main()
+ * function becomes the idle thread and must implement an
+ * infinite loop.
+ */
+#define CH_CFG_NO_IDLE_THREAD FALSE
+
+/* Use __WFI in the idle thread for waiting. Does lower the power
+ * consumption. */
+#define CORTEX_ENABLE_WFI_IDLE TRUE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Performance options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief OS optimization.
+ * @details If enabled then time efficient rather than space efficient code
+ * is used when two possible implementations exist.
+ *
+ * @note This is not related to the compiler optimization options.
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_OPTIMIZE_SPEED TRUE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Subsystem options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Time Measurement APIs.
+ * @details If enabled then the time measurement APIs are included in
+ * the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_TM FALSE
+
+/**
+ * @brief Threads registry APIs.
+ * @details If enabled then the registry APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_REGISTRY TRUE
+
+/**
+ * @brief Threads synchronization APIs.
+ * @details If enabled then the @p chThdWait() function is included in
+ * the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_WAITEXIT TRUE
+
+/**
+ * @brief Semaphores APIs.
+ * @details If enabled then the Semaphores APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_SEMAPHORES TRUE
+
+/**
+ * @brief Semaphores queuing mode.
+ * @details If enabled then the threads are enqueued on semaphores by
+ * priority rather than in FIFO order.
+ *
+ * @note The default is @p FALSE. Enable this if you have special
+ * requirements.
+ * @note Requires @p CH_CFG_USE_SEMAPHORES.
+ */
+#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE
+
+/**
+ * @brief Mutexes APIs.
+ * @details If enabled then the mutexes APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MUTEXES TRUE
+
+/**
+ * @brief Enables recursive behavior on mutexes.
+ * @note Recursive mutexes are heavier and have an increased
+ * memory footprint.
+ *
+ * @note The default is @p FALSE.
+ * @note Requires @p CH_CFG_USE_MUTEXES.
+ */
+#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE
+
+/**
+ * @brief Conditional Variables APIs.
+ * @details If enabled then the conditional variables APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_MUTEXES.
+ */
+#define CH_CFG_USE_CONDVARS TRUE
+
+/**
+ * @brief Conditional Variables APIs with timeout.
+ * @details If enabled then the conditional variables APIs with timeout
+ * specification are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_CONDVARS.
+ */
+#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE
+
+/**
+ * @brief Events Flags APIs.
+ * @details If enabled then the event flags APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_EVENTS TRUE
+
+/**
+ * @brief Events Flags APIs with timeout.
+ * @details If enabled then the events APIs with timeout specification
+ * are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_EVENTS.
+ */
+#define CH_CFG_USE_EVENTS_TIMEOUT TRUE
+
+/**
+ * @brief Synchronous Messages APIs.
+ * @details If enabled then the synchronous messages APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MESSAGES TRUE
+
+/**
+ * @brief Synchronous Messages queuing mode.
+ * @details If enabled then messages are served by priority rather than in
+ * FIFO order.
+ *
+ * @note The default is @p FALSE. Enable this if you have special
+ * requirements.
+ * @note Requires @p CH_CFG_USE_MESSAGES.
+ */
+#define CH_CFG_USE_MESSAGES_PRIORITY FALSE
+
+/**
+ * @brief Mailboxes APIs.
+ * @details If enabled then the asynchronous messages (mailboxes) APIs are
+ * included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_SEMAPHORES.
+ */
+#define CH_CFG_USE_MAILBOXES TRUE
+
+/**
+ * @brief Core Memory Manager APIs.
+ * @details If enabled then the core memory manager APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MEMCORE TRUE
+
+/**
+ * @brief Heap Allocator APIs.
+ * @details If enabled then the memory heap allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or
+ * @p CH_CFG_USE_SEMAPHORES.
+ * @note Mutexes are recommended.
+ */
+#define CH_CFG_USE_HEAP TRUE
+
+/**
+ * @brief Memory Pools Allocator APIs.
+ * @details If enabled then the memory pools allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MEMPOOLS TRUE
+
+/**
+ * @brief Dynamic Threads APIs.
+ * @details If enabled then the dynamic threads creation APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_WAITEXIT.
+ * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS.
+ */
+#define CH_CFG_USE_DYNAMIC TRUE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Debug options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Debug option, kernel statistics.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_STATISTICS FALSE
+
+/**
+ * @brief Debug option, system state check.
+ * @details If enabled the correct call protocol for system APIs is checked
+ * at runtime.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_SYSTEM_STATE_CHECK FALSE
+
+/**
+ * @brief Debug option, parameters checks.
+ * @details If enabled then the checks on the API functions input
+ * parameters are activated.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_ENABLE_CHECKS FALSE
+
+/**
+ * @brief Debug option, consistency checks.
+ * @details If enabled then all the assertions in the kernel code are
+ * activated. This includes consistency checks inside the kernel,
+ * runtime anomalies and port-defined checks.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_ENABLE_ASSERTS FALSE
+
+/**
+ * @brief Debug option, trace buffer.
+ * @details If enabled then the trace buffer is activated.
+ *
+ * @note The default is @p CH_DBG_TRACE_MASK_DISABLED.
+ */
+#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED
+
+/**
+ * @brief Trace buffer entries.
+ * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is
+ * different from @p CH_DBG_TRACE_MASK_DISABLED.
+ */
+#define CH_DBG_TRACE_BUFFER_SIZE 128
+
+/**
+ * @brief Debug option, stack checks.
+ * @details If enabled then a runtime stack check is performed.
+ *
+ * @note The default is @p FALSE.
+ * @note The stack check is performed in a architecture/port dependent way.
+ * It may not be implemented or some ports.
+ * @note The default failure mode is to halt the system with the global
+ * @p panic_msg variable set to @p NULL.
+ */
+#define CH_DBG_ENABLE_STACK_CHECK FALSE
+
+/**
+ * @brief Debug option, stacks initialization.
+ * @details If enabled then the threads working area is filled with a byte
+ * value when a thread is created. This can be useful for the
+ * runtime measurement of the used stack.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_FILL_THREADS FALSE
+
+/**
+ * @brief Debug option, threads profiling.
+ * @details If enabled then a field is added to the @p thread_t structure that
+ * counts the system ticks occurred while executing the thread.
+ *
+ * @note The default is @p FALSE.
+ * @note This debug option is not currently compatible with the
+ * tickless mode.
+ */
+#define CH_DBG_THREADS_PROFILING FALSE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Kernel hooks
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Threads descriptor structure extension.
+ * @details User fields added to the end of the @p thread_t structure.
+ */
+#define CH_CFG_THREAD_EXTRA_FIELDS \
+ /* Add threads custom fields here.*/
+
+/**
+ * @brief Threads initialization hook.
+ * @details User initialization code added to the @p chThdInit() API.
+ *
+ * @note It is invoked from within @p chThdInit() and implicitly from all
+ * the threads creation APIs.
+ */
+#define CH_CFG_THREAD_INIT_HOOK(tp) { \
+ /* Add threads initialization code here.*/ \
+}
+
+/**
+ * @brief Threads finalization hook.
+ * @details User finalization code added to the @p chThdExit() API.
+ */
+#define CH_CFG_THREAD_EXIT_HOOK(tp) { \
+ /* Add threads finalization code here.*/ \
+}
+
+/**
+ * @brief Context switch hook.
+ * @details This hook is invoked just before switching between threads.
+ */
+#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \
+ /* Context switch code here.*/ \
+}
+
+/**
+ * @brief ISR enter hook.
+ */
+#define CH_CFG_IRQ_PROLOGUE_HOOK() { \
+ /* IRQ prologue code here.*/ \
+}
+
+/**
+ * @brief ISR exit hook.
+ */
+#define CH_CFG_IRQ_EPILOGUE_HOOK() { \
+ /* IRQ epilogue code here.*/ \
+}
+
+/**
+ * @brief Idle thread enter hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to activate a power saving mode.
+ */
+#define CH_CFG_IDLE_ENTER_HOOK() { \
+ /* Idle-enter code here.*/ \
+}
+
+/**
+ * @brief Idle thread leave hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to deactivate a power saving mode.
+ */
+#define CH_CFG_IDLE_LEAVE_HOOK() { \
+ /* Idle-leave code here.*/ \
+}
+
+/**
+ * @brief Idle Loop hook.
+ * @details This hook is continuously invoked by the idle thread loop.
+ */
+#define CH_CFG_IDLE_LOOP_HOOK() { \
+ /* Idle loop code here.*/ \
+}
+
+/**
+ * @brief System tick event hook.
+ * @details This hook is invoked in the system tick handler immediately
+ * after processing the virtual timers queue.
+ */
+#define CH_CFG_SYSTEM_TICK_HOOK() { \
+ /* System tick event code here.*/ \
+}
+
+/**
+ * @brief System halt hook.
+ * @details This hook is invoked in case to a system halting error before
+ * the system is halted.
+ */
+#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \
+ /* System halt code here.*/ \
+}
+
+/**
+ * @brief Trace hook.
+ * @details This hook is invoked each time a new record is written in the
+ * trace buffer.
+ */
+#define CH_CFG_TRACE_HOOK(tep) { \
+ /* Trace code here.*/ \
+}
+
+/** @} */
+
+/*===========================================================================*/
+/* Port-specific settings (override port settings defaulted in chcore.h). */
+/*===========================================================================*/
+
+#endif /* CHCONF_H */
+
+/** @} */
diff --git a/keyboards/infinity_chibios/config.h b/keyboards/infinity_chibios/config.h
new file mode 100644
index 000000000..cb9022205
--- /dev/null
+++ b/keyboards/infinity_chibios/config.h
@@ -0,0 +1,75 @@
+/*
+Copyright 2015 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x6464
+#define DEVICE_VER 0x0001
+/* in python2: list(u"whatever".encode('utf-16-le')) */
+/* at most 32 characters or the ugly hack in usb_main.c borks */
+#define MANUFACTURER "TMK"
+#define USBSTR_MANUFACTURER 'T', '\x00', 'M', '\x00', 'K', '\x00', ' ', '\x00', '\xc6', '\x00'
+#define PRODUCT "Infinity keyboard/TMK"
+#define USBSTR_PRODUCT 'I', '\x00', 'n', '\x00', 'f', '\x00', 'i', '\x00', 'n', '\x00', 'i', '\x00', 't', '\x00', 'y', '\x00', ' ', '\x00', 'k', '\x00', 'e', '\x00', 'y', '\x00', 'b', '\x00', 'o', '\x00', 'a', '\x00', 'r', '\x00', 'd', '\x00', '/', '\x00', 'T', '\x00', 'M', '\x00', 'K', '\x00'
+
+/* key matrix size */
+#define MATRIX_ROWS 9
+#define MATRIX_COLS 7
+
+/* define if matrix has ghost */
+//#define MATRIX_HAS_GHOST
+
+/* Set 0 if debouncing isn't needed */
+#define DEBOUNCE 5
+
+/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
+//#define LOCKING_SUPPORT_ENABLE
+/* Locking resynchronize hack */
+//#define LOCKING_RESYNC_ENABLE
+
+/* key combination for command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+/* Keymap for Infiity prototype */
+#define INFINITY_PROTOTYPE
+
+
+/*
+ * Feature disable options
+ * These options are also useful to firmware size reduction.
+ */
+
+/* disable debug print */
+//#define NO_DEBUG
+
+/* disable print */
+//#define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+
+#endif
diff --git a/keyboards/infinity_chibios/halconf.h b/keyboards/infinity_chibios/halconf.h
new file mode 100644
index 000000000..53538de14
--- /dev/null
+++ b/keyboards/infinity_chibios/halconf.h
@@ -0,0 +1,353 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file templates/halconf.h
+ * @brief HAL configuration header.
+ * @details HAL configuration file, this file allows to enable or disable the
+ * various device drivers from your application. You may also use
+ * this file in order to override the device drivers default settings.
+ *
+ * @addtogroup HAL_CONF
+ * @{
+ */
+
+#ifndef _HALCONF_H_
+#define _HALCONF_H_
+
+#include "mcuconf.h"
+
+/**
+ * @brief Enables the PAL subsystem.
+ */
+#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__)
+#define HAL_USE_PAL TRUE
+#endif
+
+/**
+ * @brief Enables the ADC subsystem.
+ */
+#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__)
+#define HAL_USE_ADC FALSE
+#endif
+
+/**
+ * @brief Enables the CAN subsystem.
+ */
+#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__)
+#define HAL_USE_CAN FALSE
+#endif
+
+/**
+ * @brief Enables the DAC subsystem.
+ */
+#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__)
+#define HAL_USE_DAC FALSE
+#endif
+
+/**
+ * @brief Enables the EXT subsystem.
+ */
+#if !defined(HAL_USE_EXT) || defined(__DOXYGEN__)
+#define HAL_USE_EXT FALSE
+#endif
+
+/**
+ * @brief Enables the GPT subsystem.
+ */
+#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__)
+#define HAL_USE_GPT FALSE
+#endif
+
+/**
+ * @brief Enables the I2C subsystem.
+ */
+#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
+#define HAL_USE_I2C FALSE
+#endif
+
+/**
+ * @brief Enables the I2S subsystem.
+ */
+#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__)
+#define HAL_USE_I2S FALSE
+#endif
+
+/**
+ * @brief Enables the ICU subsystem.
+ */
+#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__)
+#define HAL_USE_ICU FALSE
+#endif
+
+/**
+ * @brief Enables the MAC subsystem.
+ */
+#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__)
+#define HAL_USE_MAC FALSE
+#endif
+
+/**
+ * @brief Enables the MMC_SPI subsystem.
+ */
+#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_MMC_SPI FALSE
+#endif
+
+/**
+ * @brief Enables the PWM subsystem.
+ */
+#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__)
+#define HAL_USE_PWM FALSE
+#endif
+
+/**
+ * @brief Enables the RTC subsystem.
+ */
+#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
+#define HAL_USE_RTC FALSE
+#endif
+
+/**
+ * @brief Enables the SDC subsystem.
+ */
+#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__)
+#define HAL_USE_SDC FALSE
+#endif
+
+/**
+ * @brief Enables the SERIAL subsystem.
+ */
+#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL FALSE
+#endif
+
+/**
+ * @brief Enables the SERIAL over USB subsystem.
+ */
+#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL_USB TRUE
+#endif
+
+/**
+ * @brief Enables the SPI subsystem.
+ */
+#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_SPI FALSE
+#endif
+
+/**
+ * @brief Enables the UART subsystem.
+ */
+#if !defined(HAL_USE_UART) || defined(__DOXYGEN__)
+#define HAL_USE_UART FALSE
+#endif
+
+/**
+ * @brief Enables the USB subsystem.
+ */
+#if !defined(HAL_USE_USB) || defined(__DOXYGEN__)
+#define HAL_USE_USB TRUE
+#endif
+
+/**
+ * @brief Enables the WDG subsystem.
+ */
+#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__)
+#define HAL_USE_WDG FALSE
+#endif
+
+/*===========================================================================*/
+/* ADC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__)
+#define ADC_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define ADC_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* CAN driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Sleep mode related APIs inclusion switch.
+ */
+#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
+#define CAN_USE_SLEEP_MODE TRUE
+#endif
+
+/*===========================================================================*/
+/* I2C driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables the mutual exclusion APIs on the I2C bus.
+ */
+#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define I2C_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* MAC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables an event sources for incoming packets.
+ */
+#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__)
+#define MAC_USE_ZERO_COPY FALSE
+#endif
+
+/**
+ * @brief Enables an event sources for incoming packets.
+ */
+#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__)
+#define MAC_USE_EVENTS TRUE
+#endif
+
+/*===========================================================================*/
+/* MMC_SPI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Delays insertions.
+ * @details If enabled this options inserts delays into the MMC waiting
+ * routines releasing some extra CPU time for the threads with
+ * lower priority, this may slow down the driver a bit however.
+ * This option is recommended also if the SPI driver does not
+ * use a DMA channel and heavily loads the CPU.
+ */
+#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__)
+#define MMC_NICE_WAITING TRUE
+#endif
+
+/*===========================================================================*/
+/* SDC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Number of initialization attempts before rejecting the card.
+ * @note Attempts are performed at 10mS intervals.
+ */
+#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__)
+#define SDC_INIT_RETRY 100
+#endif
+
+/**
+ * @brief Include support for MMC cards.
+ * @note MMC support is not yet implemented so this option must be kept
+ * at @p FALSE.
+ */
+#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__)
+#define SDC_MMC_SUPPORT FALSE
+#endif
+
+/**
+ * @brief Delays insertions.
+ * @details If enabled this options inserts delays into the MMC waiting
+ * routines releasing some extra CPU time for the threads with
+ * lower priority, this may slow down the driver a bit however.
+ */
+#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__)
+#define SDC_NICE_WAITING TRUE
+#endif
+
+/*===========================================================================*/
+/* SERIAL driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Default bit rate.
+ * @details Configuration parameter, this is the baud rate selected for the
+ * default configuration.
+ */
+#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__)
+#define SERIAL_DEFAULT_BITRATE 38400
+#endif
+
+/**
+ * @brief Serial buffers size.
+ * @details Configuration parameter, you can change the depth of the queue
+ * buffers depending on the requirements of your application.
+ * @note The default is 64 bytes for both the transmission and receive
+ * buffers.
+ */
+#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define SERIAL_BUFFERS_SIZE 16
+#endif
+
+/*===========================================================================*/
+/* SERIAL_USB driver related setting. */
+/*===========================================================================*/
+
+/**
+ * @brief Serial over USB buffers size.
+ * @details Configuration parameter, the buffer size must be a multiple of
+ * the USB data endpoint maximum packet size.
+ * @note The default is 64 bytes for both the transmission and receive
+ * buffers.
+ */
+#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define SERIAL_USB_BUFFERS_SIZE 256
+#endif
+
+/*===========================================================================*/
+/* SPI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__)
+#define SPI_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define SPI_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* USB driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__)
+#define USB_USE_WAIT TRUE
+#endif
+
+#endif /* _HALCONF_H_ */
+
+/** @} */
diff --git a/keyboards/infinity_chibios/infinity_chibios.c b/keyboards/infinity_chibios/infinity_chibios.c
new file mode 100644
index 000000000..845eda01b
--- /dev/null
+++ b/keyboards/infinity_chibios/infinity_chibios.c
@@ -0,0 +1,17 @@
+/*
+Copyright 2012,2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "infinity_chibios.h"
diff --git a/keyboards/infinity_chibios/infinity_chibios.h b/keyboards/infinity_chibios/infinity_chibios.h
new file mode 100644
index 000000000..a44c68b82
--- /dev/null
+++ b/keyboards/infinity_chibios/infinity_chibios.h
@@ -0,0 +1,66 @@
+/*
+Copyright 2014 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef KEYMAP_COMMON_H
+#define KEYMAP_COMMON_H
+
+#include "quantum.h"
+
+#ifdef INFINITY_PROTOTYPE
+
+/* Infinity prototype */
+#define KEYMAP( \
+ K00, K10, K20, K30, K40, K50, K60, K70, K80, K01, K11, K21, K31, K41, K86, \
+ K51, K61, K71, K81, K02, K12, K22, K32, K42, K52, K62, K72, K82, K03, \
+ K13, K23, K33, K43, K53, K63, K73, K83, K04, K14, K24, K34, K44, \
+ K54, K64, K74, K84, K05, K15, K25, K35, K45, K55, K65, K75, K85, \
+ K06, K16, K26, K36, K46, K56, K66, K76 \
+) { \
+ { KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06 }, \
+ { KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16 }, \
+ { KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26 }, \
+ { KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36 }, \
+ { KC_##K40, KC_##K41, KC_##K42, KC_##K43, KC_##K44, KC_##K45, KC_##K46 }, \
+ { KC_##K50, KC_##K51, KC_##K52, KC_##K53, KC_##K54, KC_##K55, KC_##K56 }, \
+ { KC_##K60, KC_##K61, KC_##K62, KC_##K63, KC_##K64, KC_##K65, KC_##K66 }, \
+ { KC_##K70, KC_##K71, KC_##K72, KC_##K73, KC_##K74, KC_##K75, KC_##K76 }, \
+ { KC_##K80, KC_##K81, KC_##K82, KC_##K83, KC_##K84, KC_##K85, KC_##K86 } \
+}
+
+#else
+
+/* Infinity production */
+#define KEYMAP( \
+ K00, K10, K20, K30, K40, K50, K60, K70, K80, K01, K11, K21, K31, K41, K51, \
+ K61, K71, K81, K02, K12, K22, K32, K42, K52, K62, K72, K82, K03, K13, \
+ K23, K33, K43, K53, K63, K73, K83, K04, K14, K24, K34, K44, K54, \
+ K64, K74, K84, K05, K15, K25, K35, K45, K55, K65, K75, K85, K06, \
+ K16, K26, K36, K46, K56, K66, K76, K86 \
+) { \
+ { KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06 }, \
+ { KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16 }, \
+ { KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26 }, \
+ { KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36 }, \
+ { KC_##K40, KC_##K41, KC_##K42, KC_##K43, KC_##K44, KC_##K45, KC_##K46 }, \
+ { KC_##K50, KC_##K51, KC_##K52, KC_##K53, KC_##K54, KC_##K55, KC_##K56 }, \
+ { KC_##K60, KC_##K61, KC_##K62, KC_##K63, KC_##K64, KC_##K65, KC_##K66 }, \
+ { KC_##K70, KC_##K71, KC_##K72, KC_##K73, KC_##K74, KC_##K75, KC_##K76 }, \
+ { KC_##K80, KC_##K81, KC_##K82, KC_##K83, KC_##K84, KC_##K85, KC_##K86 } \
+}
+
+#endif
+
+#endif
diff --git a/keyboards/infinity_chibios/keymaps/default/keymap.c b/keyboards/infinity_chibios/keymaps/default/keymap.c
new file mode 100644
index 000000000..2acf72849
--- /dev/null
+++ b/keyboards/infinity_chibios/keymaps/default/keymap.c
@@ -0,0 +1,48 @@
+#include "infinity_chibios.h"
+
+const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ /* Layer 0: Default Layer
+ * ,-----------------------------------------------------------.
+ * |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| `|BSp|
+ * |-----------------------------------------------------------|
+ * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \|
+ * |-----------------------------------------------------------|
+ * |Contro| A| S| D| F| G| H| J| K| L| ;| '|Enter |
+ * |-----------------------------------------------------------|
+ * |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift |Fn0|
+ * |-----------------------------------------------------------'
+ * | |Gui|Alt | Space |Alt |Gui| | |
+ * `-----------------------------------------------------------'
+ */
+ [0] =
+ KEYMAP(ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSLS, GRV, \
+ TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSPC, \
+ LCTL,A, S, D, F, G, H, J, K, L, SCLN,QUOT,ENT, \
+ LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH,RSFT,FN0, \
+ NO, LGUI,LALT, SPC, RALT,RGUI,NO, NO),
+
+ /* Layer 1: HHKB mode (HHKB Fn)
+ * ,-----------------------------------------------------------.
+ * |Pwr| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
+ * |-----------------------------------------------------------|
+ * |Caps | | | | | | | |Psc|Slk|Pus|Up | |Backs|
+ * |-----------------------------------------------------------|
+ * | |VoD|VoU|Mut| | | *| /|Hom|PgU|Lef|Rig|Enter |
+ * |-----------------------------------------------------------|
+ * | | | | | | | +| -|End|PgD|Dow| | |
+ * `-----------------------------------------------------------'
+ * | |Gui|Alt | Space |Alt |Gui| | |
+ * `-----------------------------------------------------------'
+ */
+ [1] =
+ KEYMAP(PWR, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
+ CAPS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PSCR,SLCK,PAUS, UP, TRNS, BSPC, \
+ TRNS,VOLD,VOLU,MUTE,TRNS,TRNS,PAST,PSLS,HOME,PGUP,LEFT,RGHT,PENT, \
+ TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PPLS,PMNS,END, PGDN,DOWN,TRNS,TRNS, \
+ TRNS,TRNS,TRNS, TRNS, TRNS,TRNS,TRNS,TRNS),
+};
+
+const uint16_t fn_actions[] = {
+ [0] = ACTION_LAYER_MOMENTARY(1),
+};
+
diff --git a/keyboards/infinity_chibios/keymaps/hasu/keymap.c b/keyboards/infinity_chibios/keymaps/hasu/keymap.c
new file mode 100644
index 000000000..e9a212f0e
--- /dev/null
+++ b/keyboards/infinity_chibios/keymaps/hasu/keymap.c
@@ -0,0 +1,199 @@
+#include "infinity_chibios.h"
+
+const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ /* Layer 0: Default Layer
+ * ,-----------------------------------------------------------.
+ * |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| `|BSp|
+ * |-----------------------------------------------------------|
+ * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \|
+ * |-----------------------------------------------------------|
+ * |Contro| A| S| D| F| G| H| J| K| L| ;| '|Enter |
+ * |-----------------------------------------------------------|
+ * |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift |Fn0|
+ * |-----------------------------------------------------------'
+ * | |Gui|Alt | Space |Alt |Gui| | |
+ * `-----------------------------------------------------------'
+ */
+ [0] =
+ KEYMAP(ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSLS,GRV, \
+ TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSPC, \
+ LCTL,A, S, D, F, G, H, J, K, L, FN3, QUOT,FN6, \
+ FN7, Z, X, C, V, B, N, M, COMM,DOT, FN2, RSFT,FN1, \
+ NO, LGUI,LALT, FN4, FN5, RGUI,NO, NO),
+
+ /* Layer 1: HHKB mode (HHKB Fn)
+ * ,-----------------------------------------------------------.
+ * |Pwr| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
+ * |-----------------------------------------------------------|
+ * |Caps | | | | | | | |Psc|Slk|Pus|Up | |Backs|
+ * |-----------------------------------------------------------|
+ * | |VoD|VoU|Mut| | | *| /|Hom|PgU|Lef|Rig|Enter |
+ * |-----------------------------------------------------------|
+ * | | | | | | | +| -|End|PgD|Dow| | |
+ * `-----------------------------------------------------------'
+ * | |Gui|Alt | Space |Alt |Gui| | |
+ * `-----------------------------------------------------------'
+ */
+ [1] =
+ KEYMAP(PWR, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
+ CAPS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PSCR,SLCK,PAUS, UP, TRNS,BSPC, \
+ LCTL,VOLD,VOLU,MUTE,TRNS,TRNS,PAST,PSLS,HOME,PGUP,LEFT,RGHT,ENT, \
+ LSFT,TRNS,TRNS,TRNS,TRNS,TRNS,PPLS,PMNS,END, PGDN,DOWN,RSFT,TRNS, \
+ TRNS,LGUI,LALT, TRNS, RALT,RGUI,TRNS,TRNS),
+
+ /* Layer 2: Vi mode[Slash]
+ * ,-----------------------------------------------------------.
+ * |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
+ * |-----------------------------------------------------------|
+ * |Tab |Hom|PgD|Up |PgU|End|Hom|PgD|PgUlEnd| | | |Backs|
+ * |-----------------------------------------------------------|
+ * |Contro| |Lef|Dow|Rig| |Lef|Dow|Up |Rig| | |Return |
+ * |-----------------------------------------------------------|
+ * |Shift | | | | | |Hom|PgD|PgUlEnd|Fn0|Shift | |
+ * `-----------------------------------------------------------'
+ * |Gui|Alt | Space |Alt |Gui|
+ * `-------------------------------------------'
+ */
+ [2] = \
+ KEYMAP(GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
+ TAB, HOME,PGDN,UP, PGUP,END, HOME,PGDN,PGUP,END, NO, NO, NO, BSPC, \
+ LCTL,NO, LEFT,DOWN,RGHT,NO, LEFT,DOWN,UP, RGHT,NO, NO, ENT, \
+ LSFT,NO, NO, NO, NO, NO, HOME,PGDN,PGUP,END, FN2, RSFT,TRNS, \
+ TRNS,LGUI,LALT, SPC, RALT,RGUI,TRNS,TRNS),
+
+ /* Layer 3: Mouse mode(IJKL)[Semicolon]
+ * ,-----------------------------------------------------------.
+ * |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
+ * |-----------------------------------------------------------|
+ * |Tab | | | | | |MwL|MwD|McU|MwU|MwR|Wbk|Wfr|Alt-T|
+ * |-----------------------------------------------------------|
+ * |Contro| | | | | |Mb2|McL|McD|McR|Fn | |Return |
+ * |-----------------------------------------------------------|
+ * |Shift | | | | |Mb3|Mb2|Mb1|Mb4|Mb5| |Shift | |
+ * `-----------------------------------------------------------'
+ * |Gui |Alt | Mb1 |Fn |Fn |
+ * `--------------------------------------------'
+ * Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel
+ */
+ [3] = \
+ KEYMAP(GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
+ FN8, NO, NO, NO, NO, NO, WH_L,WH_D,MS_U,WH_U,WH_R,FN9, FN10,FN8, \
+ LCTL,ACL0,ACL1,ACL2,ACL2,NO, NO, MS_L,MS_D,MS_R,FN3, NO, ENT, \
+ LSFT,NO, NO, NO, NO, BTN3,BTN2,BTN1,FN9, FN10,NO, RSFT,TRNS, \
+ TRNS,LGUI,LALT, BTN1, TRNS,TRNS,TRNS,TRNS),
+
+ /* Layer 4: Mouse mode(IJKL)[Space]
+ * ,-----------------------------------------------------------.
+ * |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
+ * |-----------------------------------------------------------|
+ * |Tab | | | | | |MwL|MwD|McU|MwU|MwR|Wbk|Wfr|Alt-T|
+ * |-----------------------------------------------------------|
+ * |Contro| | | | | |Mb2|McL|McD|McR|Mb1| |Return |
+ * |-----------------------------------------------------------|
+ * |Shift | | | | |Mb3|Mb2|Mb1|Mb4|Mb5| |Shift | |
+ * `-----------------------------------------------------------'
+ * |Gui |Alt | Mb1 |Fn |Fn |
+ * `--------------------------------------------'
+ * Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel
+ */
+ [4] = \
+ KEYMAP(GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
+ FN8, NO, NO, NO, NO, NO, WH_L,WH_D,MS_U,WH_U,WH_R,BTN4,BTN5,FN8, \
+ LCTL,VOLD,VOLU,MUTE,NO, NO, NO, MS_L,MS_D,MS_R,BTN1,NO, ENT, \
+ LSFT,NO, NO, NO, NO, BTN3,BTN2,BTN1,FN9, FN10,NO, RSFT,TRNS, \
+ TRNS,LGUI,LALT, TRNS, TRNS,TRNS,TRNS,TRNS),
+
+};
+
+/* id for user defined functions */
+enum function_id {
+ LSHIFT_LPAREN,
+};
+
+enum macro_id {
+ HELLO,
+ VOLUP,
+ ALT_TAB,
+};
+
+/*
+ * Fn action definition
+ */
+const uint16_t fn_actions[] = {
+ [0] = ACTION_DEFAULT_LAYER_SET(0), // Default layer(not used)
+ [1] = ACTION_LAYER_TAP_TOGGLE(1), // HHKB layer(toggle with 5 taps)
+ [2] = ACTION_LAYER_TAP_KEY(2, KC_SLASH), // Cursor layer with Slash*
+ [3] = ACTION_LAYER_TAP_KEY(3, KC_SCLN), // Mousekey layer with Semicolon*
+ [4] = ACTION_LAYER_TAP_KEY(4, KC_SPC), // Mousekey layer with Space
+ [5] = ACTION_LAYER_MOMENTARY(4), // Mousekey layer(IJKL)
+ [6] = ACTION_MODS_TAP_KEY(MOD_RCTL, KC_ENT), // RControl with tap Enter
+ [7] = ACTION_MODS_ONESHOT(MOD_LSFT), // Oneshot Shift
+ [8] = ACTION_MACRO(ALT_TAB), // Application switching
+ [9] = ACTION_MODS_KEY(MOD_LALT, KC_LEFT),
+ [10] = ACTION_MODS_KEY(MOD_LALT, KC_RIGHT),
+};
+
+/*
+ * Macro definition
+ */
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ switch (id) {
+ case HELLO:
+ return (record->event.pressed ?
+ MACRO( I(0), T(H), T(E), T(L), T(L), W(255), T(O), END ) :
+ MACRO_NONE );
+ case VOLUP:
+ return (record->event.pressed ?
+ MACRO( D(VOLU), U(VOLU), END ) :
+ MACRO_NONE );
+ case ALT_TAB:
+ return (record->event.pressed ?
+ MACRO( D(LALT), D(TAB), END ) :
+ MACRO( U(TAB), END ));
+ }
+ return MACRO_NONE;
+}
+
+
+
+/*
+ * user defined action function
+ */
+void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ if (record->event.pressed) dprint("P"); else dprint("R");
+ dprintf("%d", record->tap.count);
+ if (record->tap.interrupted) dprint("i");
+ dprint("\n");
+
+ switch (id) {
+ case LSHIFT_LPAREN:
+ // Shift parentheses example: LShft + tap '('
+ // http://stevelosh.com/blog/2012/10/a-modern-space-cadet/#shift-parentheses
+ // http://geekhack.org/index.php?topic=41989.msg1304899#msg1304899
+ if (record->event.pressed) {
+ if (record->tap.count > 0 && !record->tap.interrupted) {
+ if (record->tap.interrupted) {
+ dprint("tap interrupted\n");
+ register_mods(MOD_BIT(KC_LSHIFT));
+ }
+ } else {
+ register_mods(MOD_BIT(KC_LSHIFT));
+ }
+ } else {
+ if (record->tap.count > 0 && !(record->tap.interrupted)) {
+ add_weak_mods(MOD_BIT(KC_LSHIFT));
+ send_keyboard_report();
+ register_code(KC_9);
+ unregister_code(KC_9);
+ del_weak_mods(MOD_BIT(KC_LSHIFT));
+ send_keyboard_report();
+ record->tap.count = 0; // ad hoc: cancel tap
+ } else {
+ unregister_mods(MOD_BIT(KC_LSHIFT));
+ }
+ }
+ break;
+ }
+}
diff --git a/keyboards/infinity_chibios/led.c b/keyboards/infinity_chibios/led.c
new file mode 100644
index 000000000..aed66c7c0
--- /dev/null
+++ b/keyboards/infinity_chibios/led.c
@@ -0,0 +1,24 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "hal.h"
+
+#include "led.h"
+
+
+void led_set(uint8_t usb_led) {
+}
diff --git a/keyboards/infinity_chibios/matrix.c b/keyboards/infinity_chibios/matrix.c
new file mode 100644
index 000000000..2c68ea83a
--- /dev/null
+++ b/keyboards/infinity_chibios/matrix.c
@@ -0,0 +1,128 @@
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include "hal.h"
+#include "timer.h"
+#include "wait.h"
+#include "print.h"
+#include "matrix.h"
+
+
+/*
+ * Infinity Pinusage:
+ * Column pins are input with internal pull-down. Row pins are output and strobe with high.
+ * Key is high or 1 when it turns on.
+ *
+ * col: { PTD1, PTD2, PTD3, PTD4, PTD5, PTD6, PTD7 }
+ * row: { PTB0, PTB1, PTB2, PTB3, PTB16, PTB17, PTC4, PTC5, PTD0 }
+ */
+/* matrix state(1:on, 0:off) */
+static matrix_row_t matrix[MATRIX_ROWS];
+static matrix_row_t matrix_debouncing[MATRIX_ROWS];
+static bool debouncing = false;
+static uint16_t debouncing_time = 0;
+
+
+void matrix_init(void)
+{
+ /* Column(sense) */
+ palSetPadMode(GPIOD, 1, PAL_MODE_INPUT_PULLDOWN);
+ palSetPadMode(GPIOD, 2, PAL_MODE_INPUT_PULLDOWN);
+ palSetPadMode(GPIOD, 3, PAL_MODE_INPUT_PULLDOWN);
+ palSetPadMode(GPIOD, 4, PAL_MODE_INPUT_PULLDOWN);
+ palSetPadMode(GPIOD, 5, PAL_MODE_INPUT_PULLDOWN);
+ palSetPadMode(GPIOD, 6, PAL_MODE_INPUT_PULLDOWN);
+ palSetPadMode(GPIOD, 7, PAL_MODE_INPUT_PULLDOWN);
+
+ /* Row(strobe) */
+ palSetPadMode(GPIOB, 0, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOB, 1, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOB, 2, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOB, 3, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOB, 16, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOB, 17, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOC, 4, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOC, 5, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOD, 0, PAL_MODE_OUTPUT_PUSHPULL);
+
+ memset(matrix, 0, MATRIX_ROWS);
+ memset(matrix_debouncing, 0, MATRIX_ROWS);
+}
+
+uint8_t matrix_scan(void)
+{
+ for (int row = 0; row < MATRIX_ROWS; row++) {
+ matrix_row_t data = 0;
+
+ // strobe row
+ switch (row) {
+ case 0: palSetPad(GPIOB, 0); break;
+ case 1: palSetPad(GPIOB, 1); break;
+ case 2: palSetPad(GPIOB, 2); break;
+ case 3: palSetPad(GPIOB, 3); break;
+ case 4: palSetPad(GPIOB, 16); break;
+ case 5: palSetPad(GPIOB, 17); break;
+ case 6: palSetPad(GPIOC, 4); break;
+ case 7: palSetPad(GPIOC, 5); break;
+ case 8: palSetPad(GPIOD, 0); break;
+ }
+
+ wait_us(1); // need wait to settle pin state
+
+ // read col data
+ data = (palReadPort(GPIOD)>>1);
+
+ // un-strobe row
+ switch (row) {
+ case 0: palClearPad(GPIOB, 0); break;
+ case 1: palClearPad(GPIOB, 1); break;
+ case 2: palClearPad(GPIOB, 2); break;
+ case 3: palClearPad(GPIOB, 3); break;
+ case 4: palClearPad(GPIOB, 16); break;
+ case 5: palClearPad(GPIOB, 17); break;
+ case 6: palClearPad(GPIOC, 4); break;
+ case 7: palClearPad(GPIOC, 5); break;
+ case 8: palClearPad(GPIOD, 0); break;
+ }
+
+ if (matrix_debouncing[row] != data) {
+ matrix_debouncing[row] = data;
+ debouncing = true;
+ debouncing_time = timer_read();
+ }
+ }
+
+ if (debouncing && timer_elapsed(debouncing_time) > DEBOUNCE) {
+ for (int row = 0; row < MATRIX_ROWS; row++) {
+ matrix[row] = matrix_debouncing[row];
+ }
+ debouncing = false;
+ }
+ return 1;
+}
+
+bool matrix_is_on(uint8_t row, uint8_t col)
+{
+ return (matrix[row] & (1<<col));
+}
+
+matrix_row_t matrix_get_row(uint8_t row)
+{
+ return matrix[row];
+}
+
+void matrix_print(void)
+{
+ xprintf("\nr/c 01234567\n");
+ for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
+ xprintf("%02X: ");
+ matrix_row_t data = matrix_get_row(row);
+ for (int col = 0; col < MATRIX_COLS; col++) {
+ if (data & (1<<col))
+ xprintf("1");
+ else
+ xprintf("0");
+ }
+ xprintf("\n");
+ }
+}
diff --git a/keyboards/infinity_chibios/mcuconf.h b/keyboards/infinity_chibios/mcuconf.h
new file mode 100644
index 000000000..66b6ce25d
--- /dev/null
+++ b/keyboards/infinity_chibios/mcuconf.h
@@ -0,0 +1,55 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#ifndef _MCUCONF_H_
+#define _MCUCONF_H_
+
+#define K20x_MCUCONF
+
+/*
+ * HAL driver system settings.
+ */
+
+/* Select the MCU clocking mode below by enabling the appropriate block. */
+
+#define KINETIS_NO_INIT FALSE
+
+/* FEI mode - 48 MHz with internal 32.768 kHz crystal */
+#define KINETIS_MCG_MODE KINETIS_MCG_MODE_FEI
+#define KINETIS_MCG_FLL_DMX32 1 /* Fine-tune for 32.768 kHz */
+#define KINETIS_MCG_FLL_DRS 1 /* 1464x FLL factor */
+#define KINETIS_SYSCLK_FREQUENCY 47972352UL /* 32.768 kHz * 1464 (~48 MHz) */
+#define KINETIS_CLKDIV1_OUTDIV1 1
+#define KINETIS_CLKDIV1_OUTDIV2 1
+#define KINETIS_CLKDIV1_OUTDIV4 2
+#define KINETIS_BUSCLK_FREQUENCY KINETIS_SYSCLK_FREQUENCY
+#define KINETIS_FLASHCLK_FREQUENCY KINETIS_SYSCLK_FREQUENCY/2
+
+/*
+ * SERIAL driver system settings.
+ */
+#define KINETIS_SERIAL_USE_UART0 TRUE
+
+/*
+ * USB driver settings
+ */
+#define KINETIS_USB_USE_USB0 TRUE
+/* Need to redefine this, since the default is for K20x */
+/* This is for Teensy LC; you should comment it out (or change to 5)
+ * for Teensy 3.x */
+#define KINETIS_USB_USB0_IRQ_PRIORITY 2
+
+#endif /* _MCUCONF_H_ */
diff --git a/keyboards/infinity_ergodox/MEMO.txt b/keyboards/infinity_ergodox/MEMO.txt
new file mode 100644
index 000000000..e2886aa00
--- /dev/null
+++ b/keyboards/infinity_ergodox/MEMO.txt
@@ -0,0 +1,385 @@
+flabbergast's TMK/ChibiOS port
+==============================
+2015/10/16
+
+
+Build
+-----
+$ git clone -b chibios https://github.com/flabbergast/tmk_keyboard.git
+
+$ cd tmk_keyboard
+$ git submodule add -f -b kinetis https://github.com/flabbergast/ChibiOS.git tmk_core/tool/chibios/chibios
+or
+$ cd tmk_keyboard/tmk_core/tool/chibios
+$ git clone -b kinetis https://github.com/flabbergast/ChibiOS.git tmk_core/tool/chibios/chibios
+
+$ cd tmk_keyboard/keyboard/infinity_chibios
+$ make
+
+
+
+
+Chibios Configuration
+---------------------
+halconf.h: for HAL configuration
+ placed in project directory
+ read in chibios/os/hal/hal.mk
+ included in chibios/os/hal/include/hal.h
+mcuconf.h: for MCU configuration
+ placed in project directory
+ included in halconf.h
+
+
+Chibios Term
+------------
+PAL = Port Abstraction Layer
+ palWritePad
+ palReadPad
+ palSetPad
+ chibios/os/hal/include/pal.h
+
+LLD = Low Level Driver
+
+
+Makefile
+--------
+ # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
+ MCU_FAMILY = KINETIS
+ MCU_SERIES = KL2x
+
+ # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+ # or <this_dir>/ld/
+ MCU_LDSCRIPT = MKL26Z64
+
+ # - it should exist in <chibios>/os/common/ports/ARMCMx/compilers/GCC/mk/
+ MCU_STARTUP = kl2x
+
+ # Board: it should exist either in <chibios>/os/hal/boards/
+ # or <this_dir>/boards
+ BOARD = PJRC_TEENSY_LC
+
+ MCU = cortex-m0
+
+ # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
+ ARMV = 6
+
+
+halconf.h
+---------
+
+
+mcuconf.h
+---------
+
+
+chconf.h
+--------
+
+
+ld script
+---------
+--- ../../tmk_core/tool/chibios/chibios/os/common/ports/ARMCMx/compilers/GCC/ld/MKL26Z64.ld 2015-10-15 09:08:58.732904304 +0900
++++ ld/MKL26Z64.ld 2015-10-15 08:48:06.430215496 +0900
+@@ -27,7 +27,8 @@
+ {
+ flash0 : org = 0x00000000, len = 0xc0
+ flashcfg : org = 0x00000400, len = 0x10
+- flash : org = 0x00000410, len = 64k - 0x410
++ flash : org = 0x00000410, len = 62k - 0x410
++ eeprom_emu : org = 0x0000F800, len = 2k
+ ram : org = 0x1FFFF800, len = 8k
+ }
+
+@@ -35,6 +36,10 @@
+ __ram_size__ = LENGTH(ram);
+ __ram_end__ = __ram_start__ + __ram_size__;
+
++__eeprom_workarea_start__ = ORIGIN(eeprom_emu);
++__eeprom_workarea_size__ = LENGTH(eeprom_emu);
++__eeprom_workarea_end__ = __eeprom_workarea_start__ + __eeprom_workarea_size__;
++
+ SECTIONS
+ {
+ . = 0;
+
+
+
+Configuration/Startup for Infinity 60%
+--------------------------------------
+Configuration:
+
+
+Clock:
+Inifinity
+ FEI(FLL Engaged Internal) mode with core clock:48MHz, bus clock:48MHz, flash clock:24MHz
+ Clock dividor:
+ SIM_CLKDIV1[OUTDIV1] = 0 divide-by-1 for core clock
+ SIM_CLKDIV1[OUTDIV2] = 0 divide-by-1 for bus clock
+ SIM_CLKDIV1[OUTDIV4] = 1 divide-by-2 for flash clock
+ Internal reference clock:
+ MCG_C1[IREFS] = 1 Internal Reference Select for clock source for FLL
+ MCG_C1[IRCLKEN] = 1 Internal Reference Clock Enable
+ FLL multipilication:
+ MCG_C4[DMX32] = 1
+ MCG_C4[DRST_DRS] = 01 FLL factor 1464 * 32.768kHz = 48MHz
+
+chibios/os/hal/ports/KINETIS/K20x/hal_lld.c
+ k20x_clock_init(): called in __early_init() defined in board.c
+ disable watchdog and configure clock
+
+ configurable macros:
+ KINETIS_NO_INIT: whether init or not
+ KINETIS_MCG_MODE: clock mode
+ KINETIS_MCG_MODE_FEI
+ KINETIS_MCG_MODE_PEE
+ hal/ports/KINETIS/K20x/hal_lld.h
+
+
+chibios/os/hal/boards/FREESCALE_FREEDOM_K20D50M/board.h
+ PALConfig pal_default_config
+ boardInit()
+ __early_init()
+ macro definitions for board infos, freq and mcu type
+
+chibios/os/hal/boards/FREESCALE_FREEDOM_K20D50M/board.c
+
+USB
+
+
+Startup
+-------
+ common/ports/ARMCMx/GCC/crt0_v[67]m.s
+ Reset_Handler: startup code
+ common/ports/ARMCMx/GCC/crt1.c
+ __core_init(): weak
+ __early_init(): weak
+ __late_init(): weak
+ __default_exit(): weak
+ called from Reset_Handler of crt0
+ common/ports/ARMCMx/GCC/vector.c
+ common/ports/ARMCMx/GCC/ld/*.ld
+
+chibios/os/common/ports/ARMCMx/compilers/GCC/
+├── crt0_v6m.s
+├── crt0_v7m.s
+├── crt1.c
+├── ld
+│   ├── MK20DX128BLDR3.ld
+│   ├── MK20DX128BLDR4.ld
+│   ├── MK20DX128.ld
+│   ├── MK20DX256.ld
+│   ├── MKL25Z128.ld
+│   ├── MKL26Z128.ld
+│   ├── MKL26Z64.ld
+│   └── STM32L476xG.ld
+├── mk
+│   ├── startup_k20x5.mk
+│   ├── startup_k20x7.mk
+│   ├── startup_k20x.mk
+│   ├── startup_kl2x.mk
+│   └── startup_stm32l4xx.mk
+├── rules.ld
+├── rules.mk
+└── vectors.c
+
+chibios/os/hal/
+├── boards
+│   ├── FREESCALE_FREEDOM_K20D50M
+│   │   ├── board.c
+│   │   ├── board.h
+│   │   └── board.mk
+│   ├── MCHCK_K20
+│   │   ├── board.c
+│   │   ├── board.h
+│   │   └── board.mk
+│   ├── PJRC_TEENSY_3
+│   │   ├── board.c
+│   │   ├── board.h
+│   │   └── board.mk
+│   ├── PJRC_TEENSY_3_1
+│   │   ├── board.c
+│   │   ├── board.h
+│   │   └── board.mk
+│   ├── PJRC_TEENSY_LC
+│   │   ├── board.c
+│   │   ├── board.h
+│   │   └── board.mk
+│   ├── readme.txt
+│   ├── simulator
+│   │   ├── board.c
+│   │   ├── board.h
+│   │   └── board.mk
+│   ├── ST_NUCLEO_F030R8
+│   │   ├── board.c
+│   │   ├── board.h
+│   │   ├── board.mk
+│   │   └── cfg
+│   │   └── board.chcfg
+├── hal.mk
+├── include
+│   ├── adc.h
+│   ├── can.h
+│   ├── dac.h
+│   ├── ext.h
+│   ├── gpt.h
+│   ├── hal_channels.h
+│   ├── hal_files.h
+│   ├── hal.h
+│   ├── hal_ioblock.h
+│   ├── hal_mmcsd.h
+│   ├── hal_queues.h
+│   ├── hal_streams.h
+│   ├── i2c.h
+│   ├── i2s.h
+│   ├── icu.h
+│   ├── mac.h
+│   ├── mii.h
+│   ├── mmc_spi.h
+│   ├── pal.h
+│   ├── pwm.h
+│   ├── rtc.h
+│   ├── sdc.h
+│   ├── serial.h
+│   ├── serial_usb.h
+│   ├── spi.h
+│   ├── st.h
+│   ├── uart.h
+│   └── usb.h
+├── lib
+│   └── streams
+│   ├── chprintf.c
+│   ├── chprintf.h
+│   ├── memstreams.c
+│   ├── memstreams.h
+│   ├── nullstreams.c
+│   └── nullstreams.h
+├── osal
+│   ├── nil
+│   │   ├── osal.c
+│   │   ├── osal.h
+│   │   └── osal.mk
+│   ├── os-less
+│   │   └── ARMCMx
+│   │   ├── osal.c
+│   │   ├── osal.h
+│   │   └── osal.mk
+│   └── rt
+│   ├── osal.c
+│   ├── osal.h
+│   └── osal.mk
+├── ports
+│   ├── AVR
+│   ├── common
+│   │   └── ARMCMx
+│   │   ├── mpu.h
+│   │   ├── nvic.c
+│   │   └── nvic.h
+│   ├── KINETIS
+│   │   ├── K20x
+│   │   │   ├── hal_lld.c
+│   │   │   ├── hal_lld.h
+│   │   │   ├── kinetis_registry.h
+│   │   │   ├── platform.dox
+│   │   │   ├── platform.mk
+│   │   │   ├── pwm_lld.c
+│   │   │   ├── pwm_lld.h
+│   │   │   ├── spi_lld.c
+│   │   │   └── spi_lld.h
+│   │   ├── KL2x
+│   │   │   ├── hal_lld.c
+│   │   │   ├── hal_lld.h
+│   │   │   ├── kinetis_registry.h
+│   │   │   ├── platform.mk
+│   │   │   ├── pwm_lld.c
+│   │   │   └── pwm_lld.h
+│   │   ├── LLD
+│   │   │   ├── adc_lld.c
+│   │   │   ├── adc_lld.h
+│   │   │   ├── ext_lld.c
+│   │   │   ├── ext_lld.h
+│   │   │   ├── gpt_lld.c
+│   │   │   ├── gpt_lld.h
+│   │   │   ├── i2c_lld.c
+│   │   │   ├── i2c_lld.h
+│   │   │   ├── pal_lld.c
+│   │   │   ├── pal_lld.h
+│   │   │   ├── serial_lld.c
+│   │   │   ├── serial_lld.h
+│   │   │   ├── st_lld.c
+│   │   │   ├── st_lld.h
+│   │   │   ├── usb_lld.c
+│   │   │   └── usb_lld.h
+│   │   └── README.md
+│   ├── LPC
+│   ├── simulator
+│   └── STM32
+├── src
+│   ├── adc.c
+│   ├── can.c
+│   ├── dac.c
+│   ├── ext.c
+│   ├── gpt.c
+│   ├── hal.c
+│   ├── hal_mmcsd.c
+│   ├── hal_queues.c
+│   ├── i2c.c
+│   ├── i2s.c
+│   ├── icu.c
+│   ├── mac.c
+│   ├── mmc_spi.c
+│   ├── pal.c
+│   ├── pwm.c
+│   ├── rtc.c
+│   ├── sdc.c
+│   ├── serial.c
+│   ├── serial_usb.c
+│   ├── spi.c
+│   ├── st.c
+│   ├── uart.c
+│   └── usb.c
+└── templates
+ ├── adc_lld.c
+ ├── adc_lld.h
+ ├── can_lld.c
+ ├── can_lld.h
+ ├── dac_lld.c
+ ├── dac_lld.h
+ ├── ext_lld.c
+ ├── ext_lld.h
+ ├── gpt_lld.c
+ ├── gpt_lld.h
+ ├── halconf.h
+ ├── hal_lld.c
+ ├── hal_lld.h
+ ├── i2c_lld.c
+ ├── i2c_lld.h
+ ├── i2s_lld.c
+ ├── i2s_lld.h
+ ├── icu_lld.c
+ ├── icu_lld.h
+ ├── mac_lld.c
+ ├── mac_lld.h
+ ├── mcuconf.h
+ ├── osal
+ │   ├── osal.c
+ │   ├── osal.h
+ │   └── osal.mk
+ ├── pal_lld.c
+ ├── pal_lld.h
+ ├── platform.mk
+ ├── pwm_lld.c
+ ├── pwm_lld.h
+ ├── rtc_lld.c
+ ├── rtc_lld.h
+ ├── sdc_lld.c
+ ├── sdc_lld.h
+ ├── serial_lld.c
+ ├── serial_lld.h
+ ├── spi_lld.c
+ ├── spi_lld.h
+ ├── st_lld.c
+ ├── st_lld.h
+ ├── uart_lld.c
+ ├── uart_lld.h
+ ├── usb_lld.c
+ └── usb_lld.h
diff --git a/keyboards/infinity_ergodox/Makefile b/keyboards/infinity_ergodox/Makefile
new file mode 100644
index 000000000..fb21aae5e
--- /dev/null
+++ b/keyboards/infinity_ergodox/Makefile
@@ -0,0 +1,72 @@
+# project specific files
+SRC = matrix.c \
+ led.c
+
+## chip/board settings
+# - the next two should match the directories in
+# <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
+# - For Teensies, FAMILY = KINETIS and SERIES is either
+# KL2x (LC) or K20x (3.0,3.1,3.2).
+# - For Infinity KB, SERIES = K20x
+MCU_FAMILY = KINETIS
+MCU_SERIES = K20x
+
+# Linker script to use
+# - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+# or <this_dir>/ld/
+# - NOTE: a custom ld script is needed for EEPROM on Teensy LC
+# - LDSCRIPT =
+# - MKL26Z64 for Teensy LC
+# - MK20DX128 for Teensy 3.0
+# - MK20DX256 for Teensy 3.1 and 3.2
+# - MK20DX128BLDR4 for Infinity 60% with Kiibohd bootloader
+# - MK20DX256BLDR8 for Infinity ErgoDox with Kiibohd bootloader
+MCU_LDSCRIPT = MK20DX256BLDR8
+
+# Startup code to use
+# - it should exist in <chibios>/os/common/ports/ARMCMx/compilers/GCC/mk/
+# - STARTUP =
+# - kl2x for Teensy LC
+# - k20x5 for Teensy 3.0 and Infinity 60%
+# - k20x7 for Teensy 3.1, 3.2 and Infinity ErgoDox
+MCU_STARTUP = k20x7
+
+# Board: it should exist either in <chibios>/os/hal/boards/
+# or <this_dir>/boards
+# - BOARD =
+# - PJRC_TEENSY_LC for Teensy LC
+# - PJRC_TEENSY_3 for Teensy 3.0
+# - PJRC_TEENSY_3_1 for Teensy 3.1 or 3.2
+# - MCHCK_K20 for Infinity KB
+#BOARD = MCHCK_K20
+BOARD = PJRC_TEENSY_3_1
+
+# Cortex version
+# Teensy LC is cortex-m0; Teensy 3.x are cortex-m4
+MCU = cortex-m4
+
+# ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
+# I.e. 6 for Teensy LC; 7 for Teensy 3.x
+ARMV = 7
+
+# Vector table for application
+# 0x00000000-0x00001000 area is occupied by bootlaoder.*/
+# The CORTEX_VTOR... is needed only for MCHCK/Infinity KB
+OPT_DEFS = -DCORTEX_VTOR_INIT=0x00002000
+
+# Build Options
+# comment out to disable the options.
+#
+BOOTMAGIC_ENABLE ?= yes # Virtual DIP switch configuration
+## (Note that for BOOTMAGIC on Teensy LC you have to use a custom .ld script.)
+MOUSEKEY_ENABLE ?= yes # Mouse keys
+EXTRAKEY_ENABLE ?= yes # Audio control and System control
+CONSOLE_ENABLE ?= yes # Console for debug
+COMMAND_ENABLE ?= yes # Commands for debug and configuration
+SLEEP_LED_ENABLE ?= yes # Breathing sleep LED during USB suspend
+NKRO_ENABLE ?= yes # USB Nkey Rollover
+CUSTOM_MATRIX ?= yes # Custom matrix file
+
+ifndef QUANTUM_DIR
+ include ../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/infinity_ergodox/bootloader_defs.h b/keyboards/infinity_ergodox/bootloader_defs.h
new file mode 100644
index 000000000..c67153be6
--- /dev/null
+++ b/keyboards/infinity_ergodox/bootloader_defs.h
@@ -0,0 +1 @@
+#define KIIBOHD_BOOTLOADER
diff --git a/keyboards/infinity_ergodox/chconf.h b/keyboards/infinity_ergodox/chconf.h
new file mode 100644
index 000000000..d59c35eb6
--- /dev/null
+++ b/keyboards/infinity_ergodox/chconf.h
@@ -0,0 +1,524 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file templates/chconf.h
+ * @brief Configuration file template.
+ * @details A copy of this file must be placed in each project directory, it
+ * contains the application specific kernel settings.
+ *
+ * @addtogroup config
+ * @details Kernel related settings and hooks.
+ * @{
+ */
+
+#ifndef _CHCONF_H_
+#define _CHCONF_H_
+
+#define _CHIBIOS_RT_CONF_
+
+/*===========================================================================*/
+/**
+ * @name System timers settings
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief System time counter resolution.
+ * @note Allowed values are 16 or 32 bits.
+ */
+#define CH_CFG_ST_RESOLUTION 32
+
+/**
+ * @brief System tick frequency.
+ * @details Frequency of the system timer that drives the system ticks. This
+ * setting also defines the system tick time unit.
+ */
+#define CH_CFG_ST_FREQUENCY 100000
+
+/**
+ * @brief Time delta constant for the tick-less mode.
+ * @note If this value is zero then the system uses the classic
+ * periodic tick. This value represents the minimum number
+ * of ticks that is safe to specify in a timeout directive.
+ * The value one is not valid, timeouts are rounded up to
+ * this value.
+ */
+#define CH_CFG_ST_TIMEDELTA 0
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Kernel parameters and options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Round robin interval.
+ * @details This constant is the number of system ticks allowed for the
+ * threads before preemption occurs. Setting this value to zero
+ * disables the preemption for threads with equal priority and the
+ * round robin becomes cooperative. Note that higher priority
+ * threads can still preempt, the kernel is always preemptive.
+ * @note Disabling the round robin preemption makes the kernel more compact
+ * and generally faster.
+ * @note The round robin preemption is not supported in tickless mode and
+ * must be set to zero in that case.
+ */
+#define CH_CFG_TIME_QUANTUM 20
+
+/**
+ * @brief Managed RAM size.
+ * @details Size of the RAM area to be managed by the OS. If set to zero
+ * then the whole available RAM is used. The core memory is made
+ * available to the heap allocator and/or can be used directly through
+ * the simplified core memory allocator.
+ *
+ * @note In order to let the OS manage the whole RAM the linker script must
+ * provide the @p __heap_base__ and @p __heap_end__ symbols.
+ * @note Requires @p CH_CFG_USE_MEMCORE.
+ */
+#define CH_CFG_MEMCORE_SIZE 0
+
+/**
+ * @brief Idle thread automatic spawn suppression.
+ * @details When this option is activated the function @p chSysInit()
+ * does not spawn the idle thread. The application @p main()
+ * function becomes the idle thread and must implement an
+ * infinite loop.
+ */
+#define CH_CFG_NO_IDLE_THREAD FALSE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Performance options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief OS optimization.
+ * @details If enabled then time efficient rather than space efficient code
+ * is used when two possible implementations exist.
+ *
+ * @note This is not related to the compiler optimization options.
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_OPTIMIZE_SPEED TRUE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Subsystem options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Time Measurement APIs.
+ * @details If enabled then the time measurement APIs are included in
+ * the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_TM FALSE
+
+/**
+ * @brief Threads registry APIs.
+ * @details If enabled then the registry APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_REGISTRY TRUE
+
+/**
+ * @brief Threads synchronization APIs.
+ * @details If enabled then the @p chThdWait() function is included in
+ * the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_WAITEXIT TRUE
+
+/**
+ * @brief Semaphores APIs.
+ * @details If enabled then the Semaphores APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_SEMAPHORES TRUE
+
+/**
+ * @brief Semaphores queuing mode.
+ * @details If enabled then the threads are enqueued on semaphores by
+ * priority rather than in FIFO order.
+ *
+ * @note The default is @p FALSE. Enable this if you have special
+ * requirements.
+ * @note Requires @p CH_CFG_USE_SEMAPHORES.
+ */
+#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE
+
+/**
+ * @brief Mutexes APIs.
+ * @details If enabled then the mutexes APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MUTEXES TRUE
+
+/**
+ * @brief Enables recursive behavior on mutexes.
+ * @note Recursive mutexes are heavier and have an increased
+ * memory footprint.
+ *
+ * @note The default is @p FALSE.
+ * @note Requires @p CH_CFG_USE_MUTEXES.
+ */
+#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE
+
+/**
+ * @brief Conditional Variables APIs.
+ * @details If enabled then the conditional variables APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_MUTEXES.
+ */
+#define CH_CFG_USE_CONDVARS TRUE
+
+/**
+ * @brief Conditional Variables APIs with timeout.
+ * @details If enabled then the conditional variables APIs with timeout
+ * specification are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_CONDVARS.
+ */
+#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE
+
+/**
+ * @brief Events Flags APIs.
+ * @details If enabled then the event flags APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_EVENTS TRUE
+
+/**
+ * @brief Events Flags APIs with timeout.
+ * @details If enabled then the events APIs with timeout specification
+ * are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_EVENTS.
+ */
+#define CH_CFG_USE_EVENTS_TIMEOUT TRUE
+
+/**
+ * @brief Synchronous Messages APIs.
+ * @details If enabled then the synchronous messages APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MESSAGES TRUE
+
+/**
+ * @brief Synchronous Messages queuing mode.
+ * @details If enabled then messages are served by priority rather than in
+ * FIFO order.
+ *
+ * @note The default is @p FALSE. Enable this if you have special
+ * requirements.
+ * @note Requires @p CH_CFG_USE_MESSAGES.
+ */
+#define CH_CFG_USE_MESSAGES_PRIORITY FALSE
+
+/**
+ * @brief Mailboxes APIs.
+ * @details If enabled then the asynchronous messages (mailboxes) APIs are
+ * included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_SEMAPHORES.
+ */
+#define CH_CFG_USE_MAILBOXES TRUE
+
+/**
+ * @brief I/O Queues APIs.
+ * @details If enabled then the I/O queues APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_QUEUES TRUE
+
+/**
+ * @brief Core Memory Manager APIs.
+ * @details If enabled then the core memory manager APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MEMCORE TRUE
+
+/**
+ * @brief Heap Allocator APIs.
+ * @details If enabled then the memory heap allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or
+ * @p CH_CFG_USE_SEMAPHORES.
+ * @note Mutexes are recommended.
+ */
+#define CH_CFG_USE_HEAP TRUE
+
+/**
+ * @brief Memory Pools Allocator APIs.
+ * @details If enabled then the memory pools allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MEMPOOLS TRUE
+
+/**
+ * @brief Dynamic Threads APIs.
+ * @details If enabled then the dynamic threads creation APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_WAITEXIT.
+ * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS.
+ */
+#define CH_CFG_USE_DYNAMIC TRUE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Debug options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Debug option, kernel statistics.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_STATISTICS FALSE
+
+/**
+ * @brief Debug option, system state check.
+ * @details If enabled the correct call protocol for system APIs is checked
+ * at runtime.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_SYSTEM_STATE_CHECK FALSE
+
+/**
+ * @brief Debug option, parameters checks.
+ * @details If enabled then the checks on the API functions input
+ * parameters are activated.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_ENABLE_CHECKS FALSE
+
+/**
+ * @brief Debug option, consistency checks.
+ * @details If enabled then all the assertions in the kernel code are
+ * activated. This includes consistency checks inside the kernel,
+ * runtime anomalies and port-defined checks.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_ENABLE_ASSERTS FALSE
+
+/**
+ * @brief Debug option, trace buffer.
+ * @details If enabled then the context switch circular trace buffer is
+ * activated.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_ENABLE_TRACE FALSE
+
+/**
+ * @brief Debug option, stack checks.
+ * @details If enabled then a runtime stack check is performed.
+ *
+ * @note The default is @p FALSE.
+ * @note The stack check is performed in a architecture/port dependent way.
+ * It may not be implemented or some ports.
+ * @note The default failure mode is to halt the system with the global
+ * @p panic_msg variable set to @p NULL.
+ */
+#define CH_DBG_ENABLE_STACK_CHECK FALSE
+
+/**
+ * @brief Debug option, stacks initialization.
+ * @details If enabled then the threads working area is filled with a byte
+ * value when a thread is created. This can be useful for the
+ * runtime measurement of the used stack.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_FILL_THREADS FALSE
+
+/**
+ * @brief Debug option, threads profiling.
+ * @details If enabled then a field is added to the @p thread_t structure that
+ * counts the system ticks occurred while executing the thread.
+ *
+ * @note The default is @p FALSE.
+ * @note This debug option is not currently compatible with the
+ * tickless mode.
+ */
+#define CH_DBG_THREADS_PROFILING FALSE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Kernel hooks
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Threads descriptor structure extension.
+ * @details User fields added to the end of the @p thread_t structure.
+ */
+#define CH_CFG_THREAD_EXTRA_FIELDS \
+ /* Add threads custom fields here.*/
+
+/**
+ * @brief Threads initialization hook.
+ * @details User initialization code added to the @p chThdInit() API.
+ *
+ * @note It is invoked from within @p chThdInit() and implicitly from all
+ * the threads creation APIs.
+ */
+#define CH_CFG_THREAD_INIT_HOOK(tp) { \
+ /* Add threads initialization code here.*/ \
+}
+
+/**
+ * @brief Threads finalization hook.
+ * @details User finalization code added to the @p chThdExit() API.
+ *
+ * @note It is inserted into lock zone.
+ * @note It is also invoked when the threads simply return in order to
+ * terminate.
+ */
+#define CH_CFG_THREAD_EXIT_HOOK(tp) { \
+ /* Add threads finalization code here.*/ \
+}
+
+/**
+ * @brief Context switch hook.
+ * @details This hook is invoked just before switching between threads.
+ */
+#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \
+ /* Context switch code here.*/ \
+}
+
+/**
+ * @brief ISR enter hook.
+ */
+#define CH_CFG_IRQ_PROLOGUE_HOOK() { \
+ /* IRQ prologue code here.*/ \
+}
+
+/**
+ * @brief ISR exit hook.
+ */
+#define CH_CFG_IRQ_EPILOGUE_HOOK() { \
+ /* IRQ epilogue code here.*/ \
+}
+
+/**
+ * @brief Idle thread enter hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to activate a power saving mode.
+ */
+#define CH_CFG_IDLE_ENTER_HOOK() { \
+}
+
+/**
+ * @brief Idle thread leave hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to deactivate a power saving mode.
+ */
+#define CH_CFG_IDLE_LEAVE_HOOK() { \
+}
+
+/**
+ * @brief Idle Loop hook.
+ * @details This hook is continuously invoked by the idle thread loop.
+ */
+#define CH_CFG_IDLE_LOOP_HOOK() { \
+ /* Idle loop code here.*/ \
+}
+
+/**
+ * @brief System tick event hook.
+ * @details This hook is invoked in the system tick handler immediately
+ * after processing the virtual timers queue.
+ */
+#define CH_CFG_SYSTEM_TICK_HOOK() { \
+ /* System tick event code here.*/ \
+}
+
+/**
+ * @brief System halt hook.
+ * @details This hook is invoked in case to a system halting error before
+ * the system is halted.
+ */
+#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \
+ /* System halt code here.*/ \
+}
+
+/**
+ * @brief Trace hook.
+ * @details This hook is invoked each time a new record is written in the
+ * trace buffer.
+ */
+#define CH_CFG_TRACE_HOOK(tep) { \
+ /* Trace code here.*/ \
+}
+
+/** @} */
+
+/*===========================================================================*/
+/* Port-specific settings (override port settings defaulted in chcore.h). */
+/*===========================================================================*/
+
+#endif /* _CHCONF_H_ */
+
+/** @} */
diff --git a/keyboards/infinity_ergodox/config.h b/keyboards/infinity_ergodox/config.h
new file mode 100644
index 000000000..d24ee0f05
--- /dev/null
+++ b/keyboards/infinity_ergodox/config.h
@@ -0,0 +1,80 @@
+/*
+Copyright 2015 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x6464
+#define DEVICE_VER 0x0001
+/* in python2: list(u"whatever".encode('utf-16-le')) */
+/* at most 32 characters or the ugly hack in usb_main.c borks */
+#define MANUFACTURER "TMK"
+#define USBSTR_MANUFACTURER 'T', '\x00', 'M', '\x00', 'K', '\x00', ' ', '\x00'
+#define PRODUCT "Infinity keyboard/TMK"
+#define USBSTR_PRODUCT 'I', '\x00', 'n', '\x00', 'f', '\x00', 'i', '\x00', 'n', '\x00', 'i', '\x00', 't', '\x00', 'y', '\x00', ' ', '\x00', 'k', '\x00', 'e', '\x00', 'y', '\x00', 'b', '\x00', 'o', '\x00', 'a', '\x00', 'r', '\x00', 'd', '\x00', '/', '\x00', 'T', '\x00', 'M', '\x00', 'K', '\x00'
+
+/* key matrix size */
+#define MATRIX_ROWS 18
+#define MATRIX_COLS 5
+#define LOCAL_MATRIX_ROWS 9
+
+/* define if matrix has ghost */
+//#define MATRIX_HAS_GHOST
+
+/* Set 0 if debouncing isn't needed */
+#define DEBOUNCE 5
+
+/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
+//#define LOCKING_SUPPORT_ENABLE
+/* Locking resynchronize hack */
+//#define LOCKING_RESYNC_ENABLE
+
+/* key combination for command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+/* Keymap for Infiity prototype */
+#define INFINITY_PROTOTYPE
+
+#define SERIAL_LINK_BAUD 562500
+#define SERIAL_LINK_THREAD_PRIORITY (NORMALPRIO - 1)
+// The visualizer needs gfx thread priorities
+#define VISUALIZER_THREAD_PRIORITY (NORMAL_PRIORITY - 2)
+
+/*
+ * Feature disable options
+ * These options are also useful to firmware size reduction.
+ */
+
+/* disable debug print */
+//#define NO_DEBUG
+
+/* disable print */
+//#define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+
+#endif
diff --git a/keyboards/infinity_ergodox/halconf.h b/keyboards/infinity_ergodox/halconf.h
new file mode 100644
index 000000000..55dd5e88d
--- /dev/null
+++ b/keyboards/infinity_ergodox/halconf.h
@@ -0,0 +1,353 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file templates/halconf.h
+ * @brief HAL configuration header.
+ * @details HAL configuration file, this file allows to enable or disable the
+ * various device drivers from your application. You may also use
+ * this file in order to override the device drivers default settings.
+ *
+ * @addtogroup HAL_CONF
+ * @{
+ */
+
+#ifndef _HALCONF_H_
+#define _HALCONF_H_
+
+#include "mcuconf.h"
+
+/**
+ * @brief Enables the PAL subsystem.
+ */
+#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__)
+#define HAL_USE_PAL TRUE
+#endif
+
+/**
+ * @brief Enables the ADC subsystem.
+ */
+#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__)
+#define HAL_USE_ADC FALSE
+#endif
+
+/**
+ * @brief Enables the CAN subsystem.
+ */
+#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__)
+#define HAL_USE_CAN FALSE
+#endif
+
+/**
+ * @brief Enables the DAC subsystem.
+ */
+#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__)
+#define HAL_USE_DAC FALSE
+#endif
+
+/**
+ * @brief Enables the EXT subsystem.
+ */
+#if !defined(HAL_USE_EXT) || defined(__DOXYGEN__)
+#define HAL_USE_EXT FALSE
+#endif
+
+/**
+ * @brief Enables the GPT subsystem.
+ */
+#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__)
+#define HAL_USE_GPT FALSE
+#endif
+
+/**
+ * @brief Enables the I2C subsystem.
+ */
+#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
+#define HAL_USE_I2C TRUE
+#endif
+
+/**
+ * @brief Enables the I2S subsystem.
+ */
+#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__)
+#define HAL_USE_I2S FALSE
+#endif
+
+/**
+ * @brief Enables the ICU subsystem.
+ */
+#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__)
+#define HAL_USE_ICU FALSE
+#endif
+
+/**
+ * @brief Enables the MAC subsystem.
+ */
+#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__)
+#define HAL_USE_MAC FALSE
+#endif
+
+/**
+ * @brief Enables the MMC_SPI subsystem.
+ */
+#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_MMC_SPI FALSE
+#endif
+
+/**
+ * @brief Enables the PWM subsystem.
+ */
+#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__)
+#define HAL_USE_PWM FALSE
+#endif
+
+/**
+ * @brief Enables the RTC subsystem.
+ */
+#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
+#define HAL_USE_RTC FALSE
+#endif
+
+/**
+ * @brief Enables the SDC subsystem.
+ */
+#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__)
+#define HAL_USE_SDC FALSE
+#endif
+
+/**
+ * @brief Enables the SERIAL subsystem.
+ */
+#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL TRUE
+#endif
+
+/**
+ * @brief Enables the SERIAL over USB subsystem.
+ */
+#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL_USB TRUE
+#endif
+
+/**
+ * @brief Enables the SPI subsystem.
+ */
+#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_SPI TRUE
+#endif
+
+/**
+ * @brief Enables the UART subsystem.
+ */
+#if !defined(HAL_USE_UART) || defined(__DOXYGEN__)
+#define HAL_USE_UART FALSE
+#endif
+
+/**
+ * @brief Enables the USB subsystem.
+ */
+#if !defined(HAL_USE_USB) || defined(__DOXYGEN__)
+#define HAL_USE_USB TRUE
+#endif
+
+/**
+ * @brief Enables the WDG subsystem.
+ */
+#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__)
+#define HAL_USE_WDG FALSE
+#endif
+
+/*===========================================================================*/
+/* ADC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__)
+#define ADC_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define ADC_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* CAN driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Sleep mode related APIs inclusion switch.
+ */
+#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
+#define CAN_USE_SLEEP_MODE TRUE
+#endif
+
+/*===========================================================================*/
+/* I2C driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables the mutual exclusion APIs on the I2C bus.
+ */
+#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define I2C_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* MAC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables an event sources for incoming packets.
+ */
+#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__)
+#define MAC_USE_ZERO_COPY FALSE
+#endif
+
+/**
+ * @brief Enables an event sources for incoming packets.
+ */
+#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__)
+#define MAC_USE_EVENTS TRUE
+#endif
+
+/*===========================================================================*/
+/* MMC_SPI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Delays insertions.
+ * @details If enabled this options inserts delays into the MMC waiting
+ * routines releasing some extra CPU time for the threads with
+ * lower priority, this may slow down the driver a bit however.
+ * This option is recommended also if the SPI driver does not
+ * use a DMA channel and heavily loads the CPU.
+ */
+#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__)
+#define MMC_NICE_WAITING TRUE
+#endif
+
+/*===========================================================================*/
+/* SDC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Number of initialization attempts before rejecting the card.
+ * @note Attempts are performed at 10mS intervals.
+ */
+#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__)
+#define SDC_INIT_RETRY 100
+#endif
+
+/**
+ * @brief Include support for MMC cards.
+ * @note MMC support is not yet implemented so this option must be kept
+ * at @p FALSE.
+ */
+#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__)
+#define SDC_MMC_SUPPORT FALSE
+#endif
+
+/**
+ * @brief Delays insertions.
+ * @details If enabled this options inserts delays into the MMC waiting
+ * routines releasing some extra CPU time for the threads with
+ * lower priority, this may slow down the driver a bit however.
+ */
+#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__)
+#define SDC_NICE_WAITING TRUE
+#endif
+
+/*===========================================================================*/
+/* SERIAL driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Default bit rate.
+ * @details Configuration parameter, this is the baud rate selected for the
+ * default configuration.
+ */
+#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__)
+#define SERIAL_DEFAULT_BITRATE 38400
+#endif
+
+/**
+ * @brief Serial buffers size.
+ * @details Configuration parameter, you can change the depth of the queue
+ * buffers depending on the requirements of your application.
+ * @note The default is 64 bytes for both the transmission and receive
+ * buffers.
+ */
+#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define SERIAL_BUFFERS_SIZE 128
+#endif
+
+/*===========================================================================*/
+/* SERIAL_USB driver related setting. */
+/*===========================================================================*/
+
+/**
+ * @brief Serial over USB buffers size.
+ * @details Configuration parameter, the buffer size must be a multiple of
+ * the USB data endpoint maximum packet size.
+ * @note The default is 64 bytes for both the transmission and receive
+ * buffers.
+ */
+#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define SERIAL_USB_BUFFERS_SIZE 256
+#endif
+
+/*===========================================================================*/
+/* SPI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__)
+#define SPI_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define SPI_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* USB driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__)
+#define USB_USE_WAIT TRUE
+#endif
+
+#endif /* _HALCONF_H_ */
+
+/** @} */
diff --git a/keyboards/infinity_ergodox/infinity_ergodox.c b/keyboards/infinity_ergodox/infinity_ergodox.c
new file mode 100644
index 000000000..34aded1a7
--- /dev/null
+++ b/keyboards/infinity_ergodox/infinity_ergodox.c
@@ -0,0 +1 @@
+#include "infinity_ergodox.h"
diff --git a/keyboards/infinity_ergodox/infinity_ergodox.h b/keyboards/infinity_ergodox/infinity_ergodox.h
new file mode 100644
index 000000000..de7267594
--- /dev/null
+++ b/keyboards/infinity_ergodox/infinity_ergodox.h
@@ -0,0 +1,44 @@
+#ifndef KEYBOARDS_INFINITY_ERGODOX_INFINITY_ERGODOX_H_
+#define KEYBOARDS_INFINITY_ERGODOX_INFINITY_ERGODOX_H_
+
+#include "quantum.h"
+
+#define KEYMAP( \
+ A80, A70, A60, A50, A40, A30, A20, \
+ A81, A71, A61, A51, A41, A31, A21, \
+ A82, A72, A62, A52, A42, A32, \
+ A83, A73, A63, A53, A43, A33, A23, \
+ A84, A74, A64, A54, A44, \
+ A13, A03, \
+ A04, \
+ A34, A24, A14, \
+ B20, B30, B40, B50, B60, B70, B80, \
+ B21, B31, B41, B51, B61, B71, B81, \
+ B32, B42, B52, B62, B72, B82, \
+ B23, B33, B43, B53, B63, B73, B83, \
+ B44, B54, B64, B74, B84, \
+ B03, B13, \
+ B04, \
+ B14, B24, B34 \
+) { \
+ { KC_NO, KC_NO, KC_NO, KC_##A03, KC_##A04 }, \
+ { KC_NO, KC_NO, KC_NO, KC_##A13, KC_##A14 }, \
+ { KC_##A20, KC_##A21, KC_NO, KC_##A23, KC_##A24 }, \
+ { KC_##A30, KC_##A31, KC_##A32, KC_##A33, KC_##A34 }, \
+ { KC_##A40, KC_##A41, KC_##A42, KC_##A43, KC_##A44 }, \
+ { KC_##A50, KC_##A51, KC_##A52, KC_##A53, KC_##A54 }, \
+ { KC_##A60, KC_##A61, KC_##A62, KC_##A63, KC_##A64 }, \
+ { KC_##A70, KC_##A71, KC_##A72, KC_##A73, KC_##A74 }, \
+ { KC_##A80, KC_##A81, KC_##A82, KC_##A83, KC_##A84 }, \
+ { KC_NO, KC_NO, KC_NO, KC_##B03, KC_##B04 }, \
+ { KC_NO, KC_NO, KC_NO, KC_##B13, KC_##B14 }, \
+ { KC_##B20, KC_##B21, KC_NO, KC_##B23, KC_##B24 }, \
+ { KC_##B30, KC_##B31, KC_##B32, KC_##B33, KC_##B34 }, \
+ { KC_##B40, KC_##B41, KC_##B42, KC_##B43, KC_##B44 }, \
+ { KC_##B50, KC_##B51, KC_##B52, KC_##B53, KC_##B54 }, \
+ { KC_##B60, KC_##B61, KC_##B62, KC_##B63, KC_##B64 }, \
+ { KC_##B70, KC_##B71, KC_##B72, KC_##B73, KC_##B74 }, \
+ { KC_##B80, KC_##B81, KC_##B82, KC_##B83, KC_##B84 } \
+}
+
+#endif /* KEYBOARDS_INFINITY_ERGODOX_INFINITY_ERGODOX_H_ */
diff --git a/keyboards/infinity_ergodox/keymaps/default/keymap.c b/keyboards/infinity_ergodox/keymaps/default/keymap.c
new file mode 100644
index 000000000..c33fb7b92
--- /dev/null
+++ b/keyboards/infinity_ergodox/keymaps/default/keymap.c
@@ -0,0 +1,111 @@
+/*
+Copyright 2016 Fred Sundvik <fsundvik@gmail.com>
+Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "infinity_ergodox.h"
+
+const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ KEYMAP( // layer 0 : default
+ // left hand
+ EQL, 1, 2, 3, 4, 5, ESC,
+ BSLS,Q, W, E, R, T, FN1,
+ TAB, A, S, D, F, G,
+ LSFT,Z, X, C, V, B, FN0,
+ LGUI,GRV, BSLS,LEFT,RGHT,
+ LCTL,LALT,
+ HOME,
+ BSPC,DEL, END,
+ // right hand
+ FN2, 6, 7, 8, 9, 0, MINS,
+ LBRC,Y, U, I, O, P, RBRC,
+ H, J, K, L, SCLN,QUOT,
+ FN0, N, M, COMM,DOT, SLSH,RSFT,
+ LEFT,DOWN,UP, RGHT,RGUI,
+ RALT,RCTL,
+ PGUP,
+ PGDN,ENT, SPC
+ ),
+
+ KEYMAP( // layer 1 : function and symbol keys
+ // left hand
+ TRNS,F1, F2, F3, F4, F5, F11,
+ TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,FN3,
+ TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+ TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+ TRNS,TRNS,TRNS,TRNS,TRNS,
+ TRNS,TRNS,
+ TRNS,
+ TRNS,TRNS,TRNS,
+ // right hand
+ F12, F6, F7, F8, F9, F10, TRNS,
+ TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+ TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+ TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+ TRNS,TRNS,TRNS,TRNS,TRNS,
+ TRNS,TRNS,
+ TRNS,
+ TRNS,TRNS,TRNS
+ ),
+
+ KEYMAP( // layer 2 : keyboard functions
+ // left hand
+ BTLD,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+ TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, FN3,
+ TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+ TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+ TRNS,TRNS,TRNS,TRNS,TRNS,
+ TRNS,TRNS,
+ TRNS,
+ TRNS,TRNS,TRNS,
+ // right hand
+ TRNS, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+ TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+ TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+ TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+ TRNS,TRNS,TRNS,TRNS,TRNS,
+ TRNS,TRNS,
+ TRNS,
+ TRNS,TRNS,TRNS
+ ),
+
+ KEYMAP( // layer 3: numpad
+ // left hand
+ TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+ TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+ TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+ TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,
+ TRNS,TRNS,TRNS,TRNS,TRNS,
+ TRNS,TRNS,
+ TRNS,
+ TRNS,TRNS,TRNS,
+ // right hand
+ TRNS,NLCK,PSLS,PAST,PAST,PMNS,BSPC,
+ TRNS,NO, P7, P8, P9, PMNS,BSPC,
+ NO, P4, P5, P6, PPLS,PENT,
+ TRNS,NO, P1, P2, P3, PPLS,PENT,
+ P0, PDOT,SLSH,PENT,PENT,
+ TRNS,TRNS,
+ TRNS,
+ TRNS,TRNS,TRNS
+ ),
+};
+const uint16_t fn_actions[] = {
+ ACTION_LAYER_MOMENTARY(1), // FN0 - switch to Layer1
+ ACTION_LAYER_SET(2, ON_PRESS), // FN1 - set Layer2
+ ACTION_LAYER_TOGGLE(3), // FN2 - toggle Layer3 aka Numpad layer
+ ACTION_LAYER_SET(0, ON_PRESS), // FN3 - set Layer0
+};
diff --git a/keyboards/infinity_ergodox/led.c b/keyboards/infinity_ergodox/led.c
new file mode 100644
index 000000000..77195bb35
--- /dev/null
+++ b/keyboards/infinity_ergodox/led.c
@@ -0,0 +1,49 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "hal.h"
+
+#include "led.h"
+
+
+void led_set(uint8_t usb_led) {
+// The LCD backlight functionality conflicts with this simple
+// red backlight
+#if !defined(LCD_BACKLIGHT_ENABLE) && defined(STATUS_LED_ENABLE)
+ // PTC1: LCD Backlight Red(0:on/1:off)
+ GPIOC->PDDR |= (1<<1);
+ PORTC->PCR[1] |= PORTx_PCRn_DSE | PORTx_PCRn_MUX(1);
+ if (usb_led & (1<<USB_LED_CAPS_LOCK)) {
+ GPIOC->PCOR |= (1<<1);
+ } else {
+ GPIOC->PSOR |= (1<<1);
+ }
+#elif !defined(LCD_BACKLIGHT_ENABLE)
+ (void)usb_led;
+ GPIOC->PDDR |= (1<<1);
+ PORTC->PCR[1] |= PORTx_PCRn_DSE | PORTx_PCRn_MUX(1);
+ GPIOC->PSOR |= (1<<1);
+ GPIOC->PDDR |= (1<<2);
+ PORTC->PCR[2] |= PORTx_PCRn_DSE | PORTx_PCRn_MUX(1);
+ GPIOC->PSOR |= (1<<2);
+ GPIOC->PDDR |= (1<<3);
+ PORTC->PCR[3] |= PORTx_PCRn_DSE | PORTx_PCRn_MUX(1);
+ GPIOC->PSOR |= (1<<3);
+#else
+ (void)usb_led;
+#endif
+}
diff --git a/keyboards/infinity_ergodox/matrix.c b/keyboards/infinity_ergodox/matrix.c
new file mode 100644
index 000000000..2b806cd64
--- /dev/null
+++ b/keyboards/infinity_ergodox/matrix.c
@@ -0,0 +1,169 @@
+/*
+Copyright 2016 Fred Sundvik <fsundvik@gmail.com>
+Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include "hal.h"
+#include "timer.h"
+#include "wait.h"
+#include "print.h"
+#include "debug.h"
+#include "matrix.h"
+
+
+/*
+ * Infinity ErgoDox Pinusage:
+ * Column pins are input with internal pull-down. Row pins are output and strobe with high.
+ * Key is high or 1 when it turns on.
+ *
+ * col: { PTD1, PTD4, PTD5, PTD6, PTD7 }
+ * row: { PTB2, PTB3, PTB18, PTB19, PTC0, PTC9, PTC10, PTC11, PTD0 }
+ */
+/* matrix state(1:on, 0:off) */
+static matrix_row_t matrix[MATRIX_ROWS];
+static matrix_row_t matrix_debouncing[LOCAL_MATRIX_ROWS];
+static bool debouncing = false;
+static uint16_t debouncing_time = 0;
+
+
+void matrix_init(void)
+{
+ /* Column(sense) */
+ palSetPadMode(GPIOD, 1, PAL_MODE_INPUT_PULLDOWN);
+ palSetPadMode(GPIOD, 4, PAL_MODE_INPUT_PULLDOWN);
+ palSetPadMode(GPIOD, 5, PAL_MODE_INPUT_PULLDOWN);
+ palSetPadMode(GPIOD, 6, PAL_MODE_INPUT_PULLDOWN);
+ palSetPadMode(GPIOD, 7, PAL_MODE_INPUT_PULLDOWN);
+
+ /* Row(strobe) */
+ palSetPadMode(GPIOB, 2, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOB, 3, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOB, 18, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOB, 19, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOC, 0, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOC, 9, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOC, 10, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOC, 11, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOD, 0, PAL_MODE_OUTPUT_PUSHPULL);
+
+ memset(matrix, 0, MATRIX_ROWS);
+ memset(matrix_debouncing, 0, LOCAL_MATRIX_ROWS);
+}
+
+uint8_t matrix_scan(void)
+{
+ for (int row = 0; row < LOCAL_MATRIX_ROWS; row++) {
+ matrix_row_t data = 0;
+
+ // strobe row
+ switch (row) {
+ case 0: palSetPad(GPIOB, 2); break;
+ case 1: palSetPad(GPIOB, 3); break;
+ case 2: palSetPad(GPIOB, 18); break;
+ case 3: palSetPad(GPIOB, 19); break;
+ case 4: palSetPad(GPIOC, 0); break;
+ case 5: palSetPad(GPIOC, 9); break;
+ case 6: palSetPad(GPIOC, 10); break;
+ case 7: palSetPad(GPIOC, 11); break;
+ case 8: palSetPad(GPIOD, 0); break;
+ }
+
+ // need wait to settle pin state
+ // if you wait too short, or have a too high update rate
+ // the keyboard might freeze, or there might not be enough
+ // processing power to update the LCD screen properly.
+ // 20us, or two ticks at 100000Hz seems to be OK
+ wait_us(20);
+
+ // read col data: { PTD1, PTD4, PTD5, PTD6, PTD7 }
+ data = ((palReadPort(GPIOD) & 0xF0) >> 3) |
+ ((palReadPort(GPIOD) & 0x02) >> 1);
+
+ // un-strobe row
+ switch (row) {
+ case 0: palClearPad(GPIOB, 2); break;
+ case 1: palClearPad(GPIOB, 3); break;
+ case 2: palClearPad(GPIOB, 18); break;
+ case 3: palClearPad(GPIOB, 19); break;
+ case 4: palClearPad(GPIOC, 0); break;
+ case 5: palClearPad(GPIOC, 9); break;
+ case 6: palClearPad(GPIOC, 10); break;
+ case 7: palClearPad(GPIOC, 11); break;
+ case 8: palClearPad(GPIOD, 0); break;
+ }
+
+ if (matrix_debouncing[row] != data) {
+ matrix_debouncing[row] = data;
+ debouncing = true;
+ debouncing_time = timer_read();
+ }
+ }
+
+ uint8_t offset = 0;
+#ifdef MASTER_IS_ON_RIGHT
+ if (is_serial_link_master()) {
+ offset = MATRIX_ROWS - LOCAL_MATRIX_ROWS;
+ }
+#endif
+
+ if (debouncing && timer_elapsed(debouncing_time) > DEBOUNCE) {
+ for (int row = 0; row < LOCAL_MATRIX_ROWS; row++) {
+ matrix[offset + row] = matrix_debouncing[row];
+ }
+ debouncing = false;
+ }
+ return 1;
+}
+
+bool matrix_is_on(uint8_t row, uint8_t col)
+{
+ return (matrix[row] & (1<<col));
+}
+
+matrix_row_t matrix_get_row(uint8_t row)
+{
+ return matrix[row];
+}
+
+void matrix_print(void)
+{
+ xprintf("\nr/c 01234567\n");
+ for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
+ xprintf("%X0: ", row);
+ matrix_row_t data = matrix_get_row(row);
+ for (int col = 0; col < MATRIX_COLS; col++) {
+ if (data & (1<<col))
+ xprintf("1");
+ else
+ xprintf("0");
+ }
+ xprintf("\n");
+ }
+}
+
+void matrix_set_remote(matrix_row_t* rows, uint8_t index) {
+ uint8_t offset = 0;
+#ifdef MASTER_IS_ON_RIGHT
+ offset = MATRIX_ROWS - LOCAL_MATRIX_ROWS * (index + 2);
+#else
+ offset = LOCAL_MATRIX_ROWS * (index + 1);
+#endif
+ for (int row = 0; row < LOCAL_MATRIX_ROWS; row++) {
+ matrix[offset + row] = rows[row];
+ }
+}
diff --git a/keyboards/infinity_ergodox/mcuconf.h b/keyboards/infinity_ergodox/mcuconf.h
new file mode 100644
index 000000000..f6730b99c
--- /dev/null
+++ b/keyboards/infinity_ergodox/mcuconf.h
@@ -0,0 +1,74 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#ifndef _MCUCONF_H_
+#define _MCUCONF_H_
+
+#define K20x_MCUCONF
+
+/*
+ * HAL driver system settings.
+ */
+
+#define K20x7
+
+/* Select the MCU clocking mode below by enabling the appropriate block. */
+
+#define KINETIS_NO_INIT FALSE
+
+/* PEE mode - 48MHz system clock driven by external crystal. */
+#define KINETIS_MCG_MODE KINETIS_MCG_MODE_PEE
+#define KINETIS_PLLCLK_FREQUENCY 72000000UL
+#define KINETIS_SYSCLK_FREQUENCY 72000000UL
+#define KINETIS_BUSCLK_FREQUENCY 36000000UL
+#define KINETIS_FLASHCLK_FREQUENCY 24000000UL
+
+#if 0
+/* FEI mode - 48 MHz with internal 32.768 kHz crystal */
+#define KINETIS_MCG_MODE KINETIS_MCG_MODE_FEI
+#define KINETIS_MCG_FLL_DMX32 1 /* Fine-tune for 32.768 kHz */
+#define KINETIS_MCG_FLL_DRS 1 /* 1464x FLL factor */
+#define KINETIS_SYSCLK_FREQUENCY 47972352UL /* 32.768 kHz * 1464 (~48 MHz) */
+#define KINETIS_CLKDIV1_OUTDIV1 1
+#define KINETIS_CLKDIV1_OUTDIV2 1
+#define KINETIS_CLKDIV1_OUTDIV4 2
+#define KINETIS_BUSCLK_FREQUENCY KINETIS_SYSCLK_FREQUENCY
+#define KINETIS_FLASHCLK_FREQUENCY KINETIS_SYSCLK_FREQUENCY/2
+#endif
+
+/*
+ * SERIAL driver system settings.
+ */
+#define KINETIS_SERIAL_USE_UART0 TRUE
+#define KINETIS_SERIAL_USE_UART1 TRUE
+
+/*
+ * USB driver settings
+ */
+#define KINETIS_USB_USE_USB0 TRUE
+/* Need to redefine this, since the default is for K20x */
+/* This is for Teensy LC; you should comment it out (or change to 5)
+ * for Teensy 3.x */
+#define KINETIS_USB_USB0_IRQ_PRIORITY 2
+
+/*
+ * SPI driver system settings.
+ */
+#define KINETIS_SPI_USE_SPI0 TRUE
+
+#define KINETIS_I2C_USE_I2C0 TRUE
+
+#endif /* _MCUCONF_H_ */
diff --git a/keyboards/jd45/Makefile b/keyboards/jd45/Makefile
new file mode 100644
index 000000000..75d544f16
--- /dev/null
+++ b/keyboards/jd45/Makefile
@@ -0,0 +1,71 @@
+
+
+# MCU name
+#MCU = at90usb1287
+MCU = atmega32u4
+
+# Processor frequency.
+# This will define a symbol, F_CPU, in all source code files equal to the
+# processor frequency in Hz. You can then use this symbol in your source code to
+# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
+# automatically to create a 32-bit value in your source code.
+#
+# This will be an integer division of F_USB below, as it is sourced by
+# F_USB after it has run through any CPU prescalers. Note that this value
+# does not *change* the processor frequency - it should merely be updated to
+# reflect the processor speed set externally so that the code can use accurate
+# software delays.
+F_CPU = 16000000
+
+
+#
+# LUFA specific
+#
+# Target architecture (see library "Board Types" documentation).
+ARCH = AVR8
+
+# Input clock frequency.
+# This will define a symbol, F_USB, in all source code files equal to the
+# input clock frequency (before any prescaling is performed) in Hz. This value may
+# differ from F_CPU if prescaling is used on the latter, and is required as the
+# raw input clock is fed directly to the PLL sections of the AVR for high speed
+# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
+# at the end, this will be done automatically to create a 32-bit value in your
+# source code.
+#
+# If no clock division is performed on the input clock inside the AVR (via the
+# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
+F_USB = $(F_CPU)
+
+# Interrupt driven control endpoint task(+60)
+OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
+
+
+# Boot Section Size in *bytes*
+# Teensy halfKay 512
+# Teensy++ halfKay 1024
+# Atmel DFU loader 4096
+# LUFA bootloader 4096
+# USBaspLoader 2048
+OPT_DEFS += -DBOOTLOADER_SIZE=4096
+
+
+# Build Options
+# comment out to disable the options.
+#
+BOOTMAGIC_ENABLE ?= yes # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE ?= yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450)
+CONSOLE_ENABLE ?= yes # Console for debug(+400)
+COMMAND_ENABLE ?= yes # Commands for debug and configuration
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+# SLEEP_LED_ENABLE ?= yes # Breathing sleep LED during USB suspend
+# NKRO_ENABLE ?= yes # USB Nkey Rollover - not yet supported in LUFA
+BACKLIGHT_ENABLE ?= yes # Enable keyboard backlight functionality
+MIDI_ENABLE ?= YES # MIDI controls
+# UNICODE_ENABLE ?= YES # Unicode
+BLUETOOTH_ENABLE ?= yes # Enable Bluetooth with the Adafruit EZ-Key HID
+
+ifndef QUANTUM_DIR
+ include ../../Makefile
+endif
diff --git a/keyboards/jd45/config.h b/keyboards/jd45/config.h
new file mode 100644
index 000000000..ee989b7b4
--- /dev/null
+++ b/keyboards/jd45/config.h
@@ -0,0 +1,82 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "config_common.h"
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x6060
+#define DEVICE_VER 0x0001
+#define MANUFACTURER geekhack
+#define PRODUCT JD45
+#define DESCRIPTION q.m.k. keyboard firmware for JD45
+
+/* key matrix size */
+#define MATRIX_ROWS 4
+#define MATRIX_COLS 13
+
+/* Planck PCB default pin-out */
+#define MATRIX_ROW_PINS { F0, F1, F5, B4 }
+#define MATRIX_COL_PINS { F4, D7, B5, B6, C6, C7, D4, D6, D5, D0, D1, D2, B0 }
+#define UNUSED_PINS
+
+#define BACKLIGHT_PIN B7
+
+/* COL2ROW or ROW2COL */
+#define DIODE_DIRECTION COL2ROW
+
+/* define if matrix has ghost */
+//#define MATRIX_HAS_GHOST
+
+/* number of backlight levels */
+#define BACKLIGHT_LEVELS 3
+
+/* Set 0 if debouncing isn't needed */
+#define DEBOUNCING_DELAY 5
+
+/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
+#define LOCKING_SUPPORT_ENABLE
+/* Locking resynchronize hack */
+#define LOCKING_RESYNC_ENABLE
+
+/* key combination for command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+/*
+ * Feature disable options
+ * These options are also useful to firmware size reduction.
+ */
+
+/* disable debug print */
+#define NO_DEBUG
+
+/* disable print */
+#define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+
+#endif
diff --git a/keyboards/jd45/jd45.c b/keyboards/jd45/jd45.c
new file mode 100644
index 000000000..00c581047
--- /dev/null
+++ b/keyboards/jd45/jd45.c
@@ -0,0 +1 @@
+#include "jd45.h" \ No newline at end of file
diff --git a/keyboards/jd45/jd45.h b/keyboards/jd45/jd45.h
new file mode 100644
index 000000000..04ac6649e
--- /dev/null
+++ b/keyboards/jd45/jd45.h
@@ -0,0 +1,20 @@
+#ifndef JD45_H
+#define JD45_H
+
+#include "quantum.h"
+
+/* JD45 keymap definition macro
+ */
+#define KEYMAP( \
+ K01, K02, K03, K04, K05, K06, K07, K08, K09, K10, K11, K12, K13, \
+ K14, K15, K16, K17, K18, K19, K20, K21, K22, K23, K24, K25, \
+ K26, K27, K28, K29, K30, K31, K32, K33, K34, K35, K36, K37, \
+ K38, K39, K40, K41, K42, K43, K44, K45, K46, K47 \
+) { \
+ { KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07, KC_##K08, KC_##K09, KC_##K10, KC_##K11, KC_##K12, KC_##K13 }, \
+ { KC_##K14, KC_##K15, KC_##K16, KC_##K17, KC_##K18, KC_##K19, KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_NO }, \
+ { KC_##K26, KC_##K27, KC_##K28, KC_##K29, KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36, KC_##K37, KC_NO }, \
+ { KC_##K38, KC_##K39, KC_##K40, KC_##K41, KC_##K42, KC_NO, KC_##K43, KC_NO, KC_##K44, KC_##K45, KC_##K46, KC_##K47, KC_NO } \
+}
+
+#endif
diff --git a/keyboards/jd45/keymaps/default/keymap.c b/keyboards/jd45/keymaps/default/keymap.c
new file mode 100644
index 000000000..95abb1505
--- /dev/null
+++ b/keyboards/jd45/keymaps/default/keymap.c
@@ -0,0 +1,17 @@
+#include "jd45.h"
+
+/* this keymap is to provide a basic keyboard layout for testing the matrix
+ * for more practical and complicated keymap refer to other keymaps in the same folder
+ */
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[0] = KEYMAP(
+ ESC, Q, W, E, R, T, Y, U, I, O, P, QUOT, BSPC,
+ TAB, A, S, D, F, G, H, J, K, L, SCLN, ENT,
+ LSFT, Z, X, C, V, B, N, M, COMM, DOT, SLSH, RSFT,
+ PAUSE, LCTL, LALT, DEL, SPC, DEL, LEFT, UP, DOWN, RIGHT ),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+
+};
diff --git a/keyboards/jd45/keymaps/justin/keymap.c b/keyboards/jd45/keymaps/justin/keymap.c
new file mode 100644
index 000000000..c278abba5
--- /dev/null
+++ b/keyboards/jd45/keymaps/justin/keymap.c
@@ -0,0 +1,86 @@
+#include "jd45.h"
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[0] = KEYMAP(
+ ESC, Q, W, F, P, G, J, L, U, Y, SCLN, QUOT, BSPC,
+ FN8, A, R, S, T, D, H, N, E, I, O, ENT,
+ LSFT, Z, X, C, V, B, K, M, COMM, DOT, SLSH, FN6,
+ FN4, LGUI, FN7, FN2, FN1, SPC, FN5, RALT, FN3, FN0 ),
+[1] = KEYMAP(
+ TRNS, FN10, FN11, FN12, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, UP, DEL,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, HOME, PGUP, LEFT, RGHT,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, END, PGDN, DOWN, TRNS,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS ),
+[2] = KEYMAP(
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, 7, 8, 9, 0, TRNS, TRNS,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, LBRC, 4, 5, 6, DOT, TRNS,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, RBRC, 1, 2, 3, BSLS, TRNS,
+ TRNS,FN29, TRNS, TRNS, TRNS, PAUSE, EQL, MINS, TRNS, TRNS ),
+[3] = KEYMAP(
+ TRNS, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS ),
+[4] = KEYMAP(
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, 7, 8, 9, 0, TRNS, TRNS,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, LBRC, 4, 5, 6, DOT, TRNS,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, RBRC, 1, 2, 3, BSLS, TRNS,
+ TRNS,FN29, TRNS, TRNS, TRNS, PAUSE, EQL, MINS, TRNS, TRNS ),
+};
+
+enum macro_id {
+ PSWD1,
+ PSWD2,
+ PSWD3,
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [0] = ACTION_MODS_TAP_KEY(MOD_LCTL, KC_MINS),
+ [1] = ACTION_LAYER_MOMENTARY(1), // FN1
+ [2] = ACTION_LAYER_MOMENTARY(2), // FN2
+ [3] = ACTION_LAYER_MOMENTARY(3), // FN3
+ [4] = ACTION_MODS_TAP_KEY(MOD_LSFT, KC_GRV),
+ [5] = ACTION_MODS_TAP_KEY(MOD_RSFT, KC_RGUI),
+ [6] = ACTION_MODS_TAP_KEY(MOD_RSFT, KC_CAPS),
+ [7] = ACTION_LAYER_MODS(4, MOD_LSFT), // FN4
+ [8] = ACTION_MODS_TAP_KEY(MOD_LCTL, KC_TAB),
+
+ [10] = ACTION_MACRO(PSWD1),
+ [11] = ACTION_MACRO(PSWD2),
+ [12] = ACTION_MACRO(PSWD3),
+
+ [29] = ACTION_BACKLIGHT_TOGGLE(),
+ [30] = ACTION_BACKLIGHT_INCREASE(),
+ [31] = ACTION_BACKLIGHT_DECREASE()
+
+};
+
+/*
+ * Macro definition
+ */
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ switch (id) {
+ case PSWD1:
+ return (record->event.pressed ?
+ MACRO( I(0), T(1), T(2), T(3), T(4), T(5), T(6), T(7), T(8), T(ENT), END ) :
+ MACRO_NONE );
+ case PSWD2:
+ return (record->event.pressed ?
+ MACRO( I(0), T(1), T(2), T(3), T(4), T(5), T(6), T(7), T(8), T(ENT), END ) :
+ MACRO_NONE );
+ case PSWD3:
+ return (record->event.pressed ?
+ MACRO( I(0), T(1), T(2), T(3), T(4), T(5), T(6), T(7), T(8), T(ENT), END ) :
+ MACRO_NONE );
+ //case VOLUP:
+ // return (record->event.pressed ?
+ // MACRO( D(VOLU), U(VOLU), END ) :
+ // MACRO_NONE );
+ //case ALT_TAB:
+ // return (record->event.pressed ?
+ // MACRO( D(LALT), D(TAB), END ) :
+ // MACRO( U(TAB), END ));
+ }
+ return MACRO_NONE;
+}
diff --git a/keyboards/kc60/Makefile b/keyboards/kc60/Makefile
new file mode 100644
index 000000000..9717b519c
--- /dev/null
+++ b/keyboards/kc60/Makefile
@@ -0,0 +1,76 @@
+
+
+# MCU name
+#MCU = at90usb1287
+MCU = atmega32u4
+
+# Processor frequency.
+# This will define a symbol, F_CPU, in all source code files equal to the
+# processor frequency in Hz. You can then use this symbol in your source code to
+# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
+# automatically to create a 32-bit value in your source code.
+#
+# This will be an integer division of F_USB below, as it is sourced by
+# F_USB after it has run through any CPU prescalers. Note that this value
+# does not *change* the processor frequency - it should merely be updated to
+# reflect the processor speed set externally so that the code can use accurate
+# software delays.
+F_CPU = 16000000
+
+
+#
+# LUFA specific
+#
+# Target architecture (see library "Board Types" documentation).
+ARCH = AVR8
+
+# Input clock frequency.
+# This will define a symbol, F_USB, in all source code files equal to the
+# input clock frequency (before any prescaling is performed) in Hz. This value may
+# differ from F_CPU if prescaling is used on the latter, and is required as the
+# raw input clock is fed directly to the PLL sections of the AVR for high speed
+# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
+# at the end, this will be done automatically to create a 32-bit value in your
+# source code.
+#
+# If no clock division is performed on the input clock inside the AVR (via the
+# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
+F_USB = $(F_CPU)
+
+# Interrupt driven control endpoint task(+60)
+OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
+
+
+# Boot Section Size in *bytes*
+# Teensy halfKay 512
+# Teensy++ halfKay 1024
+# Atmel DFU loader 4096
+# LUFA bootloader 4096
+# USBaspLoader 2048
+OPT_DEFS += -DBOOTLOADER_SIZE=4096
+
+
+# Build Options
+# change yes to no to disable
+#
+BOOTMAGIC_ENABLE ?= yes # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE ?= yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450)
+CONSOLE_ENABLE ?= yes # Console for debug(+400)
+COMMAND_ENABLE ?= yes # Commands for debug and configuration
+KEYBOARD_LOCK_ENABLE ?= yes # Allow locking of keyboard via magic key
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE ?= no # Breathing sleep LED during USB suspend
+# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+NKRO_ENABLE ?= no # USB Nkey Rollover
+BACKLIGHT_ENABLE ?= yes # Enable keyboard backlight functionality
+MIDI_ENABLE ?= no # MIDI controls
+UNICODE_ENABLE ?= no # Unicode
+BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID
+AUDIO_ENABLE ?= no # Audio output on port C6
+
+
+ifndef QUANTUM_DIR
+ include ../../Makefile
+endif
+
diff --git a/keyboards/kc60/config.h b/keyboards/kc60/config.h
new file mode 100644
index 000000000..c4a9b9ff8
--- /dev/null
+++ b/keyboards/kc60/config.h
@@ -0,0 +1,164 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "config_common.h"
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x6060
+#define DEVICE_VER 0x0001
+#define MANUFACTURER You
+#define PRODUCT kc60v2
+#define DESCRIPTION A custom keyboard
+
+/* key matrix size */
+#define MATRIX_ROWS 5
+#define MATRIX_COLS 14
+
+/*
+ * Keyboard Matrix Assignments
+ *
+ * Change this to how you wired your keyboard
+ * COLS: AVR pins used for columns, left to right
+ * ROWS: AVR pins used for rows, top to bottom
+ * DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode)
+ * ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode)
+ *
+*/
+
+// Possible pins for columns include: F1 F0 E6 D7 D6 D4 C7 C6 B7 B5 B4 B3 B1 B0
+// Pins for rows include: D0 D1 F6 F7 D5
+// KC60 Version 2
+#define MATRIX_ROW_PINS { D0, D1, F6, F7, D5 }
+#define MATRIX_COL_PINS { F0, F1, E6, C7, C6, B7, D4, B1, B0, B5, B4, D7, D6, B3 }
+#define UNUSED_PINS
+
+#define BACKLIGHT_PIN B6
+
+/* COL2ROW or ROW2COL */
+#define DIODE_DIRECTION COL2ROW
+
+/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
+#define DEBOUNCING_DELAY 5
+
+/* define if matrix has ghost (lacks anti-ghosting diodes) */
+//#define MATRIX_HAS_GHOST
+
+/* number of backlight levels */
+#define BACKLIGHT_LEVELS 3
+
+/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
+#define LOCKING_SUPPORT_ENABLE
+/* Locking resynchronize hack */
+#define LOCKING_RESYNC_ENABLE
+
+/*
+ * Force NKRO
+ *
+ * Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved
+ * state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the
+ * makefile for this to work.)
+ *
+ * If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N)
+ * until the next keyboard reset.
+ *
+ * NKRO may prevent your keystrokes from being detected in the BIOS, but it is
+ * fully operational during normal computer usage.
+ *
+ * For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N)
+ * or via bootmagic (hold SPACE+N while plugging in the keyboard). Once set by
+ * bootmagic, NKRO mode will always be enabled until it is toggled again during a
+ * power-up.
+ *
+ */
+//#define FORCE_NKRO
+
+/*
+ * Magic Key Options
+ *
+ * Magic keys are hotkey commands that allow control over firmware functions of
+ * the keyboard. They are best used in combination with the HID Listen program,
+ * found here: https://www.pjrc.com/teensy/hid_listen.html
+ *
+ * The options below allow the magic key functionality to be changed. This is
+ * useful if your keyboard/keypad is missing keys and you want magic key support.
+ *
+ */
+
+/* key combination for magic key command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+/* control how magic key switches layers */
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS true
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS true
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM false
+
+/* override magic key keymap */
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM
+//#define MAGIC_KEY_HELP1 H
+//#define MAGIC_KEY_HELP2 SLASH
+//#define MAGIC_KEY_DEBUG D
+//#define MAGIC_KEY_DEBUG_MATRIX X
+//#define MAGIC_KEY_DEBUG_KBD K
+//#define MAGIC_KEY_DEBUG_MOUSE M
+//#define MAGIC_KEY_VERSION V
+//#define MAGIC_KEY_STATUS S
+//#define MAGIC_KEY_CONSOLE C
+//#define MAGIC_KEY_LAYER0_ALT1 ESC
+//#define MAGIC_KEY_LAYER0_ALT2 GRAVE
+//#define MAGIC_KEY_LAYER0 0
+//#define MAGIC_KEY_LAYER1 1
+//#define MAGIC_KEY_LAYER2 2
+//#define MAGIC_KEY_LAYER3 3
+//#define MAGIC_KEY_LAYER4 4
+//#define MAGIC_KEY_LAYER5 5
+//#define MAGIC_KEY_LAYER6 6
+//#define MAGIC_KEY_LAYER7 7
+//#define MAGIC_KEY_LAYER8 8
+//#define MAGIC_KEY_LAYER9 9
+//#define MAGIC_KEY_BOOTLOADER PAUSE
+//#define MAGIC_KEY_LOCK CAPS
+//#define MAGIC_KEY_EEPROM E
+//#define MAGIC_KEY_NKRO N
+//#define MAGIC_KEY_SLEEP_LED Z
+
+/*
+ * Feature disable options
+ * These options are also useful to firmware size reduction.
+ */
+
+/* disable debug print */
+//#define NO_DEBUG
+
+/* disable print */
+//#define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+
+#endif
diff --git a/keyboards/kc60/kc60.c b/keyboards/kc60/kc60.c
new file mode 100644
index 000000000..746ac634a
--- /dev/null
+++ b/keyboards/kc60/kc60.c
@@ -0,0 +1 @@
+#include "kc60.h"
diff --git a/keyboards/kc60/kc60.h b/keyboards/kc60/kc60.h
new file mode 100644
index 000000000..34eab4b2a
--- /dev/null
+++ b/keyboards/kc60/kc60.h
@@ -0,0 +1,23 @@
+#ifndef KC60_H
+#define KC60_H
+
+#include "quantum.h"
+
+// This a shortcut to help you visually see your layout.
+// The first section contains all of the arguements
+// The second converts the arguments into a multi-dimensional array
+#define KEYMAP( \
+ K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, \
+ K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, \
+ K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, K2C, K2D, \
+ K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3C, K3D, \
+ K40, K41, K42, K45, K4A, K4B, K4C, K4D \
+ ) { \
+ { K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D }, \
+ { K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D }, \
+ { K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, K2C, K2D }, \
+ { K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3C, K3D }, \
+ { K40, K41, K42, KC_NO, KC_NO, K45, KC_NO, KC_NO, KC_NO, KC_NO,K4A, K4B, K4C, K4D } \
+}
+
+#endif
diff --git a/keyboards/kc60/keymaps/default/keymap.c b/keyboards/kc60/keymaps/default/keymap.c
new file mode 100644
index 000000000..6f8352c69
--- /dev/null
+++ b/keyboards/kc60/keymaps/default/keymap.c
@@ -0,0 +1,24 @@
+// This is the canonical layout file for the Quantum project. If you want to add another keyboard,
+// this is the style you want to emulate.
+
+#include "kc60.h"
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ [0] = KEYMAP( /* Basic QWERTY */
+ KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, \
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, \
+ KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_NO, KC_ENT, \
+ KC_LSFT, KC_NO, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_NO, KC_RSFT, \
+ KC_LCTL, KC_LALT, KC_LGUI, KC_SPC, KC_RGUI, KC_RALT, KC_RCTL, RESET \
+ ),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ return MACRO_NONE;
+};
diff --git a/keyboards/kc60/keymaps/sgoodwin/keymap.c b/keyboards/kc60/keymaps/sgoodwin/keymap.c
new file mode 100644
index 000000000..99e95c232
--- /dev/null
+++ b/keyboards/kc60/keymaps/sgoodwin/keymap.c
@@ -0,0 +1,42 @@
+// This is the canonical layout file for the Quantum project. If you want to add another keyboard,
+// this is the style you want to emulate.
+
+#include "kc60.h"
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ /*
+ * Toggles between colemak and qwerty by tapping the bottom right key.
+ * Holding capslock key gives a layer like the KBParadise v60.
+ */
+ [0] = KEYMAP( /* Basic Colemak */
+ KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, \
+ KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_LBRC, KC_RBRC, KC_BSLS, \
+ MO(2), KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT, KC_NO, KC_ENT, \
+ KC_LSFT, KC_NO, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_K, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_NO, KC_RSFT, \
+ KC_LCTL, KC_LALT, KC_LGUI, KC_SPC, KC_RGUI, KC_RALT, KC_RCTL, DF(1) \
+ ),
+ [1] = KEYMAP( /* Basic QWERTY */
+ KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, \
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, \
+ MO(2), KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_NO, KC_ENT, \
+ KC_LSFT, KC_NO, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_NO, KC_RSFT, \
+ KC_LCTL, KC_LALT, KC_LGUI, KC_SPC, KC_RGUI, KC_RALT, KC_RCTL, DF(0) \
+ ),
+ [2] = KEYMAP( /* KBP v60-like arrows, media keys, etc */
+ KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL, \
+ KC_TRNS, KC_TRNS, KC_UP, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_UP, BL_INC, BL_DEC, BL_STEP, \
+ KC_TRNS, KC_LEFT, KC_DOWN, KC_RIGHT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_LEFT, KC_DOWN, KC_RIGHT, KC_NO, KC_TRNS, \
+ KC_TRNS, KC_NO, KC_MPRV, KC_MPLY, KC_MNXT, KC_VOLD, KC_VOLU, KC_MUTE, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_NO, KC_TRNS, \
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_SPC, DEBUG, RESET, KC_TRNS, KC_NO \
+ ),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ return MACRO_NONE;
+};
diff --git a/keyboards/kc60/keymaps/stanleylai/Makefile b/keyboards/kc60/keymaps/stanleylai/Makefile
new file mode 100644
index 000000000..b8b2beda4
--- /dev/null
+++ b/keyboards/kc60/keymaps/stanleylai/Makefile
@@ -0,0 +1,25 @@
+
+
+# Build Options
+# change yes to no to disable
+#
+BOOTMAGIC_ENABLE ?= yes # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE ?= no # Mouse keys(+4700)
+EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450)
+CONSOLE_ENABLE ?= no # Console for debug(+400)
+COMMAND_ENABLE ?= no # Commands for debug and configuration
+KEYBOARD_LOCK_ENABLE ?= yes # Allow locking of keyboard via magic key
+BACKLIGHT_ENABLE ?= yes # Enable keyboard backlight functionality
+RGBLIGHT_ENABLE ?= yes # Enable WS2812 underglow RGB strip
+MIDI_ENABLE ?= no # MIDI controls
+UNICODE_ENABLE ?= no # Unicode
+BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID
+AUDIO_ENABLE ?= no # Audio output on port C6
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE ?= no # Breathing sleep LED during USB suspend
+# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+NKRO_ENABLE ?= yes # USB Nkey Rollover
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif
diff --git a/keyboards/kc60/keymaps/stanleylai/base_layer.png b/keyboards/kc60/keymaps/stanleylai/base_layer.png
new file mode 100644
index 000000000..97235c6af
--- /dev/null
+++ b/keyboards/kc60/keymaps/stanleylai/base_layer.png
Binary files differ
diff --git a/keyboards/kc60/keymaps/stanleylai/config.h b/keyboards/kc60/keymaps/stanleylai/config.h
new file mode 100644
index 000000000..b5024a6d0
--- /dev/null
+++ b/keyboards/kc60/keymaps/stanleylai/config.h
@@ -0,0 +1,3 @@
+// Use configs from WS2812 enabled Keymap
+
+#include "../ws2812/config.h"
diff --git a/keyboards/kc60/keymaps/stanleylai/keymap.c b/keyboards/kc60/keymaps/stanleylai/keymap.c
new file mode 100644
index 000000000..a7ea6040d
--- /dev/null
+++ b/keyboards/kc60/keymaps/stanleylai/keymap.c
@@ -0,0 +1,151 @@
+// This is the canonical layout file for the Quantum project. If you want to add another keyboard,
+// this is the style you want to emulate.
+
+#include "kc60.h"
+
+// Each layer gets a name for readability, which is then used in the keymap matrix below.
+// The underscores don't mean anything - you can have a layer called STUFF or any other name.
+// Layer names don't all need to be of the same length, obviously, and you can also skip them
+// entirely and just use numbers.
+#define _BL 0
+#define _FL 1
+#define _RGBL 2
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+
+// See base_layer.png and rgb_layer.png for layout reference
+
+// Base Default Layer
+// Mac Modifier Layout. Use BootMagic to toggle GUI and ALT positions.
+[_BL] = KEYMAP(
+ F(0), KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, \
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, \
+ LT(_FL, KC_CAPS), KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN,KC_QUOT, KC_NO, KC_ENT, \
+ KC_LSFT, KC_NO, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH, MO(_FL), KC_UP, \
+ KC_LCTL, KC_LALT, KC_LGUI, KC_SPC, KC_RGUI,KC_LEFT, KC_DOWN, KC_RGHT),
+
+// Function layer
+[_FL] = KEYMAP(
+ KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL, \
+ KC_NO, KC_MPRV,KC_UP, KC_MNXT,KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_PSCR,KC_SLCK, KC_PAUS, KC_INS, \
+ KC_TRNS,KC_LEFT,KC_DOWN,KC_RGHT,KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, \
+ KC_TRNS,KC_NO, KC_MUTE,KC_VOLD,KC_VOLU,KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_TRNS, LT(_RGBL, KC_PGUP),\
+ KC_TRNS,KC_TRNS,KC_TRNS, KC_MPLY, KC_TRNS,KC_HOME, KC_PGDN, KC_END),
+
+// RGB Layer
+[_RGBL] = KEYMAP(
+ #ifdef RGBLIGHT_ENABLE
+ RESET, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, \
+ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, \
+ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, \
+ KC_TRNS,KC_NO, F(1), F(2), F(3), F(4), F(5), F(6), F(7), F(8), BL_STEP,BL_TOGG, KC_TRNS, KC_TRNS,\
+ KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS),
+ #else
+ RESET, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, \
+ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, \
+ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, \
+ KC_TRNS,KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, BL_STEP,BL_TOGG, KC_TRNS, KC_TRNS,\
+ KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS),
+ #endif
+};
+
+
+enum function_id {
+ SHIFT_ESC,
+ #ifdef RGBLIGHT_ENABLE
+ RGBLED_TOGGLE,
+ RGBLED_STEP_MODE,
+ RGBLED_INCREASE_HUE,
+ RGBLED_DECREASE_HUE,
+ RGBLED_INCREASE_SAT,
+ RGBLED_DECREASE_SAT,
+ RGBLED_INCREASE_VAL,
+ RGBLED_DECREASE_VAL,
+ #endif
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [0] = ACTION_FUNCTION(SHIFT_ESC),
+ #ifdef RGBLIGHT_ENABLE
+ [1] = ACTION_FUNCTION(RGBLED_TOGGLE),
+ [2] = ACTION_FUNCTION(RGBLED_STEP_MODE),
+ [3] = ACTION_FUNCTION(RGBLED_INCREASE_HUE),
+ [4] = ACTION_FUNCTION(RGBLED_DECREASE_HUE),
+ [5] = ACTION_FUNCTION(RGBLED_INCREASE_SAT),
+ [6] = ACTION_FUNCTION(RGBLED_DECREASE_SAT),
+ [7] = ACTION_FUNCTION(RGBLED_INCREASE_VAL),
+ [8] = ACTION_FUNCTION(RGBLED_DECREASE_VAL),
+ #endif
+};
+
+#define MODS_CTRL_MASK (MOD_BIT(KC_LSHIFT)|MOD_BIT(KC_RSHIFT))
+void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) {
+ static uint8_t shift_esc_shift_mask;
+ switch (id) {
+ case SHIFT_ESC:
+ shift_esc_shift_mask = get_mods()&MODS_CTRL_MASK;
+ if (record->event.pressed) {
+ if (shift_esc_shift_mask) {
+ add_key(KC_GRV);
+ send_keyboard_report();
+ } else {
+ add_key(KC_ESC);
+ send_keyboard_report();
+ }
+ } else {
+ if (shift_esc_shift_mask) {
+ del_key(KC_GRV);
+ send_keyboard_report();
+ } else {
+ del_key(KC_ESC);
+ send_keyboard_report();
+ }
+ }
+ break;
+
+ #ifdef RGBLIGHT_ENABLE
+
+ case RGBLED_TOGGLE:
+ //led operations
+ if (record->event.pressed) {
+ rgblight_toggle();
+ }
+ break;
+ case RGBLED_INCREASE_HUE:
+ if (record->event.pressed) {
+ rgblight_increase_hue();
+ }
+ break;
+ case RGBLED_DECREASE_HUE:
+ if (record->event.pressed) {
+ rgblight_decrease_hue();
+ }
+ break;
+ case RGBLED_INCREASE_SAT:
+ if (record->event.pressed) {
+ rgblight_increase_sat();
+ }
+ break;
+ case RGBLED_DECREASE_SAT:
+ if (record->event.pressed) {
+ rgblight_decrease_sat();
+ }
+ break;
+ case RGBLED_INCREASE_VAL:
+ if (record->event.pressed) {
+ rgblight_increase_val();
+ }
+ break;
+ case RGBLED_DECREASE_VAL:
+ if (record->event.pressed) {
+ rgblight_decrease_val();
+ }
+ break;
+ case RGBLED_STEP_MODE:
+ if (record->event.pressed) {
+ rgblight_step();
+ }
+ break;
+ #endif
+ }
+}
diff --git a/keyboards/kc60/keymaps/stanleylai/readme.md b/keyboards/kc60/keymaps/stanleylai/readme.md
new file mode 100644
index 000000000..1db72610d
--- /dev/null
+++ b/keyboards/kc60/keymaps/stanleylai/readme.md
@@ -0,0 +1,26 @@
+Stanley Lai's Split Right Shift with Dedicated Arrow Keys
+======================
+
+![Image of KC60 with RGB Underglow](../ws2812/ws2812_example.jpg)
+
+## Quantum MK Firmware
+For the full Quantum feature list, see [the parent readme.md](/readme.md).
+
+## Keymap Notes
+- Keymap setup with split Right Shift in mind.
+- Right-side modifiers are setup as dedicated arrow keys
+
+### Base Layer Reference
+- Fn Layer indicated on keycap front legends.
+- Tapping Caps Lock key toggles Caps. Holding it down momentarily switches us to the Fn Layer.
+- Holding down "Fn" and "Page Down" momentarily switches us to the RGB Layer. Tapping "Page Down" behaves as expected.
+![Base Layer](base_layer.jpg)
+
+### RGB Layer Reference
+![RGB Layer](rgb_layer.jpg)
+
+## WS2812 Support
+By default, it is now setup for 16 LEDs on the PF5 breakout pin. See [included image](../ws2812/ws2812_wiring.jpg) for wiring reference.
+
+### Build
+To build this keymap, simply run `make KEYMAP=stanleylai`.
diff --git a/keyboards/kc60/keymaps/stanleylai/rgb_layer.png b/keyboards/kc60/keymaps/stanleylai/rgb_layer.png
new file mode 100644
index 000000000..2bba028bb
--- /dev/null
+++ b/keyboards/kc60/keymaps/stanleylai/rgb_layer.png
Binary files differ
diff --git a/keyboards/kc60/keymaps/wigguno/Makefile b/keyboards/kc60/keymaps/wigguno/Makefile
new file mode 100644
index 000000000..0d7d918d8
--- /dev/null
+++ b/keyboards/kc60/keymaps/wigguno/Makefile
@@ -0,0 +1,24 @@
+
+
+# Build Options
+# change yes to no to disable
+#
+BOOTMAGIC_ENABLE ?= yes # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE ?= no # Mouse keys(+4700)
+EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450)
+CONSOLE_ENABLE ?= no # Console for debug(+400)
+COMMAND_ENABLE ?= no # Commands for debug and configuration
+KEYBOARD_LOCK_ENABLE ?= yes # Allow locking of keyboard via magic key
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE ?= no # Breathing sleep LED during USB suspend
+# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+NKRO_ENABLE ?= yes # USB Nkey Rollover
+BACKLIGHT_ENABLE ?= yes # Enable keyboard backlight functionality
+MIDI_ENABLE ?= no # MIDI controls
+UNICODE_ENABLE ?= no # Unicode
+BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID
+AUDIO_ENABLE ?= no # Audio output on port C6
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif
diff --git a/keyboards/kc60/keymaps/wigguno/keymap.c b/keyboards/kc60/keymaps/wigguno/keymap.c
new file mode 100644
index 000000000..50b1d0f98
--- /dev/null
+++ b/keyboards/kc60/keymaps/wigguno/keymap.c
@@ -0,0 +1,62 @@
+// This keymap was designed to close to the default kc60 layout, with some useful changes, such as adding media keys.
+// It also moves the reset key off the base layer, as in the default kc60 layout for this firmware.
+// I have swapped FN and RGUI as my rainbow keyset has them in the opposite order.
+
+#include "kc60.h"
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+
+ /* Basic QWERTY
+ * ,-----------------------------------------------------------.
+ * |Esc | 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backsp |
+ * |-----------------------------------------------------------|
+ * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \ |
+ * |-----------------------------------------------------------|
+ * |CAPS | A| S| D| F| G| H| J| K| L| ;| '|Return |
+ * |-----------------------------------------------------------|
+ * |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift |
+ * |-----------------------------------------------------------|
+ * |Ctrl|Gui |Alt | Space |Alt |FN |Gui |Ctrl |
+ * `-----------------------------------------------------------'
+ */
+ [0] = KEYMAP(
+ KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, \
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, \
+ KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_NO, KC_ENT, \
+ KC_LSFT, KC_NO, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_NO, KC_RSFT, \
+ KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(1), KC_RGUI, KC_RCTL \
+ ),
+
+ /*
+ * ,-----------------------------------------------------------.
+ * | ` |F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12| Del |
+ * |-----------------------------------------------------------|
+ * | | | Up| | | | | | | | PS| | | |
+ * |-----------------------------------------------------------|
+ * | |Lft|Dwn|Rgt| |BL-|BL+| | | | | | |
+ * |-----------------------------------------------------------|
+ * | |Prv| PP|Nxt| | | | |Hom|End| | |
+ * |-----------------------------------------------------------|
+ * | Rst| | | BL | | | | |
+ * `-----------------------------------------------------------'
+ * PS = Print Screen
+ * PP = Play/Pause
+ */
+ [1] = KEYMAP( /* Function Layer */
+ KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DELETE, \
+ KC_TRNS, KC_TRNS, KC_UP, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PSCR, KC_TRNS, KC_TRNS, KC_TRNS, \
+ KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS, BL_DEC, BL_INC, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
+ KC_TRNS, KC_TRNS, KC_MPRV, KC_MPLY, KC_MNXT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_HOME, KC_END, KC_TRNS, KC_TRNS, KC_TRNS, \
+ RESET, KC_TRNS, KC_TRNS, BL_TOGG, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS \
+ ),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ return MACRO_NONE;
+};
diff --git a/keyboards/kc60/keymaps/wigguno/readme.md b/keyboards/kc60/keymaps/wigguno/readme.md
new file mode 100644
index 000000000..55a9f60c7
--- /dev/null
+++ b/keyboards/kc60/keymaps/wigguno/readme.md
@@ -0,0 +1,14 @@
+Wigguno's KC60 Layout
+======================
+
+## Quantum MK Firmware
+For the full Quantum feature list, see [the parent readme.md](/readme.md).
+
+## Changes from default QMK layout
+The default QMK layout for KC60 does not have a function layer. It also has the bootloader-mode reset key bound. This keymap fixes both of these by adding a sensible function layer (including moving the reset key onto it, far away from the FN key).
+
+### Changes from the default KC60 layout
+The default KC60 layout is good, but it was missing media keys. I've added previous, play/pause and next. I've also removed some of the keys from the function layer I didn't use.
+
+### Build
+To enable NKRO you must be in the keymaps/wigguno directory when running make.
diff --git a/keyboards/kc60/keymaps/ws2812/Makefile b/keyboards/kc60/keymaps/ws2812/Makefile
new file mode 100644
index 000000000..891c44416
--- /dev/null
+++ b/keyboards/kc60/keymaps/ws2812/Makefile
@@ -0,0 +1,25 @@
+
+
+# Build Options
+# change yes to no to disable
+#
+BOOTMAGIC_ENABLE ?= yes # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE ?= yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450)
+CONSOLE_ENABLE ?= yes # Console for debug(+400)
+COMMAND_ENABLE ?= yes # Commands for debug and configuration
+KEYBOARD_LOCK_ENABLE ?= yes # Allow locking of keyboard via magic key
+BACKLIGHT_ENABLE ?= yes # Enable keyboard backlight functionality
+RGBLIGHT_ENABLE ?= yes # Enable WS2812 underglow RGB strip
+MIDI_ENABLE ?= no # MIDI controls
+UNICODE_ENABLE ?= no # Unicode
+BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID
+AUDIO_ENABLE ?= no # Audio output on port C6
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE ?= no # Breathing sleep LED during USB suspend
+# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+NKRO_ENABLE ?= no # USB Nkey Rollover
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif
diff --git a/keyboards/kc60/keymaps/ws2812/config.h b/keyboards/kc60/keymaps/ws2812/config.h
new file mode 100644
index 000000000..933bb0d2d
--- /dev/null
+++ b/keyboards/kc60/keymaps/ws2812/config.h
@@ -0,0 +1,10 @@
+#include "../../config.h"
+
+/* WS2812B RGB Underglow LED */
+#define ws2812_PORTREG PORTF
+#define ws2812_DDRREG DDRF
+#define ws2812_pin PF5 // Based on wiring depicted in ws2812_wiring.jpg
+#define RGBLED_NUM 16 // Number of LEDs. Change this to match your use case.
+#define RGBLIGHT_HUE_STEP 8
+#define RGBLIGHT_SAT_STEP 8
+#define RGBLIGHT_VAL_STEP 8
diff --git a/keyboards/kc60/keymaps/ws2812/keymap.c b/keyboards/kc60/keymaps/ws2812/keymap.c
new file mode 100644
index 000000000..bd5bef787
--- /dev/null
+++ b/keyboards/kc60/keymaps/ws2812/keymap.c
@@ -0,0 +1,161 @@
+// This is the canonical layout file for the Quantum project. If you want to add another keyboard,
+// this is the style you want to emulate.
+
+#include "kc60.h"
+
+// Used for SHIFT_ESC
+#define MODS_CTRL_MASK (MOD_BIT(KC_LSHIFT)|MOD_BIT(KC_RSHIFT))
+
+// Each layer gets a name for readability, which is then used in the keymap matrix below.
+// The underscores don't mean anything - you can have a layer called STUFF or any other name.
+// Layer names don't all need to be of the same length, obviously, and you can also skip them
+// entirely and just use numbers.
+#define _BL 0
+#define _FL 1
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ /* Keymap _BL: (Base Layer) Default Layer
+ * ,-----------------------------------------------------------.
+ * |Esc~| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backsp |
+ * |-----------------------------------------------------------|
+ * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \ |
+ * |-----------------------------------------------------------|
+ * |CAPS | A| S| D| F| G| H| J| K| L| ;| '|Return |
+ * |-----------------------------------------------------------|
+ * |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift |
+ * |-----------------------------------------------------------|
+ * |Ctrl|Gui |Alt | Space |Alt |Gui |FN |Ctrl |
+ * `-----------------------------------------------------------'
+ */
+[_BL] = KEYMAP(
+ F(0), KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, \
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, \
+ KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN,KC_QUOT, KC_NO, KC_ENT, \
+ KC_LSFT, KC_NO, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH, KC_NO, KC_RSFT, \
+ KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT,KC_RGUI, MO(_FL), KC_RCTL),
+
+ /* Keymap _FL: Function Layer
+ * ,-----------------------------------------------------------.
+ * |~ |F1 |F2 |F3 |F4 |F5 |F6 |F7 |F8 |F9 |F10|F11|F12| DEL |
+ * |-----------------------------------------------------------|
+ * | | |UP | | | | | | | | |BL-|BL+|BL |
+ * |-----------------------------------------------------------|
+ * | |LFT|DWN|RGT| | | | | | | | |
+ * |-----------------------------------------------------------|
+ * | |FN1|FN2|FN3|FN4|FN5|FN6|FN7|FN8| | | |
+ * |-----------------------------------------------------------|
+ * | | | | | | | |RSET|
+ * `-----------------------------------------------------------'
+ */
+[_FL] = KEYMAP(
+ #ifdef RGBLIGHT_ENABLE
+ KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL, \
+ KC_TRNS, KC_TRNS, KC_UP, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, BL_DEC, BL_INC, BL_TOGG, \
+ KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
+ KC_TRNS, KC_TRNS, F(1), F(2), F(3), F(4), F(5), F(6), F(7), F(8), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, RESET),
+ #else
+ KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL, \
+ KC_TRNS, KC_TRNS, KC_UP, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, BL_DEC, BL_INC, BL_TOGG, \
+ KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, RESET),
+ #endif
+};
+
+enum function_id {
+ SHIFT_ESC,
+ #ifdef RGBLIGHT_ENABLE
+ RGBLED_TOGGLE,
+ RGBLED_STEP_MODE,
+ RGBLED_INCREASE_HUE,
+ RGBLED_DECREASE_HUE,
+ RGBLED_INCREASE_SAT,
+ RGBLED_DECREASE_SAT,
+ RGBLED_INCREASE_VAL,
+ RGBLED_DECREASE_VAL
+ #endif
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [0] = ACTION_FUNCTION(SHIFT_ESC),
+ #ifdef RGBLIGHT_ENABLE
+ [1] = ACTION_FUNCTION(RGBLED_TOGGLE),
+ [2] = ACTION_FUNCTION(RGBLED_STEP_MODE),
+ [3] = ACTION_FUNCTION(RGBLED_INCREASE_HUE),
+ [4] = ACTION_FUNCTION(RGBLED_DECREASE_HUE),
+ [5] = ACTION_FUNCTION(RGBLED_INCREASE_SAT),
+ [6] = ACTION_FUNCTION(RGBLED_DECREASE_SAT),
+ [7] = ACTION_FUNCTION(RGBLED_INCREASE_VAL),
+ [8] = ACTION_FUNCTION(RGBLED_DECREASE_VAL),
+ #endif
+};
+
+void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) {
+ static uint8_t shift_esc_shift_mask;
+ switch (id) {
+ case SHIFT_ESC:
+ shift_esc_shift_mask = get_mods()&MODS_CTRL_MASK;
+ if (record->event.pressed) {
+ if (shift_esc_shift_mask) {
+ add_key(KC_GRV);
+ send_keyboard_report();
+ } else {
+ add_key(KC_ESC);
+ send_keyboard_report();
+ }
+ } else {
+ if (shift_esc_shift_mask) {
+ del_key(KC_GRV);
+ send_keyboard_report();
+ } else {
+ del_key(KC_ESC);
+ send_keyboard_report();
+ }
+ }
+ break;
+ //led operations
+ #ifdef RGBLIGHT_ENABLE
+ case RGBLED_TOGGLE:
+ if (record->event.pressed) {
+ rgblight_toggle();
+ }
+ break;
+ case RGBLED_INCREASE_HUE:
+ if (record->event.pressed) {
+ rgblight_increase_hue();
+ }
+ break;
+ case RGBLED_DECREASE_HUE:
+ if (record->event.pressed) {
+ rgblight_decrease_hue();
+ }
+ break;
+ case RGBLED_INCREASE_SAT:
+ if (record->event.pressed) {
+ rgblight_increase_sat();
+ }
+ break;
+ case RGBLED_DECREASE_SAT:
+ if (record->event.pressed) {
+ rgblight_decrease_sat();
+ }
+ break;
+ case RGBLED_INCREASE_VAL:
+ if (record->event.pressed) {
+ rgblight_increase_val();
+ }
+ break;
+ case RGBLED_DECREASE_VAL:
+ if (record->event.pressed) {
+ rgblight_decrease_val();
+ }
+ break;
+ case RGBLED_STEP_MODE:
+ if (record->event.pressed) {
+ rgblight_step();
+ }
+ break;
+ #endif
+ }
+}
diff --git a/keyboards/kc60/keymaps/ws2812/readme.md b/keyboards/kc60/keymaps/ws2812/readme.md
new file mode 100644
index 000000000..5588fd2d9
--- /dev/null
+++ b/keyboards/kc60/keymaps/ws2812/readme.md
@@ -0,0 +1,21 @@
+KC60 with WS2812 RGB Underglow
+======================
+
+![Image of KC60 with RGB Underglow](ws2812_example.jpg)
+
+## Quantum MK Firmware
+For the full Quantum feature list, see [the parent readme.md](/readme.md).
+
+## WS2812 Support
+By default, it is now setup for 16 LEDs on the PF5 breakout pin. See [included image](ws2812_wiring.jpg) for wiring reference.
+
+### Build
+To build this keymap with WS2812 enabled, simply run `make KEYMAP=ws2812`.
+
+### Reference Images
+![Wiring Reference](ws2812_wiring.jpg)
+![RGB Strip turned on](ws2812_underside-lit.jpg)
+![RGB Strip turned off](ws2812_underside.jpg)
+
+### Additional Credits
+Keymap based on work by [TerryMatthews](https://github.com/TerryMathews) for GH60 Satan.
diff --git a/keyboards/kc60/keymaps/ws2812/ws2812_example.jpg b/keyboards/kc60/keymaps/ws2812/ws2812_example.jpg
new file mode 100644
index 000000000..5c62cfded
--- /dev/null
+++ b/keyboards/kc60/keymaps/ws2812/ws2812_example.jpg
Binary files differ
diff --git a/keyboards/kc60/keymaps/ws2812/ws2812_underside-lit.jpg b/keyboards/kc60/keymaps/ws2812/ws2812_underside-lit.jpg
new file mode 100644
index 000000000..2eab21433
--- /dev/null
+++ b/keyboards/kc60/keymaps/ws2812/ws2812_underside-lit.jpg
Binary files differ
diff --git a/keyboards/kc60/keymaps/ws2812/ws2812_underside.jpg b/keyboards/kc60/keymaps/ws2812/ws2812_underside.jpg
new file mode 100644
index 000000000..159d63904
--- /dev/null
+++ b/keyboards/kc60/keymaps/ws2812/ws2812_underside.jpg
Binary files differ
diff --git a/keyboards/kc60/keymaps/ws2812/ws2812_wiring.jpg b/keyboards/kc60/keymaps/ws2812/ws2812_wiring.jpg
new file mode 100644
index 000000000..61b749b66
--- /dev/null
+++ b/keyboards/kc60/keymaps/ws2812/ws2812_wiring.jpg
Binary files differ
diff --git a/keyboards/kc60/readme.md b/keyboards/kc60/readme.md
new file mode 100644
index 000000000..acc0df68d
--- /dev/null
+++ b/keyboards/kc60/readme.md
@@ -0,0 +1,27 @@
+KC60 (version 2.0) keyboard firmware
+======================
+
+## Quantum MK Firmware
+For the full Quantum feature list, see [the parent readme.md](/readme.md).
+
+## Building
+Download or clone the whole firmware and navigate to the keyboards/kc60 folder. Once your dev env is setup, you'll be able to type `make` to generate your .hex - you can then use the Teensy Loader to program your .hex file.
+
+Depending on which keymap you would like to use, you will have to compile slightly differently.
+
+### Default
+To build with the default keymap, simply run `make`.
+
+### Other Keymaps
+Several version of keymap are available in advance but you are recommended to define your favorite layout yourself. To define your own keymap create file named `<name>.c` in the keymaps folder, and see keymap document (you can find in top readme.md) and existent keymap files.
+
+To build the firmware binary hex file with a keymap just do `make` with `KEYMAP` option like:
+```
+$ make KEYMAP=[default|jack|<name>]
+```
+Keymaps follow the format **__\<name\>.c__** and are stored in the `keymaps` folder.
+
+## WS2812 Support
+![Image of KC60 with RGB Underglow](keymaps/ws2812/ws2812_example.jpg)
+
+Build with WS2812 Support by running `make KEYMAP=ws2812`.
diff --git a/keyboards/phantom/Makefile b/keyboards/phantom/Makefile
new file mode 100644
index 000000000..3a71fd0ee
--- /dev/null
+++ b/keyboards/phantom/Makefile
@@ -0,0 +1,74 @@
+
+
+SRC = led.c
+
+# MCU name
+#MCU = at90usb1287
+MCU = atmega32u4
+
+# Processor frequency.
+# This will define a symbol, F_CPU, in all source code files equal to the
+# processor frequency in Hz. You can then use this symbol in your source code to
+# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
+# automatically to create a 32-bit value in your source code.
+#
+# This will be an integer division of F_USB below, as it is sourced by
+# F_USB after it has run through any CPU prescalers. Note that this value
+# does not *change* the processor frequency - it should merely be updated to
+# reflect the processor speed set externally so that the code can use accurate
+# software delays.
+F_CPU = 16000000
+
+
+#
+# LUFA specific
+#
+# Target architecture (see library "Board Types" documentation).
+ARCH = AVR8
+
+# Input clock frequency.
+# This will define a symbol, F_USB, in all source code files equal to the
+# input clock frequency (before any prescaling is performed) in Hz. This value may
+# differ from F_CPU if prescaling is used on the latter, and is required as the
+# raw input clock is fed directly to the PLL sections of the AVR for high speed
+# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
+# at the end, this will be done automatically to create a 32-bit value in your
+# source code.
+#
+# If no clock division is performed on the input clock inside the AVR (via the
+# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
+F_USB = $(F_CPU)
+
+# Interrupt driven control endpoint task(+60)
+OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
+
+
+# Boot Section Size in *bytes*
+# Teensy halfKay 512
+# Teensy++ halfKay 1024
+# Atmel DFU loader 4096
+# LUFA bootloader 4096
+# USBaspLoader 2048
+OPT_DEFS += -DBOOTLOADER_SIZE=4096
+
+
+# Build Options
+# comment out to disable the options.
+#
+BOOTMAGIC_ENABLE ?= yes # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE ?= no # Mouse keys(+4700)
+EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450)
+CONSOLE_ENABLE ?= yes # Console for debug(+400)
+COMMAND_ENABLE ?= yes # Commands for debug and configuration
+NKRO_ENABLE ?= yes # USB Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+RGBLIGHT_ENABLE ?=yes # Enable keyboard underlight functionality (+4870)
+BACKLIGHT_ENABLE ?= no # Enable keyboard backlight functionality (+1150)
+MIDI_ENABLE ?= no # MIDI controls
+AUDIO_ENABLE ?= no
+UNICODE_ENABLE ?= no # Unicode
+BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID
+
+
+ifndef QUANTUM_DIR
+ include ../../Makefile
+endif
diff --git a/keyboards/phantom/config.h b/keyboards/phantom/config.h
new file mode 100644
index 000000000..d5878766f
--- /dev/null
+++ b/keyboards/phantom/config.h
@@ -0,0 +1,91 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "config_common.h"
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x6060
+#define DEVICE_VER 0x0003
+#define MANUFACTURER PHANTOM
+#define PRODUCT PHANTOM RGB MOD
+#define DESCRIPTION QMK keyboard firmware for PHANTOM TKL
+
+/* key matrix size */
+#define MATRIX_ROWS 6
+#define MATRIX_COLS 17
+
+// ROWS: Top to bottom, COLS: Left to right
+/* Row pin configuration
+*/
+#define MATRIX_ROW_PINS { B5, B4, B3, B2, B1, B0 }
+/* Column pin configuration
+ */
+#define MATRIX_COL_PINS { D5, C7, C6, D4, D0, E6, F0, F1, F4, F5, F6, F7, D7, D6, D1, D2, D3 }
+#define UNUSED_PINS
+
+/* COL2ROW or ROW2COL */
+#define DIODE_DIRECTION ROW2COL
+
+/* define if matrix has ghost */
+//#define MATRIX_HAS_GHOST
+
+/* Set 0 if debouncing isn't needed */
+#define DEBOUNCING_DELAY 5
+
+/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
+#define LOCKING_SUPPORT_ENABLE
+/* Locking resynchronize hack */
+#define LOCKING_RESYNC_ENABLE
+
+/* key combination for command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+/* Underlight configuration
+ */
+ #define ws2812_PORTREG PORTE
+ #define ws2812_DDRREG DDRE
+ #define ws2812_pin 2
+ #define RGBLED_NUM 20 // Number of LEDs
+ #define RGBLIGHT_HUE_STEP 10
+ #define RGBLIGHT_SAT_STEP 17
+ #define RGBLIGHT_VAL_STEP 17
+
+/*
+ * Feature disable options
+ * These options are also useful to firmware size reduction.
+ */
+
+/* disable debug print */
+//#define NO_DEBUG
+
+/* disable print */
+//#define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+
+#endif
diff --git a/keyboards/phantom/keymaps/default/keymap.c b/keyboards/phantom/keymaps/default/keymap.c
new file mode 100644
index 000000000..1368226aa
--- /dev/null
+++ b/keyboards/phantom/keymaps/default/keymap.c
@@ -0,0 +1,169 @@
+#include "phantom.h"
+
+#ifdef RGBLIGHT_ENABLE
+#include "rgblight.h"
+#endif
+
+// Used for SHIFT_ESC
+#define MODS_CTRL_MASK (MOD_BIT(KC_LSHIFT)|MOD_BIT(KC_RSHIFT))
+
+// Each layer gets a name for readability, which is then used in the keymap matrix below.
+// The underscores don't mean anything - you can have a layer called STUFF or any other name.
+// Layer names don't all need to be of the same length, obviously, and you can also skip them
+// entirely and just use numbers.
+#define _BL 0
+#define _FL 1
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ /* Keymap _BL: (Base Layer) Default Layer
+ * ,-----------------------------------------------------------------------------.
+ * |Esc |f1| f2| f3| f4| | f5| f6| f7| f8| | f9|f10|f11|f12| |Prnt|ScLk|Paus|
+ * |-----------------------------------------------------------| |--------------|
+ * | ~ | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0| - | = |Backsp | | Ins|Home|PgUp|
+ * |-----------------------------------------------------------| |--------------|
+ * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| | Del| End|PgDn|
+ * |-----------------------------------------------------------| `--------------'
+ * |CAPS | A| S| D| F| G| H| J| K| L| ;| '|Return |
+ * |-----------------------------------------------------------| ,----.
+ * |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift | | Up |
+ * |-----------------------------------------------------------| ,-------------.
+ * |Ctrl|Gui |Alt | Space |ALT |GUI |_FL |CTRL | |Lft| Dn |Rig |
+ * `-----------------------------------------------------------' `-------------'
+ */
+[_BL] = KEYMAP(
+ KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_PSCR, KC_SLCK, KC_PAUS, \
+ KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_INS, KC_HOME, KC_PGUP, \
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_DELETE, KC_END, KC_PGDN, \
+ KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, \
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP, \
+ KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, KC_RGUI, MO(_FL), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT),
+
+ /* Keymap _FL: Function Layer
+ * ,-----------------------------------------------------------------------------.
+ * | | | | | | | | | | | | | | | | | | | |
+ * |-----------------------------------------------------------| |--------------|
+ * | | | | | | | | | | | | | | Reset | | | | |
+ * |-----------------------------------------------------------| |--------------|
+ * | | | | | | | | | | | | | | | | | | |
+ * |-----------------------------------------------------------| `--------------'
+ * | | | | | | | | | | | | | |
+ * |-----------------------------------------------------------| ,----.
+ * | | F1| F2| F3| F4| F5|F6 |F7 |F8 | | | | | |
+ * |-----------------------------------------------------------| ,-------------.
+ * | | | | | | | | | | | | |
+ * `-----------------------------------------------------------' `-------------'
+ */
+[_FL] = KEYMAP(
+ #ifdef RGBLIGHT_ENABLE
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, RESET, KC_TRNS, KC_TRNS, KC_TRNS, \
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_UP, KC_TRNS, \
+ KC_TRNS, F(1), F(2), F(3), F(4), F(5), F(6), F(7), F(8), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS),
+ #else
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, RESET, KC_TRNS, KC_TRNS, KC_TRNS, \
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_UP, KC_TRNS, \
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS),
+ #endif
+};
+
+enum function_id {
+ SHIFT_ESC,
+ #ifdef RGBLIGHT_ENABLE
+ RGBLED_TOGGLE,
+ RGBLED_STEP_MODE,
+ RGBLED_INCREASE_HUE,
+ RGBLED_DECREASE_HUE,
+ RGBLED_INCREASE_SAT,
+ RGBLED_DECREASE_SAT,
+ RGBLED_INCREASE_VAL,
+ RGBLED_DECREASE_VAL
+ #endif
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [0] = ACTION_FUNCTION(SHIFT_ESC),
+ #ifdef RGBLIGHT_ENABLE
+ [1] = ACTION_FUNCTION(RGBLED_TOGGLE),
+ [2] = ACTION_FUNCTION(RGBLED_STEP_MODE),
+ [3] = ACTION_FUNCTION(RGBLED_INCREASE_HUE),
+ [4] = ACTION_FUNCTION(RGBLED_DECREASE_HUE),
+ [5] = ACTION_FUNCTION(RGBLED_INCREASE_SAT),
+ [6] = ACTION_FUNCTION(RGBLED_DECREASE_SAT),
+ [7] = ACTION_FUNCTION(RGBLED_INCREASE_VAL),
+ [8] = ACTION_FUNCTION(RGBLED_DECREASE_VAL),
+ #endif
+};
+
+void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) {
+ static uint8_t shift_esc_shift_mask;
+ switch (id) {
+ case SHIFT_ESC:
+ shift_esc_shift_mask = get_mods()&MODS_CTRL_MASK;
+ if (record->event.pressed) {
+ if (shift_esc_shift_mask) {
+ add_key(KC_GRV);
+ send_keyboard_report();
+ } else {
+ add_key(KC_ESC);
+ send_keyboard_report();
+ }
+ } else {
+ if (shift_esc_shift_mask) {
+ del_key(KC_GRV);
+ send_keyboard_report();
+ } else {
+ del_key(KC_ESC);
+ send_keyboard_report();
+ }
+ }
+ break;
+ //led operations
+ #ifdef RGBLIGHT_ENABLE
+ case RGBLED_TOGGLE:
+ if (record->event.pressed) {
+ rgblight_toggle();
+ }
+ break;
+ case RGBLED_INCREASE_HUE:
+ if (record->event.pressed) {
+ rgblight_increase_hue();
+ }
+ break;
+ case RGBLED_DECREASE_HUE:
+ if (record->event.pressed) {
+ rgblight_decrease_hue();
+ }
+ break;
+ case RGBLED_INCREASE_SAT:
+ if (record->event.pressed) {
+ rgblight_increase_sat();
+ }
+ break;
+ case RGBLED_DECREASE_SAT:
+ if (record->event.pressed) {
+ rgblight_decrease_sat();
+ }
+ break;
+ case RGBLED_INCREASE_VAL:
+ if (record->event.pressed) {
+ rgblight_increase_val();
+ }
+ break;
+ case RGBLED_DECREASE_VAL:
+ if (record->event.pressed) {
+ rgblight_decrease_val();
+ }
+ break;
+ case RGBLED_STEP_MODE:
+ if (record->event.pressed) {
+ rgblight_step();
+ }
+ break;
+ #endif
+ }
+}
diff --git a/keyboards/phantom/led.c b/keyboards/phantom/led.c
new file mode 100644
index 000000000..b2459c774
--- /dev/null
+++ b/keyboards/phantom/led.c
@@ -0,0 +1,43 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <avr/io.h>
+#include "stdint.h"
+#include "led.h"
+
+void led_init(void) {
+ // * Set our LED pins as output
+ DDRB |= (1<<6);
+ DDRB |= (1<<7);
+}
+
+void led_set_kb(uint8_t usb_led) {
+ if (usb_led & (1<<USB_LED_CAPS_LOCK)) {
+ // Turn capslock on
+ PORTB |= (1<<6);
+ } else {
+ // Turn capslock off
+ PORTB &= ~(1<<6);
+ }
+ if (usb_led & (1<<USB_LED_SCROLL_LOCK)) {
+ // Turn scrolllock on
+ PORTB |= (1<<7);
+ } else {
+ // Turn scrolllock off
+ PORTB &= ~(1<<7);
+ }
+}
diff --git a/keyboards/phantom/phantom.c b/keyboards/phantom/phantom.c
new file mode 100644
index 000000000..d53af491f
--- /dev/null
+++ b/keyboards/phantom/phantom.c
@@ -0,0 +1,9 @@
+#include "phantom.h"
+#include "led.h"
+
+void matrix_init_kb(void) {
+ // put your keyboard start-up code here
+ // runs once when the firmware starts up
+ matrix_init_user();
+ led_init_ports();
+};
diff --git a/keyboards/phantom/phantom.h b/keyboards/phantom/phantom.h
new file mode 100644
index 000000000..420826bec
--- /dev/null
+++ b/keyboards/phantom/phantom.h
@@ -0,0 +1,40 @@
+#ifndef PHANTOM_H
+#define PHANTOM_H
+
+#include "quantum.h"
+
+/* Phantom matrix layout
+ * ,-----------------------------------------------------------------------------.
+ * |00 |02| 03| 04| 05| | 06| 07| 08| 09| | 0a|0b |0c |0d | |0e |0f |0g |
+ * |-----------------------------------------------------------| |--------------|
+ * | 01| 10| 11| 12| 13| 14| 15| 16| 17| 18| 19| 1a| 1b| 1d | |1e |1f |1g |
+ * |-----------------------------------------------------------| |--------------|
+ * |20 | 21| 22| 23| 24| 25| 26| 27| 28| 29| 2a| 2b| 2c| 2d| | 2e | 2f | 2g |
+ * |-----------------------------------------------------------| `--------------'
+ * |30 | 31| 32| 33| 34| 35| 36| 37| 38| 39| 3a| 3b| 3d |
+ * |-----------------------------------------------------------| ,----.
+ * | 40 | 42| 43| 44| 45| 46| 47| 48| 49| 4a| 4b| 4d | | 4f |
+ * |-----------------------------------------------------------| ,-------------.
+ * | 50 | 51 | 52 | 57 |5a | 5b | 5c | 5d | | 5e| 5f | 5g |
+ * `-----------------------------------------------------------' `-------------'
+ */
+// The first section contains all of the arguments
+// The second converts the arguments into a two-dimensional array
+#define KEYMAP( \
+ k00, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, k0c, k0d, k0e, k0f, k0g, \
+ k01, k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, k1d, k1e, k1f, k1g, \
+ k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b, k2c, k2d, k2e, k2f, k2g, \
+ k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k3a, k3b, k3d, \
+ k40, k42, k43, k44, k45, k46, k47, k48, k49, k4a, k4b, k4d, k4f, \
+ k50, k51, k52, k57, k5a, k5b, k5c, k5d, k5e, k5f, k5g \
+) \
+{ \
+ {k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, k0c, k0d, k0e, k0f, k0g}, \
+ {k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, k1d, k1d, k1e, k1f, k1g}, \
+ {k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b, k2c, k2d, k2e, k2f, k2g}, \
+ {k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k3a, k3b, k3d, k3d, k3d, k3d, k3d}, \
+ {k40, k40, k42, k43, k44, k45, k46, k47, k48, k49, k4a, k4b, k4d, k4d, k4f, k4f, k4f}, \
+ {k50, k51, k52, k57, k57, k57, k57, k57, k57, k57, k5a, k5b, k5c, k5d, k5e, k5f, k5g} \
+}
+
+#endif
diff --git a/keyboards/phantom/pinout.jpg b/keyboards/phantom/pinout.jpg
new file mode 100644
index 000000000..30b0b8bf4
--- /dev/null
+++ b/keyboards/phantom/pinout.jpg
Binary files differ
diff --git a/keyboards/phantom/pinout.txt b/keyboards/phantom/pinout.txt
new file mode 100644
index 000000000..36f044d15
--- /dev/null
+++ b/keyboards/phantom/pinout.txt
@@ -0,0 +1 @@
+For WS2812B LED strip support, connect DIN from strip to PE2 on Teensy (see reference image pinout.jpg) \ No newline at end of file
diff --git a/keyboards/planck/Makefile b/keyboards/planck/Makefile
new file mode 100644
index 000000000..23944f92e
--- /dev/null
+++ b/keyboards/planck/Makefile
@@ -0,0 +1,74 @@
+
+SUBPROJECT_DEFAULT = rev4
+
+# MCU name
+#MCU = at90usb1287
+MCU = atmega32u4
+
+# Processor frequency.
+# This will define a symbol, F_CPU, in all source code files equal to the
+# processor frequency in Hz. You can then use this symbol in your source code to
+# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
+# automatically to create a 32-bit value in your source code.
+#
+# This will be an integer division of F_USB below, as it is sourced by
+# F_USB after it has run through any CPU prescalers. Note that this value
+# does not *change* the processor frequency - it should merely be updated to
+# reflect the processor speed set externally so that the code can use accurate
+# software delays.
+F_CPU = 16000000
+
+#
+# LUFA specific
+#
+# Target architecture (see library "Board Types" documentation).
+ARCH = AVR8
+
+# Input clock frequency.
+# This will define a symbol, F_USB, in all source code files equal to the
+# input clock frequency (before any prescaling is performed) in Hz. This value may
+# differ from F_CPU if prescaling is used on the latter, and is required as the
+# raw input clock is fed directly to the PLL sections of the AVR for high speed
+# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
+# at the end, this will be done automatically to create a 32-bit value in your
+# source code.
+#
+# If no clock division is performed on the input clock inside the AVR (via the
+# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
+F_USB = $(F_CPU)
+
+# Interrupt driven control endpoint task(+60)
+OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
+
+
+# Boot Section Size in *bytes*
+# Teensy halfKay 512
+# Teensy++ halfKay 1024
+# Atmel DFU loader 4096
+# LUFA bootloader 4096
+# USBaspLoader 2048
+OPT_DEFS += -DBOOTLOADER_SIZE=4096
+
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE ?= no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE ?= yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450)
+CONSOLE_ENABLE ?= no # Console for debug(+400)
+COMMAND_ENABLE ?= yes # Commands for debug and configuration
+NKRO_ENABLE ?= no # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE ?= yes # Enable keyboard backlight functionality
+MIDI_ENABLE ?= no # MIDI controls
+AUDIO_ENABLE ?= no # Audio output on port C6
+UNICODE_ENABLE ?= no # Unicode
+BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE ?= no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE ?= no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/planck/config.h b/keyboards/planck/config.h
new file mode 100644
index 000000000..4dd1d22a9
--- /dev/null
+++ b/keyboards/planck/config.h
@@ -0,0 +1,88 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "config_common.h"
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x6060
+#define MANUFACTURER Ortholinear Keyboards
+#define PRODUCT The Planck Keyboard
+#define DESCRIPTION A compact ortholinear keyboard
+
+/* key matrix size */
+#define MATRIX_ROWS 4
+#define MATRIX_COLS 12
+
+/* Planck PCB default pin-out */
+#define MATRIX_ROW_PINS { D0, D5, B5, B6 }
+#define MATRIX_COL_PINS { F1, F0, B0, C7, F4, F5, F6, F7, D4, D6, B4, D7 }
+#define UNUSED_PINS
+
+#define BACKLIGHT_PIN B7
+
+/* COL2ROW or ROW2COL */
+#define DIODE_DIRECTION COL2ROW
+
+/* define if matrix has ghost */
+//#define MATRIX_HAS_GHOST
+
+/* number of backlight levels */
+#define BACKLIGHT_LEVELS 3
+
+/* Set 0 if debouncing isn't needed */
+#define DEBOUNCING_DELAY 5
+
+/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
+#define LOCKING_SUPPORT_ENABLE
+/* Locking resynchronize hack */
+#define LOCKING_RESYNC_ENABLE
+
+/* key combination for command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+/*
+ * Feature disable options
+ * These options are also useful to firmware size reduction.
+ */
+
+/* disable debug print */
+//#define NO_DEBUG
+
+/* disable print */
+//#define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+
+#ifdef SUBPROJECT_rev3
+ #include "rev3/config.h"
+#endif
+#ifdef SUBPROJECT_rev4
+ #include "rev4/config.h"
+#endif
+
+#endif
diff --git a/keyboards/planck/keymaps/ab/Makefile b/keyboards/planck/keymaps/ab/Makefile
new file mode 100644
index 000000000..44a030ba3
--- /dev/null
+++ b/keyboards/planck/keymaps/ab/Makefile
@@ -0,0 +1,63 @@
+#----------------------------------------------------------------------------
+# On command line:
+#
+# make all = Make software.
+#
+# make clean = Clean out built project files.
+#
+# make coff = Convert ELF to AVR COFF.
+#
+# make extcoff = Convert ELF to AVR Extended COFF.
+#
+# make program = Download the hex file to the device.
+# Please customize your programmer settings(PROGRAM_CMD)
+#
+# make teensy = Download the hex file to the device, using teensy_loader_cli.
+# (must have teensy_loader_cli installed).
+#
+# make dfu = Download the hex file to the device, using dfu-programmer (must
+# have dfu-programmer installed).
+#
+# make flip = Download the hex file to the device, using Atmel FLIP (must
+# have Atmel FLIP installed).
+#
+# make dfu-ee = Download the eeprom file to the device, using dfu-programmer
+# (must have dfu-programmer installed).
+#
+# make flip-ee = Download the eeprom file to the device, using Atmel FLIP
+# (must have Atmel FLIP installed).
+#
+# make debug = Start either simulavr or avarice as specified for debugging,
+# with avr-gdb or avr-insight as the front end for debugging.
+#
+# make filename.s = Just compile filename.c into the assembler code only.
+#
+# make filename.i = Create a preprocessed source file for use in submitting
+# bug reports to the GCC project.
+#
+# To rebuild project do "make clean" then "make all".
+#----------------------------------------------------------------------------
+
+# Build Options
+# change to "no" to disable the options, or define them in the makefile.mk in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = no # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif
diff --git a/keyboards/planck/keymaps/ab/keyboard-layout.json b/keyboards/planck/keymaps/ab/keyboard-layout.json
new file mode 100644
index 000000000..4e631a348
--- /dev/null
+++ b/keyboards/planck/keymaps/ab/keyboard-layout.json
@@ -0,0 +1,185 @@
+[
+ {
+ "name": "AB's Practical Keymap for Planck",
+ "author": "Anand Babu Periasamy"
+ },
+ [
+ {
+ "fa": [
+ 2,
+ 2,
+ 0,
+ 2
+ ]
+ },
+ "F1\n1\n\n!\n\n\n\n\n\nTab",
+ "F2\n2\n\n@\n\n\n\n\n\nQ",
+ "F3\n3\n\n#\n\n\n\n\n\nW",
+ "F4\n4\n\n$\n\n\n\n\n\nE",
+ "F5\n5\n\n%\n\n\n\n\n\nR",
+ "F6\n6\n\n^\n\n\n\n\n\nT",
+ "F7\n7\n\n&\n\n\n\n\n\nY",
+ "F8\n8\n\n*\n\n\n\n\n\nU",
+ "F9\n9\n\n(\n\n\n\n\n\nI",
+ "F10\n0\n\n)\n\n\n\n\n\nO",
+ "F11\n-\n\n_\n\n\n\n\n\nP",
+ "F12\n=\n\n+\n\n\n\n\n\n<i class=\"fa fa-chevron-circle-left\" aria-hidden=\"true\"></i>"
+ ],
+ [
+ {
+ "a": 7,
+ "f": 3
+ },
+ "Ctrl",
+ {
+ "f": 3
+ },
+ "A",
+ {
+ "f": 3
+ },
+ "S",
+ {
+ "f": 3
+ },
+ "D",
+ {
+ "c": "#c4bcbc",
+ "a": 4,
+ "f": 3
+ },
+ "\n(\n\n\n\n\n\n\n\nF",
+ {
+ "c": "#cccccc",
+ "f": 3
+ },
+ "\n)\n\n\n\n\n\n\n\nG",
+ {
+ "f": 3
+ },
+ "\n{\n\n\n\n\n\n\n\nH",
+ {
+ "c": "#c4bcbc",
+ "f": 3
+ },
+ "\n}\n\n\n\n\n\n\n\nJ",
+ {
+ "c": "#cccccc",
+ "a": 7,
+ "f": 3
+ },
+ "K",
+ {
+ "f": 3
+ },
+ "L",
+ {
+ "a": 6,
+ "f": 3
+ },
+ ";\n\n:",
+ {
+ "a": 7,
+ "f": 3
+ },
+ "Enter"
+ ],
+ [
+ {
+ "f": 3
+ },
+ "Shift",
+ {
+ "f": 3
+ },
+ "Z",
+ {
+ "f": 3
+ },
+ "X",
+ {
+ "f": 3
+ },
+ "C",
+ {
+ "a": 4,
+ "fa": [
+ 0,
+ 2,
+ 0,
+ 2,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 2
+ ]
+ },
+ "\\\n[\n\n\n\n\n\n\n\nV",
+ "|\n]\n\n\n\n\n\n\n\nB",
+ "`\n'\n\n\n\n\n\n\n\nN",
+ "~\n\"\n\n\n\n\n\n\n\nM",
+ {
+ "a": 6
+ },
+ ",\n\n<",
+ ".\n\n>",
+ "/\n\n?",
+ {
+ "a": 7
+ },
+ "Shift\n\n\n\nEnter"
+ ],
+ [
+ {
+ "a": 4,
+ "fa": [
+ 2,
+ 2
+ ]
+ },
+ "<i class='fa fa-download'></i>\n<i class='fa fa-lightbulb-o'></i>\n\n\n\n\n\n\n\nCtrl",
+ "\n<i class=\"fa fa-search\" aria-hidden=\"true\"></i>\n\n\n\n\n\n\n\nEsc",
+ "\n<i class=\"fa fa-search-minus\" aria-hidden=\"true\"></i>\n\n\n\n\n\n\n\n<i class='fa fa-linux'></i>",
+ "\n<i class=\"fa fa-search-plus\" aria-hidden=\"true\"></i>\n\n\n\n\n\n\n\nAlt",
+ {
+ "a": 7,
+ "f": 3
+ },
+ "<i class='fa fa-sort-down'></i>",
+ {
+ "a": 4,
+ "fa": [
+ 1,
+ 1
+ ],
+ "w": 2
+ },
+ "PgUp\nPgDn\n\n\n\n\n\n\n\nSpace",
+ {
+ "a": 7,
+ "f": 3
+ },
+ "<i class='fa fa-sort-up'></i>",
+ {
+ "a": 4,
+ "fa": [
+ 2
+ ]
+ },
+ "<i class=\"fa fa-undo\" aria-hidden=\"true\"></i>\n\n\n\n\n\n\n\n\n<i class=\"fa fa-long-arrow-left\" aria-hidden=\"true\"></i>",
+ {
+ "f": 3
+ },
+ "<i class='fa fa-volume-down'></i>\n\n\n\n\n\n\n\n\n<i class=\"fa fa-long-arrow-down\" aria-hidden=\"true\"></i>",
+ {
+ "f": 3
+ },
+ "<i class='fa fa-volume-up'></i>\n\n\n\n\n\n\n\n\n<i class=\"fa fa-long-arrow-up\" aria-hidden=\"true\"></i>",
+ {
+ "f": 3
+ },
+ "<i class='fa fa-volume-off'></i>\n\n\n\n\n\n\n\n\n<i class=\"fa fa-long-arrow-right\" aria-hidden=\"true\"></i>"
+ ]
+] \ No newline at end of file
diff --git a/keyboards/planck/keymaps/ab/keyboard-layout.png b/keyboards/planck/keymaps/ab/keyboard-layout.png
new file mode 100644
index 000000000..dcdbb726d
--- /dev/null
+++ b/keyboards/planck/keymaps/ab/keyboard-layout.png
Binary files differ
diff --git a/keyboards/planck/keymaps/ab/keyboard-photo.jpg b/keyboards/planck/keymaps/ab/keyboard-photo.jpg
new file mode 100644
index 000000000..358cb6bca
--- /dev/null
+++ b/keyboards/planck/keymaps/ab/keyboard-photo.jpg
Binary files differ
diff --git a/keyboards/planck/keymaps/ab/keymap.c b/keyboards/planck/keymaps/ab/keymap.c
new file mode 100644
index 000000000..8e1d28a65
--- /dev/null
+++ b/keyboards/planck/keymaps/ab/keymap.c
@@ -0,0 +1,132 @@
+// This is the canonical layout file for the Quantum project. If you want to add another keyboard,
+// this is the style you want to emulate.
+
+#include "planck.h"
+#include "action_layer.h"
+#include "eeconfig.h"
+#ifdef BACKLIGHT_ENABLE
+ #include "backlight.h"
+#endif
+
+extern keymap_config_t keymap_config;
+
+// Symbolic names for macro IDs.
+#define _QWERTY 0 // QUERTY layer
+#define _LOWER 1 // Lower layer
+#define _RAISE 2 // Raise layer
+#define _CUSTOM 3 // Custom layer (LOWER + RAISE)
+#define _BL 4 // Backlight
+#define _MOB 5 // Mobile#
+#define _CUS1 6 // Custom macro 1
+#define _CUS2 7 // Custom macro 2
+
+// Macro shortcuts.
+#define QWERTY M(_LOWER)
+#define LOWER M(_LOWER)
+#define RAISE M(_RAISE)
+#define CUSTOM M(_CUSTOM)
+#define BL M(_BL)
+#define MOB M(_MOB)
+#define CUS1 M(_CUS1)
+#define CUS2 M(_CUS2)
+
+// Func macro definitions.
+#define LWR_PGDN FUNC(0) // Tap for PgDn, hold for LOWER
+#define RSE_PGUP FUNC(1) // Tap for PgUp, hold for RAISE
+#define CTL_CAPS FUNC(2) // Tap for Caps, hold for Ctrl (DOESN'T SEEM TO WORK)
+#define SFT_ENT FUNC(3) // Tap for Enter, hold for Shift
+#define ZM_NRM FUNC(4) // Zoom normal
+#define ZM_IN FUNC(5) // Zoom out
+#define ZM_OUT FUNC(6) // Zoom in
+#define EM_UNDO FUNC(7) // Emacs Undo
+
+// Enable these functions using FUNC(n) macro.
+const uint16_t PROGMEM fn_actions[] = {
+ [0] = ACTION_LAYER_TAP_KEY(_LOWER, KC_PGDN),
+ [1] = ACTION_LAYER_TAP_KEY(_RAISE, KC_PGUP),
+ [2] = ACTION_MODS_TAP_KEY(MOD_LCTL, KC_CAPS),
+ [3] = ACTION_MODS_TAP_KEY(MOD_RSFT, KC_ENT),
+ [4] = ACTION_MODS_KEY(MOD_LCTL, KC_0),
+ [5] = ACTION_MODS_KEY(MOD_LCTL, KC_MINS),
+ [6] = ACTION_MODS_KEY(MOD_LCTL, KC_PLUS),
+ [7] = ACTION_MODS_KEY(MOD_LCTL, KC_UNDS),
+ };
+
+// This config can be found at Keyboard layout editor site: http://goo.gl/zjXL2l
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[_QWERTY] = { /* QWERTY */
+ {KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC},
+ {KC_LCTL, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_ENT},
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, SFT_ENT},
+ {KC_LCTL, KC_ESC, KC_LGUI, KC_LALT, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+[_LOWER] = { /* LOWER */
+ {KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_LPRN, KC_RPRN, KC_LCBR, KC_RCBR, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_LBRC, KC_RBRC, KC_QUOT, KC_DQT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS},
+ {BL, ZM_NRM, ZM_IN, ZM_OUT, KC_TRNS, KC_PGDN, KC_PGDN, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS}
+},
+[_RAISE] = { /* RAISE */
+ {KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_LCBR, KC_LCBR, KC_BSLS, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_BSLS, KC_PIPE, KC_GRV, KC_TILD, KC_LBRC, KC_LBRC, KC_TRNS, KC_TRNS},
+ {RESET, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PGUP, KC_PGUP, KC_TRNS, EM_UNDO, KC_VOLD, KC_VOLU, KC_MUTE}
+},
+[_CUSTOM] = { /* CUSTOM */
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, MOB, KC_TRNS, CUS1, CUS2, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS}
+}
+};
+
+// Set a layer persistantly.
+void persistant_default_layer_set(uint16_t default_layer) {
+ eeconfig_update_default_layer(default_layer);
+ default_layer_set(default_layer);
+}
+
+// Macro actions for each corresponding ID.
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ switch(id) {
+ case _RAISE: // Raised layer.
+ if (record->event.pressed) {
+ layer_on(_RAISE);
+ update_tri_layer(_LOWER, _RAISE, _CUSTOM);
+ } else {
+ layer_off(_RAISE);
+ update_tri_layer(_LOWER, _RAISE, _CUSTOM);
+ }
+ break;
+ case _LOWER: // Lowered layer.
+ if (record->event.pressed) {
+ layer_on(_LOWER);
+ update_tri_layer(_LOWER, _RAISE, _CUSTOM);
+ } else {
+ layer_off(_LOWER);
+ update_tri_layer(_LOWER, _RAISE, _CUSTOM);
+ }
+ break;
+ case _BL: // Backlight
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+#ifdef BACKLIGHT_ENABLE
+ backlight_step();
+#endif
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ case _MOB: // Your mobile# here.
+ return MACRODOWN(T(1), T(2), T(3), T(MINS),
+ T(1), T(2), T(3), T(MINS),
+ T(1), T(2), T(3), T(4),
+ END);
+ case _CUS1: // Your custom macro 1
+ return MACRODOWN(T(E), T(M), T(A), T(C), T(S), T(SPC), END);
+ case _CUS2: // Your custom macro 2
+ return MACRODOWN(T(L), T(S), T(SPC), T(MINS), T(L), T(ENT), END);
+ };
+ return MACRO_NONE;
+}
diff --git a/keyboards/planck/keymaps/ab/readme.md b/keyboards/planck/keymaps/ab/readme.md
new file mode 100644
index 000000000..d6280f074
--- /dev/null
+++ b/keyboards/planck/keymaps/ab/readme.md
@@ -0,0 +1,18 @@
+# Practical keymap for Planck Ortholinear 40% Mechanical Keyboard
+A practical keymap that emulates standard QWERTY keyboard for Planck. Once you get comfortable with this keymap, you may fork and customize it for your own needs.
+
+![Layout](keyboard-layout.png "Practical Keymap")
+![Photo](keyboard-photo.jpg "Planck Keyboard")
+
+* Online keyboard layout editor: http://goo.gl/mlLAFZ
+
+# Programming Instructions:
+Enter into programming mode and run the following command.
+```
+$ sudo KEYMAP=ab make dfu
+```
+# Notes
+* Simultaneous RAISE+LOWER enters CUSTOM layer. You may add your own macros and custom keys here.
+* RAISE and LOWER also acts as PgUp and PgDn when tapped.
+* [CapsLock] also acts as [Ctrl] key when you press and hold. It is convenient for GNU Emacs users.
+* Bracket keys are placed in the center of the keyboard for programmer's convenience.
diff --git a/keyboards/planck/keymaps/alexey/Makefile b/keyboards/planck/keymaps/alexey/Makefile
new file mode 100644
index 000000000..581e08cd0
--- /dev/null
+++ b/keyboards/planck/keymaps/alexey/Makefile
@@ -0,0 +1,25 @@
+
+
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = yes # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/planck/keymaps/alexey/keymap.c b/keyboards/planck/keymaps/alexey/keymap.c
new file mode 100644
index 000000000..f3cdf3d6e
--- /dev/null
+++ b/keyboards/planck/keymaps/alexey/keymap.c
@@ -0,0 +1,51 @@
+#include "keymap.h"
+#include "planck.h"
+#include "backlight.h"
+
+#define _QW 0
+#define _LW 1
+#define _RS 2
+
+// This layout tries to imitate the Atreus keyboard
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[_QW] = { /* Qwerty */
+ {KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC},
+ {KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, MO(_LW)},
+ {KC_TRNS, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_TRNS},
+ {M(0), KC_LGUI, KC_LALT, KC_LCTL, KC_LSFT, KC_SPC, KC_SPC, MO(_RS), KC_MINS, KC_QUOT, KC_ENT, KC_TRNS}
+},
+[_RS] = { /* RAISE */
+ {KC_TRNS, KC_EXLM, KC_AT, KC_LCBR, KC_RCBR, KC_PIPE, KC_PGUP, KC_7, KC_8, KC_9, KC_ASTR, KC_TRNS},
+ {KC_TRNS, KC_HASH, KC_DLR, KC_LPRN, KC_RPRN, KC_GRV, KC_PGDN, KC_4, KC_5, KC_6, KC_PLUS, KC_TRNS},
+ {KC_TRNS, KC_PERC, KC_CIRC, KC_LBRC, KC_RBRC, KC_TILD, KC_AMPR, KC_1, KC_2, KC_3, KC_BSLS, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_INS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_0, KC_EQL, KC_TRNS}
+},
+[_LW] = { /* LOWER */
+ {KC_TRNS, KC_INS, KC_HOME, KC_UP, KC_END, KC_PGUP, KC_TRNS, KC_F7, KC_F8, KC_F9, KC_F10, KC_TRNS},
+ {KC_TRNS, KC_DELETE, KC_LEFT, KC_DOWN, KC_RGHT, KC_PGDN, KC_TRNS, KC_F4, KC_F5, KC_F6, KC_F11, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F12, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_VOLD, KC_VOLU, KC_MNXT, KC_MPLY, KC_TRNS}
+}
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ backlight_step();
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
diff --git a/keyboards/planck/keymaps/angerthosenear/Makefile b/keyboards/planck/keymaps/angerthosenear/Makefile
new file mode 100644
index 000000000..581e08cd0
--- /dev/null
+++ b/keyboards/planck/keymaps/angerthosenear/Makefile
@@ -0,0 +1,25 @@
+
+
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = yes # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/planck/keymaps/angerthosenear/keymap.c b/keyboards/planck/keymaps/angerthosenear/keymap.c
new file mode 100644
index 000000000..aa75a6771
--- /dev/null
+++ b/keyboards/planck/keymaps/angerthosenear/keymap.c
@@ -0,0 +1,39 @@
+#include "keymap.h"
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[0] = { /* Qwerty */
+ {KC_ESC, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC},
+ {KC_TAB, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_ENT},
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_QUOT},
+ {KC_LCTL, KC_LGUI, KC_LALT, BL_STEP, FUNC(2), KC_SPC, KC_SPC, FUNC(1), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+ // Space is repeated to accommodate for both spacebar wiring positions
+},
+[1] = { /* WASD + NumPad */
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_P7, KC_P8, KC_P9, KC_PSLS, KC_PMNS, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_P4, KC_P5, KC_P6, KC_PAST, KC_PPLS, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_P1, KC_P2, KC_P3, KC_PDOT, KC_PENT, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, FUNC(2), KC_SPC, KC_P0, FUNC(1), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS}
+},
+[2] = { /* RAISE */
+ {KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_TRNS},
+ {KC_TRNS, FUNC(3), FUNC(4), LSFT(RSFT(KC_PAUSE)), KC_TRNS, KC_TRNS, KC_TRNS, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS},
+ {KC_TRNS, KC_F11, KC_F12, KC_F13, KC_F14, KC_F15, KC_F16, KC_F17, KC_F18, KC_F19, KC_F20, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPRV, FUNC(1), KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
+},
+[3] = { /* LOWER */
+ {S(KC_GRV), S(KC_1), S(KC_2), S(KC_3), S(KC_4), S(KC_5), S(KC_6), S(KC_7), S(KC_8), S(KC_9), S(KC_0), KC_DEL},
+ {KC_TRNS, FUNC(3), FUNC(4), LSFT(RSFT(KC_PAUSE)), KC_TRNS, KC_TRNS, KC_TRNS, S(KC_MINS), S(KC_EQL), S(KC_LBRC), S(KC_RBRC), S(KC_BSLS)},
+ {KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, FUNC(2), KC_TRNS, KC_TRNS, KC_TRNS, KC_HOME, KC_PGDN, KC_PGUP, KC_END}
+}
+};
+
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_MOMENTARY(2), // to RAISE
+ [2] = ACTION_LAYER_MOMENTARY(3), // to LOWER
+
+ [3] = ACTION_DEFAULT_LAYER_SET(0),
+ [4] = ACTION_DEFAULT_LAYER_SET(1),
+
+};
diff --git a/keyboards/planck/keymaps/austin/Makefile b/keyboards/planck/keymaps/austin/Makefile
new file mode 100644
index 000000000..581e08cd0
--- /dev/null
+++ b/keyboards/planck/keymaps/austin/Makefile
@@ -0,0 +1,25 @@
+
+
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = yes # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/planck/keymaps/austin/keymap.c b/keyboards/planck/keymaps/austin/keymap.c
new file mode 100644
index 000000000..40f808654
--- /dev/null
+++ b/keyboards/planck/keymaps/austin/keymap.c
@@ -0,0 +1,39 @@
+#include "keymap.h"
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[0] = { /* Qwerty */
+ {KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC},
+ {KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT},
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT},
+ {BL_STEP, KC_LGUI, KC_LALT, KC_LCTL, FUNC(2), KC_SPC, KC_SPC, FUNC(1), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+ // Space is repeated to accommadate for both spacebar wiring positions
+},
+[1] = { /* Colemak */
+ {KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_BSPC},
+ {KC_ESC, KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT},
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_K, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT},
+ {KC_FN3, KC_LGUI, KC_LALT, KC_LCTL, FUNC(2), KC_SPC, KC_SPC, FUNC(1), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+[2] = { /* RAISE */
+ {KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC},
+ {KC_TRNS, FUNC(3), FUNC(4), LSFT(RSFT(KC_PAUSE)), KC_TRNS, KC_TRNS, KC_TRNS, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS},
+ {KC_TRNS, KC_F11, KC_F12, KC_F13, KC_F14, KC_F15, KC_F16, KC_F17, KC_F18, KC_F19, KC_F20, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, FUNC(1), KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
+},
+[3] = { /* LOWER */
+ {S(KC_GRV), S(KC_1), S(KC_2), S(KC_3), S(KC_4), S(KC_5), S(KC_6), S(KC_7), S(KC_8), S(KC_9), S(KC_0), KC_BSPC},
+ {KC_TRNS, FUNC(3), FUNC(4), LSFT(RSFT(KC_PAUSE)), KC_TRNS, KC_TRNS, KC_TRNS, S(KC_MINS), S(KC_EQL), S(KC_LBRC), S(KC_RBRC), S(KC_BSLS)},
+ {KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, FUNC(2), KC_TRNS, KC_TRNS, KC_TRNS, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
+}
+};
+
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_MOMENTARY(2), // to RAISE
+ [2] = ACTION_LAYER_MOMENTARY(3), // to LOWER
+
+ [3] = ACTION_DEFAULT_LAYER_SET(0),
+ [4] = ACTION_DEFAULT_LAYER_SET(1),
+
+}; \ No newline at end of file
diff --git a/keyboards/planck/keymaps/basic/Makefile b/keyboards/planck/keymaps/basic/Makefile
new file mode 100644
index 000000000..0c0632da0
--- /dev/null
+++ b/keyboards/planck/keymaps/basic/Makefile
@@ -0,0 +1,25 @@
+
+
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = no # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = no # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/planck/keymaps/basic/keymap.c b/keyboards/planck/keymaps/basic/keymap.c
new file mode 100644
index 000000000..36a066e91
--- /dev/null
+++ b/keyboards/planck/keymaps/basic/keymap.c
@@ -0,0 +1,94 @@
+#include "planck.h"
+
+// Each layer gets a name for readability, which is then used in the keymap matrix below.
+// The underscores don't mean anything - you can have a layer called STUFF or any other name.
+// Layer names don't all need to be of the same length, obviously, and you can also skip them
+// entirely and just use numbers.
+
+// Fillers to make layering more clear
+#define _______ KC_TRNS
+#define XXXXXXX KC_NO
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+
+/* Qwerty
+ * ,-----------------------------------------------------------------------------------.
+ * | Tab | Q | W | E | R | T | Y | U | I | O | P | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc | A | S | D | F | G | H | J | K | L | ; | " |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift| Z | X | C | V | B | N | M | , | . | / |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Brite| Ctrl | Alt | GUI |Lower | Space |Raise | Left | Down | Up |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+[0] = {
+ {KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC},
+ {KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT},
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT },
+ {KC_RSFT, KC_LCTL, KC_LALT, KC_LGUI, M(1), KC_SPC, KC_SPC, M(2), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+
+/* Lower
+ * ,-----------------------------------------------------------------------------------.
+ * | ~ | ! | @ | # | $ | % | ^ | & | * | ( | ) | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Del | F1 | F2 | F3 | F4 | F5 | F6 | _ | + | { | } | | |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | | F7 | F8 | F9 | F10 | F11 | F12 |ISO ~ |ISO | | | |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * |Reset | | | | | | | Next | Vol- | Vol+ | Play |
+ * `-----------------------------------------------------------------------------------'
+ */
+[1] = {
+ {KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_BSPC},
+ {KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE},
+ {_______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12,S(KC_NUHS),S(KC_NUBS),_______, _______, _______},
+ {RESET, _______, _______, _______, _______, _______, _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
+},
+
+/* Raise
+ * ,-----------------------------------------------------------------------------------.
+ * | ` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Del | F1 | F2 | F3 | F4 | F5 | F6 | - | = | [ | ] | \ |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | | F7 | F8 | F9 | F10 | F11 | F12 |ISO # |ISO / | | |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * |Reset | | | | | | | Next | Vol- | Vol+ | Play |
+ * `-----------------------------------------------------------------------------------'
+ */
+[2] = {
+ {KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC},
+ {KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS},
+ {_______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_NUHS, KC_NUBS, _______, _______, _______},
+ {RESET, _______, _______, _______, _______, _______, _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
+},
+
+
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ switch(id) {
+ case 1:
+ if (record->event.pressed) {
+ layer_on(1);
+ } else {
+ layer_off(1);
+ }
+ break;
+ case 2:
+ if (record->event.pressed) {
+ layer_on(2);
+ } else {
+ layer_off(2);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
diff --git a/keyboards/planck/keymaps/basic/readme.md b/keyboards/planck/keymaps/basic/readme.md
new file mode 100644
index 000000000..3a4824b5b
--- /dev/null
+++ b/keyboards/planck/keymaps/basic/readme.md
@@ -0,0 +1,2 @@
+# A more basic Planck Layout for copying
+
diff --git a/keyboards/planck/keymaps/bone2planck/Makefile b/keyboards/planck/keymaps/bone2planck/Makefile
new file mode 100644
index 000000000..581e08cd0
--- /dev/null
+++ b/keyboards/planck/keymaps/bone2planck/Makefile
@@ -0,0 +1,25 @@
+
+
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = yes # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/planck/keymaps/bone2planck/keymap.c b/keyboards/planck/keymaps/bone2planck/keymap.c
new file mode 100644
index 000000000..f40b08685
--- /dev/null
+++ b/keyboards/planck/keymaps/bone2planck/keymap.c
@@ -0,0 +1,112 @@
+
+#include "planck.h"
+#ifdef BACKLIGHT_ENABLE
+#include "backlight.h"
+#endif
+#include "keymap_german.h"
+
+/* This Layout tries to emulate the Bone2 Variant of Neo2, and is intended to be used with a German QWERTZ Softwarelayout.
+ It has Umlauts and "ß" as it is optimized for a mix of German & English.
+ My favourite features are the placement of the special characters often used for programming right on the home row
+ and the number & navigation block combo, so you never have to move your hands from their home position.
+
+ Bone2 wiki page: http://wiki.neo-layout.org/wiki/Bone
+*/
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+
+ /* Bone2
+ * ,-----------------------------------------------------------------------------------.
+ * | Q | J | D | U | A | X | P | H | L | M | W | ẞ |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | M1 | C | T | I | E | O | B | N | R | S | G | M1 |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift| F | V | Ü | Ä | Ö | Y | Z | , | . | K |Shift |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Ctrl | GUI | Alt | M3 | M2 | Space | M2 | M3 | Esc | Tab |Enter |
+ * `-----------------------------------------------------------------------------------'
+ */
+ [0] = {
+ { DE_Q, DE_J, DE_D, DE_U, DE_A, DE_X, DE_P, DE_H, DE_L, DE_M, DE_W, DE_SS },
+ { MO(1), DE_C, DE_T, DE_I, DE_E, DE_O, DE_B, DE_N, DE_R, DE_S, DE_G, MO(1) },
+ { DE_S, DE_F, DE_V, DE_UE, DE_AE, DE_OE, DE_Y, DE_Z, DE_COMM, DE_DOT, DE_K, DE_S },
+ { KC_LCTL, KC_LGUI, KC_LALT, MO(3), MO(2), KC_SPC, KC_SPC, MO(2), MO(3), KC_ESC, KC_TAB, KC_ENT }
+ },
+
+ /* M1 Special Characters
+ * ,-----------------------------------------------------------------------------------.
+ * | ° | @ | _ | [ | ] | ^ | ! | < | > | = | & | |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | M1 | \ | / | { | } | * | ? | ( | ) | - | : | M1 |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | | # | $ | | | ~ | € | + | % | " | ' | ; | |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Ctrl | GUI | Alt | M3 | M2 | Space | M2 | M3 | Esc | Tab |Enter |
+ * `-----------------------------------------------------------------------------------'
+ */
+ [1] = {
+ { DE_RING, DE_AT, DE_UNDS, DE_LBRC, DE_RBRC, DE_CIRC, DE_EXLM, DE_LESS, DE_MORE, DE_EQL, DE_AMPR, KC_NO },
+ { KC_TRNS, DE_BSLS, DE_SLSH, DE_LCBR, DE_RCBR, DE_ASTR, DE_QST, DE_LPRN, DE_RPRN, DE_MINS, DE_COLN, KC_TRNS },
+ { KC_NO , DE_HASH, DE_DLR, DE_PIPE, DE_TILD, DE_EURO, DE_PLUS, DE_PERC, DE_DQOT, DE_QUOT, DE_SCLN, KC_NO },
+ { KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS }
+ },
+
+ /* Navigation & Number Blocks
+ * ,-----------------------------------------------------------------------------------.
+ * | | PgUp | Bksp | Up | DEL | PgDn | | 7 | 8 | 9 | | |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | | Home | Lft | Down | Right| End | . | 4 | 5 | 6 | , | |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift| | Tab | Ins | Enter| | 0 | 1 | 2 | 3 | ; |Shift |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Ctrl | GUI | Alt | M3 | M2 | Space | M2 | M3 | Esc | Tab |Enter |
+ * `-----------------------------------------------------------------------------------'
+ */
+ [2] = {
+ { KC_NO, KC_PGUP, KC_BSPC, KC_UP, KC_DEL, KC_PGDN, KC_NO, DE_7, DE_8, DE_9, KC_NO, KC_NO },
+ { KC_NO, KC_HOME, KC_LEFT, KC_DOWN, KC_RGHT, KC_END, DE_DOT, DE_4, DE_5, DE_6, DE_COMM, KC_NO },
+ { DE_S, KC_NO, KC_TAB, KC_INS, KC_ENT, KC_NO, KC_0, DE_1, DE_2, DE_3, DE_SCLN, DE_S },
+ { KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS }
+ },
+
+ /* Function & Media Keys
+ * ,-----------------------------------------------------------------------------------.
+ * | | | Print|Scroll|Pause | | | F7 | F8 | F9 | F12 | |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | | | Mute | Vol- | Vol+ | | ³ | F4 | F5 | F6 | F11 | |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift| | Prev | Play | Next | | ² | F1 | F2 | F3 | F10 |Shift |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Ctrl | GUI | Alt | M3 | | Space | | M3 | Esc | Tab |Enter |
+ * `-----------------------------------------------------------------------------------'
+ */
+ [3] = {
+ { KC_NO, KC_NO, KC_PSCR, KC_SLCK, KC_PAUS, KC_NO, KC_NO, KC_F7, KC_F8, KC_F9, KC_F12, KC_NO },
+ { KC_NO, KC_NO, KC_MUTE, KC_VOLD, KC_VOLU, KC_NO, DE_SQ3, KC_F4, KC_F5, KC_F6, KC_F11, KC_NO },
+ { KC_TRNS, KC_NO, KC_MPRV, KC_MPLY, KC_MNXT, KC_NO, DE_SQ2, KC_F1, KC_F2, KC_F3, KC_F10, KC_TRNS},
+ { KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_NO, KC_TRNS, KC_TRNS, KC_NO, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS}
+ }
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch (id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+#ifdef BACKLIGHT_ENABLE
+ backlight_step();
+#endif
+ }
+ else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
diff --git a/keyboards/planck/keymaps/brandon/Makefile b/keyboards/planck/keymaps/brandon/Makefile
new file mode 100644
index 000000000..581e08cd0
--- /dev/null
+++ b/keyboards/planck/keymaps/brandon/Makefile
@@ -0,0 +1,25 @@
+
+
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = yes # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/planck/keymaps/brandon/keymap.c b/keyboards/planck/keymaps/brandon/keymap.c
new file mode 100644
index 000000000..2b89f86db
--- /dev/null
+++ b/keyboards/planck/keymaps/brandon/keymap.c
@@ -0,0 +1,134 @@
+// This is the canonical layout file for the Quantum project. If you want to add another keyboard,
+// this is the style you want to emulate.
+
+#include "planck.h"
+#ifdef BACKLIGHT_ENABLE
+ #include "backlight.h"
+#endif
+
+// Each layer gets a name for readability, which is then used in the keymap matrix below.
+// The underscores don't mean anything - you can have a layer called STUFF or any other name.
+// Layer names don't all need to be of the same length, obviously, and you can also skip them
+// entirely and just use numbers.
+#define _QW 0
+#define _CM 1
+#define _TK 2
+#define _LW 3
+#define _RS 4
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[_QW] = { /* Qwerty */
+/* MIT Layout (QWERTY layer)
+ *
+ * ,-----------------------------------------------------------------------.
+ * | esc | q | w | e | r | t | y | u | i | o | p | bspc|
+ * |-----------------------------------------------------------------------|
+ * | tab | a | s | d | f | g | h | j | k | l | ; | ' |
+ * |-----------------------------------------------------------------------|
+ * |shift| z | x | c | v | b | n | m | , | . | / |enter|
+ * |-----------------------------------------------------------------------|
+ * | ctl | alt | win | TK |lower| spc |raise|left |down | up |right|
+ * `-----------------------------------------------------------------------'
+ */
+ {KC_ESC, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC},
+ {KC_TAB, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT},
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, MT(MOD_LSFT, KC_ENT) },
+ {KC_LCTL, KC_LALT, KC_LGUI, TG(_TK), MO(_LW), KC_SPC, KC_SPC, MO(_RS), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+[_CM] = { /* Colemak */
+/* MIT Layout (Colemak layer)
+ *
+ * ,-----------------------------------------------------------------------.
+ * | esc | q | w | f | p | g | j | l | u | y | ; | bspc|
+ * |-----------------------------------------------------------------------|
+ * | tab | a | r | s | t | d | h | n | e | i | o | ' |
+ * |-----------------------------------------------------------------------|
+ * |shift| z | x | c | v | b | k | m | , | . | / |enter|
+ * |-----------------------------------------------------------------------|
+ * | ctl | alt | win | TK |lower| spc |raise|left |down | up |right|
+ * `-----------------------------------------------------------------------'
+ */
+ {KC_ESC, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_BSPC},
+ {KC_TAB, KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT},
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_K, KC_M, KC_COMM, KC_DOT, KC_SLSH, MT(MOD_LSFT, KC_ENT)},
+ {KC_LCTL, KC_LALT, KC_LGUI, TG(_TK), MO(_LW), KC_SPC, KC_SPC, MO(_RS), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+[_RS] = { /* RAISE */
+/* MIT Layout (RAISE layer)
+ *
+ * ,-----------------------------------------------------------------------.
+ * | ` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | bspc|
+ * |-----------------------------------------------------------------------|
+ * | tab | F1 | F2 | F3 | F4 | F5 | F6 | - | = | [ | ] | \ |
+ * |-----------------------------------------------------------------------|
+ * |shift| F7 | F8 | F9 | F10 | F11 | F12 | QW | CM | BL | RST |enter|
+ * |-----------------------------------------------------------------------|
+ * | ctl | alt | win | del |lower| spc |raise|next |vold |volu |PLAY |
+ * `-----------------------------------------------------------------------'
+ */
+
+ {KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC},
+ {KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS},
+ {KC_TRNS, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, DF(_QW), DF(_CM), M(0), RESET, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
+},
+[_LW] = { /* LOWER */
+/* MIT Layout (Colemak layer)
+ *
+ * ,-----------------------------------------------------------------------.
+ * | esc | q | w | f | p | g | j | l | u | y | ; | bspc|
+ * |-----------------------------------------------------------------------|
+ * | tab | F1 | F2 | F3 | F4 | F5 | F6 | _ | + | { | } | | |
+ * |-----------------------------------------------------------------------|
+ * |shift| F7 | F8 | F9 | F10 | F11 | F12 | QW | CM | BL | RST |enter|
+ * |-----------------------------------------------------------------------|
+ * | ctl | alt | win | TK |lower| spc |raise|next |vold |volu |PLAY |
+ * `-----------------------------------------------------------------------'
+ */
+ {KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_BSPC},
+ {KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE},
+ {KC_TRNS, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, DF(_QW), DF(_CM), M(0), RESET, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
+},
+[_TK] = { /* Ten Key*/
+/* MIT Layout (Ten Key layer)
+ *
+ * ,-----------------------------------------------------------------------.
+ * | esc | F9 | F10 | F11 | F12 | PGUP| % | / | 7 | 8 | 9 | bspc|
+ * |-----------------------------------------------------------------------|
+ * | tab | F5 | F6 | F7 | F8 | PGDN| HOME| * | 4 | 5 | 6 | \ |
+ * |-----------------------------------------------------------------------|
+ * |shift| F1 | F2 | F3 | F4 | DEL | END | 0 | 1 | 2 | 3 |enter|
+ * |-----------------------------------------------------------------------|
+ * | ctl | alt | win | TK |lower| spc |raise|left |down | up |right|
+ * `-----------------------------------------------------------------------'
+ */
+ {KC_TRNS, KC_F9, KC_F10, KC_F11, KC_F12, KC_PGUP, KC_PERC, KC_SLSH, KC_7, KC_8, KC_9, KC_BSPC},
+ {KC_TRNS, KC_F5, KC_F6, KC_F7, KC_F8, KC_PGDN, KC_HOME, KC_ASTR, KC_4, KC_5, KC_6, KC_PIPE},
+ {KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_DEL, KC_END, KC_0, KC_1, KC_2, KC_3, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+}
+
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ #ifdef BACKLIGHT_ENABLE
+ backlight_step();
+ #endif
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
diff --git a/keyboards/planck/keymaps/cbbrowne/Makefile b/keyboards/planck/keymaps/cbbrowne/Makefile
new file mode 100644
index 000000000..581e08cd0
--- /dev/null
+++ b/keyboards/planck/keymaps/cbbrowne/Makefile
@@ -0,0 +1,25 @@
+
+
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = yes # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/planck/keymaps/cbbrowne/config.h b/keyboards/planck/keymaps/cbbrowne/config.h
new file mode 100644
index 000000000..2d3df59bd
--- /dev/null
+++ b/keyboards/planck/keymaps/cbbrowne/config.h
@@ -0,0 +1,15 @@
+#ifndef CONFIG_USER_H
+#define CONFIG_USER_H
+
+#include "../../config.h"
+
+/* cbbrowne user configuration */
+
+#define randadd 53
+#define randmul 181
+#define randmod 167
+
+#endif
+
+
+
diff --git a/keyboards/planck/keymaps/cbbrowne/keymap.c b/keyboards/planck/keymaps/cbbrowne/keymap.c
new file mode 100644
index 000000000..14a5be170
--- /dev/null
+++ b/keyboards/planck/keymaps/cbbrowne/keymap.c
@@ -0,0 +1,173 @@
+#include "planck.h"
+#ifdef BACKLIGHT_ENABLE
+ #include "backlight.h"
+#endif
+#include "config.h"
+#include "quantum.h"
+
+/* Each layer is given a name to aid in readability, which is then
+ used in the keymap matrix below. The underscores do not denote
+ anything - you can have a layer called STUFF or any other name.
+
+ Layer names don't all need to be of the same length, obviously, and
+ you could also skip them entirely and just use numbers, though that
+ means needing to manage the numbers.
+
+ It is preferable to keep the symbols short so that a line worth of
+ key mappings fits compactly onto a line of code. */
+
+/* This was originally based on planck/keymaps/default/default.c, and
+ then cbbrowne has revised things */
+
+/* Things I did not like about the default mapping
+
+ - I found control too hard to get to. I use it more than Tab, so
+ switched it there.
+ - Having dash on [lower-j] is a bit nonintuitive, but may be OK
+ - I'll bet I should switch ESC/TAB
+ - I'm suspicious that I want to shift M(0) from [4][1] to [4][2],
+ and shift ESC off the first column so KC_LCTL and KC_LALT can
+ be on the first column.
+ - I needed to swap ' and ENTER
+
+ - All of the above are done :-)
+
+ - Dropped out support for Dvorak and friends. They aren't
+ improvements to me
+*/
+
+
+/* Some interesting things implemented
+
+ - There is a macro that writes out "cbbrowne" to show that I could
+ - There is a (somewhat cruddy) linear congruential random number
+ generator.
+ - I would like to be seeding it with clock info to make it look
+ more random
+ - There are two macros that use the random number generators
+ - one, M_RANDDIGIT, generates a random digit based on state
+ of the random number generator
+ - the other, M_RANDLETTER, generates a random letter based on state
+ of the random number generator
+ - in both, note the use of register_code()/unregister_code()
+ to indicate the desired key
+ - I do indeed want a sweet number pad!
+*/
+
+/* Other things to do...
+
+ - Need to think about what zsh and readline actions I use lots
+ - Ought to ensure that Control-Alt-Delete is convenient enough
+ - How about Alt-F1 thru Alt-F8?
+ - What's the keystroke to get from X to console these days?
+ - A layer for doing console switching would not be a bad idea
+*/
+
+enum layers {
+ _QW = 0, /* Qwerty mapping */
+ _LW, /* Lower layer, where top line has symbols !@#$%^&*() */
+ _RS, /* Raised layer, where top line has digits 1234567890 */
+ _KP, /* Key pad */
+};
+
+enum macro_id {
+ M_LED = 0,
+ M_USERNAME,
+ M_RANDDIGIT,
+ M_RANDLETTER,
+ M_VERSION
+};
+
+/* Note that Planck has dimensions 4 rows x 12 columns */
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[_QW] = { /* Qwerty */
+ {KC_ESC, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC},
+ {KC_LCTL, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_ENT},
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_QUOT },
+ {KC_TAB, M(M_LED), KC_LALT, KC_LGUI, MO(_LW), KC_SPC, KC_SPC, MO(_RS), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+[_RS] = { /* RAISE */
+ {KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC},
+ {KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS},
+ {KC_TRNS, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, DF(_QW), DF(_KP), DF(_KP), RESET, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
+},
+[_LW] = { /* LOWER */
+ {KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_BSPC},
+ {KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE},
+ {KC_TRNS, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, DF(_QW), DF(_KP), DF(_KP), RESET, KC_TRNS},
+ {KC_TRNS, DF(_KP), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
+},
+[_KP] = { /* Key Pad */
+ {KC_ESC, M(M_USERNAME), M(M_VERSION), KC_F10, KC_F11, KC_F12, KC_PGUP, KC_KP_ENTER, KC_7, KC_8, KC_9, KC_BSPC},
+ {KC_LCTL, M(M_RANDDIGIT), KC_F5, KC_F6, KC_F7, KC_F8, KC_PGDN, KC_KP_MINUS, KC_4, KC_5, KC_6, KC_PIPE},
+ {KC_LSFT, M(M_RANDLETTER), KC_F1, KC_F2, KC_F3, KC_F4, KC_DEL, KC_KP_PLUS, KC_1, KC_2, KC_3, KC_ENTER},
+ {BL_STEP, M(M_LED), KC_LALT, KC_LGUI, KC_NO, KC_SPC, KC_SPC, DF(_QW), KC_LEFT, KC_DOWN, KC_UP, KC_RIGHT}
+}
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+};
+
+/* This bit of logic seeds a wee linear congruential random number generator */
+/* lots of prime numbers everywhere... */
+static uint16_t random_value = 157;
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ uint8_t clockbyte=0;
+ clockbyte = TCNT1 % 256;
+ uint8_t rval;
+ // MACRODOWN only works in this function
+ switch(id) {
+ case M_LED:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+#ifdef BACKLIGHT_ENABLE
+ backlight_step();
+#endif
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ case M_USERNAME:
+ if (record->event.pressed) {
+ SEND_STRING("cbbrowne");
+ }
+ break;
+ case M_VERSION:
+ if (record->event.pressed) {
+ SEND_STRING(QMK_KEYBOARD "/" QMK_KEYMAP "@" QMK_VERSION "@" QMK_BUILDDATE);
+ }
+ break;
+ case M_RANDDIGIT:
+ /* Generate, based on random number generator, a keystroke for
+ a numeric digit chosen at random */
+ random_value = ((random_value + randadd) * randmul) % randmod;
+ if (record->event.pressed) {
+ /* Here, we mix the LCRNG with low bits from one of the system
+ clocks via XOR in the theory that this may be more random
+ than either separately */
+ rval = (random_value ^ clockbyte) % 10;
+ /* Note that KC_1 thru KC_0 are a contiguous range */
+ register_code (KC_1 + rval);
+ unregister_code (KC_1 + rval);
+ }
+ break;
+ case M_RANDLETTER:
+ /* Generate, based on random number generator, a keystroke for
+ a letter chosen at random */
+ /* Here, we mix the LCRNG with low bits from one of the system
+ clocks via XOR in the theory that this may be more random
+ than either separately */
+ random_value = ((random_value + randadd) * randmul) % randmod;
+ if (record->event.pressed) {
+ rval = (random_value ^ clockbyte) % 26;
+ register_code (KC_A + rval);
+ unregister_code (KC_A + rval);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
diff --git a/keyboards/planck/keymaps/cbbrowne/readme.md b/keyboards/planck/keymaps/cbbrowne/readme.md
new file mode 100644
index 000000000..c676dd2c1
--- /dev/null
+++ b/keyboards/planck/keymaps/cbbrowne/readme.md
@@ -0,0 +1,64 @@
+cbbrowne custom keyboard
+==============================
+
+Due to cbbrowne@acm.org
+Christopher Browne
+
+This was originally based on the default keyboard map, but I have been
+doing sundry experimentation:
+
+1. Experiments
+----------------------------------------
+
+ * To figure things out about the toolset
+ * I'm an Emacs guy, so will be needing a fair bit of tuning
+ * It made sense to mess around some with keyboard maps.
+ - I tried added Workman alongside Dvorak and Colemak
+ - Boy, oh boy, these don't help!!!
+ - I have done 30 years of learning of Emacs key mappings, and
+ these alternative keyboards massively mess me up
+ - I added a keypad, originally based on keymaps/numpad.c, but
+ mighty substantially revised, as that one seems to be rotated 90
+ degrees from usual conventions for number pads
+ * The keypad layer also includes some sample "hacks" of cool things,
+ all using actions attached in using the function action_get_macro()
+ - Key [1][2] aka "q" types out my name, cbbrowne, as a fun example
+ of a key generating a bunch of keystrokes. The keystroke is
+ sufficiently inconvenient that it isn't terribly practical for me
+ to use it, but hey, it shows how others might use this facility
+ in a more useful context.
+ - Key [2][2] aka "a" uses a random number generator to select a digit 0-9 at random
+ - Key [3][2] aka "z" uses a random number generator to select a letter a-z at random
+ - Key [1][3] aka "e" spits out the keymap version number
+
+2. Some code structure ideas
+---------------------------------------------------
+
+ Each layer is given a name to aid in readability, which is then
+ used in the keymap matrix below. The underscores do not denote
+ anything - you can have a layer called STUFF or any other name.
+
+ Layer names don't all need to be of the same length, obviously, and
+ you could also skip them entirely and just use numbers, though that
+ means needing to manage the numbers.
+
+ It is preferable to keep the symbols short so that a line worth of
+ key mappings fits compactly onto a line of code. It might be an
+ interesting idea to express the maps rotated 90%, so that you
+ only need to fit 4 symbols onto each line, rather than 12.
+
+ I used enums to manage layer IDs and macro IDs so that I don't need
+ to care (beyond "start at 0", and arguably that's not needed) about
+ their values.
+
+3. Things I did not like about the default mapping
+---------------------------------------------------------
+
+ * I found control too hard to get to. I use it more than Tab, so
+ switched it there.
+ * Having dash on [lower-j] is a bit nonintuitive, but may be OK
+ * I switched ESC/TAB/M(0) around
+ * I'm suspicious that I want to shift M(0) from [4][1] to [4][2],
+ and shift ESC off the first column so KC_LCTL and KC_LALT can
+ be on the first column.
+ * I needed to swap ' and ENTER
diff --git a/keyboards/planck/keymaps/charlie/Makefile b/keyboards/planck/keymaps/charlie/Makefile
new file mode 100644
index 000000000..581e08cd0
--- /dev/null
+++ b/keyboards/planck/keymaps/charlie/Makefile
@@ -0,0 +1,25 @@
+
+
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = yes # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/planck/keymaps/charlie/keymap.c b/keyboards/planck/keymaps/charlie/keymap.c
new file mode 100644
index 000000000..966c60d20
--- /dev/null
+++ b/keyboards/planck/keymaps/charlie/keymap.c
@@ -0,0 +1,54 @@
+#include "keymap.h"
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ [0] = { /* Native */
+ {KC_ESC, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, FUNC(2)},
+ {KC_BSPC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT},
+ {KC_TAB, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT},
+ {KC_DEL, KC_LCTL, KC_NO, KC_LSFT, KC_LALT, KC_SPC, KC_NO, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+ [1] = { /* QWERTY->PHOTOSHOP */
+ {KC_DELETE, KC_0, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, FUNC(1)},
+ {KC_O, KC_G, KC_S, KC_U, KC_T, FUNC(27), KC_F21, KC_F10, KC_F11, KC_F7, KC_F8, KC_F9},
+ {KC_TAB, FUNC(4), FUNC(5), FUNC(6), KC_F1, FUNC(7), KC_F18, KC_F19, KC_F23, KC_F20, KC_F22, FUNC(9)},
+ {KC_COMM, KC_DOT, KC_R, FUNC(11), FUNC(3), KC_SPC, FUNC(12), KC_F2, FUNC(8), KC_F3, KC_F14}
+ },
+ [2] = { /* 2: FUNC(3 PHOTOSHOP */
+ {KC_ESC, FUNC(25), FUNC(26), KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO},
+ {KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, FUNC(19), FUNC(20), FUNC(21)},
+ {KC_C, KC_NO, FUNC(22), FUNC(5), KC_NO, FUNC(23), KC_NO, KC_NO, KC_NO, KC_NO, FUNC(13), KC_NO},
+ {FUNC(14), FUNC(15), FUNC(16), FUNC(17), FUNC(3), KC_SPC, FUNC(18), KC_NO, KC_NO, KC_F24, KC_NO}
+ }
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_DEFAULT_LAYER_SET(0), // set Qwerty layout
+ [2] = ACTION_DEFAULT_LAYER_SET(1), // set Photoshop presets
+ [3] = ACTION_LAYER_MOMENTARY(2), // Photoshop function layer
+
+ [4] = ACTION_MODS_KEY(MOD_LSFT | MOD_LCTL | MOD_LALT, KC_F9), // photo folder AHK
+ [5] = ACTION_MODS_KEY(MOD_LSFT | MOD_LCTL, KC_I), // select inverse
+ [6] = ACTION_MODS_KEY(MOD_LSFT, KC_M), // marquee select
+ [7] = ACTION_MODS_KEY(MOD_LALT, KC_BSPC), // fill
+ [8] = ACTION_MODS_KEY(MOD_LSFT | MOD_LCTL | MOD_LALT, KC_X), // warp
+ [9] = ACTION_MODS_KEY(MOD_LCTL | MOD_LALT | MOD_LSFT, KC_F12), // merge all new layer
+ [10] = ACTION_MODS_KEY(MOD_LCTL, KC_MINS), // zoom out
+ [11] = ACTION_MODS_KEY(MOD_LCTL, KC_H), // RBG sliders
+ [12] = ACTION_MODS_KEY(MOD_LCTL, KC_S), // save
+ [13] = ACTION_MODS_KEY(MOD_LSFT | MOD_LCTL, KC_F5), // layer mask from transparancy
+ [14] = ACTION_MODS_KEY(MOD_LCTL, KC_F2), // stroke
+ [15] = ACTION_MODS_KEY(MOD_LCTL | MOD_LSFT, KC_F2), // stroke layer
+ [16] = ACTION_MODS_KEY(MOD_LCTL, KC_0), // zoom 0
+ [17] = ACTION_MODS_KEY(MOD_LSFT | MOD_LCTL, KC_H), // HSV sliders
+ [18] = ACTION_MODS_KEY(MOD_LCTL | MOD_LSFT, KC_S), // save as
+ [19] = ACTION_MODS_KEY(MOD_LSFT | MOD_LCTL | MOD_LALT, KC_F7), // gaussian blur
+ [20] = ACTION_MODS_KEY(MOD_LSFT | MOD_LCTL | MOD_LALT, KC_F8), // motion blur
+ [21] = ACTION_MODS_KEY(MOD_LSFT | MOD_LCTL, KC_X), // liquify filter
+ [22] = ACTION_MODS_KEY(MOD_LSFT, KC_MINS), // prev layer blending
+ [23] = ACTION_MODS_KEY(MOD_LSFT | MOD_LCTL, KC_BSPC), // KC_NOrmal layer blending
+ [24] = ACTION_MODS_KEY(MOD_LSFT, KC_EQL), // next layer blending
+ [25] = ACTION_MODS_KEY(MOD_LCTL, KC_Z), // step back
+ [26] = ACTION_MODS_KEY(MOD_LCTL, KC_Y), // step forward
+ [27] = ACTION_MODS_KEY(MOD_LCTL, KC_R), // rasterize
+
+};
diff --git a/keyboards/planck/keymaps/daniel/Makefile b/keyboards/planck/keymaps/daniel/Makefile
new file mode 100644
index 000000000..581e08cd0
--- /dev/null
+++ b/keyboards/planck/keymaps/daniel/Makefile
@@ -0,0 +1,25 @@
+
+
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = yes # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/planck/keymaps/daniel/keymap.c b/keyboards/planck/keymaps/daniel/keymap.c
new file mode 100644
index 000000000..3054d7974
--- /dev/null
+++ b/keyboards/planck/keymaps/daniel/keymap.c
@@ -0,0 +1,37 @@
+#include "keymap.h"
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[0] = { /* Qwerty */
+ {KC_ESC, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC},
+ {KC_TAB, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT},
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT},
+ {FUNC(3), KC_LCTL, KC_LALT, KC_LGUI, FUNC(2), KC_SPC, KC_SPC, FUNC(1), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+ // Space is repeated to accommadate for both spacebar wiring positions
+},
+[1] = { /* RAISE */
+ {KC_GRV, S(KC_1), S(KC_2), S(KC_3), S(KC_4), S(KC_5), S(KC_6), S(KC_7), S(KC_8), S(KC_9), S(KC_0), KC_EQL},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_LBRC, KC_RBRC},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MINS, S(KC_MINS), KC_BSLS, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, FUNC(1), KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
+},
+[2] = { /* LOWER */
+ {S(KC_GRV), KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, S(KC_EQL)},
+ {KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12},
+ {KC_CAPS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_ENT},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, FUNC(2), KC_TRNS, KC_TRNS, KC_TRNS, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
+},
+[3] = { /* Qwerty */
+ {KC_ESC, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_DEL},
+ {KC_TAB, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT},
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT},
+ {KC_TRNS, KC_LCTL, KC_LALT, KC_LGUI, FUNC(2), KC_SPC, KC_SPC, FUNC(1), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+ // Space is repeated to accommadate for both spacebar wiring positions
+}
+};
+
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_MOMENTARY(1), // to RAISE
+ [2] = ACTION_LAYER_MOMENTARY(2), // to LOWER
+ [3] = ACTION_LAYER_MOMENTARY(3) // to LOWER
+};
diff --git a/keyboards/planck/keymaps/david/Makefile b/keyboards/planck/keymaps/david/Makefile
new file mode 100644
index 000000000..581e08cd0
--- /dev/null
+++ b/keyboards/planck/keymaps/david/Makefile
@@ -0,0 +1,25 @@
+
+
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = yes # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/planck/keymaps/david/keymap.c b/keyboards/planck/keymaps/david/keymap.c
new file mode 100644
index 000000000..d8a46aa83
--- /dev/null
+++ b/keyboards/planck/keymaps/david/keymap.c
@@ -0,0 +1,38 @@
+#include "keymap.h"
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[0] = { /* Qwerty */
+ {KC_Q, KC_W, KC_E, KC_R, KC_T, KC_BSPC, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC},
+ {KC_A, KC_S, KC_D, KC_F, KC_G, KC_ENT, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT},
+ {KC_Z, KC_X, KC_C, KC_V, KC_B, KC_ESC, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT},
+ {M(10), KC_LCTL, KC_LALT, KC_LGUI, FUNC(2), KC_SPC, KC_SPC, FUNC(1), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+ // Space is repeated to accommadate for both spacebar wiring positions
+},
+[1] = { /* Colemak */
+ {KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_BSPC},
+ {KC_ESC, KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT},
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_K, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT},
+ {KC_FN3, KC_LCTL, KC_LALT, KC_LGUI, FUNC(2), KC_SPC, KC_SPC, FUNC(1), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+[2] = { /* RAISE */
+ {KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC},
+ {KC_TRNS, FUNC(3), FUNC(4), RESET, M(0), M(1), M(2), KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS},
+ {KC_TRNS, KC_F11, KC_F12, M(0), M(1), M(2), M(3), M(4), M(5), M(6), M(7), KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, FUNC(1), KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
+},
+[3] = { /* LOWER */
+ {S(KC_GRV), S(KC_1), S(KC_2), S(KC_3), S(KC_4), S(KC_5), S(KC_6), S(KC_7), S(KC_8), S(KC_9), S(KC_0), KC_BSPC},
+ {KC_TRNS, FUNC(3), FUNC(4), RESET, M(0), M(1), M(2), S(KC_MINS), S(KC_EQL), S(KC_LBRC), S(KC_RBRC), S(KC_BSLS)},
+ {KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, FUNC(2), KC_TRNS, KC_TRNS, KC_TRNS, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
+}
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_MOMENTARY(2), // to RAISE
+ [2] = ACTION_LAYER_MOMENTARY(3), // to LOWER
+
+ [3] = ACTION_DEFAULT_LAYER_SET(0),
+ [4] = ACTION_DEFAULT_LAYER_SET(1),
+
+};
diff --git a/keyboards/planck/keymaps/default/Makefile b/keyboards/planck/keymaps/default/Makefile
new file mode 100644
index 000000000..581e08cd0
--- /dev/null
+++ b/keyboards/planck/keymaps/default/Makefile
@@ -0,0 +1,25 @@
+
+
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = yes # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/planck/keymaps/default/keymap.c b/keyboards/planck/keymaps/default/keymap.c
new file mode 100644
index 000000000..5f71ae7d1
--- /dev/null
+++ b/keyboards/planck/keymaps/default/keymap.c
@@ -0,0 +1,314 @@
+// This is the canonical layout file for the Quantum project. If you want to add another keyboard,
+// this is the style you want to emulate.
+
+#include "planck.h"
+#include "action_layer.h"
+#ifdef AUDIO_ENABLE
+ #include "audio.h"
+#endif
+#include "eeconfig.h"
+
+extern keymap_config_t keymap_config;
+
+// Each layer gets a name for readability, which is then used in the keymap matrix below.
+// The underscores don't mean anything - you can have a layer called STUFF or any other name.
+// Layer names don't all need to be of the same length, obviously, and you can also skip them
+// entirely and just use numbers.
+#define _QWERTY 0
+#define _COLEMAK 1
+#define _DVORAK 2
+#define _LOWER 3
+#define _RAISE 4
+#define _PLOVER 5
+#define _ADJUST 16
+
+enum planck_keycodes {
+ QWERTY = SAFE_RANGE,
+ COLEMAK,
+ DVORAK,
+ PLOVER,
+ LOWER,
+ RAISE,
+ BACKLIT,
+ EXT_PLV
+};
+
+// Fillers to make layering more clear
+#define _______ KC_TRNS
+#define XXXXXXX KC_NO
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+
+/* Qwerty
+ * ,-----------------------------------------------------------------------------------.
+ * | Tab | Q | W | E | R | T | Y | U | I | O | P | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc | A | S | D | F | G | H | J | K | L | ; | " |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift| Z | X | C | V | B | N | M | , | . | / |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Brite| Ctrl | Alt | GUI |Lower | Space |Raise | Left | Down | Up |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_QWERTY] = {
+ {KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC},
+ {KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT},
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT },
+ {BACKLIT, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+
+/* Colemak
+ * ,-----------------------------------------------------------------------------------.
+ * | Tab | Q | W | F | P | G | J | L | U | Y | ; | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc | A | R | S | T | D | H | N | E | I | O | " |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift| Z | X | C | V | B | K | M | , | . | / |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Brite| Ctrl | Alt | GUI |Lower | Space |Raise | Left | Down | Up |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_COLEMAK] = {
+ {KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_BSPC},
+ {KC_ESC, KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT},
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_K, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT },
+ {BACKLIT, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+
+/* Dvorak
+ * ,-----------------------------------------------------------------------------------.
+ * | Tab | " | , | . | P | Y | F | G | C | R | L | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc | A | O | E | U | I | D | H | T | N | S | / |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift| ; | Q | J | K | X | B | M | W | V | Z |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Brite| Ctrl | Alt | GUI |Lower | Space |Raise | Left | Down | Up |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_DVORAK] = {
+ {KC_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, KC_F, KC_G, KC_C, KC_R, KC_L, KC_BSPC},
+ {KC_ESC, KC_A, KC_O, KC_E, KC_U, KC_I, KC_D, KC_H, KC_T, KC_N, KC_S, KC_SLSH},
+ {KC_LSFT, KC_SCLN, KC_Q, KC_J, KC_K, KC_X, KC_B, KC_M, KC_W, KC_V, KC_Z, KC_ENT },
+ {BACKLIT, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+
+/* Lower
+ * ,-----------------------------------------------------------------------------------.
+ * | ~ | ! | @ | # | $ | % | ^ | & | * | ( | ) | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Del | F1 | F2 | F3 | F4 | F5 | F6 | _ | + | { | } | | |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | | F7 | F8 | F9 | F10 | F11 | F12 |ISO ~ |ISO | | | |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | | | | | | | | Next | Vol- | Vol+ | Play |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_LOWER] = {
+ {KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_BSPC},
+ {KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE},
+ {_______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12,S(KC_NUHS),S(KC_NUBS),_______, _______, _______},
+ {_______, _______, _______, _______, _______, _______, _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
+},
+
+/* Raise
+ * ,-----------------------------------------------------------------------------------.
+ * | ` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Del | F1 | F2 | F3 | F4 | F5 | F6 | - | = | [ | ] | \ |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | | F7 | F8 | F9 | F10 | F11 | F12 |ISO # |ISO / | | |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | | | | | | | | Next | Vol- | Vol+ | Play |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_RAISE] = {
+ {KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC},
+ {KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS},
+ {_______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_NUHS, KC_NUBS, _______, _______, _______},
+ {_______, _______, _______, _______, _______, _______, _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
+},
+
+/* Plover layer (http://opensteno.org)
+ * ,-----------------------------------------------------------------------------------.
+ * | # | # | # | # | # | # | # | # | # | # | # | # |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | | S | T | P | H | * | * | F | P | L | T | D |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * |TogOut| S | K | W | R | * | * | R | B | G | S | Z |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Exit | | | A | O | | E | U | | | |
+ * `-----------------------------------------------------------------------------------'
+ */
+
+[_PLOVER] = {
+ {KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1 },
+ {XXXXXXX, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC},
+ {XXXXXXX, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT},
+ {EXT_PLV, XXXXXXX, XXXXXXX, KC_C, KC_V, XXXXXXX, XXXXXXX, KC_N, KC_M, XXXXXXX, XXXXXXX, XXXXXXX}
+},
+
+/* Adjust (Lower + Raise)
+ * ,-----------------------------------------------------------------------------------.
+ * | | Reset| | | | | | | | | | Del |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | | | |Aud on|Audoff|AGnorm|AGswap|Qwerty|Colemk|Dvorak|Plover| |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | |Voice-|Voice+|Mus on|Musoff|MIDIon|MIDIof| | | | | |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | | | | | | | | | | | |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_ADJUST] = {
+ {_______, RESET, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_DEL},
+ {_______, _______, _______, AU_ON, AU_OFF, AG_NORM, AG_SWAP, QWERTY, COLEMAK, DVORAK, PLOVER, _______},
+ {_______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, _______, _______, _______, _______, _______},
+ {_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______}
+}
+
+
+};
+
+#ifdef AUDIO_ENABLE
+
+float tone_startup[][2] = SONG(STARTUP_SOUND);
+float tone_qwerty[][2] = SONG(QWERTY_SOUND);
+float tone_dvorak[][2] = SONG(DVORAK_SOUND);
+float tone_colemak[][2] = SONG(COLEMAK_SOUND);
+float tone_plover[][2] = SONG(PLOVER_SOUND);
+float tone_plover_gb[][2] = SONG(PLOVER_GOODBYE_SOUND);
+float music_scale[][2] = SONG(MUSIC_SCALE_SOUND);
+
+float tone_goodbye[][2] = SONG(GOODBYE_SOUND);
+#endif
+
+
+void persistant_default_layer_set(uint16_t default_layer) {
+ eeconfig_update_default_layer(default_layer);
+ default_layer_set(default_layer);
+}
+
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ case QWERTY:
+ if (record->event.pressed) {
+ #ifdef AUDIO_ENABLE
+ PLAY_NOTE_ARRAY(tone_qwerty, false, 0);
+ #endif
+ persistant_default_layer_set(1UL<<_QWERTY);
+ }
+ return false;
+ break;
+ case COLEMAK:
+ if (record->event.pressed) {
+ #ifdef AUDIO_ENABLE
+ PLAY_NOTE_ARRAY(tone_colemak, false, 0);
+ #endif
+ persistant_default_layer_set(1UL<<_COLEMAK);
+ }
+ return false;
+ break;
+ case DVORAK:
+ if (record->event.pressed) {
+ #ifdef AUDIO_ENABLE
+ PLAY_NOTE_ARRAY(tone_dvorak, false, 0);
+ #endif
+ persistant_default_layer_set(1UL<<_DVORAK);
+ }
+ return false;
+ break;
+ case LOWER:
+ if (record->event.pressed) {
+ layer_on(_LOWER);
+ update_tri_layer(_LOWER, _RAISE, _ADJUST);
+ } else {
+ layer_off(_LOWER);
+ update_tri_layer(_LOWER, _RAISE, _ADJUST);
+ }
+ return false;
+ break;
+ case RAISE:
+ if (record->event.pressed) {
+ layer_on(_RAISE);
+ update_tri_layer(_LOWER, _RAISE, _ADJUST);
+ } else {
+ layer_off(_RAISE);
+ update_tri_layer(_LOWER, _RAISE, _ADJUST);
+ }
+ return false;
+ break;
+ case BACKLIT:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ #ifdef BACKLIGHT_ENABLE
+ backlight_step();
+ #endif
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ return false;
+ break;
+ case PLOVER:
+ if (record->event.pressed) {
+ #ifdef AUDIO_ENABLE
+ stop_all_notes();
+ PLAY_NOTE_ARRAY(tone_plover, false, 0);
+ #endif
+ layer_off(_RAISE);
+ layer_off(_LOWER);
+ layer_off(_ADJUST);
+ layer_on(_PLOVER);
+ if (!eeconfig_is_enabled()) {
+ eeconfig_init();
+ }
+ keymap_config.raw = eeconfig_read_keymap();
+ keymap_config.nkro = 1;
+ eeconfig_update_keymap(keymap_config.raw);
+ }
+ return false;
+ break;
+ case EXT_PLV:
+ if (record->event.pressed) {
+ #ifdef AUDIO_ENABLE
+ PLAY_NOTE_ARRAY(tone_plover_gb, false, 0);
+ #endif
+ layer_off(_PLOVER);
+ }
+ return false;
+ break;
+ }
+ return true;
+}
+
+void matrix_init_user(void) {
+ #ifdef AUDIO_ENABLE
+ startup_user();
+ #endif
+}
+
+#ifdef AUDIO_ENABLE
+
+void startup_user()
+{
+ _delay_ms(20); // gets rid of tick
+ PLAY_NOTE_ARRAY(tone_startup, false, 0);
+}
+
+void shutdown_user()
+{
+ PLAY_NOTE_ARRAY(tone_goodbye, false, 0);
+ _delay_ms(150);
+ stop_all_notes();
+}
+
+void music_on_user(void)
+{
+ music_scale_user();
+}
+
+void music_scale_user(void)
+{
+ PLAY_NOTE_ARRAY(music_scale, false, 0);
+}
+
+#endif
diff --git a/keyboards/planck/keymaps/default/readme.md b/keyboards/planck/keymaps/default/readme.md
new file mode 100644
index 000000000..de9680b49
--- /dev/null
+++ b/keyboards/planck/keymaps/default/readme.md
@@ -0,0 +1,2 @@
+# The Default Planck Layout
+
diff --git a/keyboards/planck/keymaps/dzobert/Makefile b/keyboards/planck/keymaps/dzobert/Makefile
new file mode 100644
index 000000000..581e08cd0
--- /dev/null
+++ b/keyboards/planck/keymaps/dzobert/Makefile
@@ -0,0 +1,25 @@
+
+
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = yes # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/planck/keymaps/dzobert/keymap.c b/keyboards/planck/keymaps/dzobert/keymap.c
new file mode 100644
index 000000000..365649ed8
--- /dev/null
+++ b/keyboards/planck/keymaps/dzobert/keymap.c
@@ -0,0 +1,38 @@
+#include "keymap.h"
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[0] = { /* Qwerty */
+ {KC_ESC, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_TAB},
+ {KC_LCTL, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_BSPC},
+ {KC_LALT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT},
+ {KC_FN4, KC_RSFT, KC_LGUI, KC_LSFT, FUNC(2), KC_SPC, KC_SPC, FUNC(1), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+ // Space is repeated to accommadate for both spacebar wiring positions
+},
+[1] = { /* Colemak */
+ {KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_TAB},
+ {KC_ESC, KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, KC_BSPC},
+ {KC_LALT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_K, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT},
+ {KC_FN3, KC_RSFT, KC_LGUI, KC_LSFT, FUNC(2), KC_SPC, KC_SPC, FUNC(1), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+[2] = { /* RAISE */
+ {KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12},
+ {KC_TRNS, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_DEL},
+ {KC_TRNS, KC_GRV, KC_MINS, KC_EQL, KC_QUOT, S(KC_QUOT), S(KC_LBRC), S(KC_RBRC), KC_LBRC, KC_RBRC, KC_BSLS, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, FUNC(1), KC_HOME, KC_PGUP, KC_PGDN, KC_END}
+},
+[3] = { /* LOWER */
+ {KC_POWER,KC_PSCR, KC_SLCK, KC_PAUSE, KC_NLCK, KC_EXECUTE, KC_MENU, KC_APP, KC_7, KC_8, KC_9, KC_KP_SLASH},
+ {KC_TRNS, KC_VOLD, KC_VOLU, KC_MUTE, KC_CAPS, KC_CANCEL, KC_UNDO, KC_AGAIN, KC_4, KC_5, KC_6, KC_KP_ASTERISK},
+ {KC_TRNS, KC_INSERT,KC_CUT, KC_COPY, KC_PASTE, KC_BSLS, KC_9, KC_0, KC_1, KC_2, KC_3, KC_KP_MINUS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, FUNC(2), KC_TRNS, KC_TRNS, KC_TRNS, KC_0, KC_KP_DOT, KC_KP_ENTER, KC_KP_PLUS}
+}
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_MOMENTARY(2), // to RAISE
+ [2] = ACTION_LAYER_MOMENTARY(3), // to LOWER
+
+ [3] = ACTION_DEFAULT_LAYER_SET(0),
+ [4] = ACTION_DEFAULT_LAYER_SET(1),
+
+};
diff --git a/keyboards/planck/keymaps/experimental/Makefile b/keyboards/planck/keymaps/experimental/Makefile
new file mode 100644
index 000000000..581e08cd0
--- /dev/null
+++ b/keyboards/planck/keymaps/experimental/Makefile
@@ -0,0 +1,25 @@
+
+
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = yes # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/planck/keymaps/experimental/config.h b/keyboards/planck/keymaps/experimental/config.h
new file mode 100644
index 000000000..985e250ab
--- /dev/null
+++ b/keyboards/planck/keymaps/experimental/config.h
@@ -0,0 +1,9 @@
+#ifndef CONFIG_USER_H
+#define CONFIG_USER_H
+
+#include "../../config.h"
+
+#define LEADER_TIMEOUT 300
+#define BACKLIGHT_BREATHING
+
+#endif
diff --git a/keyboards/planck/keymaps/experimental/keymap.c b/keyboards/planck/keymaps/experimental/keymap.c
new file mode 100644
index 000000000..8ec335d7d
--- /dev/null
+++ b/keyboards/planck/keymaps/experimental/keymap.c
@@ -0,0 +1,366 @@
+// This is the canonical layout file for the Quantum project. If you want to add another keyboard,
+// this is the style you want to emulate.
+
+#include "planck.h"
+#include "action_layer.h"
+#ifdef AUDIO_ENABLE
+ #include "audio.h"
+#endif
+
+#include "eeconfig.h"
+
+extern keymap_config_t keymap_config;
+
+// Each layer gets a name for readability, which is then used in the keymap matrix below.
+// The underscores don't mean anything - you can have a layer called STUFF or any other name.
+// Layer names don't all need to be of the same length, obviously, and you can also skip them
+// entirely and just use numbers.
+#define _QWERTY 0
+#define _COLEMAK 1
+#define _DVORAK 2
+#define _LOWER 3
+#define _RAISE 4
+#define _PLOVER 5
+#define _ADJUST 16
+
+enum planck_keycodes {
+ QWERTY = SAFE_RANGE,
+ COLEMAK,
+ DVORAK,
+ PLOVER,
+ LOWER,
+ RAISE,
+ BACKLIT,
+ EXT_PLV
+};
+
+// Fillers to make layering more clear
+#define _______ KC_TRNS
+#define XXXXXXX KC_NO
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+
+/* Qwerty
+ * ,-----------------------------------------------------------------------------------.
+ * | Tab | Q | W | E | R | T | Y | U | I | O | P | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc | A | S | D | F | G | H | J | K | L | ; | " |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift| Z | X | C | V | B | N | M | , | . | / |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Brite| Ctrl | Alt | GUI |Lower | Space |Raise | Left | Down | Up |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_QWERTY] = {
+ {KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC},
+ {KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT},
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT },
+ {KC_LEAD, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+
+/* Colemak
+ * ,-----------------------------------------------------------------------------------.
+ * | Tab | Q | W | F | P | G | J | L | U | Y | ; | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc | A | R | S | T | D | H | N | E | I | O | " |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift| Z | X | C | V | B | K | M | , | . | / |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Brite| Ctrl | Alt | GUI |Lower | Space |Raise | Left | Down | Up |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_COLEMAK] = {
+ {KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_BSPC},
+ {KC_ESC, KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT},
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_K, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT },
+ {KC_LEAD, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+
+/* Dvorak
+ * ,-----------------------------------------------------------------------------------.
+ * | Tab | " | , | . | P | Y | F | G | C | R | L | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc | A | O | E | U | I | D | H | T | N | S | / |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift| ; | Q | J | K | X | B | M | W | V | Z |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Brite| Ctrl | Alt | GUI |Lower | Space |Raise | Left | Down | Up |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_DVORAK] = {
+ {KC_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, KC_F, KC_G, KC_C, KC_R, KC_L, KC_BSPC},
+ {KC_ESC, KC_A, KC_O, KC_E, KC_U, KC_I, KC_D, KC_H, KC_T, KC_N, KC_S, KC_SLSH},
+ {KC_LSFT, KC_SCLN, KC_Q, KC_J, KC_K, KC_X, KC_B, KC_M, KC_W, KC_V, KC_Z, KC_ENT },
+ {KC_LEAD, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+
+/* Lower
+ * ,-----------------------------------------------------------------------------------.
+ * | ~ | ! | @ | # | $ | % | ^ | & | * | ( | ) | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Del | F1 | F2 | F3 | F4 | F5 | F6 | _ | + | { | } | | |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | | F7 | F8 | F9 | F10 | F11 | F12 |ISO ~ |ISO | | | |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | | | | | | | | Next | Vol- | Vol+ | Play |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_LOWER] = {
+ {KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_BSPC},
+ {KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE},
+ {_______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12,S(KC_NUHS),S(KC_NUBS),_______, _______, _______},
+ {_______, _______, _______, _______, _______, _______, _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
+},
+
+/* Raise
+ * ,-----------------------------------------------------------------------------------.
+ * | ` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Del | F1 | F2 | F3 | F4 | F5 | F6 | - | = | [ | ] | \ |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | | F7 | F8 | F9 | F10 | F11 | F12 |ISO # |ISO / | | |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | | | | | | | | Next | Vol- | Vol+ | Play |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_RAISE] = {
+ {KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC},
+ {KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS},
+ {_______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_NUHS, KC_NUHS, _______, _______, _______},
+ {_______, _______, _______, _______, _______, _______, _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
+},
+
+/* Plover layer (http://opensteno.org)
+ * ,-----------------------------------------------------------------------------------.
+ * | # | # | # | # | # | # | # | # | # | # | # | # |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | | S | T | P | H | * | * | F | P | L | T | D |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | | S | K | W | R | * | * | R | B | G | S | Z |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Exit | | | A | O | | E | U | | | |
+ * `-----------------------------------------------------------------------------------'
+ */
+
+[_PLOVER] = {
+ {KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1 },
+ {XXXXXXX, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC},
+ {XXXXXXX, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT},
+ {EXT_PLV, XXXXXXX, XXXXXXX, KC_C, KC_V, XXXXXXX, XXXXXXX, KC_N, KC_M, XXXXXXX, XXXXXXX, XXXXXXX}
+},
+
+/* Adjust (Lower + Raise)
+ * ,-----------------------------------------------------------------------------------.
+ * | | Reset| | | | | | | | | | Del |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | | | |Aud on|Audoff|AGnorm|AGswap|Qwerty|Colemk|Dvorak|Plover| |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | |Voice-|Voice+|Mus on|Musoff| | | | | | | |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | | | | | | | | | | | |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_ADJUST] = {
+ {_______, RESET, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_DEL},
+ {_______, _______, _______, AU_ON, AU_OFF, AG_NORM, AG_SWAP, QWERTY, COLEMAK, DVORAK, PLOVER, _______},
+ {_______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, _______, _______, _______, _______, _______},
+ {_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______}
+}
+
+
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+
+};
+
+#ifdef AUDIO_ENABLE
+
+float tone_startup[][2] = SONG(STARTUP_SOUND);
+float tone_qwerty[][2] = SONG(QWERTY_SOUND);
+float tone_dvorak[][2] = SONG(DVORAK_SOUND);
+float tone_colemak[][2] = SONG(COLEMAK_SOUND);
+float tone_plover[][2] = SONG(PLOVER_SOUND);
+float tone_plover_gb[][2] = SONG(PLOVER_GOODBYE_SOUND);
+float music_scale[][2] = SONG(MUSIC_SCALE_SOUND);
+
+float tone_goodbye[][2] = SONG(GOODBYE_SOUND);
+#endif
+
+
+
+void persistant_default_layer_set(uint16_t default_layer) {
+ eeconfig_update_default_layer(default_layer);
+ default_layer_set(default_layer);
+}
+
+
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ case QWERTY:
+ if (record->event.pressed) {
+ #ifdef AUDIO_ENABLE
+ PLAY_NOTE_ARRAY(tone_qwerty, false, 0);
+ #endif
+ persistant_default_layer_set(1UL<<_QWERTY);
+ }
+ break;
+ return false;
+ case COLEMAK:
+ if (record->event.pressed) {
+ #ifdef AUDIO_ENABLE
+ PLAY_NOTE_ARRAY(tone_colemak, false, 0);
+ #endif
+ persistant_default_layer_set(1UL<<_COLEMAK);
+ }
+ break;
+ return false;
+ case DVORAK:
+ if (record->event.pressed) {
+ #ifdef AUDIO_ENABLE
+ PLAY_NOTE_ARRAY(tone_dvorak, false, 0);
+ #endif
+ persistant_default_layer_set(1UL<<_DVORAK);
+ }
+ break;
+ return false;
+ case LOWER:
+ if (record->event.pressed) {
+ layer_on(_LOWER);
+ #ifdef BACKLIGHT_ENABLE
+ breathing_speed_set(2);
+ breathing_pulse();
+ #endif
+ update_tri_layer(_LOWER, _RAISE, _ADJUST);
+ } else {
+ layer_off(_LOWER);
+ update_tri_layer(_LOWER, _RAISE, _ADJUST);
+ }
+ break;
+ return false;
+ case RAISE:
+ if (record->event.pressed) {
+ layer_on(_RAISE);
+ #ifdef BACKLIGHT_ENABLE
+ breathing_speed_set(2);
+ breathing_pulse();
+ #endif
+ update_tri_layer(_LOWER, _RAISE, _ADJUST);
+ } else {
+ layer_off(_RAISE);
+ update_tri_layer(_LOWER, _RAISE, _ADJUST);
+ }
+ break;
+ return false;
+ case BACKLIT:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ #ifdef BACKLIGHT_ENABLE
+ backlight_step();
+ #endif
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ return false;
+ case PLOVER:
+ if (record->event.pressed) {
+ #ifdef AUDIO_ENABLE
+ stop_all_notes();
+ PLAY_NOTE_ARRAY(tone_plover, false, 0);
+ #endif
+ layer_off(_RAISE);
+ layer_off(_LOWER);
+ layer_off(_ADJUST);
+ layer_on(_PLOVER);
+ if (!eeconfig_is_enabled()) {
+ eeconfig_init();
+ }
+ keymap_config.raw = eeconfig_read_keymap();
+ keymap_config.nkro = 1;
+ eeconfig_update_keymap(keymap_config.raw);
+ }
+ break;
+ return false;
+ case EXT_PLV:
+ if (record->event.pressed) {
+ #ifdef AUDIO_ENABLE
+ PLAY_NOTE_ARRAY(tone_plover_gb, false, 0);
+ #endif
+ layer_off(_PLOVER);
+ }
+ break;
+ return false;
+
+ }
+ return true;
+};
+
+void matrix_init_user(void) {
+ #ifdef AUDIO_ENABLE
+ startup_user();
+ #endif
+}
+
+#ifdef AUDIO_ENABLE
+void startup_user()
+{
+ _delay_ms(20); // gets rid of tick
+ PLAY_NOTE_ARRAY(tone_startup, false, 0);
+}
+
+void shutdown_user()
+{
+ PLAY_NOTE_ARRAY(tone_goodbye, false, 0);
+ _delay_ms(150);
+ stop_all_notes();
+}
+
+void music_on_user(void)
+{
+ music_scale_user();
+}
+
+void music_scale_user(void)
+{
+ PLAY_NOTE_ARRAY(music_scale, false, 0);
+}
+
+#endif
+
+LEADER_EXTERNS();
+
+void matrix_scan_user(void) {
+ LEADER_DICTIONARY() {
+ leading = false;
+ leader_end();
+
+ SEQ_ONE_KEY (KC_R) {
+ tap_random_base64();
+ tap_random_base64();
+ tap_random_base64();
+ tap_random_base64();
+ tap_random_base64();
+ tap_random_base64();
+ tap_random_base64();
+ tap_random_base64();
+ tap_random_base64();
+ }
+ SEQ_ONE_KEY (KC_V) {
+ SEND_STRING (QMK_KEYBOARD "/" QMK_KEYMAP " @ " QMK_VERSION);
+ }
+ SEQ_ONE_KEY(KC_F) {
+ SEND_STRING("if yes\n\tpeanut butter\nelse\n\trice snacks");
+ }
+ SEQ_TWO_KEYS(KC_A, KC_S) {
+ register_code(KC_H);
+ unregister_code(KC_H);
+ }
+ SEQ_THREE_KEYS(KC_A, KC_S, KC_D) {
+ register_code(KC_LGUI);
+ register_code(KC_S);
+ unregister_code(KC_S);
+ unregister_code(KC_LGUI);
+ }
+ }
+}
diff --git a/keyboards/planck/keymaps/experimental/readme.md b/keyboards/planck/keymaps/experimental/readme.md
new file mode 100644
index 000000000..de9680b49
--- /dev/null
+++ b/keyboards/planck/keymaps/experimental/readme.md
@@ -0,0 +1,2 @@
+# The Default Planck Layout
+
diff --git a/keyboards/planck/keymaps/gabriel/Makefile b/keyboards/planck/keymaps/gabriel/Makefile
new file mode 100644
index 000000000..581e08cd0
--- /dev/null
+++ b/keyboards/planck/keymaps/gabriel/Makefile
@@ -0,0 +1,25 @@
+
+
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = yes # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/planck/keymaps/gabriel/keymap.c b/keyboards/planck/keymaps/gabriel/keymap.c
new file mode 100644
index 000000000..805484488
--- /dev/null
+++ b/keyboards/planck/keymaps/gabriel/keymap.c
@@ -0,0 +1,108 @@
+#include "planck.h"
+
+// Each layer gets a name for readability, which is then used in the keymap matrix below.
+// The underscores don't mean anything - you can have a layer called STUFF or any other name.
+// Layer names don't all need to be of the same length, obviously, and you can also skip them
+// entirely and just use numbers.
+#define _QW 0
+#define _LW 1
+#define _RS 2
+#define _FN 3
+
+// This a slightly modified 'default' keymap that's closer to the Mac keyboard layout. I like the position
+// of 'esc' and 'tab' better this way. I also got rid of the backlighting control key and the dvorak and
+// colemak layers. I added an 'fn' layer that makes the 'bspc' a forward delete (like on OSX).
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+/* MIT Layout (QWERTY layer)
+ *
+ * ,-----------------------------------------------------------------------.
+ * | esc | q | w | e | r | t | y | u | i | o | p | bspc|
+ * |-----------------------------------------------------------------------|
+ * | tab | a | s | d | f | g | h | j | k | l | ; | ' |
+ * |-----------------------------------------------------------------------|
+ * |shift| z | x | c | v | b | n | m | , | . | / |enter|
+ * |-----------------------------------------------------------------------|
+ * | fn | ctl | alt | cmd |lower| spc |raise|left |down | up |right|
+ * `-----------------------------------------------------------------------'
+ */
+[_QW] = { /* QWERTY */
+ {KC_ESC, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC},
+ {KC_TAB, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT},
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT },
+ {MO(_FN), KC_LCTL, KC_LALT, KC_LGUI, MO(_LW), KC_SPC, KC_SPC, MO(_RS), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+/* MIT Layout (Raised layer)
+ *
+ * ,-----------------------------------------------------------------------.
+ * | ` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | |
+ * |-----------------------------------------------------------------------|
+ * | | F1 | F2 | F3 | F4 | F5 | F6 | - | + | [ | ] | | |
+ * |-----------------------------------------------------------------------|
+ * | | F7 | F8 | F9 | F10 | F11 | F12 | | | | | |
+ * |-----------------------------------------------------------------------|
+ * | | | | | | | | | | | |
+ * `-----------------------------------------------------------------------'
+ */
+[_RS] = { /* RAISE */
+ {KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC},
+ {KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_MINS, KC_PLUS, KC_LBRC, KC_RBRC, KC_PIPE},
+ {KC_TRNS, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS}
+},
+/* MIT Layout (Lowered layer)
+ *
+ * ,-----------------------------------------------------------------------.
+ * | ~ | ! | @ | # | $ | % | ^ | & | * | ( | ) | |
+ * |-----------------------------------------------------------------------|
+ * | | F1 | F2 | F3 | F4 | F5 | F6 | _ | = | { | } | \ |
+ * |-----------------------------------------------------------------------|
+ * | | F7 | F8 | F9 | F10 | F11 | F12 | | | | | |
+ * |-----------------------------------------------------------------------|
+ * | | | | | | | | | | | |
+ * `-----------------------------------------------------------------------'
+ */
+[_LW] = { /* LOWER */
+ {KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_BSPC},
+ {KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_UNDS, KC_EQL, KC_LCBR, KC_RCBR, KC_BSLS},
+ {KC_TRNS, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS}
+},
+/* MIT Layout (FN layer)
+ *
+ * ,-----------------------------------------------------------------------.
+ * | | | | | | | | | | | | del |
+ * |-----------------------------------------------------------------------|
+ * | | | | | | | | | | | | |
+ * |-----------------------------------------------------------------------|
+ * | | | | | | | | | | | | |
+ * |-----------------------------------------------------------------------|
+ * | | | | | | | |home |pgdn |pgup | end |
+ * `-----------------------------------------------------------------------'
+ */
+[_FN] = { /* FUNCTION */
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_DELT},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_HOME, KC_PGDN, KC_PGUP, KC_END}
+}
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ backlight_step();
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
diff --git a/keyboards/planck/keymaps/jacob/Keyboard Layout.PNG b/keyboards/planck/keymaps/jacob/Keyboard Layout.PNG
new file mode 100644
index 000000000..40f0b8942
--- /dev/null
+++ b/keyboards/planck/keymaps/jacob/Keyboard Layout.PNG
Binary files differ
diff --git a/keyboards/planck/keymaps/jacob/Makefile b/keyboards/planck/keymaps/jacob/Makefile
new file mode 100644
index 000000000..581e08cd0
--- /dev/null
+++ b/keyboards/planck/keymaps/jacob/Makefile
@@ -0,0 +1,25 @@
+
+
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = yes # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/planck/keymaps/jacob/keymap.c b/keyboards/planck/keymaps/jacob/keymap.c
new file mode 100644
index 000000000..5e6e8498e
--- /dev/null
+++ b/keyboards/planck/keymaps/jacob/keymap.c
@@ -0,0 +1,56 @@
+#include "planck.h"
+#include "action_layer.h"
+#ifdef BACKLIGHT_ENABLE
+ #include "backlight.h"
+#endif
+
+//Simple Keymap where CTRL, WINKEY, and ALT keys are placed in a more familiar location for Windows users.
+//Focus of this particular keymap is to enable easy transition from more traditional keyboards to OLKB Planck.
+
+// Each layer gets a name for readability, which is then used in the keymap matrix below.
+#define _QW 0
+#define _LW 1
+#define _RS 2
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ [_QW] = { /* Qwerty */
+ {KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC},
+ {KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT},
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, MT(MOD_RSFT, KC_ENT)},
+ {KC_LCTL, KC_LGUI, KC_LALT, M(0), MO(_LW), KC_SPC, KC_SPC, MO(_RS), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+ },
+ [_RS] = { /* RAISE */
+ {KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_DEL },
+ {KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS},
+ {KC_TRNS, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS}
+ },
+ [_LW] = { /* LOWER */
+ {KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_DEL },
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_LBRC, KC_RBRC, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS}
+ }
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ #ifdef BACKLIGHT_ENABLE
+ backlight_step();
+ #endif
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
diff --git a/keyboards/planck/keymaps/jacob/readme.md b/keyboards/planck/keymaps/jacob/readme.md
new file mode 100644
index 000000000..2a4be4ebc
--- /dev/null
+++ b/keyboards/planck/keymaps/jacob/readme.md
@@ -0,0 +1 @@
+Focus of this particular keymap is to enable easy transition from more traditional keyboards to OLKB Planck. \ No newline at end of file
diff --git a/keyboards/planck/keymaps/joe/Makefile b/keyboards/planck/keymaps/joe/Makefile
new file mode 100644
index 000000000..581e08cd0
--- /dev/null
+++ b/keyboards/planck/keymaps/joe/Makefile
@@ -0,0 +1,25 @@
+
+
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = yes # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/planck/keymaps/joe/keymap.c b/keyboards/planck/keymaps/joe/keymap.c
new file mode 100644
index 000000000..023e1a120
--- /dev/null
+++ b/keyboards/planck/keymaps/joe/keymap.c
@@ -0,0 +1,89 @@
+#include "keymap.h"
+#include "keymap_colemak.h"
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ [0] = { /* Joe colemak */
+ {F(3), KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_MINS},
+ {KC_BSPC, KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, KC_ENT },
+ {F(15), KC_Z, KC_X, KC_C, KC_V, KC_B, KC_K, KC_M, KC_COMM, KC_DOT, KC_UP, KC_QUOT},
+ {KC_LCTL, KC_LGUI, KC_LALT, KC_LSFT, F(1), KC_SPC, KC_SPC, F(2), KC_SLSH, KC_LEFT, KC_DOWN, KC_RGHT}
+ },
+ [1] = { /* Joe soft Colemak */
+ {F(3), CM_Q, CM_W, CM_F, CM_P, CM_G, CM_J, CM_L, CM_U, CM_Y, CM_SCLN, KC_MINS},
+ {KC_BSPC, CM_A, CM_R, CM_S, CM_T, CM_D, CM_H, CM_N, CM_E, CM_I, CM_O, KC_ENT },
+ {F(15), CM_Z, CM_X, CM_C, CM_V, CM_B, CM_K, CM_M, KC_COMM, KC_DOT, KC_UP, KC_QUOT},
+ {KC_LCTL, KC_LGUI, KC_LALT, KC_LSFT, F(1), KC_SPC, KC_SPC, F(2), KC_SLSH, KC_LEFT, KC_DOWN, KC_RGHT}
+ },
+ [2] = { /* Joe NUMPAD */
+ {F(3), KC_NO, KC_UP, KC_NO, KC_NO, KC_NO, LSFT(KC_9), LSFT(KC_0), KC_PSLS, KC_P7, KC_P8, KC_P9 },
+ {KC_BSPC, KC_LEFT, KC_DOWN, KC_RGHT, KC_NO, KC_NO, LSFT(KC_5), KC_PEQL, KC_PAST, KC_P4, KC_P5, KC_P6 },
+ {F(15), KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_PCMM, KC_PMNS, KC_P1, KC_P2, KC_P3 },
+ {KC_LCTL, KC_LGUI, KC_LALT, KC_LSFT, F(1), KC_TRNS, KC_TRNS, F(2), KC_PPLS, KC_P0, KC_PDOT, KC_PENT}
+ },
+ [3] = { /* Joe 1337 haxOr5*/
+ {F(3), KC_Q, KC_W, KC_F, KC_P, KC_6, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_MINS},
+ {KC_BSPC, KC_4, KC_R, KC_5, KC_7, KC_D, KC_H, KC_N, KC_3, KC_1, KC_0, KC_ENT },
+ {F(15), KC_Z, KC_X, KC_C, KC_V, KC_B, KC_K, KC_M, KC_COMM, KC_DOT, KC_UP, KC_QUOT},
+ {KC_LCTL, KC_LGUI, KC_LALT, KC_LSFT, F(1), KC_SPC, KC_SPC, F(2), KC_SLSH, KC_LEFT, KC_DOWN, KC_RGHT}
+ },
+ [4] = { /* Joe LOWER fn1 */
+ {KC_GRV, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, M(3), M(2), M(1), M(0) },
+ {KC_BSPC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_TRNS},
+ {KC_BSLS, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_LBRC, KC_RBRC, KC_PGUP, KC_EQL },
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, F(1), KC_TRNS, KC_TRNS, F(2), KC_NO, KC_HOME, KC_PGDN, KC_END }
+ },
+ [5] = { /* Joe UPPER fn2 */
+ {KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12 },
+ {KC_DEL, KC_BTN1, KC_MS_U, KC_BTN2, KC_BTN3, KC_WH_U, KC_BTN4, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, KC_NO },
+ {KC_TRNS, KC_MS_L, KC_MS_D, KC_MS_R, KC_WH_L, KC_WH_D, KC_WH_R, KC_NO, KC_NO, LCTL(KC_PGUP), LCTL(LALT(KC_UP)), LCTL(KC_PGDN) },
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, F(1), KC_NO, KC_NO, F(2), KC_NO, LCTL(LALT(KC_LEFT)), LCTL(LALT(KC_DOWN)), LCTL(LALT(KC_RGHT))}
+ },
+ [6] = { /* Joe SPECIAL fn3 */
+ {KC_TRNS, KC_MUTE, KC_VOLD, KC_VOLU, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO },
+ {KC_NO, KC_MPLY, KC_MPRV, KC_MNXT, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, RESET },
+ {KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO },
+ {F(6), F(7), F(8), F(9), F(1), KC_TRNS, KC_TRNS, F(2), KC_POWER, KC_WAKE, KC_SLEP, LCTL(LALT(KC_L))}
+ }
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_MOMENTARY(4), // fn1
+ [2] = ACTION_LAYER_MOMENTARY(5), // fn2
+
+ /* ESC on tap, fn3 on hold */
+ [3] = ACTION_LAYER_TAP_KEY(6, KC_ESC),
+
+ /* toggle layers */
+ [6] = ACTION_DEFAULT_LAYER_SET(0),
+ [7] = ACTION_DEFAULT_LAYER_SET(1),
+ [8] = ACTION_DEFAULT_LAYER_SET(2),
+ [9] = ACTION_DEFAULT_LAYER_SET(3),
+
+ /* tab on tap, shift on hold */
+ [15] = ACTION_MODS_TAP_KEY(MOD_LSFT, KC_TAB),
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ switch (id) {
+ case 0:
+ /* :) */
+ return MACRODOWN( DOWN(KC_LSFT), TYPE(KC_SCLN), TYPE(KC_0), UP(KC_LSFT), END );
+ break;
+ case 1:
+ /* :( */
+ return MACRODOWN( DOWN(KC_LSFT), TYPE(KC_SCLN), TYPE(KC_9), UP(KC_LSFT), END );
+ break;
+ case 2:
+ /* (: | :) */
+ return MACRODOWN( DOWN(KC_LSFT), TYPE(KC_9), TYPE(KC_SCLN), TYPE(KC_SPC), TYPE(KC_SPC), TYPE(KC_SCLN), TYPE(KC_0), UP(KC_LSFT), TYPE(KC_LEFT), TYPE(KC_LEFT), TYPE(KC_LEFT), END );
+ break;
+ case 3:
+ /* :( | ): */
+ return MACRODOWN( DOWN(KC_LSFT), TYPE(KC_SCLN), TYPE(KC_9), TYPE(KC_SPC), TYPE(KC_SPC), TYPE(KC_0), TYPE(KC_SCLN), UP(KC_LSFT), TYPE(KC_LEFT), TYPE(KC_LEFT), TYPE(KC_LEFT), END );
+ break;
+ default:
+ break;
+ }
+ return MACRO_NONE;
+}
diff --git a/keyboards/planck/keymaps/kyle/Makefile b/keyboards/planck/keymaps/kyle/Makefile
new file mode 100644
index 000000000..581e08cd0
--- /dev/null
+++ b/keyboards/planck/keymaps/kyle/Makefile
@@ -0,0 +1,25 @@
+
+
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = yes # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/planck/keymaps/kyle/keymap.c b/keyboards/planck/keymaps/kyle/keymap.c
new file mode 100644
index 000000000..f113d0e03
--- /dev/null
+++ b/keyboards/planck/keymaps/kyle/keymap.c
@@ -0,0 +1,38 @@
+#include "keymap.h"
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[0] = { /* Qwerty */
+ {KC_ESC, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC},
+ {KC_TAB, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT},
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT},
+ {KC_RCTL, KC_LCTL, KC_LALT, KC_LGUI, FUNC(2), KC_SPC, KC_SPC, FUNC(1), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+ // Space is repeated to accommadate for both spacebar wiring positions
+},
+[1] = { /* Colemak */
+ {KC_ESC, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_BSPC},
+ {KC_TAB, KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT},
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_K, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT},
+ {KC_FN3, KC_LCTL, KC_LALT, KC_LGUI, FUNC(2), KC_SPC, KC_SPC, FUNC(1), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+[2] = { /* RAISE */
+ {KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC},
+ {KC_TRNS, FUNC(3), FUNC(4), LSFT(RSFT(KC_PAUSE)), KC_TRNS, KC_TRNS, KC_TRNS, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS},
+ {KC_TRNS, KC_F11, KC_F12, KC_F13, KC_F14, KC_F15, KC_F16, KC_F17, KC_F18, KC_F19, KC_F20, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, FUNC(1), KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
+},
+[3] = { /* LOWER */
+ {S(KC_GRV), S(KC_1), S(KC_2), S(KC_3), S(KC_4), S(KC_5), S(KC_6), S(KC_7), S(KC_8), S(KC_9), S(KC_0), KC_BSPC},
+ {KC_TRNS, FUNC(3), FUNC(4), LSFT(RSFT(KC_PAUSE)), LSFT(RSFT(KC_D)), KC_TRNS, KC_TRNS, S(KC_MINS), S(KC_EQL), S(KC_LBRC), S(KC_RBRC), S(KC_BSLS)},
+ {KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_TRNS},
+ {BL_STEP, KC_TRNS, KC_TRNS, KC_TRNS, FUNC(2), KC_TRNS, KC_TRNS, KC_TRNS, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
+}
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_MOMENTARY(2), // to RAISE
+ [2] = ACTION_LAYER_MOMENTARY(3), // to LOWER
+
+ [3] = ACTION_DEFAULT_LAYER_SET(0),
+ [4] = ACTION_DEFAULT_LAYER_SET(1),
+
+};
diff --git a/keyboards/planck/keymaps/leo/Makefile b/keyboards/planck/keymaps/leo/Makefile
new file mode 100644
index 000000000..581e08cd0
--- /dev/null
+++ b/keyboards/planck/keymaps/leo/Makefile
@@ -0,0 +1,25 @@
+
+
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = yes # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/planck/keymaps/leo/keymap.c b/keyboards/planck/keymaps/leo/keymap.c
new file mode 100644
index 000000000..25a5e1579
--- /dev/null
+++ b/keyboards/planck/keymaps/leo/keymap.c
@@ -0,0 +1,35 @@
+#include "keymap.h"
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[0] = { /* BASE */
+ {KC_ESC, KC_LBRC, KC_QUOT, KC_SCLN, KC_P, KC_Y, KC_F, KC_G, KC_C, KC_R, KC_L, KC_BSPC},
+ {KC_TAB, KC_A, KC_O, KC_E, KC_U, KC_I, KC_D, KC_H, KC_T, KC_N, KC_S, KC_ENT},
+ {KC_LSFT, KC_DOT, KC_Q, KC_J, KC_K, KC_X, KC_B, KC_M, KC_W, KC_V, KC_Z, KC_COMM},
+ {KC_LCTL, KC_LALT, KC_LGUI, FUNC(3), FUNC(2), KC_SPC, KC_SPC, FUNC(1), FUNC(3), KC_RGUI, KC_RALT, KC_RCTL}
+},
+[2] = { /* RAISE */
+ {RALT(KC_RBRC), KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, S(KC_RBRC)},
+ {KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS}
+},
+[3] = { /* LOWER */
+ {S(KC_EQL),S(KC_1),S(KC_2),S(KC_3),RALT(KC_5),S(KC_5), S(KC_6), S(KC_7),RALT(KC_7),RALT(KC_0),S(KC_0), KC_MINS},
+ {KC_TRNS,RALT(KC_2),S(KC_SLSH),KC_NUBS,S(KC_NUBS),RALT(KC_MINS),RALT(KC_NUBS), KC_NUHS, S(KC_8), S(KC_9), S(KC_MINS), KC_SLSH},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, RALT(KC_8), RALT(KC_9), KC_TRNS, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS}
+},
+[4] = { /* META */
+ {KC_TRNS, KC_HOME, KC_UP, KC_END, KC_TRNS, KC_TRNS, KC_TRNS, KC_HOME, KC_UP, KC_END, KC_TRNS, KC_DEL},
+ {KC_TRNS, KC_RGHT, KC_DOWN, KC_LEFT, KC_PGUP, KC_TRNS, KC_PGUP, KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PGDN, KC_TRNS, KC_PGDN, KC_TRNS, KC_VOLD, KC_VOLU, KC_TRNS, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS}
+}
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_MOMENTARY(2), // to RAISE
+ [2] = ACTION_LAYER_MOMENTARY(3), // to LOWER
+ [3] = ACTION_LAYER_MOMENTARY(4), // to META
+
+}; \ No newline at end of file
diff --git a/keyboards/planck/keymaps/lucas/Makefile b/keyboards/planck/keymaps/lucas/Makefile
new file mode 100644
index 000000000..581e08cd0
--- /dev/null
+++ b/keyboards/planck/keymaps/lucas/Makefile
@@ -0,0 +1,25 @@
+
+
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = yes # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/planck/keymaps/lucas/keymap.c b/keyboards/planck/keymaps/lucas/keymap.c
new file mode 100644
index 000000000..2208780b1
--- /dev/null
+++ b/keyboards/planck/keymaps/lucas/keymap.c
@@ -0,0 +1,164 @@
+/*
+This is the keymap of /u/deepshitgoeshere!
+Layer 1 exists so I can have the symbol positions of QWERTY while having my system in german.
+The second layer has all the german umlauts I need and with capital and small letters on the
+same layer there is no need to press shift+lower.
+This keymap is made to work with software implemented QWERTZ.
+The "Gaming" layer is mainly customized for CS:GO.
+If you have any question about this keymap feel free to shoot me a message on reddit!
+*/
+
+#include "keymap.h"
+#include "keymap_german.h"
+#include "backlight.h"
+#include "debug.h"
+#include "action_layer.h"
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[0] = { /* Colemak
+ * ,-----------------------------------------------------------------------.
+ * | Esc | q | w | f | p | g | j | l | u | y | ; | - |
+ * |-----------------------------------------------------------------------|
+ * | BS | a | r | s | t | d | h | n | e | i | o | ' |
+ * |-----------------------------------------------------------------------|
+ * | SFT | z | x | c | v | b | k | m | , | . | / | Ent |
+ * |-----------------------------------------------------------------------|
+ * | CTL | GUI | Tab | ALT |Lower| Space |Raise|Left |Down | Up |Right|
+ * `-----------------------------------------------------------------------'
+ */
+ {KC_ESC, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Z, DE_SCLN, DE_MINS},
+ {KC_BSPC, KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, DE_QUOT},
+ {M(0), KC_Y, KC_X, KC_C, KC_V, KC_B, KC_K, KC_M, DE_COMM, DE_DOT, DE_SLSH, KC_ENT},
+ {KC_LCTL, KC_LGUI, KC_TAB, KC_LALT, F(2), F(3), F(3), F(1), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+[1] = { /* Symbols
+ * ,-----------------------------------------------------------------------.
+ * | | | | | | | | | | | : | |
+ * |-----------------------------------------------------------------------|
+ * | | | | | | | | | | | | " |
+ * |-----------------------------------------------------------------------|
+ * | | | | | | | | | < | > | ? | |
+ * |-----------------------------------------------------------------------|
+ * | | | | | | | | | | | |
+ * `-----------------------------------------------------------------------'
+ */
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, DE_DOT, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, DE_DQOT},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, M(1), DE_MORE, DE_QST, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS}
+},
+[2] = { /* Raise
+ * ,-----------------------------------------------------------------------.
+ * | | Ä | | | | | | | Ü | Ö | |Game |
+ * |-----------------------------------------------------------------------|
+ * | Del | ä | | ß | | | | | ü | ö | |FVol+|
+ * |-----------------------------------------------------------------------|
+ * | | | | | | | | |Stop | Prv | Nxt |FVol-|
+ * |-----------------------------------------------------------------------|
+ * |LCTL |LGUI | Tab |LALT |Lower| Space | |Mute |Vol- |Vol+ | P/P |
+ * `-----------------------------------------------------------------------'
+ */
+ {KC_NO, S(DE_AE), KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, S(DE_UE), S(DE_OE), KC_NO, F(4)},
+ {KC_DEL, DE_AE, KC_NO, DE_SS, KC_NO, KC_NO, KC_NO, KC_NO, DE_UE, DE_OE, KC_NO, RALT(KC_F12)},
+ {KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_MSTP, KC_MPRV, KC_MNXT, RALT(KC_F11)},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MUTE, KC_VOLD, KC_VOLU, KC_MPLY}
+},
+[3] = { /* Lower
+ * ,-----------------------------------------------------------------------.
+ * | ~ | ! | @ | # | $ | % | ^ | & | * | ( | ) | + |
+ * |-----------------------------------------------------------------------|
+ * | ` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | = |
+ * |-----------------------------------------------------------------------|
+ * | | | | | | [ | ] | { | } | € | | \ | Ent |
+ * |-----------------------------------------------------------------------|
+ * |LCTL |LGUI | Tab |LALT | | Space |Raise|Home |PgDn |PgUp | End |
+ * `-----------------------------------------------------------------------'
+ */
+ {DE_TILD, DE_EXLM, DE_AT, DE_HASH, DE_DLR, DE_PERC, DE_CIRC, DE_AMPR, DE_ASTR, DE_LPRN, DE_RPRN, DE_PLUS},
+ {DE_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, DE_EQL},
+ {KC_NO, KC_NO, KC_NO, DE_PIPE, DE_LBRC, DE_RBRC, DE_LCBR, DE_RCBR, DE_EURO, KC_NO, DE_BSLS, KC_ENT},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_HOME, KC_PGDN, KC_PGUP, KC_END}
+},
+[4] = { /* Function
+ * ,-----------------------------------------------------------------------.
+ * | F13 | F14 | F15 | F16 | F17 | F18 | F19 | F20 | F21 | F22 | F23 | F24 |
+ * |-----------------------------------------------------------------------|
+ * | F1 | F2 | F3 | F4 | F5 | F6 | F7 | F8 | F9 | F10 | F11 | F12 |
+ * |-----------------------------------------------------------------------|
+ * | | | | | | KP- | KP+ | | | | |Reset|
+ * |-----------------------------------------------------------------------|
+ * | |Light|BL DN|BL UP| | | | |Mute |Vol- |Vol+ | P/P |
+ * `-----------------------------------------------------------------------'
+ */
+ {KC_F13, KC_F14, KC_F15, KC_F16, KC_F17, KC_F18, KC_F19, KC_F20, KC_F21, KC_F22, KC_F23, KC_F24},
+ {KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12},
+ {KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_PMNS, KC_PPLS, KC_NO, KC_NO, KC_NO, RESET, KC_NO},
+ {KC_NO, BL_TOGG, BL_DEC, BL_INC, FUNC(2), KC_TRNS, KC_TRNS, KC_TRNS, KC_MUTE, KC_VOLD, KC_VOLU, KC_MPLY}
+},
+[5] = { /* Gaming
+ * ,-----------------------------------------------------------------------.
+ * | Buy | ESC | q | w | e | r | t | y | u | i | o | p |
+ * |-----------------------------------------------------------------------|
+ * | ENT | BS | a | s | d | f | g | h | j | k | l | ; |
+ * |-----------------------------------------------------------------------|
+ * | CTL | SFT | z | x | c | v | b | n | m | , | Up | / |
+ * |-----------------------------------------------------------------------|
+ * | | | Tab | ALT | | Space |CrJmp| GUI |Left |Down |Right|
+ * `-----------------------------------------------------------------------'
+ */
+ {MO(6), KC_ESC, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Z, KC_U, KC_I, KC_O, F(4)},
+ {KC_ENT, KC_BSPC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, DE_SCLN},
+ {KC_LCTL, KC_LSFT, KC_Y, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, DE_DOT, KC_UP, DE_SLSH},
+ {KC_NO, KC_NO, KC_TAB, KC_LALT, KC_NO, KC_SPC, KC_SPC, LCTL(KC_SPC), KC_LGUI, KC_LEFT, KC_DOWN, KC_RGHT}
+},
+[6] = { /* Gaming
+ * CS:GO buy binds
+ * ,-----------------------------------------------------------------------.
+ * | | | | | | | | | 7 | 8 | 9 | |
+ * |-----------------------------------------------------------------------|
+ * | BS | | | | | | | | 6 | 5 | 4 | End |
+ * |-----------------------------------------------------------------------|
+ * | CTL | SFT | | | | | | | 1 | 2 | 3 |Pgdn |
+ * |-----------------------------------------------------------------------|
+ * | | | Tab | ALT | | Space |CrJmp| | 0 | KP+ |PEnt |
+ * `-----------------------------------------------------------------------'
+ */
+ {KC_TRNS, KC_NO, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_P7, KC_P8, KC_P9, KC_NO},
+ {KC_BSPC, KC_NO, KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_P4, KC_P5, KC_P6, KC_END},
+ {KC_LCTL, KC_LSFT, KC_Y, KC_X, KC_C, KC_V, KC_B, KC_K, KC_P1, KC_P2, KC_P3, KC_PGDN},
+ {KC_NO, KC_NO, KC_TAB, KC_LALT, KC_NO, KC_SPC, KC_SPC, LCTL(KC_SPC), KC_NO, KC_P0, KC_PDOT, KC_PENT}
+},
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_MOMENTARY(2), // to RAISE
+ [2] = ACTION_LAYER_MOMENTARY(3), // to LOWER
+ [3] = ACTION_LAYER_TAP_KEY(4,KC_SPC), // to Function
+ [4] = ACTION_LAYER_TOGGLE(5), // toggle Gaming
+ [5] = ACTION_MODS_TAP_KEY(KC_LSFT, KC_CAPS), //Shift on press, Caps on tap
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ switch(id) {
+ case 0: // M(0)
+ if (record->event.pressed) {
+ register_code(KC_LSFT);
+ layer_on(1);
+ } else {
+ layer_off(1);
+ unregister_code(KC_LSFT);
+ }
+ break;
+ case 1: // M(1)
+ if (record->event.pressed) {
+ unregister_code(KC_LSFT);
+ register_code(DE_MORE);
+ } else {
+ unregister_code(DE_MORE);
+ }
+ break;
+ }
+ return MACRO_NONE;
+
+}; \ No newline at end of file
diff --git a/keyboards/planck/keymaps/lukas/Makefile b/keyboards/planck/keymaps/lukas/Makefile
new file mode 100644
index 000000000..581e08cd0
--- /dev/null
+++ b/keyboards/planck/keymaps/lukas/Makefile
@@ -0,0 +1,25 @@
+
+
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = yes # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/planck/keymaps/lukas/keymap.c b/keyboards/planck/keymaps/lukas/keymap.c
new file mode 100644
index 000000000..6fd95378b
--- /dev/null
+++ b/keyboards/planck/keymaps/lukas/keymap.c
@@ -0,0 +1,64 @@
+#include "planck.h"
+#ifdef BACKLIGHT_ENABLE
+ #include "backlight.h"
+#endif
+
+// This simple keymap is optimized for xmonad users using super as their modifier key.
+// M(1) makes it possible to change virtual screens and swap windows between them.
+
+// Each layer gets a name for readability, which is then used in the keymap matrix below.
+#define _QW 0
+#define _LW 1
+#define _RS 2
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ [_QW] = { /* Qwerty */
+ {KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC},
+ {KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT},
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT },
+ {KC_LCTL, KC_LALT, KC_LGUI, M(1), MO(_LW), KC_SPC, KC_SPC, MO(_RS), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+ },
+ [_RS] = { /* RAISE */
+ {KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_DEL },
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS}
+ },
+ [_LW] = { /* LOWER */
+ {KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_BSPC},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_LBRC, KC_RBRC, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS}
+ }
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ #ifdef BACKLIGHT_ENABLE
+ backlight_step();
+ #endif
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ case 1:
+ if (record->event.pressed) {
+ register_code(KC_LGUI);
+ layer_on(_RS);
+ } else {
+ unregister_code(KC_LGUI);
+ layer_off(_RS);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
diff --git a/keyboards/planck/keymaps/max/Makefile b/keyboards/planck/keymaps/max/Makefile
new file mode 100644
index 000000000..581e08cd0
--- /dev/null
+++ b/keyboards/planck/keymaps/max/Makefile
@@ -0,0 +1,25 @@
+
+
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = yes # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/planck/keymaps/max/keymap.c b/keyboards/planck/keymaps/max/keymap.c
new file mode 100644
index 000000000..a93b1f47d
--- /dev/null
+++ b/keyboards/planck/keymaps/max/keymap.c
@@ -0,0 +1,38 @@
+#include "keymap.h"
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[0] = { /* Qwerty */
+ {KC_ESC, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC},
+ {KC_TAB, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_ENT },
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_QUOT},
+ {KC_LCTL, BL_STEP, KC_LALT, KC_LGUI, FUNC(2), KC_SPC, KC_SPC, FUNC(1), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+ // Space is repeated to accommadate for both spacebar wiring positions
+},
+[1] = { /* Colemak */
+ {KC_ESC, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_BSPC},
+ {KC_TAB, KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, KC_ENT },
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_K, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_QUOT},
+ {KC_LCTL, BL_STEP, KC_LALT, KC_LGUI, FUNC(2), KC_SPC, KC_SPC, FUNC(1), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+[2] = { /* RAISE */
+ {KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC},
+ {KC_TRNS, FUNC(3), FUNC(4), RESET, KC_TRNS, KC_TRNS, KC_TRNS, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_TRNS},
+ {KC_TRNS, KC_F11, KC_F12, KC_F13, KC_F14, KC_F15, KC_F16, KC_F17, KC_F18, KC_F19, KC_F20, KC_BSLS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, FUNC(1), KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
+},
+[3] = { /* LOWER */
+ {S(KC_GRV), S(KC_1), S(KC_2), S(KC_3), S(KC_4), S(KC_5), S(KC_6), S(KC_7), S(KC_8), S(KC_9), S(KC_0), KC_BSPC},
+ {KC_TRNS, FUNC(3), FUNC(4), RESET, KC_TRNS, KC_TRNS, KC_TRNS, S(KC_MINS), S(KC_EQL), S(KC_LBRC), S(KC_RBRC), KC_TRNS},
+ {KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, S(KC_BSLS)},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, FUNC(2), KC_TRNS, KC_TRNS, KC_TRNS, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
+}
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_MOMENTARY(2), // to RAISE
+ [2] = ACTION_LAYER_MOMENTARY(3), // to LOWER
+
+ [3] = ACTION_DEFAULT_LAYER_SET(0),
+ [4] = ACTION_DEFAULT_LAYER_SET(1),
+
+}; \ No newline at end of file
diff --git a/keyboards/planck/keymaps/mollat/Makefile b/keyboards/planck/keymaps/mollat/Makefile
new file mode 100644
index 000000000..581e08cd0
--- /dev/null
+++ b/keyboards/planck/keymaps/mollat/Makefile
@@ -0,0 +1,25 @@
+
+
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = yes # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/planck/keymaps/mollat/keymap.c b/keyboards/planck/keymaps/mollat/keymap.c
new file mode 100644
index 000000000..e7c71efd4
--- /dev/null
+++ b/keyboards/planck/keymaps/mollat/keymap.c
@@ -0,0 +1,149 @@
+//
+// This layout is based on the following needs:
+//
+// should be as close as possible to querty/us-international layout (using international/AltGr as o/s driver)
+// added german umlauts at known places from de-layout
+// all movement keys should be at known places from vi/bash (eg HJKL for cursor keys)
+// Fn layer (at CapsLock place like the Pok3r does) for missing keys
+// additional layer for tmux window switching
+//
+// This is work in Progress! If you have suggestions write me at github.com/mollat/qmk_firmware/ and check
+// this fork for updates as I probably won't bother jack with my pull requests frequently.
+//
+
+#include "planck.h"
+
+#define _QWERTY 0
+#define _HIGH 1
+#define _LOW 2
+#define _FN 3
+#define _TMUX 4
+#define _LCTL 5
+#define _MOUSE 6
+#define __________ KC_NO // just for easy reading
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+
+[_QWERTY] = { /* Qwerty */
+ { LT(_MOUSE, KC_ESC),KC_Q,KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC },
+ { LT(_FN, KC_TAB),KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT },
+ { KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, SFT_T(KC_ENT)},
+ { __________, __________, KC_LGUI, KC_LALT, KC_LCTL,LT(_TMUX, KC_SPC),LT(_HIGH, KC_SPC),MO(_LOW),KC_RALT,KC_RGUI, __________, __________ }
+},
+
+// missing keys regarding to the form factor
+// keeping the dot and comma for typing faster IP addresses and (german) float values
+// putting the backslash on the slash's place
+[_HIGH] = {
+ { KC_GRV, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_MINS },
+ { __________, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_EQL },
+ { __________, __________, __________, __________, __________, __________, __________, __________, KC_COMM, KC_DOT, KC_BSLS, LSFT(KC_BSLS)},
+ { __________, __________, __________, __________, __________, __________, KC_TRNS, __________, __________, __________, __________, __________ }
+},
+
+// classic Fn-Layer triggered with 'CapsLock-key' like on Pok3r
+// SPC and ENT are doubled for using repeat (which I switched off, see https://github.com/tmk/tmk_keyboard/issues/287)
+// '€' sign is on the '5' position as this is the usual AltGr place on the US Internation layout
+// home/end at the 'a' and 'e' position like in bash
+// ins at 'i'
+// del besides backspace (had no better place for it because of the umlauts)
+// pg-down at 'f' (forward in vi), pg-up at 'b' (back in 'vi')
+//
+[_FN] = {
+ { __________, __________, __________, KC_END, __________, __________, __________, __________, KC_INS, __________, KC_DEL, RALT(KC_Y) },
+ { KC_TRNS, __________, RALT(KC_S), __________, KC_PGDN, RALT(KC_5), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, RALT(KC_P), RALT(KC_Q) },
+ { __________, KC_HOME, __________, __________, __________, KC_PGUP, __________, __________, __________, __________, __________, KC_ENT },
+ { RESET, __________, __________, __________, __________, KC_SPC, KC_SPC, __________, __________, __________, __________, __________ }
+},
+
+// function key layer and some shift + (missing key at the small form factor)
+[_LOW] = {
+ { KC_TILD, __________, __________, __________, __________, __________, __________, __________, __________, KC_LCBR, KC_RCBR, KC_UNDS },
+ { __________, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_LBRC, KC_RBRC, KC_PLUS },
+ { __________, __________, __________, __________, __________, KC_F9, KC_F10, KC_F11, KC_F12, __________, __________, __________ },
+ { __________, __________, __________, __________, __________, __________, __________, KC_TRNS, __________, __________, __________, __________ }
+},
+
+// most macros will switch tmux screens
+// two macros are for vi's save/quit at 'w' and 'q'
+[_TMUX] = {
+ { __________, M(14), M(13), __________, __________, __________, __________, __________, __________, __________, M(11), __________ },
+ { M(0), M(1), M(2), M(3), M(4), M(5), M(6), M(7), M(8), M(9), __________, __________ },
+ { __________, __________, __________, M(12), __________, __________, M(10), __________, __________, __________, __________, __________ },
+ { __________, __________, __________, __________, __________, KC_TRNS, __________, __________, __________, __________, __________, __________ }
+},
+
+// mouse movement can be improved (e.g. can't press hj at once), but I will use this seldom, so I stick with hjkl keys.
+[_MOUSE] = {
+ { KC_TRNS, __________, __________, __________, __________, __________, __________, __________, __________, __________, __________, __________ },
+ { __________, __________, __________, __________, KC_WH_D, __________, KC_MS_L, KC_MS_D, KC_MS_U, KC_MS_R, __________, __________ },
+ { __________, __________, __________, __________, __________, KC_WH_U, __________, __________, __________, __________, __________, __________ },
+ { __________, __________, __________, KC_ACL2, KC_ACL1, KC_ACL0, KC_MS_BTN1, KC_MS_BTN3, KC_MS_BTN2, __________, __________, __________ }
+}
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [_LCTL] = ACTION_MODS_TAP_KEY(KC_LCTL, M(12)), // does not work
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ switch(id) {
+ case 0:
+ return MACRODOWN( DOWN(KC_LCTL), TYPE(KC_B), UP(KC_LCTL), TYPE(KC_0), END );
+ break;
+ case 1:
+ return MACRODOWN( DOWN(KC_LCTL), TYPE(KC_B), UP(KC_LCTL), TYPE(KC_1), END );
+ break;
+ case 2:
+ return MACRODOWN( DOWN(KC_LCTL), TYPE(KC_B), UP(KC_LCTL), TYPE(KC_2), END );
+ break;
+ case 3:
+ return MACRODOWN( DOWN(KC_LCTL), TYPE(KC_B), UP(KC_LCTL), TYPE(KC_3), END );
+ break;
+ case 4:
+ return MACRODOWN( DOWN(KC_LCTL), TYPE(KC_B), UP(KC_LCTL), TYPE(KC_4), END );
+ break;
+ case 5:
+ return MACRODOWN( DOWN(KC_LCTL), TYPE(KC_B), UP(KC_LCTL), TYPE(KC_5), END );
+ break;
+ case 6:
+ return MACRODOWN( DOWN(KC_LCTL), TYPE(KC_B), UP(KC_LCTL), TYPE(KC_6), END );
+ break;
+ case 7:
+ return MACRODOWN( DOWN(KC_LCTL), TYPE(KC_B), UP(KC_LCTL), TYPE(KC_7), END );
+ break;
+ case 8:
+ return MACRODOWN( DOWN(KC_LCTL), TYPE(KC_B), UP(KC_LCTL), TYPE(KC_8), END );
+ break;
+ case 9:
+ // tmux last window
+ return MACRODOWN( DOWN(KC_LCTL), TYPE(KC_B), UP(KC_LCTL), TYPE(KC_L), END );
+ break;
+ // tmux next window
+ case 10:
+ return MACRODOWN( DOWN(KC_LCTL), TYPE(KC_B), UP(KC_LCTL), TYPE(KC_N), END );
+ break;
+ // tmux previous window
+ case 11:
+ return MACRODOWN( DOWN(KC_LCTL), TYPE(KC_B), UP(KC_LCTL), TYPE(KC_P), END );
+ break;
+ // tmux new window
+ case 12:
+ return MACRODOWN( DOWN(KC_LCTL), TYPE(KC_B), UP(KC_LCTL), TYPE(KC_C), END );
+ break;
+ case 13:
+ // vi save document
+ return MACRODOWN( TYPE(KC_ESC), DOWN(KC_LSFT), TYPE(KC_SCLN), UP(KC_LSFT), TYPE(KC_W), TYPE(KC_ENT), END );
+ break;
+ case 14:
+ // vi quit
+ return MACRODOWN( TYPE(KC_ESC), DOWN(KC_LSFT), TYPE(KC_SCLN), UP(KC_LSFT), TYPE(KC_Q), TYPE(KC_ENT), END );
+ break;
+ // tmux press ctrl-b
+ case 15:
+ return MACRODOWN( DOWN(KC_LCTL), TYPE(KC_B), UP(KC_LCTL), END );
+ break;
+ }
+ return MACRO_NONE;
+};
diff --git a/keyboards/planck/keymaps/nico/Makefile b/keyboards/planck/keymaps/nico/Makefile
new file mode 100644
index 000000000..581e08cd0
--- /dev/null
+++ b/keyboards/planck/keymaps/nico/Makefile
@@ -0,0 +1,25 @@
+
+
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = yes # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/planck/keymaps/nico/keymap.c b/keyboards/planck/keymaps/nico/keymap.c
new file mode 100644
index 000000000..e81fd80a4
--- /dev/null
+++ b/keyboards/planck/keymaps/nico/keymap.c
@@ -0,0 +1,69 @@
+// This is the canonical layout file for the Quantum project. If you want to add another keyboard,
+// this is the style you want to emulate.
+
+#include "planck.h"
+#include "backlight.h"
+
+// Each layer gets a name for readability, which is then used in the keymap matrix below.
+// The underscores don't mean anything - you can have a layer called STUFF or any other name.
+// Layer names don't all need to be of the same length, obviously, and you can also skip them
+// entirely and just use numbers.
+#define _QW 0
+#define _CM 1
+#define _DV 2
+#define _LW 3
+#define _RS 4
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[_QW] = { /* Qwerty */
+ {KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC},
+ {KC_LCTL, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT},
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT },
+ {M(0), KC_ESC, KC_LALT, KC_LGUI, F(1), KC_SPC, KC_SPC, F(2), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+[_CM] = { /* Colemak */
+ {KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_BSPC},
+ {KC_LCTL, KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT},
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_K, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT },
+ {M(0), KC_ESC, KC_LALT, KC_LGUI, F(1), KC_SPC, KC_SPC, F(2), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+[_DV] = { /* Dvorak */
+ {KC_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, KC_F, KC_G, KC_C, KC_R, KC_L, KC_BSPC},
+ {KC_LCTL, KC_A, KC_O, KC_E, KC_U, KC_I, KC_D, KC_H, KC_T, KC_N, KC_S, KC_SLSH},
+ {KC_LSFT, KC_SCLN, KC_Q, KC_J, KC_K, KC_X, KC_B, KC_M, KC_W, KC_V, KC_Z, KC_ENT },
+ {M(0), KC_ESC, KC_LALT, KC_LGUI, F(1), KC_SPC, KC_SPC, F(2), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+[_RS] = { /* RAISE */
+ {KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC},
+ {KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS},
+ {KC_TRNS, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, DF(_QW), DF(_CM), DF(_DV), RESET, KC_TRNS},
+ {M(0), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_F14, KC_F15, KC_TRNS, KC_MFFD, KC_VOLD, KC_VOLU, KC_MPLY}
+},
+[_LW] = { /* LOWER */
+ {KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_BSPC},
+ {KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE},
+ {KC_TRNS, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, DF(_QW), DF(_CM), DF(_DV), RESET, KC_TRNS},
+ {M(0), KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_F14, KC_F15, KC_TRNS, KC_MFFD, KC_VOLD, KC_VOLU, KC_MPLY}
+}
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_TAP_KEY(MO(_LW), KC_BSPC), // Tap for backspace, hold for LOWER
+ [2] = ACTION_LAYER_TAP_KEY(MO(_RS), KC_ENT), // Tap for enter, hold for RAISE
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ backlight_step();
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
diff --git a/keyboards/planck/keymaps/pete/Makefile b/keyboards/planck/keymaps/pete/Makefile
new file mode 100644
index 000000000..20bba3f49
--- /dev/null
+++ b/keyboards/planck/keymaps/pete/Makefile
@@ -0,0 +1,15 @@
+
+
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+AUDIO_ENABLE = no
+NKRO_ENABLE = yes
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/planck/keymaps/pete/keymap.c b/keyboards/planck/keymaps/pete/keymap.c
new file mode 100644
index 000000000..38275b403
--- /dev/null
+++ b/keyboards/planck/keymaps/pete/keymap.c
@@ -0,0 +1,266 @@
+// This is the canonical layout file for the Quantum project. If you want to add another keyboard,
+// this is the style you want to emulate.
+
+#include "planck.h"
+#include "action_layer.h"
+#ifdef AUDIO_ENABLE
+ #include "audio.h"
+#endif
+#include "eeconfig.h"
+
+extern keymap_config_t keymap_config;
+
+// Each layer gets a name for readability, which is then used in the keymap matrix below.
+// The underscores don't mean anything - you can have a layer called STUFF or any other name.
+// Layer names don't all need to be of the same length, obviously, and you can also skip them
+// entirely and just use numbers.
+#define _QWERTY 0
+#define _COLEMAK 1
+#define _DVORAK 2
+#define _LOWER 3
+#define _RAISE 4
+#define _FCT 5
+#define _SETUP 6
+#define _MAC 7
+#define _WIN 8
+#define _LIN 9
+#define _MICMUTE 16
+#define _OS 17
+
+
+// Macro name shortcuts
+#define QWERTY M(_QWERTY)
+#define COLEMAK M(_COLEMAK)
+#define DVORAK M(_DVORAK)
+#define LOWER M(_LOWER)
+#define RAISE M(_RAISE)
+#define FCT M(_FCT)
+#define OS M(_OS)
+#define MAC M(_MAC)
+#define WIN M(_WIN)
+#define LIN M(_LIN)
+#define MICMUTE M(_MICMUTE)
+
+#define MACPRNT LGUI(LSFT(KC_3))
+#define MACPRNT2 LGUI(LSFT(KC_4))
+#define WINPRNT KC_PSCR
+#define WINPRNT2 LGUI(KC_PSCR)
+#define CYCLWIN LGUI(KC_GRV)
+#define MACSLEEP LSFT(LCTL(KC_POWER))
+#define WINSLEEP KC_SLEP
+
+// Fillers to make layering more clear
+#define _______ KC_TRNS
+#define XXXXXXX KC_NO
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+
+[_QWERTY] = {
+ {KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC},
+ {KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT},
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT },
+ {OS, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+
+[_COLEMAK] = {
+ {KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_BSPC},
+ {KC_ESC, KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT},
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_K, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT },
+ {OS, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+
+[_DVORAK] = {
+ {KC_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, KC_F, KC_G, KC_C, KC_R, KC_L, KC_BSPC},
+ {KC_ESC, KC_A, KC_O, KC_E, KC_U, KC_I, KC_D, KC_H, KC_T, KC_N, KC_S, KC_SLSH},
+ {KC_LSFT, KC_SCLN, KC_Q, KC_J, KC_K, KC_X, KC_B, KC_M, KC_W, KC_V, KC_Z, KC_ENT },
+ {OS, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+
+[_LOWER] = {
+ {KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_BSPC},
+ {_______, _______, _______, _______, _______, _______, _______, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE},
+ {_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______},
+ {_______, _______, _______, _______, _______, _______, _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
+},
+
+[_RAISE] = {
+ {KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC},
+ {_______, _______, _______, _______, _______, _______, _______, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS},
+ {_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______},
+ {_RAISE, _______, _______, _______, _______, _______, _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
+},
+
+[_SETUP] = { /* Setup */
+ {_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______},
+ {_______, _______, _______, WIN, MAC, _______, _______, QWERTY, COLEMAK, DVORAK, _______, _______},
+ {_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______},
+ {_______, _______, _______, _______, _______, RESET, RESET, _______, _______, _______, _______, _______}
+},
+[_MAC] = { /* Mac */
+ {CYCLWIN,MACSLEEP, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_F1, KC_F2, KC_F3, KC_F4, KC_DELT},
+ {_______, MICMUTE, KC_MUTE, KC_VOLD, KC_VOLU, MACPRNT,MACPRNT2, KC_F5, KC_F6, KC_F7, KC_F8, XXXXXXX},
+ {_______, BL_STEP, KC_MPRV, KC_MPLY, KC_MNXT, XXXXXXX, XXXXXXX, KC_F9, KC_F10, KC_F11, KC_F12, XXXXXXX},
+ {_______, _______, _______, _______, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_HOME, KC_PGDOWN,KC_PGUP,KC_END }
+},
+[_WIN] = { /* Windows */
+ {CYCLWIN,WINSLEEP, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_F1, KC_F2, KC_F3, KC_F4, KC_DELT},
+ {_______, MICMUTE, KC_MUTE, KC_VOLD, KC_VOLU, WINPRNT,WINPRNT2, KC_F5, KC_F6, KC_F7, KC_F8, XXXXXXX},
+ {_______, BL_STEP, KC_MPRV, KC_MPLY, KC_MNXT, XXXXXXX, XXXXXXX, KC_F9, KC_F10, KC_F11, KC_F12, XXXXXXX},
+ {_______, _______, _______, _______, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_HOME, KC_PGDOWN,KC_PGUP,KC_END }
+},
+[_LIN] = { /* Linux */
+ {KC_L, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______},
+ {_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______},
+ {_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______},
+ {_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______}
+}
+
+};
+
+int currentOs = _MAC;
+const uint16_t PROGMEM fn_actions[] = {
+
+};
+
+#ifdef AUDIO_ENABLE
+
+float tone_startup[][2] = {
+ {440.0*pow(2.0,(31)/12.0), 12},
+ {440.0*pow(2.0,(28)/12.0), 8},
+ {440.0*pow(2.0,(19)/12.0), 8},
+ {440.0*pow(2.0,(24)/12.0), 8},
+ {440.0*pow(2.0,(28)/12.0), 20}
+};
+
+float tone_qwerty[][2] = SONG(QWERTY_SOUND);
+float tone_dvorak[][2] = SONG(DVORAK_SOUND);
+float tone_colemak[][2] = SONG(COLEMAK_SOUND);
+float tone_plover[][2] = SONG(PLOVER_SOUND);
+float tone_plover_gb[][2] = SONG(PLOVER_GOODBYE_SOUND);
+
+float music_scale[][2] = SONG(MUSIC_SCALE_SOUND);
+float goodbye[][2] = SONG(GOODBYE_SOUND);
+#endif
+
+
+void persistant_default_layer_set(uint16_t default_layer) {
+ eeconfig_update_default_layer(default_layer);
+ default_layer_set(default_layer);
+}
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ switch(id) {
+ case _QWERTY:
+ if (record->event.pressed) {
+ #ifdef AUDIO_ENABLE
+ PLAY_NOTE_ARRAY(tone_qwerty, false, 0);
+ #endif
+ persistant_default_layer_set(1UL<<_QWERTY);
+ }
+ break;
+ case _COLEMAK:
+ if (record->event.pressed) {
+ #ifdef AUDIO_ENABLE
+ PLAY_NOTE_ARRAY(tone_colemak, false, 0);
+ #endif
+ persistant_default_layer_set(1UL<<_COLEMAK);
+ }
+ break;
+ case _DVORAK:
+ if (record->event.pressed) {
+ #ifdef AUDIO_ENABLE
+ PLAY_NOTE_ARRAY(tone_dvorak, false, 0);
+ #endif
+ persistant_default_layer_set(1UL<<_DVORAK);
+ }
+ break;
+ case _LOWER:
+ if (record->event.pressed) {
+ layer_on(_LOWER);
+ update_tri_layer(_LOWER, _RAISE, _SETUP);
+ } else {
+ layer_off(_LOWER);
+ update_tri_layer(_LOWER, _RAISE, _SETUP);
+ }
+ break;
+ case _RAISE:
+ if (record->event.pressed) {
+ layer_on(_RAISE);
+ update_tri_layer(_LOWER, _RAISE, _SETUP);
+ } else {
+ layer_off(_RAISE);
+ update_tri_layer(_LOWER, _RAISE, _SETUP);
+ }
+ break;
+ case _FCT:
+ if (record->event.pressed) {
+ layer_on(_FCT);
+ } else {
+ layer_off(_FCT);
+ }
+ break;
+ case _MICMUTE:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ register_code(KC_RCTL);
+ register_code(KC_RALT);
+ register_code(KC_RGUI);
+ } else {
+ unregister_code(KC_RSFT);
+ unregister_code(KC_RCTL);
+ unregister_code(KC_RALT);
+ unregister_code(KC_RGUI);
+ }
+ break;
+ case _OS:
+ if (record->event.pressed) {
+ layer_on(currentOs);
+ } else {
+ layer_off(_MAC);
+ layer_off(_WIN);
+ layer_off(_LIN);
+ }
+ break;
+ case _MAC:
+ case _WIN:
+ case _LIN:
+ if (record->event.pressed) {
+ layer_off(currentOs);
+ currentOs = id;
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+void matrix_init_user(void) {
+ #ifdef AUDIO_ENABLE
+ _delay_ms(20); // stops the tick
+ PLAY_NOTE_ARRAY(tone_startup, false, 0);
+ #endif
+}
+
+#ifdef AUDIO_ENABLE
+void play_goodbye_tone()
+{
+ PLAY_NOTE_ARRAY(goodbye, false, 0);
+ _delay_ms(150);
+}
+
+uint8_t starting_note = 0x0C;
+int offset = 0;
+
+bool process_action_user(keyrecord_t *record) {
+
+ if (IS_LAYER_ON(_MUSIC)) {
+ if (record->event.pressed) {
+ play_note(((double)220.0)*pow(2.0, -4.0)*pow(2.0,(starting_note + SCALE[record->event.key.col + offset])/12.0+(MATRIX_ROWS - record->event.key.row)), 0xF);
+ } else {
+ stop_note(((double)220.0)*pow(2.0, -4.0)*pow(2.0,(starting_note + SCALE[record->event.key.col + offset])/12.0+(MATRIX_ROWS - record->event.key.row)));
+ }
+ return false;
+ }
+ return true;
+}
+#endif
diff --git a/keyboards/planck/keymaps/pete/readme.md b/keyboards/planck/keymaps/pete/readme.md
new file mode 100644
index 000000000..3cf594f3a
--- /dev/null
+++ b/keyboards/planck/keymaps/pete/readme.md
@@ -0,0 +1,14 @@
+# Planck Layout by Pete
+
+This layout is based on the default layout but uses a FN key in the bottom left corner instead of the shift / backlight key.
+On the FN layer you can do the following things
+
+- Step through back light
+- Put a mac to sleep
+- The Fxx keys in a block to click with the right hand
+- The delete key in the upper right corner
+- Quick access to screenshot functions
+- Control volume and media playback
+- Home/PgDown/PgUp/End buttons where the arrow keys are
+
+Pressing the lower and raise buttons allows to reset and change from QWERT to Colemak or Dvorak.
diff --git a/keyboards/planck/keymaps/pvc/Makefile b/keyboards/planck/keymaps/pvc/Makefile
new file mode 100644
index 000000000..0b2f060de
--- /dev/null
+++ b/keyboards/planck/keymaps/pvc/Makefile
@@ -0,0 +1,24 @@
+
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = yes # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/planck/keymaps/pvc/config.h b/keyboards/planck/keymaps/pvc/config.h
new file mode 100644
index 000000000..b64893108
--- /dev/null
+++ b/keyboards/planck/keymaps/pvc/config.h
@@ -0,0 +1,89 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "config_common.h"
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x6060
+#define DEVICE_VER 0x0001
+#define MANUFACTURER Ortholinear Keyboards
+#define PRODUCT The Planck Keyboard
+#define DESCRIPTION A compact ortholinear keyboard
+
+/* key matrix size */
+#define MATRIX_ROWS 4
+#define MATRIX_COLS 12
+
+/* Planck PCB default pin-out */
+#define MATRIX_ROW_PINS { D0, D5, B5, B6 }
+#define MATRIX_COL_PINS { F1, F0, B0, C7, F4, F5, F6, F7, D4, D6, B4, D7 }
+#define UNUSED_PINS
+
+/* COL2ROW or ROW2COL */
+#define DIODE_DIRECTION COL2ROW
+
+/* define if matrix has ghost */
+//#define MATRIX_HAS_GHOST
+
+/* number of backlight levels */
+#define BACKLIGHT_LEVELS 3
+
+/* Set 0 if debouncing isn't needed */
+#define DEBOUNCING_DELAY 5
+
+/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
+#define LOCKING_SUPPORT_ENABLE
+/* Locking resynchronize hack */
+#define LOCKING_RESYNC_ENABLE
+
+/* key combination for command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+/* ws2812 RGB LED */
+#define ws2812_PORTREG PORTD
+#define ws2812_DDRREG DDRD
+#define ws2812_pin PD1
+#define RGBLED_NUM 28 // Number of LEDs
+#define RGBLIGHT_HUE_STEP 10
+#define RGBLIGHT_SAT_STEP 17
+#define RGBLIGHT_VAL_STEP 17
+
+/*
+ * Feature disable options
+ * These options are also useful to firmware size reduction.
+ */
+
+/* disable debug print */
+//#define NO_DEBUG
+
+/* disable print */
+//#define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+
+#endif
diff --git a/keyboards/planck/keymaps/pvc/keymap.c b/keyboards/planck/keymaps/pvc/keymap.c
new file mode 100644
index 000000000..2fc5f0da1
--- /dev/null
+++ b/keyboards/planck/keymaps/pvc/keymap.c
@@ -0,0 +1,478 @@
+#include "planck.h"
+#include "action_layer.h"
+#include "eeconfig.h"
+#include "led.h"
+
+#ifdef AUDIO_ENABLE
+ #include "audio.h"
+ #include "song_list.h"
+#endif
+
+#define LAYER_QWERTY 0
+#define LAYER_COLEMAK 1
+#define LAYER_DVORAK 2
+#define LAYER_UPPER 3
+#define LAYER_LOWER 4
+#define LAYER_FUNCTION 5
+#define LAYER_MOUSE 6
+#define LAYER_ADJUST 7
+
+#define MACRO_QWERTY 0
+#define MACRO_COLEMAK 1
+#define MACRO_DVORAK 2
+#define MACRO_UPPER 3
+#define MACRO_LOWER 4
+#define MACRO_FUNCTION 5
+#define MACRO_MOUSE 6
+#define MACRO_TIMBRE_1 7
+#define MACRO_TIMBRE_2 8
+#define MACRO_TIMBRE_3 9
+#define MACRO_TIMBRE_4 10
+#define MACRO_TEMPO_U 11
+#define MACRO_TEMPO_D 12
+#define MACRO_TONE_DEFAULT 13
+#define MACRO_MUSIC_TOGGLE 14
+#define MACRO_AUDIO_TOGGLE 16
+#define MACRO_INC_VOICE 18
+#define MACRO_DEC_VOICE 19
+#define MACRO_BACKLIGHT 20
+#define MACRO_BREATH_TOGGLE 21
+#define MACRO_BREATH_SPEED_INC 23
+#define MACRO_BREATH_SPEED_DEC 24
+#define MACRO_BREATH_DEFAULT 25
+
+#define M_QWRTY M(MACRO_QWERTY)
+#define M_COLMK M(MACRO_COLEMAK)
+#define M_DVORK M(MACRO_DVORAK)
+#define M_UPPER M(MACRO_UPPER)
+#define M_LOWER M(MACRO_LOWER)
+#define M_FUNCT M(MACRO_FUNCTION)
+#define M_MOUSE M(MACRO_MOUSE)
+#define TIMBR_1 M(MACRO_TIMBRE_1)
+#define TIMBR_2 M(MACRO_TIMBRE_2)
+#define TIMBR_3 M(MACRO_TIMBRE_3)
+#define TIMBR_4 M(MACRO_TIMBRE_4)
+#define TMPO_UP M(MACRO_TEMPO_U)
+#define TMPO_DN M(MACRO_TEMPO_D)
+#define TMPO_DF M(MACRO_TONE_DEFAULT)
+#define M_BACKL M(MACRO_BACKLIGHT)
+#define M_BRTOG M(MACRO_BREATH_TOGGLE)
+#define M_BSPDU M(MACRO_BREATH_SPEED_INC)
+#define M_BSPDD M(MACRO_BREATH_SPEED_DEC)
+#define M_BDFLT M(MACRO_BREATH_DEFAULT)
+
+
+#define VC_UP M(MACRO_INC_VOICE)
+#define VC_DOWN M(MACRO_DEC_VOICE)
+
+
+#define SC_UNDO LCTL(KC_Z)
+#define SC_REDO LCTL(KC_Y)
+#define SC_CUT LCTL(KC_X)
+#define SC_COPY LCTL(KC_C)
+#define SC_PSTE LCTL(KC_V)
+#define SC_SELA LCTL(KC_A)
+#define SC_SAVE LCTL(KC_S)
+#define SC_OPEN LCTL(KC_O)
+#define SC_ACLS LALT(KC_F4)
+#define SC_CCLS LCTL(KC_F4)
+
+#define OS_SHFT KC_FN0
+
+#define _______ KC_TRNS
+#define XXXXXXX KC_NO
+#define ________________ _______, _______
+#define XXXXXXXXXXXXXXXX XXXXXXX, XXXXXXX
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+
+/* QWERTY
+ * .-----------------------------------------------------------------------------------------------------------.
+ * | TAB | Q | W | E | R | T | Y | U | I | O | P | BACKSP |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------|
+ * | ESC | A | S | D | F | G | H | J | K | L | ; | ' |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------|
+ * | LSHIFT | Z | X | C | V | B | N | M | , | . | UP | ENTER |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------|
+ * | LCTRL | LWIN | FN | LALT | UPPER | SPACE | SPACE | LOWER | SHIFT | LEFT | DOWN | RIGHT |
+ * '-----------------------------------------------------------------------------------------------------------'
+ */
+
+ [LAYER_QWERTY] = { // QWERTY
+ { KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC },
+ { KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT },
+ { KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_UP, KC_ENT },
+ { KC_LCTL, KC_LGUI, M_FUNCT, KC_LALT, M_UPPER, KC_SPC, KC_SPC, M_LOWER, OS_SHFT, KC_LEFT, KC_DOWN, KC_RGHT },
+ },
+
+/* COLEMAK
+ * .-----------------------------------------------------------------------------------------------------------.
+ * | TAB | Q | W | F | P | G | J | L | U | Y | ; | ESC |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------|
+ * | BACKSP | A | R | S | T | D | H | N | E | I | O | ' |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------|
+ * | LSHIFT | Z | X | C | V | B | K | M | , | . | UP | ENTER |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------|
+ * | LCTRL | LWIN | FN | LALT | UPPER | SPACE | SPACE | LOWER | SHIFT | LEFT | DOWN | RIGHT |
+ * '-----------------------------------------------------------------------------------------------------------'
+ */
+
+ [LAYER_COLEMAK] = { // COLEMAK
+ { KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_ESC },
+ { KC_BSPC, KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT },
+ { KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_K, KC_M, KC_COMM, KC_DOT, KC_UP, KC_ENT },
+ { KC_LCTL, KC_LGUI, M_FUNCT, KC_LALT, M_UPPER, KC_SPC, KC_SPC, M_LOWER, OS_SHFT, KC_LEFT, KC_DOWN, KC_RGHT },
+ },
+
+/* DVORAK
+ * .-----------------------------------------------------------------------------------------------------------.
+ * | TAB | ' | , | . | P | Y | F | G | C | R | L | BACKSP |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------|
+ * | ESC | A | O | E | U | I | D | H | T | N | S | / |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------|
+ * | LSHIFT | ; | Q | J | K | X | B | M | W | V | Z | ENTER |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------|
+ * | LCTRL | LWIN | FN | LALT | UPPER | SPACE | SPACE | LOWER | UP | DOWN | LEFT | RIGHT |
+ * '-----------------------------------------------------------------------------------------------------------'
+ */
+
+ [LAYER_DVORAK] = { // DVORAK
+ { KC_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, KC_F, KC_G, KC_C, KC_R, KC_L, KC_BSPC },
+ { KC_ESC, KC_A, KC_O, KC_E, KC_U, KC_I, KC_D, KC_H, KC_T, KC_N, KC_S, KC_SLSH },
+ { KC_LSFT, KC_SCLN, KC_Q, KC_J, KC_K, KC_X, KC_B, KC_M, KC_W, KC_V, KC_Z, KC_ENT },
+ { KC_LCTL, KC_LGUI, M_FUNCT, KC_LALT, M_UPPER, KC_SPC, KC_SPC, M_LOWER, KC_UP, KC_DOWN, KC_LEFT, KC_RGHT },
+ },
+
+/* UPPER
+ * .-----------------------------------------------------------------------------------------------------------.
+ * | PRINT | F1 | F2 | F3 | F4 | NUM LK | / | 7 | 8 | 9 | - | DEL |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------|
+ * | CAP LK | F5 | F6 | F7 | F8 | SCR LK | * | 4 | 5 | 6 | + | INS |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------|
+ * | | F9 | F10 | F11 | F12 | PAUSE | | 1 | 2 | 3 | ENTER | HOME |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+-----------------|
+ * | | | | | | 0 | 0 | | RALT | . | ENTER | END |
+ * '-----------------------------------------------------------------------------------------------------------'
+ */
+
+ [LAYER_UPPER] = { // UPPER
+ { KC_PSCR, KC_F1, KC_F2, KC_F3, KC_F4, KC_NLCK, KC_PSLS, KC_KP_7, KC_KP_8, KC_KP_9, KC_PMNS, KC_DEL },
+ { KC_CAPS, KC_F5, KC_F6, KC_F7, KC_F8, KC_SLCK, KC_PAST, KC_KP_4, KC_KP_5, KC_KP_6, KC_PPLS, KC_INS },
+ { _______, KC_F9, KC_F10, KC_F11, KC_F12, KC_PAUS, XXXXXXX, KC_KP_1, KC_KP_2, KC_KP_3, KC_PENT, KC_HOME },
+ { _______, _______, _______, _______, _______, KC_KP_0, KC_KP_0, _______, KC_RALT, KC_PDOT, KC_PENT, KC_END },
+ },
+
+/* LOWER
+ * .-----------------------------------------------------------------------------------------------------------.
+ * | | $ | { | [ | ( | % | # | ) | ] | } | @ | PG UP |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------|
+ * | | ^ | * | + | - | ; | : | _ | ' | " | ` | PG DN |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------|
+ * | | | | & | ! | ~ | / | \ | = | < | > | ? | HOME |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+-----------------|
+ * | | | | | | | | | | | | END |
+ * '-----------------------------------------------------------------------------------------------------------'
+ */
+
+ [LAYER_LOWER] = { // LOWER
+ { _______, KC_DLR, KC_LCBR, KC_LBRC, KC_LPRN, KC_PERC, KC_HASH, KC_RPRN, KC_RBRC, KC_RCBR, KC_AT, KC_PGUP },
+ { _______, KC_CIRC, KC_ASTR, KC_PPLS, KC_PMNS, KC_SCLN, KC_COLN, KC_UNDS, KC_QUOT, KC_DQT, KC_GRV, KC_PGDN },
+ { _______, KC_PIPE, KC_AMPR, KC_EXLM, KC_TILD, KC_SLSH, KC_BSLS, KC_EQL, KC_LT, KC_GT, KC_QUES, KC_HOME },
+ { _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_END },
+ },
+
+
+/* FUNCTION
+ * .-----------------------------------------------------------------------------------------------------------.
+ * | NUM LK | F1 | F2 | F3 | F4 | F5 | F6 | F7 | F8 | F9 | F10 | PAUSE |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------|
+ * | CAP LK | F11 | F12 | F13 | F14 | F15 | F16 | F17 | F18 | F19 | F20 | PRINT |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------|
+ * | SCR LK | XXXXXX | XXXXXX | XXXXXX | XXXXXX | XXXXXX | XXXXXX | XXXXXX | XXXXXX | XXXXXX | XXXXXX | MUTE |
+ * |--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------+--------|
+ * | LCTRL | LWIN | FN | LALT | UPPER | PLAY | PLAY | LOWER | VOL UP | VOL DN | NEXT | PREV |
+ * '-----------------------------------------------------------------------------------------------------------'
+ */
+ [LAYER_FUNCTION] = { // FUNCTION
+ { KC_NLCK, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_PAUS },
+ { KC_CAPS, KC_F11, KC_F12, KC_F13, KC_F14, KC_F15, KC_F16, KC_F17, KC_F18, KC_F19, KC_F20, KC_PSCR },
+ { KC_SLCK, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_MUTE },
+ { _______, _______, _______, _______, _______, KC_MPLY, KC_MPLY, _______, KC_VOLU, KC_VOLD, KC_MPRV, KC_MNXT },
+ },
+
+#ifdef MOUSEKEY_ENABLE
+
+ [LAYER_MOUSE] = { // MOUSE
+ { KC_ESC, KC_ACL0, KC_ACL1, KC_ACL2, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_ESC },
+ { XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX },
+ { _______, KC_BTN5, KC_BTN4, KC_BTN3, KC_BTN2, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_WH_U, KC_WH_D },
+ { _______, _______, _______, _______, _______, KC_BTN1, KC_BTN1, _______, KC_MS_U, KC_MS_D, KC_MS_L, KC_MS_R },
+ },
+
+#endif
+
+ [LAYER_ADJUST] = { // ADJUST
+ { _______, TIMBR_1, TIMBR_2, TIMBR_3, TIMBR_4, TMPO_UP, TMPO_DN, TMPO_DF, _______, _______, MU_TOG, AU_TOG },
+ { _______, M_QWRTY, M_COLMK, M_DVORK, _______, _______, _______, _______, _______, _______, _______, _______ },
+ { _______, _______, _______, _______, M_BACKL, RESET, _______, M_MOUSE, _______, _______, MUV_IN, _______ },
+ { _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, MUV_DE, _______ },
+ },
+
+/*
+ [LAYER_EMPTY] = {
+ { _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, },
+ { _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, },
+ { _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, },
+ { _______, _______, _______, _______, _______, ________________, _______, _______, _______, _______, _______, },
+ },
+*/
+
+};
+
+#ifdef AUDIO_ENABLE
+
+float tone_my_startup[][2] = SONG(ODE_TO_JOY);
+float tone_my_goodbye[][2] = SONG(ROCK_A_BYE_BABY);
+
+float tone_qwerty[][2] = SONG(QWERTY_SOUND);
+float tone_dvorak[][2] = SONG(DVORAK_SOUND);
+float tone_colemak[][2] = SONG(COLEMAK_SOUND);
+
+float tone_audio_on[][2] = SONG(CLOSE_ENCOUNTERS_5_NOTE);
+float tone_music_on[][2] = SONG(DOE_A_DEER);
+float tone_caps_on[][2] = SONG(CAPS_LOCK_ON_SOUND);
+float tone_caps_off[][2] = SONG(CAPS_LOCK_OFF_SOUND);
+float tone_numlk_on[][2] = SONG(NUM_LOCK_ON_SOUND);
+float tone_numlk_off[][2] = SONG(NUM_LOCK_OFF_SOUND);
+float tone_scroll_on[][2] = SONG(SCROLL_LOCK_ON_SOUND);
+float tone_scroll_off[][2] = SONG(SCROLL_LOCK_OFF_SOUND);
+float music_scale[][2] = SONG(MUSIC_SCALE_SOUND);
+
+#endif /* AUDIO_ENABLE */
+
+void persistant_default_layer_set(uint16_t default_layer)
+{
+ eeconfig_update_default_layer(default_layer);
+ default_layer_set(default_layer);
+}
+
+const uint16_t PROGMEM fn_actions[] = {
+ [0] = ACTION_MODS_ONESHOT(MOD_LSFT),
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+
+ // MACRODOWN only works in this function
+ switch(id)
+ {
+
+ case MACRO_QWERTY:
+ if (record->event.pressed)
+ {
+ persistant_default_layer_set(1UL<<LAYER_QWERTY);
+ #ifdef AUDIO_ENABLE
+ PLAY_NOTE_ARRAY(tone_qwerty, false, STACCATO);
+ #endif /* AUDIO_ENABLE */
+ }
+ break;
+
+ case MACRO_COLEMAK:
+ if (record->event.pressed)
+ {
+ persistant_default_layer_set(1UL<<LAYER_COLEMAK);
+ #ifdef AUDIO_ENABLE
+ PLAY_NOTE_ARRAY(tone_colemak, false, STACCATO);
+ #endif /* AUDIO_ENABLE */
+ }
+ break;
+
+ case MACRO_DVORAK:
+ if (record->event.pressed)
+ {
+ persistant_default_layer_set(1UL<<LAYER_DVORAK);
+ #ifdef AUDIO_ENABLE
+ PLAY_NOTE_ARRAY(tone_dvorak, false, STACCATO);
+ #endif /* AUDIO_ENABLE */
+ }
+ break;
+
+ case MACRO_LOWER:
+ if (record->event.pressed)
+ {
+ layer_on(LAYER_LOWER);
+ update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST);
+ }
+ else
+ {
+ layer_off(LAYER_LOWER);
+ update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST);
+ }
+ break;
+
+ case MACRO_UPPER:
+ if (record->event.pressed)
+ {
+ layer_on(LAYER_UPPER);
+ update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST);
+ }
+ else
+ {
+ layer_off(LAYER_UPPER);
+ update_tri_layer(LAYER_LOWER, LAYER_UPPER, LAYER_ADJUST);
+ }
+ break;
+
+ case MACRO_FUNCTION:
+ if (record->event.pressed)
+ {
+ layer_on(LAYER_FUNCTION);
+ }
+ else
+ {
+ layer_off(LAYER_FUNCTION);
+ }
+ break;
+
+
+#ifdef BACKLIGHT_ENABLE
+ case MACRO_BACKLIGHT:
+ if (record->event.pressed)
+ {
+ backlight_step();
+ }
+#endif
+
+#ifdef MOUSEKEY_ENABLE
+
+ case MACRO_MOUSE:
+ if (record->event.pressed)
+ {
+ layer_invert(LAYER_MOUSE);
+ }
+ break;
+
+#endif /* MOUSEKEY_ENABLE */
+
+#ifdef AUDIO_ENABLE
+
+ case MACRO_TIMBRE_1:
+ if (record->event.pressed) set_timbre(TIMBRE_12);
+ break;
+
+ case MACRO_TIMBRE_2:
+ if (record->event.pressed) set_timbre(TIMBRE_25);
+ break;
+
+ case MACRO_TIMBRE_3:
+ if (record->event.pressed) set_timbre(TIMBRE_50);
+ break;
+
+ case MACRO_TIMBRE_4:
+ if (record->event.pressed) set_timbre(TIMBRE_75);
+ break;
+
+ case MACRO_TEMPO_U:
+ if (record->event.pressed) increase_tempo(10);
+ break;
+
+ case MACRO_TEMPO_D:
+ if (record->event.pressed) decrease_tempo(10);
+ break;
+
+ case MACRO_TONE_DEFAULT:
+ if (record->event.pressed)
+ {
+ set_timbre(TIMBRE_DEFAULT);
+ set_tempo(TEMPO_DEFAULT);
+ }
+ break;
+
+#endif /* AUDIO_ENABLE */
+
+ default:
+ break;
+
+ }
+ return MACRO_NONE;
+};
+
+
+#ifdef AUDIO_ENABLE
+
+void matrix_init_user(void)
+{
+ set_voice(default_voice);
+ startup_user();
+ println("Matrix Init");
+}
+
+void led_set_user(uint8_t usb_led)
+{
+ static uint8_t old_usb_led = 0;
+
+ _delay_ms(10); // gets rid of tick
+
+ if ((usb_led & (1<<USB_LED_CAPS_LOCK)) && !(old_usb_led & (1<<USB_LED_CAPS_LOCK)))
+ {
+ // If CAPS LK LED is turning on...
+ PLAY_NOTE_ARRAY(tone_caps_on, false, LEGATO);
+ }
+ else if (!(usb_led & (1<<USB_LED_CAPS_LOCK)) && (old_usb_led & (1<<USB_LED_CAPS_LOCK)))
+ {
+ // If CAPS LK LED is turning off...
+ PLAY_NOTE_ARRAY(tone_caps_off, false, LEGATO);
+ }
+ else if ((usb_led & (1<<USB_LED_NUM_LOCK)) && !(old_usb_led & (1<<USB_LED_NUM_LOCK)))
+ {
+ // If NUM LK LED is turning on...
+ PLAY_NOTE_ARRAY(tone_numlk_on, false, LEGATO);
+ }
+ else if (!(usb_led & (1<<USB_LED_NUM_LOCK)) && (old_usb_led & (1<<USB_LED_NUM_LOCK)))
+ {
+ // If NUM LED is turning off...
+ PLAY_NOTE_ARRAY(tone_numlk_off, false, LEGATO);
+ }
+ else if ((usb_led & (1<<USB_LED_SCROLL_LOCK)) && !(old_usb_led & (1<<USB_LED_SCROLL_LOCK)))
+ {
+ // If SCROLL LK LED is turning on...
+ PLAY_NOTE_ARRAY(tone_scroll_on, false, LEGATO);
+ }
+ else if (!(usb_led & (1<<USB_LED_SCROLL_LOCK)) && (old_usb_led & (1<<USB_LED_SCROLL_LOCK)))
+ {
+ // If SCROLL LED is turning off...
+ PLAY_NOTE_ARRAY(tone_scroll_off, false, LEGATO);
+ }
+ old_usb_led = usb_led;
+}
+
+
+void startup_user()
+{
+ _delay_ms(10); // gets rid of tick
+ PLAY_NOTE_ARRAY(tone_my_startup, false, STACCATO);
+}
+
+void shutdown_user()
+{
+ PLAY_NOTE_ARRAY(tone_my_goodbye, false, STACCATO);
+ _delay_ms(2000);
+ stop_all_notes();
+}
+
+void audio_on_user(void)
+{
+ PLAY_NOTE_ARRAY(tone_audio_on, false, STACCATO);
+}
+
+void music_on_user(void)
+{
+ PLAY_NOTE_ARRAY(tone_music_on, false, STACCATO);
+}
+
+void music_scale_user(void)
+{
+ PLAY_NOTE_ARRAY(music_scale, false, STACCATO);
+}
+
+#endif /* AUDIO_ENABLE */ \ No newline at end of file
diff --git a/keyboards/planck/keymaps/readme.md b/keyboards/planck/keymaps/readme.md
new file mode 100644
index 000000000..54fb5f6d9
--- /dev/null
+++ b/keyboards/planck/keymaps/readme.md
@@ -0,0 +1,23 @@
+# How to add your own keymap
+
+Folders can be named however you'd like (will be approved upon merging), or should follow the format with a preceding `_`:
+
+ _[ISO 3166-1 alpha-2 code*]_[layout variant]_[layout name/author]
+
+\* See full list: https://en.wikipedia.org/wiki/ISO_3166-1#Officially_assigned_code_elements
+
+and contain the following files:
+
+* `keymap.c`
+* `readme.md` *recommended*
+* `config.h` *optional*, found automatically when compiling
+* `Makefile` *optional*, found automatically when compling
+
+When adding your keymap to this list, keep it organised alphabetically (select list, edit->sort lines), and use this format:
+
+ * **folder_name** description
+
+# List of Planck keymaps
+
+* **default** default Planck layout
+* **cbbrowne** cbbrowne's Planck layout \ No newline at end of file
diff --git a/keyboards/planck/keymaps/tak3over/Makefile b/keyboards/planck/keymaps/tak3over/Makefile
new file mode 100644
index 000000000..581e08cd0
--- /dev/null
+++ b/keyboards/planck/keymaps/tak3over/Makefile
@@ -0,0 +1,25 @@
+
+
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = yes # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/planck/keymaps/tak3over/keymap.c b/keyboards/planck/keymaps/tak3over/keymap.c
new file mode 100644
index 000000000..7d8243dfa
--- /dev/null
+++ b/keyboards/planck/keymaps/tak3over/keymap.c
@@ -0,0 +1,130 @@
+// This is the canonical layout file for the Quantum project. If you want to add another keyboard,
+// this is the style you want to emulate.
+//
+//Dropped the Dvorak layer and added two my layer buttons. Both Raise and lower can be accessed from either side now.
+
+#include "planck.h"
+#ifdef BACKLIGHT_ENABLE
+ #include "backlight.h"
+#endif
+
+// Each layer gets a name for readability, which is then used in the keymap matrix below.
+// The underscores don't mean anything - you can have a layer called STUFF or any other name.
+// Layer names don't all need to be of the same length, obviously, and you can also skip them
+// entirely and just use numbers.
+#define _QW 0
+#define _CM 1
+#define _LW 2
+#define _RS 3
+#define _FN 4
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+
+/* Qwerty
+ * ,-----------------------------------------------------------------------------------.
+ * | Tab | Q | W | E | R | T | Y | U | I | O | P | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc | A | S | D | F | G | H | J | K | L | ; | " |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift| Z | X | C | V | B | N | M | , | . | / |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Ctrl | Alt | GUI |Func |Lower | Space |Raise | Left | Down | Up |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_QW] = {
+ {KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC},
+ {KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT},
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT },
+ {KC_LCTL, KC_LALT, KC_LGUI, MO(_FN), MO(_LW), KC_SPC, KC_SPC, MO(_RS), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+/* Colemak
+ * ,-----------------------------------------------------------------------------------.
+ * | Tab | Q | W | F | P | G | J | L | U | Y | ; | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc | A | R | S | T | D | H | N | E | I | O | " |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift| Z | X | C | V | B | K | M | , | . | / |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Ctrl | Alt | GUI |Func |Lower | Space |Raise | Left | Down | Up |Right
+ * `-----------------------------------------------------------------------------------'
+ */
+[_CM] = {
+ {KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_BSPC},
+ {KC_ESC, KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT},
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_K, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT },
+ {KC_LCTL, KC_LALT, KC_LGUI, MO(_FN), MO(_LW), KC_SPC, KC_SPC, MO(_RS), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+/* Raise
+ * ,-----------------------------------------------------------------------------------.
+ * | ` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | Bksp
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc | F1 | F2 | F3 | F4 | F5 | F6 | - | = | [ | ] | | |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift| F7 | F8 | F9 | F10 | F11 | F12 | _ | + | { | } |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Ctrl | Alt | GUI |Func |Lower | Space |Raise | Left | Down | Up |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_RS] = {
+ {KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC},
+ {KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_PIPE},
+ {KC_TRNS, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS}
+},
+/* Lower
+ * ,-----------------------------------------------------------------------------------.
+ * | ~ | ! | @ | # | $ | % | ^ | & | * | ( | ) | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc | Reset| Ins | Home | PGUP |Colemk| Left | - | = | [ | ] | \ |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift| Brite| Del | End | PGDN |Qwerty| Del | _ | + | { | } |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Ctrl | Alt | GUI |Func |Lower | Space |Raise | Left | Down | Up |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_LW] = {
+ {KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_BSPC},
+ {KC_TRNS, RESET, KC_INS, KC_HOME, KC_PGUP, DF(_CM), KC_LEFT, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS},
+ {KC_TRNS, M(0), KC_DEL, KC_END, KC_PGDN, DF(_QW), KC_DEL, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS}
+},
+/* Function
+ * ,-----------------------------------------------------------------------------------.
+ * | ` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc | GUI | X | C | V | Z | Left | Down | Up |Right | Del | \ |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * |Shift | Ctrl | X | C | V | Z | Next | Mute | Vol- | Vol+ | Play |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Ctrl | Alt | GUI |Func |Lower | Space |Raise | Left | Down | Up |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_FN] = {
+ {KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC},
+ {KC_TRNS, KC_RGUI, KC_X, KC_C, KC_V, KC_Z, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, KC_DEL, KC_BSLS},
+ {KC_TRNS, KC_RCTL, KC_X, KC_C, KC_V, KC_Z, KC_MNXT, KC_MUTE, KC_VOLD, KC_VOLU, KC_MPLY, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS}
+}
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ #ifdef BACKLIGHT_ENABLE
+ backlight_step();
+ #endif
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
diff --git a/keyboards/planck/keymaps/unicode/Makefile b/keyboards/planck/keymaps/unicode/Makefile
new file mode 100644
index 000000000..110af7501
--- /dev/null
+++ b/keyboards/planck/keymaps/unicode/Makefile
@@ -0,0 +1,11 @@
+
+
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+UNICODE_ENABLE = yes # Unicode
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/planck/keymaps/unicode/keymap.c b/keyboards/planck/keymaps/unicode/keymap.c
new file mode 100644
index 000000000..d73e7e09d
--- /dev/null
+++ b/keyboards/planck/keymaps/unicode/keymap.c
@@ -0,0 +1,326 @@
+/*
+ Copyright
+ 2015 Jack Humbert <jack.humb@gmail.com>
+ 2016 Francois Marlier <fmarlier@gmail.com>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ For more info on how this works per OS, see here
+ https://en.wikipedia.org/wiki/Unicode_input#Hexadecimal_code_input
+*/
+
+
+#include "planck.h"
+#include "action_layer.h"
+#ifdef AUDIO_ENABLE
+ #include "audio.h"
+#endif
+#include "eeconfig.h"
+
+extern keymap_config_t keymap_config;
+
+// Each layer gets a name for readability, which is then used in the keymap matrix below.
+// The underscores don't mean anything - you can have a layer called STUFF or any other name.
+// Layer names don't all need to be of the same length, obviously, and you can also skip them
+// entirely and just use numbers.
+#define _QWERTY 0
+#define _COLEMAK 1
+#define _DVORAK 2
+#define _LOWER 3
+#define _RAISE 4
+#define _PLOVER 5
+#define _ADJUST 16
+
+// Macro name shortcuts
+#define QWERTY M(_QWERTY)
+#define COLEMAK M(_COLEMAK)
+#define DVORAK M(_DVORAK)
+#define LOWER M(_LOWER)
+#define RAISE M(_RAISE)
+#define M_BL 5
+#define PLOVER M(12)
+#define EXT_PLV M(13)
+#define TOG_OUT M(14)
+
+// Fillers to make layering more clear
+#define _______ KC_TRNS
+#define XXXXXXX KC_NO
+
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+
+/* Qwerty
+ * ,-----------------------------------------------------------------------------------.
+ * | Tab | Q | W | E | R | T | Y | U | I | O | P | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc | A | S | D | F | G | H | J | K | L | ; | " |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift| Z | X | C | V | B | N | M | , | . | / |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Brite| Ctrl | Alt | GUI |Lower | Space |Raise | Left | Down | Up |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_QWERTY] = {
+ {KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC},
+ {KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT},
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT },
+ {M(M_BL), KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+
+/* Colemak
+ * ,-----------------------------------------------------------------------------------.
+ * | Tab | Q | W | F | P | G | J | L | U | Y | ; | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc | A | R | S | T | D | H | N | E | I | O | " |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift| Z | X | C | V | B | K | M | , | . | / |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Brite| Ctrl | Alt | GUI |Lower | Space |Raise | Left | Down | Up |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_COLEMAK] = {
+ {KC_TAB, UC_q, UC_w, UC_f, UC_p, UC_g, UC_j, UC_l, UC_u, UC_y, UC_SCLN, UC_BSPC},
+ {KC_ESC, UC_a, UC_r, UC_s, UC_t, UC_d, UC_h, UC_n, UC_e, UC_i, UC_o, UC_QUOT},
+ {KC_LSFT, UC_z, UC_x, UC_c, UC_v, UC_b, UC_k, UC_m, UC_COMM, UC_DOT, UC_SLSH, KC_ENT},
+ {KC_TRNS, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+
+/* Dvorak
+ * ,-----------------------------------------------------------------------------------.
+ * | Tab | " | , | . | P | Y | F | G | C | R | L | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc | A | O | E | U | I | D | H | T | N | S | / |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift| ; | Q | J | K | X | B | M | W | V | Z |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Brite| Ctrl | Alt | GUI |Lower | Space |Raise | Left | Down | Up |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_DVORAK] = {
+ {KC_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, KC_F, KC_G, KC_C, KC_R, KC_L, KC_BSPC},
+ {KC_ESC, KC_A, KC_O, KC_E, KC_U, KC_I, KC_D, KC_H, KC_T, KC_N, KC_S, KC_SLSH},
+ {KC_LSFT, KC_SCLN, KC_Q, KC_J, KC_K, KC_X, KC_B, KC_M, KC_W, KC_V, KC_Z, KC_ENT },
+ {M(M_BL), KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+
+/* Lower
+ * ,-----------------------------------------------------------------------------------.
+ * | ~ | ! | @ | # | $ | % | ^ | & | * | ( | ) | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Del | F1 | F2 | F3 | F4 | F5 | F6 | _ | + | { | } | | |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | | F7 | F8 | F9 | F10 | F11 | F12 | | | | |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | | | | | | | | Next | Vol- | Vol+ | Play |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_LOWER] = {
+ {KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_BSPC},
+ {KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE},
+ {_______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______, _______, _______, _______, _______},
+ {_______, _______, _______, _______, _______, _______, _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
+},
+
+/* Raise
+ * ,-----------------------------------------------------------------------------------.
+ * | ` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Del | F1 | F2 | F3 | F4 | F5 | F6 | - | = | [ | ] | \ |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | | F7 | F8 | F9 | F10 | F11 | F12 | | | | |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | | | | | | | | Next | Vol- | Vol+ | Play |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_RAISE] = {
+ {KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC},
+ {KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS},
+ {_______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______, _______, _______, _______, _______},
+ {_______, _______, _______, _______, _______, _______, _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
+},
+
+/* Plover layer (http://opensteno.org)
+ * ,-----------------------------------------------------------------------------------.
+ * | # | # | # | # | # | # | # | # | # | # | # | # |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | | S | T | P | H | * | * | F | P | L | T | D |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * |TogOut| S | K | W | R | * | * | R | B | G | S | Z |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Exit | | | A | O | | E | U | | | |
+ * `-----------------------------------------------------------------------------------'
+ */
+
+[_PLOVER] = {
+ {KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1 },
+ {XXXXXXX, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC},
+ {TOG_OUT, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT},
+ {EXT_PLV, XXXXXXX, XXXXXXX, KC_C, KC_V, XXXXXXX, XXXXXXX, KC_N, KC_M, XXXXXXX, XXXXXXX, XXXXXXX}
+},
+
+/* Adjust (Lower + Raise)
+ * ,-----------------------------------------------------------------------------------.
+ * | | Reset| | | | | | | | | | Del |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | | | |Aud on|Audoff|AGnorm|AGswap|Qwerty|Colemk|Dvorak|Plover| |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | |Voice-|Voice+|Mus on|Musoff| | | | | | | |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | | | | | | | | | | | |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_ADJUST] = {
+ {_______, RESET, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_DEL},
+ {_______, _______, _______, AU_ON, AU_OFF, AG_NORM, AG_SWAP, QWERTY, COLEMAK, DVORAK, PLOVER, _______},
+ {_______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, _______, _______, _______, _______, _______},
+ {_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______}
+}
+
+
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+
+};
+
+#ifdef AUDIO_ENABLE
+float tone_startup[][2] = {
+ {440.0*pow(2.0,(31)/12.0), 12},
+ {440.0*pow(2.0,(28)/12.0), 8},
+ {440.0*pow(2.0,(19)/12.0), 8},
+ {440.0*pow(2.0,(24)/12.0), 8},
+ {440.0*pow(2.0,(28)/12.0), 20}
+};
+
+float tone_qwerty[][2] = SONG(QWERTY_SOUND);
+float tone_dvorak[][2] = SONG(DVORAK_SOUND);
+float tone_colemak[][2] = SONG(COLEMAK_SOUND);
+float tone_plover[][2] = SONG(PLOVER_SOUND);
+float tone_plover_gb[][2] = SONG(PLOVER_GOODBYE_SOUND);
+
+float goodbye[][2] = SONG(GOODBYE_SOUND);
+#endif
+
+
+void persistant_default_layer_set(uint16_t default_layer) {
+ eeconfig_update_default_layer(default_layer);
+ default_layer_set(default_layer);
+}
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ switch(id) {
+ case _QWERTY:
+ if (record->event.pressed) {
+ #ifdef AUDIO_ENABLE
+ PLAY_NOTE_ARRAY(tone_qwerty, false, 0);
+ #endif
+ persistant_default_layer_set(1UL<<_QWERTY);
+ }
+ break;
+ case _COLEMAK:
+ if (record->event.pressed) {
+ #ifdef AUDIO_ENABLE
+ PLAY_NOTE_ARRAY(tone_colemak, false, 0);
+ #endif
+ persistant_default_layer_set(1UL<<_COLEMAK);
+ }
+ break;
+ case _DVORAK:
+ if (record->event.pressed) {
+ #ifdef AUDIO_ENABLE
+ PLAY_NOTE_ARRAY(tone_dvorak, false, 0);
+ #endif
+ persistant_default_layer_set(1UL<<_DVORAK);
+ }
+ break;
+ case _LOWER:
+ if (record->event.pressed) {
+ layer_on(_LOWER);
+ update_tri_layer(_LOWER, _RAISE, _ADJUST);
+ } else {
+ layer_off(_LOWER);
+ update_tri_layer(_LOWER, _RAISE, _ADJUST);
+ }
+ break;
+ case _RAISE:
+ if (record->event.pressed) {
+ layer_on(_RAISE);
+ update_tri_layer(_LOWER, _RAISE, _ADJUST);
+ } else {
+ layer_off(_RAISE);
+ update_tri_layer(_LOWER, _RAISE, _ADJUST);
+ }
+ break;
+ case M_BL:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ #ifdef BACKLIGHT_ENABLE
+ backlight_step();
+ #endif
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ case 12:
+ if (record->event.pressed) {
+ #ifdef AUDIO_ENABLE
+ stop_all_notes();
+ PLAY_NOTE_ARRAY(tone_plover, false, 0);
+ #endif
+ layer_off(_RAISE);
+ layer_off(_LOWER);
+ layer_off(_ADJUST);
+ layer_on(_PLOVER);
+ if (!eeconfig_is_enabled()) {
+ eeconfig_init();
+ }
+ keymap_config.raw = eeconfig_read_keymap();
+ keymap_config.nkro = 1;
+ eeconfig_update_keymap(keymap_config.raw);
+ }
+ break;
+ case 13:
+ if (record->event.pressed) {
+ #ifdef AUDIO_ENABLE
+ PLAY_NOTE_ARRAY(tone_plover_gb, false, 0);
+ #endif
+ layer_off(_PLOVER);
+ }
+ break;
+ case 14:
+ if (record->event.pressed) {
+ return MACRO( D(E), D(R), D(F), D(V), D(O), D(L), U(E), U(R), U(F), U(V), U(O), U(L), END );
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+void matrix_init_user(void) {
+ #ifdef AUDIO_ENABLE
+ _delay_ms(20); // stops the tick
+ PLAY_NOTE_ARRAY(tone_startup, false, 0);
+ #endif
+}
+
+#ifdef AUDIO_ENABLE
+void play_goodbye_tone()
+{
+ PLAY_NOTE_ARRAY(goodbye, false, 0);
+ _delay_ms(150);
+}
+#endif
+
+
diff --git a/keyboards/planck/keymaps/yang/Makefile b/keyboards/planck/keymaps/yang/Makefile
new file mode 100644
index 000000000..6b18762fa
--- /dev/null
+++ b/keyboards/planck/keymaps/yang/Makefile
@@ -0,0 +1,10 @@
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+RGBLIGHT_ENABLE = yes # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+AUDIO_ENABLE = no
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/planck/keymaps/yang/WS2812-wiring.jpg b/keyboards/planck/keymaps/yang/WS2812-wiring.jpg
new file mode 100644
index 000000000..2c65cd283
--- /dev/null
+++ b/keyboards/planck/keymaps/yang/WS2812-wiring.jpg
Binary files differ
diff --git a/keyboards/planck/keymaps/yang/config.h b/keyboards/planck/keymaps/yang/config.h
new file mode 100644
index 000000000..5921e9377
--- /dev/null
+++ b/keyboards/planck/keymaps/yang/config.h
@@ -0,0 +1,15 @@
+#ifndef CONFIG_USER_H
+#define CONFIG_USER_H
+
+#include "../../config.h"
+
+/* ws2812 RGB LED */
+#define ws2812_PORTREG PORTD
+#define ws2812_DDRREG DDRD
+#define ws2812_pin PD1
+#define RGBLED_NUM 28 // Number of LEDs
+#define RGBLIGHT_HUE_STEP 10
+#define RGBLIGHT_SAT_STEP 17
+#define RGBLIGHT_VAL_STEP 17
+
+#endif
diff --git a/keyboards/planck/keymaps/yang/keymap.c b/keyboards/planck/keymaps/yang/keymap.c
new file mode 100644
index 000000000..541b1a57e
--- /dev/null
+++ b/keyboards/planck/keymaps/yang/keymap.c
@@ -0,0 +1,146 @@
+// This is the canonical layout file for the Quantum project. If you want to add another keyboard,
+// this is the style you want to emulate.
+
+#include "planck.h"
+#ifdef BACKLIGHT_ENABLE
+ #include "backlight.h"
+#endif
+
+// Each layer gets a name for readability, which is then used in the keymap matrix below.
+// The underscores don't mean anything - you can have a layer called STUFF or any other name.
+// Layer names don't all need to be of the same length, obviously, and you can also skip them
+// entirely and just use numbers.
+#define _QW 0
+#define _CM 1
+#define _DV 2
+#define _LW 3
+#define _RS 4
+#define _RGB 5
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[_QW] = { /* Qwerty */
+ {KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC},
+ {KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT},
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT },
+ {M(0), KC_LCTL, KC_LALT, KC_LGUI, MO(_LW), F(0), F(0), MO(_RS), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+[_CM] = { /* Colemak */
+ {KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_BSPC},
+ {KC_ESC, KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT},
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_K, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT },
+ {M(0), KC_LCTL, KC_LALT, KC_LGUI, MO(_LW), F(0), F(0), MO(_RS), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+[_DV] = { /* Dvorak */
+ {KC_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, KC_F, KC_G, KC_C, KC_R, KC_L, KC_BSPC},
+ {KC_ESC, KC_A, KC_O, KC_E, KC_U, KC_I, KC_D, KC_H, KC_T, KC_N, KC_S, KC_SLSH},
+ {KC_LSFT, KC_SCLN, KC_Q, KC_J, KC_K, KC_X, KC_B, KC_M, KC_W, KC_V, KC_Z, KC_ENT },
+ {M(0), KC_LCTL, KC_LALT, KC_LGUI, MO(_LW), F(0), F(0), MO(_RS), KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+[_RS] = { /* RAISE */
+ {KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC},
+ {KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS},
+ {KC_TRNS, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, DF(_QW), DF(_CM), DF(_DV), RESET, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
+},
+[_LW] = { /* LOWER */
+ {KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_BSPC},
+ {KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE},
+ {KC_TRNS, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, DF(_QW), DF(_CM), DF(_DV), RESET, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
+},
+[_RGB] = { /* RGBLIGHT */
+ {KC_TRNS, KC_PGUP, KC_UP, KC_PGDN, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_DEL},
+ {KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS, KC_HOME, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, KC_END, KC_TRNS},
+ {KC_TRNS, F(1), F(2), F(3), F(4), F(5), F(6), F(7), F(8), KC_TRNS, KC_TRNS, KC_TRNS},
+ {KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS}
+
+}
+};
+
+enum function_id {
+ RGBLED_TOGGLE,
+ RGBLED_STEP_MODE,
+ RGBLED_INCREASE_HUE,
+ RGBLED_DECREASE_HUE,
+ RGBLED_INCREASE_SAT,
+ RGBLED_DECREASE_SAT,
+ RGBLED_INCREASE_VAL,
+ RGBLED_DECREASE_VAL,
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [0] = ACTION_LAYER_TAP_KEY(_RGB, KC_SPC),
+ [1] = ACTION_FUNCTION(RGBLED_TOGGLE),
+ [2] = ACTION_FUNCTION(RGBLED_STEP_MODE),
+ [3] = ACTION_FUNCTION(RGBLED_INCREASE_HUE),
+ [4] = ACTION_FUNCTION(RGBLED_DECREASE_HUE),
+ [5] = ACTION_FUNCTION(RGBLED_INCREASE_SAT),
+ [6] = ACTION_FUNCTION(RGBLED_DECREASE_SAT),
+ [7] = ACTION_FUNCTION(RGBLED_INCREASE_VAL),
+ [8] = ACTION_FUNCTION(RGBLED_DECREASE_VAL),
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ #ifdef BACKLIGHT_ENABLE
+ backlight_step();
+ #endif
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) {
+ switch (id) {
+ case RGBLED_TOGGLE:
+ //led operations
+ if (record->event.pressed) {
+ rgblight_toggle();
+ }
+
+ break;
+ case RGBLED_INCREASE_HUE:
+ if (record->event.pressed) {
+ rgblight_increase_hue();
+ }
+ break;
+ case RGBLED_DECREASE_HUE:
+ if (record->event.pressed) {
+ rgblight_decrease_hue();
+ }
+ break;
+ case RGBLED_INCREASE_SAT:
+ if (record->event.pressed) {
+ rgblight_increase_sat();
+ }
+ break;
+ case RGBLED_DECREASE_SAT:
+ if (record->event.pressed) {
+ rgblight_decrease_sat();
+ }
+ break;
+ case RGBLED_INCREASE_VAL:
+ if (record->event.pressed) {
+ rgblight_increase_val();
+ }
+ break;
+ case RGBLED_DECREASE_VAL:
+ if (record->event.pressed) {
+ rgblight_decrease_val();
+ }
+ break;
+ case RGBLED_STEP_MODE:
+ if (record->event.pressed) {
+ rgblight_step();
+ }
+ break;
+ }
+}
diff --git a/keyboards/planck/keymaps/yang/planck-with-rgb-underglow.jpg b/keyboards/planck/keymaps/yang/planck-with-rgb-underglow.jpg
new file mode 100644
index 000000000..c636b9a83
--- /dev/null
+++ b/keyboards/planck/keymaps/yang/planck-with-rgb-underglow.jpg
Binary files differ
diff --git a/keyboards/planck/old_keymap_files/common_keymaps/keymap_brett.c b/keyboards/planck/old_keymap_files/common_keymaps/keymap_brett.c
new file mode 100644
index 000000000..3ebd82af4
--- /dev/null
+++ b/keyboards/planck/old_keymap_files/common_keymaps/keymap_brett.c
@@ -0,0 +1,42 @@
+#include "keymap.h"
+
+const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[0] = KEYMAP(
+ ESC, Q, W, E, R, T, Y, U, I, O, P, BSPC,
+ LCTL, A, S, D, F, G, H, J, K, L, SCLN, ENT,
+ LSFT, Z, X, C, V, B, N, M, COMM, DOT, SLSH, RSFT,
+ TAB, LGUI, RSFT, LALT, FN2, SPC, FN1, LEFT, DOWN, UP, RGHT),
+[1] = KEYMAP( /* RAISE */
+ GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, DEL,
+ TRNS, F1, F2, F3, F4, F5, F6, 4, 5, 6, QUOT, TRNS,
+ TRNS, F7, F8, F9, F10, F11, F12, 1, 2, 3, TRNS, PGUP,
+ MPRV, MNXT, TRNS, MUTE, TRNS, TRNS, FN1, 0, 0, TRNS, PGDN),
+[2] = KEYMAP( /* LOWER */
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, MINS,
+ TRNS, TRNS, TRNS, PAUSE, TRNS, TRNS, TRNS, TRNS, LBRC, RBRC, BSLS, EQL,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,
+ MPLY, MSTP, VOLU, VOLD, FN2, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS),
+};
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_MOMENTARY(1), // to Fn overlay
+ [2] = ACTION_LAYER_MOMENTARY(2), // to Fn overlay
+
+ [10] = ACTION_MODS_KEY(MOD_LSFT, KC_1),
+ [11] = ACTION_MODS_KEY(MOD_LSFT, KC_2),
+ [12] = ACTION_MODS_KEY(MOD_LSFT, KC_3),
+ [13] = ACTION_MODS_KEY(MOD_LSFT, KC_4),
+ [14] = ACTION_MODS_KEY(MOD_LSFT, KC_5),
+ [15] = ACTION_MODS_KEY(MOD_LSFT, KC_6),
+ [16] = ACTION_MODS_KEY(MOD_LSFT, KC_7),
+ [17] = ACTION_MODS_KEY(MOD_LSFT, KC_8),
+ [18] = ACTION_MODS_KEY(MOD_LSFT, KC_9),
+ [19] = ACTION_MODS_KEY(MOD_LSFT, KC_0),
+ [20] = ACTION_MODS_KEY(MOD_LSFT, KC_MINS),
+ [21] = ACTION_MODS_KEY(MOD_LSFT, KC_EQL),
+ [22] = ACTION_MODS_KEY(MOD_LSFT, KC_GRV),
+ [23] = ACTION_MODS_KEY(MOD_LSFT, KC_LBRC),
+ [24] = ACTION_MODS_KEY(MOD_LSFT, KC_RBRC),
+ [28] = ACTION_MODS_KEY(MOD_LSFT, KC_BSLS),
+
+ [29] = ACTION_MODS_KEY(MOD_LSFT | MOD_RSFT, KC_PAUSE),
+};
diff --git a/keyboards/planck/old_keymap_files/common_keymaps/keymap_dotcom.c b/keyboards/planck/old_keymap_files/common_keymaps/keymap_dotcom.c
new file mode 100644
index 000000000..d4ec987ab
--- /dev/null
+++ b/keyboards/planck/old_keymap_files/common_keymaps/keymap_dotcom.c
@@ -0,0 +1,34 @@
+#include "keymap.h"
+
+const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[0] = KEYMAP(
+ ESC, Q, W, E, R, T, Y, U, I, O, P, BSPC,
+ FN1, A, S, D, F, G, H, J, K, L, SCLN, ENT,
+ LSFT, Z, X, C, V, B, N, M, COMM, DOT, SLSH, LBRC,
+ LCTL, BSLS, QUOT, LALT, FN22, SPC, LEFT, UP, DOWN, RGHT, RBRC),
+[1] = KEYMAP(
+ GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, DEL,
+ TRNS, FN10, FN11, FN12, FN13, FN14, FN15, FN16, FN17, TRNS, TRNS, TRNS,
+ TRNS, FN18, FN19, FN22, EQL, MINS, FN20, TRNS, TRNS, TRNS, TRNS, TRNS,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, FN1, TRNS, VOLD, VOLU, TRNS),
+};
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_MOMENTARY(1), // to Fn overlay
+
+ [10] = ACTION_MODS_KEY(MOD_LSFT, KC_1),
+ [11] = ACTION_MODS_KEY(MOD_LSFT, KC_2),
+ [12] = ACTION_MODS_KEY(MOD_LSFT, KC_3),
+ [13] = ACTION_MODS_KEY(MOD_LSFT, KC_4),
+ [14] = ACTION_MODS_KEY(MOD_LSFT, KC_5),
+ [15] = ACTION_MODS_KEY(MOD_LSFT, KC_6),
+ [16] = ACTION_MODS_KEY(MOD_LSFT, KC_7),
+ [17] = ACTION_MODS_KEY(MOD_LSFT, KC_8),
+ [18] = ACTION_MODS_KEY(MOD_LSFT, KC_9),
+ [19] = ACTION_MODS_KEY(MOD_LSFT, KC_0),
+ [20] = ACTION_MODS_KEY(MOD_LSFT, KC_MINS),
+ [21] = ACTION_MODS_KEY(MOD_LSFT, KC_EQL),
+ [22] = ACTION_MODS_KEY(MOD_LSFT, KC_GRV),
+ [23] = ACTION_MODS_KEY(MOD_LSFT, KC_LBRC),
+ [24] = ACTION_MODS_KEY(MOD_LSFT, KC_RBRC),
+ [28] = ACTION_MODS_KEY(MOD_LSFT, KC_BSLS),
+};
diff --git a/keyboards/planck/old_keymap_files/common_keymaps/keymap_jack.c b/keyboards/planck/old_keymap_files/common_keymaps/keymap_jack.c
new file mode 100644
index 000000000..4237949d5
--- /dev/null
+++ b/keyboards/planck/old_keymap_files/common_keymaps/keymap_jack.c
@@ -0,0 +1,50 @@
+#include "keymap.h"
+
+const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[0] = KEYMAP( /* Jack */
+ TAB, Q, W, E, R, T, Y, U, I, O, P, BSPC,
+ ESC, A, S, D, F, G, H, J, K, L, SCLN, QUOT,
+ LSFT, Z, X, C, V, B, N, M, COMM, DOT, SLSH, ENT,
+ RSFT, LCTL, LALT, LGUI, FN2, SPC, FN1, LEFT, DOWN, UP, RGHT),
+[1] = KEYMAP( /* Jack colemak */
+ TAB, Q, W, F, P, G, J, L, U, Y, SCLN, BSPC,
+ ESC, A, R, S, T, D, H, N, E, I, O, QUOT,
+ LSFT, Z, X, C, V, B, K, M, COMM, DOT, SLSH, ENT,
+ FN3, LCTL, LALT, LGUI, FN2, SPC, FN1, LEFT, DOWN, UP, RGHT),
+[2] = KEYMAP( /* Jack RAISE */
+ GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, BSPC,
+ TRNS, FN3, FN4, PAUSE, TRNS, TRNS, TRNS, MINS, EQL, LBRC, RBRC, BSLS,
+ TRNS, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, TRNS,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, FN1, MNXT, VOLD, VOLU, MPLY),
+[3] = KEYMAP( /* Jack LOWER */
+ FN22, FN10, FN11, FN12, FN13, FN14, FN15, FN16, FN17, FN18, FN19, BSPC,
+ TRNS, FN3, FN4, PAUSE, TRNS, TRNS, TRNS, FN20, FN21, FN23, FN24, FN28,
+ TRNS, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, TRNS,
+ TRNS, TRNS, TRNS, TRNS, FN2, TRNS, TRNS, MNXT, VOLD, VOLU, MPLY),
+};
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_MOMENTARY(2), // to Fn overlay
+ [2] = ACTION_LAYER_MOMENTARY(3), // to Fn overlay
+
+ [3] = ACTION_DEFAULT_LAYER_SET(0),
+ [4] = ACTION_DEFAULT_LAYER_SET(1),
+
+ [10] = ACTION_MODS_KEY(MOD_LSFT, KC_1),
+ [11] = ACTION_MODS_KEY(MOD_LSFT, KC_2),
+ [12] = ACTION_MODS_KEY(MOD_LSFT, KC_3),
+ [13] = ACTION_MODS_KEY(MOD_LSFT, KC_4),
+ [14] = ACTION_MODS_KEY(MOD_LSFT, KC_5),
+ [15] = ACTION_MODS_KEY(MOD_LSFT, KC_6),
+ [16] = ACTION_MODS_KEY(MOD_LSFT, KC_7),
+ [17] = ACTION_MODS_KEY(MOD_LSFT, KC_8),
+ [18] = ACTION_MODS_KEY(MOD_LSFT, KC_9),
+ [19] = ACTION_MODS_KEY(MOD_LSFT, KC_0),
+ [20] = ACTION_MODS_KEY(MOD_LSFT, KC_MINS),
+ [21] = ACTION_MODS_KEY(MOD_LSFT, KC_EQL),
+ [22] = ACTION_MODS_KEY(MOD_LSFT, KC_GRV),
+ [23] = ACTION_MODS_KEY(MOD_LSFT, KC_LBRC),
+ [24] = ACTION_MODS_KEY(MOD_LSFT, KC_RBRC),
+ [28] = ACTION_MODS_KEY(MOD_LSFT, KC_BSLS),
+
+ [29] = ACTION_MODS_KEY(MOD_LSFT | MOD_RSFT, KC_PAUSE),
+};
diff --git a/keyboards/planck/old_keymap_files/common_keymaps/keymap_joe.c b/keyboards/planck/old_keymap_files/common_keymaps/keymap_joe.c
new file mode 100644
index 000000000..b8251c857
--- /dev/null
+++ b/keyboards/planck/old_keymap_files/common_keymaps/keymap_joe.c
@@ -0,0 +1,83 @@
+#include "keymap.h"
+
+const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[0] = KEYMAP( /* Joe qwerty */
+ ESC, Q, W, E, R, T, Y, U, I, O, P, MINS,
+ BSPC, A, S, D, F, G, H, J, K, L, SCLN, ENTER,
+ FN7, Z, X, C, V, B, N, M, COMM, DOT, SLSH, QUOT,
+ LCTL, LGUI, LALT, LSFT, FN1, SPC, FN0, LEFT, UP, DOWN, RGHT),
+[1] = KEYMAP( /* Joe colemak */
+ ESC, Q, W, F, P, G, J, L, U, Y, SCLN, MINS,
+ BSPC, A, R, S, T, D, H, N, E, I, O, ENTER,
+ FN7, Z, X, C, V, B, K, M, COMM, DOT, SLSH, QUOT,
+ LCTL, LGUI, LALT, LSFT, FN1, SPC, FN0, LEFT, UP, DOWN, RGHT),
+[2] = KEYMAP( /* Joe UPPER */
+ F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
+ DEL, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,
+ TRNS, TRNS, TRNS, TRNS, TRNS, MENU, CAPS, INS, PSCR, TRNS, FN5, FN6,
+ TRNS, TRNS, TRNS, TRNS, FN2, TRNS, FN0, FN26, FN27, FN28, FN29),
+[3] = KEYMAP( /* Joe LOWER */
+ GRV, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, FN8, FN9, FN30,
+ BSPC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, TRNS,
+ BSLS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, LBRC, RBRC, TRNS, EQL,
+ TRNS, TRNS, TRNS, TRNS, FN1, TRNS, FN2, HOME, PGUP, PGDN, END),
+[4] = KEYMAP( /* Joe LOWER + UPPER */
+ FN3, FN4, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, SLEP,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, MUTE, VOLD, VOLU, MPLY),
+};
+
+enum macro_id {
+ M_Q0,
+ M_Q1,
+ M_Q2
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [0] = ACTION_LAYER_MOMENTARY(2), // to Fn overlay
+ [1] = ACTION_LAYER_MOMENTARY(3), // to Fn overlay
+ [2] = ACTION_LAYER_MOMENTARY(4), // to Fn overlay
+
+ [3] = ACTION_DEFAULT_LAYER_SET(0),
+ [4] = ACTION_DEFAULT_LAYER_SET(1),
+
+ [5] = ACTION_MODS_KEY(MOD_LCTL, KC_PGUP),
+ [6] = ACTION_MODS_KEY(MOD_LCTL, KC_PGDN),
+
+ /* tab on tap, shift on hold */
+ [7] = ACTION_MODS_TAP_KEY(MOD_LSFT, KC_TAB),
+
+ [8] = ACTION_MACRO(M_Q0),
+ [9] = ACTION_MACRO(M_Q1),
+
+ [26] = ACTION_MODS_KEY(MOD_LCTL | MOD_LALT, KC_LEFT),
+ [27] = ACTION_MODS_KEY(MOD_LCTL | MOD_LALT, KC_UP),
+ [28] = ACTION_MODS_KEY(MOD_LCTL | MOD_LALT, KC_DOWN),
+ [29] = ACTION_MODS_KEY(MOD_LCTL | MOD_LALT, KC_RGHT),
+
+ [30] = ACTION_MACRO(M_Q2),
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ keyevent_t event = record->event;
+ switch (id) {
+ case M_Q0:
+ /* :( | ): */
+ return event.pressed ?
+ MACRO( D(LSFT), T(P), T(9), T(SPC), T(SPC), T(0), T(P), U(LSFT), T(LEFT), T(LEFT), T(LEFT), END ) :
+ MACRO_NONE;
+ case M_Q1:
+ /* (: | :) */
+ return event.pressed ?
+ MACRO( D(LSFT), T(9), T(P), T(SPC), T(SPC), T(P), T(0), U(LSFT), T(LEFT), T(LEFT), T(LEFT), END ) :
+ MACRO_NONE;
+ case M_Q2:
+ /* :) */
+ return event.pressed ?
+ MACRO( D(LSFT), T(P), T(0), U(LSFT), END ) :
+ MACRO_NONE;
+ }
+ return MACRO_NONE;
+}
diff --git a/keyboards/planck/old_keymap_files/common_keymaps/keymap_matthew.c b/keyboards/planck/old_keymap_files/common_keymaps/keymap_matthew.c
new file mode 100644
index 000000000..196b2d777
--- /dev/null
+++ b/keyboards/planck/old_keymap_files/common_keymaps/keymap_matthew.c
@@ -0,0 +1,70 @@
+// by Matthew Pepers - https://github.com/pepers
+
+/* grid planck layout - modified programmer dvorak
+,-----------------------------------------------------------------------------------------------.
+| pause | @ | | | ^ | | | | | * | # | $ | del |
+| esc | ; : | , < | . > | P | Y | F | G | G | C | R | bkspc |
+| F1 | F2 | F3 | F4 | F5 | F6 | F7 | F8 | F9 | F10 | F11 | F12 |
+|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
+| & | / | { | ( | [ | = | ! | ] | ) | } | \ | + |
+| ` ~ | A | O | E | U | I | D | H | T | N | S | - _ |
+| % | 7 | 5 | 3 | 1 | 9 | 0 | 2 | 4 | 6 | 8 | ? |
+|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
+| | | | | | | | | | | | prtsc |
+| tab | ' " | Q | J | K | X | B | M | W | V | Z | retrn |
+| | | | | | | | | | | | insrt |
+|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|-------|
+| | | | | | | | | | | | |
+| lctrl | lgui | lalt | ralt | lower | shift | space | raise | left | down | up | right |
+| | | | | | | | | home | pgdn | pgup | end |
+`-----------------------------------------------------------------------------------------------'
+*/
+
+#include "keymap.h"
+
+const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ /* 0: dvorak */
+ [0] = KEYMAP_GRID( ESC, SCLN, COMM, DOT, P, Y, F, G, C, R, L, BSPC, \
+ GRV, A, O, E, U, I, D, H, T, N, S, MINS, \
+ TAB, QUOT, Q, J, K, X, B, M, W, V, Z, ENT, \
+ LCTL, LGUI, LALT, RALT, FN1, LSFT, SPC, FN2, LEFT, DOWN, UP, RGHT),
+
+ /* 1: lower (FN1) */
+ [1] = KEYMAP_GRID( F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, \
+ FN17, 7, 5, 3, 1, 9, 0, 2, 4, 6, 8, FN18, \
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, INS, \
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, HOME, PGDN, PGUP, END),
+
+ /* 2: raise (FN2) */
+ [2] = KEYMAP_GRID(PAUS, FN19, FN20, FN21, TRNS, TRNS, TRNS, TRNS, FN22, FN23, FN24, DEL, \
+ FN10, SLSH, FN11, FN12, LBRC, EQL, FN13, RBRC, FN14, FN15, BSLS, FN16, \
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, PSCR, \
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS),
+
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_MOMENTARY(1), // lower Fn layer
+ [2] = ACTION_LAYER_MOMENTARY(2), // raise Fn layer
+
+ // lower row1
+ [17] = ACTION_MODS_KEY(MOD_LSFT, KC_5), // %
+ [18] = ACTION_MODS_KEY(MOD_LSFT, KC_SLASH), // ?
+
+ // raise row0
+ [19] = ACTION_MODS_KEY(MOD_LSFT, KC_2), // @
+ [20] = ACTION_MODS_KEY(MOD_LSFT, KC_BSLASH), // |
+ [21] = ACTION_MODS_KEY(MOD_LSFT, KC_6), // ^
+ [22] = ACTION_MODS_KEY(MOD_LSFT, KC_8), // *
+ [23] = ACTION_MODS_KEY(MOD_LSFT, KC_3), // #
+ [24] = ACTION_MODS_KEY(MOD_LSFT, KC_4), // $
+
+ // raise row1
+ [10] = ACTION_MODS_KEY(MOD_LSFT, KC_7), // &
+ [11] = ACTION_MODS_KEY(MOD_LSFT, KC_LBRACKET), // {
+ [12] = ACTION_MODS_KEY(MOD_LSFT, KC_9), // (
+ [13] = ACTION_MODS_KEY(MOD_LSFT, KC_1), // !
+ [14] = ACTION_MODS_KEY(MOD_LSFT, KC_0), // )
+ [15] = ACTION_MODS_KEY(MOD_LSFT, KC_RBRACKET), // }
+ [16] = ACTION_MODS_KEY(MOD_LSFT, KC_EQUAL), // +
+};
diff --git a/keyboards/planck/old_keymap_files/common_keymaps/keymap_mitch.c b/keyboards/planck/old_keymap_files/common_keymaps/keymap_mitch.c
new file mode 100644
index 000000000..e5a86b402
--- /dev/null
+++ b/keyboards/planck/old_keymap_files/common_keymaps/keymap_mitch.c
@@ -0,0 +1,49 @@
+#include "keymap.h"
+
+const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[0] = KEYMAP(
+ TAB, Q, W, E, R, T, Y, U, I, O, P, BSPC,
+ LCTL, A, S, D, F, G, H, J, K, L, SCLN, QUOT,
+ LSFT, Z, X, C, V, B, N, M, COMM, DOT, SLSH, FN3,
+ ESC, DEL, LALT, LGUI, FN2, SPC, FN1, LEFT, DOWN, UP, RGHT),
+[1] = KEYMAP(
+ GRV, GRV, FN22, FN19, FN10, TRNS, TRNS, 7, 8, 9, 0, BSPC,
+ TRNS, LBRC, RBRC, FN23, FN24, TRNS, TRNS, 4, 5, 6, TRNS, BSLS,
+ TRNS, MINS, FN20, EQL, FN21, TRNS, TRNS, 1, 2, 3, TRNS, ENT,
+ TRNS, TRNS, TRNS, TRNS, TRNS, SPC, FN1, TRNS, PGDN, PGUP, TRNS),
+[2] = KEYMAP(
+ FN26, FN10, FN11, FN12, FN13, FN14, FN15, FN17, FN18, FN19, FN10, DEL,
+ TRNS, TRNS, MUTE, VOLD, VOLU, TRNS, BSPC, FN14, FN15, FN16, TRNS, FN25,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, FN11, FN12, FN13, TRNS, ENT,
+ TRNS, TRNS, TRNS, TRNS, FN2, ENT, TRNS, TRNS, PGDN, PGUP, TRNS),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_MOMENTARY(1), // Switch layer raise
+ [2] = ACTION_LAYER_MOMENTARY(2), // Switch layer lower
+
+ [3] = ACTION_MODS_TAP_KEY(MOD_RSFT, KC_ENT), // Right shift serves as Enter on tap
+
+ // Numeric shift modifiers
+ [10] = ACTION_MODS_KEY(MOD_LSFT, KC_0),
+ [11] = ACTION_MODS_KEY(MOD_LSFT, KC_1),
+ [12] = ACTION_MODS_KEY(MOD_LSFT, KC_2),
+ [13] = ACTION_MODS_KEY(MOD_LSFT, KC_3),
+ [14] = ACTION_MODS_KEY(MOD_LSFT, KC_4),
+ [15] = ACTION_MODS_KEY(MOD_LSFT, KC_5),
+ [16] = ACTION_MODS_KEY(MOD_LSFT, KC_6),
+ [17] = ACTION_MODS_KEY(MOD_LSFT, KC_7),
+ [18] = ACTION_MODS_KEY(MOD_LSFT, KC_8),
+ [19] = ACTION_MODS_KEY(MOD_LSFT, KC_9),
+
+ // Other shift modifiers
+ [20] = ACTION_MODS_KEY(MOD_LSFT, KC_MINS), // _
+ [21] = ACTION_MODS_KEY(MOD_LSFT, KC_EQL), // +
+ [22] = ACTION_MODS_KEY(MOD_LSFT, KC_GRV), // ~
+ [23] = ACTION_MODS_KEY(MOD_LSFT, KC_LBRC), // {
+ [24] = ACTION_MODS_KEY(MOD_LSFT, KC_RBRC), // }
+ [25] = ACTION_MODS_KEY(MOD_LSFT, KC_BSLS), // |
+
+ // Switch windows in app
+ [26] = ACTION_MODS_KEY(MOD_LGUI, KC_GRV),
+};
diff --git a/keyboards/planck/old_keymap_files/common_keymaps/keymap_nathan.c b/keyboards/planck/old_keymap_files/common_keymaps/keymap_nathan.c
new file mode 100644
index 000000000..f0be4b030
--- /dev/null
+++ b/keyboards/planck/old_keymap_files/common_keymaps/keymap_nathan.c
@@ -0,0 +1,153 @@
+// Author: Nathan Ross Powell <nathanrospowell@gmail.com>
+// https://github.com/nathanrosspowell/tmk_keyboard/blob/planck-jack/keyboard/planck/keymap_nathan.c
+
+#include "keymap.h"
+
+const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ /* 0: main layer
+ * ,-----------------------------------------------------------------------.
+ * |Tab | q | w | e | r | t | y | u | i | o | p | BS |
+ * |-----------------------------------------------------------------------|
+ * |Ctrl | a | s | d | f | g | h | j | k | l | ; | Ret |
+ * |-----------------------------------------------------------------------|
+ * |Shift| z | x | c | v | b | n | m | [ | ( | { | < |
+ * |-----------------------------------------------------------------------|
+ * |Meta | \ | / | Alt |Lower|Space|Space|Upper|Left |Down | Up |Right|
+ * `-----------------------------------------------------------------------'
+ */
+ [0] = KEYMAP_GRID(
+ TAB, Q, W, E, R, T, Y, U, I, O, P, BSPC,
+ LCTL, A, S, D, F, G, H, J, K, L, SCLN, ENT,
+ RSFT, Z, X, C, V, B, N, M, LBRC, FN10, FN11, FN12,
+ LGUI, BSLS, SLSH, LALT, FN0, SPC, SPC, FN1, LEFT, DOWN, UP, RGHT),
+
+ /* 1: fn left/lower layer
+ * The top row are Visual Studio combos:
+ * 'Run', 'Breakpoint', 'Step over', 'Step into', 'Set cursor to line'
+ * 2nd row are key combos:
+ * 'ctrl-alt-delete', 'ctrl-shift-escape'
+ * 3rd row are macros keys:
+ * 'P0' - 'P5' execute a script on Windows machines
+ * ,-----------------------------------------------------------------------.
+ * | ESC | F5 | F9 | F10 | F11 |S+F11|CSF10|NLock|Num7 |Num8 |Num9 | Del |
+ * |-----------------------------------------------------------------------|
+ * | |C/A/D|C/S/E| Ins |Print|Pause|SLock|Num0 |Num4 |Num5 |Num6 |Num= |
+ * |-----------------------------------------------------------------------|
+ * | | P0 | P1 | P2 | P3 | P4 | P5 |Num. |Num1 |Num2 |Num3 |Num/ |
+ * |-----------------------------------------------------------------------|
+ * | |User | | | | | | |Home |PgDn |PgUp | End |
+ * `-----------------------------------------------------------------------'
+ */
+ [1] = KEYMAP_GRID(
+ ESC, F5, F9, F10, F11, FN30, FN31, NLCK, P7, P8, P9, DEL,
+ TRNS, FN16, FN17, INS, PSCR, PAUS, SLCK, P0, P4, P5, P6, PEQL,
+ TRNS, FN2, FN3, FN4, FN5, FN6, FN7, PDOT, P1, P2, P3, PSLS,
+ TRNS, FN8, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, HOME, PGDN, PGUP, END ),
+
+ /* 2: fn right/raise layer
+ * ,-----------------------------------------------------------------------.
+ * | F1 | F2 | F3 | F4 |F5 | F6 | F7 | F8 | F9 | F10 | F11 | F12 |
+ * |-----------------------------------------------------------------------|
+ * | | ! | @ | # | $ | % | ^ | & | * | - | + | = |
+ * |-----------------------------------------------------------------------|
+ * | | _ | ' | " | ` | ~ | , | . | ] | ) | } | > |
+ * |-----------------------------------------------------------------------|
+ * | |NextT|PrevT| | | | Esc | |Mute |Vol- |Vol+ | P/P |
+ * `-----------------------------------------------------------------------'
+ */
+ [2] = KEYMAP_GRID(
+ F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
+ TRNS, FN18, FN19, FN20, FN21, FN22, FN23, FN24, FN25, MINS, FN26, PAST,
+ TRNS, FN27, QUOT, FN28, GRV, FN29, COMM, DOT, RBRC, FN13, FN14, FN15,
+ TRNS, MNXT, MPRV, TRNS, TRNS, TRNS, ESC, TRNS, MUTE, VOLD, VOLU, MPLY ),
+};
+
+enum macro_id {
+ M_P0,
+ M_P1,
+ M_P2,
+ M_P3,
+ M_P4,
+ M_P5,
+ M_USERNAME
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [0] = ACTION_LAYER_MOMENTARY(1), // left/lower layer
+ [1] = ACTION_LAYER_MOMENTARY(2), // right/raise layer
+ // Program macros
+ [2] = ACTION_MACRO(M_P0),
+ [3] = ACTION_MACRO(M_P1),
+ [4] = ACTION_MACRO(M_P2),
+ [5] = ACTION_MACRO(M_P3),
+ [6] = ACTION_MACRO(M_P4),
+ [7] = ACTION_MACRO(M_P5),
+ [8] = ACTION_MACRO(M_USERNAME),
+ // Braces
+ [10] = ACTION_MODS_KEY(MOD_LSFT, KC_9), // (
+ [11] = ACTION_MODS_KEY(MOD_LSFT, KC_LBRC), // {
+ [12] = ACTION_MODS_KEY(MOD_LSFT, KC_COMMA), // <
+ [13] = ACTION_MODS_KEY(MOD_LSFT, KC_0), // )
+ [14] = ACTION_MODS_KEY(MOD_LSFT, KC_RBRC), // }
+ [15] = ACTION_MODS_KEY(MOD_LSFT, KC_DOT), // >
+ // Combo
+ [16] = ACTION_MODS_KEY(MOD_LALT | MOD_LCTL, KC_DEL), // Ctrl+Alt+Delete
+ [17] = ACTION_MODS_KEY(MOD_LSFT | MOD_LCTL, KC_ESC), // Ctrl+Shft+Escape
+ // Symbols
+ [18] = ACTION_MODS_KEY(MOD_LSFT, KC_1), // !
+ [19] = ACTION_MODS_KEY(MOD_LSFT, KC_2), // @
+ [20] = ACTION_MODS_KEY(MOD_LSFT, KC_3), // #
+ [21] = ACTION_MODS_KEY(MOD_LSFT, KC_4), // $
+ [22] = ACTION_MODS_KEY(MOD_LSFT, KC_5), // %
+ [23] = ACTION_MODS_KEY(MOD_LSFT, KC_6), // ^
+ [24] = ACTION_MODS_KEY(MOD_LSFT, KC_7), // &
+ [25] = ACTION_MODS_KEY(MOD_LSFT, KC_8), // *
+ [26] = ACTION_MODS_KEY(MOD_LSFT, KC_EQL), // +
+ [27] = ACTION_MODS_KEY(MOD_LSFT, KC_MINUS), // _
+ [28] = ACTION_MODS_KEY(MOD_LSFT, KC_QUOTE), // "
+ [29] = ACTION_MODS_KEY(MOD_LSFT, KC_GRAVE), // ~
+ // Debugging
+ [30] = ACTION_MODS_KEY(MOD_LSFT, KC_F11), // Step into
+ [31] = ACTION_MODS_KEY(MOD_LSFT | MOD_LCTL, KC_F10), // Set cursor to line
+ };
+
+// Run a script and pass a key number to it. This is Windows specific and the script needs to be on your path.
+// *open run dialog* keypress.py [PRG_NUM]
+#define ADD_PYTHON_PROGRAM_ON_WIN( PRG_NUM ) MACRO( D(LGUI), T(R), U(LGUI), W(100), T(K), T(E), T(Y), T(P), T(R), T(E), T(S), T(S), T(DOT), T(P), T(Y), T(SPC), T(PRG_NUM), END )
+// *return*
+#define RUN_PYTHON_PROGRAM_ON_WIN MACRO( T(ENT), END )
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) {
+ keyevent_t event = record->event;
+ switch (id) {
+ case M_P0:
+ return event.pressed ?
+ ADD_PYTHON_PROGRAM_ON_WIN( 0 ) :
+ RUN_PYTHON_PROGRAM_ON_WIN;
+ case M_P1:
+ return event.pressed ?
+ ADD_PYTHON_PROGRAM_ON_WIN( 1 ) :
+ RUN_PYTHON_PROGRAM_ON_WIN;
+ case M_P2:
+ return event.pressed ?
+ ADD_PYTHON_PROGRAM_ON_WIN( 2 ) :
+ RUN_PYTHON_PROGRAM_ON_WIN;
+ case M_P3:
+ return event.pressed ?
+ ADD_PYTHON_PROGRAM_ON_WIN( 3 ) :
+ RUN_PYTHON_PROGRAM_ON_WIN;
+ case M_P4:
+ return event.pressed ?
+ ADD_PYTHON_PROGRAM_ON_WIN( 4 ) :
+ RUN_PYTHON_PROGRAM_ON_WIN;
+ case M_P5:
+ return event.pressed ?
+ ADD_PYTHON_PROGRAM_ON_WIN( 5 ) :
+ RUN_PYTHON_PROGRAM_ON_WIN;
+ case M_USERNAME:
+ return event.pressed ?
+ MACRO( T(N), T(A), T(T), T(H), T(A), T(N), T(R), T(O), T(S), T(S), T(P), T(O), T(W), T(E), T(L), T(L), END ) :
+ MACRO_NONE;
+ }
+ return MACRO_NONE;
+}
diff --git a/keyboards/planck/old_keymap_files/common_keymaps/keymap_paul.c b/keyboards/planck/old_keymap_files/common_keymaps/keymap_paul.c
new file mode 100644
index 000000000..51d45be75
--- /dev/null
+++ b/keyboards/planck/old_keymap_files/common_keymaps/keymap_paul.c
@@ -0,0 +1,49 @@
+#include "keymap.h"
+
+const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[0] = KEYMAP( /* Paul */
+ TAB, Q, W, E, R, T, Y, U, I, O, P, BSPC,
+ FN1, A, S, D, F, G, H, J, K, L, SCLN, QUOT,
+ LSFT, Z, X, C, V, B, N, M, COMM, DOT, SLSH, ENT,
+ ESC, LCTL, LALT, LGUI, FN2, SPC, FN3, LEFT, DOWN, UP, RGHT),
+[1] = KEYMAP( /* Paul FN */
+ TRNS, TRNS, TRNS, FN8, FN9, TRNS, TRNS, TRNS, TRNS, MUTE, VOLD, VOLU,
+ FN1, TRNS, TRNS, HOME, END, TRNS, TRNS, TRNS, TRNS, MPRV, MPLY, MNXT,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, UP, TRNS,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, LEFT, DOWN, RGHT),
+[2] = KEYMAP( /* Paul LOWER */
+ FN22, FN10, FN11, FN12, FN13, FN14, FN15, FN16, FN17, FN18, FN19, BSPC,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, FN20, FN21, FN23, FN24, FN28,
+ TRNS, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, TRNS,
+ TRNS, TRNS, TRNS, TRNS, FN2, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS),
+[3] = KEYMAP( /* Paul RAISE */
+ GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, BSPC,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, MINS, EQL, LBRC, RBRC, BSLS,
+ TRNS, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, TRNS,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, FN3, TRNS, TRNS, TRNS, TRNS),
+};
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_MOMENTARY(1), // to Fn1 overlay (FN)
+ [2] = ACTION_LAYER_MOMENTARY(2), // to Fn2 overlay (LOWER)
+ [3] = ACTION_LAYER_MOMENTARY(3), // to Fn3 overlay (RAISE)
+
+ [8] = ACTION_MODS_KEY(MOD_LSFT, KC_HOME),
+ [9] = ACTION_MODS_KEY(MOD_LSFT, KC_END),
+ [10] = ACTION_MODS_KEY(MOD_LSFT, KC_1),
+ [11] = ACTION_MODS_KEY(MOD_LSFT, KC_2),
+ [12] = ACTION_MODS_KEY(MOD_LSFT, KC_3),
+ [13] = ACTION_MODS_KEY(MOD_LSFT, KC_4),
+ [14] = ACTION_MODS_KEY(MOD_LSFT, KC_5),
+ [15] = ACTION_MODS_KEY(MOD_LSFT, KC_6),
+ [16] = ACTION_MODS_KEY(MOD_LSFT, KC_7),
+ [17] = ACTION_MODS_KEY(MOD_LSFT, KC_8),
+ [18] = ACTION_MODS_KEY(MOD_LSFT, KC_9),
+ [19] = ACTION_MODS_KEY(MOD_LSFT, KC_0),
+ [20] = ACTION_MODS_KEY(MOD_LSFT, KC_MINS),
+ [21] = ACTION_MODS_KEY(MOD_LSFT, KC_EQL),
+ [22] = ACTION_MODS_KEY(MOD_LSFT, KC_GRV),
+ [23] = ACTION_MODS_KEY(MOD_LSFT, KC_LBRC),
+ [24] = ACTION_MODS_KEY(MOD_LSFT, KC_RBRC),
+ [28] = ACTION_MODS_KEY(MOD_LSFT, KC_BSLS),
+
+};
diff --git a/keyboards/planck/old_keymap_files/common_keymaps/keymap_peasant.c b/keyboards/planck/old_keymap_files/common_keymaps/keymap_peasant.c
new file mode 100644
index 000000000..f6493e33a
--- /dev/null
+++ b/keyboards/planck/old_keymap_files/common_keymaps/keymap_peasant.c
@@ -0,0 +1,51 @@
+#include "keymap.h"
+
+const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ [0] = KEYMAP( /* Native */
+ ESC, Q, W, E, R, T, Y, U, I, O, P, FN2,
+ BSPC, A, S, D, F, G, H, J, K, L, SCLN, QUOT,
+ TAB, Z, X, C, V, B, N, M, COMM, DOT, SLSH, ENT,
+ DEL, LCTL, NO, LSFT, LALT, SPC, NO, LEFT, DOWN, UP, RGHT),
+ [1] = KEYMAP( /* QWERTY->PHOTOSHOP */
+ DELETE, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, FN1,
+ O, G, S, U, T, FN27, F21, F10, F11, F7, F8, F9,
+ TAB, FN4, FN5, FN6, F1, FN7, F18, F19, F23, F20, F22, FN9,
+ COMM, DOT, FN10, FN11, FN3, SPC, FN12, F2, FN8, F3, F14),
+ [2] = KEYMAP( /* 2: FN3 PHOTOSHOP */
+ ESC, FN25, FN26, NO, NO, NO, NO, NO, NO, NO, NO, NO,
+ NO, NO, NO, NO, NO, NO, NO, NO, NO, FN19, FN20, FN21,
+ C, NO, FN22, FN5, NO, FN23, NO, NO, NO, NO, FN13, NO,
+ FN14, FN15, FN16, FN17, FN3, SPC, FN18, NO, NO, F24, NO),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_DEFAULT_LAYER_SET(0), // set Qwerty layout
+ [2] = ACTION_DEFAULT_LAYER_SET(1), // set Photoshop presets
+ [3] = ACTION_LAYER_ON_OFF(2), // Photoshop function layer
+
+ [4] = ACTION_MODS_KEY(MOD_LSFT | MOD_LCTL | MOD_LALT, KC_F9), // photo folder AHK
+ [5] = ACTION_MODS_KEY(MOD_LSFT | MOD_LCTL, KC_I), // select inverse
+ [6] = ACTION_MODS_KEY(MOD_LSFT, KC_M), // marquee select
+ [7] = ACTION_MODS_KEY(MOD_LALT, KC_BSPC), // fill
+ [8] = ACTION_MODS_KEY(MOD_LSFT | MOD_LCTL | MOD_LALT, KC_X), // warp
+ [9] = ACTION_MODS_KEY(MOD_LCTL | MOD_LALT | MOD_LSFT, KC_F12), // merge all new layer
+ [10] = ACTION_MODS_KEY(MOD_LCTL, KC_MINS), // zoom out
+ [11] = ACTION_MODS_KEY(MOD_LCTL, KC_H), // RBG sliders
+ [12] = ACTION_MODS_KEY(MOD_LCTL, KC_S), // save
+ [13] = ACTION_MODS_KEY(MOD_LSFT | MOD_LCTL, KC_F5), // layer mask from transparancy
+ [14] = ACTION_MODS_KEY(MOD_LALT, KC_LBRC), // prev layer
+ [15] = ACTION_MODS_KEY(MOD_LALT, KC_RBRC), // next layer
+ [16] = ACTION_MODS_KEY(MOD_LCTL, KC_EQL), // zoom in
+ [17] = ACTION_MODS_KEY(MOD_LSFT | MOD_LCTL, KC_H), // HSV sliders
+ [18] = ACTION_MODS_KEY(MOD_LSFT | MOD_LCTL | MOD_LALT, KC_F11), // save as PNG
+ [19] = ACTION_MODS_KEY(MOD_LSFT | MOD_LCTL | MOD_LALT, KC_F7), // gaussian blur
+ [20] = ACTION_MODS_KEY(MOD_LSFT | MOD_LCTL | MOD_LALT, KC_F8), // motion blur
+ [21] = ACTION_MODS_KEY(MOD_LSFT | MOD_LCTL, KC_X), // liquify filter
+ [22] = ACTION_MODS_KEY(MOD_LSFT, KC_MINS), // prev layer blending
+ [23] = ACTION_MODS_KEY(MOD_LSFT | MOD_LALT, KC_N), // normal layer blending
+ [24] = ACTION_MODS_KEY(MOD_LSFT, KC_EQL), // next layer blending
+ [25] = ACTION_MODS_KEY(MOD_LCTL, KC_Z), // step back
+ [26] = ACTION_MODS_KEY(MOD_LCTL, KC_Y), // step forward
+ [27] = ACTION_MODS_KEY(MOD_LCTL, KC_R), // rasterize
+
+};
diff --git a/keyboards/planck/old_keymap_files/common_keymaps/keymap_reed.c b/keyboards/planck/old_keymap_files/common_keymaps/keymap_reed.c
new file mode 100644
index 000000000..f721716fd
--- /dev/null
+++ b/keyboards/planck/old_keymap_files/common_keymaps/keymap_reed.c
@@ -0,0 +1,74 @@
+#include "keymap.h"
+
+/*
+ * BUILD:
+ * Simply run the command below in the keyboards/planck directory
+ * to build against this keymap
+ *
+ * make KEYMAP=reed COMMON_KEYMAP=true
+ *
+ *
+ * DETAILS:
+ *
+ * This layout works off of Jack's layout, making some changes that I
+ * feel significantly improve the function of the keyboard. Major changes
+ * include adding a "gaming mode" that will allow users to still access
+ * the number keys 1 through 4 easily for games that require it. Also
+ * included is the ability to use the tap/hold function for easy use of
+ * right shift and thumb shift with their tapped companions.
+ *
+ */
+const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[0] = KEYMAP_GRID( /* Reed */
+ ESC, Q, W, E, R, T, Y, U, I, O, P, BSPC,
+ TAB, A, S, D, F, G, H, J, K, L, SCLN, QUOT,
+ LSFT, Z, X, C, V, B, N, M, COMM, DOT, SLSH, FN5,
+ LCTL, CAPS, LALT, LGUI, FN2, FN7, SPC, FN1, LEFT, DOWN, UP, RGHT),
+
+[1] = KEYMAP_GRID( /* Reed EXTREME GAMING */
+ ESC, Q, W, E, R, T, Y, U, I, O, P, BSPC,
+ TAB, A, S, D, F, G, H, J, K, L, SCLN, QUOT,
+ LSFT, Z, X, C, V, B, N, M, COMM, DOT, SLSH, FN5,
+ LCTL, 1, 2, 3, 4, SPC, FN2, FN1, LEFT, DOWN, UP, RGHT),
+
+[2] = KEYMAP_GRID( /* Reed RAISE */
+ GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, BSPC,
+ TRNS, FN3, FN4, PAUSE, TRNS, TRNS, TRNS, MINS, EQL, LBRC, RBRC, BSLS,
+ TRNS, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, TRNS,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, FN1, MNXT, VOLD, VOLU, MPLY),
+
+[3] = KEYMAP_GRID( /* Reed LOWER */
+ TRNS, FN10, FN11, FN12, FN13, FN14, FN15, FN16, FN17, FN18, FN19, DEL,
+ TRNS, TRNS, INS, HOME, PGUP, TRNS, TRNS, FN20, FN21, FN23, FN24, FN28,
+ TRNS, TRNS, DEL, END, PGDN, F11, F12, F13, TRNS, VOLD, VOLU, TRNS,
+ TRNS, TRNS, TRNS, TRNS, FN2, TRNS, TRNS, TRNS, MPRV, MUTE, MPLY, MNXT),
+};
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_MOMENTARY(2), // to Fn overlay - RAISE
+ [2] = ACTION_LAYER_MOMENTARY(3), // to Fn overlay - LOWER
+
+ [3] = ACTION_DEFAULT_LAYER_SET(0),
+ [4] = ACTION_DEFAULT_LAYER_SET(1),
+ // Actions for the tap/hold modifiers listed above
+ [5] = ACTION_MODS_TAP_KEY(MOD_RSFT, KC_ENT),
+ [7] = ACTION_MODS_TAP_KEY(MOD_LSFT, KC_BSPC),
+
+ [10] = ACTION_MODS_KEY(MOD_LSFT, KC_1),
+ [11] = ACTION_MODS_KEY(MOD_LSFT, KC_2),
+ [12] = ACTION_MODS_KEY(MOD_LSFT, KC_3),
+ [13] = ACTION_MODS_KEY(MOD_LSFT, KC_4),
+ [14] = ACTION_MODS_KEY(MOD_LSFT, KC_5),
+ [15] = ACTION_MODS_KEY(MOD_LSFT, KC_6),
+ [16] = ACTION_MODS_KEY(MOD_LSFT, KC_7),
+ [17] = ACTION_MODS_KEY(MOD_LSFT, KC_8),
+ [18] = ACTION_MODS_KEY(MOD_LSFT, KC_9),
+ [19] = ACTION_MODS_KEY(MOD_LSFT, KC_0),
+ [20] = ACTION_MODS_KEY(MOD_LSFT, KC_MINS),
+ [21] = ACTION_MODS_KEY(MOD_LSFT, KC_EQL),
+ [22] = ACTION_MODS_KEY(MOD_LSFT, KC_GRV),
+ [23] = ACTION_MODS_KEY(MOD_LSFT, KC_LBRC),
+ [24] = ACTION_MODS_KEY(MOD_LSFT, KC_RBRC),
+ [28] = ACTION_MODS_KEY(MOD_LSFT, KC_BSLS),
+
+ [29] = ACTION_MODS_KEY(MOD_LSFT | MOD_RSFT, KC_PAUSE),
+};
diff --git a/keyboards/planck/old_keymap_files/common_keymaps/keymap_sean.c b/keyboards/planck/old_keymap_files/common_keymaps/keymap_sean.c
new file mode 100644
index 000000000..fb0eb7dad
--- /dev/null
+++ b/keyboards/planck/old_keymap_files/common_keymaps/keymap_sean.c
@@ -0,0 +1,53 @@
+#include "keymap.h"
+
+const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ [0] = KEYMAP( /* Matrix Dvorak */
+ QUOT, COMM, DOT, P, Y, SLSH, EQL, F, G, C, R, L,
+ A, O, E, U, I, ESC, BSPC, D, H, T, N, S,
+ SCLN, Q, J, K, X, TAB, ENT, B, M, W, V, Z,
+ LSFT, LCTL, LALT, LGUI, FN1, SPC, FN2, LEFT, DOWN, UP, RGHT),
+
+ [1] = KEYMAP( /* Matrix Qwerty */
+ Q, W, E, R, T, QUOT, EQL, Y, U, I, O, P,
+ A, S, D, F, G, ESC, BSPC, H, J, K, L, SCLN,
+ Z, X, C, V, B, TAB, ENT, N, M, COMM, DOT, SLSH,
+ LSFT, LCTL, LALT, LGUI, FN1, SPC, FN2, LEFT, DOWN, UP, RGHT),
+
+ [2] = KEYMAP( /* fn1 lower */
+ F1, F2, F3, F4, F5, NO, NO, F6, F7, F8, F9, F10,
+ 1, 2, 3, 4, 5, F18, DEL, 6, 7, 8, 9, 0,
+ FN3, FN4, FN28, GRV, MINS, TRNS, INS, BSLS, LBRC, RBRC, TRNS, TRNS,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, HOME, PGDN, PGUP, END),
+
+ [3] = KEYMAP( /* fn2 raise */
+ MRWD, MPLY, MFFD, NO, NO, FN21, FN22, EJCT, PWR, LSFT,PAUSE, RSFT,
+ FN11, FN12, FN13, FN14, FN15, F18, DEL, FN16, FN17, FN18, FN19, FN20,
+ FN3, FN4, FN28, FN23, FN24, TRNS, INS, FN25, FN26, FN27, MPRV, MNXT,
+ TRNS, TRNS, TRNS, TRNS, FN1, TRNS, FN2, NO, VOLD, VOLU, MUTE),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_MOMENTARY(2), // to Fn overlay LOWER
+ [2] = ACTION_LAYER_MOMENTARY(3), // to Fn overlay RAISE
+ [3] = ACTION_DEFAULT_LAYER_SET(0),
+ [4] = ACTION_DEFAULT_LAYER_SET(1),
+
+ [11] = ACTION_MODS_KEY(MOD_LSFT, KC_1),
+ [12] = ACTION_MODS_KEY(MOD_LSFT, KC_2),
+ [13] = ACTION_MODS_KEY(MOD_LSFT, KC_3),
+ [14] = ACTION_MODS_KEY(MOD_LSFT, KC_4),
+ [15] = ACTION_MODS_KEY(MOD_LSFT, KC_5),
+ [16] = ACTION_MODS_KEY(MOD_LSFT, KC_6),
+ [17] = ACTION_MODS_KEY(MOD_LSFT, KC_7),
+ [18] = ACTION_MODS_KEY(MOD_LSFT, KC_8),
+ [19] = ACTION_MODS_KEY(MOD_LSFT, KC_9),
+ [20] = ACTION_MODS_KEY(MOD_LSFT, KC_0),
+ [21] = ACTION_MODS_KEY(MOD_LSFT, KC_SLSH),
+ [22] = ACTION_MODS_KEY(MOD_LSFT, KC_EQL),
+ [23] = ACTION_MODS_KEY(MOD_LSFT, KC_GRV),
+ [24] = ACTION_MODS_KEY(MOD_LSFT, KC_MINS),
+ [25] = ACTION_MODS_KEY(MOD_LSFT, KC_BSLS),
+ [26] = ACTION_MODS_KEY(MOD_LSFT, KC_LBRC),
+ [27] = ACTION_MODS_KEY(MOD_LSFT, KC_RBRC),
+ [28] = ACTION_MODS_KEY(MOD_LSFT | MOD_RSFT, KC_PAUSE),
+};
diff --git a/keyboards/planck/old_keymap_files/common_keymaps/keymap_shane.c b/keyboards/planck/old_keymap_files/common_keymaps/keymap_shane.c
new file mode 100644
index 000000000..2191758c8
--- /dev/null
+++ b/keyboards/planck/old_keymap_files/common_keymaps/keymap_shane.c
@@ -0,0 +1,98 @@
+#include "keymap.h"
+#include "action_layer.h"
+#include "action.h"
+#include "action_util.h"
+
+/*
+ Shane's Planck Layout
+ http://www.keyboard-layout-editor.com/#/layouts/015d9011102619d7695c86ffe57cf441
+*/
+const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ [0] = KEYMAP_AND_SWAP( /* Base */
+ TAB, Q, W, E, R, T, Y, U, I, O, P, MINS,
+ LCTL, A, S, D, F, G, H, J, K, L, SCLN, BSPC,
+ LSFT, Z, X, C, V, B, N, M, COMM, DOT, SLSH, FN5,
+ /*ALPHA*/FN3, /*HYPER*/ /*SUPER*/LGUI, /*META*/LALT, LCTL, FN2, FN6, FN1, LEFT, DOWN, UP, RGHT),
+ [2] = KEYMAP_AND_SWAP( /* More modifiers */
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, RCTL, RALT, RGUI, TRNS),
+ [4] = KEYMAP_AND_SWAP( /* WASD */
+ TRNS, TRNS, UP, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,
+ TRNS, LEFT, DOWN, RIGHT, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS),
+ [6] = KEYMAP_AND_SWAP( /* Raise/FN1 */
+ FN23, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, EQL,
+ TRNS, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, ENT,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, BSLS, TRNS,
+ PAUS, TRNS, TRNS, TRNS, TRNS, BSPC, TRNS, MUTE, PGUP, PGDN, MNXT),
+ [8] = KEYMAP_AND_SWAP( /* Lower/FN2 */
+ ESC, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, FN19, FN20, TRNS,
+ TRNS, TRNS, TRNS, TRNS, CAPS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, QUOT,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, FN24, FN25, LBRC, RBRC, TRNS, TRNS,
+ FN4, TRNS, TRNS, TRNS, TRNS, ENT, TRNS, MPLY, VOLD, VOLU, MPRV),
+};
+
+enum function_id {
+ SPACE_FN,
+};
+
+void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ switch (id) {
+ case SPACE_FN:
+ if (record->event.pressed) {
+ // Change the keyboard maps.
+ // Whatever even layer's are on, turn on the odd one's too.
+ for (uint8_t i = 0; i < 9; i += 2) {
+ if (layer_state & (1UL << i))
+ layer_on(i + 1);
+ }
+ layer_on(1);
+ } else {
+ // turn off all the even layers.
+ for (uint8_t i = 0; i < 9; i += 2)
+ layer_off(i + 1);
+
+ if (record->tap.count != 0) {
+ // Space was tapped rather than used like a modifier.
+ // So send a space up and down event.
+ add_key(KC_SPC);
+ send_keyboard_report();
+ del_key(KC_SPC);
+ send_keyboard_report();
+ }
+ }
+ break;
+ }
+}
+
+
+
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_MOMENTARY(6), // to fist Fn overlay
+ [2] = ACTION_LAYER_MOMENTARY(8), // to second Fn overlay
+ [3] = ACTION_LAYER_TOGGLE(2), // toggle more modifiers
+ [4] = ACTION_LAYER_TOGGLE(4), // toggle wasd
+ [5] = ACTION_MODS_TAP_KEY(MOD_RSFT, KC_ENT),
+ [6] = ACTION_FUNCTION_TAP(SPACE_FN),
+
+ [11] = ACTION_MODS_KEY(MOD_LSFT, KC_1),
+ [12] = ACTION_MODS_KEY(MOD_LSFT, KC_2),
+ [13] = ACTION_MODS_KEY(MOD_LSFT, KC_3),
+ [14] = ACTION_MODS_KEY(MOD_LSFT, KC_4),
+ [15] = ACTION_MODS_KEY(MOD_LSFT, KC_5),
+ [16] = ACTION_MODS_KEY(MOD_LSFT, KC_6),
+ [17] = ACTION_MODS_KEY(MOD_LSFT, KC_7),
+ [18] = ACTION_MODS_KEY(MOD_LSFT, KC_8),
+ [19] = ACTION_MODS_KEY(MOD_LSFT, KC_9),
+ [20] = ACTION_MODS_KEY(MOD_LSFT, KC_0),
+ [21] = ACTION_MODS_KEY(MOD_LSFT, KC_MINS),
+ [22] = ACTION_MODS_KEY(MOD_LSFT, KC_EQL),
+ [23] = ACTION_MODS_KEY(MOD_LSFT, KC_GRV),
+ [24] = ACTION_MODS_KEY(MOD_LSFT, KC_LBRC),
+ [25] = ACTION_MODS_KEY(MOD_LSFT, KC_RBRC),
+ [26] = ACTION_MODS_KEY(MOD_LSFT, KC_BSLS),
+}; \ No newline at end of file
diff --git a/keyboards/planck/old_keymap_files/common_keymaps/keymap_simon.c b/keyboards/planck/old_keymap_files/common_keymaps/keymap_simon.c
new file mode 100644
index 000000000..8058c2e10
--- /dev/null
+++ b/keyboards/planck/old_keymap_files/common_keymaps/keymap_simon.c
@@ -0,0 +1,44 @@
+#include "keymap.h"
+
+const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[0] = KEYMAP( /* Jack */
+ ESC, Q, W, E, R, T, Y, U, I, O, P, BSPC,
+ TAB, A, S, D, F, G, H, J, K, L, DOT, ENT,
+ LSFT, Z, X, C, V, B, N, M, COMM, DOT, SCLN, DEL,
+ LCTL, ENT, LALT, CAPS, FN2, SPC, FN1, LEFT, DOWN, UP, RGHT),
+[1] = KEYMAP( /* Jack RAISE */
+ TRNS, F1, F2, F3, F4, NO, FN11, FN9, FN12, NO, FN14, TRNS,
+ TRNS, F5, F6, F7, F8, FN16, SLSH, MINS, EQL, LBRC, FN8, TRNS,
+ TRNS, F9, F10, F11, F12, F15, F16, FN22, SCLN, MINS, QUOT, TRNS,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS),
+[2] = KEYMAP( /* Jack LOWER */
+ FN22, 1, 2, 3, FN13, FN14, FN15, FN16, FN17, FN18, FN19, BSPC,
+ TRNS, 4, 5, 6, TRNS, TRNS, TRNS, FN20, FN21, FN23, FN24, FN28,
+ TRNS, 7, 8, 9, 0, FN28, FN15, F7, F8, F9, F10, TRNS,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS),
+};
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_MOMENTARY(1), // to Fn overlay
+ [2] = ACTION_LAYER_MOMENTARY(2), // to Fn overlay
+
+ [8] = ACTION_MODS_KEY(MOD_LSFT, KC_SLSH),
+ [9] = ACTION_MODS_KEY(MOD_LSFT, KC_QUOT),
+ [10] = ACTION_MODS_KEY(MOD_LSFT, KC_1),
+ [11] = ACTION_MODS_KEY(MOD_LSFT, KC_2),
+ [12] = ACTION_MODS_KEY(MOD_LSFT, KC_3),
+ [13] = ACTION_MODS_KEY(MOD_LSFT, KC_4),
+ [14] = ACTION_MODS_KEY(MOD_LSFT, KC_5),
+ [15] = ACTION_MODS_KEY(MOD_LSFT, KC_6),
+ [16] = ACTION_MODS_KEY(MOD_LSFT, KC_7),
+ [17] = ACTION_MODS_KEY(MOD_LSFT, KC_8),
+ [18] = ACTION_MODS_KEY(MOD_LSFT, KC_9),
+ [19] = ACTION_MODS_KEY(MOD_LSFT, KC_0),
+ [20] = ACTION_MODS_KEY(MOD_LSFT, KC_MINS),
+ [21] = ACTION_MODS_KEY(MOD_LSFT, KC_EQL),
+ [22] = ACTION_MODS_KEY(MOD_LSFT, KC_GRV),
+ [23] = ACTION_MODS_KEY(MOD_LSFT, KC_LBRC),
+ [24] = ACTION_MODS_KEY(MOD_LSFT, KC_RBRC),
+ [28] = ACTION_MODS_KEY(MOD_LSFT, KC_BSLS),
+
+ [29] = ACTION_MODS_KEY(MOD_LSFT | MOD_RSFT, KC_PAUSE),
+};
diff --git a/keyboards/planck/old_keymap_files/common_keymaps/keymap_tim.c b/keyboards/planck/old_keymap_files/common_keymaps/keymap_tim.c
new file mode 100644
index 000000000..64d0b7403
--- /dev/null
+++ b/keyboards/planck/old_keymap_files/common_keymaps/keymap_tim.c
@@ -0,0 +1,44 @@
+#include "keymap.h"
+
+const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[0] = KEYMAP(
+ ESC, Q, W, E, R, T, Y, U, I, O, P, BSPC,
+ TAB, A, S, D, F, G, H, J, K, L, SCLN, ENT,
+ LSFT, Z, X, C, V, B, N, M, COMM, DOT, SLSH, RSFT,
+ LCTL, LALT, DEL, LGUI, FN2, SPC, FN1, F2, F5, F9, F12),
+[2] = KEYMAP( /* RAISE */
+ TRNS, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, BSPC,
+ GRV, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, MINS, EQL, LBRC, RBRC, BSLS,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, QUOT, FN29, TRNS, TRNS,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, FN1, TRNS, TRNS, TRNS, TRNS),
+[3] = KEYMAP( /* LOWER */
+ TRNS, FN10, FN11, FN12, FN13, FN14, FN15, FN16, FN17, FN18, FN19, BSPC,
+ FN22, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, FN20, FN21, FN23, FN24, FN28,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, QUOT, FN29, TRNS, TRNS,
+ TRNS, TRNS, TRNS, TRNS, FN2, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS),
+};
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_MOMENTARY(2), // to Fn overlay
+ [2] = ACTION_LAYER_MOMENTARY(3), // to Fn overlay
+
+ [3] = ACTION_DEFAULT_LAYER_SET(0),
+ [4] = ACTION_DEFAULT_LAYER_SET(1),
+
+ [10] = ACTION_MODS_KEY(MOD_LSFT, KC_1),
+ [11] = ACTION_MODS_KEY(MOD_LSFT, KC_2),
+ [12] = ACTION_MODS_KEY(MOD_LSFT, KC_3),
+ [13] = ACTION_MODS_KEY(MOD_LSFT, KC_4),
+ [14] = ACTION_MODS_KEY(MOD_LSFT, KC_5),
+ [15] = ACTION_MODS_KEY(MOD_LSFT, KC_6),
+ [16] = ACTION_MODS_KEY(MOD_LSFT, KC_7),
+ [17] = ACTION_MODS_KEY(MOD_LSFT, KC_8),
+ [18] = ACTION_MODS_KEY(MOD_LSFT, KC_9),
+ [19] = ACTION_MODS_KEY(MOD_LSFT, KC_0),
+ [20] = ACTION_MODS_KEY(MOD_LSFT, KC_MINS),
+ [21] = ACTION_MODS_KEY(MOD_LSFT, KC_EQL),
+ [22] = ACTION_MODS_KEY(MOD_LSFT, KC_GRV),
+ [23] = ACTION_MODS_KEY(MOD_LSFT, KC_LBRC),
+ [24] = ACTION_MODS_KEY(MOD_LSFT, KC_RBRC),
+ [28] = ACTION_MODS_KEY(MOD_LSFT, KC_BSLS),
+ [29] = ACTION_MODS_KEY(MOD_LSFT, KC_QUOT),
+};
diff --git a/keyboards/planck/old_keymap_files/common_keymaps/keymap_wilba.c b/keyboards/planck/old_keymap_files/common_keymaps/keymap_wilba.c
new file mode 100644
index 000000000..22326ebe4
--- /dev/null
+++ b/keyboards/planck/old_keymap_files/common_keymaps/keymap_wilba.c
@@ -0,0 +1,56 @@
+#include "keymap.h"
+
+const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[0] = KEYMAP( /* Wilba */
+ FN27, FN28, FN29, E, R, T, Y, U, I, O, P, BSPC,
+ TAB, A, S, D, F, G, H, J, K, L, SCLN, QUOT,
+ LSFT, Z, X, C, V, B, N, M, COMM, DOT, SLSH, ENT,
+ LCTL, LGUI, LALT, RSFT, FN1, SPC, FN2, LEFT, DOWN, UP, RGHT),
+[1] = KEYMAP( /* Wilba Alternate */
+ ESC, Q, W, E, R, T, Y, U, I, O, P, BSPC,
+ TAB, A, S, D, F, G, H, J, K, L, SCLN, QUOT,
+ LSFT, Z, X, C, V, B, N, M, COMM, DOT, SLSH, ENT,
+ LCTL, LGUI, LALT, RSFT, FN1, SPC, FN2, LEFT, DOWN, UP, RGHT),
+[2] = KEYMAP( /* Wilba LOWER */
+ TRNS, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, TRNS,
+ TRNS, F11, F12, LBRC, RBRC, FN20, EQL, FN23, FN24, MINS, FN21, TRNS,
+ TRNS, BSLS, GRV, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,
+ TRNS, TRNS, TRNS, TRNS, FN1, TRNS, TRNS, MNXT, VOLD, VOLU, MPLY),
+[3] = KEYMAP( /* Wilba RAISE */
+ TRNS, FN10, FN11, FN12, FN13, FN14, FN15, FN16, FN17, FN18, FN19, TRNS,
+ TRNS, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, TRNS,
+ TRNS, FN25, FN22, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,
+ TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, FN2, TRNS, TRNS, TRNS, TRNS),
+};
+const uint16_t PROGMEM fn_actions[] = {
+ [1] = ACTION_LAYER_MOMENTARY(2), // LOWER
+ [2] = ACTION_LAYER_MOMENTARY(3), // RAISE
+
+ [3] = ACTION_DEFAULT_LAYER_SET(0),
+ [4] = ACTION_DEFAULT_LAYER_SET(1),
+
+ [10] = ACTION_MODS_KEY(MOD_LSFT, KC_1), // !
+ [11] = ACTION_MODS_KEY(MOD_LSFT, KC_2), // @
+ [12] = ACTION_MODS_KEY(MOD_LSFT, KC_3), // #
+ [13] = ACTION_MODS_KEY(MOD_LSFT, KC_4), // $
+ [14] = ACTION_MODS_KEY(MOD_LSFT, KC_5), // %
+ [15] = ACTION_MODS_KEY(MOD_LSFT, KC_6), // ^
+ [16] = ACTION_MODS_KEY(MOD_LSFT, KC_7), // &
+ [17] = ACTION_MODS_KEY(MOD_LSFT, KC_8), // *
+ [18] = ACTION_MODS_KEY(MOD_LSFT, KC_9), // (
+ [19] = ACTION_MODS_KEY(MOD_LSFT, KC_0), // )
+
+ [20] = ACTION_MODS_KEY(MOD_LSFT, KC_MINS), // _
+ [21] = ACTION_MODS_KEY(MOD_LSFT, KC_EQL), // +
+ [22] = ACTION_MODS_KEY(MOD_LSFT, KC_GRV), // ~
+ [23] = ACTION_MODS_KEY(MOD_LSFT, KC_LBRC), // {
+ [24] = ACTION_MODS_KEY(MOD_LSFT, KC_RBRC), // }
+ [25] = ACTION_MODS_KEY(MOD_LSFT, KC_BSLS), // |
+
+ [26] = ACTION_MODS_KEY(MOD_LSFT | MOD_RSFT, KC_PAUSE),
+
+ [27] = ACTION_BACKLIGHT_TOGGLE(),
+ [28] = ACTION_BACKLIGHT_INCREASE(),
+ [29] = ACTION_BACKLIGHT_DECREASE()
+
+};
diff --git a/keyboards/planck/old_keymap_files/keymap_common.c b/keyboards/planck/old_keymap_files/keymap_common.c
new file mode 100644
index 000000000..db4f18a95
--- /dev/null
+++ b/keyboards/planck/old_keymap_files/keymap_common.c
@@ -0,0 +1,30 @@
+/*
+Copyright 2012,2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "keymap.h"
+
+
+/* translates key to keycode */
+uint8_t keymap_key_to_keycode(uint8_t layer, keypos_t key)
+{
+ return pgm_read_byte(&keymaps[(layer)][(key.row)][(key.col)]);
+}
+
+/* translates Fn keycode to action */
+action_t keymap_fn_to_action(uint8_t keycode)
+{
+ return (action_t){ .code = pgm_read_word(&fn_actions[FN_INDEX(keycode)]) };
+}
diff --git a/keyboards/planck/old_keymap_files/keymap_common.h b/keyboards/planck/old_keymap_files/keymap_common.h
new file mode 100644
index 000000000..d46df9287
--- /dev/null
+++ b/keyboards/planck/old_keymap_files/keymap_common.h
@@ -0,0 +1,129 @@
+/*
+Copyright 2012,2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef KEYMAP_COMMON_H
+#define KEYMAP_COMMON_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <avr/pgmspace.h>
+#include "keycode.h"
+#include "action.h"
+#include "action_macro.h"
+#include "report.h"
+#include "host.h"
+// #include "print.h"
+#include "debug.h"
+#include "keymap.h"
+
+
+extern const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS];
+extern const uint16_t fn_actions[];
+
+
+// MIT Layout
+/*
+ * ,-----------------------------------------------------------------------.
+ * | | | | | | | | | | | | |
+ * |-----------------------------------------------------------------------|
+ * | | | | | | | | | | | | |
+ * |-----------------------------------------------------------------------|
+ * | | | | | | | | | | | | |
+ * |-----------------------------------------------------------------------|
+ * | | | | | | | | | | | |
+ * `-----------------------------------------------------------------------'
+ */
+#define KEYMAP( \
+ K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, \
+ K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, \
+ K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, \
+ K30, K31, K32, K33, K34, K35, K37, K38, K39, K3A, K3B \
+) { \
+ { KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07, KC_##K08, KC_##K09, KC_##K0A, KC_##K0B }, \
+ { KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_##K17, KC_##K18, KC_##K19, KC_##K1A, KC_##K1B }, \
+ { KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_##K27, KC_##K28, KC_##K29, KC_##K2A, KC_##K2B }, \
+ { KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K35, KC_##K37, KC_##K38, KC_##K39, KC_##K3A, KC_##K3B } \
+}
+
+// Grid Layout
+/*
+ * ,-----------------------------------------------------------------------.
+ * | | | | | | | | | | | | |
+ * |-----------------------------------------------------------------------|
+ * | | | | | | | | | | | | |
+ * |-----------------------------------------------------------------------|
+ * | | | | | | | | | | | | |
+ * |-----------------------------------------------------------------------|
+ * | | | | | | | | | | | | |
+ * `-----------------------------------------------------------------------'
+ */
+#define KEYMAP_GRID( \
+ K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, \
+ K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, \
+ K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, \
+ K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B \
+) { \
+ { KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07, KC_##K08, KC_##K09, KC_##K0A, KC_##K0B }, \
+ { KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_##K17, KC_##K18, KC_##K19, KC_##K1A, KC_##K1B }, \
+ { KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_##K27, KC_##K28, KC_##K29, KC_##K2A, KC_##K2B }, \
+ { KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36, KC_##K37, KC_##K38, KC_##K39, KC_##K3A, KC_##K3B } \
+}
+
+#define KEYMAP_REVERSE( \
+ K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, \
+ K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, \
+ K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, \
+ K30, K31, K32, K33, K34, K35, K37, K38, K39, K3A, K3B \
+ ) { \
+ { KC_##K0B, KC_##K0A, KC_##K09, KC_##K08, KC_##K07, KC_##K06, KC_##K05, KC_##K04, KC_##K03, KC_##K02, KC_##K01, KC_##K00 }, \
+ { KC_##K1B, KC_##K1A, KC_##K19, KC_##K18, KC_##K17, KC_##K16, KC_##K15, KC_##K14, KC_##K13, KC_##K12, KC_##K11, KC_##K10 }, \
+ { KC_##K2B, KC_##K2A, KC_##K29, KC_##K28, KC_##K27, KC_##K26, KC_##K25, KC_##K24, KC_##K23, KC_##K22, KC_##K21, KC_##K20 }, \
+ { KC_##K3B, KC_##K3A, KC_##K39, KC_##K38, KC_##K37, KC_##K35, KC_##K35, KC_##K34, KC_##K33, KC_##K32, KC_##K31, KC_##K30 }, \
+ }
+
+#define KEYMAP_AND_REVERSE(args...) KEYMAP(args), KEYMAP_REVERSE(args)
+
+#define KEYMAP_SWAP( \
+ K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, \
+ K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, \
+ K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, \
+ K30, K31, K32, K33, K34, K35, K37, K38, K39, K3A, K3B \
+ ) { \
+ { KC_##K06, KC_##K07, KC_##K08, KC_##K09, KC_##K0A, KC_##K0B, KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05 }, \
+ { KC_##K16, KC_##K17, KC_##K18, KC_##K19, KC_##K1A, KC_##K1B, KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15 }, \
+ { KC_##K26, KC_##K27, KC_##K28, KC_##K29, KC_##K2A, KC_##K2B, KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25 }, \
+ { KC_##K37, KC_##K38, KC_##K39, KC_##K3A, KC_##K3B, KC_##K35, KC_##K35, KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34 }, \
+}
+
+#define KEYMAP_AND_SWAP(args...) KEYMAP(args), KEYMAP_SWAP(args)
+
+/*
+ Keymap for the Planck 48 key variant.
+ */
+#define KEYMAP_48( \
+ K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, \
+ K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, \
+ K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, \
+ K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B \
+) { \
+ { KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07, KC_##K08, KC_##K09, KC_##K0A, KC_##K0B }, \
+ { KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_##K17, KC_##K18, KC_##K19, KC_##K1A, KC_##K1B }, \
+ { KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_##K27, KC_##K28, KC_##K29, KC_##K2A, KC_##K2B }, \
+ { KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36, KC_##K37, KC_##K38, KC_##K39, KC_##K3A, KC_##K3B }, \
+}
+
+
+#endif
diff --git a/keyboards/planck/out.txt b/keyboards/planck/out.txt
new file mode 100644
index 000000000..644a6a777
--- /dev/null
+++ b/keyboards/planck/out.txt
@@ -0,0 +1,66 @@
+-------- begin --------
+avr-gcc.exe (AVR_8_bit_GNU_Toolchain_3.5.0_1662) 4.9.2
+Copyright (C) 2014 Free Software Foundation, Inc.
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+Compiling: ../../keyboards/planck/planck.c [OK]
+Compiling: ../../keyboards/planck/keymaps/experimental/keymap.c [WARNINGS]
+ |
+ | ../../keyboards/planck/keymaps/experimental/keymap.c: In function 'action_get_macro':
+ | ../../keyboards/planck/keymaps/experimental/keymap.c:227:17: warning: implicit declaration of function 'breathing_speed_set' [-Wimplicit-function-declaration]
+ | breathing_speed_set(2);
+ | ^
+ | ../../keyboards/planck/keymaps/experimental/keymap.c:228:17: warning: implicit declaration of function 'breathing_pulse' [-Wimplicit-function-declaration]
+ | breathing_pulse();
+ | ^
+ |
+Compiling: ../../quantum/quantum.c [OK]
+Compiling: ../../quantum/keymap.c [OK]
+Compiling: ../../quantum/keycode_config.c [OK]
+Compiling: ../../quantum/matrix.c [OK]
+Compiling: ../../quantum/audio/audio.c [OK]
+Compiling: ../../quantum/audio/voices.c [OK]
+Compiling: ../../quantum/audio/luts.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/lufa.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/descriptor.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/HIDParser.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Device_AVR8.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/EndpointStream_AVR8.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Host_AVR8.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/PipeStream_AVR8.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/USBController_AVR8.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/USBInterrupt_AVR8.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/ConfigDescriptors.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/DeviceStandardReq.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/Events.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/HostStandardReq.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/USBTask.c [OK]
+Compiling: ../../tmk_core/common/host.c [OK]
+Compiling: ../../tmk_core/common/keyboard.c [OK]
+Compiling: ../../tmk_core/common/action.c [OK]
+Compiling: ../../tmk_core/common/action_tapping.c [OK]
+Compiling: ../../tmk_core/common/action_macro.c [OK]
+Compiling: ../../tmk_core/common/action_layer.c [OK]
+Compiling: ../../tmk_core/common/action_util.c [OK]
+Compiling: ../../tmk_core/common/print.c [OK]
+Compiling: ../../tmk_core/common/debug.c [OK]
+Compiling: ../../tmk_core/common/util.c [OK]
+Compiling: ../../tmk_core/common/avr/suspend.c [OK]
+Assembling: ../../tmk_core/common/avr/xprintf.S [OK]
+Compiling: ../../tmk_core/common/avr/timer.c [OK]
+Compiling: ../../tmk_core/common/avr/bootloader.c [OK]
+Compiling: ../../tmk_core/common/magic.c [OK]
+Compiling: ../../tmk_core/common/avr/eeconfig.c [OK]
+Compiling: ../../tmk_core/common/mousekey.c [OK]
+Compiling: ../../tmk_core/common/command.c [OK]
+Compiling: ../../tmk_core/common/backlight.c [OK]
+Linking: .build/planck_experimental.elf [ERRORS]
+ |
+ | .build/obj_planck_experimental/keyboards/planck/keymaps/experimental/keymap.o: In function `action_get_macro':
+ | C:\Users\Fred Wales\Documents\Programming\qmk_firmware\keyboards\planck/../../keyboards/planck/keymaps/experimental/keymap.c:240: undefined reference to `breathing_speed_set'
+ | C:\Users\Fred Wales\Documents\Programming\qmk_firmware\keyboards\planck/../../keyboards/planck/keymaps/experimental/keymap.c:241: undefined reference to `breathing_pulse'
+ | collect2.exe: error: ld returned 1 exit status
+ |
diff --git a/keyboards/planck/planck.c b/keyboards/planck/planck.c
new file mode 100644
index 000000000..8d70bb4e5
--- /dev/null
+++ b/keyboards/planck/planck.c
@@ -0,0 +1,9 @@
+#include "planck.h"
+
+void matrix_init_kb(void) {
+ // Turn status LED on
+ DDRE |= (1<<6);
+ PORTE |= (1<<6);
+
+ matrix_init_user();
+} \ No newline at end of file
diff --git a/keyboards/planck/planck.h b/keyboards/planck/planck.h
new file mode 100644
index 000000000..8cfee5d1c
--- /dev/null
+++ b/keyboards/planck/planck.h
@@ -0,0 +1,39 @@
+#ifndef PLANCK_H
+#define PLANCK_H
+
+#ifdef SUBPROJECT_rev3
+ #include "rev3.h"
+#endif
+#ifdef SUBPROJECT_rev4
+ #include "rev4.h"
+#endif
+
+#include "quantum.h"
+
+#define PLANCK_MIT( \
+ k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, \
+ k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, \
+ k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b, \
+ k30, k31, k32, k33, k34, k35, k37, k38, k39, k3a, k3b \
+) \
+{ \
+ { k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b }, \
+ { k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b }, \
+ { k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b }, \
+ { k30, k31, k32, k33, k34, k35, k35, k37, k38, k39, k3a, k3b } \
+}
+
+#define PLANCK_GRID( \
+ k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, \
+ k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, \
+ k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b, \
+ k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k3a, k3b \
+) \
+{ \
+ { k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b }, \
+ { k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b }, \
+ { k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b }, \
+ { k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k3a, k3b } \
+}
+
+#endif
diff --git a/keyboards/planck/readme.md b/keyboards/planck/readme.md
new file mode 100644
index 000000000..f89fdeb93
--- /dev/null
+++ b/keyboards/planck/readme.md
@@ -0,0 +1,31 @@
+Planck keyboard firmware
+======================
+DIY/Assembled compact ortholinear 40% keyboard by [Ortholinear Keyboards](http://ortholinearkeyboards.com).
+
+## Quantum MK Firmware
+
+For the full Quantum feature list, see [the parent readme.md](/readme.md).
+
+## Building
+
+Download or clone the whole firmware and navigate to the keyboards/planck folder. Once your dev env is setup, you'll be able to type `make` to generate your .hex - you can then use `make dfu` to program your PCB once you hit the reset button.
+
+Depending on which keymap you would like to use, you will have to compile slightly differently.
+
+### Default
+To build with the default keymap, simply run `make`.
+
+### Other Keymaps
+Several version of keymap are available in advance but you are recommended to define your favorite layout yourself. To define your own keymap create file named `<name>.c` in the keymaps folder, and see keymap document (you can find in top readme.md) and existent keymap files.
+
+To build the firmware binary hex file with a keymap just do `make` with `KEYMAP` option like:
+```
+$ make KEYMAP=[default|jack|<name>]
+```
+Keymaps follow the format **__\<name\>.c__** and are stored in the `keymaps` folder.
+
+### Notable forks (which some of the keymap files are from)
+- [Shane's Fork](https://github.com/shanecelis/tmk_keyboard/tree/master/keyboard/planck)
+- [Pierre's Fork](https://github.com/pcarrier/tmk_keyboard/blob/pcarrier/planck/keyboard/gh60/keymap_planck.c)
+- [Nathan's Fork](https://github.com/nathanrosspowell/tmk_keyboard/tree/planck-jack/keyboard/planck)
+- [Matthew's Fork](https://github.com/pepers/tmk_keyboard/tree/master/keyboard/planck_grid)
diff --git a/keyboards/planck/rev3/Makefile b/keyboards/planck/rev3/Makefile
new file mode 100644
index 000000000..3ed1445e4
--- /dev/null
+++ b/keyboards/planck/rev3/Makefile
@@ -0,0 +1,5 @@
+AUDIO_ENABLE ?= no # Audio output on port C6
+
+ifndef QUANTUM_DIR
+ include ../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/planck/rev3/config.h b/keyboards/planck/rev3/config.h
new file mode 100644
index 000000000..cc37874e8
--- /dev/null
+++ b/keyboards/planck/rev3/config.h
@@ -0,0 +1,8 @@
+#ifndef REV3_CONFIG_H
+#define REV3_CONFIG_H
+
+#include "../config.h"
+
+#define DEVICE_VER 0x0003
+
+#endif
diff --git a/keyboards/planck/rev3/rev3.c b/keyboards/planck/rev3/rev3.c
new file mode 100644
index 000000000..9ccd1d880
--- /dev/null
+++ b/keyboards/planck/rev3/rev3.c
@@ -0,0 +1 @@
+#include "rev3.h" \ No newline at end of file
diff --git a/keyboards/planck/rev3/rev3.h b/keyboards/planck/rev3/rev3.h
new file mode 100644
index 000000000..628951d97
--- /dev/null
+++ b/keyboards/planck/rev3/rev3.h
@@ -0,0 +1,6 @@
+#ifndef REV3_H
+#define REV3_H
+
+#include "../planck.h"
+
+#endif \ No newline at end of file
diff --git a/keyboards/planck/rev4/Makefile b/keyboards/planck/rev4/Makefile
new file mode 100644
index 000000000..ed09f85a4
--- /dev/null
+++ b/keyboards/planck/rev4/Makefile
@@ -0,0 +1,5 @@
+AUDIO_ENABLE ?= yes # Audio output on port C6
+
+ifndef QUANTUM_DIR
+ include ../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/planck/rev4/config.h b/keyboards/planck/rev4/config.h
new file mode 100644
index 000000000..98189fba7
--- /dev/null
+++ b/keyboards/planck/rev4/config.h
@@ -0,0 +1,8 @@
+#ifndef REV4_CONFIG_H
+#define REV4_CONFIG_H
+
+#include "../config.h"
+
+#define DEVICE_VER 0x0004
+
+#endif \ No newline at end of file
diff --git a/keyboards/planck/rev4/rev4.c b/keyboards/planck/rev4/rev4.c
new file mode 100644
index 000000000..98a75d2ed
--- /dev/null
+++ b/keyboards/planck/rev4/rev4.c
@@ -0,0 +1 @@
+#include "rev4.h" \ No newline at end of file
diff --git a/keyboards/planck/rev4/rev4.h b/keyboards/planck/rev4/rev4.h
new file mode 100644
index 000000000..e4cf1800b
--- /dev/null
+++ b/keyboards/planck/rev4/rev4.h
@@ -0,0 +1,6 @@
+#ifndef REV4_H
+#define REV4_H
+
+#include "../planck.h"
+
+#endif \ No newline at end of file
diff --git a/keyboards/preonic/Makefile b/keyboards/preonic/Makefile
new file mode 100644
index 000000000..08e9205cb
--- /dev/null
+++ b/keyboards/preonic/Makefile
@@ -0,0 +1,73 @@
+
+
+# MCU name
+#MCU = at90usb1287
+MCU = atmega32u4
+
+# Processor frequency.
+# This will define a symbol, F_CPU, in all source code files equal to the
+# processor frequency in Hz. You can then use this symbol in your source code to
+# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
+# automatically to create a 32-bit value in your source code.
+#
+# This will be an integer division of F_USB below, as it is sourced by
+# F_USB after it has run through any CPU prescalers. Note that this value
+# does not *change* the processor frequency - it should merely be updated to
+# reflect the processor speed set externally so that the code can use accurate
+# software delays.
+F_CPU = 16000000
+
+#
+# LUFA specific
+#
+# Target architecture (see library "Board Types" documentation).
+ARCH = AVR8
+
+# Input clock frequency.
+# This will define a symbol, F_USB, in all source code files equal to the
+# input clock frequency (before any prescaling is performed) in Hz. This value may
+# differ from F_CPU if prescaling is used on the latter, and is required as the
+# raw input clock is fed directly to the PLL sections of the AVR for high speed
+# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
+# at the end, this will be done automatically to create a 32-bit value in your
+# source code.
+#
+# If no clock division is performed on the input clock inside the AVR (via the
+# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
+F_USB = $(F_CPU)
+
+# Interrupt driven control endpoint task(+60)
+OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
+
+
+# Boot Section Size in *bytes*
+# Teensy halfKay 512
+# Teensy++ halfKay 1024
+# Atmel DFU loader 4096
+# LUFA bootloader 4096
+# USBaspLoader 2048
+OPT_DEFS += -DBOOTLOADER_SIZE=4096
+
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE ?= no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE ?= yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450)
+CONSOLE_ENABLE ?= no # Console for debug(+400)
+COMMAND_ENABLE ?= yes # Commands for debug and configuration
+NKRO_ENABLE ?= no # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE ?= yes # Enable keyboard backlight functionality
+MIDI_ENABLE ?= no # MIDI controls
+AUDIO_ENABLE ?= no # Audio output on port C6
+UNICODE_ENABLE ?= no # Unicode
+BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE ?= no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE ?= no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/preonic/config.h b/keyboards/preonic/config.h
new file mode 100644
index 000000000..04946f7fb
--- /dev/null
+++ b/keyboards/preonic/config.h
@@ -0,0 +1,91 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "config_common.h"
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x6061
+#define DEVICE_VER 0x0001
+#define MANUFACTURER Ortholinear Keyboards
+#define PRODUCT The Preonic Keyboard
+#define DESCRIPTION A compact ortholinear keyboard
+
+/* key matrix size */
+#define MATRIX_ROWS 5
+#define MATRIX_COLS 12
+
+/* Planck PCB default pin-out */
+#define MATRIX_ROW_PINS { D2, D5, B5, B6, D3 }
+#define MATRIX_COL_PINS { F1, F0, B0, C7, F4, F5, F6, F7, D4, D6, B4, D7 }
+#define UNUSED_PINS
+
+#define BACKLIGHT_PIN B7
+
+/* COL2ROW or ROW2COL */
+#define DIODE_DIRECTION COL2ROW
+
+/* define if matrix has ghost */
+//#define MATRIX_HAS_GHOST
+
+/* number of backlight levels */
+#define BACKLIGHT_LEVELS 3
+
+/* Set 0 if debouncing isn't needed */
+#define DEBOUNCING_DELAY 5
+
+/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
+#define LOCKING_SUPPORT_ENABLE
+/* Locking resynchronize hack */
+#define LOCKING_RESYNC_ENABLE
+
+/* key combination for command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+/* ws2812 RGB LED */
+#define ws2812_PORTREG PORTD
+#define ws2812_DDRREG DDRD
+#define ws2812_pin PD1
+#define RGBLED_NUM 28 // Number of LEDs
+#define RGBLIGHT_HUE_STEP 10
+#define RGBLIGHT_SAT_STEP 17
+#define RGBLIGHT_VAL_STEP 17
+
+/*
+ * Feature disable options
+ * These options are also useful to firmware size reduction.
+ */
+
+/* disable debug print */
+// #define NO_DEBUG
+
+/* disable print */
+// #define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+
+#endif
diff --git a/keyboards/preonic/keymaps/default/Makefile b/keyboards/preonic/keymaps/default/Makefile
new file mode 100644
index 000000000..581e08cd0
--- /dev/null
+++ b/keyboards/preonic/keymaps/default/Makefile
@@ -0,0 +1,25 @@
+
+
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = yes # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/preonic/keymaps/default/keymap.c b/keyboards/preonic/keymaps/default/keymap.c
new file mode 100644
index 000000000..9a957f7ee
--- /dev/null
+++ b/keyboards/preonic/keymaps/default/keymap.c
@@ -0,0 +1,280 @@
+#include "preonic.h"
+#include "action_layer.h"
+#include "eeconfig.h"
+#ifdef AUDIO_ENABLE
+ #include "audio.h"
+#endif
+
+// Each layer gets a name for readability, which is then used in the keymap matrix below.
+// The underscores don't mean anything - you can have a layer called STUFF or any other name.
+// Layer names don't all need to be of the same length, obviously, and you can also skip them
+// entirely and just use numbers.
+#define _QWERTY 0
+#define _COLEMAK 1
+#define _DVORAK 2
+#define _LOWER 3
+#define _RAISE 4
+#define _ADJUST 16
+
+enum preonic_keycodes {
+ QWERTY = SAFE_RANGE,
+ COLEMAK,
+ DVORAK,
+ LOWER,
+ RAISE,
+ BACKLIT
+};
+
+// Fillers to make layering more clear
+#define _______ KC_TRNS
+#define XXXXXXX KC_NO
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+
+/* Qwerty
+ * ,-----------------------------------------------------------------------------------.
+ * | ` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | Bksp |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Tab | Q | W | E | R | T | Y | U | I | O | P | Del |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc | A | S | D | F | G | H | J | K | L | ; | " |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift| Z | X | C | V | B | N | M | , | . | / |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Brite| Ctrl | Alt | GUI |Lower | Space |Raise | Left | Down | Up |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_QWERTY] = {
+ {KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC},
+ {KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_DEL},
+ {KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT},
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT },
+ {BACKLIT, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+
+/* Colemak
+ * ,-----------------------------------------------------------------------------------.
+ * | ` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | Bksp |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Tab | Q | W | F | P | G | J | L | U | Y | ; | Del |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc | A | R | S | T | D | H | N | E | I | O | " |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift| Z | X | C | V | B | K | M | , | . | / |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Brite| Ctrl | Alt | GUI |Lower | Space |Raise | Left | Down | Up |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_COLEMAK] = {
+ {KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC},
+ {KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_DEL},
+ {KC_ESC, KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT},
+ {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_K, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT },
+ {BACKLIT, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+
+/* Dvorak
+ * ,-----------------------------------------------------------------------------------.
+ * | ` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | Bksp |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Tab | " | , | . | P | Y | F | G | C | R | L | Del |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc | A | O | E | U | I | D | H | T | N | S | / |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift| ; | Q | J | K | X | B | M | W | V | Z |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Brite| Ctrl | Alt | GUI |Lower | Space |Raise | Left | Down | Up |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_DVORAK] = {
+ {KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC},
+ {KC_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, KC_F, KC_G, KC_C, KC_R, KC_L, KC_DEL},
+ {KC_ESC, KC_A, KC_O, KC_E, KC_U, KC_I, KC_D, KC_H, KC_T, KC_N, KC_S, KC_SLSH},
+ {KC_LSFT, KC_SCLN, KC_Q, KC_J, KC_K, KC_X, KC_B, KC_M, KC_W, KC_V, KC_Z, KC_ENT },
+ {BACKLIT, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT}
+},
+
+/* Lower
+ * ,-----------------------------------------------------------------------------------.
+ * | ~ | ! | @ | # | $ | % | ^ | & | * | ( | ) | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | ~ | ! | @ | # | $ | % | ^ | & | * | ( | ) | Del |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Del | F1 | F2 | F3 | F4 | F5 | F6 | _ | + | { | } | | |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | | F7 | F8 | F9 | F10 | F11 | F12 |ISO ~ |ISO | | | |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | | | | | | | | Next | Vol- | Vol+ | Play |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_LOWER] = {
+ {KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_BSPC},
+ {KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_DEL},
+ {KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE},
+ {_______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12,S(KC_NUHS),S(KC_NUBS),_______, _______, _______},
+ {_______, _______, _______, _______, _______, _______, _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
+},
+
+/* Raise
+ * ,-----------------------------------------------------------------------------------.
+ * | ` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | Bksp |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | ` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | Del |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Del | F1 | F2 | F3 | F4 | F5 | F6 | - | = | [ | ] | \ |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | | F7 | F8 | F9 | F10 | F11 | F12 |ISO # |ISO / | | |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | | | | | | | | Next | Vol- | Vol+ | Play |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_RAISE] = {
+ {KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC},
+ {KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_DEL},
+ {KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS},
+ {_______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_NUHS, KC_NUBS, _______, _______, _______},
+ {_______, _______, _______, _______, _______, _______, _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY}
+},
+
+/* Adjust (Lower + Raise)
+ * ,-----------------------------------------------------------------------------------.
+ * | F1 | F2 | F3 | F4 | F5 | F6 | F7 | F8 | F9 | F10 | F11 | F12 |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | | Reset| | | | | | | | | | Del |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | | | |Audoff|Aud on|AGnorm|AGswap|Qwerty|Colemk|Dvorak| | |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | |Voice-|Voice+|Musoff|Mus on| | | | | | | |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | | | | | | | | | | | |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_ADJUST] = {
+ {KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12},
+ {_______, RESET, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_DEL},
+ {_______, _______, _______, AU_ON, AU_OFF, AG_NORM, AG_SWAP, QWERTY, COLEMAK, DVORAK, _______, _______},
+ {_______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, _______, _______, _______, _______, _______},
+ {_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______}
+}
+
+
+};
+
+#ifdef AUDIO_ENABLE
+float tone_startup[][2] = {
+ {NOTE_B5, 20},
+ {NOTE_B6, 8},
+ {NOTE_DS6, 20},
+ {NOTE_B6, 8}
+};
+
+float tone_qwerty[][2] = SONG(QWERTY_SOUND);
+float tone_dvorak[][2] = SONG(DVORAK_SOUND);
+float tone_colemak[][2] = SONG(COLEMAK_SOUND);
+
+float tone_goodbye[][2] = SONG(GOODBYE_SOUND);
+
+float music_scale[][2] = SONG(MUSIC_SCALE_SOUND);
+#endif
+
+void persistant_default_layer_set(uint16_t default_layer) {
+ eeconfig_update_default_layer(default_layer);
+ default_layer_set(default_layer);
+}
+
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ case QWERTY:
+ if (record->event.pressed) {
+ #ifdef AUDIO_ENABLE
+ PLAY_NOTE_ARRAY(tone_qwerty, false, 0);
+ #endif
+ persistant_default_layer_set(1UL<<_QWERTY);
+ }
+ return false;
+ break;
+ case COLEMAK:
+ if (record->event.pressed) {
+ #ifdef AUDIO_ENABLE
+ PLAY_NOTE_ARRAY(tone_colemak, false, 0);
+ #endif
+ persistant_default_layer_set(1UL<<_COLEMAK);
+ }
+ return false;
+ break;
+ case DVORAK:
+ if (record->event.pressed) {
+ #ifdef AUDIO_ENABLE
+ PLAY_NOTE_ARRAY(tone_dvorak, false, 0);
+ #endif
+ persistant_default_layer_set(1UL<<_DVORAK);
+ }
+ return false;
+ break;
+ case LOWER:
+ if (record->event.pressed) {
+ layer_on(_LOWER);
+ update_tri_layer(_LOWER, _RAISE, _ADJUST);
+ } else {
+ layer_off(_LOWER);
+ update_tri_layer(_LOWER, _RAISE, _ADJUST);
+ }
+ return false;
+ break;
+ case RAISE:
+ if (record->event.pressed) {
+ layer_on(_RAISE);
+ update_tri_layer(_LOWER, _RAISE, _ADJUST);
+ } else {
+ layer_off(_RAISE);
+ update_tri_layer(_LOWER, _RAISE, _ADJUST);
+ }
+ return false;
+ break;
+ case BACKLIT:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ #ifdef BACKLIGHT_ENABLE
+ backlight_step();
+ #endif
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ return false;
+ break;
+ }
+ return true;
+};
+
+void matrix_init_user(void) {
+ #ifdef AUDIO_ENABLE
+ startup_user();
+ #endif
+}
+
+#ifdef AUDIO_ENABLE
+
+void startup_user()
+{
+ _delay_ms(20); // gets rid of tick
+ PLAY_NOTE_ARRAY(tone_startup, false, 0);
+}
+
+void shutdown_user()
+{
+ PLAY_NOTE_ARRAY(tone_goodbye, false, 0);
+ _delay_ms(150);
+ stop_all_notes();
+}
+
+void music_on_user(void)
+{
+ music_scale_user();
+}
+
+void music_scale_user(void)
+{
+ PLAY_NOTE_ARRAY(music_scale, false, 0);
+}
+
+#endif \ No newline at end of file
diff --git a/keyboards/preonic/keymaps/default/readme.md b/keyboards/preonic/keymaps/default/readme.md
new file mode 100644
index 000000000..e911968dd
--- /dev/null
+++ b/keyboards/preonic/keymaps/default/readme.md
@@ -0,0 +1 @@
+# The default Preonic layout - largely based on the Planck's \ No newline at end of file
diff --git a/keyboards/preonic/preonic.c b/keyboards/preonic/preonic.c
new file mode 100644
index 000000000..889c3fc8f
--- /dev/null
+++ b/keyboards/preonic/preonic.c
@@ -0,0 +1,10 @@
+#include "preonic.h"
+
+void matrix_init_kb(void) {
+
+ // Turn status LED on
+ DDRE |= (1<<6);
+ PORTE |= (1<<6);
+
+ matrix_init_user();
+}; \ No newline at end of file
diff --git a/keyboards/preonic/preonic.h b/keyboards/preonic/preonic.h
new file mode 100644
index 000000000..0e0b101e4
--- /dev/null
+++ b/keyboards/preonic/preonic.h
@@ -0,0 +1,36 @@
+#ifndef PREONIC_H
+#define PREONIC_H
+
+#include "quantum.h"
+
+#define PREONIC_MIT( \
+ k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, \
+ k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, \
+ k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b, \
+ k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k3a, k3b, \
+ k40, k41, k42, k43, k44, k45, k47, k48, k49, k4a, k4b \
+) \
+{ \
+ { k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b }, \
+ { k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b }, \
+ { k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b }, \
+ { k30, k31, k32, k33, k34, k35, k35, k37, k38, k39, k3a, k3b }, \
+ { k40, k41, k42, k43, k44, k45, k45, k47, k48, k49, k4a, k4b } \
+}
+
+#define PREONIC_GRID( \
+ k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, \
+ k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, \
+ k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b, \
+ k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k3a, k3b, \
+ k40, k41, k42, k43, k44, k45, k46, k47, k48, k49, k4a, k4b \
+) \
+{ \
+ { k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b }, \
+ { k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b }, \
+ { k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b }, \
+ { k30, k31, k32, k33, k34, k35, k35, k37, k38, k39, k3a, k3b }, \
+ { k40, k41, k42, k43, k44, k45, k46, k47, k48, k49, k4a, k4b } \
+}
+
+#endif
diff --git a/keyboards/preonic/readme.md b/keyboards/preonic/readme.md
new file mode 100644
index 000000000..f0be255a0
--- /dev/null
+++ b/keyboards/preonic/readme.md
@@ -0,0 +1,25 @@
+Preonic keyboard firmware
+======================
+DIY/Assembled compact ortholinear 50% keyboard by [Ortholinear Keyboards](http://ortholinearkeyboards.com).
+
+## Quantum MK Firmware
+
+For the full Quantum feature list, see [the parent readme.md](/readme.md).
+
+## Building
+
+Download or clone the whole firmware and navigate to the keyboards/preonic folder. Once your dev env is setup, you'll be able to type `make` to generate your .hex - you can then use `make dfu` to program your PCB once you hit the reset button.
+
+Depending on which keymap you would like to use, you will have to compile slightly differently.
+
+### Default
+To build with the default keymap, simply run `make`.
+
+### Other Keymaps
+Several version of keymap are available in advance but you are recommended to define your favorite layout yourself. To define your own keymap, create a file in the keymaps folder named `<name>.c` and see keymap document (you can find in top readme.md) and existent keymap files.
+
+To build the firmware binary hex file with a keymap just do `make` with `KEYMAP` option like:
+```
+$ make KEYMAP=[default|jack|<name>]
+```
+Keymaps follow the format **__\<name\>.c__** and are stored in the `keymaps` folder.
diff --git a/keyboards/readme.md b/keyboards/readme.md
new file mode 100644
index 000000000..e97986546
--- /dev/null
+++ b/keyboards/readme.md
@@ -0,0 +1,45 @@
+# Included Keyboards
+QMK runs on a diverse range of keyboards. Some of these keyboards are officially supported and see constant community contributions, while others are part of the repository for historical reasons.
+
+## Official QMK Keyboards
+
+These keyboards are manufactured by the maintainers of QMK.
+
+### Ortholinear Keyboards - Jack Humbert
+
+What makes OLKB keyboards shine is a combo of lean aesthetics, compact size, and killer tactile feel. These are available through [olkb.com](http://olkb.com) as well as through [Massdrop](http://massdrop.com) from time to time, as easy to assemble kits.
+
+* [Planck](/keyboards/planck/) - A 40% DIY powerhouse of customizability and modification capability. It's a lean, mean, typing machine.
+* [Preonic](/keyboards/preonic/) - Like the Planck, but bigger. 50%.
+* [Atomic](/keyboards/atomic/) - Imagine the size of the Planck. Now imagine the size of the Preonic. Now imagine _bigger_. That is the Atomic. A 60% keyboard.
+
+### ErgoDox EZ - Erez Zukerman
+
+Made in Taiwan using advanced robotic manufacturing, the ErgoDox EZ is a fully-assembled, premium ergonomic keyboard. Its split design allows you to place both halves shoulder width, and its custom-made wrist rests and tilt/tent kit make for incredibly comfortable typing. Available on [ergodox-ez.com](https://ergodox-ez.com).
+
+* [ErgoDox EZ](/keyboards/ergodox_ez/) - Our one and only product. Yes, it's that awesome. Comes with either printed or blank keycaps, and 7 different keyswitch types.
+
+### Clueboard - Zach White
+
+Designed and built in Felton, CA, Clueboards keyboard emphasize quality and locally sourced components, available on [clueboard.co](http://clueboard.co)
+
+* [Clueboard](/keyboards/clueboard/) - The 66% custom keyboard.
+* [Cluepad](/keyboards/cluepad/) - A mechanical numpad with QMK superpowers.
+
+
+## Community-supported QMK Keyboards
+
+These keyboards are part of the QMK repository, but their manufacturers are not official maintainers of the repository.
+
+* [alps64](/keyboards/alps64/) &mdash; A 60% keyboard for Alps keyswitches.
+* [arrow_pad](/keyboards/arrow_pad) &mdash; A custom creation by IBNobody.
+* [atreus](/keyboards/atreus) &mdash; Made by Technomancy.
+* [bantam44](/keyboards/bantam44) &mdash; It is a 44-key 40% staggered keyboard.
+* [gh60](/keyboards/gh60) &mdash; A 60% Geekhack community-driven project.
+* [hhkb](/keyboards/hhkb) &mdash; The Happy Hacking keyboard can be hacked with a custom controller to run QMK.
+* [jd45](/keyboards/jd45) &mdash; Another Geekhack community project, designed by jdcarpe.
+* [kc60](/keyboards/kc60) &mdash; A programmable Chinese-made keyboard, lost in the mists of time.
+* [phantom](/keyboards/phantom) &mdash; A tenkeyless kit by Teel, also from Geekhack.
+* [retro_refit](/keyboards/retro_refit) &mdash; Another creation by IBNobody.
+* [satan](/keyboards/satan) &mdash; A GH60 variant.
+* [sixkeyboard](/keyboards/sixkeyboard) &mdash; A 6-key keyboard made by TechKeys.
diff --git a/keyboards/retro_refit/Makefile b/keyboards/retro_refit/Makefile
new file mode 100644
index 000000000..2dd8cc5f7
--- /dev/null
+++ b/keyboards/retro_refit/Makefile
@@ -0,0 +1,74 @@
+
+
+# MCU name
+#MCU = at90usb1287
+MCU = atmega32u4
+
+# Processor frequency.
+# This will define a symbol, F_CPU, in all source code files equal to the
+# processor frequency in Hz. You can then use this symbol in your source code to
+# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
+# automatically to create a 32-bit value in your source code.
+#
+# This will be an integer division of F_USB below, as it is sourced by
+# F_USB after it has run through any CPU prescalers. Note that this value
+# does not *change* the processor frequency - it should merely be updated to
+# reflect the processor speed set externally so that the code can use accurate
+# software delays.
+F_CPU = 16000000
+
+
+#
+# LUFA specific
+#
+# Target architecture (see library "Board Types" documentation).
+ARCH = AVR8
+
+# Input clock frequency.
+# This will define a symbol, F_USB, in all source code files equal to the
+# input clock frequency (before any prescaling is performed) in Hz. This value may
+# differ from F_CPU if prescaling is used on the latter, and is required as the
+# raw input clock is fed directly to the PLL sections of the AVR for high speed
+# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
+# at the end, this will be done automatically to create a 32-bit value in your
+# source code.
+#
+# If no clock division is performed on the input clock inside the AVR (via the
+# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
+F_USB = $(F_CPU)
+
+# Interrupt driven control endpoint task(+60)
+OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
+
+
+# Boot Section Size in *bytes*
+# Teensy halfKay 512
+# Teensy++ halfKay 1024
+# Atmel DFU loader 4096
+# LUFA bootloader 4096
+# USBaspLoader 2048
+OPT_DEFS += -DBOOTLOADER_SIZE=512
+
+
+# Build Options
+# comment out to disable the options.
+#
+BOOTMAGIC_ENABLE ?= yes # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE ?= yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450)
+CONSOLE_ENABLE ?= yes # Console for debug(+400)
+COMMAND_ENABLE ?= yes # Commands for debug and configuration
+KEYBOARD_LOCK_ENABLE ?= yes # Allow locking of keyboard via magic key
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+# SLEEP_LED_ENABLE ?= yes # Breathing sleep LED during USB suspend
+NKRO_ENABLE ?= yes # USB Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+# BACKLIGHT_ENABLE ?= yes # Enable keyboard backlight functionality
+# MIDI_ENABLE ?= YES # MIDI controls
+# UNICODE_ENABLE ?= YES # Unicode
+# BLUETOOTH_ENABLE ?= yes # Enable Bluetooth with the Adafruit EZ-Key HID
+
+
+ifndef QUANTUM_DIR
+ include ../../Makefile
+endif
+
diff --git a/keyboards/retro_refit/config.h b/keyboards/retro_refit/config.h
new file mode 100644
index 000000000..f2194e550
--- /dev/null
+++ b/keyboards/retro_refit/config.h
@@ -0,0 +1,123 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "config_common.h"
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x6060
+#define DEVICE_VER 0x0001
+#define MANUFACTURER Nobody
+#define PRODUCT retro_refit
+#define DESCRIPTION Retro Refit
+
+/* key matrix size */
+#define MATRIX_ROWS 11
+#define MATRIX_COLS 8
+
+// See note in retro_refit.h for an explanation of how this matrix is wired up
+#define MATRIX_ROW_PINS { D4, D7, B4, B5, B6, F7, F6, F5, F4, F1, F0 }
+#define MATRIX_COL_PINS { B0, B1, B2, B3, D2, D3, C7, D5 }
+#define UNUSED_PINS
+
+/* COL2ROW or ROW2COL */
+#define DIODE_DIRECTION COL2ROW
+
+/* define if matrix has ghost */
+//#define MATRIX_HAS_GHOST
+
+/* number of backlight levels */
+#define BACKLIGHT_LEVELS 0
+
+/* Set 0 if debouncing isn't needed */
+#define DEBOUNCING_DELAY 5
+
+/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
+#define LOCKING_SUPPORT_ENABLE
+/* Locking resynchronize hack */
+#define LOCKING_RESYNC_ENABLE
+
+
+/* Force NKRO Mode - If forced on, must be disabled via magic key (default = LShift+RShift+N) */
+#define FORCE_NKRO
+
+/*
+ * Magic key options
+ * These options allow the magic key functionality to be changed. This is useful
+ * if your keyboard/keypad is missing keys and you want magic key support.
+ */
+
+/* key combination for magic key command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+/* control how magic key switches layers */
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS true
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS true
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM false
+
+/* remap magic keys */
+//#define MAGIC_KEY_HELP1 H
+//#define MAGIC_KEY_HELP2 SLASH
+//#define MAGIC_KEY_DEBUG D
+//#define MAGIC_KEY_DEBUG_MATRIX X
+//#define MAGIC_KEY_DEBUG_KBD K
+//#define MAGIC_KEY_DEBUG_MOUSE M
+//#define MAGIC_KEY_VERSION V
+//#define MAGIC_KEY_STATUS S
+//#define MAGIC_KEY_CONSOLE C
+//#define MAGIC_KEY_LAYER0_ALT1 ESC
+//#define MAGIC_KEY_LAYER0_ALT2 GRAVE
+//#define MAGIC_KEY_LAYER0 0
+//#define MAGIC_KEY_LAYER1 1
+//#define MAGIC_KEY_LAYER2 2
+//#define MAGIC_KEY_LAYER3 3
+//#define MAGIC_KEY_LAYER4 4
+//#define MAGIC_KEY_LAYER5 5
+//#define MAGIC_KEY_LAYER6 6
+//#define MAGIC_KEY_LAYER7 7
+//#define MAGIC_KEY_LAYER8 8
+//#define MAGIC_KEY_LAYER9 9
+//#define MAGIC_KEY_BOOTLOADER PAUSE
+#define MAGIC_KEY_LOCK BSLS
+//#define MAGIC_KEY_EEPROM E
+//#define MAGIC_KEY_NKRO N
+//#define MAGIC_KEY_SLEEP_LED Z
+
+/*
+ * Feature disable options
+ * These options are also useful to firmware size reduction.
+ */
+
+/* disable debug print */
+//#define NO_DEBUG
+
+/* disable print */
+//#define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+
+#endif
diff --git a/keyboards/retro_refit/keymaps/default/keymap.c b/keyboards/retro_refit/keymaps/default/keymap.c
new file mode 100644
index 000000000..405402d5e
--- /dev/null
+++ b/keyboards/retro_refit/keymaps/default/keymap.c
@@ -0,0 +1,33 @@
+// This is the canonical layout file for the Quantum project. If you want to add another keyboard,
+// this is the style you want to emulate.
+
+#include "retro_refit.h"
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[0] =
+ KEYMAP( ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, NLCK, SLCK, PSCR, PAUS, \
+ GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS, EQL, BSPC, HOME, \
+ TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC, RBRC, PGUP, \
+ BSLS, A, S, D, F, G, H, J, K, L, SCLN, QUOT, ENT, PGDN, \
+ LSFT, Z, X, C, V, B, N, M, COMM, DOT, SLSH, RSFT, UP, END, \
+ LCTL, LGUI, LALT, SPC, INS, DEL, LEFT, DOWN, RGHT),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
diff --git a/keyboards/retro_refit/readme.md b/keyboards/retro_refit/readme.md
new file mode 100644
index 000000000..b01a1a9ca
--- /dev/null
+++ b/keyboards/retro_refit/readme.md
@@ -0,0 +1,24 @@
+retro_refit keyboard firmware
+======================
+
+## Quantum MK Firmware
+
+For the full Quantum feature list, see [the parent readme.md](/readme.md).
+
+## Building
+
+Download or clone the whole firmware and navigate to the keyboards/retro_refit folder. Once your dev env is setup, you'll be able to type `make` to generate your .hex - you can then use the Teensy Loader to program your .hex file.
+
+Depending on which keymap you would like to use, you will have to compile slightly differently.
+
+### Default
+To build with the default keymap, simply run `make`.
+
+### Other Keymaps
+Several version of keymap are available in advance but you are recommended to define your favorite layout yourself. To define your own keymap create file named `<name>.c` and see keymap document (you can find in top readme.md) and existent keymap files.
+
+To build the firmware binary hex file with a keymap just do `make` with `KEYMAP` option like:
+```
+$ make KEYMAP=[default|jack|<name>]
+```
+Keymaps follow the format **__\<name\>.c__** and are stored in the `keymaps` folder. \ No newline at end of file
diff --git a/keyboards/retro_refit/retro_refit.c b/keyboards/retro_refit/retro_refit.c
new file mode 100644
index 000000000..3d610eba3
--- /dev/null
+++ b/keyboards/retro_refit/retro_refit.c
@@ -0,0 +1,47 @@
+#include "retro_refit.h"
+#include "led.h"
+
+void matrix_init_kb(void) {
+ // put your keyboard start-up code here
+ // runs once when the firmware starts up
+
+ // Disable status LED on KB, enable status LED on Teensy (KB_STATUS = !TEENSY_STATUS)
+ DDRD |= (1<<6);
+ PORTD |= (1<<6);
+
+ matrix_init_user();
+};
+
+void led_set_kb(uint8_t usb_led) {
+ // put your keyboard LED indicator (ex: Caps Lock LED) toggling code here
+
+ if (usb_led & (1<<USB_LED_CAPS_LOCK)) {
+ // output low
+ DDRD |= (1<<0);
+ PORTD &= ~(1<<0);
+ } else {
+ // Hi-Z
+ DDRD &= ~(1<<0);
+ PORTD &= ~(1<<0);
+ }
+ if (usb_led & (1<<USB_LED_NUM_LOCK)) {
+ // output low
+ DDRD |= (1<<1);
+ PORTD &= ~(1<<1);
+ } else {
+ // Hi-Z
+ DDRD &= ~(1<<1);
+ PORTD &= ~(1<<1);
+ }
+ if (usb_led & (1<<USB_LED_SCROLL_LOCK)) {
+ // output low
+ DDRC |= (1<<6);
+ PORTC &= ~(1<<6);
+ } else {
+ // Hi-Z
+ DDRC &= ~(1<<6);
+ PORTC &= ~(1<<6);
+ }
+
+ led_set_user(usb_led);
+}; \ No newline at end of file
diff --git a/keyboards/retro_refit/retro_refit.h b/keyboards/retro_refit/retro_refit.h
new file mode 100644
index 000000000..109acdc39
--- /dev/null
+++ b/keyboards/retro_refit/retro_refit.h
@@ -0,0 +1,38 @@
+#ifndef RETRO_REFIT_H
+#define RETRO_REFIT_H
+
+#include "quantum.h"
+
+// This macro is an example of using a non-standard row-column matrix. The
+// keyboard in question had 11 rows and 8 columns, but the rows were not all
+// horizontal, and the columns were not all vertical. For example, row 2
+// contained "Print Screen", "N", "M", ",", ".", "/", "Right Shift", and
+// "Left Alt". Column 0 contained "F6", "7", "O", "'", "Q", "D", "B",
+// "Left Alt", "Up Arrow", and "Down Arrow".
+//
+// The macro makes programming the keys easier and in a more straight-forward
+// manner because it realigns the keys into a 6x15 sensible keyboard layout
+// instead of the obtuse 11x8 matrix.
+
+#define KEYMAP( \
+ K77, K05, K04, K03, K02, K01, K00, KA7, KA6, KA5, KA4, KA3, KA2, K11, K94, \
+ K27, K76, K75, K74, K73, K72, K71, K70, K67, K66, K65, K64, K63, K62, KA1, \
+ K61, K60, K57, K56, K55, K54, K53, K52, K51, K50, K47, K46, K45, K97, \
+ K43, K42, K41, K40, K37, K36, K35, K34, K33, K32, K31, K30, K44, K87, \
+ K26, K24, K23, K22, K21, K20, K17, K16, K15, K14, K13, K12, KA0, K91, \
+ K10, K06, K25, K07, K86, K85, K95, K90, K93 \
+) { \
+{ KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07, }, \
+{ KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_##K17, }, \
+{ KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_##K27, }, \
+{ KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36, KC_##K37, }, \
+{ KC_##K40, KC_##K41, KC_##K42, KC_##K43, KC_##K44, KC_##K45, KC_##K46, KC_##K47, }, \
+{ KC_##K50, KC_##K51, KC_##K52, KC_##K53, KC_##K54, KC_##K55, KC_##K56, KC_##K57, }, \
+{ KC_##K60, KC_##K61, KC_##K62, KC_##K63, KC_##K64, KC_##K65, KC_##K66, KC_##K67, }, \
+{ KC_##K70, KC_##K71, KC_##K72, KC_##K73, KC_##K74, KC_##K75, KC_##K76, KC_##K77, }, \
+{ KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_##K85, KC_##K86, KC_##K87, }, \
+{ KC_##K90, KC_##K91, KC_NO, KC_##K93, KC_##K94, KC_##K95, KC_NO, KC_##K97, }, \
+{ KC_##KA0, KC_##KA1, KC_##KA2, KC_##KA3, KC_##KA4, KC_##KA5, KC_##KA6, KC_##KA7, } \
+}
+
+#endif \ No newline at end of file
diff --git a/keyboards/satan/Makefile b/keyboards/satan/Makefile
new file mode 100644
index 000000000..184b5ac37
--- /dev/null
+++ b/keyboards/satan/Makefile
@@ -0,0 +1,70 @@
+
+# MCU name
+#MCU = at90usb1287
+MCU = atmega32u4
+
+# Processor frequency.
+# This will define a symbol, F_CPU, in all source code files equal to the
+# processor frequency in Hz. You can then use this symbol in your source code to
+# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
+# automatically to create a 32-bit value in your source code.
+#
+# This will be an integer division of F_USB below, as it is sourced by
+# F_USB after it has run through any CPU prescalers. Note that this value
+# does not *change* the processor frequency - it should merely be updated to
+# reflect the processor speed set externally so that the code can use accurate
+# software delays.
+F_CPU = 16000000
+
+
+#
+# LUFA specific
+#
+# Target architecture (see library "Board Types" documentation).
+ARCH = AVR8
+
+# Input clock frequency.
+# This will define a symbol, F_USB, in all source code files equal to the
+# input clock frequency (before any prescaling is performed) in Hz. This value may
+# differ from F_CPU if prescaling is used on the latter, and is required as the
+# raw input clock is fed directly to the PLL sections of the AVR for high speed
+# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
+# at the end, this will be done automatically to create a 32-bit value in your
+# source code.
+#
+# If no clock division is performed on the input clock inside the AVR (via the
+# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
+F_USB = $(F_CPU)
+
+# Interrupt driven control endpoint task(+60)
+OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
+
+
+# Boot Section Size in *bytes*
+# Teensy halfKay 512
+# Teensy++ halfKay 1024
+# Atmel DFU loader 4096
+# LUFA bootloader 4096
+# USBaspLoader 2048
+OPT_DEFS += -DBOOTLOADER_SIZE=4096
+
+
+# Build Options
+# comment out to disable the options.
+#
+BOOTMAGIC_ENABLE ?= yes # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE ?= no # Mouse keys(+4700)
+EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450)
+CONSOLE_ENABLE ?= yes # Console for debug(+400)
+COMMAND_ENABLE ?= yes # Commands for debug and configuration
+NKRO_ENABLE ?= yes # USB Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+RGBLIGHT_ENABLE ?= yes # Enable keyboard underlight functionality (+4870)
+BACKLIGHT_ENABLE ?= yes # Enable keyboard backlight functionality (+1150)
+MIDI_ENABLE ?= no # MIDI controls
+AUDIO_ENABLE ?= no
+UNICODE_ENABLE ?= no # Unicode
+BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID
+
+ifndef QUANTUM_DIR
+ include ../../Makefile
+endif
diff --git a/keyboards/satan/config.h b/keyboards/satan/config.h
new file mode 100644
index 000000000..a7ea8f904
--- /dev/null
+++ b/keyboards/satan/config.h
@@ -0,0 +1,94 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "config_common.h"
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x6060
+#define DEVICE_VER 0x0003
+#define MANUFACTURER SATAN
+#define PRODUCT GH60
+#define DESCRIPTION QMK keyboard firmware for Satan GH60 with WS2812 support
+
+/* key matrix size */
+#define MATRIX_ROWS 5
+#define MATRIX_COLS 14
+
+// ROWS: Top to bottom, COLS: Left to right
+
+#define MATRIX_ROW_PINS { D0, D1, D2, D3, D5 }
+#define MATRIX_COL_PINS { F0, F1, E6, C7, C6, B7, D4, B1, B0, B5, B4, D7, D6, B3 }
+#define UNUSED_PINS
+
+#define BACKLIGHT_PIN B6
+
+/* COL2ROW or ROW2COL */
+#define DIODE_DIRECTION COL2ROW
+
+/* define if matrix has ghost */
+//#define MATRIX_HAS_GHOST
+
+/* Set 0 if debouncing isn't needed */
+#define DEBOUNCING_DELAY 5
+
+/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
+#define LOCKING_SUPPORT_ENABLE
+/* Locking resynchronize hack */
+#define LOCKING_RESYNC_ENABLE
+
+/* key combination for command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+/* Backlight configuration
+ */
+#define BACKLIGHT_LEVELS 4
+
+/* Underlight configuration
+ */
+ #define ws2812_PORTREG PORTE
+ #define ws2812_DDRREG DDRE
+ #define ws2812_pin 2
+ #define RGBLED_NUM 8 // Number of LEDs
+ #define RGBLIGHT_HUE_STEP 10
+ #define RGBLIGHT_SAT_STEP 17
+ #define RGBLIGHT_VAL_STEP 17
+
+/*
+ * Feature disable options
+ * These options are also useful to firmware size reduction.
+ */
+
+/* disable debug print */
+//#define NO_DEBUG
+
+/* disable print */
+//#define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+
+#endif
diff --git a/keyboards/satan/controller.jpg b/keyboards/satan/controller.jpg
new file mode 100644
index 000000000..76ffa4500
--- /dev/null
+++ b/keyboards/satan/controller.jpg
Binary files differ
diff --git a/keyboards/satan/keymaps/default/keymap.c b/keyboards/satan/keymaps/default/keymap.c
new file mode 100644
index 000000000..b19404afc
--- /dev/null
+++ b/keyboards/satan/keymaps/default/keymap.c
@@ -0,0 +1,162 @@
+#include "satan.h"
+
+#ifdef RGBLIGHT_ENABLE
+#include "rgblight.h"
+#endif
+
+// Used for SHIFT_ESC
+#define MODS_CTRL_MASK (MOD_BIT(KC_LSHIFT)|MOD_BIT(KC_RSHIFT))
+
+// Each layer gets a name for readability, which is then used in the keymap matrix below.
+// The underscores don't mean anything - you can have a layer called STUFF or any other name.
+// Layer names don't all need to be of the same length, obviously, and you can also skip them
+// entirely and just use numbers.
+#define _BL 0
+#define _FL 1
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ /* Keymap _BL: (Base Layer) Default Layer
+ * ,-----------------------------------------------------------.
+ * |Esc~| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backsp |
+ * |-----------------------------------------------------------|
+ * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \ |
+ * |-----------------------------------------------------------|
+ * |CAPS | A| S| D| F| G| H| J| K| L| ;| '|Return |
+ * |-----------------------------------------------------------|
+ * |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift |
+ * |-----------------------------------------------------------|
+ * |Ctrl|Gui |Alt | Space |Alt |Gui |FN |Ctrl |
+ * `-----------------------------------------------------------'
+ */
+[_BL] = KEYMAP(
+ F(0), KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, \
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, \
+ KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN,KC_QUOT, KC_ENT, \
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH, KC_RSFT, \
+ KC_LCTL, KC_LGUI,KC_LALT, KC_SPC, KC_RALT, KC_RGUI, MO(_FL), KC_RCTL),
+
+ /* Keymap _FL: Function Layer
+ * ,-----------------------------------------------------------.
+ * | | | | | | | | | | | | | | RESET|
+ * |-----------------------------------------------------------|
+ * | | | | | | | | | | | |BL-|BL+|BL |
+ * |-----------------------------------------------------------|
+ * | | | | | | | | | | | | |
+ * |-----------------------------------------------------------|
+ * | | F1|F2 | F3|F4 | F5| F6| F7| F8| | | |
+ * |-----------------------------------------------------------|
+ * | | | | | | | | |
+ * `-----------------------------------------------------------'
+ */
+[_FL] = KEYMAP(
+ #ifdef RGBLIGHT_ENABLE
+ KC_GRV, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, RESET, \
+ KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, BL_DEC, BL_INC, BL_TOGG, \
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
+ KC_TRNS, F(1), F(2), F(3), F(4), F(5), F(6), F(7), F(8), KC_TRNS, KC_TRNS, KC_TRNS, \
+ KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS),
+ #else
+ KC_GRV, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, RESET, \
+ KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, BL_DEC, BL_INC, BL_TOGG, \
+ KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \
+ KC_TRNS,KC_TRNS,KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS),
+ #endif
+};
+
+enum function_id {
+ SHIFT_ESC,
+ #ifdef RGBLIGHT_ENABLE
+ RGBLED_TOGGLE,
+ RGBLED_STEP_MODE,
+ RGBLED_INCREASE_HUE,
+ RGBLED_DECREASE_HUE,
+ RGBLED_INCREASE_SAT,
+ RGBLED_DECREASE_SAT,
+ RGBLED_INCREASE_VAL,
+ RGBLED_DECREASE_VAL
+ #endif
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [0] = ACTION_FUNCTION(SHIFT_ESC),
+ #ifdef RGBLIGHT_ENABLE
+ [1] = ACTION_FUNCTION(RGBLED_TOGGLE),
+ [2] = ACTION_FUNCTION(RGBLED_STEP_MODE),
+ [3] = ACTION_FUNCTION(RGBLED_INCREASE_HUE),
+ [4] = ACTION_FUNCTION(RGBLED_DECREASE_HUE),
+ [5] = ACTION_FUNCTION(RGBLED_INCREASE_SAT),
+ [6] = ACTION_FUNCTION(RGBLED_DECREASE_SAT),
+ [7] = ACTION_FUNCTION(RGBLED_INCREASE_VAL),
+ [8] = ACTION_FUNCTION(RGBLED_DECREASE_VAL),
+ #endif
+};
+
+void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) {
+ static uint8_t shift_esc_shift_mask;
+ switch (id) {
+ case SHIFT_ESC:
+ shift_esc_shift_mask = get_mods()&MODS_CTRL_MASK;
+ if (record->event.pressed) {
+ if (shift_esc_shift_mask) {
+ add_key(KC_GRV);
+ send_keyboard_report();
+ } else {
+ add_key(KC_ESC);
+ send_keyboard_report();
+ }
+ } else {
+ if (shift_esc_shift_mask) {
+ del_key(KC_GRV);
+ send_keyboard_report();
+ } else {
+ del_key(KC_ESC);
+ send_keyboard_report();
+ }
+ }
+ break;
+ //led operations
+ #ifdef RGBLIGHT_ENABLE
+ case RGBLED_TOGGLE:
+ if (record->event.pressed) {
+ rgblight_toggle();
+ }
+ break;
+ case RGBLED_INCREASE_HUE:
+ if (record->event.pressed) {
+ rgblight_increase_hue();
+ }
+ break;
+ case RGBLED_DECREASE_HUE:
+ if (record->event.pressed) {
+ rgblight_decrease_hue();
+ }
+ break;
+ case RGBLED_INCREASE_SAT:
+ if (record->event.pressed) {
+ rgblight_increase_sat();
+ }
+ break;
+ case RGBLED_DECREASE_SAT:
+ if (record->event.pressed) {
+ rgblight_decrease_sat();
+ }
+ break;
+ case RGBLED_INCREASE_VAL:
+ if (record->event.pressed) {
+ rgblight_increase_val();
+ }
+ break;
+ case RGBLED_DECREASE_VAL:
+ if (record->event.pressed) {
+ rgblight_decrease_val();
+ }
+ break;
+ case RGBLED_STEP_MODE:
+ if (record->event.pressed) {
+ rgblight_step();
+ }
+ break;
+ #endif
+ }
+}
diff --git a/keyboards/satan/keymaps/sethbc/keymap.c b/keyboards/satan/keymaps/sethbc/keymap.c
new file mode 100644
index 000000000..0ea4a7ae4
--- /dev/null
+++ b/keyboards/satan/keymaps/sethbc/keymap.c
@@ -0,0 +1,149 @@
+#include "satan.h"
+
+#ifdef RGBLIGHT_ENABLE
+#include "rgblight.h"
+#endif
+
+// Used for SHIFT_ESC
+#define MODS_CTRL_MASK (MOD_BIT(KC_LSHIFT)|MOD_BIT(KC_RSHIFT))
+
+// Each layer gets a name for readability, which is then used in the keymap matrix below.
+// The underscores don't mean anything - you can have a layer called STUFF or any other name.
+// Layer names don't all need to be of the same length, obviously, and you can also skip them
+// entirely and just use numbers.
+#define _BL 0
+#define _FL 1
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ /* Keymap _BL: (Base Layer) Default Layer
+ * ,-----------------------------------------------------------.
+ * |Esc~| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| \ | ~ |
+ * |-----------------------------------------------------------|
+ * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]|bksp |
+ * |-----------------------------------------------------------|
+ * |CAPS | A| S| D| F| G| H| J| K| L| ;| '|Return |
+ * |-----------------------------------------------------------|
+ * |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift| fn |
+ * |-----------------------------------------------------------|
+ * |Ctrl|Gui |Alt | Space |Alt |Gui |FN |Ctrl |
+ * `-----------------------------------------------------------'
+ */
+[_BL] = KEYMAP_HHKB(
+ F(0), KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSLS, KC_GRV, \
+ KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSPC, \
+ KC_LCTL, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, \
+ KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, MO(_FL), \
+ KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, KC_RGUI, KC_MENU, KC_RCTL),
+
+[_FL] = KEYMAP_HHKB(
+ #ifdef RGBLIGHT_ENABLE
+ KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_TRNS, RESET, \
+ KC_CAPS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PSCR, KC_SLCK, KC_PAUS, KC_UP, KC_TRNS, KC_BSPC, \
+ KC_TRNS, KC_VOLD, KC_VOLU, KC_MUTE, KC_TRNS, KC_TRNS, KC_PAST, KC_PSLS, KC_HOME, KC_PGUP, KC_LEFT, KC_RGHT, KC_PENT, \
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PPLS, KC_PMNS, KC_END, KC_PGDN, KC_DOWN, KC_TRNS, KC_TRNS, \
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS),
+ #else
+ KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_TRNS, RESET, \
+ KC_CAPS, KC_TRNS, F(1), F(2), F(3), KC_TRNS, KC_TRNS, KC_TRNS, KC_PSCR, KC_SLCK, KC_PAUS, KC_UP, KC_TRNS, KC_BSPC, \
+ KC_TRNS, KC_VOLD, F(4), F(5), F(6), KC_TRNS, KC_PAST, KC_PSLS, KC_HOME, KC_PGUP, KC_LEFT, KC_RGHT, KC_PENT, \
+ KC_TRNS, F(7), F(8), KC_TRNS, KC_TRNS, KC_TRNS, KC_PPLS, KC_PMNS, KC_END, KC_PGDN, KC_DOWN, KC_TRNS, KC_TRNS, \
+ KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS),
+ #endif
+};
+
+enum function_id {
+ SHIFT_ESC,
+ #ifdef RGBLIGHT_ENABLE
+ RGBLED_TOGGLE,
+ RGBLED_STEP_MODE,
+ RGBLED_INCREASE_HUE,
+ RGBLED_DECREASE_HUE,
+ RGBLED_INCREASE_SAT,
+ RGBLED_DECREASE_SAT,
+ RGBLED_INCREASE_VAL,
+ RGBLED_DECREASE_VAL
+ #endif
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+ [0] = ACTION_FUNCTION(SHIFT_ESC),
+ #ifdef RGBLIGHT_ENABLE
+ [1] = ACTION_FUNCTION(RGBLED_TOGGLE),
+ [2] = ACTION_FUNCTION(RGBLED_STEP_MODE),
+ [3] = ACTION_FUNCTION(RGBLED_INCREASE_HUE),
+ [4] = ACTION_FUNCTION(RGBLED_DECREASE_HUE),
+ [5] = ACTION_FUNCTION(RGBLED_INCREASE_SAT),
+ [6] = ACTION_FUNCTION(RGBLED_DECREASE_SAT),
+ [7] = ACTION_FUNCTION(RGBLED_INCREASE_VAL),
+ [8] = ACTION_FUNCTION(RGBLED_DECREASE_VAL),
+ #endif
+};
+
+void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) {
+ static uint8_t shift_esc_shift_mask;
+ switch (id) {
+ case SHIFT_ESC:
+ shift_esc_shift_mask = get_mods()&MODS_CTRL_MASK;
+ if (record->event.pressed) {
+ if (shift_esc_shift_mask) {
+ add_key(KC_GRV);
+ send_keyboard_report();
+ } else {
+ add_key(KC_ESC);
+ send_keyboard_report();
+ }
+ } else {
+ if (shift_esc_shift_mask) {
+ del_key(KC_GRV);
+ send_keyboard_report();
+ } else {
+ del_key(KC_ESC);
+ send_keyboard_report();
+ }
+ }
+ break;
+ //led operations
+ #ifdef RGBLIGHT_ENABLE
+ case RGBLED_TOGGLE:
+ if (record->event.pressed) {
+ rgblight_toggle();
+ }
+ break;
+ case RGBLED_INCREASE_HUE:
+ if (record->event.pressed) {
+ rgblight_increase_hue();
+ }
+ break;
+ case RGBLED_DECREASE_HUE:
+ if (record->event.pressed) {
+ rgblight_decrease_hue();
+ }
+ break;
+ case RGBLED_INCREASE_SAT:
+ if (record->event.pressed) {
+ rgblight_increase_sat();
+ }
+ break;
+ case RGBLED_DECREASE_SAT:
+ if (record->event.pressed) {
+ rgblight_decrease_sat();
+ }
+ break;
+ case RGBLED_INCREASE_VAL:
+ if (record->event.pressed) {
+ rgblight_increase_val();
+ }
+ break;
+ case RGBLED_DECREASE_VAL:
+ if (record->event.pressed) {
+ rgblight_decrease_val();
+ }
+ break;
+ case RGBLED_STEP_MODE:
+ if (record->event.pressed) {
+ rgblight_step();
+ }
+ break;
+ #endif
+ }
+}
diff --git a/keyboards/satan/pinout.txt b/keyboards/satan/pinout.txt
new file mode 100644
index 000000000..d1ad4ac88
--- /dev/null
+++ b/keyboards/satan/pinout.txt
@@ -0,0 +1 @@
+For WS2812B LED strip support, connect DIN from strip to PE2 on ATmega32u4 controller (see reference image controller.jpg) \ No newline at end of file
diff --git a/keyboards/satan/power.jpg b/keyboards/satan/power.jpg
new file mode 100644
index 000000000..0514eef5c
--- /dev/null
+++ b/keyboards/satan/power.jpg
Binary files differ
diff --git a/keyboards/satan/satan.c b/keyboards/satan/satan.c
new file mode 100644
index 000000000..d2c5d5c20
--- /dev/null
+++ b/keyboards/satan/satan.c
@@ -0,0 +1,30 @@
+#include "satan.h"
+#include "led.h"
+
+void matrix_init_kb(void) {
+ // put your keyboard start-up code here
+ // runs once when the firmware starts up
+ matrix_init_user();
+ led_init_ports();
+};
+
+void matrix_scan_kb(void) {
+ // put your looping keyboard code here
+ // runs every cycle (a lot)
+ matrix_scan_user();
+};
+
+void led_init_ports(void) {
+ // * Set our LED pins as output
+ DDRB |= (1<<2);
+}
+
+void led_set_kb(uint8_t usb_led) {
+ if (usb_led & (1<<USB_LED_CAPS_LOCK)) {
+ // Turn capslock on
+ PORTB &= ~(1<<2);
+ } else {
+ // Turn capslock off
+ PORTB |= (1<<2);
+ }
+}
diff --git a/keyboards/satan/satan.h b/keyboards/satan/satan.h
new file mode 100644
index 000000000..fa1711915
--- /dev/null
+++ b/keyboards/satan/satan.h
@@ -0,0 +1,69 @@
+#ifndef SATAN_H
+#define SATAN_H
+
+#include "quantum.h"
+
+/* Clueboard matrix layout
+ * ,-----------------------------------------------------------.
+ * | 00 |01| 02| 03| 04| 05| 06| 07| 08| 09| 0a| 0b| 0c| 0d |
+ * |-----------------------------------------------------------|
+ * | 10 | 11| 12| 13| 14| 15| 16| 17| 18| 19| 1a| 1b| 1c| 1d |
+ * |-----------------------------------------------------------|
+ * | 20 | 21| 22| 23| 24| 25| 26| 27| 28| 29| 2a| 2b| 2d |
+ * |-----------------------------------------------------------|
+ * | 30 | 32| 33| 34| 35| 36| 37| 38| 39| 3a| 3b| 3d |
+ * |-----------------------------------------------------------|
+ * | 40 | 41 | 42 | 45 | 4a | 4b | 4c | 4d |
+ * `-----------------------------------------------------------'
+ */
+// The first section contains all of the arguments
+// The second converts the arguments into a two-dimensional array
+#define KEYMAP( \
+ k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, k0c, k0d, \
+ k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, k1c, k1d, \
+ k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b, k2d, \
+ k30, k32, k33, k34, k35, k36, k37, k38, k39, k3a, k3b, k3d, \
+ k40, k41, k42, k45, k4a, k4b, k4c, k4d \
+) \
+{ \
+ {k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, k0c, k0d}, \
+ {k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, k1c, k1d}, \
+ {k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b, KC_NO, k2d}, \
+ {k30, KC_NO, k32, k33, k34, k35, k36, k37, k38, k39, k3a, k3b, KC_NO, k3d}, \
+ {k40, k41, k42, KC_NO, KC_NO, k45, KC_NO, KC_NO, KC_NO, KC_NO, k4a, k4b, k4c, k4d} \
+}
+
+/* Satan HHKB matrix layout
+ * ,------------------------------------------------------------.
+ * | 00 |01| 02| 03| 04| 05| 06| 07| 08| 09| 0a| 0b| 0c| 0d| 49 |
+ * |------------------------------------------------------------|
+ * | 10 | 11| 12| 13| 14| 15| 16| 17| 18| 19| 1a| 1b| 1c| 1d |
+ * |------------------------------------------------------------|
+ * | 20 | 21| 22| 23| 24| 25| 26| 27| 28| 29| 2a| 2b| 2d |
+ * |------------------------------------------------------------|
+ * | 30 | 32| 33| 34| 35| 36| 37| 38| 39| 3a| 3b| 3d | 3c |
+ * |------------------------------------------------------------|
+ * | 40 | 41 | 42 | 45 | 4a | 4b | 4c | 4d |
+ * `------------------------------------------------------------'
+ */
+
+#define KEYMAP_HHKB( \
+ k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, k0c, k0d, k49, \
+ k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, k1c, k1d, \
+ k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b, k2d, \
+ k30, k32, k33, k34, k35, k36, k37, k38, k39, k3a, k3b, k3d, k3c, \
+ k40, k41, k42, k45, k4a, k4b, k4c, k4d \
+) \
+{ \
+ {k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, k0c, k0d}, \
+ {k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, k1c, k1d}, \
+ {k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b, KC_NO, k2d}, \
+ {k30, KC_NO, k32, k33, k34, k35, k36, k37, k38, k39, k3a, k3b, k3c, k3d}, \
+ {k40, k41, k42, KC_NO, KC_NO, k45, KC_NO, KC_NO, KC_NO, k49, k4a, k4b, k4c, k4d} \
+}
+
+
+void matrix_init_user(void);
+void matrix_scan_user(void);
+
+#endif
diff --git a/keyboards/sixkeyboard/Makefile b/keyboards/sixkeyboard/Makefile
new file mode 100644
index 000000000..6f273064a
--- /dev/null
+++ b/keyboards/sixkeyboard/Makefile
@@ -0,0 +1,75 @@
+
+
+SRC = matrix.c
+
+# MCU name
+#MCU = at90usb1287
+MCU = atmega16u2
+
+# Processor frequency.
+# This will define a symbol, F_CPU, in all source code files equal to the
+# processor frequency in Hz. You can then use this symbol in your source code to
+# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
+# automatically to create a 32-bit value in your source code.
+#
+# This will be an integer division of F_USB below, as it is sourced by
+# F_USB after it has run through any CPU prescalers. Note that this value
+# does not *change* the processor frequency - it should merely be updated to
+# reflect the processor speed set externally so that the code can use accurate
+# software delays.
+F_CPU = 16000000
+
+
+#
+# LUFA specific
+#
+# Target architecture (see library "Board Types" documentation).
+ARCH = AVR8
+
+# Input clock frequency.
+# This will define a symbol, F_USB, in all source code files equal to the
+# input clock frequency (before any prescaling is performed) in Hz. This value may
+# differ from F_CPU if prescaling is used on the latter, and is required as the
+# raw input clock is fed directly to the PLL sections of the AVR for high speed
+# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
+# at the end, this will be done automatically to create a 32-bit value in your
+# source code.
+#
+# If no clock division is performed on the input clock inside the AVR (via the
+# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
+F_USB = $(F_CPU)
+
+# Interrupt driven control endpoint task(+60)
+OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
+
+
+# Boot Section Size in *bytes*
+# Teensy halfKay 512
+# Teensy++ halfKay 1024
+# Atmel DFU loader 4096
+# LUFA bootloader 4096
+# USBaspLoader 2048
+OPT_DEFS += -DBOOTLOADER_SIZE=4096
+
+
+# Build Options
+# comment out to disable the options.
+#
+BOOTMAGIC_ENABLE ?= no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE ?= no # Mouse keys(+4700)
+EXTRAKEY_ENABLE ?= no # Audio control and System control(+450)
+CONSOLE_ENABLE ?= no # Console for debug(+400)
+COMMAND_ENABLE ?= no # Commands for debug and configuration
+SLEEP_LED_ENABLE ?= no # Breathing sleep LED during USB suspend
+NKRO_ENABLE ?= no # USB Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE ?= no # Enable keyboard backlight functionality
+MIDI_ENABLE ?= no # MIDI controls
+AUDIO_ENABLE ?= no
+UNICODE_ENABLE ?= no # Unicode
+BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID
+CUSTOM_MATRIX = yes
+
+ifndef QUANTUM_DIR
+ include ../../Makefile
+endif
+
diff --git a/keyboards/sixkeyboard/config.h b/keyboards/sixkeyboard/config.h
new file mode 100644
index 000000000..bf58bb2b7
--- /dev/null
+++ b/keyboards/sixkeyboard/config.h
@@ -0,0 +1,115 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "config_common.h"
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x6062
+#define DEVICE_VER 0x0001
+#define MANUFACTURER techkeys.us
+#define PRODUCT sixkeykeyboard
+#define DESCRIPTION A little 6-key macro pad
+
+/* key matrix size */
+#define MATRIX_ROWS 2
+#define MATRIX_COLS 3
+
+/* define if matrix has ghost */
+//#define MATRIX_HAS_GHOST
+
+/* number of backlight levels */
+#define BACKLIGHT_LEVELS 0
+
+/* Set 0 if debouncing isn't needed */
+#define DEBOUNCING_DELAY 5
+
+/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
+#define LOCKING_SUPPORT_ENABLE
+/* Locking resynchronize hack */
+#define LOCKING_RESYNC_ENABLE
+
+
+/* Force NKRO Mode - If forced on, must be disabled via magic key (default = LShift+RShift+N) */
+#define FORCE_NKRO
+
+/*
+ * Magic key options
+ * These options allow the magic key functionality to be changed. This is useful
+ * if your keyboard/keypad is missing keys and you want magic key support.
+ */
+
+/* key combination for magic key command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+/* control how magic key switches layers */
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS true
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS true
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM false
+
+/* remap magic keys */
+//#define MAGIC_KEY_HELP1 H
+//#define MAGIC_KEY_HELP2 SLASH
+//#define MAGIC_KEY_DEBUG D
+//#define MAGIC_KEY_DEBUG_MATRIX X
+//#define MAGIC_KEY_DEBUG_KBD K
+//#define MAGIC_KEY_DEBUG_MOUSE M
+//#define MAGIC_KEY_VERSION V
+//#define MAGIC_KEY_STATUS S
+//#define MAGIC_KEY_CONSOLE C
+//#define MAGIC_KEY_LAYER0_ALT1 ESC
+//#define MAGIC_KEY_LAYER0_ALT2 GRAVE
+//#define MAGIC_KEY_LAYER0 0
+//#define MAGIC_KEY_LAYER1 1
+//#define MAGIC_KEY_LAYER2 2
+//#define MAGIC_KEY_LAYER3 3
+//#define MAGIC_KEY_LAYER4 4
+//#define MAGIC_KEY_LAYER5 5
+//#define MAGIC_KEY_LAYER6 6
+//#define MAGIC_KEY_LAYER7 7
+//#define MAGIC_KEY_LAYER8 8
+//#define MAGIC_KEY_LAYER9 9
+//#define MAGIC_KEY_BOOTLOADER PAUSE
+//#define MAGIC_KEY_LOCK BSLS
+//#define MAGIC_KEY_EEPROM E
+//#define MAGIC_KEY_NKRO N
+//#define MAGIC_KEY_SLEEP_LED Z
+
+/*
+ * Feature disable options
+ * These options are also useful to firmware size reduction.
+ */
+
+/* disable debug print */
+//#define NO_DEBUG
+
+/* disable print */
+//#define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+
+#endif
diff --git a/keyboards/sixkeyboard/keymaps/default/keymap.c b/keyboards/sixkeyboard/keymaps/default/keymap.c
new file mode 100644
index 000000000..641ed790e
--- /dev/null
+++ b/keyboards/sixkeyboard/keymaps/default/keymap.c
@@ -0,0 +1,39 @@
+// This is the canonical layout file for the Quantum project. If you want to add another keyboard,
+// this is the style you want to emulate.
+
+#include "sixkeyboard.h"
+#include "matrix.h"
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[0] = {
+ {KC_A, KC_B, KC_C},
+ {KC_D, KC_E, KC_F}
+ }
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+void matrix_scan_user(void) {
+ // jump to bootloaer when all keys are pressed
+ if (matrix_get_row(0) == 0b111 && matrix_get_row(1) == 0b111) {
+ clear_keyboard();
+ bootloader_jump();
+ }
+}; \ No newline at end of file
diff --git a/keyboards/sixkeyboard/matrix.c b/keyboards/sixkeyboard/matrix.c
new file mode 100644
index 000000000..ed1b70e28
--- /dev/null
+++ b/keyboards/sixkeyboard/matrix.c
@@ -0,0 +1,130 @@
+/*
+
+Note for ErgoDox EZ customizers: Here be dragons!
+This is not a file you want to be messing with.
+All of the interesting stuff for you is under keymaps/ :)
+Love, Erez
+
+Copyright 2013 Oleg Kostyuk <cub.uanic@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * scan matrix
+ */
+#include <stdint.h>
+#include <stdbool.h>
+#include <avr/io.h>
+#include <util/delay.h>
+#include "action_layer.h"
+#include "print.h"
+#include "debug.h"
+#include "util.h"
+#include "matrix.h"
+#include "sixkeyboard.h"
+
+/* matrix state(1:on, 0:off) */
+static matrix_row_t matrix[MATRIX_ROWS];
+
+__attribute__ ((weak))
+void matrix_init_kb(void) {
+ matrix_init_user();
+}
+
+__attribute__ ((weak))
+void matrix_scan_kb(void) {
+ matrix_scan_user();
+}
+
+__attribute__ ((weak))
+void matrix_init_user(void) {
+}
+
+__attribute__ ((weak))
+void matrix_scan_user(void) {
+}
+
+inline
+uint8_t matrix_rows(void)
+{
+ return MATRIX_ROWS;
+}
+
+inline
+uint8_t matrix_cols(void)
+{
+ return MATRIX_COLS;
+}
+
+void matrix_init(void)
+{
+
+ DDRC &= ~(1<<7);
+ PORTC |= (1<<7);
+ DDRB &= ~(1<<7 | 1<<5);
+ PORTB |= (1<<7 | 1<<5);
+ DDRD &= ~(1<<6 | 1<<4 | 1<<1);
+ PORTD |= (1<<6 | 1<<4 | 1<<1);
+
+ matrix_init_kb();
+
+}
+
+uint8_t matrix_scan(void)
+{
+ matrix[0] = (PINC&(1<<7) ? 0 : (1<<0)) | (PINB&(1<<7) ? 0 : (1<<1)) | (PINB&(1<<5) ? 0 : (1<<2));
+ matrix[1] = (PIND&(1<<6) ? 0 : (1<<0)) | (PIND&(1<<1) ? 0 : (1<<1)) | (PIND&(1<<4) ? 0 : (1<<2));
+
+ matrix_scan_quantum();
+
+ return 1;
+}
+
+bool matrix_is_modified(void)
+{
+ return true;
+}
+
+inline
+bool matrix_is_on(uint8_t row, uint8_t col)
+{
+ return (matrix[row] & ((matrix_row_t)1<<col));
+}
+
+inline
+matrix_row_t matrix_get_row(uint8_t row)
+{
+ return matrix[row];
+}
+
+void matrix_print(void)
+{
+ print("\nr/c 0123456789ABCDEF\n");
+ for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
+ phex(row); print(": ");
+ pbin_reverse16(matrix_get_row(row));
+ print("\n");
+ }
+}
+
+uint8_t matrix_key_count(void)
+{
+ uint8_t count = 0;
+ for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+ count += bitpop16(matrix[i]);
+ }
+ return count;
+}
+
diff --git a/keyboards/sixkeyboard/readme.md b/keyboards/sixkeyboard/readme.md
new file mode 100644
index 000000000..7d78a0cae
--- /dev/null
+++ b/keyboards/sixkeyboard/readme.md
@@ -0,0 +1,18 @@
+# Techkeys SixKeyBoard
+
+[Get one here!](http://techkeys.us/collections/accessories/products/sixkeyboard)
+
+The schematic is like this:
+
+```
+ switches leds
+,--+--+--. ,--+--+--.
+|C7|B7|B5| |C6|B6|B4|
++--+--+--+ +--+--+--+
+|D6|D1|D4| |D5|D2|D3|
+`--+--+--' `--+--+--'
+```
+
+The LED on the bottom is `C4`. All 7 of the leds are turned on when the keyboard boots-up in the `sixkeyboard.c` file - backlight_enable is not required. The MCU is an Atmega16u2, so the flash memory is limited to 0x3000 bytes - the current setup uses just about all of that! I'm sure things can be opitimised a bit.
+
+There is a jumper on the bottom of the board (next to the USB port) that serves as a reset button - I drilled a hole in my case to allow for quick access via a screwdriver/metal object. \ No newline at end of file
diff --git a/keyboards/sixkeyboard/sixkeyboard.c b/keyboards/sixkeyboard/sixkeyboard.c
new file mode 100644
index 000000000..85190f616
--- /dev/null
+++ b/keyboards/sixkeyboard/sixkeyboard.c
@@ -0,0 +1,30 @@
+#include "sixkeyboard.h"
+
+void matrix_init_kb(void) {
+ // put your keyboard start-up code here
+ // runs once when the firmware starts up
+
+ DDRC |= (1<<4);
+ PORTC &= ~(1<<4);
+
+
+ DDRC |= (1<<6);
+ PORTC &= ~(1<<6);
+
+ DDRB |= (1<<6);
+ PORTB &= ~(1<<6);
+
+ DDRB |= (1<<4);
+ PORTB &= ~(1<<4);
+
+ DDRD |= (1<<5);
+ PORTD &= ~(1<<5);
+
+ DDRD |= (1<<2);
+ PORTD &= ~(1<<2);
+
+ DDRD |= (1<<3);
+ PORTD &= ~(1<<3);
+
+ matrix_init_user();
+}; \ No newline at end of file
diff --git a/keyboards/sixkeyboard/sixkeyboard.h b/keyboards/sixkeyboard/sixkeyboard.h
new file mode 100644
index 000000000..66f53bf7e
--- /dev/null
+++ b/keyboards/sixkeyboard/sixkeyboard.h
@@ -0,0 +1,18 @@
+#ifndef SIXKEYBOARD_H
+#define SIXKEYBOARD_H
+
+#include "quantum.h"
+
+// This macro is an example of using a non-standard row-column matrix. The
+// keyboard in question had 11 rows and 8 columns, but the rows were not all
+// horizontal, and the columns were not all vertical. For example, row 2
+// contained "Print Screen", "N", "M", ",", ".", "/", "Right Shift", and
+// "Left Alt". Column 0 contained "F6", "7", "O", "'", "Q", "D", "B",
+// "Left Alt", "Up Arrow", and "Down Arrow".
+//
+// The macro makes programming the keys easier and in a more straight-forward
+// manner because it realigns the keys into a 6x15 sensible keyboard layout
+// instead of the obtuse 11x8 matrix.
+
+
+#endif \ No newline at end of file
diff --git a/lib/chibios b/lib/chibios
new file mode 160000
+Subproject a7df9a891067621e8e1a5c2a2c0ceada82403af
diff --git a/lib/chibios-contrib b/lib/chibios-contrib
new file mode 160000
+Subproject e1311c4db6cd366cf760673f769e925741ac0ad
diff --git a/quantum/analog.c b/quantum/analog.c
new file mode 100644
index 000000000..49b84ee0e
--- /dev/null
+++ b/quantum/analog.c
@@ -0,0 +1,53 @@
+// Simple analog to digitial conversion
+
+#include <avr/io.h>
+#include <avr/pgmspace.h>
+#include <stdint.h>
+#include "analog.h"
+
+
+static uint8_t aref = (1<<REFS0); // default to AREF = Vcc
+
+
+void analogReference(uint8_t mode)
+{
+ aref = mode & 0xC0;
+}
+
+
+// Arduino compatible pin input
+int16_t analogRead(uint8_t pin)
+{
+#if defined(__AVR_ATmega32U4__)
+ static const uint8_t PROGMEM pin_to_mux[] = {
+ 0x00, 0x01, 0x04, 0x05, 0x06, 0x07,
+ 0x25, 0x24, 0x23, 0x22, 0x21, 0x20};
+ if (pin >= 12) return 0;
+ return adc_read(pgm_read_byte(pin_to_mux + pin));
+#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
+ if (pin >= 8) return 0;
+ return adc_read(pin);
+#else
+ return 0;
+#endif
+}
+
+// Mux input
+int16_t adc_read(uint8_t mux)
+{
+#if defined(__AVR_AT90USB162__)
+ return 0;
+#else
+ uint8_t low;
+
+ ADCSRA = (1<<ADEN) | ADC_PRESCALER; // enable ADC
+ ADCSRB = (1<<ADHSM) | (mux & 0x20); // high speed mode
+ ADMUX = aref | (mux & 0x1F); // configure mux input
+ ADCSRA = (1<<ADEN) | ADC_PRESCALER | (1<<ADSC); // start the conversion
+ while (ADCSRA & (1<<ADSC)) ; // wait for result
+ low = ADCL; // must read LSB first
+ return (ADCH << 8) | low; // must read MSB only once!
+#endif
+}
+
+
diff --git a/quantum/analog.h b/quantum/analog.h
new file mode 100644
index 000000000..9b95a93be
--- /dev/null
+++ b/quantum/analog.h
@@ -0,0 +1,36 @@
+#ifndef _analog_h_included__
+#define _analog_h_included__
+
+#include <stdint.h>
+
+void analogReference(uint8_t mode);
+int16_t analogRead(uint8_t pin);
+int16_t adc_read(uint8_t mux);
+
+#define ADC_REF_POWER (1<<REFS0)
+#define ADC_REF_INTERNAL ((1<<REFS1) | (1<<REFS0))
+#define ADC_REF_EXTERNAL (0)
+
+// These prescaler values are for high speed mode, ADHSM = 1
+#if F_CPU == 16000000L
+#define ADC_PRESCALER ((1<<ADPS2) | (1<<ADPS1))
+#elif F_CPU == 8000000L
+#define ADC_PRESCALER ((1<<ADPS2) | (1<<ADPS0))
+#elif F_CPU == 4000000L
+#define ADC_PRESCALER ((1<<ADPS2))
+#elif F_CPU == 2000000L
+#define ADC_PRESCALER ((1<<ADPS1) | (1<<ADPS0))
+#elif F_CPU == 1000000L
+#define ADC_PRESCALER ((1<<ADPS1))
+#else
+#define ADC_PRESCALER ((1<<ADPS0))
+#endif
+
+// some avr-libc versions do not properly define ADHSM
+#if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
+#if !defined(ADHSM)
+#define ADHSM (7)
+#endif
+#endif
+
+#endif
diff --git a/quantum/audio/audio.c b/quantum/audio/audio.c
new file mode 100644
index 000000000..ead5fbf3e
--- /dev/null
+++ b/quantum/audio/audio.c
@@ -0,0 +1,477 @@
+#include <stdio.h>
+#include <string.h>
+//#include <math.h>
+#include <avr/pgmspace.h>
+#include <avr/interrupt.h>
+#include <avr/io.h>
+#include "print.h"
+#include "audio.h"
+#include "keymap.h"
+
+#include "eeconfig.h"
+
+#define CPU_PRESCALER 8
+
+// -----------------------------------------------------------------------------
+// Timer Abstractions
+// -----------------------------------------------------------------------------
+
+// TIMSK3 - Timer/Counter #3 Interrupt Mask Register
+// Turn on/off 3A interputs, stopping/enabling the ISR calls
+#define ENABLE_AUDIO_COUNTER_3_ISR TIMSK3 |= _BV(OCIE3A)
+#define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3A)
+
+// TCCR3A: Timer/Counter #3 Control Register
+// Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
+#define ENABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A |= _BV(COM3A1);
+#define DISABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A &= ~(_BV(COM3A1) | _BV(COM3A0));
+
+// Fast PWM Mode Controls
+#define TIMER_3_PERIOD ICR3
+#define TIMER_3_DUTY_CYCLE OCR3A
+
+// -----------------------------------------------------------------------------
+
+
+int voices = 0;
+int voice_place = 0;
+float frequency = 0;
+int volume = 0;
+long position = 0;
+
+float frequencies[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+int volumes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+bool sliding = false;
+
+float place = 0;
+
+uint8_t * sample;
+uint16_t sample_length = 0;
+
+bool playing_notes = false;
+bool playing_note = false;
+float note_frequency = 0;
+float note_length = 0;
+uint8_t note_tempo = TEMPO_DEFAULT;
+float note_timbre = TIMBRE_DEFAULT;
+uint16_t note_position = 0;
+float (* notes_pointer)[][2];
+uint16_t notes_count;
+bool notes_repeat;
+float notes_rest;
+bool note_resting = false;
+
+uint8_t current_note = 0;
+uint8_t rest_counter = 0;
+
+#ifdef VIBRATO_ENABLE
+float vibrato_counter = 0;
+float vibrato_strength = .5;
+float vibrato_rate = 0.125;
+#endif
+
+float polyphony_rate = 0;
+
+static bool audio_initialized = false;
+
+audio_config_t audio_config;
+
+uint16_t envelope_index = 0;
+
+void audio_init()
+{
+
+ // Check EEPROM
+ if (!eeconfig_is_enabled())
+ {
+ eeconfig_init();
+ }
+ audio_config.raw = eeconfig_read_audio();
+
+ // Set port PC6 (OC3A and /OC4A) as output
+ DDRC |= _BV(PORTC6);
+
+ DISABLE_AUDIO_COUNTER_3_ISR;
+
+ // TCCR3A / TCCR3B: Timer/Counter #3 Control Registers
+ // Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
+ // Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14 (Period = ICR3, Duty Cycle = OCR3A)
+ // Clock Select (CS3n) = 0b010 = Clock / 8
+ TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
+ TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30);
+
+ audio_initialized = true;
+}
+
+void stop_all_notes()
+{
+ if (!audio_initialized) {
+ audio_init();
+ }
+ voices = 0;
+
+ DISABLE_AUDIO_COUNTER_3_ISR;
+ DISABLE_AUDIO_COUNTER_3_OUTPUT;
+
+ playing_notes = false;
+ playing_note = false;
+ frequency = 0;
+ volume = 0;
+
+ for (uint8_t i = 0; i < 8; i++)
+ {
+ frequencies[i] = 0;
+ volumes[i] = 0;
+ }
+}
+
+void stop_note(float freq)
+{
+ if (playing_note) {
+ if (!audio_initialized) {
+ audio_init();
+ }
+ for (int i = 7; i >= 0; i--) {
+ if (frequencies[i] == freq) {
+ frequencies[i] = 0;
+ volumes[i] = 0;
+ for (int j = i; (j < 7); j++) {
+ frequencies[j] = frequencies[j+1];
+ frequencies[j+1] = 0;
+ volumes[j] = volumes[j+1];
+ volumes[j+1] = 0;
+ }
+ break;
+ }
+ }
+ voices--;
+ if (voices < 0)
+ voices = 0;
+ if (voice_place >= voices) {
+ voice_place = 0;
+ }
+ if (voices == 0) {
+ DISABLE_AUDIO_COUNTER_3_ISR;
+ DISABLE_AUDIO_COUNTER_3_OUTPUT;
+ frequency = 0;
+ volume = 0;
+ playing_note = false;
+ }
+ }
+}
+
+#ifdef VIBRATO_ENABLE
+
+float mod(float a, int b)
+{
+ float r = fmod(a, b);
+ return r < 0 ? r + b : r;
+}
+
+float vibrato(float average_freq) {
+ #ifdef VIBRATO_STRENGTH_ENABLE
+ float vibrated_freq = average_freq * pow(vibrato_lut[(int)vibrato_counter], vibrato_strength);
+ #else
+ float vibrated_freq = average_freq * vibrato_lut[(int)vibrato_counter];
+ #endif
+ vibrato_counter = mod((vibrato_counter + vibrato_rate * (1.0 + 440.0/average_freq)), VIBRATO_LUT_LENGTH);
+ return vibrated_freq;
+}
+
+#endif
+
+ISR(TIMER3_COMPA_vect)
+{
+ float freq;
+
+ if (playing_note) {
+ if (voices > 0) {
+ if (polyphony_rate > 0) {
+ if (voices > 1) {
+ voice_place %= voices;
+ if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) {
+ voice_place = (voice_place + 1) % voices;
+ place = 0.0;
+ }
+ }
+
+ #ifdef VIBRATO_ENABLE
+ if (vibrato_strength > 0) {
+ freq = vibrato(frequencies[voice_place]);
+ } else {
+ freq = frequencies[voice_place];
+ }
+ #else
+ freq = frequencies[voice_place];
+ #endif
+ } else {
+ if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440/frequencies[voices - 1]/12/2)) {
+ frequency = frequency * pow(2, 440/frequency/12/2);
+ } else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) {
+ frequency = frequency * pow(2, -440/frequency/12/2);
+ } else {
+ frequency = frequencies[voices - 1];
+ }
+
+ #ifdef VIBRATO_ENABLE
+ if (vibrato_strength > 0) {
+ freq = vibrato(frequency);
+ } else {
+ freq = frequency;
+ }
+ #else
+ freq = frequency;
+ #endif
+ }
+
+ if (envelope_index < 65535) {
+ envelope_index++;
+ }
+
+ freq = voice_envelope(freq);
+
+ if (freq < 30.517578125) {
+ freq = 30.52;
+ }
+
+ TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
+ TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
+ }
+ }
+
+ if (playing_notes) {
+ if (note_frequency > 0) {
+ #ifdef VIBRATO_ENABLE
+ if (vibrato_strength > 0) {
+ freq = vibrato(note_frequency);
+ } else {
+ freq = note_frequency;
+ }
+ #else
+ freq = note_frequency;
+ #endif
+
+ if (envelope_index < 65535) {
+ envelope_index++;
+ }
+ freq = voice_envelope(freq);
+
+ TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
+ TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
+ } else {
+ TIMER_3_PERIOD = 0;
+ TIMER_3_DUTY_CYCLE = 0;
+ }
+
+ note_position++;
+ bool end_of_note = false;
+ if (TIMER_3_PERIOD > 0) {
+ end_of_note = (note_position >= (note_length / TIMER_3_PERIOD * 0xFFFF));
+ } else {
+ end_of_note = (note_position >= (note_length * 0x7FF));
+ }
+
+ if (end_of_note) {
+ current_note++;
+ if (current_note >= notes_count) {
+ if (notes_repeat) {
+ current_note = 0;
+ } else {
+ DISABLE_AUDIO_COUNTER_3_ISR;
+ DISABLE_AUDIO_COUNTER_3_OUTPUT;
+ playing_notes = false;
+ return;
+ }
+ }
+ if (!note_resting && (notes_rest > 0)) {
+ note_resting = true;
+ note_frequency = 0;
+ note_length = notes_rest;
+ current_note--;
+ } else {
+ note_resting = false;
+ envelope_index = 0;
+ note_frequency = (*notes_pointer)[current_note][0];
+ note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
+ }
+
+ note_position = 0;
+ }
+ }
+
+ if (!audio_config.enable) {
+ playing_notes = false;
+ playing_note = false;
+ }
+}
+
+void play_note(float freq, int vol) {
+
+ if (!audio_initialized) {
+ audio_init();
+ }
+
+ if (audio_config.enable && voices < 8) {
+ DISABLE_AUDIO_COUNTER_3_ISR;
+
+ // Cancel notes if notes are playing
+ if (playing_notes)
+ stop_all_notes();
+
+ playing_note = true;
+
+ envelope_index = 0;
+
+ if (freq > 0) {
+ frequencies[voices] = freq;
+ volumes[voices] = vol;
+ voices++;
+ }
+
+ ENABLE_AUDIO_COUNTER_3_ISR;
+ ENABLE_AUDIO_COUNTER_3_OUTPUT;
+ }
+
+}
+
+void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest)
+{
+
+ if (!audio_initialized) {
+ audio_init();
+ }
+
+ if (audio_config.enable) {
+
+ DISABLE_AUDIO_COUNTER_3_ISR;
+
+ // Cancel note if a note is playing
+ if (playing_note)
+ stop_all_notes();
+
+ playing_notes = true;
+
+ notes_pointer = np;
+ notes_count = n_count;
+ notes_repeat = n_repeat;
+ notes_rest = n_rest;
+
+ place = 0;
+ current_note = 0;
+
+ note_frequency = (*notes_pointer)[current_note][0];
+ note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
+ note_position = 0;
+
+
+ ENABLE_AUDIO_COUNTER_3_ISR;
+ ENABLE_AUDIO_COUNTER_3_OUTPUT;
+ }
+
+}
+
+bool is_playing_notes(void) {
+ return playing_notes;
+}
+
+bool is_audio_on(void) {
+ return (audio_config.enable != 0);
+}
+
+void audio_toggle(void) {
+ audio_config.enable ^= 1;
+ eeconfig_update_audio(audio_config.raw);
+ if (audio_config.enable)
+ audio_on_user();
+}
+
+void audio_on(void) {
+ audio_config.enable = 1;
+ eeconfig_update_audio(audio_config.raw);
+ audio_on_user();
+}
+
+void audio_off(void) {
+ audio_config.enable = 0;
+ eeconfig_update_audio(audio_config.raw);
+}
+
+#ifdef VIBRATO_ENABLE
+
+// Vibrato rate functions
+
+void set_vibrato_rate(float rate) {
+ vibrato_rate = rate;
+}
+
+void increase_vibrato_rate(float change) {
+ vibrato_rate *= change;
+}
+
+void decrease_vibrato_rate(float change) {
+ vibrato_rate /= change;
+}
+
+#ifdef VIBRATO_STRENGTH_ENABLE
+
+void set_vibrato_strength(float strength) {
+ vibrato_strength = strength;
+}
+
+void increase_vibrato_strength(float change) {
+ vibrato_strength *= change;
+}
+
+void decrease_vibrato_strength(float change) {
+ vibrato_strength /= change;
+}
+
+#endif /* VIBRATO_STRENGTH_ENABLE */
+
+#endif /* VIBRATO_ENABLE */
+
+// Polyphony functions
+
+void set_polyphony_rate(float rate) {
+ polyphony_rate = rate;
+}
+
+void enable_polyphony() {
+ polyphony_rate = 5;
+}
+
+void disable_polyphony() {
+ polyphony_rate = 0;
+}
+
+void increase_polyphony_rate(float change) {
+ polyphony_rate *= change;
+}
+
+void decrease_polyphony_rate(float change) {
+ polyphony_rate /= change;
+}
+
+// Timbre function
+
+void set_timbre(float timbre) {
+ note_timbre = timbre;
+}
+
+// Tempo functions
+
+void set_tempo(uint8_t tempo) {
+ note_tempo = tempo;
+}
+
+void decrease_tempo(uint8_t tempo_change) {
+ note_tempo += tempo_change;
+}
+
+void increase_tempo(uint8_t tempo_change) {
+ if (note_tempo - tempo_change < 10) {
+ note_tempo = 10;
+ } else {
+ note_tempo -= tempo_change;
+ }
+}
diff --git a/quantum/audio/audio.h b/quantum/audio/audio.h
new file mode 100644
index 000000000..47f326ea0
--- /dev/null
+++ b/quantum/audio/audio.h
@@ -0,0 +1,91 @@
+#ifndef AUDIO_H
+#define AUDIO_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <avr/io.h>
+#include <util/delay.h>
+#include "musical_notes.h"
+#include "song_list.h"
+#include "voices.h"
+#include "quantum.h"
+
+// Largely untested PWM audio mode (doesn't sound as good)
+// #define PWM_AUDIO
+
+// #define VIBRATO_ENABLE
+
+// Enable vibrato strength/amplitude - slows down ISR too much
+// #define VIBRATO_STRENGTH_ENABLE
+
+typedef union {
+ uint8_t raw;
+ struct {
+ bool enable :1;
+ uint8_t level :7;
+ };
+} audio_config_t;
+
+bool is_audio_on(void);
+void audio_toggle(void);
+void audio_on(void);
+void audio_off(void);
+
+// Vibrato rate functions
+
+#ifdef VIBRATO_ENABLE
+
+void set_vibrato_rate(float rate);
+void increase_vibrato_rate(float change);
+void decrease_vibrato_rate(float change);
+
+#ifdef VIBRATO_STRENGTH_ENABLE
+
+void set_vibrato_strength(float strength);
+void increase_vibrato_strength(float change);
+void decrease_vibrato_strength(float change);
+
+#endif
+
+#endif
+
+// Polyphony functions
+
+void set_polyphony_rate(float rate);
+void enable_polyphony(void);
+void disable_polyphony(void);
+void increase_polyphony_rate(float change);
+void decrease_polyphony_rate(float change);
+
+void set_timbre(float timbre);
+void set_tempo(uint8_t tempo);
+
+void increase_tempo(uint8_t tempo_change);
+void decrease_tempo(uint8_t tempo_change);
+
+void audio_init(void);
+
+#ifdef PWM_AUDIO
+void play_sample(uint8_t * s, uint16_t l, bool r);
+#endif
+void play_note(float freq, int vol);
+void stop_note(float freq);
+void stop_all_notes(void);
+void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest);
+
+#define SCALE (int8_t []){ 0 + (12*0), 2 + (12*0), 4 + (12*0), 5 + (12*0), 7 + (12*0), 9 + (12*0), 11 + (12*0), \
+ 0 + (12*1), 2 + (12*1), 4 + (12*1), 5 + (12*1), 7 + (12*1), 9 + (12*1), 11 + (12*1), \
+ 0 + (12*2), 2 + (12*2), 4 + (12*2), 5 + (12*2), 7 + (12*2), 9 + (12*2), 11 + (12*2), \
+ 0 + (12*3), 2 + (12*3), 4 + (12*3), 5 + (12*3), 7 + (12*3), 9 + (12*3), 11 + (12*3), \
+ 0 + (12*4), 2 + (12*4), 4 + (12*4), 5 + (12*4), 7 + (12*4), 9 + (12*4), 11 + (12*4), }
+
+// These macros are used to allow play_notes to play an array of indeterminate
+// length. This works around the limitation of C's sizeof operation on pointers.
+// The global float array for the song must be used here.
+#define NOTE_ARRAY_SIZE(x) ((int16_t)(sizeof(x) / (sizeof(x[0]))))
+#define PLAY_NOTE_ARRAY(note_array, note_repeat, note_rest_style) play_notes(&note_array, NOTE_ARRAY_SIZE((note_array)), (note_repeat), (note_rest_style));
+
+
+bool is_playing_notes(void);
+
+#endif \ No newline at end of file
diff --git a/quantum/audio/audio_pwm.c b/quantum/audio/audio_pwm.c
new file mode 100644
index 000000000..f820eec1b
--- /dev/null
+++ b/quantum/audio/audio_pwm.c
@@ -0,0 +1,643 @@
+#include <stdio.h>
+#include <string.h>
+//#include <math.h>
+#include <avr/pgmspace.h>
+#include <avr/interrupt.h>
+#include <avr/io.h>
+#include "print.h"
+#include "audio.h"
+#include "keymap.h"
+
+#include "eeconfig.h"
+
+#define PI 3.14159265
+
+#define CPU_PRESCALER 8
+
+
+// Timer Abstractions
+
+// TIMSK3 - Timer/Counter #3 Interrupt Mask Register
+// Turn on/off 3A interputs, stopping/enabling the ISR calls
+#define ENABLE_AUDIO_COUNTER_3_ISR TIMSK3 |= _BV(OCIE3A)
+#define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3A)
+
+
+// TCCR3A: Timer/Counter #3 Control Register
+// Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
+#define ENABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A |= _BV(COM3A1);
+#define DISABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A &= ~(_BV(COM3A1) | _BV(COM3A0));
+
+
+#define NOTE_PERIOD ICR3
+#define NOTE_DUTY_CYCLE OCR3A
+
+
+#ifdef PWM_AUDIO
+ #include "wave.h"
+ #define SAMPLE_DIVIDER 39
+ #define SAMPLE_RATE (2000000.0/SAMPLE_DIVIDER/2048)
+ // Resistor value of 1/ (2 * PI * 10nF * (2000000 hertz / SAMPLE_DIVIDER / 10)) for 10nF cap
+
+ float places[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+ uint16_t place_int = 0;
+ bool repeat = true;
+#endif
+
+void delay_us(int count) {
+ while(count--) {
+ _delay_us(1);
+ }
+}
+
+int voices = 0;
+int voice_place = 0;
+float frequency = 0;
+int volume = 0;
+long position = 0;
+
+float frequencies[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+int volumes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+bool sliding = false;
+
+float place = 0;
+
+uint8_t * sample;
+uint16_t sample_length = 0;
+// float freq = 0;
+
+bool playing_notes = false;
+bool playing_note = false;
+float note_frequency = 0;
+float note_length = 0;
+uint8_t note_tempo = TEMPO_DEFAULT;
+float note_timbre = TIMBRE_DEFAULT;
+uint16_t note_position = 0;
+float (* notes_pointer)[][2];
+uint16_t notes_count;
+bool notes_repeat;
+float notes_rest;
+bool note_resting = false;
+
+uint8_t current_note = 0;
+uint8_t rest_counter = 0;
+
+#ifdef VIBRATO_ENABLE
+float vibrato_counter = 0;
+float vibrato_strength = .5;
+float vibrato_rate = 0.125;
+#endif
+
+float polyphony_rate = 0;
+
+static bool audio_initialized = false;
+
+audio_config_t audio_config;
+
+uint16_t envelope_index = 0;
+
+void audio_init() {
+
+ // Check EEPROM
+ if (!eeconfig_is_enabled())
+ {
+ eeconfig_init();
+ }
+ audio_config.raw = eeconfig_read_audio();
+
+ #ifdef PWM_AUDIO
+
+ PLLFRQ = _BV(PDIV2);
+ PLLCSR = _BV(PLLE);
+ while(!(PLLCSR & _BV(PLOCK)));
+ PLLFRQ |= _BV(PLLTM0); /* PCK 48MHz */
+
+ /* Init a fast PWM on Timer4 */
+ TCCR4A = _BV(COM4A0) | _BV(PWM4A); /* Clear OC4A on Compare Match */
+ TCCR4B = _BV(CS40); /* No prescaling => f = PCK/256 = 187500Hz */
+ OCR4A = 0;
+
+ /* Enable the OC4A output */
+ DDRC |= _BV(PORTC6);
+
+ DISABLE_AUDIO_COUNTER_3_ISR; // Turn off 3A interputs
+
+ TCCR3A = 0x0; // Options not needed
+ TCCR3B = _BV(CS31) | _BV(CS30) | _BV(WGM32); // 64th prescaling and CTC
+ OCR3A = SAMPLE_DIVIDER - 1; // Correct count/compare, related to sample playback
+
+ #else
+
+ // Set port PC6 (OC3A and /OC4A) as output
+ DDRC |= _BV(PORTC6);
+
+ DISABLE_AUDIO_COUNTER_3_ISR;
+
+ // TCCR3A / TCCR3B: Timer/Counter #3 Control Registers
+ // Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
+ // Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14 (Period = ICR3, Duty Cycle = OCR3A)
+ // Clock Select (CS3n) = 0b010 = Clock / 8
+ TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
+ TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30);
+
+ #endif
+
+ audio_initialized = true;
+}
+
+void stop_all_notes() {
+ if (!audio_initialized) {
+ audio_init();
+ }
+ voices = 0;
+ #ifdef PWM_AUDIO
+ DISABLE_AUDIO_COUNTER_3_ISR;
+ #else
+ DISABLE_AUDIO_COUNTER_3_ISR;
+ DISABLE_AUDIO_COUNTER_3_OUTPUT;
+ #endif
+
+ playing_notes = false;
+ playing_note = false;
+ frequency = 0;
+ volume = 0;
+
+ for (uint8_t i = 0; i < 8; i++)
+ {
+ frequencies[i] = 0;
+ volumes[i] = 0;
+ }
+}
+
+void stop_note(float freq)
+{
+ if (playing_note) {
+ if (!audio_initialized) {
+ audio_init();
+ }
+ #ifdef PWM_AUDIO
+ freq = freq / SAMPLE_RATE;
+ #endif
+ for (int i = 7; i >= 0; i--) {
+ if (frequencies[i] == freq) {
+ frequencies[i] = 0;
+ volumes[i] = 0;
+ for (int j = i; (j < 7); j++) {
+ frequencies[j] = frequencies[j+1];
+ frequencies[j+1] = 0;
+ volumes[j] = volumes[j+1];
+ volumes[j+1] = 0;
+ }
+ break;
+ }
+ }
+ voices--;
+ if (voices < 0)
+ voices = 0;
+ if (voice_place >= voices) {
+ voice_place = 0;
+ }
+ if (voices == 0) {
+ #ifdef PWM_AUDIO
+ DISABLE_AUDIO_COUNTER_3_ISR;
+ #else
+ DISABLE_AUDIO_COUNTER_3_ISR;
+ DISABLE_AUDIO_COUNTER_3_OUTPUT;
+ #endif
+ frequency = 0;
+ volume = 0;
+ playing_note = false;
+ }
+ }
+}
+
+#ifdef VIBRATO_ENABLE
+
+float mod(float a, int b)
+{
+ float r = fmod(a, b);
+ return r < 0 ? r + b : r;
+}
+
+float vibrato(float average_freq) {
+ #ifdef VIBRATO_STRENGTH_ENABLE
+ float vibrated_freq = average_freq * pow(vibrato_lut[(int)vibrato_counter], vibrato_strength);
+ #else
+ float vibrated_freq = average_freq * vibrato_lut[(int)vibrato_counter];
+ #endif
+ vibrato_counter = mod((vibrato_counter + vibrato_rate * (1.0 + 440.0/average_freq)), VIBRATO_LUT_LENGTH);
+ return vibrated_freq;
+}
+
+#endif
+
+ISR(TIMER3_COMPA_vect)
+{
+ if (playing_note) {
+ #ifdef PWM_AUDIO
+ if (voices == 1) {
+ // SINE
+ OCR4A = pgm_read_byte(&sinewave[(uint16_t)place]) >> 2;
+
+ // SQUARE
+ // if (((int)place) >= 1024){
+ // OCR4A = 0xFF >> 2;
+ // } else {
+ // OCR4A = 0x00;
+ // }
+
+ // SAWTOOTH
+ // OCR4A = (int)place / 4;
+
+ // TRIANGLE
+ // if (((int)place) >= 1024) {
+ // OCR4A = (int)place / 2;
+ // } else {
+ // OCR4A = 2048 - (int)place / 2;
+ // }
+
+ place += frequency;
+
+ if (place >= SINE_LENGTH)
+ place -= SINE_LENGTH;
+
+ } else {
+ int sum = 0;
+ for (int i = 0; i < voices; i++) {
+ // SINE
+ sum += pgm_read_byte(&sinewave[(uint16_t)places[i]]) >> 2;
+
+ // SQUARE
+ // if (((int)places[i]) >= 1024){
+ // sum += 0xFF >> 2;
+ // } else {
+ // sum += 0x00;
+ // }
+
+ places[i] += frequencies[i];
+
+ if (places[i] >= SINE_LENGTH)
+ places[i] -= SINE_LENGTH;
+ }
+ OCR4A = sum;
+ }
+ #else
+ if (voices > 0) {
+ float freq;
+ if (polyphony_rate > 0) {
+ if (voices > 1) {
+ voice_place %= voices;
+ if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) {
+ voice_place = (voice_place + 1) % voices;
+ place = 0.0;
+ }
+ }
+ #ifdef VIBRATO_ENABLE
+ if (vibrato_strength > 0) {
+ freq = vibrato(frequencies[voice_place]);
+ } else {
+ #else
+ {
+ #endif
+ freq = frequencies[voice_place];
+ }
+ } else {
+ if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440/frequencies[voices - 1]/12/2)) {
+ frequency = frequency * pow(2, 440/frequency/12/2);
+ } else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) {
+ frequency = frequency * pow(2, -440/frequency/12/2);
+ } else {
+ frequency = frequencies[voices - 1];
+ }
+
+
+ #ifdef VIBRATO_ENABLE
+ if (vibrato_strength > 0) {
+ freq = vibrato(frequency);
+ } else {
+ #else
+ {
+ #endif
+ freq = frequency;
+ }
+ }
+
+ if (envelope_index < 65535) {
+ envelope_index++;
+ }
+ freq = voice_envelope(freq);
+
+ if (freq < 30.517578125)
+ freq = 30.52;
+ NOTE_PERIOD = (int)(((double)F_CPU) / (freq * CPU_PRESCALER)); // Set max to the period
+ NOTE_DUTY_CYCLE = (int)((((double)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre); // Set compare to half the period
+ }
+ #endif
+ }
+
+ // SAMPLE
+ // OCR4A = pgm_read_byte(&sample[(uint16_t)place_int]);
+
+ // place_int++;
+
+ // if (place_int >= sample_length)
+ // if (repeat)
+ // place_int -= sample_length;
+ // else
+ // DISABLE_AUDIO_COUNTER_3_ISR;
+
+
+ if (playing_notes) {
+ #ifdef PWM_AUDIO
+ OCR4A = pgm_read_byte(&sinewave[(uint16_t)place]) >> 0;
+
+ place += note_frequency;
+ if (place >= SINE_LENGTH)
+ place -= SINE_LENGTH;
+ #else
+ if (note_frequency > 0) {
+ float freq;
+
+ #ifdef VIBRATO_ENABLE
+ if (vibrato_strength > 0) {
+ freq = vibrato(note_frequency);
+ } else {
+ #else
+ {
+ #endif
+ freq = note_frequency;
+ }
+
+ if (envelope_index < 65535) {
+ envelope_index++;
+ }
+ freq = voice_envelope(freq);
+
+ NOTE_PERIOD = (int)(((double)F_CPU) / (freq * CPU_PRESCALER)); // Set max to the period
+ NOTE_DUTY_CYCLE = (int)((((double)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre); // Set compare to half the period
+ } else {
+ NOTE_PERIOD = 0;
+ NOTE_DUTY_CYCLE = 0;
+ }
+ #endif
+
+
+ note_position++;
+ bool end_of_note = false;
+ if (NOTE_PERIOD > 0)
+ end_of_note = (note_position >= (note_length / NOTE_PERIOD * 0xFFFF));
+ else
+ end_of_note = (note_position >= (note_length * 0x7FF));
+ if (end_of_note) {
+ current_note++;
+ if (current_note >= notes_count) {
+ if (notes_repeat) {
+ current_note = 0;
+ } else {
+ #ifdef PWM_AUDIO
+ DISABLE_AUDIO_COUNTER_3_ISR;
+ #else
+ DISABLE_AUDIO_COUNTER_3_ISR;
+ DISABLE_AUDIO_COUNTER_3_OUTPUT;
+ #endif
+ playing_notes = false;
+ return;
+ }
+ }
+ if (!note_resting && (notes_rest > 0)) {
+ note_resting = true;
+ note_frequency = 0;
+ note_length = notes_rest;
+ current_note--;
+ } else {
+ note_resting = false;
+ #ifdef PWM_AUDIO
+ note_frequency = (*notes_pointer)[current_note][0] / SAMPLE_RATE;
+ note_length = (*notes_pointer)[current_note][1] * (((float)note_tempo) / 100);
+ #else
+ envelope_index = 0;
+ note_frequency = (*notes_pointer)[current_note][0];
+ note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
+ #endif
+ }
+ note_position = 0;
+ }
+
+ }
+
+ if (!audio_config.enable) {
+ playing_notes = false;
+ playing_note = false;
+ }
+}
+
+void play_note(float freq, int vol) {
+
+ if (!audio_initialized) {
+ audio_init();
+ }
+
+ if (audio_config.enable && voices < 8) {
+ DISABLE_AUDIO_COUNTER_3_ISR;
+
+ // Cancel notes if notes are playing
+ if (playing_notes)
+ stop_all_notes();
+
+ playing_note = true;
+
+ envelope_index = 0;
+
+ #ifdef PWM_AUDIO
+ freq = freq / SAMPLE_RATE;
+ #endif
+ if (freq > 0) {
+ frequencies[voices] = freq;
+ volumes[voices] = vol;
+ voices++;
+ }
+
+ #ifdef PWM_AUDIO
+ ENABLE_AUDIO_COUNTER_3_ISR;
+ #else
+ ENABLE_AUDIO_COUNTER_3_ISR;
+ ENABLE_AUDIO_COUNTER_3_OUTPUT;
+ #endif
+ }
+
+}
+
+void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest)
+{
+
+ if (!audio_initialized) {
+ audio_init();
+ }
+
+ if (audio_config.enable) {
+
+ DISABLE_AUDIO_COUNTER_3_ISR;
+
+ // Cancel note if a note is playing
+ if (playing_note)
+ stop_all_notes();
+
+ playing_notes = true;
+
+ notes_pointer = np;
+ notes_count = n_count;
+ notes_repeat = n_repeat;
+ notes_rest = n_rest;
+
+ place = 0;
+ current_note = 0;
+
+ #ifdef PWM_AUDIO
+ note_frequency = (*notes_pointer)[current_note][0] / SAMPLE_RATE;
+ note_length = (*notes_pointer)[current_note][1] * (((float)note_tempo) / 100);
+ #else
+ note_frequency = (*notes_pointer)[current_note][0];
+ note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
+ #endif
+ note_position = 0;
+
+
+ #ifdef PWM_AUDIO
+ ENABLE_AUDIO_COUNTER_3_ISR;
+ #else
+ ENABLE_AUDIO_COUNTER_3_ISR;
+ ENABLE_AUDIO_COUNTER_3_OUTPUT;
+ #endif
+ }
+
+}
+
+#ifdef PWM_AUDIO
+void play_sample(uint8_t * s, uint16_t l, bool r) {
+ if (!audio_initialized) {
+ audio_init();
+ }
+
+ if (audio_config.enable) {
+ DISABLE_AUDIO_COUNTER_3_ISR;
+ stop_all_notes();
+ place_int = 0;
+ sample = s;
+ sample_length = l;
+ repeat = r;
+
+ ENABLE_AUDIO_COUNTER_3_ISR;
+ }
+}
+#endif
+
+
+void audio_toggle(void) {
+ audio_config.enable ^= 1;
+ eeconfig_update_audio(audio_config.raw);
+}
+
+void audio_on(void) {
+ audio_config.enable = 1;
+ eeconfig_update_audio(audio_config.raw);
+}
+
+void audio_off(void) {
+ audio_config.enable = 0;
+ eeconfig_update_audio(audio_config.raw);
+}
+
+#ifdef VIBRATO_ENABLE
+
+// Vibrato rate functions
+
+void set_vibrato_rate(float rate) {
+ vibrato_rate = rate;
+}
+
+void increase_vibrato_rate(float change) {
+ vibrato_rate *= change;
+}
+
+void decrease_vibrato_rate(float change) {
+ vibrato_rate /= change;
+}
+
+#ifdef VIBRATO_STRENGTH_ENABLE
+
+void set_vibrato_strength(float strength) {
+ vibrato_strength = strength;
+}
+
+void increase_vibrato_strength(float change) {
+ vibrato_strength *= change;
+}
+
+void decrease_vibrato_strength(float change) {
+ vibrato_strength /= change;
+}
+
+#endif /* VIBRATO_STRENGTH_ENABLE */
+
+#endif /* VIBRATO_ENABLE */
+
+// Polyphony functions
+
+void set_polyphony_rate(float rate) {
+ polyphony_rate = rate;
+}
+
+void enable_polyphony() {
+ polyphony_rate = 5;
+}
+
+void disable_polyphony() {
+ polyphony_rate = 0;
+}
+
+void increase_polyphony_rate(float change) {
+ polyphony_rate *= change;
+}
+
+void decrease_polyphony_rate(float change) {
+ polyphony_rate /= change;
+}
+
+// Timbre function
+
+void set_timbre(float timbre) {
+ note_timbre = timbre;
+}
+
+// Tempo functions
+
+void set_tempo(uint8_t tempo) {
+ note_tempo = tempo;
+}
+
+void decrease_tempo(uint8_t tempo_change) {
+ note_tempo += tempo_change;
+}
+
+void increase_tempo(uint8_t tempo_change) {
+ if (note_tempo - tempo_change < 10) {
+ note_tempo = 10;
+ } else {
+ note_tempo -= tempo_change;
+ }
+}
+
+
+//------------------------------------------------------------------------------
+// Override these functions in your keymap file to play different tunes on
+// startup and bootloader jump
+__attribute__ ((weak))
+void play_startup_tone()
+{
+}
+
+__attribute__ ((weak))
+void play_goodbye_tone()
+{
+}
+//------------------------------------------------------------------------------
diff --git a/quantum/audio/luts.c b/quantum/audio/luts.c
new file mode 100644
index 000000000..9f3de9a05
--- /dev/null
+++ b/quantum/audio/luts.c
@@ -0,0 +1,382 @@
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/pgmspace.h>
+#include "luts.h"
+
+const float vibrato_lut[VIBRATO_LUT_LENGTH] =
+{
+ 1.0022336811487,
+ 1.0042529943610,
+ 1.0058584256028,
+ 1.0068905285205,
+ 1.0072464122237,
+ 1.0068905285205,
+ 1.0058584256028,
+ 1.0042529943610,
+ 1.0022336811487,
+ 1.0000000000000,
+ 0.9977712970630,
+ 0.9957650169978,
+ 0.9941756956510,
+ 0.9931566259436,
+ 0.9928057204913,
+ 0.9931566259436,
+ 0.9941756956510,
+ 0.9957650169978,
+ 0.9977712970630,
+ 1.0000000000000,
+};
+
+const uint16_t frequency_lut[FREQUENCY_LUT_LENGTH] =
+{
+ 0x8E0B,
+ 0x8C02,
+ 0x8A00,
+ 0x8805,
+ 0x8612,
+ 0x8426,
+ 0x8241,
+ 0x8063,
+ 0x7E8C,
+ 0x7CBB,
+ 0x7AF2,
+ 0x792E,
+ 0x7772,
+ 0x75BB,
+ 0x740B,
+ 0x7261,
+ 0x70BD,
+ 0x6F20,
+ 0x6D88,
+ 0x6BF6,
+ 0x6A69,
+ 0x68E3,
+ 0x6762,
+ 0x65E6,
+ 0x6470,
+ 0x6300,
+ 0x6194,
+ 0x602E,
+ 0x5ECD,
+ 0x5D71,
+ 0x5C1A,
+ 0x5AC8,
+ 0x597B,
+ 0x5833,
+ 0x56EF,
+ 0x55B0,
+ 0x5475,
+ 0x533F,
+ 0x520E,
+ 0x50E1,
+ 0x4FB8,
+ 0x4E93,
+ 0x4D73,
+ 0x4C57,
+ 0x4B3E,
+ 0x4A2A,
+ 0x491A,
+ 0x480E,
+ 0x4705,
+ 0x4601,
+ 0x4500,
+ 0x4402,
+ 0x4309,
+ 0x4213,
+ 0x4120,
+ 0x4031,
+ 0x3F46,
+ 0x3E5D,
+ 0x3D79,
+ 0x3C97,
+ 0x3BB9,
+ 0x3ADD,
+ 0x3A05,
+ 0x3930,
+ 0x385E,
+ 0x3790,
+ 0x36C4,
+ 0x35FB,
+ 0x3534,
+ 0x3471,
+ 0x33B1,
+ 0x32F3,
+ 0x3238,
+ 0x3180,
+ 0x30CA,
+ 0x3017,
+ 0x2F66,
+ 0x2EB8,
+ 0x2E0D,
+ 0x2D64,
+ 0x2CBD,
+ 0x2C19,
+ 0x2B77,
+ 0x2AD8,
+ 0x2A3A,
+ 0x299F,
+ 0x2907,
+ 0x2870,
+ 0x27DC,
+ 0x2749,
+ 0x26B9,
+ 0x262B,
+ 0x259F,
+ 0x2515,
+ 0x248D,
+ 0x2407,
+ 0x2382,
+ 0x2300,
+ 0x2280,
+ 0x2201,
+ 0x2184,
+ 0x2109,
+ 0x2090,
+ 0x2018,
+ 0x1FA3,
+ 0x1F2E,
+ 0x1EBC,
+ 0x1E4B,
+ 0x1DDC,
+ 0x1D6E,
+ 0x1D02,
+ 0x1C98,
+ 0x1C2F,
+ 0x1BC8,
+ 0x1B62,
+ 0x1AFD,
+ 0x1A9A,
+ 0x1A38,
+ 0x19D8,
+ 0x1979,
+ 0x191C,
+ 0x18C0,
+ 0x1865,
+ 0x180B,
+ 0x17B3,
+ 0x175C,
+ 0x1706,
+ 0x16B2,
+ 0x165E,
+ 0x160C,
+ 0x15BB,
+ 0x156C,
+ 0x151D,
+ 0x14CF,
+ 0x1483,
+ 0x1438,
+ 0x13EE,
+ 0x13A4,
+ 0x135C,
+ 0x1315,
+ 0x12CF,
+ 0x128A,
+ 0x1246,
+ 0x1203,
+ 0x11C1,
+ 0x1180,
+ 0x1140,
+ 0x1100,
+ 0x10C2,
+ 0x1084,
+ 0x1048,
+ 0x100C,
+ 0xFD1,
+ 0xF97,
+ 0xF5E,
+ 0xF25,
+ 0xEEE,
+ 0xEB7,
+ 0xE81,
+ 0xE4C,
+ 0xE17,
+ 0xDE4,
+ 0xDB1,
+ 0xD7E,
+ 0xD4D,
+ 0xD1C,
+ 0xCEC,
+ 0xCBC,
+ 0xC8E,
+ 0xC60,
+ 0xC32,
+ 0xC05,
+ 0xBD9,
+ 0xBAE,
+ 0xB83,
+ 0xB59,
+ 0xB2F,
+ 0xB06,
+ 0xADD,
+ 0xAB6,
+ 0xA8E,
+ 0xA67,
+ 0xA41,
+ 0xA1C,
+ 0x9F7,
+ 0x9D2,
+ 0x9AE,
+ 0x98A,
+ 0x967,
+ 0x945,
+ 0x923,
+ 0x901,
+ 0x8E0,
+ 0x8C0,
+ 0x8A0,
+ 0x880,
+ 0x861,
+ 0x842,
+ 0x824,
+ 0x806,
+ 0x7E8,
+ 0x7CB,
+ 0x7AF,
+ 0x792,
+ 0x777,
+ 0x75B,
+ 0x740,
+ 0x726,
+ 0x70B,
+ 0x6F2,
+ 0x6D8,
+ 0x6BF,
+ 0x6A6,
+ 0x68E,
+ 0x676,
+ 0x65E,
+ 0x647,
+ 0x630,
+ 0x619,
+ 0x602,
+ 0x5EC,
+ 0x5D7,
+ 0x5C1,
+ 0x5AC,
+ 0x597,
+ 0x583,
+ 0x56E,
+ 0x55B,
+ 0x547,
+ 0x533,
+ 0x520,
+ 0x50E,
+ 0x4FB,
+ 0x4E9,
+ 0x4D7,
+ 0x4C5,
+ 0x4B3,
+ 0x4A2,
+ 0x491,
+ 0x480,
+ 0x470,
+ 0x460,
+ 0x450,
+ 0x440,
+ 0x430,
+ 0x421,
+ 0x412,
+ 0x403,
+ 0x3F4,
+ 0x3E5,
+ 0x3D7,
+ 0x3C9,
+ 0x3BB,
+ 0x3AD,
+ 0x3A0,
+ 0x393,
+ 0x385,
+ 0x379,
+ 0x36C,
+ 0x35F,
+ 0x353,
+ 0x347,
+ 0x33B,
+ 0x32F,
+ 0x323,
+ 0x318,
+ 0x30C,
+ 0x301,
+ 0x2F6,
+ 0x2EB,
+ 0x2E0,
+ 0x2D6,
+ 0x2CB,
+ 0x2C1,
+ 0x2B7,
+ 0x2AD,
+ 0x2A3,
+ 0x299,
+ 0x290,
+ 0x287,
+ 0x27D,
+ 0x274,
+ 0x26B,
+ 0x262,
+ 0x259,
+ 0x251,
+ 0x248,
+ 0x240,
+ 0x238,
+ 0x230,
+ 0x228,
+ 0x220,
+ 0x218,
+ 0x210,
+ 0x209,
+ 0x201,
+ 0x1FA,
+ 0x1F2,
+ 0x1EB,
+ 0x1E4,
+ 0x1DD,
+ 0x1D6,
+ 0x1D0,
+ 0x1C9,
+ 0x1C2,
+ 0x1BC,
+ 0x1B6,
+ 0x1AF,
+ 0x1A9,
+ 0x1A3,
+ 0x19D,
+ 0x197,
+ 0x191,
+ 0x18C,
+ 0x186,
+ 0x180,
+ 0x17B,
+ 0x175,
+ 0x170,
+ 0x16B,
+ 0x165,
+ 0x160,
+ 0x15B,
+ 0x156,
+ 0x151,
+ 0x14C,
+ 0x148,
+ 0x143,
+ 0x13E,
+ 0x13A,
+ 0x135,
+ 0x131,
+ 0x12C,
+ 0x128,
+ 0x124,
+ 0x120,
+ 0x11C,
+ 0x118,
+ 0x114,
+ 0x110,
+ 0x10C,
+ 0x108,
+ 0x104,
+ 0x100,
+ 0xFD,
+ 0xF9,
+ 0xF5,
+ 0xF2,
+ 0xEE,
+};
+
diff --git a/quantum/audio/luts.h b/quantum/audio/luts.h
new file mode 100644
index 000000000..7df3078a7
--- /dev/null
+++ b/quantum/audio/luts.h
@@ -0,0 +1,15 @@
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/pgmspace.h>
+
+#ifndef LUTS_H
+#define LUTS_H
+
+#define VIBRATO_LUT_LENGTH 20
+
+#define FREQUENCY_LUT_LENGTH 349
+
+extern const float vibrato_lut[VIBRATO_LUT_LENGTH];
+extern const uint16_t frequency_lut[FREQUENCY_LUT_LENGTH];
+
+#endif /* LUTS_H */ \ No newline at end of file
diff --git a/quantum/audio/musical_notes.h b/quantum/audio/musical_notes.h
new file mode 100644
index 000000000..b08d16a6f
--- /dev/null
+++ b/quantum/audio/musical_notes.h
@@ -0,0 +1,217 @@
+#ifndef MUSICAL_NOTES_H
+#define MUSICAL_NOTES_H
+
+// Tempo Placeholder
+#define TEMPO_DEFAULT 100
+
+
+#define SONG(notes...) { notes }
+
+
+// Note Types
+#define MUSICAL_NOTE(note, duration) {(NOTE##note), duration}
+#define WHOLE_NOTE(note) MUSICAL_NOTE(note, 64)
+#define HALF_NOTE(note) MUSICAL_NOTE(note, 32)
+#define QUARTER_NOTE(note) MUSICAL_NOTE(note, 16)
+#define EIGHTH_NOTE(note) MUSICAL_NOTE(note, 8)
+#define SIXTEENTH_NOTE(note) MUSICAL_NOTE(note, 4)
+
+#define WHOLE_DOT_NOTE(note) MUSICAL_NOTE(note, 64+32)
+#define HALF_DOT_NOTE(note) MUSICAL_NOTE(note, 32+16)
+#define QUARTER_DOT_NOTE(note) MUSICAL_NOTE(note, 16+8)
+#define EIGHTH_DOT_NOTE(note) MUSICAL_NOTE(note, 8+4)
+#define SIXTEENTH_DOT_NOTE(note) MUSICAL_NOTE(note, 4+2)
+
+// Note Type Shortcuts
+#define M__NOTE(note, duration) MUSICAL_NOTE(note, duration)
+#define W__NOTE(n) WHOLE_NOTE(n)
+#define H__NOTE(n) HALF_NOTE(n)
+#define Q__NOTE(n) QUARTER_NOTE(n)
+#define E__NOTE(n) EIGHTH_NOTE(n)
+#define S__NOTE(n) SIXTEENTH_NOTE(n)
+#define WD_NOTE(n) WHOLE_DOT_NOTE(n)
+#define HD_NOTE(n) HALF_DOT_NOTE(n)
+#define QD_NOTE(n) QUARTER_DOT_NOTE(n)
+#define ED_NOTE(n) EIGHTH_DOT_NOTE(n)
+#define SD_NOTE(n) SIXTEENTH_DOT_NOTE(n)
+
+// Note Styles
+// Staccato makes sure there is a rest between each note. Think: TA TA TA
+// Legato makes notes flow together. Think: TAAA
+#define STACCATO 0.01
+#define LEGATO 0
+
+// Note Timbre
+// Changes how the notes sound
+#define TIMBRE_12 0.125
+#define TIMBRE_25 0.250
+#define TIMBRE_50 0.500
+#define TIMBRE_75 0.750
+#define TIMBRE_DEFAULT TIMBRE_50
+
+
+// Notes - # = Octave
+
+#define NOTE_REST 0.00
+
+/* These notes are currently bugged
+#define NOTE_C0 16.35
+#define NOTE_CS0 17.32
+#define NOTE_D0 18.35
+#define NOTE_DS0 19.45
+#define NOTE_E0 20.60
+#define NOTE_F0 21.83
+#define NOTE_FS0 23.12
+#define NOTE_G0 24.50
+#define NOTE_GS0 25.96
+#define NOTE_A0 27.50
+#define NOTE_AS0 29.14
+#define NOTE_B0 30.87
+#define NOTE_C1 32.70
+#define NOTE_CS1 34.65
+#define NOTE_D1 36.71
+#define NOTE_DS1 38.89
+#define NOTE_E1 41.20
+#define NOTE_F1 43.65
+#define NOTE_FS1 46.25
+#define NOTE_G1 49.00
+#define NOTE_GS1 51.91
+#define NOTE_A1 55.00
+#define NOTE_AS1 58.27
+*/
+
+#define NOTE_B1 61.74
+#define NOTE_C2 65.41
+#define NOTE_CS2 69.30
+#define NOTE_D2 73.42
+#define NOTE_DS2 77.78
+#define NOTE_E2 82.41
+#define NOTE_F2 87.31
+#define NOTE_FS2 92.50
+#define NOTE_G2 98.00
+#define NOTE_GS2 103.83
+#define NOTE_A2 110.00
+#define NOTE_AS2 116.54
+#define NOTE_B2 123.47
+#define NOTE_C3 130.81
+#define NOTE_CS3 138.59
+#define NOTE_D3 146.83
+#define NOTE_DS3 155.56
+#define NOTE_E3 164.81
+#define NOTE_F3 174.61
+#define NOTE_FS3 185.00
+#define NOTE_G3 196.00
+#define NOTE_GS3 207.65
+#define NOTE_A3 220.00
+#define NOTE_AS3 233.08
+#define NOTE_B3 246.94
+#define NOTE_C4 261.63
+#define NOTE_CS4 277.18
+#define NOTE_D4 293.66
+#define NOTE_DS4 311.13
+#define NOTE_E4 329.63
+#define NOTE_F4 349.23
+#define NOTE_FS4 369.99
+#define NOTE_G4 392.00
+#define NOTE_GS4 415.30
+#define NOTE_A4 440.00
+#define NOTE_AS4 466.16
+#define NOTE_B4 493.88
+#define NOTE_C5 523.25
+#define NOTE_CS5 554.37
+#define NOTE_D5 587.33
+#define NOTE_DS5 622.25
+#define NOTE_E5 659.26
+#define NOTE_F5 698.46
+#define NOTE_FS5 739.99
+#define NOTE_G5 783.99
+#define NOTE_GS5 830.61
+#define NOTE_A5 880.00
+#define NOTE_AS5 932.33
+#define NOTE_B5 987.77
+#define NOTE_C6 1046.50
+#define NOTE_CS6 1108.73
+#define NOTE_D6 1174.66
+#define NOTE_DS6 1244.51
+#define NOTE_E6 1318.51
+#define NOTE_F6 1396.91
+#define NOTE_FS6 1479.98
+#define NOTE_G6 1567.98
+#define NOTE_GS6 1661.22
+#define NOTE_A6 1760.00
+#define NOTE_AS6 1864.66
+#define NOTE_B6 1975.53
+#define NOTE_C7 2093.00
+#define NOTE_CS7 2217.46
+#define NOTE_D7 2349.32
+#define NOTE_DS7 2489.02
+#define NOTE_E7 2637.02
+#define NOTE_F7 2793.83
+#define NOTE_FS7 2959.96
+#define NOTE_G7 3135.96
+#define NOTE_GS7 3322.44
+#define NOTE_A7 3520.00
+#define NOTE_AS7 3729.31
+#define NOTE_B7 3951.07
+#define NOTE_C8 4186.01
+#define NOTE_CS8 4434.92
+#define NOTE_D8 4698.64
+#define NOTE_DS8 4978.03
+#define NOTE_E8 5274.04
+#define NOTE_F8 5587.65
+#define NOTE_FS8 5919.91
+#define NOTE_G8 6271.93
+#define NOTE_GS8 6644.88
+#define NOTE_A8 7040.00
+#define NOTE_AS8 7458.62
+#define NOTE_B8 7902.13
+
+// Flat Aliases
+#define NOTE_DF0 NOTE_CS0
+#define NOTE_EF0 NOTE_DS0
+#define NOTE_GF0 NOTE_FS0
+#define NOTE_AF0 NOTE_GS0
+#define NOTE_BF0 NOTE_AS0
+#define NOTE_DF1 NOTE_CS1
+#define NOTE_EF1 NOTE_DS1
+#define NOTE_GF1 NOTE_FS1
+#define NOTE_AF1 NOTE_GS1
+#define NOTE_BF1 NOTE_AS1
+#define NOTE_DF2 NOTE_CS2
+#define NOTE_EF2 NOTE_DS2
+#define NOTE_GF2 NOTE_FS2
+#define NOTE_AF2 NOTE_GS2
+#define NOTE_BF2 NOTE_AS2
+#define NOTE_DF3 NOTE_CS3
+#define NOTE_EF3 NOTE_DS3
+#define NOTE_GF3 NOTE_FS3
+#define NOTE_AF3 NOTE_GS3
+#define NOTE_BF3 NOTE_AS3
+#define NOTE_DF4 NOTE_CS4
+#define NOTE_EF4 NOTE_DS4
+#define NOTE_GF4 NOTE_FS4
+#define NOTE_AF4 NOTE_GS4
+#define NOTE_BF4 NOTE_AS4
+#define NOTE_DF5 NOTE_CS5
+#define NOTE_EF5 NOTE_DS5
+#define NOTE_GF5 NOTE_FS5
+#define NOTE_AF5 NOTE_GS5
+#define NOTE_BF5 NOTE_AS5
+#define NOTE_DF6 NOTE_CS6
+#define NOTE_EF6 NOTE_DS6
+#define NOTE_GF6 NOTE_FS6
+#define NOTE_AF6 NOTE_GS6
+#define NOTE_BF6 NOTE_AS6
+#define NOTE_DF7 NOTE_CS7
+#define NOTE_EF7 NOTE_DS7
+#define NOTE_GF7 NOTE_FS7
+#define NOTE_AF7 NOTE_GS7
+#define NOTE_BF7 NOTE_AS7
+#define NOTE_DF8 NOTE_CS8
+#define NOTE_EF8 NOTE_DS8
+#define NOTE_GF8 NOTE_FS8
+#define NOTE_AF8 NOTE_GS8
+#define NOTE_BF8 NOTE_AS8
+
+
+#endif \ No newline at end of file
diff --git a/quantum/audio/song_list.h b/quantum/audio/song_list.h
new file mode 100644
index 000000000..fc6fcdeef
--- /dev/null
+++ b/quantum/audio/song_list.h
@@ -0,0 +1,117 @@
+#include "musical_notes.h"
+
+#ifndef SONG_LIST_H
+#define SONG_LIST_H
+
+#define ODE_TO_JOY \
+ Q__NOTE(_E4), Q__NOTE(_E4), Q__NOTE(_F4), Q__NOTE(_G4), \
+ Q__NOTE(_G4), Q__NOTE(_F4), Q__NOTE(_E4), Q__NOTE(_D4), \
+ Q__NOTE(_C4), Q__NOTE(_C4), Q__NOTE(_D4), Q__NOTE(_E4), \
+ QD_NOTE(_E4), E__NOTE(_D4), H__NOTE(_D4),
+
+#define ROCK_A_BYE_BABY \
+ QD_NOTE(_B4), E__NOTE(_D4), Q__NOTE(_B5), \
+ H__NOTE(_A5), Q__NOTE(_G5), \
+ QD_NOTE(_B4), E__NOTE(_D5), Q__NOTE(_G5), \
+ H__NOTE(_FS5),
+
+#define CLOSE_ENCOUNTERS_5_NOTE \
+ Q__NOTE(_D5), \
+ Q__NOTE(_E5), \
+ Q__NOTE(_C5), \
+ Q__NOTE(_C4), \
+ Q__NOTE(_G4),
+
+#define DOE_A_DEER \
+ QD_NOTE(_C4), E__NOTE(_D4), \
+ QD_NOTE(_E4), E__NOTE(_C4), \
+ Q__NOTE(_E4), Q__NOTE(_C4), \
+ Q__NOTE(_E4),
+
+#define GOODBYE_SOUND \
+ E__NOTE(_E7), \
+ E__NOTE(_A6), \
+ ED_NOTE(_E6),
+
+#define STARTUP_SOUND \
+ ED_NOTE(_E7 ), \
+ E__NOTE(_CS7), \
+ E__NOTE(_E6 ), \
+ E__NOTE(_A6 ), \
+ M__NOTE(_CS7, 20),
+
+#define QWERTY_SOUND \
+ E__NOTE(_GS6 ), \
+ E__NOTE(_A6 ), \
+ S__NOTE(_REST), \
+ Q__NOTE(_E7 ),
+
+#define COLEMAK_SOUND \
+ E__NOTE(_GS6 ), \
+ E__NOTE(_A6 ), \
+ S__NOTE(_REST), \
+ ED_NOTE(_E7 ), \
+ S__NOTE(_REST), \
+ ED_NOTE(_GS7 ),
+
+#define DVORAK_SOUND \
+ E__NOTE(_GS6 ), \
+ E__NOTE(_A6 ), \
+ S__NOTE(_REST), \
+ E__NOTE(_E7 ), \
+ S__NOTE(_REST), \
+ E__NOTE(_FS7 ), \
+ S__NOTE(_REST), \
+ E__NOTE(_E7 ),
+
+#define PLOVER_SOUND \
+ E__NOTE(_GS6 ), \
+ E__NOTE(_A6 ), \
+ S__NOTE(_REST), \
+ ED_NOTE(_E7 ), \
+ S__NOTE(_REST), \
+ ED_NOTE(_A7 ),
+
+#define PLOVER_GOODBYE_SOUND \
+ E__NOTE(_GS6 ), \
+ E__NOTE(_A6 ), \
+ S__NOTE(_REST), \
+ ED_NOTE(_A7 ), \
+ S__NOTE(_REST), \
+ ED_NOTE(_E7 ),
+
+#define MUSIC_SCALE_SOUND \
+ E__NOTE(_A5 ), \
+ E__NOTE(_B5 ), \
+ E__NOTE(_CS6), \
+ E__NOTE(_D6 ), \
+ E__NOTE(_E6 ), \
+ E__NOTE(_FS6), \
+ E__NOTE(_GS6), \
+ E__NOTE(_A6 ),
+
+#define CAPS_LOCK_ON_SOUND \
+ E__NOTE(_A3), \
+ E__NOTE(_B3),
+
+#define CAPS_LOCK_OFF_SOUND \
+ E__NOTE(_B3), \
+ E__NOTE(_A3),
+
+#define SCROLL_LOCK_ON_SOUND \
+ E__NOTE(_D4), \
+ E__NOTE(_E4),
+
+#define SCROLL_LOCK_OFF_SOUND \
+ E__NOTE(_E4), \
+ E__NOTE(_D4),
+
+#define NUM_LOCK_ON_SOUND \
+ E__NOTE(_D5), \
+ E__NOTE(_E5),
+
+#define NUM_LOCK_OFF_SOUND \
+ E__NOTE(_E5), \
+ E__NOTE(_D5),
+
+#endif
diff --git a/quantum/audio/voices.c b/quantum/audio/voices.c
new file mode 100644
index 000000000..6d4172a06
--- /dev/null
+++ b/quantum/audio/voices.c
@@ -0,0 +1,165 @@
+#include "voices.h"
+#include "audio.h"
+#include "stdlib.h"
+
+// these are imported from audio.c
+extern uint16_t envelope_index;
+extern float note_timbre;
+extern float polyphony_rate;
+
+voice_type voice = default_voice;
+
+void set_voice(voice_type v) {
+ voice = v;
+}
+
+void voice_iterate() {
+ voice = (voice + 1) % number_of_voices;
+}
+
+void voice_deiterate() {
+ voice = (voice - 1) % number_of_voices;
+}
+
+float voice_envelope(float frequency) {
+ // envelope_index ranges from 0 to 0xFFFF, which is preserved at 880.0 Hz
+ uint16_t compensated_index = (uint16_t)((float)envelope_index * (880.0 / frequency));
+
+ switch (voice) {
+ case default_voice:
+ note_timbre = TIMBRE_50;
+ polyphony_rate = 0;
+ break;
+
+ case butts_fader:
+ polyphony_rate = 0;
+ switch (compensated_index) {
+ case 0 ... 9:
+ frequency = frequency / 4;
+ note_timbre = TIMBRE_12;
+ break;
+
+ case 10 ... 19:
+ frequency = frequency / 2;
+ note_timbre = TIMBRE_12;
+ break;
+
+ case 20 ... 200:
+ note_timbre = .125 - pow(((float)compensated_index - 20) / (200 - 20), 2)*.125;
+ break;
+
+ default:
+ note_timbre = 0;
+ break;
+ }
+ break;
+
+ // case octave_crunch:
+ // polyphony_rate = 0;
+ // switch (compensated_index) {
+ // case 0 ... 9:
+ // case 20 ... 24:
+ // case 30 ... 32:
+ // frequency = frequency / 2;
+ // note_timbre = TIMBRE_12;
+ // break;
+
+ // case 10 ... 19:
+ // case 25 ... 29:
+ // case 33 ... 35:
+ // frequency = frequency * 2;
+ // note_timbre = TIMBRE_12;
+ // break;
+
+ // default:
+ // note_timbre = TIMBRE_12;
+ // break;
+ // }
+ // break;
+
+ case duty_osc:
+ // This slows the loop down a substantial amount, so higher notes may freeze
+ polyphony_rate = 0;
+ switch (compensated_index) {
+ default:
+ #define OCS_SPEED 10
+ #define OCS_AMP .25
+ // sine wave is slow
+ // note_timbre = (sin((float)compensated_index/10000*OCS_SPEED) * OCS_AMP / 2) + .5;
+ // triangle wave is a bit faster
+ note_timbre = (float)abs((compensated_index*OCS_SPEED % 3000) - 1500) * ( OCS_AMP / 1500 ) + (1 - OCS_AMP) / 2;
+ break;
+ }
+ break;
+
+ case duty_octave_down:
+ polyphony_rate = 0;
+ note_timbre = (envelope_index % 2) * .125 + .375 * 2;
+ if ((envelope_index % 4) == 0)
+ note_timbre = 0.5;
+ if ((envelope_index % 8) == 0)
+ note_timbre = 0;
+ break;
+ case delayed_vibrato:
+ polyphony_rate = 0;
+ note_timbre = TIMBRE_50;
+ #define VOICE_VIBRATO_DELAY 150
+ #define VOICE_VIBRATO_SPEED 50
+ switch (compensated_index) {
+ case 0 ... VOICE_VIBRATO_DELAY:
+ break;
+ default:
+ frequency = frequency * vibrato_lut[(int)fmod((((float)compensated_index - (VOICE_VIBRATO_DELAY + 1))/1000*VOICE_VIBRATO_SPEED), VIBRATO_LUT_LENGTH)];
+ break;
+ }
+ break;
+ // case delayed_vibrato_octave:
+ // polyphony_rate = 0;
+ // if ((envelope_index % 2) == 1) {
+ // note_timbre = 0.55;
+ // } else {
+ // note_timbre = 0.45;
+ // }
+ // #define VOICE_VIBRATO_DELAY 150
+ // #define VOICE_VIBRATO_SPEED 50
+ // switch (compensated_index) {
+ // case 0 ... VOICE_VIBRATO_DELAY:
+ // break;
+ // default:
+ // frequency = frequency * VIBRATO_LUT[(int)fmod((((float)compensated_index - (VOICE_VIBRATO_DELAY + 1))/1000*VOICE_VIBRATO_SPEED), VIBRATO_LUT_LENGTH)];
+ // break;
+ // }
+ // break;
+ // case duty_fifth_down:
+ // note_timbre = 0.5;
+ // if ((envelope_index % 3) == 0)
+ // note_timbre = 0.75;
+ // break;
+ // case duty_fourth_down:
+ // note_timbre = 0.0;
+ // if ((envelope_index % 12) == 0)
+ // note_timbre = 0.75;
+ // if (((envelope_index % 12) % 4) != 1)
+ // note_timbre = 0.75;
+ // break;
+ // case duty_third_down:
+ // note_timbre = 0.5;
+ // if ((envelope_index % 5) == 0)
+ // note_timbre = 0.75;
+ // break;
+ // case duty_fifth_third_down:
+ // note_timbre = 0.5;
+ // if ((envelope_index % 5) == 0)
+ // note_timbre = 0.75;
+ // if ((envelope_index % 3) == 0)
+ // note_timbre = 0.25;
+ // break;
+
+ default:
+ break;
+ }
+
+ return frequency;
+}
+
+
diff --git a/quantum/audio/voices.h b/quantum/audio/voices.h
new file mode 100644
index 000000000..b2495b23b
--- /dev/null
+++ b/quantum/audio/voices.h
@@ -0,0 +1,31 @@
+#include <stdint.h>
+#include <stdbool.h>
+#include <avr/io.h>
+#include <util/delay.h>
+#include "luts.h"
+
+#ifndef VOICES_H
+#define VOICES_H
+
+float voice_envelope(float frequency);
+
+typedef enum {
+ default_voice,
+ butts_fader,
+ octave_crunch,
+ duty_osc,
+ duty_octave_down,
+ delayed_vibrato,
+ // delayed_vibrato_octave,
+ // duty_fifth_down,
+ // duty_fourth_down,
+ // duty_third_down,
+ // duty_fifth_third_down,
+ number_of_voices // important that this is last
+} voice_type;
+
+void set_voice(voice_type v);
+void voice_iterate(void);
+void voice_deiterate(void);
+
+#endif \ No newline at end of file
diff --git a/quantum/audio/wave.h b/quantum/audio/wave.h
new file mode 100644
index 000000000..6ebc34851
--- /dev/null
+++ b/quantum/audio/wave.h
@@ -0,0 +1,265 @@
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/pgmspace.h>
+
+#define SINE_LENGTH 2048
+
+const uint8_t sinewave[] PROGMEM= //2048 values
+{
+0x80,0x80,0x80,0x81,0x81,0x81,0x82,0x82,
+0x83,0x83,0x83,0x84,0x84,0x85,0x85,0x85,
+0x86,0x86,0x87,0x87,0x87,0x88,0x88,0x88,
+0x89,0x89,0x8a,0x8a,0x8a,0x8b,0x8b,0x8c,
+0x8c,0x8c,0x8d,0x8d,0x8e,0x8e,0x8e,0x8f,
+0x8f,0x8f,0x90,0x90,0x91,0x91,0x91,0x92,
+0x92,0x93,0x93,0x93,0x94,0x94,0x95,0x95,
+0x95,0x96,0x96,0x96,0x97,0x97,0x98,0x98,
+0x98,0x99,0x99,0x9a,0x9a,0x9a,0x9b,0x9b,
+0x9b,0x9c,0x9c,0x9d,0x9d,0x9d,0x9e,0x9e,
+0x9e,0x9f,0x9f,0xa0,0xa0,0xa0,0xa1,0xa1,
+0xa2,0xa2,0xa2,0xa3,0xa3,0xa3,0xa4,0xa4,
+0xa5,0xa5,0xa5,0xa6,0xa6,0xa6,0xa7,0xa7,
+0xa7,0xa8,0xa8,0xa9,0xa9,0xa9,0xaa,0xaa,
+0xaa,0xab,0xab,0xac,0xac,0xac,0xad,0xad,
+0xad,0xae,0xae,0xae,0xaf,0xaf,0xb0,0xb0,
+0xb0,0xb1,0xb1,0xb1,0xb2,0xb2,0xb2,0xb3,
+0xb3,0xb4,0xb4,0xb4,0xb5,0xb5,0xb5,0xb6,
+0xb6,0xb6,0xb7,0xb7,0xb7,0xb8,0xb8,0xb8,
+0xb9,0xb9,0xba,0xba,0xba,0xbb,0xbb,0xbb,
+0xbc,0xbc,0xbc,0xbd,0xbd,0xbd,0xbe,0xbe,
+0xbe,0xbf,0xbf,0xbf,0xc0,0xc0,0xc0,0xc1,
+0xc1,0xc1,0xc2,0xc2,0xc2,0xc3,0xc3,0xc3,
+0xc4,0xc4,0xc4,0xc5,0xc5,0xc5,0xc6,0xc6,
+0xc6,0xc7,0xc7,0xc7,0xc8,0xc8,0xc8,0xc9,
+0xc9,0xc9,0xca,0xca,0xca,0xcb,0xcb,0xcb,
+0xcb,0xcc,0xcc,0xcc,0xcd,0xcd,0xcd,0xce,
+0xce,0xce,0xcf,0xcf,0xcf,0xcf,0xd0,0xd0,
+0xd0,0xd1,0xd1,0xd1,0xd2,0xd2,0xd2,0xd2,
+0xd3,0xd3,0xd3,0xd4,0xd4,0xd4,0xd5,0xd5,
+0xd5,0xd5,0xd6,0xd6,0xd6,0xd7,0xd7,0xd7,
+0xd7,0xd8,0xd8,0xd8,0xd9,0xd9,0xd9,0xd9,
+0xda,0xda,0xda,0xda,0xdb,0xdb,0xdb,0xdc,
+0xdc,0xdc,0xdc,0xdd,0xdd,0xdd,0xdd,0xde,
+0xde,0xde,0xde,0xdf,0xdf,0xdf,0xe0,0xe0,
+0xe0,0xe0,0xe1,0xe1,0xe1,0xe1,0xe2,0xe2,
+0xe2,0xe2,0xe3,0xe3,0xe3,0xe3,0xe4,0xe4,
+0xe4,0xe4,0xe4,0xe5,0xe5,0xe5,0xe5,0xe6,
+0xe6,0xe6,0xe6,0xe7,0xe7,0xe7,0xe7,0xe8,
+0xe8,0xe8,0xe8,0xe8,0xe9,0xe9,0xe9,0xe9,
+0xea,0xea,0xea,0xea,0xea,0xeb,0xeb,0xeb,
+0xeb,0xeb,0xec,0xec,0xec,0xec,0xec,0xed,
+0xed,0xed,0xed,0xed,0xee,0xee,0xee,0xee,
+0xee,0xef,0xef,0xef,0xef,0xef,0xf0,0xf0,
+0xf0,0xf0,0xf0,0xf0,0xf1,0xf1,0xf1,0xf1,
+0xf1,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf3,
+0xf3,0xf3,0xf3,0xf3,0xf3,0xf4,0xf4,0xf4,
+0xf4,0xf4,0xf4,0xf5,0xf5,0xf5,0xf5,0xf5,
+0xf5,0xf5,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,
+0xf6,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,
+0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,
+0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,
+0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,
+0xfa,0xfa,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,
+0xfb,0xfb,0xfb,0xfb,0xfc,0xfc,0xfc,0xfc,
+0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,
+0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,
+0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfe,0xfe,
+0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,
+0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,
+0xfe,0xfe,0xfe,0xfe,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xfe,0xfe,0xfe,
+0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,
+0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,
+0xfe,0xfe,0xfe,0xfd,0xfd,0xfd,0xfd,0xfd,
+0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,
+0xfd,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,
+0xfc,0xfc,0xfc,0xfc,0xfc,0xfb,0xfb,0xfb,
+0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfa,
+0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,
+0xfa,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,
+0xf9,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,
+0xf8,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,
+0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf5,
+0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf4,0xf4,
+0xf4,0xf4,0xf4,0xf4,0xf3,0xf3,0xf3,0xf3,
+0xf3,0xf3,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,
+0xf1,0xf1,0xf1,0xf1,0xf1,0xf0,0xf0,0xf0,
+0xf0,0xf0,0xf0,0xef,0xef,0xef,0xef,0xef,
+0xee,0xee,0xee,0xee,0xee,0xed,0xed,0xed,
+0xed,0xed,0xec,0xec,0xec,0xec,0xec,0xeb,
+0xeb,0xeb,0xeb,0xeb,0xea,0xea,0xea,0xea,
+0xea,0xe9,0xe9,0xe9,0xe9,0xe8,0xe8,0xe8,
+0xe8,0xe8,0xe7,0xe7,0xe7,0xe7,0xe6,0xe6,
+0xe6,0xe6,0xe5,0xe5,0xe5,0xe5,0xe4,0xe4,
+0xe4,0xe4,0xe4,0xe3,0xe3,0xe3,0xe3,0xe2,
+0xe2,0xe2,0xe2,0xe1,0xe1,0xe1,0xe1,0xe0,
+0xe0,0xe0,0xe0,0xdf,0xdf,0xdf,0xde,0xde,
+0xde,0xde,0xdd,0xdd,0xdd,0xdd,0xdc,0xdc,
+0xdc,0xdc,0xdb,0xdb,0xdb,0xda,0xda,0xda,
+0xda,0xd9,0xd9,0xd9,0xd9,0xd8,0xd8,0xd8,
+0xd7,0xd7,0xd7,0xd7,0xd6,0xd6,0xd6,0xd5,
+0xd5,0xd5,0xd5,0xd4,0xd4,0xd4,0xd3,0xd3,
+0xd3,0xd2,0xd2,0xd2,0xd2,0xd1,0xd1,0xd1,
+0xd0,0xd0,0xd0,0xcf,0xcf,0xcf,0xcf,0xce,
+0xce,0xce,0xcd,0xcd,0xcd,0xcc,0xcc,0xcc,
+0xcb,0xcb,0xcb,0xcb,0xca,0xca,0xca,0xc9,
+0xc9,0xc9,0xc8,0xc8,0xc8,0xc7,0xc7,0xc7,
+0xc6,0xc6,0xc6,0xc5,0xc5,0xc5,0xc4,0xc4,
+0xc4,0xc3,0xc3,0xc3,0xc2,0xc2,0xc2,0xc1,
+0xc1,0xc1,0xc0,0xc0,0xc0,0xbf,0xbf,0xbf,
+0xbe,0xbe,0xbe,0xbd,0xbd,0xbd,0xbc,0xbc,
+0xbc,0xbb,0xbb,0xbb,0xba,0xba,0xba,0xb9,
+0xb9,0xb8,0xb8,0xb8,0xb7,0xb7,0xb7,0xb6,
+0xb6,0xb6,0xb5,0xb5,0xb5,0xb4,0xb4,0xb4,
+0xb3,0xb3,0xb2,0xb2,0xb2,0xb1,0xb1,0xb1,
+0xb0,0xb0,0xb0,0xaf,0xaf,0xae,0xae,0xae,
+0xad,0xad,0xad,0xac,0xac,0xac,0xab,0xab,
+0xaa,0xaa,0xaa,0xa9,0xa9,0xa9,0xa8,0xa8,
+0xa7,0xa7,0xa7,0xa6,0xa6,0xa6,0xa5,0xa5,
+0xa5,0xa4,0xa4,0xa3,0xa3,0xa3,0xa2,0xa2,
+0xa2,0xa1,0xa1,0xa0,0xa0,0xa0,0x9f,0x9f,
+0x9e,0x9e,0x9e,0x9d,0x9d,0x9d,0x9c,0x9c,
+0x9b,0x9b,0x9b,0x9a,0x9a,0x9a,0x99,0x99,
+0x98,0x98,0x98,0x97,0x97,0x96,0x96,0x96,
+0x95,0x95,0x95,0x94,0x94,0x93,0x93,0x93,
+0x92,0x92,0x91,0x91,0x91,0x90,0x90,0x8f,
+0x8f,0x8f,0x8e,0x8e,0x8e,0x8d,0x8d,0x8c,
+0x8c,0x8c,0x8b,0x8b,0x8a,0x8a,0x8a,0x89,
+0x89,0x88,0x88,0x88,0x87,0x87,0x87,0x86,
+0x86,0x85,0x85,0x85,0x84,0x84,0x83,0x83,
+0x83,0x82,0x82,0x81,0x81,0x81,0x80,0x80,
+0x80,0x7f,0x7f,0x7e,0x7e,0x7e,0x7d,0x7d,
+0x7c,0x7c,0x7c,0x7b,0x7b,0x7a,0x7a,0x7a,
+0x79,0x79,0x78,0x78,0x78,0x77,0x77,0x77,
+0x76,0x76,0x75,0x75,0x75,0x74,0x74,0x73,
+0x73,0x73,0x72,0x72,0x71,0x71,0x71,0x70,
+0x70,0x70,0x6f,0x6f,0x6e,0x6e,0x6e,0x6d,
+0x6d,0x6c,0x6c,0x6c,0x6b,0x6b,0x6a,0x6a,
+0x6a,0x69,0x69,0x69,0x68,0x68,0x67,0x67,
+0x67,0x66,0x66,0x65,0x65,0x65,0x64,0x64,
+0x64,0x63,0x63,0x62,0x62,0x62,0x61,0x61,
+0x61,0x60,0x60,0x5f,0x5f,0x5f,0x5e,0x5e,
+0x5d,0x5d,0x5d,0x5c,0x5c,0x5c,0x5b,0x5b,
+0x5a,0x5a,0x5a,0x59,0x59,0x59,0x58,0x58,
+0x58,0x57,0x57,0x56,0x56,0x56,0x55,0x55,
+0x55,0x54,0x54,0x53,0x53,0x53,0x52,0x52,
+0x52,0x51,0x51,0x51,0x50,0x50,0x4f,0x4f,
+0x4f,0x4e,0x4e,0x4e,0x4d,0x4d,0x4d,0x4c,
+0x4c,0x4b,0x4b,0x4b,0x4a,0x4a,0x4a,0x49,
+0x49,0x49,0x48,0x48,0x48,0x47,0x47,0x47,
+0x46,0x46,0x45,0x45,0x45,0x44,0x44,0x44,
+0x43,0x43,0x43,0x42,0x42,0x42,0x41,0x41,
+0x41,0x40,0x40,0x40,0x3f,0x3f,0x3f,0x3e,
+0x3e,0x3e,0x3d,0x3d,0x3d,0x3c,0x3c,0x3c,
+0x3b,0x3b,0x3b,0x3a,0x3a,0x3a,0x39,0x39,
+0x39,0x38,0x38,0x38,0x37,0x37,0x37,0x36,
+0x36,0x36,0x35,0x35,0x35,0x34,0x34,0x34,
+0x34,0x33,0x33,0x33,0x32,0x32,0x32,0x31,
+0x31,0x31,0x30,0x30,0x30,0x30,0x2f,0x2f,
+0x2f,0x2e,0x2e,0x2e,0x2d,0x2d,0x2d,0x2d,
+0x2c,0x2c,0x2c,0x2b,0x2b,0x2b,0x2a,0x2a,
+0x2a,0x2a,0x29,0x29,0x29,0x28,0x28,0x28,
+0x28,0x27,0x27,0x27,0x26,0x26,0x26,0x26,
+0x25,0x25,0x25,0x25,0x24,0x24,0x24,0x23,
+0x23,0x23,0x23,0x22,0x22,0x22,0x22,0x21,
+0x21,0x21,0x21,0x20,0x20,0x20,0x1f,0x1f,
+0x1f,0x1f,0x1e,0x1e,0x1e,0x1e,0x1d,0x1d,
+0x1d,0x1d,0x1c,0x1c,0x1c,0x1c,0x1b,0x1b,
+0x1b,0x1b,0x1b,0x1a,0x1a,0x1a,0x1a,0x19,
+0x19,0x19,0x19,0x18,0x18,0x18,0x18,0x17,
+0x17,0x17,0x17,0x17,0x16,0x16,0x16,0x16,
+0x15,0x15,0x15,0x15,0x15,0x14,0x14,0x14,
+0x14,0x14,0x13,0x13,0x13,0x13,0x13,0x12,
+0x12,0x12,0x12,0x12,0x11,0x11,0x11,0x11,
+0x11,0x10,0x10,0x10,0x10,0x10,0xf,0xf,
+0xf,0xf,0xf,0xf,0xe,0xe,0xe,0xe,
+0xe,0xd,0xd,0xd,0xd,0xd,0xd,0xc,
+0xc,0xc,0xc,0xc,0xc,0xb,0xb,0xb,
+0xb,0xb,0xb,0xa,0xa,0xa,0xa,0xa,
+0xa,0xa,0x9,0x9,0x9,0x9,0x9,0x9,
+0x9,0x8,0x8,0x8,0x8,0x8,0x8,0x8,
+0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x7,
+0x6,0x6,0x6,0x6,0x6,0x6,0x6,0x6,
+0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5,
+0x5,0x5,0x4,0x4,0x4,0x4,0x4,0x4,
+0x4,0x4,0x4,0x4,0x3,0x3,0x3,0x3,
+0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,
+0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,
+0x2,0x2,0x2,0x2,0x2,0x2,0x1,0x1,
+0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,
+0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,
+0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,
+0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,
+0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,
+0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,
+0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,
+0x2,0x3,0x3,0x3,0x3,0x3,0x3,0x3,
+0x3,0x3,0x3,0x3,0x3,0x4,0x4,0x4,
+0x4,0x4,0x4,0x4,0x4,0x4,0x4,0x5,
+0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5,
+0x5,0x6,0x6,0x6,0x6,0x6,0x6,0x6,
+0x6,0x7,0x7,0x7,0x7,0x7,0x7,0x7,
+0x7,0x8,0x8,0x8,0x8,0x8,0x8,0x8,
+0x9,0x9,0x9,0x9,0x9,0x9,0x9,0xa,
+0xa,0xa,0xa,0xa,0xa,0xa,0xb,0xb,
+0xb,0xb,0xb,0xb,0xc,0xc,0xc,0xc,
+0xc,0xc,0xd,0xd,0xd,0xd,0xd,0xd,
+0xe,0xe,0xe,0xe,0xe,0xf,0xf,0xf,
+0xf,0xf,0xf,0x10,0x10,0x10,0x10,0x10,
+0x11,0x11,0x11,0x11,0x11,0x12,0x12,0x12,
+0x12,0x12,0x13,0x13,0x13,0x13,0x13,0x14,
+0x14,0x14,0x14,0x14,0x15,0x15,0x15,0x15,
+0x15,0x16,0x16,0x16,0x16,0x17,0x17,0x17,
+0x17,0x17,0x18,0x18,0x18,0x18,0x19,0x19,
+0x19,0x19,0x1a,0x1a,0x1a,0x1a,0x1b,0x1b,
+0x1b,0x1b,0x1b,0x1c,0x1c,0x1c,0x1c,0x1d,
+0x1d,0x1d,0x1d,0x1e,0x1e,0x1e,0x1e,0x1f,
+0x1f,0x1f,0x1f,0x20,0x20,0x20,0x21,0x21,
+0x21,0x21,0x22,0x22,0x22,0x22,0x23,0x23,
+0x23,0x23,0x24,0x24,0x24,0x25,0x25,0x25,
+0x25,0x26,0x26,0x26,0x26,0x27,0x27,0x27,
+0x28,0x28,0x28,0x28,0x29,0x29,0x29,0x2a,
+0x2a,0x2a,0x2a,0x2b,0x2b,0x2b,0x2c,0x2c,
+0x2c,0x2d,0x2d,0x2d,0x2d,0x2e,0x2e,0x2e,
+0x2f,0x2f,0x2f,0x30,0x30,0x30,0x30,0x31,
+0x31,0x31,0x32,0x32,0x32,0x33,0x33,0x33,
+0x34,0x34,0x34,0x34,0x35,0x35,0x35,0x36,
+0x36,0x36,0x37,0x37,0x37,0x38,0x38,0x38,
+0x39,0x39,0x39,0x3a,0x3a,0x3a,0x3b,0x3b,
+0x3b,0x3c,0x3c,0x3c,0x3d,0x3d,0x3d,0x3e,
+0x3e,0x3e,0x3f,0x3f,0x3f,0x40,0x40,0x40,
+0x41,0x41,0x41,0x42,0x42,0x42,0x43,0x43,
+0x43,0x44,0x44,0x44,0x45,0x45,0x45,0x46,
+0x46,0x47,0x47,0x47,0x48,0x48,0x48,0x49,
+0x49,0x49,0x4a,0x4a,0x4a,0x4b,0x4b,0x4b,
+0x4c,0x4c,0x4d,0x4d,0x4d,0x4e,0x4e,0x4e,
+0x4f,0x4f,0x4f,0x50,0x50,0x51,0x51,0x51,
+0x52,0x52,0x52,0x53,0x53,0x53,0x54,0x54,
+0x55,0x55,0x55,0x56,0x56,0x56,0x57,0x57,
+0x58,0x58,0x58,0x59,0x59,0x59,0x5a,0x5a,
+0x5a,0x5b,0x5b,0x5c,0x5c,0x5c,0x5d,0x5d,
+0x5d,0x5e,0x5e,0x5f,0x5f,0x5f,0x60,0x60,
+0x61,0x61,0x61,0x62,0x62,0x62,0x63,0x63,
+0x64,0x64,0x64,0x65,0x65,0x65,0x66,0x66,
+0x67,0x67,0x67,0x68,0x68,0x69,0x69,0x69,
+0x6a,0x6a,0x6a,0x6b,0x6b,0x6c,0x6c,0x6c,
+0x6d,0x6d,0x6e,0x6e,0x6e,0x6f,0x6f,0x70,
+0x70,0x70,0x71,0x71,0x71,0x72,0x72,0x73,
+0x73,0x73,0x74,0x74,0x75,0x75,0x75,0x76,
+0x76,0x77,0x77,0x77,0x78,0x78,0x78,0x79,
+0x79,0x7a,0x7a,0x7a,0x7b,0x7b,0x7c,0x7c,
+0x7c,0x7d,0x7d,0x7e,0x7e,0x7e,0x7f,0x7f
+}; \ No newline at end of file
diff --git a/quantum/config_common.h b/quantum/config_common.h
new file mode 100644
index 000000000..09a4fe701
--- /dev/null
+++ b/quantum/config_common.h
@@ -0,0 +1,119 @@
+#ifndef CONFIG_DEFINITIONS_H
+#define CONFIG_DEFINITIONS_H
+
+/* diode directions */
+#define COL2ROW 0
+#define ROW2COL 1
+/* I/O pins */
+#define B0 0x30
+#define B1 0x31
+#define B2 0x32
+#define B3 0x33
+#define B4 0x34
+#define B5 0x35
+#define B6 0x36
+#define B7 0x37
+#define C0 0x60
+#define C1 0x61
+#define C2 0x62
+#define C3 0x63
+#define C4 0x64
+#define C5 0x65
+#define C6 0x66
+#define C7 0x67
+#define D0 0x90
+#define D1 0x91
+#define D2 0x92
+#define D3 0x93
+#define D4 0x94
+#define D5 0x95
+#define D6 0x96
+#define D7 0x97
+#define E0 0xC0
+#define E1 0xC1
+#define E2 0xC2
+#define E3 0xC3
+#define E4 0xC4
+#define E5 0xC5
+#define E6 0xC6
+#define E7 0xC7
+#define F0 0xF0
+#define F1 0xF1
+#define F2 0xF2
+#define F3 0xF3
+#define F4 0xF4
+#define F5 0xF5
+#define F6 0xF6
+#define F7 0xF7
+
+/* USART configuration */
+#ifdef BLUETOOTH_ENABLE
+# ifdef __AVR_ATmega32U4__
+# define SERIAL_UART_BAUD 9600
+# define SERIAL_UART_DATA UDR1
+# define SERIAL_UART_UBRR (F_CPU / (16UL * SERIAL_UART_BAUD) - 1)
+# define SERIAL_UART_RXD_VECT USART1_RX_vect
+# define SERIAL_UART_TXD_READY (UCSR1A & _BV(UDRE1))
+# define SERIAL_UART_INIT() do { \
+ /* baud rate */ \
+ UBRR1L = SERIAL_UART_UBRR; \
+ /* baud rate */ \
+ UBRR1H = SERIAL_UART_UBRR >> 8; \
+ /* enable TX */ \
+ UCSR1B = _BV(TXEN1); \
+ /* 8-bit data */ \
+ UCSR1C = _BV(UCSZ11) | _BV(UCSZ10); \
+ sei(); \
+ } while(0)
+# else
+# error "USART configuration is needed."
+#endif
+
+// I'm fairly sure these aren't needed, but oh well - Jack
+
+/*
+ * PS/2 Interrupt configuration
+ */
+#ifdef PS2_USE_INT
+/* uses INT1 for clock line(ATMega32U4) */
+#define PS2_CLOCK_PORT PORTD
+#define PS2_CLOCK_PIN PIND
+#define PS2_CLOCK_DDR DDRD
+#define PS2_CLOCK_BIT 1
+
+#define PS2_DATA_PORT PORTD
+#define PS2_DATA_PIN PIND
+#define PS2_DATA_DDR DDRD
+#define PS2_DATA_BIT 0
+
+#define PS2_INT_INIT() do { \
+ EICRA |= ((1<<ISC11) | \
+ (0<<ISC10)); \
+} while (0)
+#define PS2_INT_ON() do { \
+ EIMSK |= (1<<INT1); \
+} while (0)
+#define PS2_INT_OFF() do { \
+ EIMSK &= ~(1<<INT1); \
+} while (0)
+#define PS2_INT_VECT INT1_vect
+#endif
+
+/*
+ * PS/2 Busywait configuration
+ */
+#ifdef PS2_USE_BUSYWAIT
+#define PS2_CLOCK_PORT PORTD
+#define PS2_CLOCK_PIN PIND
+#define PS2_CLOCK_DDR DDRD
+#define PS2_CLOCK_BIT 1
+
+#define PS2_DATA_PORT PORTD
+#define PS2_DATA_PIN PIND
+#define PS2_DATA_DDR DDRD
+#define PS2_DATA_BIT 0
+#endif
+
+#endif
+
+#endif
diff --git a/quantum/keycode_config.c b/quantum/keycode_config.c
new file mode 100644
index 000000000..6d90781a1
--- /dev/null
+++ b/quantum/keycode_config.c
@@ -0,0 +1,74 @@
+#include "keycode_config.h"
+
+extern keymap_config_t keymap_config;
+
+uint16_t keycode_config(uint16_t keycode) {
+
+ switch (keycode) {
+ case KC_CAPSLOCK:
+ case KC_LOCKING_CAPS:
+ if (keymap_config.swap_control_capslock || keymap_config.capslock_to_control) {
+ return KC_LCTL;
+ }
+ return keycode;
+ case KC_LCTL:
+ if (keymap_config.swap_control_capslock) {
+ return KC_CAPSLOCK;
+ }
+ return KC_LCTL;
+ case KC_LALT:
+ if (keymap_config.swap_lalt_lgui) {
+ if (keymap_config.no_gui) {
+ return KC_NO;
+ }
+ return KC_LGUI;
+ }
+ return KC_LALT;
+ case KC_LGUI:
+ if (keymap_config.swap_lalt_lgui) {
+ return KC_LALT;
+ }
+ if (keymap_config.no_gui) {
+ return KC_NO;
+ }
+ return KC_LGUI;
+ case KC_RALT:
+ if (keymap_config.swap_ralt_rgui) {
+ if (keymap_config.no_gui) {
+ return KC_NO;
+ }
+ return KC_RGUI;
+ }
+ return KC_RALT;
+ case KC_RGUI:
+ if (keymap_config.swap_ralt_rgui) {
+ return KC_RALT;
+ }
+ if (keymap_config.no_gui) {
+ return KC_NO;
+ }
+ return KC_RGUI;
+ case KC_GRAVE:
+ if (keymap_config.swap_grave_esc) {
+ return KC_ESC;
+ }
+ return KC_GRAVE;
+ case KC_ESC:
+ if (keymap_config.swap_grave_esc) {
+ return KC_GRAVE;
+ }
+ return KC_ESC;
+ case KC_BSLASH:
+ if (keymap_config.swap_backslash_backspace) {
+ return KC_BSPACE;
+ }
+ return KC_BSLASH;
+ case KC_BSPACE:
+ if (keymap_config.swap_backslash_backspace) {
+ return KC_BSLASH;
+ }
+ return KC_BSPACE;
+ default:
+ return keycode;
+ }
+} \ No newline at end of file
diff --git a/quantum/keycode_config.h b/quantum/keycode_config.h
new file mode 100644
index 000000000..6216eefc9
--- /dev/null
+++ b/quantum/keycode_config.h
@@ -0,0 +1,21 @@
+#include "eeconfig.h"
+#include "keycode.h"
+
+uint16_t keycode_config(uint16_t keycode);
+
+/* NOTE: Not portable. Bit field order depends on implementation */
+typedef union {
+ uint16_t raw;
+ struct {
+ bool swap_control_capslock:1;
+ bool capslock_to_control:1;
+ bool swap_lalt_lgui:1;
+ bool swap_ralt_rgui:1;
+ bool no_gui:1;
+ bool swap_grave_esc:1;
+ bool swap_backslash_backspace:1;
+ bool nkro:1;
+ };
+} keymap_config_t;
+
+extern keymap_config_t keymap_config;
diff --git a/quantum/keymap.h b/quantum/keymap.h
new file mode 100644
index 000000000..73f99f821
--- /dev/null
+++ b/quantum/keymap.h
@@ -0,0 +1,328 @@
+/*
+Copyright 2012,2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef KEYMAP_H
+#define KEYMAP_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "action.h"
+#if defined(__AVR__)
+#include <avr/pgmspace.h>
+#endif
+#include "keycode.h"
+#include "action_macro.h"
+#include "report.h"
+#include "host.h"
+// #include "print.h"
+#include "debug.h"
+#include "keycode_config.h"
+
+// ChibiOS uses RESET in its FlagStatus enumeration
+// Therefore define it as QK_RESET here, to avoid name collision
+#if defined(PROTOCOL_CHIBIOS)
+#define RESET QK_RESET
+#endif
+
+/* translates key to keycode */
+uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key);
+
+extern const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS];
+extern const uint16_t fn_actions[];
+
+enum quantum_keycodes {
+ // Ranges used in shortucuts - not to be used directly
+ QK_TMK = 0x0000,
+ QK_TMK_MAX = 0x00FF,
+ QK_MODS = 0x0100,
+ QK_LCTL = 0x0100,
+ QK_LSFT = 0x0200,
+ QK_LALT = 0x0400,
+ QK_LGUI = 0x0800,
+ QK_RCTL = 0x1100,
+ QK_RSFT = 0x1200,
+ QK_RALT = 0x1400,
+ QK_RGUI = 0x1800,
+ QK_MODS_MAX = 0x1FFF,
+ QK_FUNCTION = 0x2000,
+ QK_FUNCTION_MAX = 0x2FFF,
+ QK_MACRO = 0x3000,
+ QK_MACRO_MAX = 0x3FFF,
+ QK_LAYER_TAP = 0x4000,
+ QK_LAYER_TAP_MAX = 0x4FFF,
+ QK_TO = 0x5000,
+ QK_TO_MAX = 0x50FF,
+ QK_MOMENTARY = 0x5100,
+ QK_MOMENTARY_MAX = 0x51FF,
+ QK_DEF_LAYER = 0x5200,
+ QK_DEF_LAYER_MAX = 0x52FF,
+ QK_TOGGLE_LAYER = 0x5300,
+ QK_TOGGLE_LAYER_MAX = 0x53FF,
+ QK_ONE_SHOT_LAYER = 0x5400,
+ QK_ONE_SHOT_LAYER_MAX = 0x54FF,
+ QK_ONE_SHOT_MOD = 0x5500,
+ QK_ONE_SHOT_MOD_MAX = 0x55FF,
+#ifndef DISABLE_CHORDING
+ QK_CHORDING = 0x5600,
+ QK_CHORDING_MAX = 0x56FF,
+#endif
+ QK_MOD_TAP = 0x6000,
+ QK_MOD_TAP_MAX = 0x6FFF,
+ QK_TAP_DANCE = 0x7100,
+ QK_TAP_DANCE_MAX = 0x71FF,
+#ifdef UNICODE_ENABLE
+ QK_UNICODE = 0x8000,
+ QK_UNICODE_MAX = 0xFFFF,
+#endif
+
+ // Loose keycodes - to be used directly
+
+ RESET = 0x7000,
+ DEBUG,
+ MAGIC_SWAP_CONTROL_CAPSLOCK,
+ MAGIC_CAPSLOCK_TO_CONTROL,
+ MAGIC_SWAP_LALT_LGUI,
+ MAGIC_SWAP_RALT_RGUI,
+ MAGIC_NO_GUI,
+ MAGIC_SWAP_GRAVE_ESC,
+ MAGIC_SWAP_BACKSLASH_BACKSPACE,
+ MAGIC_HOST_NKRO,
+ MAGIC_SWAP_ALT_GUI,
+ MAGIC_UNSWAP_CONTROL_CAPSLOCK,
+ MAGIC_UNCAPSLOCK_TO_CONTROL,
+ MAGIC_UNSWAP_LALT_LGUI,
+ MAGIC_UNSWAP_RALT_RGUI,
+ MAGIC_UNNO_GUI,
+ MAGIC_UNSWAP_GRAVE_ESC,
+ MAGIC_UNSWAP_BACKSLASH_BACKSPACE,
+ MAGIC_UNHOST_NKRO,
+ MAGIC_UNSWAP_ALT_GUI,
+
+ // Leader key
+#ifndef DISABLE_LEADER
+ KC_LEAD,
+#endif
+
+ // Audio on/off/toggle
+ AU_ON,
+ AU_OFF,
+ AU_TOG,
+
+ // Music mode on/off/toggle
+ MU_ON,
+ MU_OFF,
+ MU_TOG,
+
+ // Music voice iterate
+ MUV_IN,
+ MUV_DE,
+
+ // Midi mode on/off
+ MIDI_ON,
+ MIDI_OFF,
+
+ // Backlight functionality
+ BL_0,
+ BL_1,
+ BL_2,
+ BL_3,
+ BL_4,
+ BL_5,
+ BL_6,
+ BL_7,
+ BL_8,
+ BL_9,
+ BL_10,
+ BL_11,
+ BL_12,
+ BL_13,
+ BL_14,
+ BL_15,
+ BL_DEC,
+ BL_INC,
+ BL_TOGG,
+ BL_STEP,
+
+ // Left shift, open paren
+ KC_LSPO,
+
+ // Right shift, close paren
+ KC_RSPC,
+
+ // always leave at the end
+ SAFE_RANGE
+};
+
+// Ability to use mods in layouts
+#define LCTL(kc) (kc | QK_LCTL)
+#define LSFT(kc) (kc | QK_LSFT)
+#define LALT(kc) (kc | QK_LALT)
+#define LGUI(kc) (kc | QK_LGUI)
+#define RCTL(kc) (kc | QK_RCTL)
+#define RSFT(kc) (kc | QK_RSFT)
+#define RALT(kc) (kc | QK_RALT)
+#define RGUI(kc) (kc | QK_RGUI)
+
+#define HYPR(kc) (kc | QK_LCTL | QK_LSFT | QK_LALT | QK_LGUI)
+#define MEH(kc) (kc | QK_LCTL | QK_LSFT | QK_LALT)
+#define LCAG(kc) (kc | QK_LCTL | QK_LALT | QK_LGUI)
+
+#define MOD_HYPR 0xf
+#define MOD_MEH 0x7
+
+
+// Aliases for shifted symbols
+// Each key has a 4-letter code, and some have longer aliases too.
+// While the long aliases are descriptive, the 4-letter codes
+// make for nicer grid layouts (everything lines up), and are
+// the preferred style for Quantum.
+#define KC_TILD LSFT(KC_GRV) // ~
+#define KC_TILDE KC_TILD
+
+#define KC_EXLM LSFT(KC_1) // !
+#define KC_EXCLAIM KC_EXLM
+
+#define KC_AT LSFT(KC_2) // @
+
+#define KC_HASH LSFT(KC_3) // #
+
+#define KC_DLR LSFT(KC_4) // $
+#define KC_DOLLAR KC_DLR
+
+#define KC_PERC LSFT(KC_5) // %
+#define KC_PERCENT KC_PERC
+
+#define KC_CIRC LSFT(KC_6) // ^
+#define KC_CIRCUMFLEX KC_CIRC
+
+#define KC_AMPR LSFT(KC_7) // &
+#define KC_AMPERSAND KC_AMPR
+
+#define KC_ASTR LSFT(KC_8) // *
+#define KC_ASTERISK KC_ASTR
+
+#define KC_LPRN LSFT(KC_9) // (
+#define KC_LEFT_PAREN KC_LPRN
+
+#define KC_RPRN LSFT(KC_0) // )
+#define KC_RIGHT_PAREN KC_RPRN
+
+#define KC_UNDS LSFT(KC_MINS) // _
+#define KC_UNDERSCORE KC_UNDS
+
+#define KC_PLUS LSFT(KC_EQL) // +
+
+#define KC_LCBR LSFT(KC_LBRC) // {
+#define KC_LEFT_CURLY_BRACE KC_LCBR
+
+#define KC_RCBR LSFT(KC_RBRC) // }
+#define KC_RIGHT_CURLY_BRACE KC_RCBR
+
+#define KC_LABK LSFT(KC_COMM) // <
+#define KC_LEFT_ANGLE_BRACKET KC_LABK
+
+#define KC_RABK LSFT(KC_DOT) // >
+#define KC_RIGHT_ANGLE_BRACKET KC_RABK
+
+#define KC_COLN LSFT(KC_SCLN) // :
+#define KC_COLON KC_COLN
+
+#define KC_PIPE LSFT(KC_BSLS) // |
+
+#define KC_LT LSFT(KC_COMM) // <
+
+#define KC_GT LSFT(KC_DOT) // >
+
+#define KC_QUES LSFT(KC_SLSH) // ?
+#define KC_QUESTION KC_QUES
+
+#define KC_DQT LSFT(KC_QUOT) // "
+#define KC_DOUBLE_QUOTE KC_DQT
+#define KC_DQUO KC_DQT
+
+#define KC_DELT KC_DELETE // Del key (four letter code)
+
+// Alias for function layers than expand past FN31
+#define FUNC(kc) (kc | QK_FUNCTION)
+
+// Aliases
+#define S(kc) LSFT(kc)
+#define F(kc) FUNC(kc)
+
+#define M(kc) (kc | QK_MACRO)
+
+#define MACRODOWN(...) (record->event.pressed ? MACRO(__VA_ARGS__) : MACRO_NONE)
+
+// L-ayer, T-ap - 256 keycode max, 16 layer max
+#define LT(layer, kc) (kc | QK_LAYER_TAP | ((layer & 0xF) << 8))
+
+#define AG_SWAP MAGIC_SWAP_ALT_GUI
+#define AG_NORM MAGIC_UNSWAP_ALT_GUI
+
+#define BL_ON BL_9
+#define BL_OFF BL_0
+
+#define MI_ON MIDI_ON
+#define MI_OFF MIDI_OFF
+
+// GOTO layer - 16 layers max
+// when:
+// ON_PRESS = 1
+// ON_RELEASE = 2
+// Unless you have a good reason not to do so, prefer ON_PRESS (1) as your default.
+#define TO(layer, when) (layer | QK_TO | (when << 0x4))
+
+// Momentary switch layer - 256 layer max
+#define MO(layer) (layer | QK_MOMENTARY)
+
+// Set default layer - 256 layer max
+#define DF(layer) (layer | QK_DEF_LAYER)
+
+// Toggle to layer - 256 layer max
+#define TG(layer) (layer | QK_TOGGLE_LAYER)
+
+// One-shot layer - 256 layer max
+#define OSL(layer) (layer | QK_ONE_SHOT_LAYER)
+
+// One-shot mod
+#define OSM(layer) (layer | QK_ONE_SHOT_MOD)
+
+// M-od, T-ap - 256 keycode max
+#define MT(mod, kc) (kc | QK_MOD_TAP | ((mod & 0xF) << 8))
+#define CTL_T(kc) MT(MOD_LCTL, kc)
+#define SFT_T(kc) MT(MOD_LSFT, kc)
+#define ALT_T(kc) MT(MOD_LALT, kc)
+#define GUI_T(kc) MT(MOD_LGUI, kc)
+#define C_S_T(kc) MT((MOD_LCTL | MOD_LSFT), kc) // Control + Shift e.g. for gnome-terminal
+#define MEH_T(kc) MT((MOD_LCTL | MOD_LSFT | MOD_LALT), kc) // Meh is a less hyper version of the Hyper key -- doesn't include Win or Cmd, so just alt+shift+ctrl
+#define LCAG_T(kc) MT((MOD_LCTL | MOD_LALT | MOD_LGUI), kc) // Left control alt and gui
+#define ALL_T(kc) MT((MOD_LCTL | MOD_LSFT | MOD_LALT | MOD_LGUI), kc) // see http://brettterpstra.com/2012/12/08/a-useful-caps-lock-key/
+
+// Dedicated keycode versions for Hyper and Meh, if you want to use them as standalone keys rather than mod-tap
+#define KC_HYPR HYPR(KC_NO)
+#define KC_MEH MEH(KC_NO)
+
+#ifdef UNICODE_ENABLE
+ // For sending unicode codes.
+ // You may not send codes over 7FFF -- this supports most of UTF8.
+ // To have a key that sends out Œ, go UC(0x0152)
+ #define UNICODE(n) (n | QK_UNICODE)
+ #define UC(n) UNICODE(n)
+#endif
+
+
+#endif
diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c
new file mode 100644
index 000000000..76872ac59
--- /dev/null
+++ b/quantum/keymap_common.c
@@ -0,0 +1,171 @@
+/*
+Copyright 2012,2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "keymap.h"
+#include "report.h"
+#include "keycode.h"
+#include "action_layer.h"
+#if defined(__AVR__)
+#include <util/delay.h>
+#include <stdio.h>
+#endif
+#include "action.h"
+#include "action_macro.h"
+#include "debug.h"
+#include "backlight.h"
+#include "quantum.h"
+
+#ifdef MIDI_ENABLE
+ #include "keymap_midi.h"
+#endif
+
+extern keymap_config_t keymap_config;
+
+#include <inttypes.h>
+
+/* converts key to action */
+action_t action_for_key(uint8_t layer, keypos_t key)
+{
+ // 16bit keycodes - important
+ uint16_t keycode = keymap_key_to_keycode(layer, key);
+
+ // keycode remapping
+ keycode = keycode_config(keycode);
+
+ action_t action;
+ uint8_t action_layer, when, mod;
+ // The arm-none-eabi compiler generates out of bounds warnings when using the fn_actions directly for some reason
+ const uint16_t* actions = fn_actions;
+
+ switch (keycode) {
+ case KC_FN0 ... KC_FN31:
+ action.code = pgm_read_word(&actions[FN_INDEX(keycode)]);
+ break;
+ case KC_A ... KC_EXSEL:
+ case KC_LCTRL ... KC_RGUI:
+ action.code = ACTION_KEY(keycode);
+ break;
+ case KC_SYSTEM_POWER ... KC_SYSTEM_WAKE:
+ action.code = ACTION_USAGE_SYSTEM(KEYCODE2SYSTEM(keycode));
+ break;
+ case KC_AUDIO_MUTE ... KC_WWW_FAVORITES:
+ action.code = ACTION_USAGE_CONSUMER(KEYCODE2CONSUMER(keycode));
+ break;
+ case KC_MS_UP ... KC_MS_ACCEL2:
+ action.code = ACTION_MOUSEKEY(keycode);
+ break;
+ case KC_TRNS:
+ action.code = ACTION_TRANSPARENT;
+ break;
+ case QK_MODS ... QK_MODS_MAX: ;
+ // Has a modifier
+ // Split it up
+ action.code = ACTION_MODS_KEY(keycode >> 8, keycode & 0xFF); // adds modifier to key
+ break;
+ case QK_FUNCTION ... QK_FUNCTION_MAX: ;
+ // Is a shortcut for function action_layer, pull last 12bits
+ // This means we have 4,096 FN macros at our disposal
+ action.code = pgm_read_word(&actions[(int)keycode & 0xFFF]);
+ break;
+ case QK_MACRO ... QK_MACRO_MAX:
+ action.code = ACTION_MACRO(keycode & 0xFF);
+ break;
+ case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
+ action.code = ACTION_LAYER_TAP_KEY((keycode >> 0x8) & 0xF, keycode & 0xFF);
+ break;
+ case QK_TO ... QK_TO_MAX: ;
+ // Layer set "GOTO"
+ when = (keycode >> 0x4) & 0x3;
+ action_layer = keycode & 0xF;
+ action.code = ACTION_LAYER_SET(action_layer, when);
+ break;
+ case QK_MOMENTARY ... QK_MOMENTARY_MAX: ;
+ // Momentary action_layer
+ action_layer = keycode & 0xFF;
+ action.code = ACTION_LAYER_MOMENTARY(action_layer);
+ break;
+ case QK_DEF_LAYER ... QK_DEF_LAYER_MAX: ;
+ // Set default action_layer
+ action_layer = keycode & 0xFF;
+ action.code = ACTION_DEFAULT_LAYER_SET(action_layer);
+ break;
+ case QK_TOGGLE_LAYER ... QK_TOGGLE_LAYER_MAX: ;
+ // Set toggle
+ action_layer = keycode & 0xFF;
+ action.code = ACTION_LAYER_TOGGLE(action_layer);
+ break;
+ case QK_ONE_SHOT_LAYER ... QK_ONE_SHOT_LAYER_MAX: ;
+ // OSL(action_layer) - One-shot action_layer
+ action_layer = keycode & 0xFF;
+ action.code = ACTION_LAYER_ONESHOT(action_layer);
+ break;
+ case QK_ONE_SHOT_MOD ... QK_ONE_SHOT_MOD_MAX: ;
+ // OSM(mod) - One-shot mod
+ mod = keycode & 0xFF;
+ action.code = ACTION_MODS_ONESHOT(mod);
+ break;
+ case QK_MOD_TAP ... QK_MOD_TAP_MAX:
+ action.code = ACTION_MODS_TAP_KEY((keycode >> 0x8) & 0xF, keycode & 0xFF);
+ break;
+ #ifdef BACKLIGHT_ENABLE
+ case BL_0 ... BL_15:
+ action.code = ACTION_BACKLIGHT_LEVEL(keycode - BL_0);
+ break;
+ case BL_DEC:
+ action.code = ACTION_BACKLIGHT_DECREASE();
+ break;
+ case BL_INC:
+ action.code = ACTION_BACKLIGHT_INCREASE();
+ break;
+ case BL_TOGG:
+ action.code = ACTION_BACKLIGHT_TOGGLE();
+ break;
+ case BL_STEP:
+ action.code = ACTION_BACKLIGHT_STEP();
+ break;
+ #endif
+ default:
+ action.code = ACTION_NO;
+ break;
+ }
+ return action;
+}
+
+__attribute__ ((weak))
+const uint16_t PROGMEM fn_actions[] = {
+
+};
+
+/* Macro */
+__attribute__ ((weak))
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ return MACRO_NONE;
+}
+
+/* Function */
+__attribute__ ((weak))
+void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+}
+
+/* translates key to keycode */
+uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key)
+{
+ // Read entire word (16bits)
+ return pgm_read_word(&keymaps[(layer)][(key.row)][(key.col)]);
+}
diff --git a/quantum/keymap_extras/keymap_bepo.h b/quantum/keymap_extras/keymap_bepo.h
new file mode 100644
index 000000000..4c3096054
--- /dev/null
+++ b/quantum/keymap_extras/keymap_bepo.h
@@ -0,0 +1,311 @@
+/* Keymap macros for the French BÉPO layout - http://bepo.fr */
+#ifndef KEYMAP_BEPO_H
+#define KEYMAP_BEPO_H
+
+#include "keymap.h"
+
+// Alt gr
+#ifndef ALTGR
+#define ALTGR(kc) RALT(kc)
+#endif
+#ifndef ALGR
+#define ALGR(kc) ALTGR(kc)
+#endif
+#define BP_ALGR KC_RALT
+
+// Normal characters
+// First row (on usual keyboards)
+#define BP_DOLLAR KC_GRAVE // $
+#define BP_DLR BP_DOLLAR
+#define BP_DOUBLE_QUOTE KC_1 // "
+#define BP_DQOT BP_DOUBLE_QUOTE
+#define BP_LEFT_GUILLEMET KC_2 // «
+#define BP_LGIL BP_LEFT_GUILLEMET
+#define BP_RIGHT_GUILLEMET KC_3 // »
+#define BP_RGIL BP_RIGHT_GUILLEMET
+#define BP_LEFT_PAREN KC_4 // (
+#define BP_LPRN BP_LEFT_PAREN
+#define BP_RIGHT_PAREN KC_5 // )
+#define BP_RPRN BP_RIGHT_PAREN
+#define BP_AT KC_6 // @
+#define BP_PLUS KC_7 // +
+#define BP_MINUS KC_8 // -
+#define BP_MINS BP_MINUS
+#define BP_SLASH KC_9 // /
+#define BP_SLSH BP_SLASH
+#define BP_ASTERISK KC_0 // *
+#define BP_ASTR BP_ASTERISK
+#define BP_EQUAL KC_MINUS // =
+#define BP_EQL BP_EQUAL
+#define BP_PERCENT KC_EQUAL // %
+#define BP_PERC BP_PERCENT
+
+// Second row
+#define BP_B KC_Q
+#define BP_E_ACUTE KC_W // é
+#define BP_ECUT BP_E_ACUTE
+#define BP_P KC_E
+#define BP_O KC_R
+#define BP_E_GRAVE KC_T // è
+#define BP_EGRV BP_E_GRAVE
+#define BP_DEAD_CIRCUMFLEX KC_Y // dead ^
+#define BP_DCRC BP_DEAD_CIRCUMFLEX
+#define BP_V KC_U
+#define BP_D KC_I
+#define BP_L KC_O
+#define BP_J KC_P
+#define BP_Z KC_LBRACKET
+#define BP_W KC_RBRACKET
+
+// Third row
+#define BP_A KC_A
+#define BP_U KC_S
+#define BP_I KC_D
+#define BP_E KC_F
+#define BP_COMMA KC_G // ,
+#define BP_COMM BP_COMMA
+#define BP_C KC_H
+#define BP_T KC_J
+#define BP_S KC_K
+#define BP_R KC_L
+#define BP_N KC_SCOLON
+#define BP_M KC_QUOTE
+#define BP_C_CEDILLA KC_BSLASH // ç
+#define BP_CCED BP_C_CEDILLA
+
+// Fourth row
+#define BP_E_CIRCUMFLEX KC_NONUS_BSLASH // ê
+#define BP_ECRC BP_E_CIRCUMFLEX
+#define BP_A_GRAVE KC_Z // à
+#define BP_AGRV BP_A_GRAVE
+#define BP_Y KC_X
+#define BP_X KC_C
+#define BP_DOT KC_V // .
+#define BP_K KC_B
+#define BP_APOSTROPHE KC_N
+#define BP_APOS BP_APOSTROPHE // '
+#define BP_Q KC_M
+#define BP_G KC_COMMA
+#define BP_H KC_DOT
+#define BP_F KC_SLASH
+
+// Shifted characters
+// First row
+#define BP_HASH LSFT(BP_DOLLAR) // #
+#define BP_1 LSFT(KC_1)
+#define BP_2 LSFT(KC_2)
+#define BP_3 LSFT(KC_3)
+#define BP_4 LSFT(KC_4)
+#define BP_5 LSFT(KC_5)
+#define BP_6 LSFT(KC_6)
+#define BP_7 LSFT(KC_7)
+#define BP_8 LSFT(KC_8)
+#define BP_9 LSFT(KC_9)
+#define BP_0 LSFT(KC_0)
+#define BP_DEGREE LSFT(BP_EQUAL) // °
+#define BP_DEGR BP_DEGREE
+#define BP_GRAVE LSFT(BP_PERCENT) // `
+#define BP_GRV BP_GRAVE
+
+// Second row
+#define BP_EXCLAIM LSFT(BP_DEAD_CIRCUMFLEX) // !
+#define BP_EXLM BP_EXCLAIM
+
+// Third row
+#define BP_SCOLON LSFT(BP_COMMA) // ;
+#define BP_SCLN BP_SCOLON
+
+// Fourth row
+#define BP_COLON LSFT(BP_DOT) // :
+#define BP_COLN BP_COLON
+#define BP_QUESTION LSFT(BP_QUOTE) // ?
+#define BP_QEST BP_QUESTION
+
+// Space bar
+#define BP_NON_BREAKING_SPACE LSFT(KC_SPACE)
+#define BP_NBSP BP_NON_BREAKING_SPACE
+
+// AltGr-ed characters
+// First row
+#define BP_EN_DASH ALTGR(BP_DOLLAR) // –
+#define BP_NDSH BP_EN_DASH
+#define BP_EM_DASH ALTGR(KC_1) // —
+#define BP_MDSH BP_EM_DASH
+#define BP_LESS ALTGR(KC_2) // <
+#define BP_GREATER ALTGR(KC_3) // >
+#define BP_GRTR BP_GREATER
+#define BP_LBRACKET ALTGR(KC_4) // [
+#define BP_LBRC BP_LBRACKET
+#define BP_RBRACKET ALTGR(KC_5) // ]
+#define BP_RBRC BP_RBRACKET
+#define BP_CIRCUMFLEX ALTGR(KC_6) // ^
+#define BP_CIRC BP_CIRCUMFLEX
+#define BP_PLUS_MINUS ALTGR(KC_7) // ±
+#define BP_PSMS BP_PLUS_MINUS
+#define BP_MATH_MINUS ALTGR(KC_8) // −
+#define BP_MMNS BP_MATH_MINUS
+#define BP_OBELUS ALTGR(KC_9) // ÷
+#define BP_OBEL BP_OBELUS
+// more conventional name of the symbol
+#define BP_DIVISION_SIGN BP_OBELUS
+#define BP_DVSN BP_DIVISION_SIGN
+#define BP_TIMES ALTGR(KC_0) // ×
+#define BP_TIMS BP_TIMES
+#define BP_DIFFERENT ALTGR(BP_EQUAL) // ≠
+#define BP_DIFF BP_DIFFERENT
+#define BP_PERMILLE ALTGR(BP_PERCENT) // ‰
+#define BP_PMIL BP_PERMILLE
+
+// Second row
+#define BP_PIPE ALTGR(BP_B) // |
+#define BP_DEAD_ACUTE ALTGR(BP_E_ACUTE) // dead ´
+#define BP_DACT BP_DEAD_ACUTE
+#define BP_AMPERSAND ALTGR(BP_P) // &
+#define BP_AMPR BP_AMPERSAND
+#define BP_OE_LIGATURE ALTGR(BP_O) // œ
+#define BP_OE BP_OE_LIGATURE
+#define BP_DEAD_GRAVE ALTGR(BP_E_GRAVE) // `
+#define BP_DGRV BP_DEAD_GRAVE
+#define BP_INVERTED_EXCLAIM ALTGR(BP_DEAD_CIRCUMFLEX) // ¡
+#define BP_IXLM BP_INVERTED_EXCLAIM
+#define BP_DEAD_CARON ALTGR(BP_V) // dead ˇ
+#define BP_DCAR BP_DEAD_CARON
+#define BP_ETH ALTGR(BP_D) // ð
+#define BP_DEAD_SLASH ALTGR(BP_L) // dead /
+#define BP_DSLH BP_DEAD_SLASH
+#define BP_IJ_LIGATURE ALTGR(BP_J) // ij
+#define BP_IJ BP_IJ_LIGATURE
+#define BP_SCHWA ALTGR(BP_Z) // ə
+#define BP_SCWA BP_SCHWA
+#define BP_DEAD_BREVE ALTGR(BP_W) // dead ˘
+#define BP_DBRV BP_DEAD_BREVE
+
+// Third row
+#define BP_AE_LIGATURE ALTGR(BP_A) // æ
+#define BP_AE BP_AE_LIGATURE
+#define BP_U_GRAVE AGR(BP_U) // ù
+#define BP_UGRV BP_U_GRAVE
+#define BP_DEAD_TREMA ALTGR(BP_I) // dead ¨ (trema/umlaut/diaresis)
+#define BP_DTRM BP_DEAD_TREMA
+#define BP_EURO ALTGR(BP_E) // €
+#define BP_TYPOGRAPHICAL_APOSTROPHE ALTGR(BP_COMMMA) // ’
+#define BP_TAPO BP_TYPOGRAPHICAL_APOSTROPHE
+#define BP_COPYRIGHT ALTGR(BP_C) // ©
+#define BP_CPRT BP_COPYRIGHT
+#define BP_THORN ALTGR(BP_T) // þ
+#define BP_THRN BP_THORN
+#define BP_SHARP_S ALTGR(BP_S) // ß
+#define BP_SRPS BP_SHARP_S
+#define BP_REGISTERED_TRADEMARK ALTGR(BP_R) // ®
+#define BP_RTM BP_REGISTERED_TRADEMARK
+#define BP_DEAD_TILDE ALTGR(BP_N) // dead ~
+#define BP_DTLD BP_DEAD_TILDE
+#define BP_DEAD_MACRON ALTGR(BP_M) // dead ¯
+#define BP_DMCR BP_DEAD_MACRON
+#define BP_DEAD_CEDILLA ALTGR(BP_C_CEDILLA) // dead ¸
+#define BP_DCED BP_DEAD_CEDILLA
+
+// Fourth row
+#define BP_NONUS_SLASH ALTGR(BP_E_CIRCUMFLEX) // / on non-us backslash key (102nd key, ê in bépo)
+#define BP_NUSL BP_NONUS_SLASH
+#define BP_BACKSLASH ALTGR(BP_A_GRAVE) /* \ */
+#define BP_BSLS BP_BACKSLASH
+#define BP_LEFT_CURLY_BRACE ALTGR(BP_Y) // {
+#define BP_LCBR BP_LEFT_CURLY_BRACE
+#define BP_RIGHT_CURLY_BRACE ALTGR(BP_X) // }
+#define BP_RCBR BP_RIGHT_CURLY_BRACE
+#define BP_ELLIPSIS ALTGR(BP_DOT) // …
+#define BP_ELPS BP_ELLIPSIS
+#define BP_TILDE ALTGR(BP_K) // ~
+#define BP_TILD BP_TILDE
+#define BP_INVERTED_QUESTION ALTGR(BP_QUESTION) // ¿
+#define BP_IQST BP_INVERTED_QUESTION
+#define BP_DEAD_RING ALTGR(BP_Q) // dead °
+#define BP_DRNG BP_DEAD_RING
+#define BP_DEAD_GREEK ALTGR(BP_G) // dead Greek key (following key will make a Greek letter)
+#define BP_DGRK BP_DEAD_GREEK
+#define BP_DAGGER ALTGR(BP_H) // †
+#define BP_DAGR BP_DAGGER
+#define BP_DEAD_OGONEK ALTGR(BP_F) // dead ˛
+#define BP_DOGO BP_DEAD_OGONEK
+
+// Space bar
+#define BP_UNDERSCORE ALTGR(KC_SPACE) // _
+#define BP_UNDS BP_UNDERSCORE
+
+// AltGr-Shifted characters (different from capitalised AltGr-ed characters)
+// First row
+#define BP_PARAGRAPH ALTGR(BP_HASH) // ¶
+#define BP_PARG BP_PARAGRAPH
+#define BP_LOW_DOUBLE_QUOTE ALTGR(BP_1) // „
+#define BP_LWQT BP_LOW_DOUBLE_QUOTE
+#define BP_LEFT_DOUBLE_QUOTE ALTGR(BP_2) // “
+#define BP_LDQT BP_LEFT_DOUBLE_QUOTE
+#define BP_RIGHT_DOUBLE_QUOTE ALTGR(BP_3) // ”
+#define BP_RDQT BP_RIGHT_DOUBLE_QUOTE
+#define BP_LESS_OR_EQUAL ALTGR(BP_4) // ≤
+#define BP_LEQL BP_LESS_OR_EQUAL
+#define BP_GREATER_OR_EQUAL ALTGR(BP_5) // ≥
+#define BP_GEQL BP_GREATER_OR_EQUAL
+// nothing on ALTGR(BP_6)
+#define BP_NEGATION ALTGR(BP_7) // ¬
+#define BP_NEGT BP_NEGATION
+#define BP_ONE_QUARTER ALTGR(BP_8) // ¼
+#define BP_1QRT BP_ONE_QUARTER
+#define BP_ONE_HALF ALTGR(BP_9) // ½
+#define BP_1HLF BP_ONE_HALF
+#define BP_THREE_QUARTERS ALTGR(BP_0) // ¾
+#define BP_3QRT BP_THREE_QUARTERS
+#define BP_MINUTES ALTGR(BP_DEGREE) // ′
+#define BP_MNUT BP_MINUTES
+#define BP_SECONDS ALTGR(BP_GRAVE) // ″
+#define BP_SCND BP_SECONDS
+
+// Second row
+#define BP_BROKEN_PIPE LSFT(BP_PIPE) // ¦
+#define BP_BPIP BP_BROKEN_PIPE
+#define BP_DEAD_DOUBLE_ACUTE LSFT(BP_DEAD_ACUTE) // ˝
+#define BP_DDCT BP_DEAD_DOUBLE_ACUTE
+#define BP_SECTION ALTGR(LSFT(BP_P)) // §
+#define BP_SECT BP_SECTION
+// LSFT(BP_DEAD_GRAVE) is actually the same character as LSFT(BP_PERCENT)
+#define BP_GRAVE_BIS LSFT(BP_DEAD_GRAVE) // `
+#define BP_GRVB BP_GRAVE_BIS
+
+// Third row
+#define BP_DEAD_DOT_ABOVE LSFT(BP_DEAD_TREMA) // dead ˙
+#define BP_DDTA BP_DEAD_DOT_ABOVE
+#define BP_DEAD_CURRENCY LSFT(BP_EURO) // dead ¤ (next key will generate a currency code like ¥ or £)
+#define BP_DCUR BP_DEAD_CURRENCY
+#define BP_DEAD_HORN LSFT(ALTGR(BP_COMMA)) // dead ̛
+#define BP_DHRN BP_DEAD_HORN
+#define BP_LONG_S LSFT(ALTGR(BP_C)) // ſ
+#define BP_LNGS BP_LONG_S
+#define BP_TRADEMARK LSFT(BP_REGISTERED_TRADEMARK) // ™
+#define BP_TM BP_TRADEMARK
+#define BP_ORDINAL_INDICATOR_O LSFT(ALTGR(BP_M)) // º
+#define BP_ORDO BP_ORDINAL_INDICATOR_O
+#define BP_DEAD_COMMA LSFT(BP_DEAD_CEDILLA) // dead ˛
+#define BP_DCOM BP_DEAD_COMMA
+
+// Fourth row
+#define BP_LEFT_QUOTE LSFT(ALTGR(BP_Y)) // ‘
+#define BP_LQOT BP_LEFT_QUOTE
+#define BP_RIGHT_QUOTE LSFT(ALTGR(BP_X)) // ’
+#define BP_RQOT BP_RIGHT_QUOTE
+#define BP_INTERPUNCT LSFT(ALTGR(BP_DOT)) // ·
+#define BP_IPCT BP_INTERPUNCT
+#define BP_DEAD_HOOK_ABOVE LSFT(ALTGR(BP_QUESTION)) // dead ̉
+#define BP_DHKA BP_DEAD_HOOK_ABOVE
+#define BP_DEAD_UNDERDOT LSFT(BP_DEAD_RING) // dead ̣
+#define BP_DUDT BP_DEAD_UNDERDOT
+#define BP_DOUBLE_DAGGER LSFT(BP_DAGGER) // ‡
+#define BP_DDGR BP_DOUBLE_DAGGER
+#define BP_ORDINAL_INDICATOR_A LSFT(ALTGR(BP_F)) // ª
+#define BP_ORDA BP_ORDINAL_INDICATOR_A
+
+// Space bar
+#define BP_NARROW_NON_BREAKING_SPACE ALTGR(BP_NON_BREAKING_SPACE)
+#define BP_NNBS BP_NARROW_NON_BREAKING_SPACE
+
+#endif
diff --git a/quantum/keymap_extras/keymap_colemak.h b/quantum/keymap_extras/keymap_colemak.h
new file mode 100644
index 000000000..b8d615748
--- /dev/null
+++ b/quantum/keymap_extras/keymap_colemak.h
@@ -0,0 +1,75 @@
+#ifndef KEYMAP_COLEMAK_H
+#define KEYMAP_COLEMAK_H
+
+#include "keymap.h"
+// For software implementation of colemak
+#define CM_Q KC_Q
+#define CM_W KC_W
+#define CM_F KC_E
+#define CM_P KC_R
+#define CM_G KC_T
+#define CM_J KC_Y
+#define CM_L KC_U
+#define CM_U KC_I
+#define CM_Y KC_O
+#define CM_SCLN KC_P
+
+#define CM_A KC_A
+#define CM_R KC_S
+#define CM_S KC_D
+#define CM_T KC_F
+#define CM_D KC_G
+#define CM_H KC_H
+#define CM_N KC_J
+#define CM_E KC_K
+#define CM_I KC_L
+#define CM_O KC_SCLN
+#define CM_COLN LSFT(CM_SCLN)
+
+#define CM_Z KC_Z
+#define CM_X KC_X
+#define CM_C KC_C
+#define CM_V KC_V
+#define CM_B KC_B
+#define CM_K KC_N
+#define CM_M KC_M
+#define CM_COMM KC_COMM
+#define CM_DOT KC_DOT
+#define CM_SLSH KC_SLSH
+
+// Make it easy to support these in macros
+// TODO: change macro implementation so these aren't needed
+#define KC_CM_Q CM_Q
+#define KC_CM_W CM_W
+#define KC_CM_F CM_F
+#define KC_CM_P CM_P
+#define KC_CM_G CM_G
+#define KC_CM_J CM_J
+#define KC_CM_L CM_L
+#define KC_CM_U CM_U
+#define KC_CM_Y CM_Y
+#define KC_CM_SCLN CM_SCLN
+
+#define KC_CM_A CM_A
+#define KC_CM_R CM_R
+#define KC_CM_S CM_S
+#define KC_CM_T CM_T
+#define KC_CM_D CM_D
+#define KC_CM_H CM_H
+#define KC_CM_N CM_N
+#define KC_CM_E CM_E
+#define KC_CM_I CM_I
+#define KC_CM_O CM_O
+
+#define KC_CM_Z CM_Z
+#define KC_CM_X CM_X
+#define KC_CM_C CM_C
+#define KC_CM_V CM_V
+#define KC_CM_B CM_B
+#define KC_CM_K CM_K
+#define KC_CM_M CM_M
+#define KC_CM_COMM CM_COMM
+#define KC_CM_DOT CM_DOT
+#define KC_CM_SLSH CM_SLSH
+
+#endif
diff --git a/quantum/keymap_extras/keymap_dvorak.h b/quantum/keymap_extras/keymap_dvorak.h
new file mode 100644
index 000000000..e855056e8
--- /dev/null
+++ b/quantum/keymap_extras/keymap_dvorak.h
@@ -0,0 +1,74 @@
+#ifndef KEYMAP_DVORAK_H
+#define KEYMAP_DVORAK_H
+
+#include "keymap.h"
+
+// Normal characters
+#define DV_GRV KC_GRV
+#define DV_1 KC_1
+#define DV_2 KC_2
+#define DV_3 KC_3
+#define DV_4 KC_4
+#define DV_5 KC_5
+#define DV_6 KC_6
+#define DV_7 KC_7
+#define DV_8 KC_8
+#define DV_9 KC_9
+#define DV_0 KC_0
+#define DV_LBRC KC_MINS
+#define DV_RBRC KC_EQL
+
+#define DV_QUOT KC_Q
+#define DV_COMM KC_W
+#define DV_DOT KC_E
+#define DV_P KC_R
+#define DV_Y KC_T
+#define DV_F KC_Y
+#define DV_G KC_U
+#define DV_C KC_I
+#define DV_R KC_O
+#define DV_L KC_P
+#define DV_SLSH KC_LBRC
+#define DV_EQL KC_RBRC
+
+#define DV_A KC_A
+#define DV_O KC_S
+#define DV_E KC_D
+#define DV_U KC_F
+#define DV_I KC_G
+#define DV_D KC_H
+#define DV_H KC_J
+#define DV_T KC_K
+#define DV_N KC_L
+#define DV_S KC_SCLN
+#define DV_MINS KC_QUOT
+
+#define DV_SCLN KC_Z
+#define DV_Q KC_X
+#define DV_J KC_C
+#define DV_K KC_V
+#define DV_X KC_B
+#define DV_B KC_N
+#define DV_M KC_M
+#define DV_W KC_COMM
+#define DV_V KC_DOT
+#define DV_Z KC_SLSH
+
+// Shifted characters
+#define DV_TILD LSFT(DV_GRV)
+#define DV_EXLM LSFT(DV_1)
+#define DV_AT LSFT(DV_2)
+#define DV_HASH LSFT(DV_3)
+#define DV_DLR LSFT(DV_4)
+#define DV_PERC LSFT(DV_5)
+#define DV_CIRC LSFT(DV_6)
+#define DV_AMPR LSFT(DV_7)
+#define DV_ASTR LSFT(DV_8)
+#define DV_LPRN LSFT(DV_9)
+#define DV_RPRN LSFT(DV_0)
+#define DV_LCBR LSFT(DV_LBRC)
+#define DV_RCBR LSFT(DV_RBRC)
+#define DV_UNDS LSFT(DV_MINS)
+#define DV_PLUS LSFT(DV_EQL)
+
+#endif
diff --git a/quantum/keymap_extras/keymap_fr_ch.h b/quantum/keymap_extras/keymap_fr_ch.h
new file mode 100644
index 000000000..3fd971357
--- /dev/null
+++ b/quantum/keymap_extras/keymap_fr_ch.h
@@ -0,0 +1,98 @@
+#ifndef KEYMAP_FR_CH
+#define KEYMAP_FR_CH
+
+#include "keymap.h"
+
+// Alt gr
+#define ALGR(kc) kc | 0x1400
+#define FR_CH_ALGR KC_RALT
+
+// normal characters
+#define FR_CH_Z KC_Y
+#define FR_CH_Y KC_Z
+
+#define FR_CH_A KC_A
+#define FR_CH_B KC_B
+#define FR_CH_C KC_C
+#define FR_CH_D KC_D
+#define FR_CH_E KC_E
+#define FR_CH_F KC_F
+#define FR_CH_G KC_G
+#define FR_CH_H KC_H
+#define FR_CH_I KC_I
+#define FR_CH_J KC_J
+#define FR_CH_K KC_K
+#define FR_CH_L KC_L
+#define FR_CH_M KC_M
+#define FR_CH_N KC_N
+#define FR_CH_O KC_O
+#define FR_CH_P KC_P
+#define FR_CH_Q KC_Q
+#define FR_CH_R KC_R
+#define FR_CH_S KC_S
+#define FR_CH_T KC_T
+#define FR_CH_U KC_U
+#define FR_CH_V KC_V
+#define FR_CH_W KC_W
+#define FR_CH_X KC_X
+
+#define FR_CH_0 KC_0
+#define FR_CH_1 KC_1
+#define FR_CH_2 KC_2
+#define FR_CH_3 KC_3
+#define FR_CH_4 KC_4
+#define FR_CH_5 KC_5
+#define FR_CH_6 KC_6
+#define FR_CH_7 KC_7
+#define FR_CH_8 KC_8
+#define FR_CH_9 KC_9
+
+#define FR_CH_DOT KC_DOT
+#define FR_CH_COMM KC_COMM
+
+#define FR_CH_QUOT KC_MINS
+#define FR_CH_AE KC_QUOT
+#define FR_CH_UE KC_LBRC
+#define FR_CH_OE KC_SCLN
+
+#define FR_CH_CIRC KC_EQL // accent circumflex ^ and grave ` and ~
+#define FR_CH_LESS KC_NUBS // < and > and backslash
+#define FR_CH_MINS KC_SLSH // - and _
+#define FR_CH_DLR KC_BSLS // $, £ and }
+#define FR_CH_PARA KC_GRV // § and ring °
+#define FR_CH_DIAE KC_RBRC // accent ¨
+
+// shifted characters
+#define FR_CH_RING LSFT(KC_GRV) // °
+#define FR_CH_EXLM LSFT(KC_RBRC) // !
+#define FR_CH_PLUS LSFT(KC_1) // +
+#define FR_CH_DQOT LSFT(KC_2) // "
+#define FR_CH_ASTR LSFT(KC_3) // *
+#define FR_CH_PERC LSFT(KC_5) // %
+#define FR_CH_AMPR LSFT(KC_6) // &
+#define FR_CH_SLSH LSFT(KC_7) // /
+#define FR_CH_LPRN LSFT(KC_8) // (
+#define FR_CH_RPRN LSFT(KC_9) // )
+#define FR_CH_EQL LSFT(KC_0) // =
+#define FR_CH_QST LSFT(FR_CH_QUOT) // ?
+#define FR_CH_MORE LSFT(FR_CH_LESS) // >
+#define FR_CH_COLN LSFT(KC_DOT) // :
+#define FR_CH_SCLN LSFT(KC_COMM) // ;
+#define FR_CH_UNDS LSFT(FR_CH_MINS) // _
+#define FR_CH_CCED LSFT(KC_4) // ç
+#define FR_CH_GRV LSFT(FR_CH_CIRC) // accent grave `
+
+// Alt Gr-ed characters
+#define FR_CH_LCBR ALGR(KC_QUOT) // {
+#define FR_CH_LBRC ALGR(KC_LBRC) // [
+#define FR_CH_RBRC ALGR(KC_9) // ]
+#define FR_CH_RCBR ALGR(KC_0) // }
+#define FR_CH_BSLS ALGR(FR_CH_LESS) // backslash
+#define FR_CH_AT ALGR(KC_2) // @
+#define FR_CH_EURO ALGR(KC_E) // €
+#define FR_CH_TILD ALGR(FR_CH_CIRC) // ~
+#define FR_CH_PIPE ALGR(KC_1) // |
+#define FR_CH_HASH ALGR(KC_3) // #
+#define FR_CH_ACUT ALGR(FR_CH_QUOT) // accent acute ´
+
+#endif
diff --git a/quantum/keymap_extras/keymap_french.h b/quantum/keymap_extras/keymap_french.h
new file mode 100644
index 000000000..2a44c80b1
--- /dev/null
+++ b/quantum/keymap_extras/keymap_french.h
@@ -0,0 +1,83 @@
+#ifndef KEYMAP_FRENCH_H
+#define KEYMAP_FRENCH_H
+
+#include "keymap.h"
+
+// Alt gr
+#define ALGR(kc) kc | 0x1400
+#define NO_ALGR KC_RALT
+
+// Normal characters
+#define FR_SUP2 KC_GRV
+#define FR_AMP KC_1
+#define FR_EACU KC_2
+#define FR_QUOT KC_3
+#define FR_APOS KC_4
+#define FR_LPRN KC_5
+#define FR_MINS KC_6
+#define FR_EGRV KC_7
+#define FR_UNDS KC_8
+#define FR_CCED KC_9
+#define FR_AGRV KC_0
+#define FR_RPRN KC_MINS
+#define FR_EQL KC_EQL
+
+#define FR_A KC_Q
+#define FR_Z KC_W
+#define FR_CIRC KC_LBRC
+#define FR_DLR KC_RBRC
+
+#define FR_Q KC_A
+#define FR_M KC_SCLN
+#define FR_UGRV KC_QUOT
+#define FR_ASTR KC_NUHS
+
+#define FR_LESS KC_NUBS
+#define FR_W KC_Z
+#define FR_COMM KC_M
+#define FR_SCLN KC_COMM
+#define FR_COLN KC_DOT
+#define FR_EXLM KC_SLSH
+
+// Shifted characters
+#define FR_1 LSFT(KC_1)
+#define FR_2 LSFT(KC_2)
+#define FR_3 LSFT(KC_3)
+#define FR_4 LSFT(KC_4)
+#define FR_5 LSFT(KC_5)
+#define FR_6 LSFT(KC_6)
+#define FR_7 LSFT(KC_7)
+#define FR_8 LSFT(KC_8)
+#define FR_9 LSFT(KC_9)
+#define FR_0 LSFT(KC_0)
+#define FR_OVRR LSFT(FR_RPRN)
+#define FR_PLUS LSFT(FR_EQL)
+
+#define FR_UMLT LSFT(FR_CIRC)
+#define FR_PND LSFT(FR_DLR)
+#define FR_PERC LSFT(FR_UGRV)
+#define FR_MU LSFT(FR_ASTR)
+
+#define FR_GRTR LSFT(FR_LESS)
+#define FR_QUES LSFT(FR_COMM)
+#define FR_DOT LSFT(FR_SCLN)
+#define FR_SLSH LSFT(FR_COLN)
+#define FR_SECT LSFT(FR_EXLM)
+
+// Alt Gr-ed characters
+#define FR_TILD ALGR(KC_2)
+#define FR_HASH ALGR(KC_3)
+#define FR_LCBR ALGR(KC_4)
+#define FR_LBRC ALGR(KC_5)
+#define FR_PIPE ALGR(KC_6)
+#define FR_GRV ALGR(KC_7)
+#define FR_BSLS ALGR(KC_8)
+#define FR_CIRC ALGR(KC_9)
+#define FR_AT ALGR(KC_0)
+#define FR_RBRC ALGR(FR_RPRN)
+#define FR_RCBR ALGR(FR_EQL)
+
+#define FR_EURO ALGR(KC_E)
+#define FR_BULT ALGR(FR_DLR)
+
+#endif \ No newline at end of file
diff --git a/quantum/keymap_extras/keymap_french_osx.h b/quantum/keymap_extras/keymap_french_osx.h
new file mode 100644
index 000000000..004d73ee2
--- /dev/null
+++ b/quantum/keymap_extras/keymap_french_osx.h
@@ -0,0 +1,77 @@
+#ifndef KEYMAP_FRENCH_OSX_H
+#define KEYMAP_FRENCH_OSX_H
+
+#include "keymap.h"
+
+// Normal characters
+#define FR_AT KC_GRV
+#define FR_AMP KC_1
+#define FR_EACU KC_2
+#define FR_QUOT KC_3
+#define FR_APOS KC_4
+#define FR_LPRN KC_5
+#define FR_SECT KC_6
+#define FR_EGRV KC_7
+#define FR_EXLM KC_8
+#define FR_CCED KC_9
+#define FR_AGRV KC_0
+#define FR_RPRN KC_MINS
+#define FR_MINS KC_EQL
+
+#define FR_A KC_Q
+#define FR_Z KC_W
+#define FR_CIRC KC_LBRC
+#define FR_DLR KC_RBRC
+
+#define FR_Q KC_A
+#define FR_M KC_SCLN
+#define FR_UGRV KC_QUOT
+#define FR_GRV KC_NUHS
+
+#define FR_LESS KC_NUBS
+#define FR_W KC_Z
+#define FR_COMM KC_M
+#define FR_SCLN KC_COMM
+#define FR_COLN KC_DOT
+#define FR_EQL KC_SLSH
+
+// Shifted characters
+#define FR_HASH LSFT(KC_GRV)
+#define FR_1 LSFT(KC_1)
+#define FR_2 LSFT(KC_2)
+#define FR_3 LSFT(KC_3)
+#define FR_4 LSFT(KC_4)
+#define FR_5 LSFT(KC_5)
+#define FR_6 LSFT(KC_6)
+#define FR_7 LSFT(KC_7)
+#define FR_8 LSFT(KC_8)
+#define FR_9 LSFT(KC_9)
+#define FR_0 LSFT(KC_0)
+#define FR_UNDS LSFT(FR_MINS)
+
+#define FR_UMLT LSFT(FR_CIRC)
+#define FR_ASTR LSFT(FR_DLR)
+
+#define FR_PERC LSFT(FR_UGRV)
+#define FR_PND LSFT(FR_GRV)
+
+#define FR_GRTR LSFT(FR_LESS)
+#define FR_QUES LSFT(FR_COMM)
+#define FR_DOT LSFT(FR_SCLN)
+#define FR_SLSH LSFT(FR_COLN)
+#define FR_PLUS LSFT(FR_EQL)
+
+// Alted characters
+#define FR_LCBR LALT(KC_5)
+#define FR_RCBR LALT(FR_RPRN)
+#define FR_EURO LALT(KC_E)
+#define FR_BULT LALT(FR_DLR)
+#define FR_TILD LALT(KC_N)
+
+// Shift+Alt-ed characters
+#define FR_LBRC LSFT(LALT(KC_5))
+#define FR_RBRC LSFT(LALT(FR_RPRN))
+#define FR_PIPE LSFT(LALT(KC_L))
+#define FR_BSLS LSFT(LALT(FR_COLN))
+
+#endif \ No newline at end of file
diff --git a/quantum/keymap_extras/keymap_german.h b/quantum/keymap_extras/keymap_german.h
new file mode 100644
index 000000000..3f9ae8bad
--- /dev/null
+++ b/quantum/keymap_extras/keymap_german.h
@@ -0,0 +1,99 @@
+#ifndef KEYMAP_GERMAN
+#define KEYMAP_GERMAN
+
+#include "keymap.h"
+
+// Alt gr
+#define ALGR(kc) kc | 0x1400
+#define DE_ALGR KC_RALT
+
+// normal characters
+#define DE_Z KC_Y
+#define DE_Y KC_Z
+
+#define DE_A KC_A
+#define DE_B KC_B
+#define DE_C KC_C
+#define DE_D KC_D
+#define DE_E KC_E
+#define DE_F KC_F
+#define DE_G KC_G
+#define DE_H KC_H
+#define DE_I KC_I
+#define DE_J KC_J
+#define DE_K KC_K
+#define DE_L KC_L
+#define DE_M KC_M
+#define DE_N KC_N
+#define DE_O KC_O
+#define DE_P KC_P
+#define DE_Q KC_Q
+#define DE_R KC_R
+#define DE_S KC_S
+#define DE_T KC_T
+#define DE_U KC_U
+#define DE_V KC_V
+#define DE_W KC_W
+#define DE_X KC_X
+
+#define DE_0 KC_0
+#define DE_1 KC_1
+#define DE_2 KC_2
+#define DE_3 KC_3
+#define DE_4 KC_4
+#define DE_5 KC_5
+#define DE_6 KC_6
+#define DE_7 KC_7
+#define DE_8 KC_8
+#define DE_9 KC_9
+
+#define DE_DOT KC_DOT
+#define DE_COMM KC_COMM
+
+#define DE_SS KC_MINS
+#define DE_AE KC_QUOT
+#define DE_UE KC_LBRC
+#define DE_OE KC_SCLN
+
+#define DE_CIRC KC_GRAVE // accent circumflex ^ and ring °
+#define DE_ACUT KC_EQL // accent acute ´ and grave `
+#define DE_PLUS KC_RBRC // + and * and ~
+#define DE_HASH KC_BSLS // # and '
+#define DE_LESS KC_NUBS // < and > and |
+#define DE_MINS KC_SLSH // - and _
+
+// shifted characters
+#define DE_RING LSFT(DE_CIRC) // °
+#define DE_EXLM LSFT(KC_1) // !
+#define DE_DQOT LSFT(KC_2) // "
+#define DE_PARA LSFT(KC_3) // §
+#define DE_DLR LSFT(KC_4) // $
+#define DE_PERC LSFT(KC_5) // %
+#define DE_AMPR LSFT(KC_6) // &
+#define DE_SLSH LSFT(KC_7) // /
+#define DE_LPRN LSFT(KC_8) // (
+#define DE_RPRN LSFT(KC_9) // )
+#define DE_EQL LSFT(KC_0) // =
+#define DE_QST LSFT(DE_SS) // ?
+#define DE_GRV LSFT(DE_ACUT) // `
+#define DE_ASTR LSFT(DE_PLUS) // *
+#define DE_QUOT LSFT(DE_HASH) // '
+#define DE_MORE LSFT(DE_LESS) // >
+#define DE_COLN LSFT(KC_DOT) // :
+#define DE_SCLN LSFT(KC_COMM) // ;
+#define DE_UNDS LSFT(DE_MINS) // _
+
+// Alt Gr-ed characters
+#define DE_SQ2 ALGR(KC_2) // ²
+#define DE_SQ3 ALGR(KC_3) // ³
+#define DE_LCBR ALGR(KC_7) // {
+#define DE_LBRC ALGR(KC_8) // [
+#define DE_RBRC ALGR(KC_9) // ]
+#define DE_RCBR ALGR(KC_0) // }
+#define DE_BSLS ALGR(DE_SS) // backslash
+#define DE_AT ALGR(KC_Q) // @
+#define DE_EURO ALGR(KC_E) // €
+#define DE_TILD ALGR(DE_PLUS) // ~
+#define DE_PIPE ALGR(DE_LESS) // |
+
+#endif
diff --git a/quantum/keymap_extras/keymap_german_ch.h b/quantum/keymap_extras/keymap_german_ch.h
new file mode 100644
index 000000000..6a782bcd7
--- /dev/null
+++ b/quantum/keymap_extras/keymap_german_ch.h
@@ -0,0 +1,102 @@
+#ifndef KEYMAP_SWISS_GERMAN
+#define KEYMAP_SWISS_GERMAN
+
+#include "keymap.h"
+
+// Alt gr
+#define ALGR(kc) kc | 0x1400
+#define CH_ALGR KC_RALT
+
+// normal characters
+#define CH_Z KC_Y
+#define CH_Y KC_Z
+
+#define CH_A KC_A
+#define CH_B KC_B
+#define CH_C KC_C
+#define CH_D KC_D
+#define CH_E KC_E
+#define CH_F KC_F
+#define CH_G KC_G
+#define CH_H KC_H
+#define CH_I KC_I
+#define CH_J KC_J
+#define CH_K KC_K
+#define CH_L KC_L
+#define CH_M KC_M
+#define CH_N KC_N
+#define CH_O KC_O
+#define CH_P KC_P
+#define CH_Q KC_Q
+#define CH_R KC_R
+#define CH_S KC_S
+#define CH_T KC_T
+#define CH_U KC_U
+#define CH_V KC_V
+#define CH_W KC_W
+#define CH_X KC_X
+
+#define CH_0 KC_0
+#define CH_1 KC_1
+#define CH_2 KC_2
+#define CH_3 KC_3
+#define CH_4 KC_4
+#define CH_5 KC_5
+#define CH_6 KC_6
+#define CH_7 KC_7
+#define CH_8 KC_8
+#define CH_9 KC_9
+
+#define CH_DOT KC_DOT
+#define CH_COMM KC_COMM
+
+#define CH_QUOT KC_MINS // ' ? ´
+#define CH_AE KC_QUOT
+#define CH_UE KC_LBRC
+#define CH_OE KC_SCLN
+
+#define CH_PARA KC_GRAVE // secction sign § and °
+#define CH_CARR KC_EQL // carret ^ ` ~
+#define CH_DIER KC_RBRC // dieresis ¨ ! ]
+#define CH_DLR KC_BSLS // $ £ }
+#define CH_LESS KC_NUBS // < and > and backslash
+#define CH_MINS KC_SLSH // - and _
+
+// shifted characters
+#define CH_RING LSFT(CH_PARA) // °
+#define CH_PLUS LSFT(KC_1) // +
+#define CH_DQOT LSFT(KC_2) // "
+#define CH_PAST LSFT(KC_3) // *
+#define CH_CELA LSFT(KC_4) // ç
+#define CH_PERC LSFT(KC_5) // %
+#define CH_AMPR LSFT(KC_6) // &
+#define CH_SLSH LSFT(KC_7) // /
+#define CH_LPRN LSFT(KC_8) // (
+#define CH_RPRN LSFT(KC_9) // )
+#define CH_EQL LSFT(KC_0) // =
+#define CH_QST LSFT(CH_QUOT) // ?
+#define CH_GRV LSFT(CH_CARR) // `
+#define CH_EXLM LSFT(CH_DIER) // !
+#define CH_POND LSFT(CH_DLR) // £
+#define CH_MORE LSFT(CH_LESS) // >
+#define CH_COLN LSFT(KC_DOT) // :
+#define CH_SCLN LSFT(KC_COMM) // ;
+#define CH_UNDS LSFT(CH_MINS) // _
+
+// Alt Gr-ed characters
+#define CH_BRBR ALGR(KC_1) // ¦ brocken bar
+#define CH_AT ALGR(KC_2) // @
+#define CH_HASH ALGR(KC_3) // #
+#define CH_NOTL ALGR(KC_6) // ¬ negative logic
+#define CH_PIPE ALGR(KC_7) // |
+#define CH_CENT ALGR(KC_8) // ¢ cent
+#define CH_ACUT ALGR(CH_QUOT) // ´
+#define CH_TILD ALGR(CH_CARR) // ~
+#define CH_EURO ALGR(KC_E) // €
+#define CH_LBRC ALGR(CH_UE) // [
+#define CH_RBRC ALGR(CH_DIER) // ]
+#define CH_LCBR ALGR(CH_AE) // {
+#define CH_RCBR ALGR(CH_DLR) // }
+#define CH_BSLS ALGR(CH_LESS) // backslash
+
+#endif
diff --git a/quantum/keymap_extras/keymap_german_osx.h b/quantum/keymap_extras/keymap_german_osx.h
new file mode 100644
index 000000000..f63f06618
--- /dev/null
+++ b/quantum/keymap_extras/keymap_german_osx.h
@@ -0,0 +1,97 @@
+#ifndef KEYMAP_GERMAN_OSX
+#define KEYMAP_GERMAN_OSX
+
+#include "keymap.h"
+
+// Alt gr
+
+// normal characters
+#define DE_OSX_Z KC_Y
+#define DE_OSX_Y KC_Z
+
+#define DE_OSX_A KC_A
+#define DE_OSX_B KC_B
+#define DE_OSX_C KC_C
+#define DE_OSX_D KC_D
+#define DE_OSX_E KC_E
+#define DE_OSX_F KC_F
+#define DE_OSX_G KC_G
+#define DE_OSX_H KC_H
+#define DE_OSX_I KC_I
+#define DE_OSX_J KC_J
+#define DE_OSX_K KC_K
+#define DE_OSX_L KC_L
+#define DE_OSX_M KC_M
+#define DE_OSX_N KC_N
+#define DE_OSX_O KC_O
+#define DE_OSX_P KC_P
+#define DE_OSX_Q KC_Q
+#define DE_OSX_R KC_R
+#define DE_OSX_S KC_S
+#define DE_OSX_T KC_T
+#define DE_OSX_U KC_U
+#define DE_OSX_V KC_V
+#define DE_OSX_W KC_W
+#define DE_OSX_X KC_X
+
+#define DE_OSX_0 KC_0
+#define DE_OSX_1 KC_1
+#define DE_OSX_2 KC_2
+#define DE_OSX_3 KC_3
+#define DE_OSX_4 KC_4
+#define DE_OSX_5 KC_5
+#define DE_OSX_6 KC_6
+#define DE_OSX_7 KC_7
+#define DE_OSX_8 KC_8
+#define DE_OSX_9 KC_9
+
+#define DE_OSX_DOT KC_DOT
+#define DE_OSX_COMM KC_COMM
+
+#define DE_OSX_SS KC_MINS
+#define DE_OSX_AE KC_QUOT
+#define DE_OSX_UE KC_LBRC
+#define DE_OSX_OE KC_SCLN
+
+#define DE_OSX_CIRC KC_NUBS // accent circumflex ^ and ring °
+#define DE_OSX_ACUT KC_EQL // accent acute ´ and grave `
+#define DE_OSX_PLUS KC_RBRC // + and * and ~
+#define DE_OSX_HASH KC_BSLS // # and '
+#define DE_OSX_LESS KC_GRV // < and > and |
+#define DE_OSX_MINS KC_SLSH // - and _
+
+// shifted characters
+#define DE_OSX_RING LSFT(DE_OSX_CIRC) // °
+#define DE_OSX_EXLM LSFT(KC_1) // !
+#define DE_OSX_DQOT LSFT(KC_2) // "
+#define DE_OSX_PARA LSFT(KC_3) // §
+#define DE_OSX_DLR LSFT(KC_4) // $
+#define DE_OSX_PERC LSFT(KC_5) // %
+#define DE_OSX_AMPR LSFT(KC_6) // &
+#define DE_OSX_SLSH LSFT(KC_7) // /
+#define DE_OSX_LPRN LSFT(KC_8) // (
+#define DE_OSX_RPRN LSFT(KC_9) // )
+#define DE_OSX_EQL LSFT(KC_0) // =
+#define DE_OSX_QST LSFT(DE_OSX_SS) // ?
+#define DE_OSX_GRV LSFT(DE_OSX_ACUT) // `
+#define DE_OSX_ASTR LSFT(DE_OSX_PLUS) // *
+#define DE_OSX_QUOT LSFT(DE_OSX_HASH) // '
+#define DE_OSX_MORE LSFT(DE_OSX_LESS) // >
+#define DE_OSX_COLN LSFT(KC_DOT) // :
+#define DE_OSX_SCLN LSFT(KC_COMM) // ;
+#define DE_OSX_UNDS LSFT(DE_OSX_MINS) // _
+
+// Alt-ed characters
+//#define DE_OSX_SQ2 LALT(KC_2) // ²
+//#define DE_OSX_SQ3 LALT(KC_3) // ³
+#define DE_OSX_LCBR LALT(KC_8) // {
+#define DE_OSX_LBRC LALT(KC_5) // [
+#define DE_OSX_RBRC LALT(KC_6) // ]
+#define DE_OSX_RCBR LALT(KC_9) // }
+#define DE_OSX_BSLS LALT(LSFT(KC_7)) // backslash
+#define DE_OSX_AT LALT(DE_OSX_L) // @
+#define DE_OSX_EURO LALT(KC_E) // €
+#define DE_OSX_TILD LALT(DE_OSX_N) // ~
+#define DE_OSX_PIPE LALT(DE_OSX_7) // |
+
+#endif
diff --git a/quantum/keymap_extras/keymap_neo2.h b/quantum/keymap_extras/keymap_neo2.h
new file mode 100644
index 000000000..80439af34
--- /dev/null
+++ b/quantum/keymap_extras/keymap_neo2.h
@@ -0,0 +1,63 @@
+#ifndef KEYMAP_NEO2
+#define KEYMAP_NEO2
+
+#include "keymap.h"
+#include "keymap_german.h"
+
+#define NEO_A KC_D
+#define NEO_B KC_N
+#define NEO_C KC_R
+#define NEO_D DE_OE
+#define NEO_E KC_F
+#define NEO_F KC_O
+#define NEO_G KC_I
+#define NEO_H KC_U
+#define NEO_I KC_S
+#define NEO_J DE_MINS
+#define NEO_K DE_Z
+#define NEO_L KC_E
+#define NEO_M KC_M
+#define NEO_N KC_J
+#define NEO_O KC_G
+#define NEO_P KC_V
+#define NEO_Q KC_P
+#define NEO_R KC_K
+#define NEO_S KC_H
+#define NEO_T KC_L
+#define NEO_U KC_A
+#define NEO_V KC_W
+#define NEO_W KC_T
+#define NEO_X KC_Q
+#define NEO_Y DE_AE
+#define NEO_Z KC_B
+#define NEO_AE KC_C
+#define NEO_OE KC_X
+#define NEO_UE DE_Y
+#define NEO_SS DE_UE
+
+#define NEO_DOT DE_DOT
+#define NEO_COMM DE_COMM
+
+#define NEO_1 DE_1
+#define NEO_2 DE_2
+#define NEO_3 DE_3
+#define NEO_4 DE_4
+#define NEO_5 DE_5
+#define NEO_6 DE_6
+#define NEO_7 DE_7
+#define NEO_8 DE_8
+#define NEO_9 DE_9
+#define NEO_0 DE_0
+#define NEO_MINS DE_SS
+
+#define NEO_ACUT DE_PLUS
+#define NEO_GRV DE_ACUT
+#define NEO_CIRC DE_CIRC
+
+#define NEO_L1_L KC_CAPS
+#define NEO_L1_R DE_HASH
+
+#define NEO_L2_L DE_LESS
+#define NEO_L2_R DE_ALGR
+
+#endif
diff --git a/quantum/keymap_extras/keymap_nordic.h b/quantum/keymap_extras/keymap_nordic.h
new file mode 100644
index 000000000..3acb8b698
--- /dev/null
+++ b/quantum/keymap_extras/keymap_nordic.h
@@ -0,0 +1,59 @@
+#ifndef KEYMAP_NORDIC_H
+#define KEYMAP_NORDIC_H
+
+#include "keymap.h"
+
+// Alt gr
+#define ALGR(kc) kc | 0x1400
+#define NO_ALGR KC_RALT
+
+// Normal characters
+#define NO_HALF KC_GRV
+#define NO_PLUS KC_MINS
+#define NO_ACUT KC_EQL
+
+#define NO_AM KC_LBRC
+#define NO_QUOT KC_RBRC
+#define NO_AE KC_SCLN
+#define NO_OSLH KC_QUOT
+#define NO_APOS KC_NUHS
+
+#define NO_LESS KC_NUBS
+#define NO_MINS KC_SLSH
+
+// Shifted characters
+#define NO_SECT LSFT(NO_HALF)
+#define NO_QUO2 LSFT(KC_2)
+#define NO_BULT LSFT(KC_4)
+#define NO_AMP LSFT(KC_6)
+#define NO_SLSH LSFT(KC_7)
+#define NO_LPRN LSFT(KC_8)
+#define NO_RPRN LSFT(KC_9)
+#define NO_EQL LSFT(KC_0)
+#define NO_QUES LSFT(NO_PLUS)
+#define NO_GRV LSFT(NO_ACUT)
+
+#define NO_CIRC LSFT(NO_QUOT)
+
+#define NO_GRTR LSFT(NO_LESS)
+#define NO_SCLN LSFT(KC_COMM)
+#define NO_COLN LSFT(KC_DOT)
+#define NO_UNDS LSFT(NO_MINS)
+
+// Alt Gr-ed characters
+#define NO_AT ALGR(KC_2)
+#define NO_PND ALGR(KC_3)
+#define NO_DLR ALGR(KC_4)
+#define NO_LCBR ALGR(KC_7)
+#define NO_LBRC ALGR(KC_8)
+#define NO_RBRC ALGR(KC_9)
+#define NO_RCBR ALGR(KC_0)
+#define NO_PIPE ALGR(KC_NUBS)
+
+#define NO_EURO ALGR(KC_E)
+#define NO_TILD ALGR(NO_QUOT)
+
+#define NO_BSLS ALGR(KC_MINS)
+#define NO_MU ALGR(KC_M)
+
+#endif
diff --git a/quantum/keymap_extras/keymap_norwegian.h b/quantum/keymap_extras/keymap_norwegian.h
new file mode 100644
index 000000000..018bfeae5
--- /dev/null
+++ b/quantum/keymap_extras/keymap_norwegian.h
@@ -0,0 +1,41 @@
+#ifndef KEYMAP_NORWEGIAN_H
+#define KEYMAP_NORWEGIAN_H
+
+#include "keymap_nordic.h"
+
+// There are slight differrences in the keyboards in the nordic contries
+
+// Norwegian redifinitions from the nordic keyset
+#undef NO_ACUT
+#define NO_ACUT ALGR(NO_BSLS) // ´
+#undef NO_AE
+#define NO_AE KC_QUOT // æ
+#undef NO_BSLS
+#define NO_BSLS KC_EQL // '\'
+#undef NO_CIRC
+#define NO_CIRC LSFT(C_RBRC) // ^
+#undef NO_GRV
+#define NO_GRV LSFT(NO_BSLS) //
+#undef NO_OSLH
+#define NO_OSLH KC_SCLN // ø
+#undef NO_PIPE
+#define NO_PIPE KC_GRV // |
+
+// Additional norwegian keys not defined in the nordic keyset
+#define NO_AA KC_LBRC // å
+#define NO_ASTR LSFT(KC_BSLS) // *
+
+// Norwegian unique MAC characters
+#define NO_ACUT_MAC KC_EQL // =
+#define NO_APOS_MAC KC_NUBS // '
+#define NO_AT_MAC KC_BSLS // @
+#define NO_BSLS_MAC ALGR(LSFT(KC_7)) // '\'
+#define NO_DLR_MAC LSFT(KC_4) // $
+#define NO_GRV_MAC ALGR(NO_BSLS) // `
+#define NO_GRTR_MAC LSFT(KC_GRV) // >
+#define NO_LCBR_MAC ALGR(LSFT(KC_8)) // }
+#define NO_LESS_MAC KC_GRV // >
+#define NO_PIPE_MAC ALGR(KC_7) // |
+#define NO_RCBR_MAC ALGR(LSFT(KC_9)) // }
+
+#endif
diff --git a/quantum/keymap_extras/keymap_plover.h b/quantum/keymap_extras/keymap_plover.h
new file mode 100644
index 000000000..9b88f7d84
--- /dev/null
+++ b/quantum/keymap_extras/keymap_plover.h
@@ -0,0 +1,32 @@
+#ifndef KEYMAP_PLOVER_H
+#define KEYMAP_PLOVER_H
+
+#include "keymap.h"
+
+#define PV_NUM KC_1
+#define PV_LS KC_Q
+#define PV_LT KC_W
+#define PV_LP KC_E
+#define PV_LH KC_R
+#define PV_LK KC_S
+#define PV_LW KC_D
+#define PV_LR KC_F
+
+#define PV_STAR KC_Y
+#define PV_RF KC_U
+#define PV_RP KC_I
+#define PV_RL KC_O
+#define PV_RT KC_P
+#define PV_RD KC_LBRC
+#define PV_RR KC_J
+#define PV_RB KC_K
+#define PV_RG KC_L
+#define PV_RS KC_SCLN
+#define PV_RZ KC_QUOT
+
+#define PV_A KC_C
+#define PV_O KC_V
+#define PV_E KC_N
+#define PV_U KC_M
+
+#endif
diff --git a/quantum/keymap_extras/keymap_spanish.h b/quantum/keymap_extras/keymap_spanish.h
new file mode 100644
index 000000000..af76e39fc
--- /dev/null
+++ b/quantum/keymap_extras/keymap_spanish.h
@@ -0,0 +1,62 @@
+#ifndef KEYMAP_SPANISH_H
+#define KEYMAP_SPANISH_H
+
+#include "keymap.h"
+
+// Alt gr
+#define ALGR(kc) kc | 0x1400
+#define NO_ALGR KC_RALT
+
+// Normal characters
+#define ES_OVRR KC_GRV
+#define ES_APOS KC_MINS
+#define ES_IEXL KC_EQL
+
+#define ES_GRV KC_LBRC
+#define ES_PLUS KC_RBRC
+
+#define ES_NTIL KC_SCLN
+#define ES_ACUT KC_QUOT
+#define ES_CCED KC_NUHS
+
+#define ES_LESS KC_NUBS
+#define ES_MINS KC_SLSH
+
+// Shifted characters
+#define ES_ASML LSFT(ES_OVRR)
+#define ES_QUOT LSFT(KC_2)
+#define ES_OVDT LSFT(KC_3)
+#define ES_AMPR LSFT(KC_6)
+#define ES_SLSH LSFT(KC_7)
+#define ES_LPRN LSFT(KC_8)
+#define ES_RPRN LSFT(KC_9)
+#define ES_EQL LSFT(KC_0)
+#define ES_QUES LSFT(ES_APOS)
+#define ES_IQUE LSFT(ES_IEXL)
+
+#define ES_CIRC LSFT(ES_GRV)
+#define ES_ASTR LSFT(ES_PLUS)
+
+#define ES_UMLT LSFT(ES_GRV)
+
+#define ES_GRTR LSFT(ES_LESS)
+#define ES_SCLN LSFT(ES_COMM)
+#define ES_COLN LSFT(ES_DOT)
+#define ES_UNDS LSFT(ES_MINS)
+
+// Alt Gr-ed characters
+#define ES_BSLS ALGR(ES_OVRR)
+#define ES_PIPE ALGR(KC_1)
+#define ES_AT ALGR(KC_2)
+#define ES_HASH ALGR(KC_3)
+#define ES_TILD ALGR(ES_NTIL)
+#define ES_EURO ALGR(KC_5)
+#define ES_NOT ALGR(KC_6)
+
+#define ES_LBRC ALGR(ES_GRV)
+#define ES_RBRC ALGR(ES_PLUS)
+
+#define ES_LCBR ALGR(ES_ACUT)
+#define ES_RCRB ALGR(ES_CCED)
+
+#endif
diff --git a/quantum/keymap_extras/keymap_uk.h b/quantum/keymap_extras/keymap_uk.h
new file mode 100644
index 000000000..5c5d95179
--- /dev/null
+++ b/quantum/keymap_extras/keymap_uk.h
@@ -0,0 +1,36 @@
+#ifndef KEYMAP_UK_H
+#define KEYMAP_UK_H
+
+#include "keymap.h"
+
+// Alt gr
+#define ALGR(kc) kc | 0x1400
+#define NO_ALGR KC_RALT
+
+// Normal characters
+#define UK_HASH KC_NUHS
+
+#define UK_BSLS KC_NUBS
+
+// Shifted characters
+#define UK_NOT LSFT(KC_GRV)
+#define UK_QUOT LSFT(KC_2)
+#define UK_PND LSFT(KC_3)
+
+#define UK_AT LSFT(KC_QUOT)
+#define UK_TILD LSFT(KC_NUHS)
+
+#define UK_PIPE LSFT(KC_NUBS)
+
+// Alt Gr-ed characters
+#define UK_BRKP ALGR(KC_GRV)
+#define UK_EURO ALGR(KC_4)
+
+#define UK_EACT ALGR(KC_E)
+#define UK_UACT ALGR(KC_U)
+#define UK_IACT ALGR(KC_I)
+#define UK_OACT ALGR(KC_O)
+
+#define UK_AACT ALGR(KC_A)
+
+#endif \ No newline at end of file
diff --git a/quantum/light_ws2812.c b/quantum/light_ws2812.c
new file mode 100755
index 000000000..f20043067
--- /dev/null
+++ b/quantum/light_ws2812.c
@@ -0,0 +1,181 @@
+/*
+* light weight WS2812 lib V2.0b
+*
+* Controls WS2811/WS2812/WS2812B RGB-LEDs
+* Author: Tim (cpldcpu@gmail.com)
+*
+* Jan 18th, 2014 v2.0b Initial Version
+* Nov 29th, 2015 v2.3 Added SK6812RGBW support
+*
+* License: GNU GPL v2 (see License.txt)
+*/
+
+#include "light_ws2812.h"
+#include <avr/interrupt.h>
+#include <avr/io.h>
+#include <util/delay.h>
+#include "debug.h"
+
+// Setleds for standard RGB
+void inline ws2812_setleds(struct cRGB *ledarray, uint16_t leds)
+{
+ ws2812_setleds_pin(ledarray,leds, _BV(ws2812_pin));
+}
+
+void inline ws2812_setleds_pin(struct cRGB *ledarray, uint16_t leds, uint8_t pinmask)
+{
+ ws2812_DDRREG |= pinmask; // Enable DDR
+ ws2812_sendarray_mask((uint8_t*)ledarray,leds+leds+leds,pinmask);
+ _delay_us(50);
+}
+
+// Setleds for SK6812RGBW
+void inline ws2812_setleds_rgbw(struct cRGBW *ledarray, uint16_t leds)
+{
+ ws2812_DDRREG |= _BV(ws2812_pin); // Enable DDR
+ ws2812_sendarray_mask((uint8_t*)ledarray,leds<<2,_BV(ws2812_pin));
+ _delay_us(80);
+}
+
+void ws2812_sendarray(uint8_t *data,uint16_t datlen)
+{
+ ws2812_sendarray_mask(data,datlen,_BV(ws2812_pin));
+}
+
+/*
+ This routine writes an array of bytes with RGB values to the Dataout pin
+ using the fast 800kHz clockless WS2811/2812 protocol.
+*/
+
+// Timing in ns
+#define w_zeropulse 350
+#define w_onepulse 900
+#define w_totalperiod 1250
+
+// Fixed cycles used by the inner loop
+#define w_fixedlow 2
+#define w_fixedhigh 4
+#define w_fixedtotal 8
+
+// Insert NOPs to match the timing, if possible
+#define w_zerocycles (((F_CPU/1000)*w_zeropulse )/1000000)
+#define w_onecycles (((F_CPU/1000)*w_onepulse +500000)/1000000)
+#define w_totalcycles (((F_CPU/1000)*w_totalperiod +500000)/1000000)
+
+// w1 - nops between rising edge and falling edge - low
+#define w1 (w_zerocycles-w_fixedlow)
+// w2 nops between fe low and fe high
+#define w2 (w_onecycles-w_fixedhigh-w1)
+// w3 nops to complete loop
+#define w3 (w_totalcycles-w_fixedtotal-w1-w2)
+
+#if w1>0
+ #define w1_nops w1
+#else
+ #define w1_nops 0
+#endif
+
+// The only critical timing parameter is the minimum pulse length of the "0"
+// Warn or throw error if this timing can not be met with current F_CPU settings.
+#define w_lowtime ((w1_nops+w_fixedlow)*1000000)/(F_CPU/1000)
+#if w_lowtime>550
+ #error "Light_ws2812: Sorry, the clock speed is too low. Did you set F_CPU correctly?"
+#elif w_lowtime>450
+ #warning "Light_ws2812: The timing is critical and may only work on WS2812B, not on WS2812(S)."
+ #warning "Please consider a higher clockspeed, if possible"
+#endif
+
+#if w2>0
+#define w2_nops w2
+#else
+#define w2_nops 0
+#endif
+
+#if w3>0
+#define w3_nops w3
+#else
+#define w3_nops 0
+#endif
+
+#define w_nop1 "nop \n\t"
+#define w_nop2 "rjmp .+0 \n\t"
+#define w_nop4 w_nop2 w_nop2
+#define w_nop8 w_nop4 w_nop4
+#define w_nop16 w_nop8 w_nop8
+
+void inline ws2812_sendarray_mask(uint8_t *data,uint16_t datlen,uint8_t maskhi)
+{
+ uint8_t curbyte,ctr,masklo;
+ uint8_t sreg_prev;
+
+ masklo =~maskhi&ws2812_PORTREG;
+ maskhi |= ws2812_PORTREG;
+ sreg_prev=SREG;
+ cli();
+
+ while (datlen--) {
+ curbyte=*data++;
+
+ asm volatile(
+ " ldi %0,8 \n\t"
+ "loop%=: \n\t"
+ " out %2,%3 \n\t" // '1' [01] '0' [01] - re
+#if (w1_nops&1)
+w_nop1
+#endif
+#if (w1_nops&2)
+w_nop2
+#endif
+#if (w1_nops&4)
+w_nop4
+#endif
+#if (w1_nops&8)
+w_nop8
+#endif
+#if (w1_nops&16)
+w_nop16
+#endif
+ " sbrs %1,7 \n\t" // '1' [03] '0' [02]
+ " out %2,%4 \n\t" // '1' [--] '0' [03] - fe-low
+ " lsl %1 \n\t" // '1' [04] '0' [04]
+#if (w2_nops&1)
+ w_nop1
+#endif
+#if (w2_nops&2)
+ w_nop2
+#endif
+#if (w2_nops&4)
+ w_nop4
+#endif
+#if (w2_nops&8)
+ w_nop8
+#endif
+#if (w2_nops&16)
+ w_nop16
+#endif
+ " out %2,%4 \n\t" // '1' [+1] '0' [+1] - fe-high
+#if (w3_nops&1)
+w_nop1
+#endif
+#if (w3_nops&2)
+w_nop2
+#endif
+#if (w3_nops&4)
+w_nop4
+#endif
+#if (w3_nops&8)
+w_nop8
+#endif
+#if (w3_nops&16)
+w_nop16
+#endif
+
+ " dec %0 \n\t" // '1' [+2] '0' [+2]
+ " brne loop%=\n\t" // '1' [+3] '0' [+4]
+ : "=&d" (ctr)
+ : "r" (curbyte), "I" (_SFR_IO_ADDR(ws2812_PORTREG)), "r" (maskhi), "r" (masklo)
+ );
+ }
+
+ SREG=sreg_prev;
+}
diff --git a/quantum/light_ws2812.h b/quantum/light_ws2812.h
new file mode 100755
index 000000000..54eef22d9
--- /dev/null
+++ b/quantum/light_ws2812.h
@@ -0,0 +1,73 @@
+/*
+ * light weight WS2812 lib include
+ *
+ * Version 2.3 - Nev 29th 2015
+ * Author: Tim (cpldcpu@gmail.com)
+ *
+ * Please do not change this file! All configuration is handled in "ws2812_config.h"
+ *
+ * License: GNU GPL v2 (see License.txt)
+ +
+ */
+
+#ifndef LIGHT_WS2812_H_
+#define LIGHT_WS2812_H_
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+//#include "ws2812_config.h"
+
+/*
+ * Structure of the LED array
+ *
+ * cRGB: RGB for WS2812S/B/C/D, SK6812, SK6812Mini, SK6812WWA, APA104, APA106
+ * cRGBW: RGBW for SK6812RGBW
+ */
+
+struct cRGB { uint8_t g; uint8_t r; uint8_t b; };
+struct cRGBW { uint8_t g; uint8_t r; uint8_t b; uint8_t w;};
+
+
+
+/* User Interface
+ *
+ * Input:
+ * ledarray: An array of GRB data describing the LED colors
+ * number_of_leds: The number of LEDs to write
+ * pinmask (optional): Bitmask describing the output bin. e.g. _BV(PB0)
+ *
+ * The functions will perform the following actions:
+ * - Set the data-out pin as output
+ * - Send out the LED data
+ * - Wait 50�s to reset the LEDs
+ */
+
+void ws2812_setleds (struct cRGB *ledarray, uint16_t number_of_leds);
+void ws2812_setleds_pin (struct cRGB *ledarray, uint16_t number_of_leds,uint8_t pinmask);
+void ws2812_setleds_rgbw(struct cRGBW *ledarray, uint16_t number_of_leds);
+
+/*
+ * Old interface / Internal functions
+ *
+ * The functions take a byte-array and send to the data output as WS2812 bitstream.
+ * The length is the number of bytes to send - three per LED.
+ */
+
+void ws2812_sendarray (uint8_t *array,uint16_t length);
+void ws2812_sendarray_mask(uint8_t *array,uint16_t length, uint8_t pinmask);
+
+
+/*
+ * Internal defines
+ */
+#ifndef CONCAT
+#define CONCAT(a, b) a ## b
+#endif
+#ifndef CONCAT_EXP
+#define CONCAT_EXP(a, b) CONCAT(a, b)
+#endif
+
+// #define ws2812_PORTREG CONCAT_EXP(PORT,ws2812_port)
+// #define ws2812_DDRREG CONCAT_EXP(DDR,ws2812_port)
+
+#endif /* LIGHT_WS2812_H_ */
diff --git a/quantum/matrix.c b/quantum/matrix.c
new file mode 100644
index 000000000..094917025
--- /dev/null
+++ b/quantum/matrix.c
@@ -0,0 +1,307 @@
+/*
+Copyright 2012 Jun Wako
+Copyright 2014 Jack Humbert
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <stdint.h>
+#include <stdbool.h>
+#if defined(__AVR__)
+#include <avr/io.h>
+#endif
+#include "wait.h"
+#include "print.h"
+#include "debug.h"
+#include "util.h"
+#include "matrix.h"
+
+/* Set 0 if debouncing isn't needed */
+/*
+ * This constant define not debouncing time in msecs, but amount of matrix
+ * scan loops which should be made to get stable debounced results.
+ *
+ * On Ergodox matrix scan rate is relatively low, because of slow I2C.
+ * Now it's only 317 scans/second, or about 3.15 msec/scan.
+ * According to Cherry specs, debouncing time is 5 msec.
+ *
+ * And so, there is no sense to have DEBOUNCE higher than 2.
+ */
+
+#ifndef DEBOUNCING_DELAY
+# define DEBOUNCING_DELAY 5
+#endif
+static uint8_t debouncing = DEBOUNCING_DELAY;
+
+static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
+static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
+
+/* matrix state(1:on, 0:off) */
+static matrix_row_t matrix[MATRIX_ROWS];
+static matrix_row_t matrix_debouncing[MATRIX_ROWS];
+
+#if DIODE_DIRECTION == ROW2COL
+ static matrix_row_t matrix_reversed[MATRIX_COLS];
+ static matrix_row_t matrix_reversed_debouncing[MATRIX_COLS];
+#endif
+
+#if MATRIX_COLS > 16
+ #define SHIFTER 1UL
+#else
+ #define SHIFTER 1
+#endif
+
+static matrix_row_t read_cols(void);
+static void init_cols(void);
+static void unselect_rows(void);
+static void select_row(uint8_t row);
+
+__attribute__ ((weak))
+void matrix_init_quantum(void) {
+ matrix_init_kb();
+}
+
+__attribute__ ((weak))
+void matrix_scan_quantum(void) {
+ matrix_scan_kb();
+}
+
+__attribute__ ((weak))
+void matrix_init_kb(void) {
+ matrix_init_user();
+}
+
+__attribute__ ((weak))
+void matrix_scan_kb(void) {
+ matrix_scan_user();
+}
+
+__attribute__ ((weak))
+void matrix_init_user(void) {
+}
+
+__attribute__ ((weak))
+void matrix_scan_user(void) {
+}
+
+inline
+uint8_t matrix_rows(void) {
+ return MATRIX_ROWS;
+}
+
+inline
+uint8_t matrix_cols(void) {
+ return MATRIX_COLS;
+}
+
+// void matrix_power_up(void) {
+// #if DIODE_DIRECTION == COL2ROW
+// for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
+// /* DDRxn */
+// _SFR_IO8((row_pins[r] >> 4) + 1) |= _BV(row_pins[r] & 0xF);
+// toggle_row(r);
+// }
+// for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
+// /* PORTxn */
+// _SFR_IO8((col_pins[c] >> 4) + 2) |= _BV(col_pins[c] & 0xF);
+// }
+// #else
+// for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
+// /* DDRxn */
+// _SFR_IO8((col_pins[c] >> 4) + 1) |= _BV(col_pins[c] & 0xF);
+// toggle_col(c);
+// }
+// for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
+// /* PORTxn */
+// _SFR_IO8((row_pins[r] >> 4) + 2) |= _BV(row_pins[r] & 0xF);
+// }
+// #endif
+// }
+
+void matrix_init(void) {
+ // To use PORTF disable JTAG with writing JTD bit twice within four cycles.
+ #ifdef __AVR_ATmega32U4__
+ MCUCR |= _BV(JTD);
+ MCUCR |= _BV(JTD);
+ #endif
+
+ // initialize row and col
+ unselect_rows();
+ init_cols();
+
+ // initialize matrix state: all keys off
+ for (uint8_t i=0; i < MATRIX_ROWS; i++) {
+ matrix[i] = 0;
+ matrix_debouncing[i] = 0;
+ }
+
+ matrix_init_quantum();
+}
+
+uint8_t matrix_scan(void)
+{
+
+#if DIODE_DIRECTION == COL2ROW
+ for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+ select_row(i);
+ wait_us(30); // without this wait read unstable value.
+ matrix_row_t cols = read_cols();
+ if (matrix_debouncing[i] != cols) {
+ matrix_debouncing[i] = cols;
+ if (debouncing) {
+ debug("bounce!: "); debug_hex(debouncing); debug("\n");
+ }
+ debouncing = DEBOUNCING_DELAY;
+ }
+ unselect_rows();
+ }
+
+ if (debouncing) {
+ if (--debouncing) {
+ wait_us(1);
+ } else {
+ for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+ matrix[i] = matrix_debouncing[i];
+ }
+ }
+ }
+#else
+ for (uint8_t i = 0; i < MATRIX_COLS; i++) {
+ select_row(i);
+ wait_us(30); // without this wait read unstable value.
+ matrix_row_t rows = read_cols();
+ if (matrix_reversed_debouncing[i] != rows) {
+ matrix_reversed_debouncing[i] = rows;
+ if (debouncing) {
+ debug("bounce!: "); debug_hex(debouncing); debug("\n");
+ }
+ debouncing = DEBOUNCING_DELAY;
+ }
+ unselect_rows();
+ }
+
+ if (debouncing) {
+ if (--debouncing) {
+ wait_us(1);
+ } else {
+ for (uint8_t i = 0; i < MATRIX_COLS; i++) {
+ matrix_reversed[i] = matrix_reversed_debouncing[i];
+ }
+ }
+ }
+ for (uint8_t y = 0; y < MATRIX_ROWS; y++) {
+ matrix_row_t row = 0;
+ for (uint8_t x = 0; x < MATRIX_COLS; x++) {
+ row |= ((matrix_reversed[x] & (1<<y)) >> y) << x;
+ }
+ matrix[y] = row;
+ }
+#endif
+
+ matrix_scan_quantum();
+
+ return 1;
+}
+
+bool matrix_is_modified(void)
+{
+ if (debouncing) return false;
+ return true;
+}
+
+inline
+bool matrix_is_on(uint8_t row, uint8_t col)
+{
+ return (matrix[row] & ((matrix_row_t)1<col));
+}
+
+inline
+matrix_row_t matrix_get_row(uint8_t row)
+{
+ return matrix[row];
+}
+
+void matrix_print(void)
+{
+ print("\nr/c 0123456789ABCDEF\n");
+ for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
+ phex(row); print(": ");
+ pbin_reverse16(matrix_get_row(row));
+ print("\n");
+ }
+}
+
+uint8_t matrix_key_count(void)
+{
+ uint8_t count = 0;
+ for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+ count += bitpop16(matrix[i]);
+ }
+ return count;
+}
+
+static void init_cols(void)
+{
+#if DIODE_DIRECTION == COL2ROW
+ for(int x = 0; x < MATRIX_COLS; x++) {
+ int pin = col_pins[x];
+#else
+ for(int x = 0; x < MATRIX_ROWS; x++) {
+ int pin = row_pins[x];
+#endif
+ _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF);
+ _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF);
+ }
+}
+
+static matrix_row_t read_cols(void)
+{
+ matrix_row_t result = 0;
+
+#if DIODE_DIRECTION == COL2ROW
+ for(int x = 0; x < MATRIX_COLS; x++) {
+ int pin = col_pins[x];
+#else
+ for(int x = 0; x < MATRIX_ROWS; x++) {
+ int pin = row_pins[x];
+#endif
+ result |= (_SFR_IO8(pin >> 4) & _BV(pin & 0xF)) ? 0 : (SHIFTER << x);
+ }
+ return result;
+}
+
+static void unselect_rows(void)
+{
+#if DIODE_DIRECTION == COL2ROW
+ for(int x = 0; x < MATRIX_ROWS; x++) {
+ int pin = row_pins[x];
+#else
+ for(int x = 0; x < MATRIX_COLS; x++) {
+ int pin = col_pins[x];
+#endif
+ _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF);
+ _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF);
+ }
+}
+
+static void select_row(uint8_t row)
+{
+
+#if DIODE_DIRECTION == COL2ROW
+ int pin = row_pins[row];
+#else
+ int pin = col_pins[row];
+#endif
+ _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF);
+ _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF);
+}
diff --git a/quantum/process_keycode/process_chording.c b/quantum/process_keycode/process_chording.c
new file mode 100644
index 000000000..d7814629f
--- /dev/null
+++ b/quantum/process_keycode/process_chording.c
@@ -0,0 +1,60 @@
+#include "process_chording.h"
+
+bool keys_chord(uint8_t keys[]) {
+ uint8_t keys_size = sizeof(keys)/sizeof(keys[0]);
+ bool pass = true;
+ uint8_t in = 0;
+ for (uint8_t i = 0; i < chord_key_count; i++) {
+ bool found = false;
+ for (uint8_t j = 0; j < keys_size; j++) {
+ if (chord_keys[i] == (keys[j] & 0xFF)) {
+ in++; // detects key in chord
+ found = true;
+ break;
+ }
+ }
+ if (found)
+ continue;
+ if (chord_keys[i] != 0) {
+ pass = false; // makes sure rest are blank
+ }
+ }
+ return (pass && (in == keys_size));
+}
+
+bool process_chording(uint16_t keycode, keyrecord_t *record) {
+ if (keycode >= QK_CHORDING && keycode <= QK_CHORDING_MAX) {
+ if (record->event.pressed) {
+ if (!chording) {
+ chording = true;
+ for (uint8_t i = 0; i < CHORDING_MAX; i++)
+ chord_keys[i] = 0;
+ chord_key_count = 0;
+ chord_key_down = 0;
+ }
+ chord_keys[chord_key_count] = (keycode & 0xFF);
+ chord_key_count++;
+ chord_key_down++;
+ return false;
+ } else {
+ if (chording) {
+ chord_key_down--;
+ if (chord_key_down == 0) {
+ chording = false;
+ // Chord Dictionary
+ if (keys_chord((uint8_t[]){KC_ENTER, KC_SPACE})) {
+ register_code(KC_A);
+ unregister_code(KC_A);
+ return false;
+ }
+ for (uint8_t i = 0; i < chord_key_count; i++) {
+ register_code(chord_keys[i]);
+ unregister_code(chord_keys[i]);
+ return false;
+ }
+ }
+ }
+ }
+ }
+ return true;
+} \ No newline at end of file
diff --git a/quantum/process_keycode/process_chording.h b/quantum/process_keycode/process_chording.h
new file mode 100644
index 000000000..49c97db3b
--- /dev/null
+++ b/quantum/process_keycode/process_chording.h
@@ -0,0 +1,16 @@
+#ifndef PROCESS_CHORDING_H
+#define PROCESS_CHORDING_H
+
+#include "quantum.h"
+
+// Chording stuff
+#define CHORDING_MAX 4
+bool chording = false;
+
+uint8_t chord_keys[CHORDING_MAX] = {0};
+uint8_t chord_key_count = 0;
+uint8_t chord_key_down = 0;
+
+bool process_chording(uint16_t keycode, keyrecord_t *record);
+
+#endif \ No newline at end of file
diff --git a/quantum/process_keycode/process_leader.c b/quantum/process_keycode/process_leader.c
new file mode 100644
index 000000000..e53d221e7
--- /dev/null
+++ b/quantum/process_keycode/process_leader.c
@@ -0,0 +1,38 @@
+#include "process_leader.h"
+
+__attribute__ ((weak))
+void leader_start(void) {}
+
+__attribute__ ((weak))
+void leader_end(void) {}
+
+// Leader key stuff
+bool leading = false;
+uint16_t leader_time = 0;
+
+uint16_t leader_sequence[5] = {0, 0, 0, 0, 0};
+uint8_t leader_sequence_size = 0;
+
+bool process_leader(uint16_t keycode, keyrecord_t *record) {
+ // Leader key set-up
+ if (record->event.pressed) {
+ if (!leading && keycode == KC_LEAD) {
+ leader_start();
+ leading = true;
+ leader_time = timer_read();
+ leader_sequence_size = 0;
+ leader_sequence[0] = 0;
+ leader_sequence[1] = 0;
+ leader_sequence[2] = 0;
+ leader_sequence[3] = 0;
+ leader_sequence[4] = 0;
+ return false;
+ }
+ if (leading && timer_elapsed(leader_time) < LEADER_TIMEOUT) {
+ leader_sequence[leader_sequence_size] = keycode;
+ leader_sequence_size++;
+ return false;
+ }
+ }
+ return true;
+} \ No newline at end of file
diff --git a/quantum/process_keycode/process_leader.h b/quantum/process_keycode/process_leader.h
new file mode 100644
index 000000000..c83db8abb
--- /dev/null
+++ b/quantum/process_keycode/process_leader.h
@@ -0,0 +1,23 @@
+#ifndef PROCESS_LEADER_H
+#define PROCESS_LEADER_H
+
+#include "quantum.h"
+
+bool process_leader(uint16_t keycode, keyrecord_t *record);
+
+void leader_start(void);
+void leader_end(void);
+
+#ifndef LEADER_TIMEOUT
+ #define LEADER_TIMEOUT 200
+#endif
+#define SEQ_ONE_KEY(key) if (leader_sequence[0] == (key) && leader_sequence[1] == 0 && leader_sequence[2] == 0 && leader_sequence[3] == 0 && leader_sequence[4] == 0)
+#define SEQ_TWO_KEYS(key1, key2) if (leader_sequence[0] == (key1) && leader_sequence[1] == (key2) && leader_sequence[2] == 0 && leader_sequence[3] == 0 && leader_sequence[4] == 0)
+#define SEQ_THREE_KEYS(key1, key2, key3) if (leader_sequence[0] == (key1) && leader_sequence[1] == (key2) && leader_sequence[2] == (key3) && leader_sequence[3] == 0 && leader_sequence[4] == 0)
+#define SEQ_FOUR_KEYS(key1, key2, key3, key4) if (leader_sequence[0] == (key1) && leader_sequence[1] == (key2) && leader_sequence[2] == (key3) && leader_sequence[3] == (key4) && leader_sequence[4] == 0)
+#define SEQ_FIVE_KEYS(key1, key2, key3, key4, key5) if (leader_sequence[0] == (key1) && leader_sequence[1] == (key2) && leader_sequence[2] == (key3) && leader_sequence[3] == (key4) && leader_sequence[4] == (key5))
+
+#define LEADER_EXTERNS() extern bool leading; extern uint16_t leader_time; extern uint16_t leader_sequence[5]; extern uint8_t leader_sequence_size
+#define LEADER_DICTIONARY() if (leading && timer_elapsed(leader_time) > LEADER_TIMEOUT)
+
+#endif \ No newline at end of file
diff --git a/quantum/process_keycode/process_midi.c b/quantum/process_keycode/process_midi.c
new file mode 100644
index 000000000..d6ab9c626
--- /dev/null
+++ b/quantum/process_keycode/process_midi.c
@@ -0,0 +1,66 @@
+#include "process_midi.h"
+
+bool midi_activated = false;
+uint8_t starting_note = 0x0C;
+int offset = 7;
+
+bool process_midi(uint16_t keycode, keyrecord_t *record) {
+ if (keycode == MI_ON && record->event.pressed) {
+ midi_activated = true;
+ music_scale_user();
+ return false;
+ }
+
+ if (keycode == MI_OFF && record->event.pressed) {
+ midi_activated = false;
+ midi_send_cc(&midi_device, 0, 0x7B, 0);
+ return false;
+ }
+
+ if (midi_activated) {
+ if (record->event.key.col == (MATRIX_COLS - 1) && record->event.key.row == (MATRIX_ROWS - 1)) {
+ if (record->event.pressed) {
+ starting_note++; // Change key
+ midi_send_cc(&midi_device, 0, 0x7B, 0);
+ }
+ return false;
+ }
+ if (record->event.key.col == (MATRIX_COLS - 2) && record->event.key.row == (MATRIX_ROWS - 1)) {
+ if (record->event.pressed) {
+ starting_note--; // Change key
+ midi_send_cc(&midi_device, 0, 0x7B, 0);
+ }
+ return false;
+ }
+ if (record->event.key.col == (MATRIX_COLS - 3) && record->event.key.row == (MATRIX_ROWS - 1) && record->event.pressed) {
+ offset++; // Change scale
+ midi_send_cc(&midi_device, 0, 0x7B, 0);
+ return false;
+ }
+ if (record->event.key.col == (MATRIX_COLS - 4) && record->event.key.row == (MATRIX_ROWS - 1) && record->event.pressed) {
+ offset--; // Change scale
+ midi_send_cc(&midi_device, 0, 0x7B, 0);
+ return false;
+ }
+ // basic
+ // uint8_t note = (starting_note + SCALE[record->event.key.col + offset])+12*(MATRIX_ROWS - record->event.key.row);
+ // advanced
+ // uint8_t note = (starting_note + record->event.key.col + offset)+12*(MATRIX_ROWS - record->event.key.row);
+ // guitar
+ uint8_t note = (starting_note + record->event.key.col + offset)+5*(MATRIX_ROWS - record->event.key.row);
+ // violin
+ // uint8_t note = (starting_note + record->event.key.col + offset)+7*(MATRIX_ROWS - record->event.key.row);
+
+ if (record->event.pressed) {
+ // midi_send_noteon(&midi_device, record->event.key.row, starting_note + SCALE[record->event.key.col], 127);
+ midi_send_noteon(&midi_device, 0, note, 127);
+ } else {
+ // midi_send_noteoff(&midi_device, record->event.key.row, starting_note + SCALE[record->event.key.col], 127);
+ midi_send_noteoff(&midi_device, 0, note, 127);
+ }
+
+ if (keycode < 0xFF) // ignores all normal keycodes, but lets RAISE, LOWER, etc through
+ return false;
+ }
+ return true;
+} \ No newline at end of file
diff --git a/quantum/process_keycode/process_midi.h b/quantum/process_keycode/process_midi.h
new file mode 100644
index 000000000..acd4fc1b1
--- /dev/null
+++ b/quantum/process_keycode/process_midi.h
@@ -0,0 +1,207 @@
+#ifndef PROCESS_MIDI_H
+#define PROCESS_MIDI_H
+
+#include "quantum.h"
+
+bool process_midi(uint16_t keycode, keyrecord_t *record);
+
+#define MIDI(n) ((n) | 0x6000)
+#define MIDI12 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000
+
+#define CHNL(note, channel) (note + (channel << 8))
+
+#define SCALE (int8_t []){ 0 + (12*0), 2 + (12*0), 4 + (12*0), 5 + (12*0), 7 + (12*0), 9 + (12*0), 11 + (12*0), \
+ 0 + (12*1), 2 + (12*1), 4 + (12*1), 5 + (12*1), 7 + (12*1), 9 + (12*1), 11 + (12*1), \
+ 0 + (12*2), 2 + (12*2), 4 + (12*2), 5 + (12*2), 7 + (12*2), 9 + (12*2), 11 + (12*2), \
+ 0 + (12*3), 2 + (12*3), 4 + (12*3), 5 + (12*3), 7 + (12*3), 9 + (12*3), 11 + (12*3), \
+ 0 + (12*4), 2 + (12*4), 4 + (12*4), 5 + (12*4), 7 + (12*4), 9 + (12*4), 11 + (12*4), }
+
+#define N_CN1 (0x600C + (12 * -1) + 0 )
+#define N_CN1S (0x600C + (12 * -1) + 1 )
+#define N_DN1F (0x600C + (12 * -1) + 1 )
+#define N_DN1 (0x600C + (12 * -1) + 2 )
+#define N_DN1S (0x600C + (12 * -1) + 3 )
+#define N_EN1F (0x600C + (12 * -1) + 3 )
+#define N_EN1 (0x600C + (12 * -1) + 4 )
+#define N_FN1 (0x600C + (12 * -1) + 5 )
+#define N_FN1S (0x600C + (12 * -1) + 6 )
+#define N_GN1F (0x600C + (12 * -1) + 6 )
+#define N_GN1 (0x600C + (12 * -1) + 7 )
+#define N_GN1S (0x600C + (12 * -1) + 8 )
+#define N_AN1F (0x600C + (12 * -1) + 8 )
+#define N_AN1 (0x600C + (12 * -1) + 9 )
+#define N_AN1S (0x600C + (12 * -1) + 10)
+#define N_BN1F (0x600C + (12 * -1) + 10)
+#define N_BN1 (0x600C + (12 * -1) + 11)
+#define N_C0 (0x600C + (12 * 0) + 0 )
+#define N_C0S (0x600C + (12 * 0) + 1 )
+#define N_D0F (0x600C + (12 * 0) + 1 )
+#define N_D0 (0x600C + (12 * 0) + 2 )
+#define N_D0S (0x600C + (12 * 0) + 3 )
+#define N_E0F (0x600C + (12 * 0) + 3 )
+#define N_E0 (0x600C + (12 * 0) + 4 )
+#define N_F0 (0x600C + (12 * 0) + 5 )
+#define N_F0S (0x600C + (12 * 0) + 6 )
+#define N_G0F (0x600C + (12 * 0) + 6 )
+#define N_G0 (0x600C + (12 * 0) + 7 )
+#define N_G0S (0x600C + (12 * 0) + 8 )
+#define N_A0F (0x600C + (12 * 0) + 8 )
+#define N_A0 (0x600C + (12 * 0) + 9 )
+#define N_A0S (0x600C + (12 * 0) + 10)
+#define N_B0F (0x600C + (12 * 0) + 10)
+#define N_B0 (0x600C + (12 * 0) + 11)
+#define N_C1 (0x600C + (12 * 1) + 0 )
+#define N_C1S (0x600C + (12 * 1) + 1 )
+#define N_D1F (0x600C + (12 * 1) + 1 )
+#define N_D1 (0x600C + (12 * 1) + 2 )
+#define N_D1S (0x600C + (12 * 1) + 3 )
+#define N_E1F (0x600C + (12 * 1) + 3 )
+#define N_E1 (0x600C + (12 * 1) + 4 )
+#define N_F1 (0x600C + (12 * 1) + 5 )
+#define N_F1S (0x600C + (12 * 1) + 6 )
+#define N_G1F (0x600C + (12 * 1) + 6 )
+#define N_G1 (0x600C + (12 * 1) + 7 )
+#define N_G1S (0x600C + (12 * 1) + 8 )
+#define N_A1F (0x600C + (12 * 1) + 8 )
+#define N_A1 (0x600C + (12 * 1) + 9 )
+#define N_A1S (0x600C + (12 * 1) + 10)
+#define N_B1F (0x600C + (12 * 1) + 10)
+#define N_B1 (0x600C + (12 * 1) + 11)
+#define N_C2 (0x600C + (12 * 2) + 0 )
+#define N_C2S (0x600C + (12 * 2) + 1 )
+#define N_D2F (0x600C + (12 * 2) + 1 )
+#define N_D2 (0x600C + (12 * 2) + 2 )
+#define N_D2S (0x600C + (12 * 2) + 3 )
+#define N_E2F (0x600C + (12 * 2) + 3 )
+#define N_E2 (0x600C + (12 * 2) + 4 )
+#define N_F2 (0x600C + (12 * 2) + 5 )
+#define N_F2S (0x600C + (12 * 2) + 6 )
+#define N_G2F (0x600C + (12 * 2) + 6 )
+#define N_G2 (0x600C + (12 * 2) + 7 )
+#define N_G2S (0x600C + (12 * 2) + 8 )
+#define N_A2F (0x600C + (12 * 2) + 8 )
+#define N_A2 (0x600C + (12 * 2) + 9 )
+#define N_A2S (0x600C + (12 * 2) + 10)
+#define N_B2F (0x600C + (12 * 2) + 10)
+#define N_B2 (0x600C + (12 * 2) + 11)
+#define N_C3 (0x600C + (12 * 3) + 0 )
+#define N_C3S (0x600C + (12 * 3) + 1 )
+#define N_D3F (0x600C + (12 * 3) + 1 )
+#define N_D3 (0x600C + (12 * 3) + 2 )
+#define N_D3S (0x600C + (12 * 3) + 3 )
+#define N_E3F (0x600C + (12 * 3) + 3 )
+#define N_E3 (0x600C + (12 * 3) + 4 )
+#define N_F3 (0x600C + (12 * 3) + 5 )
+#define N_F3S (0x600C + (12 * 3) + 6 )
+#define N_G3F (0x600C + (12 * 3) + 6 )
+#define N_G3 (0x600C + (12 * 3) + 7 )
+#define N_G3S (0x600C + (12 * 3) + 8 )
+#define N_A3F (0x600C + (12 * 3) + 8 )
+#define N_A3 (0x600C + (12 * 3) + 9 )
+#define N_A3S (0x600C + (12 * 3) + 10)
+#define N_B3F (0x600C + (12 * 3) + 10)
+#define N_B3 (0x600C + (12 * 3) + 11)
+#define N_C4 (0x600C + (12 * 4) + 0 )
+#define N_C4S (0x600C + (12 * 4) + 1 )
+#define N_D4F (0x600C + (12 * 4) + 1 )
+#define N_D4 (0x600C + (12 * 4) + 2 )
+#define N_D4S (0x600C + (12 * 4) + 3 )
+#define N_E4F (0x600C + (12 * 4) + 3 )
+#define N_E4 (0x600C + (12 * 4) + 4 )
+#define N_F4 (0x600C + (12 * 4) + 5 )
+#define N_F4S (0x600C + (12 * 4) + 6 )
+#define N_G4F (0x600C + (12 * 4) + 6 )
+#define N_G4 (0x600C + (12 * 4) + 7 )
+#define N_G4S (0x600C + (12 * 4) + 8 )
+#define N_A4F (0x600C + (12 * 4) + 8 )
+#define N_A4 (0x600C + (12 * 4) + 9 )
+#define N_A4S (0x600C + (12 * 4) + 10)
+#define N_B4F (0x600C + (12 * 4) + 10)
+#define N_B4 (0x600C + (12 * 4) + 11)
+#define N_C5 (0x600C + (12 * 5) + 0 )
+#define N_C5S (0x600C + (12 * 5) + 1 )
+#define N_D5F (0x600C + (12 * 5) + 1 )
+#define N_D5 (0x600C + (12 * 5) + 2 )
+#define N_D5S (0x600C + (12 * 5) + 3 )
+#define N_E5F (0x600C + (12 * 5) + 3 )
+#define N_E5 (0x600C + (12 * 5) + 4 )
+#define N_F5 (0x600C + (12 * 5) + 5 )
+#define N_F5S (0x600C + (12 * 5) + 6 )
+#define N_G5F (0x600C + (12 * 5) + 6 )
+#define N_G5 (0x600C + (12 * 5) + 7 )
+#define N_G5S (0x600C + (12 * 5) + 8 )
+#define N_A5F (0x600C + (12 * 5) + 8 )
+#define N_A5 (0x600C + (12 * 5) + 9 )
+#define N_A5S (0x600C + (12 * 5) + 10)
+#define N_B5F (0x600C + (12 * 5) + 10)
+#define N_B5 (0x600C + (12 * 5) + 11)
+#define N_C6 (0x600C + (12 * 6) + 0 )
+#define N_C6S (0x600C + (12 * 6) + 1 )
+#define N_D6F (0x600C + (12 * 6) + 1 )
+#define N_D6 (0x600C + (12 * 6) + 2 )
+#define N_D6S (0x600C + (12 * 6) + 3 )
+#define N_E6F (0x600C + (12 * 6) + 3 )
+#define N_E6 (0x600C + (12 * 6) + 4 )
+#define N_F6 (0x600C + (12 * 6) + 5 )
+#define N_F6S (0x600C + (12 * 6) + 6 )
+#define N_G6F (0x600C + (12 * 6) + 6 )
+#define N_G6 (0x600C + (12 * 6) + 7 )
+#define N_G6S (0x600C + (12 * 6) + 8 )
+#define N_A6F (0x600C + (12 * 6) + 8 )
+#define N_A6 (0x600C + (12 * 6) + 9 )
+#define N_A6S (0x600C + (12 * 6) + 10)
+#define N_B6F (0x600C + (12 * 6) + 10)
+#define N_B6 (0x600C + (12 * 6) + 11)
+#define N_C7 (0x600C + (12 * 7) + 0 )
+#define N_C7S (0x600C + (12 * 7) + 1 )
+#define N_D7F (0x600C + (12 * 7) + 1 )
+#define N_D7 (0x600C + (12 * 7) + 2 )
+#define N_D7S (0x600C + (12 * 7) + 3 )
+#define N_E7F (0x600C + (12 * 7) + 3 )
+#define N_E7 (0x600C + (12 * 7) + 4 )
+#define N_F7 (0x600C + (12 * 7) + 5 )
+#define N_F7S (0x600C + (12 * 7) + 6 )
+#define N_G7F (0x600C + (12 * 7) + 6 )
+#define N_G7 (0x600C + (12 * 7) + 7 )
+#define N_G7S (0x600C + (12 * 7) + 8 )
+#define N_A7F (0x600C + (12 * 7) + 8 )
+#define N_A7 (0x600C + (12 * 7) + 9 )
+#define N_A7S (0x600C + (12 * 7) + 10)
+#define N_B7F (0x600C + (12 * 7) + 10)
+#define N_B7 (0x600C + (12 * 7) + 11)
+#define N_C8 (0x600C + (12 * 8) + 0 )
+#define N_C8S (0x600C + (12 * 8) + 1 )
+#define N_D8F (0x600C + (12 * 8) + 1 )
+#define N_D8 (0x600C + (12 * 8) + 2 )
+#define N_D8S (0x600C + (12 * 8) + 3 )
+#define N_E8F (0x600C + (12 * 8) + 3 )
+#define N_E8 (0x600C + (12 * 8) + 4 )
+#define N_F8 (0x600C + (12 * 8) + 5 )
+#define N_F8S (0x600C + (12 * 8) + 6 )
+#define N_G8F (0x600C + (12 * 8) + 6 )
+#define N_G8 (0x600C + (12 * 8) + 7 )
+#define N_G8S (0x600C + (12 * 8) + 8 )
+#define N_A8F (0x600C + (12 * 8) + 8 )
+#define N_A8 (0x600C + (12 * 8) + 9 )
+#define N_A8S (0x600C + (12 * 8) + 10)
+#define N_B8F (0x600C + (12 * 8) + 10)
+#define N_B8 (0x600C + (12 * 8) + 11)
+#define N_C8 (0x600C + (12 * 8) + 0 )
+#define N_C8S (0x600C + (12 * 8) + 1 )
+#define N_D8F (0x600C + (12 * 8) + 1 )
+#define N_D8 (0x600C + (12 * 8) + 2 )
+#define N_D8S (0x600C + (12 * 8) + 3 )
+#define N_E8F (0x600C + (12 * 8) + 3 )
+#define N_E8 (0x600C + (12 * 8) + 4 )
+#define N_F8 (0x600C + (12 * 8) + 5 )
+#define N_F8S (0x600C + (12 * 8) + 6 )
+#define N_G8F (0x600C + (12 * 8) + 6 )
+#define N_G8 (0x600C + (12 * 8) + 7 )
+#define N_G8S (0x600C + (12 * 8) + 8 )
+#define N_A8F (0x600C + (12 * 8) + 8 )
+#define N_A8 (0x600C + (12 * 8) + 9 )
+#define N_A8S (0x600C + (12 * 8) + 10)
+#define N_B8F (0x600C + (12 * 8) + 10)
+#define N_B8 (0x600C + (12 * 8) + 11)
+
+#endif \ No newline at end of file
diff --git a/quantum/process_keycode/process_music.c b/quantum/process_keycode/process_music.c
new file mode 100644
index 000000000..c8f3ddb90
--- /dev/null
+++ b/quantum/process_keycode/process_music.c
@@ -0,0 +1,171 @@
+#include "process_music.h"
+
+bool music_activated = false;
+uint8_t starting_note = 0x0C;
+int offset = 7;
+
+// music sequencer
+static bool music_sequence_recording = false;
+static bool music_sequence_playing = false;
+static float music_sequence[16] = {0};
+static uint8_t music_sequence_count = 0;
+static uint8_t music_sequence_position = 0;
+
+static uint16_t music_sequence_timer = 0;
+static uint16_t music_sequence_interval = 100;
+
+bool process_music(uint16_t keycode, keyrecord_t *record) {
+
+ if (keycode == AU_ON && record->event.pressed) {
+ audio_on();
+ return false;
+ }
+
+ if (keycode == AU_OFF && record->event.pressed) {
+ audio_off();
+ return false;
+ }
+
+ if (keycode == AU_TOG && record->event.pressed) {
+ if (is_audio_on())
+ {
+ audio_off();
+ }
+ else
+ {
+ audio_on();
+ }
+ return false;
+ }
+
+ if (keycode == MU_ON && record->event.pressed) {
+ music_on();
+ return false;
+ }
+
+ if (keycode == MU_OFF && record->event.pressed) {
+ music_off();
+ return false;
+ }
+
+ if (keycode == MU_TOG && record->event.pressed) {
+ if (music_activated)
+ {
+ music_off();
+ }
+ else
+ {
+ music_on();
+ }
+ return false;
+ }
+
+ if (keycode == MUV_IN && record->event.pressed) {
+ voice_iterate();
+ music_scale_user();
+ return false;
+ }
+
+ if (keycode == MUV_DE && record->event.pressed) {
+ voice_deiterate();
+ music_scale_user();
+ return false;
+ }
+
+ if (music_activated) {
+
+ if (keycode == KC_LCTL && record->event.pressed) { // Start recording
+ stop_all_notes();
+ music_sequence_recording = true;
+ music_sequence_playing = false;
+ music_sequence_count = 0;
+ return false;
+ }
+
+ if (keycode == KC_LALT && record->event.pressed) { // Stop recording/playing
+ stop_all_notes();
+ music_sequence_recording = false;
+ music_sequence_playing = false;
+ return false;
+ }
+
+ if (keycode == KC_LGUI && record->event.pressed) { // Start playing
+ stop_all_notes();
+ music_sequence_recording = false;
+ music_sequence_playing = true;
+ music_sequence_position = 0;
+ music_sequence_timer = 0;
+ return false;
+ }
+
+ if (keycode == KC_UP) {
+ if (record->event.pressed)
+ music_sequence_interval-=10;
+ return false;
+ }
+
+ if (keycode == KC_DOWN) {
+ if (record->event.pressed)
+ music_sequence_interval+=10;
+ return false;
+ }
+
+ float freq = ((float)220.0)*pow(2.0, -5.0)*pow(2.0,(starting_note + SCALE[record->event.key.col + offset])/12.0+(MATRIX_ROWS - record->event.key.row));
+ if (record->event.pressed) {
+ play_note(freq, 0xF);
+ if (music_sequence_recording) {
+ music_sequence[music_sequence_count] = freq;
+ music_sequence_count++;
+ }
+ } else {
+ stop_note(freq);
+ }
+
+ if (keycode < 0xFF) // ignores all normal keycodes, but lets RAISE, LOWER, etc through
+ return false;
+ }
+ return true;
+}
+
+bool is_music_on(void) {
+ return (music_activated != 0);
+}
+
+void music_toggle(void) {
+ if (!music_activated) {
+ music_on();
+ } else {
+ music_off();
+ }
+}
+
+void music_on(void) {
+ music_activated = 1;
+ music_on_user();
+}
+
+void music_off(void) {
+ music_activated = 0;
+ stop_all_notes();
+}
+
+
+__attribute__ ((weak))
+void music_on_user() {}
+
+__attribute__ ((weak))
+void audio_on_user() {}
+
+__attribute__ ((weak))
+void music_scale_user() {}
+
+void matrix_scan_music(void) {
+ if (music_sequence_playing) {
+ if ((music_sequence_timer == 0) || (timer_elapsed(music_sequence_timer) > music_sequence_interval)) {
+ music_sequence_timer = timer_read();
+ stop_note(music_sequence[(music_sequence_position - 1 < 0)?(music_sequence_position - 1 + music_sequence_count):(music_sequence_position - 1)]);
+ play_note(music_sequence[music_sequence_position], 0xF);
+ music_sequence_position = (music_sequence_position + 1) % music_sequence_count;
+ }
+ }
+}
diff --git a/quantum/process_keycode/process_music.h b/quantum/process_keycode/process_music.h
new file mode 100644
index 000000000..318b3e387
--- /dev/null
+++ b/quantum/process_keycode/process_music.h
@@ -0,0 +1,27 @@
+#ifndef PROCESS_MUSIC_H
+#define PROCESS_MUSIC_H
+
+#include "quantum.h"
+
+bool process_music(uint16_t keycode, keyrecord_t *record);
+
+bool is_music_on(void);
+void music_toggle(void);
+void music_on(void);
+void music_off(void);
+
+void audio_on_user(void);
+void music_on_user(void);
+void music_scale_user(void);
+
+void matrix_scan_music(void);
+
+#ifndef SCALE
+#define SCALE (int8_t []){ 0 + (12*0), 2 + (12*0), 4 + (12*0), 5 + (12*0), 7 + (12*0), 9 + (12*0), 11 + (12*0), \
+ 0 + (12*1), 2 + (12*1), 4 + (12*1), 5 + (12*1), 7 + (12*1), 9 + (12*1), 11 + (12*1), \
+ 0 + (12*2), 2 + (12*2), 4 + (12*2), 5 + (12*2), 7 + (12*2), 9 + (12*2), 11 + (12*2), \
+ 0 + (12*3), 2 + (12*3), 4 + (12*3), 5 + (12*3), 7 + (12*3), 9 + (12*3), 11 + (12*3), \
+ 0 + (12*4), 2 + (12*4), 4 + (12*4), 5 + (12*4), 7 + (12*4), 9 + (12*4), 11 + (12*4), }
+#endif
+
+#endif \ No newline at end of file
diff --git a/quantum/process_keycode/process_tap_dance.c b/quantum/process_keycode/process_tap_dance.c
new file mode 100644
index 000000000..9b172e1b6
--- /dev/null
+++ b/quantum/process_keycode/process_tap_dance.c
@@ -0,0 +1,90 @@
+#include "quantum.h"
+
+static qk_tap_dance_state_t qk_tap_dance_state;
+
+static void _process_tap_dance_action_pair (qk_tap_dance_state_t *state,
+ uint16_t kc1, uint16_t kc2) {
+ uint16_t kc;
+
+ if (state->count == 0)
+ return;
+
+ kc = (state->count == 1) ? kc1 : kc2;
+
+ register_code (kc);
+ unregister_code (kc);
+
+ if (state->count >= 2) {
+ reset_tap_dance (state);
+ }
+}
+
+static void _process_tap_dance_action_fn (qk_tap_dance_state_t *state,
+ qk_tap_dance_user_fn_t fn)
+{
+ fn(state);
+}
+
+void process_tap_dance_action (uint16_t keycode)
+{
+ uint16_t idx = keycode - QK_TAP_DANCE;
+ qk_tap_dance_action_t action;
+
+ action = tap_dance_actions[idx];
+
+ switch (action.type) {
+ case QK_TAP_DANCE_TYPE_PAIR:
+ _process_tap_dance_action_pair (&qk_tap_dance_state,
+ action.pair.kc1, action.pair.kc2);
+ break;
+ case QK_TAP_DANCE_TYPE_FN:
+ _process_tap_dance_action_fn (&qk_tap_dance_state, action.fn);
+ break;
+
+ default:
+ break;
+ }
+}
+
+bool process_tap_dance(uint16_t keycode, keyrecord_t *record) {
+ bool r = true;
+
+ switch(keycode) {
+ case QK_TAP_DANCE ... QK_TAP_DANCE_MAX:
+ if (qk_tap_dance_state.keycode && qk_tap_dance_state.keycode != keycode) {
+ process_tap_dance_action (qk_tap_dance_state.keycode);
+ } else {
+ r = false;
+ }
+
+ if (record->event.pressed) {
+ qk_tap_dance_state.keycode = keycode;
+ qk_tap_dance_state.timer = timer_read ();
+ qk_tap_dance_state.count++;
+ }
+ break;
+
+ default:
+ if (qk_tap_dance_state.keycode) {
+ process_tap_dance_action (qk_tap_dance_state.keycode);
+
+ reset_tap_dance (&qk_tap_dance_state);
+ }
+ break;
+ }
+
+ return r;
+}
+
+void matrix_scan_tap_dance () {
+ if (qk_tap_dance_state.keycode && timer_elapsed (qk_tap_dance_state.timer) > TAPPING_TERM) {
+ process_tap_dance_action (qk_tap_dance_state.keycode);
+
+ reset_tap_dance (&qk_tap_dance_state);
+ }
+}
+
+void reset_tap_dance (qk_tap_dance_state_t *state) {
+ state->keycode = 0;
+ state->count = 0;
+}
diff --git a/quantum/process_keycode/process_tap_dance.h b/quantum/process_keycode/process_tap_dance.h
new file mode 100644
index 000000000..b9d7c7fcf
--- /dev/null
+++ b/quantum/process_keycode/process_tap_dance.h
@@ -0,0 +1,62 @@
+#ifndef PROCESS_TAP_DANCE_H
+#define PROCESS_TAP_DANCE_H
+
+#ifdef TAP_DANCE_ENABLE
+
+#include <stdbool.h>
+#include <inttypes.h>
+
+typedef struct
+{
+ uint8_t count;
+ uint16_t keycode;
+ uint16_t timer;
+} qk_tap_dance_state_t;
+
+#define TD(n) (QK_TAP_DANCE + n)
+
+typedef enum
+{
+ QK_TAP_DANCE_TYPE_PAIR,
+ QK_TAP_DANCE_TYPE_FN,
+} qk_tap_dance_type_t;
+
+typedef void (*qk_tap_dance_user_fn_t) (qk_tap_dance_state_t *state);
+
+typedef struct
+{
+ qk_tap_dance_type_t type;
+ union {
+ struct {
+ uint16_t kc1;
+ uint16_t kc2;
+ } pair;
+ qk_tap_dance_user_fn_t fn;
+ };
+} qk_tap_dance_action_t;
+
+#define ACTION_TAP_DANCE_DOUBLE(kc1, kc2) { \
+ .type = QK_TAP_DANCE_TYPE_PAIR, \
+ .pair = { kc1, kc2 } \
+ }
+
+#define ACTION_TAP_DANCE_FN(user_fn) { \
+ .type = QK_TAP_DANCE_TYPE_FN, \
+ .fn = user_fn \
+ }
+
+extern const qk_tap_dance_action_t tap_dance_actions[];
+
+/* To be used internally */
+
+bool process_tap_dance(uint16_t keycode, keyrecord_t *record);
+void matrix_scan_tap_dance (void);
+void reset_tap_dance (qk_tap_dance_state_t *state);
+
+#else
+
+#define TD(n) KC_NO
+
+#endif
+
+#endif
diff --git a/quantum/process_keycode/process_unicode.c b/quantum/process_keycode/process_unicode.c
new file mode 100644
index 000000000..ad5d7f86b
--- /dev/null
+++ b/quantum/process_keycode/process_unicode.c
@@ -0,0 +1,57 @@
+#include "process_unicode.h"
+
+static uint8_t input_mode;
+
+uint16_t hex_to_keycode(uint8_t hex)
+{
+ if (hex == 0x0) {
+ return KC_0;
+ } else if (hex < 0xA) {
+ return KC_1 + (hex - 0x1);
+ } else {
+ return KC_A + (hex - 0xA);
+ }
+}
+
+void set_unicode_mode(uint8_t os_target)
+{
+ input_mode = os_target;
+}
+
+bool process_unicode(uint16_t keycode, keyrecord_t *record) {
+ if (keycode > QK_UNICODE && record->event.pressed) {
+ uint16_t unicode = keycode & 0x7FFF;
+ switch(input_mode) {
+ case UC_OSX:
+ register_code(KC_LALT);
+ break;
+ case UC_LNX:
+ register_code(KC_LCTL);
+ register_code(KC_LSFT);
+ register_code(KC_U);
+ unregister_code(KC_U);
+ break;
+ case UC_WIN:
+ register_code(KC_LALT);
+ register_code(KC_PPLS);
+ unregister_code(KC_PPLS);
+ break;
+ }
+ for(int i = 3; i >= 0; i--) {
+ uint8_t digit = ((unicode >> (i*4)) & 0xF);
+ register_code(hex_to_keycode(digit));
+ unregister_code(hex_to_keycode(digit));
+ }
+ switch(input_mode) {
+ case UC_OSX:
+ case UC_WIN:
+ unregister_code(KC_LALT);
+ break;
+ case UC_LNX:
+ unregister_code(KC_LCTL);
+ unregister_code(KC_LSFT);
+ break;
+ }
+ }
+ return true;
+} \ No newline at end of file
diff --git a/quantum/process_keycode/process_unicode.h b/quantum/process_keycode/process_unicode.h
new file mode 100644
index 000000000..ca17f8f66
--- /dev/null
+++ b/quantum/process_keycode/process_unicode.h
@@ -0,0 +1,122 @@
+#ifndef PROCESS_UNICODE_H
+#define PROCESS_UNICODE_H
+
+#include "quantum.h"
+
+#define UC_OSX 0
+#define UC_LNX 1
+#define UC_WIN 2
+#define UC_BSD 3
+
+void set_unicode_input_mode(uint8_t os_target);
+
+bool process_unicode(uint16_t keycode, keyrecord_t *record);
+
+#define UC_BSPC UC(0x0008)
+
+#define UC_SPC UC(0x0020)
+
+#define UC_EXLM UC(0x0021)
+#define UC_DQUT UC(0x0022)
+#define UC_HASH UC(0x0023)
+#define UC_DLR UC(0x0024)
+#define UC_PERC UC(0x0025)
+#define UC_AMPR UC(0x0026)
+#define UC_QUOT UC(0x0027)
+#define UC_LPRN UC(0x0028)
+#define UC_RPRN UC(0x0029)
+#define UC_ASTR UC(0x002A)
+#define UC_PLUS UC(0x002B)
+#define UC_COMM UC(0x002C)
+#define UC_DASH UC(0x002D)
+#define UC_DOT UC(0x002E)
+#define UC_SLSH UC(0x002F)
+
+#define UC_0 UC(0x0030)
+#define UC_1 UC(0x0031)
+#define UC_2 UC(0x0032)
+#define UC_3 UC(0x0033)
+#define UC_4 UC(0x0034)
+#define UC_5 UC(0x0035)
+#define UC_6 UC(0x0036)
+#define UC_7 UC(0x0037)
+#define UC_8 UC(0x0038)
+#define UC_9 UC(0x0039)
+
+#define UC_COLN UC(0x003A)
+#define UC_SCLN UC(0x003B)
+#define UC_LT UC(0x003C)
+#define UC_EQL UC(0x003D)
+#define UC_GT UC(0x003E)
+#define UC_QUES UC(0x003F)
+#define UC_AT UC(0x0040)
+
+#define UC_A UC(0x0041)
+#define UC_B UC(0x0042)
+#define UC_C UC(0x0043)
+#define UC_D UC(0x0044)
+#define UC_E UC(0x0045)
+#define UC_F UC(0x0046)
+#define UC_G UC(0x0047)
+#define UC_H UC(0x0048)
+#define UC_I UC(0x0049)
+#define UC_J UC(0x004A)
+#define UC_K UC(0x004B)
+#define UC_L UC(0x004C)
+#define UC_M UC(0x004D)
+#define UC_N UC(0x004E)
+#define UC_O UC(0x004F)
+#define UC_P UC(0x0050)
+#define UC_Q UC(0x0051)
+#define UC_R UC(0x0052)
+#define UC_S UC(0x0053)
+#define UC_T UC(0x0054)
+#define UC_U UC(0x0055)
+#define UC_V UC(0x0056)
+#define UC_W UC(0x0057)
+#define UC_X UC(0x0058)
+#define UC_Y UC(0x0059)
+#define UC_Z UC(0x005A)
+
+#define UC_LBRC UC(0x005B)
+#define UC_BSLS UC(0x005C)
+#define UC_RBRC UC(0x005D)
+#define UC_CIRM UC(0x005E)
+#define UC_UNDR UC(0x005F)
+
+#define UC_GRV UC(0x0060)
+
+#define UC_a UC(0x0061)
+#define UC_b UC(0x0062)
+#define UC_c UC(0x0063)
+#define UC_d UC(0x0064)
+#define UC_e UC(0x0065)
+#define UC_f UC(0x0066)
+#define UC_g UC(0x0067)
+#define UC_h UC(0x0068)
+#define UC_i UC(0x0069)
+#define UC_j UC(0x006A)
+#define UC_k UC(0x006B)
+#define UC_l UC(0x006C)
+#define UC_m UC(0x006D)
+#define UC_n UC(0x006E)
+#define UC_o UC(0x006F)
+#define UC_p UC(0x0070)
+#define UC_q UC(0x0071)
+#define UC_r UC(0x0072)
+#define UC_s UC(0x0073)
+#define UC_t UC(0x0074)
+#define UC_u UC(0x0075)
+#define UC_v UC(0x0076)
+#define UC_w UC(0x0077)
+#define UC_x UC(0x0078)
+#define UC_y UC(0x0079)
+#define UC_z UC(0x007A)
+
+#define UC_LCBR UC(0x007B)
+#define UC_PIPE UC(0x007C)
+#define UC_RCBR UC(0x007D)
+#define UC_TILD UC(0x007E)
+#define UC_DEL UC(0x007F)
+
+#endif \ No newline at end of file
diff --git a/quantum/quantum.c b/quantum/quantum.c
new file mode 100644
index 000000000..d59bd5a3f
--- /dev/null
+++ b/quantum/quantum.c
@@ -0,0 +1,717 @@
+#include "quantum.h"
+
+__attribute__ ((weak))
+bool process_action_kb(keyrecord_t *record) {
+ return true;
+}
+
+__attribute__ ((weak))
+bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
+ return process_record_user(keycode, record);
+}
+
+__attribute__ ((weak))
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+ return true;
+}
+
+// Shift / paren setup
+
+#ifndef LSPO_KEY
+ #define LSPO_KEY KC_9
+#endif
+#ifndef RSPC_KEY
+ #define RSPC_KEY KC_0
+#endif
+
+static bool shift_interrupted[2] = {0, 0};
+
+bool process_record_quantum(keyrecord_t *record) {
+
+ /* This gets the keycode from the key pressed */
+ keypos_t key = record->event.key;
+ uint16_t keycode;
+
+ #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
+ uint8_t layer;
+
+ if (record->event.pressed) {
+ layer = layer_switch_get_layer(key);
+ update_source_layers_cache(key, layer);
+ } else {
+ layer = read_source_layers_cache(key);
+ }
+ keycode = keymap_key_to_keycode(layer, key);
+ #else
+ keycode = keymap_key_to_keycode(layer_switch_get_layer(key), key);
+ #endif
+
+ // This is how you use actions here
+ // if (keycode == KC_LEAD) {
+ // action_t action;
+ // action.code = ACTION_DEFAULT_LAYER_SET(0);
+ // process_action(record, action);
+ // return false;
+ // }
+
+ if (!(
+ process_record_kb(keycode, record) &&
+ #ifdef MIDI_ENABLE
+ process_midi(keycode, record) &&
+ #endif
+ #ifdef AUDIO_ENABLE
+ process_music(keycode, record) &&
+ #endif
+ #ifdef TAP_DANCE_ENABLE
+ process_tap_dance(keycode, record) &&
+ #endif
+ #ifndef DISABLE_LEADER
+ process_leader(keycode, record) &&
+ #endif
+ #ifndef DISABLE_CHORDING
+ process_chording(keycode, record) &&
+ #endif
+ #ifdef UNICODE_ENABLE
+ process_unicode(keycode, record) &&
+ #endif
+ true)) {
+ return false;
+ }
+
+ // Shift / paren setup
+
+ switch(keycode) {
+ case RESET:
+ if (record->event.pressed) {
+ clear_keyboard();
+ #ifdef AUDIO_ENABLE
+ stop_all_notes();
+ shutdown_user();
+ #endif
+ wait_ms(250);
+ #ifdef ATREUS_ASTAR
+ *(uint16_t *)0x0800 = 0x7777; // these two are a-star-specific
+ #endif
+ bootloader_jump();
+ return false;
+ }
+ break;
+ case DEBUG:
+ if (record->event.pressed) {
+ print("\nDEBUG: enabled.\n");
+ debug_enable = true;
+ return false;
+ }
+ break;
+ case MAGIC_SWAP_CONTROL_CAPSLOCK ... MAGIC_UNSWAP_ALT_GUI:
+ if (record->event.pressed) {
+ // MAGIC actions (BOOTMAGIC without the boot)
+ if (!eeconfig_is_enabled()) {
+ eeconfig_init();
+ }
+ /* keymap config */
+ keymap_config.raw = eeconfig_read_keymap();
+ if (keycode == MAGIC_SWAP_CONTROL_CAPSLOCK) {
+ keymap_config.swap_control_capslock = 1;
+ } else if (keycode == MAGIC_CAPSLOCK_TO_CONTROL) {
+ keymap_config.capslock_to_control = 1;
+ } else if (keycode == MAGIC_SWAP_LALT_LGUI) {
+ keymap_config.swap_lalt_lgui = 1;
+ } else if (keycode == MAGIC_SWAP_RALT_RGUI) {
+ keymap_config.swap_ralt_rgui = 1;
+ } else if (keycode == MAGIC_NO_GUI) {
+ keymap_config.no_gui = 1;
+ } else if (keycode == MAGIC_SWAP_GRAVE_ESC) {
+ keymap_config.swap_grave_esc = 1;
+ } else if (keycode == MAGIC_SWAP_BACKSLASH_BACKSPACE) {
+ keymap_config.swap_backslash_backspace = 1;
+ } else if (keycode == MAGIC_HOST_NKRO) {
+ keymap_config.nkro = 1;
+ } else if (keycode == MAGIC_SWAP_ALT_GUI) {
+ keymap_config.swap_lalt_lgui = 1;
+ keymap_config.swap_ralt_rgui = 1;
+ }
+ /* UNs */
+ else if (keycode == MAGIC_UNSWAP_CONTROL_CAPSLOCK) {
+ keymap_config.swap_control_capslock = 0;
+ } else if (keycode == MAGIC_UNCAPSLOCK_TO_CONTROL) {
+ keymap_config.capslock_to_control = 0;
+ } else if (keycode == MAGIC_UNSWAP_LALT_LGUI) {
+ keymap_config.swap_lalt_lgui = 0;
+ } else if (keycode == MAGIC_UNSWAP_RALT_RGUI) {
+ keymap_config.swap_ralt_rgui = 0;
+ } else if (keycode == MAGIC_UNNO_GUI) {
+ keymap_config.no_gui = 0;
+ } else if (keycode == MAGIC_UNSWAP_GRAVE_ESC) {
+ keymap_config.swap_grave_esc = 0;
+ } else if (keycode == MAGIC_UNSWAP_BACKSLASH_BACKSPACE) {
+ keymap_config.swap_backslash_backspace = 0;
+ } else if (keycode == MAGIC_UNHOST_NKRO) {
+ keymap_config.nkro = 0;
+ } else if (keycode == MAGIC_UNSWAP_ALT_GUI) {
+ keymap_config.swap_lalt_lgui = 0;
+ keymap_config.swap_ralt_rgui = 0;
+ }
+ eeconfig_update_keymap(keymap_config.raw);
+ return false;
+ }
+ break;
+ case KC_LSPO: {
+ if (record->event.pressed) {
+ shift_interrupted[0] = false;
+ register_mods(MOD_BIT(KC_LSFT));
+ }
+ else {
+ if (!shift_interrupted[0]) {
+ register_code(LSPO_KEY);
+ unregister_code(LSPO_KEY);
+ }
+ unregister_mods(MOD_BIT(KC_LSFT));
+ }
+ return false;
+ break;
+ }
+
+ case KC_RSPC: {
+ if (record->event.pressed) {
+ shift_interrupted[1] = false;
+ register_mods(MOD_BIT(KC_RSFT));
+ }
+ else {
+ if (!shift_interrupted[1]) {
+ register_code(RSPC_KEY);
+ unregister_code(RSPC_KEY);
+ }
+ unregister_mods(MOD_BIT(KC_RSFT));
+ }
+ return false;
+ break;
+ }
+ default: {
+ shift_interrupted[0] = true;
+ shift_interrupted[1] = true;
+ break;
+ }
+ }
+
+ return process_action_kb(record);
+}
+
+const bool ascii_to_qwerty_shift_lut[0x80] PROGMEM = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 1, 1, 1, 0,
+ 1, 1, 1, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 1, 0, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 0, 0, 0, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 0
+};
+
+const uint8_t ascii_to_qwerty_keycode_lut[0x80] PROGMEM = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ KC_BSPC, KC_TAB, KC_ENT, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, KC_ESC, 0, 0, 0, 0,
+ KC_SPC, KC_1, KC_QUOT, KC_3, KC_4, KC_5, KC_7, KC_QUOT,
+ KC_9, KC_0, KC_8, KC_EQL, KC_COMM, KC_MINS, KC_DOT, KC_SLSH,
+ KC_0, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7,
+ KC_8, KC_9, KC_SCLN, KC_SCLN, KC_COMM, KC_EQL, KC_DOT, KC_SLSH,
+ KC_2, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G,
+ KC_H, KC_I, KC_J, KC_K, KC_L, KC_M, KC_N, KC_O,
+ KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W,
+ KC_X, KC_Y, KC_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_6, KC_MINS,
+ KC_GRV, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G,
+ KC_H, KC_I, KC_J, KC_K, KC_L, KC_M, KC_N, KC_O,
+ KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W,
+ KC_X, KC_Y, KC_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_GRV, KC_DEL
+};
+
+/* for users whose OSes are set to Colemak */
+#if 0
+#include "keymap_colemak.h"
+
+const bool ascii_to_colemak_shift_lut[0x80] PROGMEM = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 1, 1, 1, 0,
+ 1, 1, 1, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 1, 0, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 0, 0, 0, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 0
+};
+
+const uint8_t ascii_to_colemak_keycode_lut[0x80] PROGMEM = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ KC_BSPC, KC_TAB, KC_ENT, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, KC_ESC, 0, 0, 0, 0,
+ KC_SPC, KC_1, KC_QUOT, KC_3, KC_4, KC_5, KC_7, KC_QUOT,
+ KC_9, KC_0, KC_8, KC_EQL, KC_COMM, KC_MINS, KC_DOT, KC_SLSH,
+ KC_0, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7,
+ KC_8, KC_9, CM_SCLN, CM_SCLN, KC_COMM, KC_EQL, KC_DOT, KC_SLSH,
+ KC_2, CM_A, CM_B, CM_C, CM_D, CM_E, CM_F, CM_G,
+ CM_H, CM_I, CM_J, CM_K, CM_L, CM_M, CM_N, CM_O,
+ CM_P, CM_Q, CM_R, CM_S, CM_T, CM_U, CM_V, CM_W,
+ CM_X, CM_Y, CM_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_6, KC_MINS,
+ KC_GRV, CM_A, CM_B, CM_C, CM_D, CM_E, CM_F, CM_G,
+ CM_H, CM_I, CM_J, CM_K, CM_L, CM_M, CM_N, CM_O,
+ CM_P, CM_Q, CM_R, CM_S, CM_T, CM_U, CM_V, CM_W,
+ CM_X, CM_Y, CM_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_GRV, KC_DEL
+};
+
+#endif
+
+void send_string(const char *str) {
+ while (1) {
+ uint8_t keycode;
+ uint8_t ascii_code = pgm_read_byte(str);
+ if (!ascii_code) break;
+ keycode = pgm_read_byte(&ascii_to_qwerty_keycode_lut[ascii_code]);
+ if (pgm_read_byte(&ascii_to_qwerty_shift_lut[ascii_code])) {
+ register_code(KC_LSFT);
+ register_code(keycode);
+ unregister_code(keycode);
+ unregister_code(KC_LSFT);
+ }
+ else {
+ register_code(keycode);
+ unregister_code(keycode);
+ }
+ ++str;
+ }
+}
+
+void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3) {
+ if (IS_LAYER_ON(layer1) && IS_LAYER_ON(layer2)) {
+ layer_on(layer3);
+ } else {
+ layer_off(layer3);
+ }
+}
+
+void tap_random_base64(void) {
+ #if defined(__AVR_ATmega32U4__)
+ uint8_t key = (TCNT0 + TCNT1 + TCNT3 + TCNT4) % 64;
+ #else
+ uint8_t key = rand() % 64;
+ #endif
+ switch (key) {
+ case 0 ... 25:
+ register_code(KC_LSFT);
+ register_code(key + KC_A);
+ unregister_code(key + KC_A);
+ unregister_code(KC_LSFT);
+ break;
+ case 26 ... 51:
+ register_code(key - 26 + KC_A);
+ unregister_code(key - 26 + KC_A);
+ break;
+ case 52:
+ register_code(KC_0);
+ unregister_code(KC_0);
+ break;
+ case 53 ... 61:
+ register_code(key - 53 + KC_1);
+ unregister_code(key - 53 + KC_1);
+ break;
+ case 62:
+ register_code(KC_LSFT);
+ register_code(KC_EQL);
+ unregister_code(KC_EQL);
+ unregister_code(KC_LSFT);
+ break;
+ case 63:
+ register_code(KC_SLSH);
+ unregister_code(KC_SLSH);
+ break;
+ }
+}
+
+void matrix_init_quantum() {
+ #ifdef BACKLIGHT_ENABLE
+ backlight_init_ports();
+ #endif
+ matrix_init_kb();
+}
+
+void matrix_scan_quantum() {
+ #ifdef AUDIO_ENABLE
+ matrix_scan_music();
+ #endif
+
+ #ifdef TAP_DANCE_ENABLE
+ matrix_scan_tap_dance();
+ #endif
+ matrix_scan_kb();
+}
+
+#if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_PIN)
+
+static const uint8_t backlight_pin = BACKLIGHT_PIN;
+
+#if BACKLIGHT_PIN == B7
+# define COM1x1 COM1C1
+# define OCR1x OCR1C
+#elif BACKLIGHT_PIN == B6
+# define COM1x1 COM1B1
+# define OCR1x OCR1B
+#elif BACKLIGHT_PIN == B5
+# define COM1x1 COM1A1
+# define OCR1x OCR1A
+#else
+# error "Backlight pin not supported - use B5, B6, or B7"
+#endif
+
+__attribute__ ((weak))
+void backlight_init_ports(void)
+{
+
+ // Setup backlight pin as output and output low.
+ // DDRx |= n
+ _SFR_IO8((backlight_pin >> 4) + 1) |= _BV(backlight_pin & 0xF);
+ // PORTx &= ~n
+ _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
+
+ // Use full 16-bit resolution.
+ ICR1 = 0xFFFF;
+
+ // I could write a wall of text here to explain... but TL;DW
+ // Go read the ATmega32u4 datasheet.
+ // And this: http://blog.saikoled.com/post/43165849837/secret-konami-cheat-code-to-high-resolution-pwm-on
+
+ // Pin PB7 = OCR1C (Timer 1, Channel C)
+ // Compare Output Mode = Clear on compare match, Channel C = COM1C1=1 COM1C0=0
+ // (i.e. start high, go low when counter matches.)
+ // WGM Mode 14 (Fast PWM) = WGM13=1 WGM12=1 WGM11=1 WGM10=0
+ // Clock Select = clk/1 (no prescaling) = CS12=0 CS11=0 CS10=1
+
+ TCCR1A = _BV(COM1x1) | _BV(WGM11); // = 0b00001010;
+ TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
+
+ backlight_init();
+ #ifdef BACKLIGHT_BREATHING
+ breathing_defaults();
+ #endif
+}
+
+__attribute__ ((weak))
+void backlight_set(uint8_t level)
+{
+ // Prevent backlight blink on lowest level
+ // PORTx &= ~n
+ _SFR_IO8((backlight_pin >> 4) + 2) &= ~_BV(backlight_pin & 0xF);
+
+ if ( level == 0 ) {
+ // Turn off PWM control on backlight pin, revert to output low.
+ TCCR1A &= ~(_BV(COM1x1));
+ OCR1x = 0x0;
+ } else if ( level == BACKLIGHT_LEVELS ) {
+ // Turn on PWM control of backlight pin
+ TCCR1A |= _BV(COM1x1);
+ // Set the brightness
+ OCR1x = 0xFFFF;
+ } else {
+ // Turn on PWM control of backlight pin
+ TCCR1A |= _BV(COM1x1);
+ // Set the brightness
+ OCR1x = 0xFFFF >> ((BACKLIGHT_LEVELS - level) * ((BACKLIGHT_LEVELS + 1) / 2));
+ }
+
+ #ifdef BACKLIGHT_BREATHING
+ breathing_intensity_default();
+ #endif
+}
+
+
+#ifdef BACKLIGHT_BREATHING
+
+#define BREATHING_NO_HALT 0
+#define BREATHING_HALT_OFF 1
+#define BREATHING_HALT_ON 2
+
+static uint8_t breath_intensity;
+static uint8_t breath_speed;
+static uint16_t breathing_index;
+static uint8_t breathing_halt;
+
+void breathing_enable(void)
+{
+ if (get_backlight_level() == 0)
+ {
+ breathing_index = 0;
+ }
+ else
+ {
+ // Set breathing_index to be at the midpoint (brightest point)
+ breathing_index = 0x20 << breath_speed;
+ }
+
+ breathing_halt = BREATHING_NO_HALT;
+
+ // Enable breathing interrupt
+ TIMSK1 |= _BV(OCIE1A);
+}
+
+void breathing_pulse(void)
+{
+ if (get_backlight_level() == 0)
+ {
+ breathing_index = 0;
+ }
+ else
+ {
+ // Set breathing_index to be at the midpoint + 1 (brightest point)
+ breathing_index = 0x21 << breath_speed;
+ }
+
+ breathing_halt = BREATHING_HALT_ON;
+
+ // Enable breathing interrupt
+ TIMSK1 |= _BV(OCIE1A);
+}
+
+void breathing_disable(void)
+{
+ // Disable breathing interrupt
+ TIMSK1 &= ~_BV(OCIE1A);
+ backlight_set(get_backlight_level());
+}
+
+void breathing_self_disable(void)
+{
+ if (get_backlight_level() == 0)
+ {
+ breathing_halt = BREATHING_HALT_OFF;
+ }
+ else
+ {
+ breathing_halt = BREATHING_HALT_ON;
+ }
+
+ //backlight_set(get_backlight_level());
+}
+
+void breathing_toggle(void)
+{
+ if (!is_breathing())
+ {
+ if (get_backlight_level() == 0)
+ {
+ breathing_index = 0;
+ }
+ else
+ {
+ // Set breathing_index to be at the midpoint + 1 (brightest point)
+ breathing_index = 0x21 << breath_speed;
+ }
+
+ breathing_halt = BREATHING_NO_HALT;
+ }
+
+ // Toggle breathing interrupt
+ TIMSK1 ^= _BV(OCIE1A);
+
+ // Restore backlight level
+ if (!is_breathing())
+ {
+ backlight_set(get_backlight_level());
+ }
+}
+
+bool is_breathing(void)
+{
+ return (TIMSK1 && _BV(OCIE1A));
+}
+
+void breathing_intensity_default(void)
+{
+ //breath_intensity = (uint8_t)((uint16_t)100 * (uint16_t)get_backlight_level() / (uint16_t)BACKLIGHT_LEVELS);
+ breath_intensity = ((BACKLIGHT_LEVELS - get_backlight_level()) * ((BACKLIGHT_LEVELS + 1) / 2));
+}
+
+void breathing_intensity_set(uint8_t value)
+{
+ breath_intensity = value;
+}
+
+void breathing_speed_default(void)
+{
+ breath_speed = 4;
+}
+
+void breathing_speed_set(uint8_t value)
+{
+ bool is_breathing_now = is_breathing();
+ uint8_t old_breath_speed = breath_speed;
+
+ if (is_breathing_now)
+ {
+ // Disable breathing interrupt
+ TIMSK1 &= ~_BV(OCIE1A);
+ }
+
+ breath_speed = value;
+
+ if (is_breathing_now)
+ {
+ // Adjust index to account for new speed
+ breathing_index = (( (uint8_t)( (breathing_index) >> old_breath_speed ) ) & 0x3F) << breath_speed;
+
+ // Enable breathing interrupt
+ TIMSK1 |= _BV(OCIE1A);
+ }
+
+}
+
+void breathing_speed_inc(uint8_t value)
+{
+ if ((uint16_t)(breath_speed - value) > 10 )
+ {
+ breathing_speed_set(0);
+ }
+ else
+ {
+ breathing_speed_set(breath_speed - value);
+ }
+}
+
+void breathing_speed_dec(uint8_t value)
+{
+ if ((uint16_t)(breath_speed + value) > 10 )
+ {
+ breathing_speed_set(10);
+ }
+ else
+ {
+ breathing_speed_set(breath_speed + value);
+ }
+}
+
+void breathing_defaults(void)
+{
+ breathing_intensity_default();
+ breathing_speed_default();
+ breathing_halt = BREATHING_NO_HALT;
+}
+
+/* Breathing Sleep LED brighness(PWM On period) table
+ * (64[steps] * 4[duration]) / 64[PWM periods/s] = 4 second breath cycle
+ *
+ * http://www.wolframalpha.com/input/?i=%28sin%28+x%2F64*pi%29**8+*+255%2C+x%3D0+to+63
+ * (0..63).each {|x| p ((sin(x/64.0*PI)**8)*255).to_i }
+ */
+static const uint8_t breathing_table[64] PROGMEM = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 6, 10,
+ 15, 23, 32, 44, 58, 74, 93, 113, 135, 157, 179, 199, 218, 233, 245, 252,
+255, 252, 245, 233, 218, 199, 179, 157, 135, 113, 93, 74, 58, 44, 32, 23,
+ 15, 10, 6, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+ISR(TIMER1_COMPA_vect)
+{
+ // OCR1x = (pgm_read_byte(&breathing_table[ ( (uint8_t)( (breathing_index++) >> breath_speed ) ) & 0x3F ] )) * breath_intensity;
+
+
+ uint8_t local_index = ( (uint8_t)( (breathing_index++) >> breath_speed ) ) & 0x3F;
+
+ if (((breathing_halt == BREATHING_HALT_ON) && (local_index == 0x20)) || ((breathing_halt == BREATHING_HALT_OFF) && (local_index == 0x3F)))
+ {
+ // Disable breathing interrupt
+ TIMSK1 &= ~_BV(OCIE1A);
+ }
+
+ OCR1x = (uint16_t)(((uint16_t)pgm_read_byte(&breathing_table[local_index]) * 257)) >> breath_intensity;
+
+}
+
+
+
+#endif // breathing
+
+#else // backlight
+
+__attribute__ ((weak))
+void backlight_init_ports(void)
+{
+
+}
+
+__attribute__ ((weak))
+void backlight_set(uint8_t level)
+{
+
+}
+
+#endif // backlight
+
+
+
+__attribute__ ((weak))
+void led_set_user(uint8_t usb_led) {
+
+}
+
+__attribute__ ((weak))
+void led_set_kb(uint8_t usb_led) {
+ led_set_user(usb_led);
+}
+
+__attribute__ ((weak))
+void led_init_ports(void)
+{
+
+}
+
+__attribute__ ((weak))
+void led_set(uint8_t usb_led)
+{
+
+ // Example LED Code
+ //
+ // // Using PE6 Caps Lock LED
+ // if (usb_led & (1<<USB_LED_CAPS_LOCK))
+ // {
+ // // Output high.
+ // DDRE |= (1<<6);
+ // PORTE |= (1<<6);
+ // }
+ // else
+ // {
+ // // Output low.
+ // DDRE &= ~(1<<6);
+ // PORTE &= ~(1<<6);
+ // }
+
+ led_set_kb(usb_led);
+}
+
+
+//------------------------------------------------------------------------------
+// Override these functions in your keymap file to play different tunes on
+// different events such as startup and bootloader jump
+
+__attribute__ ((weak))
+void startup_user() {}
+
+__attribute__ ((weak))
+void shutdown_user() {}
+
+//------------------------------------------------------------------------------
diff --git a/quantum/quantum.h b/quantum/quantum.h
new file mode 100644
index 000000000..3a0b74202
--- /dev/null
+++ b/quantum/quantum.h
@@ -0,0 +1,107 @@
+#ifndef QUANTUM_H
+#define QUANTUM_H
+
+#if defined(__AVR__)
+#include <avr/pgmspace.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#endif
+#include "wait.h"
+#include "matrix.h"
+#include "keymap.h"
+#ifdef BACKLIGHT_ENABLE
+ #include "backlight.h"
+#endif
+#ifdef RGBLIGHT_ENABLE
+ #include "rgblight.h"
+#endif
+
+#include "action_layer.h"
+#include "eeconfig.h"
+#include <stddef.h>
+#include "bootloader.h"
+#include "timer.h"
+#include "config_common.h"
+#include "led.h"
+#include "action_util.h"
+#include <stdlib.h>
+
+
+extern uint32_t default_layer_state;
+
+#ifndef NO_ACTION_LAYER
+ extern uint32_t layer_state;
+#endif
+
+#ifdef MIDI_ENABLE
+ #include <lufa.h>
+ #include "process_midi.h"
+#endif
+
+#ifdef AUDIO_ENABLE
+ #include "audio.h"
+ #include "process_music.h"
+#endif
+
+#ifndef DISABLE_LEADER
+ #include "process_leader.h"
+#endif
+
+#define DISABLE_CHORDING
+#ifndef DISABLE_CHORDING
+ #include "process_chording.h"
+#endif
+
+#ifdef UNICODE_ENABLE
+ #include "process_unicode.h"
+#endif
+
+#include "process_tap_dance.h"
+
+#define SEND_STRING(str) send_string(PSTR(str))
+void send_string(const char *str);
+
+// For tri-layer
+void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3);
+
+void tap_random_base64(void);
+
+#define IS_LAYER_ON(layer) (layer_state & (1UL << (layer)))
+#define IS_LAYER_OFF(layer) (~layer_state & (1UL << (layer)))
+
+void matrix_init_kb(void);
+void matrix_scan_kb(void);
+void matrix_init_user(void);
+void matrix_scan_user(void);
+bool process_action_kb(keyrecord_t *record);
+bool process_record_kb(uint16_t keycode, keyrecord_t *record);
+bool process_record_user(uint16_t keycode, keyrecord_t *record);
+
+void startup_user(void);
+void shutdown_user(void);
+
+#ifdef BACKLIGHT_ENABLE
+void backlight_init_ports(void);
+
+#ifdef BACKLIGHT_BREATHING
+void breathing_enable(void);
+void breathing_pulse(void);
+void breathing_disable(void);
+void breathing_self_disable(void);
+void breathing_toggle(void);
+bool is_breathing(void);
+
+void breathing_defaults(void);
+void breathing_intensity_default(void);
+void breathing_speed_default(void);
+void breathing_speed_set(uint8_t value);
+void breathing_speed_inc(uint8_t value);
+void breathing_speed_dec(uint8_t value);
+#endif
+
+#endif
+
+void led_set_user(uint8_t usb_led);
+void led_set_kb(uint8_t usb_led);
+
+#endif
diff --git a/quantum/rgblight.c b/quantum/rgblight.c
new file mode 100644
index 000000000..c29ffedc3
--- /dev/null
+++ b/quantum/rgblight.c
@@ -0,0 +1,505 @@
+#include <avr/eeprom.h>
+#include <avr/interrupt.h>
+#include <util/delay.h>
+#include "progmem.h"
+#include "timer.h"
+#include "rgblight.h"
+#include "debug.h"
+
+const uint8_t DIM_CURVE[] PROGMEM = {
+ 0, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6,
+ 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8,
+ 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11,
+ 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15,
+ 15, 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 20,
+ 20, 20, 21, 21, 22, 22, 22, 23, 23, 24, 24, 25, 25, 25, 26, 26,
+ 27, 27, 28, 28, 29, 29, 30, 30, 31, 32, 32, 33, 33, 34, 35, 35,
+ 36, 36, 37, 38, 38, 39, 40, 40, 41, 42, 43, 43, 44, 45, 46, 47,
+ 48, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
+ 63, 64, 65, 66, 68, 69, 70, 71, 73, 74, 75, 76, 78, 79, 81, 82,
+ 83, 85, 86, 88, 90, 91, 93, 94, 96, 98, 99, 101, 103, 105, 107, 109,
+ 110, 112, 114, 116, 118, 121, 123, 125, 127, 129, 132, 134, 136, 139, 141, 144,
+ 146, 149, 151, 154, 157, 159, 162, 165, 168, 171, 174, 177, 180, 183, 186, 190,
+ 193, 196, 200, 203, 207, 211, 214, 218, 222, 226, 230, 234, 238, 242, 248, 255,
+};
+const uint8_t RGBLED_BREATHING_TABLE[] PROGMEM = {0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,17,18,20,21,23,25,27,29,31,33,35,37,40,42,44,47,49,52,54,57,59,62,65,67,70,73,76,79,82,85,88,90,93,97,100,103,106,109,112,115,118,121,124,127,131,134,137,140,143,146,149,152,155,158,162,165,167,170,173,176,179,182,185,188,190,193,196,198,201,203,206,208,211,213,215,218,220,222,224,226,228,230,232,234,235,237,238,240,241,243,244,245,246,248,249,250,250,251,252,253,253,254,254,254,255,255,255,255,255,255,255,254,254,254,253,253,252,251,250,250,249,248,246,245,244,243,241,240,238,237,235,234,232,230,228,226,224,222,220,218,215,213,211,208,206,203,201,198,196,193,190,188,185,182,179,176,173,170,167,165,162,158,155,152,149,146,143,140,137,134,131,128,124,121,118,115,112,109,106,103,100,97,93,90,88,85,82,79,76,73,70,67,65,62,59,57,54,52,49,47,44,42,40,37,35,33,31,29,27,25,23,21,20,18,17,15,14,12,11,10,9,7,6,5,5,4,3,2,2,1,1,1,0,0,0};
+const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5};
+const uint8_t RGBLED_RAINBOW_MOOD_INTERVALS[] PROGMEM = {120, 60, 30};
+const uint8_t RGBLED_RAINBOW_SWIRL_INTERVALS[] PROGMEM = {100, 50, 20};
+const uint8_t RGBLED_SNAKE_INTERVALS[] PROGMEM = {100, 50, 20};
+const uint8_t RGBLED_KNIGHT_INTERVALS[] PROGMEM = {100, 50, 20};
+
+rgblight_config_t rgblight_config;
+rgblight_config_t inmem_config;
+struct cRGB led[RGBLED_NUM];
+uint8_t rgblight_inited = 0;
+
+
+void sethsv(uint16_t hue, uint8_t sat, uint8_t val, struct cRGB *led1) {
+ /* convert hue, saturation and brightness ( HSB/HSV ) to RGB
+ The DIM_CURVE is used only on brightness/value and on saturation (inverted).
+ This looks the most natural.
+ */
+ uint8_t r = 0, g = 0, b = 0;
+
+ val = pgm_read_byte(&DIM_CURVE[val]);
+ sat = 255 - pgm_read_byte(&DIM_CURVE[255 - sat]);
+
+ uint8_t base;
+
+ if (sat == 0) { // Acromatic color (gray). Hue doesn't mind.
+ r = val;
+ g = val;
+ b = val;
+ } else {
+ base = ((255 - sat) * val) >> 8;
+
+ switch (hue / 60) {
+ case 0:
+ r = val;
+ g = (((val - base)*hue) / 60) + base;
+ b = base;
+ break;
+
+ case 1:
+ r = (((val - base)*(60 - (hue % 60))) / 60) + base;
+ g = val;
+ b = base;
+ break;
+
+ case 2:
+ r = base;
+ g = val;
+ b = (((val - base)*(hue % 60)) / 60) + base;
+ break;
+
+ case 3:
+ r = base;
+ g = (((val - base)*(60 - (hue % 60))) / 60) + base;
+ b = val;
+ break;
+
+ case 4:
+ r = (((val - base)*(hue % 60)) / 60) + base;
+ g = base;
+ b = val;
+ break;
+
+ case 5:
+ r = val;
+ g = base;
+ b = (((val - base)*(60 - (hue % 60))) / 60) + base;
+ break;
+ }
+ }
+ setrgb(r,g,b, led1);
+}
+
+void setrgb(uint8_t r, uint8_t g, uint8_t b, struct cRGB *led1) {
+ (*led1).r = r;
+ (*led1).g = g;
+ (*led1).b = b;
+}
+
+
+uint32_t eeconfig_read_rgblight(void) {
+ return eeprom_read_dword(EECONFIG_RGBLIGHT);
+}
+void eeconfig_update_rgblight(uint32_t val) {
+ eeprom_update_dword(EECONFIG_RGBLIGHT, val);
+}
+void eeconfig_update_rgblight_default(void) {
+ dprintf("eeconfig_update_rgblight_default\n");
+ rgblight_config.enable = 1;
+ rgblight_config.mode = 1;
+ rgblight_config.hue = 200;
+ rgblight_config.sat = 204;
+ rgblight_config.val = 204;
+ eeconfig_update_rgblight(rgblight_config.raw);
+}
+void eeconfig_debug_rgblight(void) {
+ dprintf("rgblight_config eprom\n");
+ dprintf("rgblight_config.enable = %d\n", rgblight_config.enable);
+ dprintf("rghlight_config.mode = %d\n", rgblight_config.mode);
+ dprintf("rgblight_config.hue = %d\n", rgblight_config.hue);
+ dprintf("rgblight_config.sat = %d\n", rgblight_config.sat);
+ dprintf("rgblight_config.val = %d\n", rgblight_config.val);
+}
+
+void rgblight_init(void) {
+ debug_enable = 1; // Debug ON!
+ dprintf("rgblight_init called.\n");
+ rgblight_inited = 1;
+ dprintf("rgblight_init start!\n");
+ if (!eeconfig_is_enabled()) {
+ dprintf("rgblight_init eeconfig is not enabled.\n");
+ eeconfig_init();
+ eeconfig_update_rgblight_default();
+ }
+ rgblight_config.raw = eeconfig_read_rgblight();
+ if (!rgblight_config.mode) {
+ dprintf("rgblight_init rgblight_config.mode = 0. Write default values to EEPROM.\n");
+ eeconfig_update_rgblight_default();
+ rgblight_config.raw = eeconfig_read_rgblight();
+ }
+ eeconfig_debug_rgblight(); // display current eeprom values
+
+ rgblight_timer_init(); // setup the timer
+
+ if (rgblight_config.enable) {
+ rgblight_mode(rgblight_config.mode);
+ }
+}
+
+void rgblight_increase(void) {
+ uint8_t mode = 0;
+ if (rgblight_config.mode < RGBLIGHT_MODES) {
+ mode = rgblight_config.mode + 1;
+ }
+ rgblight_mode(mode);
+}
+
+void rgblight_decrease(void) {
+ uint8_t mode = 0;
+ if (rgblight_config.mode > 1) { //mode will never < 1, if mode is less than 1, eeprom need to be initialized.
+ mode = rgblight_config.mode-1;
+ }
+ rgblight_mode(mode);
+}
+
+void rgblight_step(void) {
+ uint8_t mode = 0;
+ mode = rgblight_config.mode + 1;
+ if (mode > RGBLIGHT_MODES) {
+ mode = 1;
+ }
+ rgblight_mode(mode);
+}
+
+void rgblight_mode(uint8_t mode) {
+ if (!rgblight_config.enable) {
+ return;
+ }
+ if (mode<1) {
+ rgblight_config.mode = 1;
+ } else if (mode > RGBLIGHT_MODES) {
+ rgblight_config.mode = RGBLIGHT_MODES;
+ } else {
+ rgblight_config.mode = mode;
+ }
+ eeconfig_update_rgblight(rgblight_config.raw);
+ xprintf("rgblight mode: %u\n", rgblight_config.mode);
+ if (rgblight_config.mode == 1) {
+ rgblight_timer_disable();
+ } else if (rgblight_config.mode >=2 && rgblight_config.mode <=23) {
+ // MODE 2-5, breathing
+ // MODE 6-8, rainbow mood
+ // MODE 9-14, rainbow swirl
+ // MODE 15-20, snake
+ // MODE 21-23, knight
+ rgblight_timer_enable();
+ }
+ rgblight_sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val);
+}
+
+void rgblight_toggle(void) {
+ rgblight_config.enable ^= 1;
+ eeconfig_update_rgblight(rgblight_config.raw);
+ xprintf("rgblight toggle: rgblight_config.enable = %u\n", rgblight_config.enable);
+ if (rgblight_config.enable) {
+ rgblight_mode(rgblight_config.mode);
+ } else {
+ rgblight_timer_disable();
+ _delay_ms(50);
+ rgblight_set();
+ }
+}
+
+
+void rgblight_increase_hue(void){
+ uint16_t hue;
+ hue = (rgblight_config.hue+RGBLIGHT_HUE_STEP) % 360;
+ rgblight_sethsv(hue, rgblight_config.sat, rgblight_config.val);
+}
+void rgblight_decrease_hue(void){
+ uint16_t hue;
+ if (rgblight_config.hue-RGBLIGHT_HUE_STEP <0 ) {
+ hue = (rgblight_config.hue+360-RGBLIGHT_HUE_STEP) % 360;
+ } else {
+ hue = (rgblight_config.hue-RGBLIGHT_HUE_STEP) % 360;
+ }
+ rgblight_sethsv(hue, rgblight_config.sat, rgblight_config.val);
+}
+void rgblight_increase_sat(void) {
+ uint8_t sat;
+ if (rgblight_config.sat + RGBLIGHT_SAT_STEP > 255) {
+ sat = 255;
+ } else {
+ sat = rgblight_config.sat+RGBLIGHT_SAT_STEP;
+ }
+ rgblight_sethsv(rgblight_config.hue, sat, rgblight_config.val);
+}
+void rgblight_decrease_sat(void){
+ uint8_t sat;
+ if (rgblight_config.sat - RGBLIGHT_SAT_STEP < 0) {
+ sat = 0;
+ } else {
+ sat = rgblight_config.sat-RGBLIGHT_SAT_STEP;
+ }
+ rgblight_sethsv(rgblight_config.hue, sat, rgblight_config.val);
+}
+void rgblight_increase_val(void){
+ uint8_t val;
+ if (rgblight_config.val + RGBLIGHT_VAL_STEP > 255) {
+ val = 255;
+ } else {
+ val = rgblight_config.val+RGBLIGHT_VAL_STEP;
+ }
+ rgblight_sethsv(rgblight_config.hue, rgblight_config.sat, val);
+}
+void rgblight_decrease_val(void) {
+ uint8_t val;
+ if (rgblight_config.val - RGBLIGHT_VAL_STEP < 0) {
+ val = 0;
+ } else {
+ val = rgblight_config.val-RGBLIGHT_VAL_STEP;
+ }
+ rgblight_sethsv(rgblight_config.hue, rgblight_config.sat, val);
+}
+
+void rgblight_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val){
+ inmem_config.raw = rgblight_config.raw;
+ if (rgblight_config.enable) {
+ struct cRGB tmp_led;
+ sethsv(hue, sat, val, &tmp_led);
+ inmem_config.hue = hue;
+ inmem_config.sat = sat;
+ inmem_config.val = val;
+ // dprintf("rgblight set hue [MEMORY]: %u,%u,%u\n", inmem_config.hue, inmem_config.sat, inmem_config.val);
+ rgblight_setrgb(tmp_led.r, tmp_led.g, tmp_led.b);
+ }
+}
+void rgblight_sethsv(uint16_t hue, uint8_t sat, uint8_t val){
+ if (rgblight_config.enable) {
+ if (rgblight_config.mode == 1) {
+ // same static color
+ rgblight_sethsv_noeeprom(hue, sat, val);
+ } else {
+ // all LEDs in same color
+ if (rgblight_config.mode >= 2 && rgblight_config.mode <= 5) {
+ // breathing mode, ignore the change of val, use in memory value instead
+ val = rgblight_config.val;
+ } else if (rgblight_config.mode >= 6 && rgblight_config.mode <= 14) {
+ // rainbow mood and rainbow swirl, ignore the change of hue
+ hue = rgblight_config.hue;
+ }
+ }
+ rgblight_config.hue = hue;
+ rgblight_config.sat = sat;
+ rgblight_config.val = val;
+ eeconfig_update_rgblight(rgblight_config.raw);
+ xprintf("rgblight set hsv [EEPROM]: %u,%u,%u\n", rgblight_config.hue, rgblight_config.sat, rgblight_config.val);
+ }
+}
+
+void rgblight_setrgb(uint8_t r, uint8_t g, uint8_t b){
+ // dprintf("rgblight set rgb: %u,%u,%u\n", r,g,b);
+ for (uint8_t i=0;i<RGBLED_NUM;i++) {
+ led[i].r = r;
+ led[i].g = g;
+ led[i].b = b;
+ }
+ rgblight_set();
+
+}
+
+void rgblight_set(void) {
+ if (rgblight_config.enable) {
+ ws2812_setleds(led, RGBLED_NUM);
+ } else {
+ for (uint8_t i=0;i<RGBLED_NUM;i++) {
+ led[i].r = 0;
+ led[i].g = 0;
+ led[i].b = 0;
+ }
+ ws2812_setleds(led, RGBLED_NUM);
+ }
+}
+
+// Animation timer -- AVR Timer3
+void rgblight_timer_init(void) {
+ static uint8_t rgblight_timer_is_init = 0;
+ if (rgblight_timer_is_init) {
+ return;
+ }
+ rgblight_timer_is_init = 1;
+ /* Timer 3 setup */
+ TCCR3B = _BV(WGM32) //CTC mode OCR3A as TOP
+ | _BV(CS30); //Clock selelct: clk/1
+ /* Set TOP value */
+ uint8_t sreg = SREG;
+ cli();
+ OCR3AH = (RGBLED_TIMER_TOP>>8)&0xff;
+ OCR3AL = RGBLED_TIMER_TOP&0xff;
+ SREG = sreg;
+}
+void rgblight_timer_enable(void) {
+ TIMSK3 |= _BV(OCIE3A);
+ dprintf("TIMER3 enabled.\n");
+}
+void rgblight_timer_disable(void) {
+ TIMSK3 &= ~_BV(OCIE3A);
+ dprintf("TIMER3 disabled.\n");
+}
+void rgblight_timer_toggle(void) {
+ TIMSK3 ^= _BV(OCIE3A);
+ dprintf("TIMER3 toggled.\n");
+}
+
+ISR(TIMER3_COMPA_vect) {
+ // Mode = 1, static light, do nothing here
+ if (rgblight_config.mode>=2 && rgblight_config.mode<=5) {
+ // mode = 2 to 5, breathing mode
+ rgblight_effect_breathing(rgblight_config.mode-2);
+
+ } else if (rgblight_config.mode>=6 && rgblight_config.mode<=8) {
+ rgblight_effect_rainbow_mood(rgblight_config.mode-6);
+ } else if (rgblight_config.mode>=9 && rgblight_config.mode<=14) {
+ rgblight_effect_rainbow_swirl(rgblight_config.mode-9);
+ } else if (rgblight_config.mode>=15 && rgblight_config.mode<=20) {
+ rgblight_effect_snake(rgblight_config.mode-15);
+ } else if (rgblight_config.mode>=21 && rgblight_config.mode<=23) {
+ rgblight_effect_knight(rgblight_config.mode-21);
+ }
+}
+
+// effects
+void rgblight_effect_breathing(uint8_t interval) {
+ static uint8_t pos = 0;
+ static uint16_t last_timer = 0;
+
+ if (timer_elapsed(last_timer)<pgm_read_byte(&RGBLED_BREATHING_INTERVALS[interval])) return;
+ last_timer = timer_read();
+
+ rgblight_sethsv_noeeprom(rgblight_config.hue, rgblight_config.sat, pgm_read_byte(&RGBLED_BREATHING_TABLE[pos]));
+ pos = (pos+1) % 256;
+}
+
+void rgblight_effect_rainbow_mood(uint8_t interval) {
+ static uint16_t current_hue=0;
+ static uint16_t last_timer = 0;
+
+ if (timer_elapsed(last_timer)<pgm_read_byte(&RGBLED_RAINBOW_MOOD_INTERVALS[interval])) return;
+ last_timer = timer_read();
+ rgblight_sethsv_noeeprom(current_hue, rgblight_config.sat, rgblight_config.val);
+ current_hue = (current_hue+1) % 360;
+}
+
+void rgblight_effect_rainbow_swirl(uint8_t interval) {
+ static uint16_t current_hue=0;
+ static uint16_t last_timer = 0;
+ uint16_t hue;
+ uint8_t i;
+ if (timer_elapsed(last_timer)<pgm_read_byte(&RGBLED_RAINBOW_MOOD_INTERVALS[interval/2])) return;
+ last_timer = timer_read();
+ for (i=0; i<RGBLED_NUM; i++) {
+ hue = (360/RGBLED_NUM*i+current_hue)%360;
+ sethsv(hue, rgblight_config.sat, rgblight_config.val, &led[i]);
+ }
+ rgblight_set();
+
+ if (interval % 2) {
+ current_hue = (current_hue+1) % 360;
+ } else {
+ if (current_hue -1 < 0) {
+ current_hue = 359;
+ } else {
+ current_hue = current_hue - 1;
+ }
+
+ }
+}
+void rgblight_effect_snake(uint8_t interval) {
+ static uint8_t pos=0;
+ static uint16_t last_timer = 0;
+ uint8_t i,j;
+ int8_t k;
+ int8_t increament = 1;
+ if (interval%2) increament = -1;
+ if (timer_elapsed(last_timer)<pgm_read_byte(&RGBLED_SNAKE_INTERVALS[interval/2])) return;
+ last_timer = timer_read();
+ for (i=0;i<RGBLED_NUM;i++) {
+ led[i].r=0;
+ led[i].g=0;
+ led[i].b=0;
+ for (j=0;j<RGBLIGHT_EFFECT_SNAKE_LENGTH;j++) {
+ k = pos+j*increament;
+ if (k<0) k = k+RGBLED_NUM;
+ if (i==k) {
+ sethsv(rgblight_config.hue, rgblight_config.sat, (uint8_t)(rgblight_config.val*(RGBLIGHT_EFFECT_SNAKE_LENGTH-j)/RGBLIGHT_EFFECT_SNAKE_LENGTH), &led[i]);
+ }
+ }
+ }
+ rgblight_set();
+ if (increament == 1) {
+ if (pos - 1 < 0) {
+ pos = RGBLED_NUM-1;
+ } else {
+ pos -= 1;
+ }
+ } else {
+ pos = (pos+1)%RGBLED_NUM;
+ }
+
+}
+
+void rgblight_effect_knight(uint8_t interval) {
+ static int8_t pos=0;
+ static uint16_t last_timer = 0;
+ uint8_t i,j,cur;
+ int8_t k;
+ struct cRGB preled[RGBLED_NUM];
+ static int8_t increament = -1;
+ if (timer_elapsed(last_timer)<pgm_read_byte(&RGBLED_KNIGHT_INTERVALS[interval])) return;
+ last_timer = timer_read();
+ for (i=0;i<RGBLED_NUM;i++) {
+ preled[i].r=0;
+ preled[i].g=0;
+ preled[i].b=0;
+ for (j=0;j<RGBLIGHT_EFFECT_KNIGHT_LENGTH;j++) {
+ k = pos+j*increament;
+ if (k<0) k = 0;
+ if (k>=RGBLED_NUM) k=RGBLED_NUM-1;
+ if (i==k) {
+ sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, &preled[i]);
+ }
+ }
+ }
+ if (RGBLIGHT_EFFECT_KNIGHT_OFFSET) {
+ for (i=0;i<RGBLED_NUM;i++) {
+ cur = (i+RGBLIGHT_EFFECT_KNIGHT_OFFSET) % RGBLED_NUM;
+ led[i].r = preled[cur].r;
+ led[i].g = preled[cur].g;
+ led[i].b = preled[cur].b;
+ }
+ }
+ rgblight_set();
+ if (increament == 1) {
+ if (pos - 1 < 0 - RGBLIGHT_EFFECT_KNIGHT_LENGTH) {
+ pos = 0- RGBLIGHT_EFFECT_KNIGHT_LENGTH;
+ increament = -1;
+ } else {
+ pos -= 1;
+ }
+ } else {
+ if (pos+1>RGBLED_NUM+RGBLIGHT_EFFECT_KNIGHT_LENGTH) {
+ pos = RGBLED_NUM+RGBLIGHT_EFFECT_KNIGHT_LENGTH-1;
+ increament = 1;
+ } else {
+ pos += 1;
+ }
+ }
+
+}
diff --git a/quantum/rgblight.h b/quantum/rgblight.h
new file mode 100644
index 000000000..64f92523e
--- /dev/null
+++ b/quantum/rgblight.h
@@ -0,0 +1,86 @@
+#ifndef RGBLIGHT_H
+#define RGBLIGHT_H
+
+#ifndef RGBLIGHT_MODES
+#define RGBLIGHT_MODES 23
+#endif
+
+#ifndef RGBLIGHT_EFFECT_SNAKE_LENGTH
+#define RGBLIGHT_EFFECT_SNAKE_LENGTH 7
+#endif
+
+#ifndef RGBLIGHT_EFFECT_KNIGHT_LENGTH
+#define RGBLIGHT_EFFECT_KNIGHT_LENGTH 7
+#endif
+#ifndef RGBLIGHT_EFFECT_KNIGHT_OFFSET
+#define RGBLIGHT_EFFECT_KNIGHT_OFFSET 9
+#endif
+
+#ifndef RGBLIGHT_EFFECT_DUALKNIGHT_LENGTH
+#define RGBLIGHT_EFFECT_DUALKNIGHT_LENGTH 4
+#endif
+
+#ifndef RGBLIGHT_HUE_STEP
+#define RGBLIGHT_HUE_STEP 10
+#endif
+#ifndef RGBLIGHT_SAT_STEP
+#define RGBLIGHT_SAT_STEP 17
+#endif
+#ifndef RGBLIGHT_VAL_STEP
+#define RGBLIGHT_VAL_STEP 17
+#endif
+
+#define RGBLED_TIMER_TOP F_CPU/(256*64)
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "eeconfig.h"
+#include "light_ws2812.h"
+
+typedef union {
+ uint32_t raw;
+ struct {
+ bool enable :1;
+ uint8_t mode :6;
+ uint16_t hue :9;
+ uint8_t sat :8;
+ uint8_t val :8;
+ };
+} rgblight_config_t;
+
+void rgblight_init(void);
+void rgblight_increase(void);
+void rgblight_decrease(void);
+void rgblight_toggle(void);
+void rgblight_step(void);
+void rgblight_mode(uint8_t mode);
+void rgblight_set(void);
+void rgblight_increase_hue(void);
+void rgblight_decrease_hue(void);
+void rgblight_increase_sat(void);
+void rgblight_decrease_sat(void);
+void rgblight_increase_val(void);
+void rgblight_decrease_val(void);
+void rgblight_sethsv(uint16_t hue, uint8_t sat, uint8_t val);
+void rgblight_setrgb(uint8_t r, uint8_t g, uint8_t b);
+
+uint32_t eeconfig_read_rgblight(void);
+void eeconfig_update_rgblight(uint32_t val);
+void eeconfig_update_rgblight_default(void);
+void eeconfig_debug_rgblight(void);
+
+void sethsv(uint16_t hue, uint8_t sat, uint8_t val, struct cRGB *led1);
+void setrgb(uint8_t r, uint8_t g, uint8_t b, struct cRGB *led1);
+void rgblight_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val);
+
+void rgblight_timer_init(void);
+void rgblight_timer_enable(void);
+void rgblight_timer_disable(void);
+void rgblight_timer_toggle(void);
+void rgblight_effect_breathing(uint8_t interval);
+void rgblight_effect_rainbow_mood(uint8_t interval);
+void rgblight_effect_rainbow_swirl(uint8_t interval);
+void rgblight_effect_snake(uint8_t interval);
+void rgblight_effect_knight(uint8_t interval);
+
+#endif
diff --git a/quantum/serial_link/.gitignore b/quantum/serial_link/.gitignore
new file mode 100644
index 000000000..2d68e206e
--- /dev/null
+++ b/quantum/serial_link/.gitignore
@@ -0,0 +1 @@
+*.stackdump
diff --git a/quantum/serial_link/.gitmodules b/quantum/serial_link/.gitmodules
new file mode 100644
index 000000000..991cfe96d
--- /dev/null
+++ b/quantum/serial_link/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "cgreen/cgreen"]
+ path = cgreen/cgreen
+ url = http://github.com/cgreen-devs/cgreen
diff --git a/LICENSE b/quantum/serial_link/LICENSE
index d7cc3198c..d7cc3198c 100644
--- a/LICENSE
+++ b/quantum/serial_link/LICENSE
diff --git a/README.md b/quantum/serial_link/README.md
index 94af9125c..94af9125c 100644
--- a/README.md
+++ b/quantum/serial_link/README.md
diff --git a/cgreen/Makefile b/quantum/serial_link/cgreen/Makefile
index 6b31a3f92..6b31a3f92 100644
--- a/cgreen/Makefile
+++ b/quantum/serial_link/cgreen/Makefile
diff --git a/cgreen/Makefile.build b/quantum/serial_link/cgreen/Makefile.build
index f76165244..f76165244 100644
--- a/cgreen/Makefile.build
+++ b/quantum/serial_link/cgreen/Makefile.build
diff --git a/cgreen/cgreen b/quantum/serial_link/cgreen/cgreen
-Subproject d4d438dda1b7131f0bd0530b2c258e9dea6a2a9
+Subproject d4d438dda1b7131f0bd0530b2c258e9dea6a2a9
diff --git a/serial_link.mk b/quantum/serial_link/serial_link.mk
index e164cc5ff..e164cc5ff 100644
--- a/serial_link.mk
+++ b/quantum/serial_link/serial_link.mk
diff --git a/serial_link/protocol/byte_stuffer.c b/quantum/serial_link/serial_link/protocol/byte_stuffer.c
index fb4c45a8d..fb4c45a8d 100644
--- a/serial_link/protocol/byte_stuffer.c
+++ b/quantum/serial_link/serial_link/protocol/byte_stuffer.c
diff --git a/serial_link/protocol/byte_stuffer.h b/quantum/serial_link/serial_link/protocol/byte_stuffer.h
index 2cc88beb4..2cc88beb4 100644
--- a/serial_link/protocol/byte_stuffer.h
+++ b/quantum/serial_link/serial_link/protocol/byte_stuffer.h
diff --git a/serial_link/protocol/frame_router.c b/quantum/serial_link/serial_link/protocol/frame_router.c
index 04b8c2e75..04b8c2e75 100644
--- a/serial_link/protocol/frame_router.c
+++ b/quantum/serial_link/serial_link/protocol/frame_router.c
diff --git a/serial_link/protocol/frame_router.h b/quantum/serial_link/serial_link/protocol/frame_router.h
index 712250ff3..712250ff3 100644
--- a/serial_link/protocol/frame_router.h
+++ b/quantum/serial_link/serial_link/protocol/frame_router.h
diff --git a/serial_link/protocol/frame_validator.c b/quantum/serial_link/serial_link/protocol/frame_validator.c
index 474f80ee8..474f80ee8 100644
--- a/serial_link/protocol/frame_validator.c
+++ b/quantum/serial_link/serial_link/protocol/frame_validator.c
diff --git a/serial_link/protocol/frame_validator.h b/quantum/serial_link/serial_link/protocol/frame_validator.h
index 4a910d510..4a910d510 100644
--- a/serial_link/protocol/frame_validator.h
+++ b/quantum/serial_link/serial_link/protocol/frame_validator.h
diff --git a/serial_link/protocol/physical.h b/quantum/serial_link/serial_link/protocol/physical.h
index 425e06cdd..425e06cdd 100644
--- a/serial_link/protocol/physical.h
+++ b/quantum/serial_link/serial_link/protocol/physical.h
diff --git a/serial_link/protocol/transport.c b/quantum/serial_link/serial_link/protocol/transport.c
index f418d11ce..f418d11ce 100644
--- a/serial_link/protocol/transport.c
+++ b/quantum/serial_link/serial_link/protocol/transport.c
diff --git a/serial_link/protocol/transport.h b/quantum/serial_link/serial_link/protocol/transport.h
index 9a052d880..9a052d880 100644
--- a/serial_link/protocol/transport.h
+++ b/quantum/serial_link/serial_link/protocol/transport.h
diff --git a/serial_link/protocol/triple_buffered_object.c b/quantum/serial_link/serial_link/protocol/triple_buffered_object.c
index e3e8989d3..e3e8989d3 100644
--- a/serial_link/protocol/triple_buffered_object.c
+++ b/quantum/serial_link/serial_link/protocol/triple_buffered_object.c
diff --git a/serial_link/protocol/triple_buffered_object.h b/quantum/serial_link/serial_link/protocol/triple_buffered_object.h
index 2e57db3f5..2e57db3f5 100644
--- a/serial_link/protocol/triple_buffered_object.h
+++ b/quantum/serial_link/serial_link/protocol/triple_buffered_object.h
diff --git a/serial_link/system/serial_link.c b/quantum/serial_link/serial_link/system/serial_link.c
index 75c7e77a7..75c7e77a7 100644
--- a/serial_link/system/serial_link.c
+++ b/quantum/serial_link/serial_link/system/serial_link.c
diff --git a/serial_link/system/serial_link.h b/quantum/serial_link/serial_link/system/serial_link.h
index 351e03877..351e03877 100644
--- a/serial_link/system/serial_link.h
+++ b/quantum/serial_link/serial_link/system/serial_link.h
diff --git a/serial_link/tests/Makefile b/quantum/serial_link/serial_link/tests/Makefile
index 1b072c6f1..1b072c6f1 100644
--- a/serial_link/tests/Makefile
+++ b/quantum/serial_link/serial_link/tests/Makefile
diff --git a/serial_link/tests/byte_stuffer_tests.c b/quantum/serial_link/serial_link/tests/byte_stuffer_tests.c
index 64b170e8c..64b170e8c 100644
--- a/serial_link/tests/byte_stuffer_tests.c
+++ b/quantum/serial_link/serial_link/tests/byte_stuffer_tests.c
diff --git a/serial_link/tests/frame_router_tests.c b/quantum/serial_link/serial_link/tests/frame_router_tests.c
index 6c806fa93..6c806fa93 100644
--- a/serial_link/tests/frame_router_tests.c
+++ b/quantum/serial_link/serial_link/tests/frame_router_tests.c
diff --git a/serial_link/tests/frame_validator_tests.c b/quantum/serial_link/serial_link/tests/frame_validator_tests.c
index d20947e2c..d20947e2c 100644
--- a/serial_link/tests/frame_validator_tests.c
+++ b/quantum/serial_link/serial_link/tests/frame_validator_tests.c
diff --git a/serial_link/tests/transport_tests.c b/quantum/serial_link/serial_link/tests/transport_tests.c
index 358e1b9fd..358e1b9fd 100644
--- a/serial_link/tests/transport_tests.c
+++ b/quantum/serial_link/serial_link/tests/transport_tests.c
diff --git a/serial_link/tests/triple_buffered_object_tests.c b/quantum/serial_link/serial_link/tests/triple_buffered_object_tests.c
index 6f7c82b46..6f7c82b46 100644
--- a/serial_link/tests/triple_buffered_object_tests.c
+++ b/quantum/serial_link/serial_link/tests/triple_buffered_object_tests.c
diff --git a/serial_link_tests.mk b/quantum/serial_link/serial_link_tests.mk
index e292f582a..e292f582a 100644
--- a/serial_link_tests.mk
+++ b/quantum/serial_link/serial_link_tests.mk
diff --git a/quantum/template/Makefile b/quantum/template/Makefile
new file mode 100644
index 000000000..3f6d133c9
--- /dev/null
+++ b/quantum/template/Makefile
@@ -0,0 +1,75 @@
+
+
+# MCU name
+#MCU = at90usb1287
+MCU = atmega32u4
+
+# Processor frequency.
+# This will define a symbol, F_CPU, in all source code files equal to the
+# processor frequency in Hz. You can then use this symbol in your source code to
+# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
+# automatically to create a 32-bit value in your source code.
+#
+# This will be an integer division of F_USB below, as it is sourced by
+# F_USB after it has run through any CPU prescalers. Note that this value
+# does not *change* the processor frequency - it should merely be updated to
+# reflect the processor speed set externally so that the code can use accurate
+# software delays.
+F_CPU = 16000000
+
+
+#
+# LUFA specific
+#
+# Target architecture (see library "Board Types" documentation).
+ARCH = AVR8
+
+# Input clock frequency.
+# This will define a symbol, F_USB, in all source code files equal to the
+# input clock frequency (before any prescaling is performed) in Hz. This value may
+# differ from F_CPU if prescaling is used on the latter, and is required as the
+# raw input clock is fed directly to the PLL sections of the AVR for high speed
+# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
+# at the end, this will be done automatically to create a 32-bit value in your
+# source code.
+#
+# If no clock division is performed on the input clock inside the AVR (via the
+# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
+F_USB = $(F_CPU)
+
+# Interrupt driven control endpoint task(+60)
+OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
+
+
+# Boot Section Size in *bytes*
+# Teensy halfKay 512
+# Teensy++ halfKay 1024
+# Atmel DFU loader 4096
+# LUFA bootloader 4096
+# USBaspLoader 2048
+OPT_DEFS += -DBOOTLOADER_SIZE=512
+
+
+# Build Options
+# change yes to no to disable
+#
+BOOTMAGIC_ENABLE ?= no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE ?= yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450)
+CONSOLE_ENABLE ?= yes # Console for debug(+400)
+COMMAND_ENABLE ?= yes # Commands for debug and configuration
+# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
+SLEEP_LED_ENABLE ?= no # Breathing sleep LED during USB suspend
+# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+NKRO_ENABLE ?= no # USB Nkey Rollover
+BACKLIGHT_ENABLE ?= no # Enable keyboard backlight functionality on B7 by default
+MIDI_ENABLE ?= no # MIDI controls
+UNICODE_ENABLE ?= no # Unicode
+BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID
+AUDIO_ENABLE ?= no # Audio output on port C6
+
+ifndef QUANTUM_DIR
+ include ../../Makefile
+endif
+
+
diff --git a/quantum/template/config.h b/quantum/template/config.h
new file mode 100644
index 000000000..b02f0c7eb
--- /dev/null
+++ b/quantum/template/config.h
@@ -0,0 +1,162 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "config_common.h"
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x6060
+#define DEVICE_VER 0x0001
+#define MANUFACTURER You
+#define PRODUCT %KEYBOARD%
+#define DESCRIPTION A custom keyboard
+
+/* key matrix size */
+#define MATRIX_ROWS 2
+#define MATRIX_COLS 3
+
+/*
+ * Keyboard Matrix Assignments
+ *
+ * Change this to how you wired your keyboard
+ * COLS: AVR pins used for columns, left to right
+ * ROWS: AVR pins used for rows, top to bottom
+ * DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode)
+ * ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode)
+ *
+*/
+#define MATRIX_ROW_PINS { D0, D5 }
+#define MATRIX_COL_PINS { F1, F0, B0 }
+#define UNUSED_PINS
+
+/* COL2ROW or ROW2COL */
+#define DIODE_DIRECTION COL2ROW
+
+// #define BACKLIGHT_PIN B7
+// #define BACKLIGHT_BREATHING
+// #define BACKLIGHT_LEVELS 3
+
+
+/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
+#define DEBOUNCING_DELAY 5
+
+/* define if matrix has ghost (lacks anti-ghosting diodes) */
+//#define MATRIX_HAS_GHOST
+
+/* number of backlight levels */
+
+/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
+#define LOCKING_SUPPORT_ENABLE
+/* Locking resynchronize hack */
+#define LOCKING_RESYNC_ENABLE
+
+/*
+ * Force NKRO
+ *
+ * Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved
+ * state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the
+ * makefile for this to work.)
+ *
+ * If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N)
+ * until the next keyboard reset.
+ *
+ * NKRO may prevent your keystrokes from being detected in the BIOS, but it is
+ * fully operational during normal computer usage.
+ *
+ * For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N)
+ * or via bootmagic (hold SPACE+N while plugging in the keyboard). Once set by
+ * bootmagic, NKRO mode will always be enabled until it is toggled again during a
+ * power-up.
+ *
+ */
+//#define FORCE_NKRO
+
+/*
+ * Magic Key Options
+ *
+ * Magic keys are hotkey commands that allow control over firmware functions of
+ * the keyboard. They are best used in combination with the HID Listen program,
+ * found here: https://www.pjrc.com/teensy/hid_listen.html
+ *
+ * The options below allow the magic key functionality to be changed. This is
+ * useful if your keyboard/keypad is missing keys and you want magic key support.
+ *
+ */
+
+/* key combination for magic key command */
+#define IS_COMMAND() ( \
+ keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
+)
+
+/* control how magic key switches layers */
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS true
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS true
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM false
+
+/* override magic key keymap */
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS
+//#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM
+//#define MAGIC_KEY_HELP1 H
+//#define MAGIC_KEY_HELP2 SLASH
+//#define MAGIC_KEY_DEBUG D
+//#define MAGIC_KEY_DEBUG_MATRIX X
+//#define MAGIC_KEY_DEBUG_KBD K
+//#define MAGIC_KEY_DEBUG_MOUSE M
+//#define MAGIC_KEY_VERSION V
+//#define MAGIC_KEY_STATUS S
+//#define MAGIC_KEY_CONSOLE C
+//#define MAGIC_KEY_LAYER0_ALT1 ESC
+//#define MAGIC_KEY_LAYER0_ALT2 GRAVE
+//#define MAGIC_KEY_LAYER0 0
+//#define MAGIC_KEY_LAYER1 1
+//#define MAGIC_KEY_LAYER2 2
+//#define MAGIC_KEY_LAYER3 3
+//#define MAGIC_KEY_LAYER4 4
+//#define MAGIC_KEY_LAYER5 5
+//#define MAGIC_KEY_LAYER6 6
+//#define MAGIC_KEY_LAYER7 7
+//#define MAGIC_KEY_LAYER8 8
+//#define MAGIC_KEY_LAYER9 9
+//#define MAGIC_KEY_BOOTLOADER PAUSE
+//#define MAGIC_KEY_LOCK CAPS
+//#define MAGIC_KEY_EEPROM E
+//#define MAGIC_KEY_NKRO N
+//#define MAGIC_KEY_SLEEP_LED Z
+
+/*
+ * Feature disable options
+ * These options are also useful to firmware size reduction.
+ */
+
+/* disable debug print */
+//#define NO_DEBUG
+
+/* disable print */
+//#define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+
+#endif
diff --git a/quantum/template/keymaps/default/Makefile b/quantum/template/keymaps/default/Makefile
new file mode 100644
index 000000000..f4671a9d1
--- /dev/null
+++ b/quantum/template/keymaps/default/Makefile
@@ -0,0 +1,21 @@
+# Build Options
+# change to "no" to disable the options, or define them in the Makefile in
+# the appropriate keymap folder that will get included automatically
+#
+BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000)
+MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
+EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
+CONSOLE_ENABLE = no # Console for debug(+400)
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
+MIDI_ENABLE = no # MIDI controls
+AUDIO_ENABLE = no # Audio output on port C6
+UNICODE_ENABLE = no # Unicode
+BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
+RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.
+SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
+
+ifndef QUANTUM_DIR
+ include ../../../../Makefile
+endif \ No newline at end of file
diff --git a/quantum/template/keymaps/default/config.h b/quantum/template/keymaps/default/config.h
new file mode 100644
index 000000000..df06a2620
--- /dev/null
+++ b/quantum/template/keymaps/default/config.h
@@ -0,0 +1,8 @@
+#ifndef CONFIG_USER_H
+#define CONFIG_USER_H
+
+#include "../../config.h"
+
+// place overrides here
+
+#endif \ No newline at end of file
diff --git a/quantum/template/keymaps/default/keymap.c b/quantum/template/keymaps/default/keymap.c
new file mode 100644
index 000000000..e28a4723e
--- /dev/null
+++ b/quantum/template/keymaps/default/keymap.c
@@ -0,0 +1,44 @@
+#include "%KEYBOARD%.h"
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+[0] = KEYMAP( /* Base */
+ KC_A, KC_1, KC_H, \
+ KC_TAB, KC_SPC \
+),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+
+};
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ // MACRODOWN only works in this function
+ switch(id) {
+ case 0:
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ } else {
+ unregister_code(KC_RSFT);
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+
+
+void matrix_init_user(void) {
+
+}
+
+void matrix_scan_user(void) {
+
+}
+
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+ return true;
+}
+
+void led_set_user(uint8_t usb_led) {
+
+} \ No newline at end of file
diff --git a/quantum/template/keymaps/default/readme.md b/quantum/template/keymaps/default/readme.md
new file mode 100644
index 000000000..21aa663d5
--- /dev/null
+++ b/quantum/template/keymaps/default/readme.md
@@ -0,0 +1 @@
+# The default keymap for %KEYBOARD% \ No newline at end of file
diff --git a/quantum/template/readme.md b/quantum/template/readme.md
new file mode 100644
index 000000000..b2fb4dd98
--- /dev/null
+++ b/quantum/template/readme.md
@@ -0,0 +1,28 @@
+%KEYBOARD% keyboard firmware
+======================
+
+## Quantum MK Firmware
+
+For the full Quantum feature list, see [the parent readme.md](/doc/readme.md).
+
+## Building
+
+Download or clone the whole firmware and navigate to the keyboards/%KEYBOARD% folder. Once your dev env is setup, you'll be able to type `make` to generate your .hex - you can then use the Teensy Loader to program your .hex file.
+
+Depending on which keymap you would like to use, you will have to compile slightly differently.
+
+### Default
+
+To build with the default keymap, simply run `make`.
+
+### Other Keymaps
+
+Several version of keymap are available in advance but you are recommended to define your favorite layout yourself. To define your own keymap create a folder with the name of your keymap in the keymaps folder, and see keymap documentation (you can find in top readme.md) and existant keymap files.
+
+To build the firmware binary hex file with a keymap just do `make` with `keymap` option like:
+
+```
+$ make keymap=[default|jack|<name>]
+```
+
+Keymaps follow the format **__keymap.c__** and are stored in folders in the `keymaps` folder, eg `keymaps/my_keymap/` \ No newline at end of file
diff --git a/quantum/template/template.c b/quantum/template/template.c
new file mode 100644
index 000000000..dcc4b0a22
--- /dev/null
+++ b/quantum/template/template.c
@@ -0,0 +1,28 @@
+#include "%KEYBOARD%.h"
+
+void matrix_init_kb(void) {
+ // put your keyboard start-up code here
+ // runs once when the firmware starts up
+
+ matrix_init_user();
+}
+
+void matrix_scan_kb(void) {
+ // put your looping keyboard code here
+ // runs every cycle (a lot)
+
+ matrix_scan_user();
+}
+
+bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
+ // put your per-action keyboard code here
+ // runs for every action, just before processing by the firmware
+
+ return process_action_user(record);
+}
+
+void led_set_kb(uint8_t usb_led) {
+ // put your keyboard LED indicator (ex: Caps Lock LED) toggling code here
+
+ led_set_user(usb_led);
+}
diff --git a/quantum/template/template.h b/quantum/template/template.h
new file mode 100644
index 000000000..cd78a54e3
--- /dev/null
+++ b/quantum/template/template.h
@@ -0,0 +1,19 @@
+#ifndef %KEYBOARD_UPPERCASE%_H
+#define %KEYBOARD_UPPERCASE%_H
+
+#include "quantum.h"
+
+// This a shortcut to help you visually see your layout.
+// The following is an example using the Planck MIT layout
+// The first section contains all of the arguements
+// The second converts the arguments into a two-dimensional array
+#define KEYMAP( \
+ k00, k01, k02, \
+ k10, k11 \
+) \
+{ \
+ { k00, k01, k02 }, \
+ { k10, KC_NO, k11 }, \
+}
+
+#endif
diff --git a/quantum/tools/eeprom_reset.hex b/quantum/tools/eeprom_reset.hex
new file mode 100644
index 000000000..a8a75389f
--- /dev/null
+++ b/quantum/tools/eeprom_reset.hex
@@ -0,0 +1,9 @@
+:10000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00
+:10001000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0
+:10002000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0
+:10003000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0
+:10004000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0
+:10005000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0
+:10006000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA0
+:10007000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF90
+:00000001FF
diff --git a/quantum/tools/readme.md b/quantum/tools/readme.md
new file mode 100644
index 000000000..5f355256d
--- /dev/null
+++ b/quantum/tools/readme.md
@@ -0,0 +1,6 @@
+`eeprom_reset.hex` is to reset the eeprom on the Atmega32u4, like this:
+
+ dfu-programmer atmega32u4 erase
+ dfu-programmer atmega32u4 flash --eeprom eeprom_reset.hex
+
+ You'll need to reflash afterwards, because DFU requires the flash to be erased before messing with the eeprom.
diff --git a/readme.md b/readme.md
new file mode 100644
index 000000000..c24d951d8
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,813 @@
+# Quantum Mechanical Keyboard Firmware
+
+[![Build Status](https://travis-ci.org/jackhumbert/qmk_firmware.svg?branch=master)](https://travis-ci.org/jackhumbert/qmk_firmware)
+
+This is a keyboard firmware based on the [tmk_keyboard firmware](http://github.com/tmk/tmk_keyboard) with some useful features for Atmel AVR controllers, and more specifically, the [OLKB product line](http://olkb.com), the [ErgoDox EZ](http://www.ergodox-ez.com) keyboard, and the [Clueboard product line](http://clueboard.co/).
+
+## Official website
+
+For an easy-to-read version of this document and the repository, check out [http://qmk.fm](http://qmk.fm). Nicely formatted keyboard and keymap listings are also available there, along with the ability to download .hex files instead of having to setup a build environment and compile them.
+
+## Included Keyboards
+
+* [Planck](/keyboards/planck/)
+* [Preonic](/keyboards/preonic/)
+* [Atomic](/keyboards/atomic/)
+* [ErgoDox EZ](/keyboards/ergodox_ez/)
+* [Clueboard](/keyboards/clueboard/)
+* [Cluepad](/keyboards/cluepad/)
+
+The project also includes community support for [lots of other keyboards](/keyboards/).
+
+## Maintainers
+
+QMK is developed and maintained by Jack Humbert of OLKB with contributions from the community, and of course, [Hasu](https://github.com/tmk). This repo used to be a fork of [TMK](https://github.com/tmk/tmk_keyboard), and we are incredibly grateful for his founding contributions to the firmware. We've had to break the fork due to purely technical reasons - it simply became too different over time, and we've had to start refactoring some of the basic bits and pieces. We are huge fans of TMK and Hasu :)
+
+This documentation is edited and maintained by Erez Zukerman of ErgoDox EZ. If you spot any typos or inaccuracies, please [open an issue](https://github.com/jackhumbert/qmk_firmware/issues/new).
+#### 2016/02/10
+core: flabbergast's Chibios protocol was merged from <https://github.com/flabbergast/tmk_keyboard/tree/chibios> (@72b1668). See [tmk_core/protocol/chibios/README.md](tmk_core/protocol/chibios/README.md). Chibios protocol supports Cortex-M such as STM32 and Kinetis.
+
+
+The OLKB product firmwares are maintained by [Jack Humbert](https://github.com/jackhumbert), the Ergodox EZ by [Erez Zukerman](https://github.com/ezuk), and the Clueboard by [Zach White](https://github.com/skullydazed).
+
+## Documentation roadmap
+
+This is not a tiny project. While this is the main readme, there are many other files you might want to consult. Here are some points of interest:
+
+* The readme for your own keyboard: This is found under `keyboards/<your keyboards's name>/`. So for the ErgoDox EZ, it's [here](keyboards/ergodox_ez/); for the Planck, it's [here](keyboards/planck/) and so on.
+* The list of possible keycodes you can use in your keymap is actually spread out in a few different places:
+ * [doc/keycode.txt](doc/keycode.txt) - an explanation of those same keycodes.
+ * [quantum/keymap.h](quantum/keymap.h) - this is where the QMK-specific aliases are all set up. Things like the Hyper and Meh key, the Leader key, and all of the other QMK innovations. These are also explained and documented below, but `keymap.h` is where they're actually defined.
+* The [TMK documentation](doc/TMK_readme.md). QMK is based on TMK, and this explains how it works internally.
+
+# Getting started
+
+Before you are able to compile, you'll need to install an environment for AVR development. You'll find the instructions for any OS below. If you find another/better way to set things up from scratch, please consider [making a pull request](https://github.com/jackhumbert/qmk_firmware/pulls) with your changes!
+
+## Build Environment Setup
+
+### Windows (Vista and later)
+1. If you have ever installed WinAVR, uninstall it.
+2. Install [MHV AVR Tools](https://infernoembedded.com/sites/default/files/project/MHV_AVR_Tools_20131101.exe). Disable smatch, but **be sure to leave the option to add the tools to the PATH checked**.
+3. Install [MinGW](https://sourceforge.net/projects/mingw/files/Installer/mingw-get-setup.exe/download). During installation, uncheck the option to install a graphical user interface. **DO NOT change the default installation folder.** The scripts depend on the default location.
+4. Clone this repository. [This link will download it as a zip file, which you'll need to extract.](https://github.com/jackhumbert/qmk_firmware/archive/master.zip) Open the extracted folder in Windows Explorer.
+5. Double-click on the 1-setup-path-win batch script to run it. You'll need to accept a User Account Control prompt. Press the spacebar to dismiss the success message in the command prompt that pops up.
+6. Right-click on the 2-setup-environment-win batch script, select "Run as administrator", and accept the User Account Control prompt. This part may take a couple of minutes, and you'll need to approve a driver installation, but once it finishes, your environment is complete!
+7. Future build commands should be run from the MHV AVR Shell, which sets up an environment compatible with colorful build output. The standard Command Prompt will also work, but add `COLOR=false` to the end of all make commands when using it.
+
+### Mac
+If you're using [homebrew,](http://brew.sh/) you can use the following commands:
+
+ brew tap osx-cross/avr
+ brew install avr-libc
+ brew install dfu-programmer
+
+This is the recommended method. If you don't have homebrew, [install it!](http://brew.sh/) It's very much worth it for anyone who works in the command line.
+
+You can also try these instructions:
+
+1. Install Xcode from the App Store.
+2. Install the Command Line Tools from `Xcode->Preferences->Downloads`.
+3. Install [DFU-Programmer][dfu-prog].
+
+### Linux
+Install AVR GCC, AVR libc, and dfu-progammer with your favorite package manager.
+
+Debian/Ubuntu example:
+
+ sudo apt-get update
+ sudo apt-get install gcc-avr avr-libc dfu-programmer
+
+### Vagrant
+If you have any problems building the firmware, you can try using a tool called Vagrant. It will set up a virtual computer with a known configuration that's ready-to-go for firmware building. OLKB does NOT host the files for this virtual computer. Details on how to set up Vagrant are in the [VAGRANT_GUIDE file](VAGRANT_GUIDE.md).
+
+## Verify Your Installation
+1. If you haven't already, obtain this repository ([https://github.com/jackhumbert/qmk_firmware](https://github.com/jackhumbert/qmk_firmware)). You can either download it as a zip file and extract it, or clone it using the command line tool git or the Github Desktop application.
+2. Open up a terminal or command prompt and navigate to the `qmk_firmware` folder using the `cd` command. The command prompt will typically open to your home directory. If, for example, you cloned the repository to your Documents folder, then you would type `cd Documents/qmk_firmware`. If you extracted the file from a zip, then it may be named `qmk_firmware-master` instead.
+3. To confirm that you're in the correct location, you can display the contents of your current folder using the `dir` command on Windows, or the `ls` command on Linux or Mac. You should see several files, including `readme.md` and a `quantum` folder. From here, you need to navigate to the appropriate folder under `keyboards/`. For example, if you're building for a Planck, run `cd keyboards/planck`.
+4. Once you're in the correct keyboard-specific folder, run the `make` command. This should output a lot of information about the build process. More information about the `make` command can be found below.
+
+# Customizing your keymap
+
+In every keymap folder, the following files are recommended:
+
+* `config.h` - the options to configure your keymap
+* `keymap.c` - all of your keymap code, required
+* `Makefile` - the features of QMK that are enabled, required to run `make` in your keymap folder
+* `readme.md` - a description of your keymap, how others might use it, and explanations of features
+
+## The `make` command
+
+The `make` command is how you compile the firmware into a .hex file, which can be loaded by a dfu programmer (like dfu-progammer via `make dfu`) or the [Teensy loader](https://www.pjrc.com/teensy/loader.html) (only used with Teensys). You can run `make` from the root (`/`), your keyboard folder (`/keyboards/<keyboard>/`), or your keymap folder (`/keyboards/<keyboard>/keymaps/<keymap>/`) if you have a `Makefile` there (see the example [here](/doc/keymap_makefile_example.mk)).
+
+By default, this will generate a `<keyboard>_<keymap>.hex` file in whichever folder you run `make` from. These files are ignored by git, so don't worry about deleting them when committing/creating pull requests. Your .hex file will also be available on qmk.fm/keyboards/<keyboard>/keymaps/<keymap>/.
+
+Below are some definitions that will be useful:
+
+* The "root" (`/`) folder is the qmk_firmware folder, in which are `doc`, `keyboard`, `quantum`, etc.
+* The "keyboard" folder is any keyboard project's folder, like `/keyboards/planck`.
+* The "keymap" folder is any keymap's folder, like `/keyboards/planck/keymaps/default`.
+
+Below is a list of the useful `make` commands in QMK:
+
+* `make` - cleans automatically and builds your keyboard and keymap depending on which folder you're in. This defaults to the "default" layout (unless in a keymap folder), and Planck keyboard in the root folder
+ * `make keyboard=<keyboard>` - specifies the keyboard (only to be used in root)
+ * `make keymap=<keymap>` - specifies the keymap (only to be used in root and keyboard folder - not needed when in keymap folder)
+* `make quick` - skips the clean step (cannot be used immediately after modifying config.h or Makefiles)
+* `make dfu` - (requires dfu-programmer) builds and flashes the keymap to your keyboard once placed in reset/dfu mode (button or press `KC_RESET`). This does not work for Teensy-based keyboards like the ErgoDox EZ.
+ * `keyboard=` and `keymap=` are compatible with this
+* `make all-keyboards` - builds all keymaps for all keyboards and outputs status of each (use in root)
+* `make all-keyboards-default` - builds all default keymaps for all keyboards and outputs status of each (use in root)
+* `make all-keymaps [keyboard=<keyboard>]` - builds all of the keymaps for whatever keyboard folder you're in, or specified by `<keyboard>`
+* `make all-keyboards-quick`, `make all-keyboards-default-quick` and `make all-keymaps-quick [keyboard=<keyboard>]` - like the normal "make-all-*" commands, but they skip the clean steps
+
+Other, less useful functionality:
+
+* `make COLOR=false` - turns off color output
+* `make SILENT=true` - turns off output besides errors/warnings
+* `make VERBOSE=true` - outputs all of the avr-gcc stuff (not interesting)
+
+## The `Makefile`
+
+There are 3 different `make` and `Makefile` locations:
+
+* root (`/`)
+* keyboard (`/keyboards/<keyboard>/`)
+* keymap (`/keyboards/<keyboard>/keymaps/<keymap>/`)
+
+The root contains the code used to automatically figure out which keymap or keymaps to compile based on your current directory and commandline arguments. It's considered stable, and shouldn't be modified. The keyboard one will contain the MCU set-up and default settings for your keyboard, and shouldn't be modified unless you are the producer of that keyboard. The keymap Makefile can be modified by users, and is optional. It is included automatically if it exists. You can see an example [here](/doc/keymap_makefile_example.mk) - the last few lines are the most important. The settings you set here will override any defaults set in the keyboard Makefile. **It is required if you want to run `make` in the keymap folder.**
+
+### Makefile options
+
+Set the variables to `no` to disable them, and `yes` to enable them.
+
+`BOOTMAGIC_ENABLE`
+
+This allows you to hold a key and the salt key (space by default) and have access to a various EEPROM settings that persist over power loss. It's advised you keep this disabled, as the settings are often changed by accident, and produce confusing results that makes it difficult to debug. It's one of the more common problems encountered in help sessions.
+
+`MOUSEKEY_ENABLE`
+
+This gives you control over cursor movements and clicks via keycodes/custom functions.
+
+`EXTRAKEY_ENABLE`
+
+This allows you to use the system and audio control key codes.
+
+`CONSOLE_ENABLE`
+
+TODO
+
+`COMMAND_ENABLE`
+
+TODO
+
+`SLEEP_LED_ENABLE`
+
+Enables your LED to breath while your computer is sleeping. Timer1 is being used here. This feature is largely unused and untested, and needs updating/abstracting.
+
+`NKRO_ENABLE`
+
+This allows for n-key rollover (default is 6) to be enabled. It is off by default, but can be forced by adding `#define FORCE_NKRO` to your config.h.
+
+`BACKLIGHT_ENABLE`
+
+This enables your backlight on Timer1 and ports B5, B6, or B7 (for now). You can specify your port by putting this in your `config.h`:
+
+ #define BACKLIGHT_PIN B7
+
+`MIDI_ENABLE`
+
+This enables MIDI sending and receiving with your keyboard. To enter MIDI send mode, you can use the keycode `MI_ON`, and `MI_OFF` to turn it off. This is a largely untested feature, but more information can be found in the `quantum/quantum.c` file.
+
+`UNICODE_ENABLE`
+
+This allows you to send unicode symbols via `UC(<unicode>)` in your keymap. Only codes up to 0x7FFF are currently supported.
+
+`BLUETOOTH_ENABLE`
+
+This allows you to interface with a Bluefruit EZ-key to send keycodes wirelessly. It uses the D2 and D3 pins.
+
+`AUDIO_ENABLE`
+
+This allows you output audio on the C6 pin (needs abstracting). See the [audio section](#driving-a-speaker---audio-support) for more information.
+
+### Customizing Makefile options on a per-keymap basis
+
+If your keymap directory has a file called `Makefile` (note the filename), any Makefile options you set in that file will take precedence over other Makefile options for your particular keyboard.
+
+So let's say your keyboard's makefile has `BACKLIGHT_ENABLE = yes` (or maybe doesn't even list the `BACKLIGHT_ENABLE` option, which would cause it to be off). You want your particular keymap to not have the debug console, so you make a file called `Makefile` and specify `BACKLIGHT_ENABLE = no`.
+
+You can use the `doc/keymap_makefile_example.md` as a template/starting point.
+
+## The `config.h` file
+
+There are 2 `config.h` locations:
+
+* keyboard (`/keyboards/<keyboard>/`)
+* keymap (`/keyboards/<keyboard>/keymaps/<keymap>/`)
+
+The keyboard `config.h` is included only if the keymap one doesn't exist. The format to use for your custom one [is here](/doc/keymap_config_h_example.h). If you want to override a setting from the parent `config.h` file, you need to do this:
+
+```c
+#undef MY_SETTING
+#define MY_SETTING 4
+```
+
+For a value of `4` for this imaginary setting. So we `undef` it first, then `define` it.
+
+You can then override any settings, rather than having to copy and paste the whole thing.
+
+## Going beyond the keycodes
+
+Aside from the [basic keycodes](doc/keycode.txt), your keymap can include shortcuts to common operations.
+
+### Switching and toggling layers
+
+`MO(layer)` - momentary switch to *layer*. As soon as you let go of the key, the layer is deactivated and you pop back out to the previous layer. When you apply this to a key, that same key must be set as `KC_TRNS` on the destination layer. Otherwise, you won't make it back to the original layer when you release the key (and you'll get a keycode sent). You can only switch to layers *above* your current layer. If you're on layer 0 and you use `MO(1)`, that will switch to layer 1 just fine. But if you include `MO(3)` on layer 5, that won't do anything for you -- because layer 3 is lower than layer 5 on the stack.
+
+`OSL(layer)` - momentary switch to *layer*, as a one-shot operation. So if you have a key that's defined as `OSL(1)`, and you tap that key, then only the very next keystroke would come from layer 1. You would drop back to layer zero immediately after that one keystroke. That's handy if you have a layer full of custom shortcuts -- for example, a dedicated key for closing a window. So you tap your one-shot layer mod, then tap that magic 'close window' key, and keep typing like a boss. Layer 1 would remain active as long as you hold that key down, too (so you can use it like a momentary toggle-layer key with extra powers).
+
+`LT(layer, kc)` - momentary switch to *layer* when held, and *kc* when tapped. Like `MO()`, this only works upwards in the layer stack (`layer` must be higher than the current layer).
+
+`TG(layer)` - toggles a layer on or off. As with `MO()`, you should set this key as `KC_TRNS` in the destination layer so that tapping it again actually toggles back to the original layer. Only works upwards in the layer stack.
+
+
+### Fun with modifier keys
+
+* `LSFT(kc)` - applies left Shift to *kc* (keycode) - `S(kc)` is an alias
+* `RSFT(kc)` - applies right Shift to *kc*
+* `LCTL(kc)` - applies left Control to *kc*
+* `RCTL(kc)` - applies right Control to *kc*
+* `LALT(kc)` - applies left Alt to *kc*
+* `RALT(kc)` - applies right Alt to *kc*
+* `LGUI(kc)` - applies left GUI (command/win) to *kc*
+* `RGUI(kc)` - applies right GUI (command/win) to *kc*
+* `HYPR(kc)` - applies Hyper (all modifiers) to *kc*
+* `MEH(kc)` - applies Meh (all modifiers except Win/Cmd) to *kc*
+* `LCAG(kc)` - applies CtrlAltGui to *kc*
+
+You can also chain these, like this:
+
+ LALT(LCTL(KC_DEL)) -- this makes a key that sends Alt, Control, and Delete in a single keypress.
+
+The following shortcuts automatically add `LSFT()` to keycodes to get commonly used symbols. Their long names are also available and documented in `/quantum/keymap_common.h`.
+
+ KC_TILD ~
+ KC_EXLM !
+ KC_AT @
+ KC_HASH #
+ KC_DLR $
+ KC_PERC %
+ KC_CIRC ^
+ KC_AMPR &
+ KC_ASTR *
+ KC_LPRN (
+ KC_RPRN )
+ KC_UNDS _
+ KC_PLUS +
+ KC_DQUO "
+ KC_LCBR {
+ KC_RCBR }
+ KC_LABK <
+ KC_RABK >
+ KC_PIPE |
+ KC_COLN :
+
+`OSM(mod)` - this is a "one shot" modifier. So let's say you have your left Shift key defined as `OSM(MOD_LSFT)`. Tap it, let go, and Shift is "on" -- but only for the next character you'll type. So to write "The", you don't need to hold down Shift -- you tap it, tap t, and move on with life. And if you hold down the left Shift key, it just works as a left Shift key, as you would expect (so you could type THE). There's also a magical, secret way to "lock" a modifier by tapping it multiple times. If you want to learn more about that, open an issue. :)
+
+`MT(mod, kc)` - is *mod* (modifier key - MOD_LCTL, MOD_LSFT) when held, and *kc* when tapped. In other words, you can have a key that sends Esc (or the letter O or whatever) when you tap it, but works as a Control key or a Shift key when you hold it down.
+
+These are the values you can use for the `mod` in `MT()` and `OSM()` (right-hand modifiers are not available for `MT()`):
+
+ * MOD_LCTL
+ * MOD_LSFT
+ * MOD_LALT
+ * MOD_LGUI
+ * MOD_HYPR
+ * MOD_MEH
+
+These can also be combined like `MOD_LCTL | MOD_LSFT` e.g. `MT(MOD_LCTL | MOD_LSFT, KC_ESC)` which would activate Control and Shift when held, and send Escape when tapped.
+
+We've added shortcuts to make common modifier/tap (mod-tap) mappings more compact:
+
+ * `CTL_T(kc)` - is LCTL when held and *kc* when tapped
+ * `SFT_T(kc)` - is LSFT when held and *kc* when tapped
+ * `ALT_T(kc)` - is LALT when held and *kc* when tapped
+ * `GUI_T(kc)` - is LGUI when held and *kc* when tapped
+ * `ALL_T(kc)` - is Hyper (all mods) when held and *kc* when tapped. To read more about what you can do with a Hyper key, see [this blog post by Brett Terpstra](http://brettterpstra.com/2012/12/08/a-useful-caps-lock-key/)
+ * `LCAG_T(kc)` - is CtrlAltGui when held and *kc* when tapped
+ * `MEH_T(kc)` - is like Hyper, but not as cool -- does not include the Cmd/Win key, so just sends Alt+Ctrl+Shift.
+
+### Space Cadet Shift: The future, built in
+
+Steve Losh [described](http://stevelosh.com/blog/2012/10/a-modern-space-cadet/) the Space Cadet Shift quite well. Essentially, you hit the left Shift on its own, and you get an opening parenthesis; hit the right Shift on its own, and you get the closing one. When hit with other keys, the Shift key keeps working as it always does. Yes, it's as cool as it sounds.
+
+To use it, use `KC_LSPO` (Left Shift, Parens Open) for your left Shift on your keymap, and `KC_RSPC` (Right Shift, Parens Close) for your right Shift.
+
+It's defaulted to work on US keyboards, but if your layout uses different keys for parenthesis, you can define those in your `config.h` like this:
+
+ #define LSPO_KEY KC_9
+ #define RSPC_KEY KC_0
+
+The only other thing you're going to want to do is create a `Makefile` in your keymap directory and set the following:
+
+```
+COMMAND_ENABLE = no # Commands for debug and configuration
+```
+
+This is just to keep the keyboard from going into command mode when you hold both Shift keys at the same time.
+
+### The Leader key: A new kind of modifier
+
+If you've ever used Vim, you know what a Leader key is. If not, you're about to discover a wonderful concept. :) Instead of hitting Alt+Shift+W for example (holding down three keys at the same time), what if you could hit a _sequence_ of keys instead? So you'd hit our special modifier (the Leader key), followed by W and then C (just a rapid succession of keys), and something would happen.
+
+That's what `KC_LEAD` does. Here's an example:
+
+1. Pick a key on your keyboard you want to use as the Leader key. Assign it the keycode `KC_LEAD`. This key would be dedicated just for this -- it's a single action key, can't be used for anything else.
+2. Include the line `#define LEADER_TIMEOUT 300` somewhere in your keymap.c file, probably near the top. The 300 there is 300ms -- that's how long you have for the sequence of keys following the leader. You can tweak this value for comfort, of course.
+3. Within your `matrix_scan_user` function, do something like this:
+
+```
+void matrix_scan_user(void) {
+ LEADER_DICTIONARY() {
+ leading = false;
+ leader_end();
+
+ SEQ_ONE_KEY(KC_F) {
+ register_code(KC_S);
+ unregister_code(KC_S);
+ }
+ SEQ_TWO_KEYS(KC_A, KC_S) {
+ register_code(KC_H);
+ unregister_code(KC_H);
+ }
+ SEQ_THREE_KEYS(KC_A, KC_S, KC_D) {
+ register_code(KC_LGUI);
+ register_code(KC_S);
+ unregister_code(KC_S);
+ unregister_code(KC_LGUI);
+ }
+ }
+}
+```
+
+As you can see, you have three function. you can use - `SEQ_ONE_KEY` for single-key sequences (Leader followed by just one key), and `SEQ_TWO_KEYS` and `SEQ_THREE_KEYS` for longer sequences. Each of these accepts one or more keycodes as arguments. This is an important point: You can use keycodes from **any layer on your keyboard**. That layer would need to be active for the leader macro to fire, obviously.
+
+### Temporarily setting the default layer
+
+`DF(layer)` - sets default layer to *layer*. The default layer is the one at the "bottom" of the layer stack - the ultimate fallback layer. This currently does not persist over power loss. When you plug the keyboard back in, layer 0 will always be the default. It is theoretically possible to work around that, but that's not what `DF` does.
+
+### Prevent stuck modifiers
+
+Consider the following scenario:
+
+1. Layer 0 has a key defined as Shift.
+2. The same key is defined on layer 1 as the letter A.
+3. User presses Shift.
+4. User switches to layer 1 for whatever reason.
+5. User releases Shift, or rather the letter A.
+6. User switches back to layer 0.
+
+Shift was actually never released and is still considered pressed.
+
+If such situation bothers you add this to your `config.h`:
+
+ #define PREVENT_STUCK_MODIFIERS
+
+This option uses 5 bytes of memory per every 8 keys on the keyboard
+rounded up (5 bits per key). For example on Planck (48 keys) it uses
+(48/8)\*5 = 30 bytes.
+
+### Remember: These are just aliases
+
+These functions work the same way that their `ACTION_*` functions do - they're just quick aliases. To dig into all of the tmk ACTION_* functions, please see the [TMK documentation](https://github.com/jackhumbert/qmk_firmware/blob/master/doc/keymap.md#2-action).
+
+Instead of using `FNx` when defining `ACTION_*` functions, you can use `F(x)` - the benefit here is being able to use more than 32 function actions (up to 4096), if you happen to need them.
+
+## Macro shortcuts: Send a whole string when pressing just one key
+
+Instead of using the `ACTION_MACRO` function, you can simply use `M(n)` to access macro *n* - *n* will get passed into the `action_get_macro` as the `id`, and you can use a switch statement to trigger it. This gets called on the keydown and keyup, so you'll need to use an if statement testing `record->event.pressed` (see keymap_default.c).
+
+```c
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) // this is the function signature -- just copy/paste it into your keymap file as it is.
+{
+ switch(id) {
+ case 0: // this would trigger when you hit a key mapped as M(0)
+ if (record->event.pressed) {
+ return MACRO( I(255), T(H), T(E), T(L), T(L), W(255), T(O), END ); // this sends the string 'hello' when the macro executes
+ }
+ break;
+ }
+ return MACRO_NONE;
+};
+```
+A macro can include the following commands:
+
+* I() change interval of stroke in milliseconds.
+* D() press key.
+* U() release key.
+* T() type key(press and release).
+* W() wait (milliseconds).
+* END end mark.
+
+So above you can see the stroke interval changed to 255ms between each keystroke, then a bunch of keys being typed, waits a while, then the macro ends.
+
+Note: Using macros to have your keyboard send passwords for you is possible, but a bad idea.
+
+### Advanced macro functions
+
+To get more control over the keys/actions your keyboard takes, the following functions are available to you in the `action_get_macro` function block:
+
+* `record->event.pressed`
+
+This is a boolean value that can be tested to see if the switch is being pressed or released. An example of this is
+
+```c
+if (record->event.pressed) {
+ // on keydown
+} else {
+ // on keyup
+}
+```
+
+* `register_code(<kc>);`
+
+This sends the `<kc>` keydown event to the computer. Some examples would be `KC_ESC`, `KC_C`, `KC_4`, and even modifiers such as `KC_LSFT` and `KC_LGUI`.
+
+* `unregister_code(<kc>);`
+
+Parallel to `register_code` function, this sends the `<kc>` keyup event to the computer. If you don't use this, the key will be held down until it's sent.
+
+* `layer_on(<n>);`
+
+This will turn on the layer `<n>` - the higher layer number will always take priority. Make sure you have `KC_TRNS` for the key you're pressing on the layer you're switching to, or you'll get stick there unless you have another plan.
+
+* `layer_off(<n>);`
+
+This will turn off the layer `<n>`.
+
+* `clear_keyboard();`
+
+This will clear all mods and keys currently pressed.
+
+* `clear_mods();`
+
+This will clear all mods currently pressed.
+
+* `clear_keyboard_but_mods();`
+
+This will clear all keys besides the mods currently pressed.
+
+* `update_tri_layer(layer_1, layer_2, layer_3);`
+
+If the user attempts to activate layer 1 AND layer 2 at the same time (for example, by hitting their respective layer keys), layer 3 will be activated. Layers 1 and 2 will _also_ be activated, for the purposes of fallbacks (so a given key will fall back from 3 to 2, to 1 -- and only then to 0).
+
+#### Naming your macros
+
+If you have a bunch of macros you want to refer to from your keymap, while keeping the keymap easily readable, you can just name them like so:
+
+```
+#define AUD_OFF M(6)
+#define AUD_ON M(7)
+#define MUS_OFF M(8)
+#define MUS_ON M(9)
+#define VC_IN M(10)
+#define VC_DE M(11)
+#define PLOVER M(12)
+#define EXT_PLV M(13)
+```
+
+As was done on the [Planck default keymap](/keyboards/planck/keymaps/default/keymap.c#L33-L40)
+
+#### Timer functionality
+
+It's possible to start timers and read values for time-specific events - here's an example:
+
+```c
+static uint16_t key_timer;
+key_timer = timer_read();
+if (timer_elapsed(key_timer) < 100) {
+ // do something if less than 100ms have passed
+} else {
+ // do something if 100ms or more have passed
+}
+```
+
+It's best to declare the `static uint16_t key_timer;` outside of the macro block (top of file, etc).
+
+#### Example: Single-key copy/paste (hold to copy, tap to paste)
+
+With QMK, it's easy to make one key do two things, as long as one of those things is being a modifier. :) So if you want a key to act as Ctrl when held and send the letter R when tapped, that's easy: `CTL_T(KC_R)`. But what do you do when you want that key to send Ctrl-V (paste) when tapped, and Ctrl-C (copy) when held?
+
+Here's what you do:
+
+
+```
+static uint16_t key_timer;
+
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ switch(id) {
+ case 0: {
+ if (record->event.pressed) {
+ key_timer = timer_read(); // if the key is being pressed, we start the timer.
+ }
+ else { // this means the key was just released, so we can figure out how long it was pressed for (tap or "held down").
+ if (timer_elapsed(key_timer) > 150) { // 150 being 150ms, the threshhold we pick for counting something as a tap.
+ return MACRO( D(LCTL), T(C), U(LCTL), END );
+ }
+ else {
+ return MACRO( D(LCTL), T(V), U(LCTL), END );
+ }
+ }
+ break;
+ }
+ }
+ return MACRO_NONE;
+};
+```
+
+And then, to assign this macro to a key on your keyboard layout, you just use `M(0)` on the key you want to press for copy/paste.
+
+## Additional keycode aliases for software-implemented layouts (Colemak, Dvorak, etc)
+
+Everything is assuming you're in Qwerty (in software) by default, but there is built-in support for using a Colemak or Dvorak layout by including this at the top of your keymap:
+
+ #include <keymap_colemak.h>
+
+If you use Dvorak, use `keymap_dvorak.h` instead of `keymap_colemak.h` for this line. After including this line, you will get access to:
+
+ * `CM_*` for all of the Colemak-equivalent characters
+ * `DV_*` for all of the Dvorak-equivalent characters
+
+These implementations assume you're using Colemak or Dvorak on your OS, not on your keyboard - this is referred to as a software-implemented layout. If your computer is in Qwerty and your keymap is in Colemak or Dvorak, this is referred to as a firmware-implemented layout, and you won't need these features.
+
+To give an example, if you're using software-implemented Colemak, and want to get an `F`, you would use `CM_F` - `KC_F` under these same circumstances would result in `T`.
+
+## Additional language support
+
+In `quantum/keymap_extras/`, you'll see various language files - these work the same way as the alternative layout ones do. Most are defined by their two letter country/language code followed by an underscore and a 4-letter abbreviation of its name. `FR_UGRV` which will result in a `ù` when using a software-implemented AZERTY layout. It's currently difficult to send such characters in just the firmware (but it's being worked on - see Unicode support).
+
+## Unicode support
+
+You can currently send 4 hex digits with your OS-specific modifier key (RALT for OSX with the "Unicode Hex Input" layout) - this is currently limited to supporting one OS at a time, and requires a recompile for switching. 8 digit hex codes are being worked on. The keycode function is `UC(n)`, where *n* is a 4 digit hexidecimal. Enable from the Makefile.
+
+## Other firmware shortcut keycodes
+
+* `RESET` - puts the MCU in DFU mode for flashing new firmware (with `make dfu`)
+* `DEBUG` - the firmware into debug mode - you'll need hid_listen to see things
+* `BL_ON` - turns the backlight on
+* `BL_OFF` - turns the backlight off
+* `BL_<n>` - sets the backlight to level *n*
+* `BL_INC` - increments the backlight level by one
+* `BL_DEC` - decrements the backlight level by one
+* `BL_TOGG` - toggles the backlight
+* `BL_STEP` - steps through the backlight levels
+
+Enable the backlight from the Makefile.
+
+# Custom Quantum functions
+
+All of these functions are available in the `*_kb()` or `*_user()` variety. `kb` ones should only be used in the `<keyboard>/<keyboard>.c` file, and `user` ones should only be used in the `keymap.c`. The keyboard ones call the user ones - it's necessary to keep these calls to allow the keymap functions to work correctly.
+
+## `void martix_init_*(void)`
+
+This function gets called when the matrix is initiated, and can contain start-up code for your keyboard/keymap.
+
+## `void matrix_scan_*(void)`
+
+This function gets called at every matrix scan, which is basically as often as the MCU can handle. Be careful what you put here, as it will get run a lot.
+
+## `bool process_record_*(uint16_t keycode, keyrecord_t *record)`
+
+This function gets called on every keypress/release, and is where you can define custom functionality. The return value is whether or not QMK should continue processing the keycode - returning `false` stops the execution.
+
+The `keycode` variable is whatever is defined in your keymap, eg `MO(1)`, `KC_L`, etc. and can be switch-cased to execute code whenever a particular code is pressed.
+
+The `record` variable contains infomation about the actual press:
+
+```
+keyrecord_t record {
+ keyevent_t event {
+ keypos_t key {
+ uint8_t col
+ uint8_t row
+ }
+ bool pressed
+ uint16_t time
+ }
+}
+```
+
+The conditional `if (record->event.pressed)` can tell if the key is being pressed or released, and you can execute code based on that.
+
+## `void led_set_*(uint8_t usb_led)`
+
+This gets called whenever there is a state change on your host LEDs (eg caps lock, scroll lock, etc). The LEDs are defined as:
+
+```
+#define USB_LED_NUM_LOCK 0
+#define USB_LED_CAPS_LOCK 1
+#define USB_LED_SCROLL_LOCK 2
+#define USB_LED_COMPOSE 3
+#define USB_LED_KANA 4
+```
+
+and can be tested against the `usb_led` with a conditional like `if (usb_led & (1<<USB_LED_CAPS_LOCK))` - if this is true, you can turn your LED one, otherwise turn it off.
+
+# Modding your keyboard
+
+## Audio output from a speaker
+
+Your keyboard can make sounds! If you've got a Planck, Preonic, or basically any keyboard that allows access to the C6 port, you can hook up a simple speaker and make it beep. You can use those beeps to indicate layer transitions, modifiers, special keys, or just to play some funky 8bit tunes.
+
+The audio code lives in [quantum/audio/audio.h](/quantum/audio/audio.h) and in the other files in the audio directory. It's enabled by default on the Planck [stock keymap](/keyboards/planck/keymaps/default/keymap.c). Here are the important bits:
+
+```
+#include "audio.h"
+```
+
+Then, lower down the file:
+
+```
+float tone_startup[][2] = {
+ ED_NOTE(_E7 ),
+ E__NOTE(_CS7),
+ E__NOTE(_E6 ),
+ E__NOTE(_A6 ),
+ M__NOTE(_CS7, 20)
+};
+```
+
+This is how you write a song. Each of these lines is a note, so we have a little ditty composed of five notes here.
+
+Then, we have this chunk:
+
+```
+float tone_qwerty[][2] = SONG(QWERTY_SOUND);
+float tone_dvorak[][2] = SONG(DVORAK_SOUND);
+float tone_colemak[][2] = SONG(COLEMAK_SOUND);
+float tone_plover[][2] = SONG(PLOVER_SOUND);
+float tone_plover_gb[][2] = SONG(PLOVER_GOODBYE_SOUND);
+
+float music_scale[][2] = SONG(MUSIC_SCALE_SOUND);
+float goodbye[][2] = SONG(GOODBYE_SOUND);
+```
+
+Wherein we bind predefined songs (from [audio/song_list.h](/audio/song_list.h)) into named variables. This is one optimization that helps save on memory: These songs only take up memory when you reference them in your keymap, because they're essentially all preprocessor directives.
+
+So now you have something called `tone_plover` for example. How do you make it play the Plover tune, then? If you look further down the keymap, you'll see this:
+
+```
+PLAY_NOTE_ARRAY(tone_plover, false, 0); // Signature is: Song name, repeat, rest style
+```
+
+This is inside one of the macros. So when that macro executes, your keyboard plays that particular chime.
+
+"Rest style" in the method signature above (the last parameter) specifies if there's a rest (a moment of silence) between the notes.
+
+## MIDI functionalty
+
+This is still a WIP, but check out `quantum/keymap_midi.c` to see what's happening. Enable from the Makefile.
+
+## Bluetooth functionality
+
+This requires [some hardware changes](https://www.reddit.com/r/MechanicalKeyboards/comments/3psx0q/the_planck_keyboard_with_bluetooth_guide_and/?ref=search_posts), but can be enabled via the Makefile. The firmware will still output characters via USB, so be aware of this when charging via a computer. It would make sense to have a switch on the Bluefruit to turn it off at will.
+
+## International Characters on Windows
+
+[AutoHotkey](https://autohotkey.com) allows Windows users to create custom hotkeys among others.
+
+The method does not require Unicode support in the keyboard itself but depends instead of AutoHotkey running in the background.
+
+First you need to select a modifier combination that is not in use by any of your programs.
+CtrlAltWin is not used very widely and should therefore be perfect for this.
+There is a macro defined for a mod-tab combo `LCAG_T`.
+Add this mod-tab combo to a key on your keyboard, e.g.: `LCAG_T(KC_TAB)`.
+This makes the key behave like a tab key if pressed and released immediately but changes it to the modifier if used with another key.
+
+In the default script of AutoHotkey you can define custom hotkeys.
+
+ <^<!<#a::Send, ä
+ <^<!<#<+a::Send, Ä
+
+The hotkeys above are for the combination CtrlAltGui and CtrlAltGuiShift plus the letter a.
+AutoHotkey inserts the Text right of `Send, ` when this combination is pressed.
+
+## RGB Under Glow Mod
+
+![Planck with RGB Underglow](https://raw.githubusercontent.com/yangliu/qmk_firmware/planck-rgb/keyboards/planck/keymaps/yang/planck-with-rgb-underglow.jpg)
+
+Here is a quick demo on Youtube (with NPKC KC60) (https://www.youtube.com/watch?v=VKrpPAHlisY).
+
+For this mod, you need an unused pin wiring to DI of WS2812 strip. After wiring the VCC, GND, and DI, you can enable the underglow in your Makefile.
+
+ RGBLIGHT_ENABLE = yes
+
+Please note that the underglow is not compatible with audio output. So you cannot enable both of them at the same time.
+
+Please add the following options into your config.h, and set them up according your hardware configuration. These settings are for the F4 by default:
+
+ #define ws2812_PORTREG PORTF
+ #define ws2812_DDRREG DDRF
+ #define ws2812_pin PF4
+ #define RGBLED_NUM 14 // Number of LEDs
+ #define RGBLIGHT_HUE_STEP 10
+ #define RGBLIGHT_SAT_STEP 17
+ #define RGBLIGHT_VAL_STEP 17
+
+You'll need to edit `PORTF`, `DDRF`, and `PF4` on the first three lines to the port/pin you have your LED(s) wired to, eg for B3 change things to:
+
+ #define ws2812_PORTREG PORTB
+ #define ws2812_DDRREG DDRB
+ #define ws2812_pin PB3
+
+The firmware supports 5 different light effects, and the color (hue, saturation, brightness) can be customized in most effects. To control the underglow, you need to modify your keymap file to assign those functions to some keys/key combinations. For details, please check this keymap. `keyboards/planck/keymaps/yang/keymap.c`
+
+### WS2812 Wiring
+
+![WS2812 Wiring](https://raw.githubusercontent.com/yangliu/qmk_firmware/planck-rgb/keyboards/planck/keymaps/yang/WS2812-wiring.jpg)
+
+Please note the USB port can only supply a limited amount of power to the keyboard (500mA by standard, however, modern computer and most usb hubs can provide 700+mA.). According to the data of NeoPixel from Adafruit, 30 WS2812 LEDs require a 5V 1A power supply, LEDs used in this mod should not more than 20.
+
+## Safety Considerations
+
+You probably don't want to "brick" your keyboard, making it impossible
+to rewrite firmware onto it. Here are some of the parameters to show
+what things are (and likely aren't) too risky.
+
+- If a keyboard map does not include RESET, then, to get into DFU
+ mode, you will need to press the reset button on the PCB, which
+ requires unscrewing some bits.
+- Messing with tmk_core / common files might make the keyboard
+ inoperable
+- Too large a .hex file is trouble; `make dfu` will erase the block,
+ test the size (oops, wrong order!), which errors out, failing to
+ flash the keyboard
+- DFU tools do /not/ allow you to write into the bootloader (unless
+ you throw in extra fruitsalad of options), so there is little risk
+ there.
+- EEPROM has around a 100000 write cycle. You shouldn't rewrite the
+ firmware repeatedly and continually; that'll burn the EEPROM
+ eventually.
+
+# Porting your keyboard to QMK
+
+If your keyboard is running an Atmega chip (atmega32u4 and others), it's pretty easy to get things setup for compiling your own firmware to flash onto your board. There is a `/util/new_project.sh <keyboard>` script to help get you started - you can simply pass your keyboard's name into the script, and all of the necessary files will be created. The components of each are described below.
+
+## `/keyboards/<keyboard>/config.h`
+
+The `USB Device descriptor parameter` block contains parameters are used to uniquely identify your keyboard, but they don't really matter to the machine.
+
+Your `MATRIX_ROWS` and `MATRIX_COLS` are the numbers of rows and cols in your keyboard matrix - this may be different than the number of actual rows and columns on your keyboard. There are some tricks you can pull to increase the number of keys in a given matrix, but most keyboards are pretty straight-forward.
+
+The `MATRIX_ROW_PINS` and `MATRIX_COL_PINS` are the pins your MCU uses on each row/column. Your schematic (if you have one) will have this information on it, and the values will vary depending on your setup. This is one of the most important things to double-check in getting your keyboard setup correctly.
+
+For the `DIODE_DIRECTION`, most hand-wiring guides will instruct you to wire the diodes in the `COL2ROW` position, but it's possible that they are in the other - people coming from EasyAVR often use `ROW2COL`. Nothing will function if this is incorrect.
+
+`BACKLIGHT_PIN` is the pin that your PWM-controlled backlight (if one exists) is hooked-up to. Currently only B5, B6, and B7 are supported.
+
+`BACKLIGHT_BREATHING` is a fancier backlight feature, and uses one of the timers.
+
+`BACKLIGHT_LEVELS` is how many levels exist for your backlight - max is 15, and they are computed automatically from this number.
+
+## `/keyboards/<keyboard>/Makefile`
+
+The values at the top likely won't need to be changed, since most boards use the `atmega32u4` chip. The `BOOTLOADER_SIZE` will need to be adjusted based on your MCU type. It's defaulted to the Teensy, since that's the most common controller. Below is quoted from the `Makefile`.
+
+```
+# Boot Section Size in *bytes*
+# Teensy halfKay 512
+# Teensy++ halfKay 1024
+# Atmel DFU loader 4096
+# LUFA bootloader 4096
+# USBaspLoader 2048
+OPT_DEFS += -DBOOTLOADER_SIZE=512
+```
+
+At the bottom of the file, you'll find lots of features to turn on and off - all of these options should be set with `?=` to allow for the keymap overrides. `?=` only assigns if the variable was previously undefined. For the full documenation of these features, see the [Makefile options](#makefile-options).
+
+## `/keyboards/<keyboard>/readme.md`
+
+This is where you'll describe your keyboard - please write as much as you can about it! Talking about default functionality/features is useful here. Feel free to link to external pages/sites if necessary. Images can be included here as well. This file will be rendered into a webpage at qmk.fm/keyboards/<keyboard>/.
+
+## `/keyboards/<keyboard>/<keyboard>.c`
+
+This is where all of the custom logic for your keyboard goes - you may not need to put anything in this file, since a lot of things are configured automatically. All of the `*_kb()` functions are defined here. If you modify them, remember to keep the calls to `*_user()`, or things in the keymaps might not work. You can read more about the functions [here](#custom-quantum-functions-for-keyboards-and-keymaps)
+
+## `/keyboards/<keyboard>/<keyboard>.h`
+
+Here is where you can (optionally) define your `KEYMAP` function to remap your matrix into a more readable format. With ortholinear boards, this isn't always necessary, but it can help to accomodate the dead spots on your matrix, where there are keys that take up more than one space (2u, staggering, 6.25u, etc). The example shows the difference between the physical keys, and the matrix design:
+
+```
+#define KEYMAP( \
+ k00, k01, k02, \
+ k10, k11 \
+) \
+{ \
+ { k00, k01, k02 }, \
+ { k10, KC_NO, k11 }, \
+}
+```
+
+Each of the `kxx` variables needs to be unique, and usually follows the format `k<row><col>`. You can place `KC_NO` where your dead keys are in your matrix.
diff --git a/tmk_core/.gitignore b/tmk_core/.gitignore
new file mode 100644
index 000000000..f3f46872a
--- /dev/null
+++ b/tmk_core/.gitignore
@@ -0,0 +1,13 @@
+.dep
+*.o
+*.eep
+*.elf
+*.hex
+*.lss
+*.lst
+*.map
+*.sym
+tags
+*~
+build/
+*.bak
diff --git a/tmk_core/.gitmodules b/tmk_core/.gitmodules
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tmk_core/.gitmodules
diff --git a/tmk_core/avr.mk b/tmk_core/avr.mk
new file mode 100644
index 000000000..3bf2b34f8
--- /dev/null
+++ b/tmk_core/avr.mk
@@ -0,0 +1,186 @@
+# Hey Emacs, this is a -*- makefile -*-
+##############################################################################
+# Compiler settings
+#
+CC = avr-gcc
+OBJCOPY = avr-objcopy
+OBJDUMP = avr-objdump
+SIZE = avr-size
+AR = avr-ar rcs
+NM = avr-nm
+HEX = $(OBJCOPY) -O $(FORMAT) -R .eeprom -R .fuse -R .lock -R .signature
+EEP = $(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O $(FORMAT)
+BIN =
+
+
+
+COMPILEFLAGS += -funsigned-char
+COMPILEFLAGS += -funsigned-bitfields
+COMPILEFLAGS += -ffunction-sections
+COMPILEFLAGS += -fdata-sections
+COMPILEFLAGS += -fpack-struct
+COMPILEFLAGS += -fshort-enums
+
+CFLAGS += $(COMPILEFLAGS)
+CFLAGS += -fno-inline-small-functions
+CFLAGS += -fno-strict-aliasing
+
+CPPFLAGS += $(COMPILEFLAGS)
+CPPFLAGS += -fno-exceptions
+
+LDFLAGS +=-Wl,--gc-sections
+
+OPT_DEFS += -DF_CPU=$(F_CPU)UL
+
+MCUFLAGS = -mmcu=$(MCU)
+
+# List any extra directories to look for libraries here.
+# Each directory must be seperated by a space.
+# Use forward slashes for directory separators.
+# For a directory that has spaces, enclose it in quotes.
+EXTRALIBDIRS =
+
+
+#---------------- External Memory Options ----------------
+
+# 64 KB of external RAM, starting after internal RAM (ATmega128!),
+# used for variables (.data/.bss) and heap (malloc()).
+#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
+
+# 64 KB of external RAM, starting after internal RAM (ATmega128!),
+# only used for heap (malloc()).
+#EXTMEMOPTS = -Wl,--section-start,.data=0x801100,--defsym=__heap_end=0x80ffff
+
+EXTMEMOPTS =
+
+#---------------- Debugging Options ----------------
+
+# Debugging format.
+# Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs.
+# AVR Studio 4.10 requires dwarf-2.
+# AVR [Extended] COFF format requires stabs, plus an avr-objcopy run.
+DEBUG = dwarf-2
+
+# For simulavr only - target MCU frequency.
+DEBUG_MFREQ = $(F_CPU)
+
+# Set the DEBUG_UI to either gdb or insight.
+# DEBUG_UI = gdb
+DEBUG_UI = insight
+
+# Set the debugging back-end to either avarice, simulavr.
+DEBUG_BACKEND = avarice
+#DEBUG_BACKEND = simulavr
+
+# GDB Init Filename.
+GDBINIT_FILE = __avr_gdbinit
+
+# When using avarice settings for the JTAG
+JTAG_DEV = /dev/com1
+
+# Debugging port used to communicate between GDB / avarice / simulavr.
+DEBUG_PORT = 4242
+
+# Debugging host used to communicate between GDB / avarice / simulavr, normally
+# just set to localhost unless doing some sort of crazy debugging when
+# avarice is running on a different computer.
+DEBUG_HOST = localhost
+
+#============================================================================
+# Autodecct teensy loader
+ifneq (, $(shell which teensy-loader-cli 2>/dev/null))
+ TEENSY_LOADER_CLI = teensy-loader-cli
+else
+ TEENSY_LOADER_CLI = teensy_loader_cli
+endif
+
+# Program the device.
+program: $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).eep
+ $(PROGRAM_CMD)
+
+teensy: $(BUILD_DIR)/$(TARGET).hex
+ $(TEENSY_LOADER_CLI) -mmcu=$(MCU) -w -v $(BUILD_DIR)/$(TARGET).hex
+
+flip: $(BUILD_DIR)/$(TARGET).hex
+ batchisp -hardware usb -device $(MCU) -operation erase f
+ batchisp -hardware usb -device $(MCU) -operation loadbuffer $(BUILD_DIR)/$(TARGET).hex program
+ batchisp -hardware usb -device $(MCU) -operation start reset 0
+
+dfu: $(BUILD_DIR)/$(TARGET).hex sizeafter
+ifneq (, $(findstring 0.7, $(shell dfu-programmer --version 2>&1)))
+ dfu-programmer $(MCU) erase --force
+else
+ dfu-programmer $(MCU) erase
+endif
+ dfu-programmer $(MCU) flash $(BUILD_DIR)/$(TARGET).hex
+ dfu-programmer $(MCU) reset
+
+dfu-start:
+ dfu-programmer $(MCU) reset
+ dfu-programmer $(MCU) start
+
+flip-ee: $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).eep
+ $(COPY) $(BUILD_DIR)/$(TARGET).eep $(BUILD_DIR)/$(TARGET)eep.hex
+ batchisp -hardware usb -device $(MCU) -operation memory EEPROM erase
+ batchisp -hardware usb -device $(MCU) -operation memory EEPROM loadbuffer $(BUILD_DIR)/$(TARGET)eep.hex program
+ batchisp -hardware usb -device $(MCU) -operation start reset 0
+ $(REMOVE) $(BUILD_DIR)/$(TARGET)eep.hex
+
+dfu-ee: $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).eep
+ifneq (, $(findstring 0.7, $(shell dfu-programmer --version 2>&1)))
+ dfu-programmer $(MCU) flash --eeprom $(BUILD_DIR)/$(TARGET).eep
+else
+ dfu-programmer $(MCU) flash-eeprom $(BUILD_DIR)/$(TARGET).eep
+endif
+ dfu-programmer $(MCU) reset
+
+
+# Generate avr-gdb config/init file which does the following:
+# define the reset signal, load the target file, connect to target, and set
+# a breakpoint at main().
+gdb-config:
+ @$(REMOVE) $(GDBINIT_FILE)
+ @echo define reset >> $(GDBINIT_FILE)
+ @echo SIGNAL SIGHUP >> $(GDBINIT_FILE)
+ @echo end >> $(GDBINIT_FILE)
+ @echo file $(BUILD_DIR)/$(TARGET).elf >> $(GDBINIT_FILE)
+ @echo target remote $(DEBUG_HOST):$(DEBUG_PORT) >> $(GDBINIT_FILE)
+ifeq ($(DEBUG_BACKEND),simulavr)
+ @echo load >> $(GDBINIT_FILE)
+endif
+ @echo break main >> $(GDBINIT_FILE)
+
+debug: gdb-config $(BUILD_DIR)/$(TARGET).elf
+ifeq ($(DEBUG_BACKEND), avarice)
+ @echo Starting AVaRICE - Press enter when "waiting to connect" message displays.
+ @$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \
+ $(BUILD_DIR)/$(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT)
+ @$(WINSHELL) /c pause
+
+else
+ @$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \
+ $(DEBUG_MFREQ) --port $(DEBUG_PORT)
+endif
+ @$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE)
+
+
+
+
+# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
+COFFCONVERT = $(OBJCOPY) --debugging
+COFFCONVERT += --change-section-address .data-0x800000
+COFFCONVERT += --change-section-address .bss-0x800000
+COFFCONVERT += --change-section-address .noinit-0x800000
+COFFCONVERT += --change-section-address .eeprom-0x810000
+
+
+
+coff: $(BUILD_DIR)/$(TARGET).elf
+ @$(SECHO) $(MSG_COFF) $(BUILD_DIR)/$(TARGET).cof
+ $(COFFCONVERT) -O coff-avr $< $(BUILD_DIR)/$(TARGET).cof
+
+
+extcoff: $(BUILD_DIR)/$(TARGET).elf
+ @$(SECHO) $(MSG_EXTENDED_COFF) $(BUILD_DIR)/$(TARGET).cof
+ $(COFFCONVERT) -O coff-ext-avr $< $(BUILD_DIR)/$(TARGET).cof
+
diff --git a/tmk_core/chibios.mk b/tmk_core/chibios.mk
new file mode 100644
index 000000000..cb67ac6f2
--- /dev/null
+++ b/tmk_core/chibios.mk
@@ -0,0 +1,158 @@
+# Hey Emacs, this is a -*- makefile -*-
+##############################################################################
+# Architecture or project specific options
+#
+
+# Stack size to be allocated to the Cortex-M process stack. This stack is
+# the stack used by the main() thread.
+ifeq ($(USE_PROCESS_STACKSIZE),)
+ USE_PROCESS_STACKSIZE = 0x200
+endif
+
+# Stack size to the allocated to the Cortex-M main/exceptions stack. This
+# stack is used for processing interrupts and exceptions.
+ifeq ($(USE_EXCEPTIONS_STACKSIZE),)
+ USE_EXCEPTIONS_STACKSIZE = 0x400
+endif
+
+#
+# Architecture or project specific options
+##############################################################################
+
+##############################################################################
+# Project, sources and paths
+#
+
+# Imported source files and paths
+CHIBIOS = $(TOP_DIR)/lib/chibios
+CHIBIOS_CONTRIB = $(TOP_DIR)/lib/chibios-contrib
+# Startup files. Try a few different locations, for compability with old versions and
+# for things hardware in the contrib repository
+STARTUP_MK = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/startup_$(MCU_STARTUP).mk
+ifeq ("$(wildcard $(STARTUP_MK))","")
+ STARTUP_MK = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_$(MCU_STARTUP).mk
+ ifeq ("$(wildcard $(STARTUP_MK))","")
+ STARTUP_MK = $(CHIBIOS_CONTRIB)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_$(MCU_STARTUP).mk
+ endif
+endif
+include $(STARTUP_MK)
+# HAL-OSAL files (optional).
+include $(CHIBIOS)/os/hal/hal.mk
+
+PLATFORM_MK = $(CHIBIOS)/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)/platform.mk
+ifeq ("$(wildcard $(PLATFORM_MK))","")
+PLATFORM_MK = $(CHIBIOS_CONTRIB)/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)/platform.mk
+endif
+include $(PLATFORM_MK)
+
+
+BOARD_MK = $(KEYBOARD_PATH)/boards/$(BOARD)/board.mk
+ifeq ("$(wildcard $(BOARD_MK))","")
+ BOARD_MK = $(CHIBIOS)/os/hal/boards/$(BOARD)/board.mk
+ ifeq ("$(wildcard $(BOARD_MK))","")
+ BOARD_MK = $(CHIBIOS_CONTRIB)/os/hal/boards/$(BOARD)/board.mk
+ endif
+endif
+include $(BOARD_MK)
+include $(CHIBIOS)/os/hal/osal/rt/osal.mk
+# RTOS files (optional).
+include $(CHIBIOS)/os/rt/rt.mk
+# Compability with old version
+PORT_V = $(CHIBIOS)/os/rt/ports/ARMCMx/compilers/GCC/mk/port_v$(ARMV)m.mk
+ifeq ("$(wildcard $(PORT_V))","")
+PORT_V = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/port_v$(ARMV)m.mk
+endif
+include $(PORT_V)
+# Other files (optional).
+include $(CHIBIOS)/os/hal/lib/streams/streams.mk
+
+RULESPATH = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC
+ifeq ("$(wildcard $(RULESPATH)/rules.mk)","")
+RULESPATH = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC
+endif
+
+# Define linker script file here
+ifneq ("$(wildcard $(KEYBOARD_PATH)/ld/$(MCU_LDSCRIPT).ld)","")
+LDSCRIPT = $(KEYBOARD_PATH)/ld/$(MCU_LDSCRIPT).ld
+else
+LDSCRIPT = $(STARTUPLD)/$(MCU_LDSCRIPT).ld
+endif
+
+CHIBISRC = $(STARTUPSRC) \
+ $(KERNSRC) \
+ $(PORTSRC) \
+ $(OSALSRC) \
+ $(HALSRC) \
+ $(PLATFORMSRC) \
+ $(BOARDSRC) \
+ $(STREAMSSRC) \
+ $(STARTUPASM) \
+ $(PORTASM) \
+ $(OSALASM)
+
+SRC += $(patsubst $(TOP_DIR)/%,%,$(CHIBISRC))
+
+EXTRAINCDIRS += $(CHIBIOS)/os/license \
+ $(STARTUPINC) $(KERNINC) $(PORTINC) $(OSALINC) \
+ $(HALINC) $(PLATFORMINC) $(BOARDINC) $(TESTINC) \
+ $(STREAMSINC) $(CHIBIOS)/os/various
+
+#
+# Project, sources and paths
+##############################################################################
+
+
+##############################################################################
+# Compiler settings
+#
+CC = arm-none-eabi-gcc
+OBJCOPY = arm-none-eabi-objcopy
+OBJDUMP = arm-none-eabi-objdump
+SIZE = arm-none-eabi-size
+AR = arm-none-eabi-ar
+NM = arm-none-eabi-nm
+HEX = $(OBJCOPY) -O $(FORMAT)
+EEP =
+BIN = $(OBJCOPY) -O binary
+
+THUMBFLAGS = -DTHUMB_PRESENT -mno-thumb-interwork -DTHUMB_NO_INTERWORKING -mthumb -DTHUMB
+
+COMPILEFLAGS += -fomit-frame-pointer
+COMPILEFLAGS += -falign-functions=16
+COMPILEFLAGS += -ffunction-sections
+COMPILEFLAGS += -fdata-sections
+COMPILEFLAGS += -fno-common
+COMPILEFLAGS += $(THUMBFLAGS)
+
+CFLAGS += $(COMPILEFLAGS)
+
+ASFLAGS += $(THUMBFLAGS)
+
+CPPFLAGS += $(COMPILEFLAGS)
+CPPFLAGS += -fno-rtti
+
+LDFLAGS +=-Wl,--gc-sections
+LDFLAGS += -mno-thumb-interwork -mthumb
+LDSYMBOLS =,--defsym=__process_stack_size__=$(USE_PROCESS_STACKSIZE)
+LDSYMBOLS :=$(LDSYMBOLS),--defsym=__main_stack_size__=$(USE_EXCEPTIONS_STACKSIZE)
+LDFLAGS += -Wl,--script=$(LDSCRIPT)$(LDSYMBOLS)
+
+OPT_DEFS += -DPROTOCOL_CHIBIOS
+
+MCUFLAGS = -mcpu=$(MCU)
+
+DEBUG = gdb
+
+# Define ASM defines here
+# bootloader definitions may be used in the startup .s file
+ifneq ("$(wildcard $(KEYBOARD_PATH)/bootloader_defs.h)","")
+ OPT_DEFS += -include $(KEYBOARD_PATH)/bootloader_defs.h
+else ifneq ("$(wildcard $(KEYBOARD_PATH)/boards/$(BOARD)/bootloader_defs.h)","")
+ OPT_DEFS += -include $(KEYBOARD_PATH)/boards/$(BOARD)/bootloader_defs.h
+endif
+
+# List any extra directories to look for libraries here.
+EXTRALIBDIRS = $(RULESPATH)/ld
+
+dfu-util: $(BUILD_DIR)/$(TARGET).bin sizeafter
+ dfu-util -D $(BUILD_DIR)/$(TARGET).bin \ No newline at end of file
diff --git a/tmk_core/common.mk b/tmk_core/common.mk
new file mode 100644
index 000000000..d71fba9bc
--- /dev/null
+++ b/tmk_core/common.mk
@@ -0,0 +1,112 @@
+COMMON_DIR = common
+ifeq ($(PLATFORM),AVR)
+ PLATFORM_COMMON_DIR = $(COMMON_DIR)/avr
+else ifeq ($(PLATFORM),CHIBIOS)
+ PLATFORM_COMMON_DIR = $(COMMON_DIR)/chibios
+endif
+
+SRC += $(COMMON_DIR)/host.c \
+ $(COMMON_DIR)/keyboard.c \
+ $(COMMON_DIR)/action.c \
+ $(COMMON_DIR)/action_tapping.c \
+ $(COMMON_DIR)/action_macro.c \
+ $(COMMON_DIR)/action_layer.c \
+ $(COMMON_DIR)/action_util.c \
+ $(COMMON_DIR)/print.c \
+ $(COMMON_DIR)/debug.c \
+ $(COMMON_DIR)/util.c \
+ $(COMMON_DIR)/eeconfig.c \
+ $(PLATFORM_COMMON_DIR)/suspend.c \
+ $(PLATFORM_COMMON_DIR)/timer.c \
+ $(PLATFORM_COMMON_DIR)/bootloader.c \
+
+ifeq ($(PLATFORM),AVR)
+ SRC += $(PLATFORM_COMMON_DIR)/xprintf.S
+endif
+
+ifeq ($(PLATFORM),CHIBIOS)
+ SRC += $(PLATFORM_COMMON_DIR)/printf.c
+ SRC += $(PLATFORM_COMMON_DIR)/eeprom.c
+endif
+
+
+
+# Option modules
+ifeq ($(strip $(BOOTMAGIC_ENABLE)), yes)
+ OPT_DEFS += -DBOOTMAGIC_ENABLE
+ SRC += $(COMMON_DIR)/bootmagic.c
+else
+ OPT_DEFS += -DMAGIC_ENABLE
+ SRC += $(COMMON_DIR)/magic.c
+endif
+
+ifeq ($(strip $(MOUSEKEY_ENABLE)), yes)
+ SRC += $(COMMON_DIR)/mousekey.c
+ OPT_DEFS += -DMOUSEKEY_ENABLE
+ OPT_DEFS += -DMOUSE_ENABLE
+endif
+
+ifeq ($(strip $(EXTRAKEY_ENABLE)), yes)
+ OPT_DEFS += -DEXTRAKEY_ENABLE
+endif
+
+ifeq ($(strip $(CONSOLE_ENABLE)), yes)
+ OPT_DEFS += -DCONSOLE_ENABLE
+else
+ OPT_DEFS += -DNO_PRINT
+ OPT_DEFS += -DNO_DEBUG
+endif
+
+ifeq ($(strip $(COMMAND_ENABLE)), yes)
+ SRC += $(COMMON_DIR)/command.c
+ OPT_DEFS += -DCOMMAND_ENABLE
+endif
+
+ifeq ($(strip $(NKRO_ENABLE)), yes)
+ OPT_DEFS += -DNKRO_ENABLE
+endif
+
+ifeq ($(strip $(USB_6KRO_ENABLE)), yes)
+ OPT_DEFS += -DUSB_6KRO_ENABLE
+endif
+
+ifeq ($(strip $(SLEEP_LED_ENABLE)), yes)
+ SRC += $(PLATFORM_COMMON_DIR)/sleep_led.c
+ OPT_DEFS += -DSLEEP_LED_ENABLE
+ OPT_DEFS += -DNO_SUSPEND_POWER_DOWN
+endif
+
+ifeq ($(strip $(BACKLIGHT_ENABLE)), yes)
+ SRC += $(COMMON_DIR)/backlight.c
+ OPT_DEFS += -DBACKLIGHT_ENABLE
+endif
+
+ifeq ($(strip $(BLUETOOTH_ENABLE)), yes)
+ OPT_DEFS += -DBLUETOOTH_ENABLE
+endif
+
+ifeq ($(strip $(KEYMAP_SECTION_ENABLE)), yes)
+ OPT_DEFS += -DKEYMAP_SECTION_ENABLE
+
+ ifeq ($(strip $(MCU)),atmega32u2)
+ EXTRALDFLAGS = -Wl,-L$(TMK_DIR),-Tldscript_keymap_avr35.x
+ else ifeq ($(strip $(MCU)),atmega32u4)
+ EXTRALDFLAGS = -Wl,-L$(TMK_DIR),-Tldscript_keymap_avr5.x
+ else
+ EXTRALDFLAGS = $(error no ldscript for keymap section)
+ endif
+endif
+
+# Version string
+OPT_DEFS += -DVERSION=$(shell (git describe --always --dirty || echo 'unknown') 2> /dev/null)
+
+# Bootloader address
+ifdef STM32_BOOTLOADER_ADDRESS
+ OPT_DEFS += -DSTM32_BOOTLOADER_ADDRESS=$(STM32_BOOTLOADER_ADDRESS)
+endif
+
+# Search Path
+VPATH += $(TMK_PATH)/$(COMMON_DIR)
+ifeq ($(PLATFORM),CHIBIOS)
+VPATH += $(TMK_PATH)/$(COMMON_DIR)/chibios
+endif \ No newline at end of file
diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c
new file mode 100644
index 000000000..be6dea2b7
--- /dev/null
+++ b/tmk_core/common/action.c
@@ -0,0 +1,698 @@
+/*
+Copyright 2012,2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "host.h"
+#include "keycode.h"
+#include "keyboard.h"
+#include "mousekey.h"
+#include "command.h"
+#include "led.h"
+#include "backlight.h"
+#include "action_layer.h"
+#include "action_tapping.h"
+#include "action_macro.h"
+#include "action_util.h"
+#include "action.h"
+
+#ifdef DEBUG_ACTION
+#include "debug.h"
+#else
+#include "nodebug.h"
+#endif
+
+
+void action_exec(keyevent_t event)
+{
+ if (!IS_NOEVENT(event)) {
+ dprint("\n---- action_exec: start -----\n");
+ dprint("EVENT: "); debug_event(event); dprintln();
+ }
+
+ keyrecord_t record = { .event = event };
+
+#ifndef NO_ACTION_TAPPING
+ action_tapping_process(record);
+#else
+ process_record(&record);
+ if (!IS_NOEVENT(record.event)) {
+ dprint("processed: "); debug_record(record); dprintln();
+ }
+#endif
+}
+
+#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
+bool disable_action_cache = false;
+
+void process_record_nocache(keyrecord_t *record)
+{
+ disable_action_cache = true;
+ process_record(record);
+ disable_action_cache = false;
+}
+#else
+void process_record_nocache(keyrecord_t *record)
+{
+ process_record(record);
+}
+#endif
+
+__attribute__ ((weak))
+bool process_record_quantum(keyrecord_t *record) {
+ return true;
+}
+
+void process_record(keyrecord_t *record)
+{
+ if (IS_NOEVENT(record->event)) { return; }
+
+ if(!process_record_quantum(record))
+ return;
+
+ action_t action = store_or_get_action(record->event.pressed, record->event.key);
+ dprint("ACTION: "); debug_action(action);
+#ifndef NO_ACTION_LAYER
+ dprint(" layer_state: "); layer_debug();
+ dprint(" default_layer_state: "); default_layer_debug();
+#endif
+ dprintln();
+
+ process_action(record, action);
+}
+
+void process_action(keyrecord_t *record, action_t action)
+{
+ bool do_release_oneshot = false;
+ keyevent_t event = record->event;
+#ifndef NO_ACTION_TAPPING
+ uint8_t tap_count = record->tap.count;
+#endif
+
+#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
+ if (has_oneshot_layer_timed_out()) {
+ dprintf("Oneshot layer: timeout\n");
+ clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
+ }
+#endif
+
+ if (event.pressed) {
+ // clear the potential weak mods left by previously pressed keys
+ clear_weak_mods();
+ }
+
+#ifndef NO_ACTION_ONESHOT
+ // notice we only clear the one shot layer if the pressed key is not a modifier.
+ if (is_oneshot_layer_active() && event.pressed && !IS_MOD(action.key.code)) {
+ clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
+ do_release_oneshot = !is_oneshot_layer_active();
+ }
+#endif
+
+ switch (action.kind.id) {
+ /* Key and Mods */
+ case ACT_LMODS:
+ case ACT_RMODS:
+ {
+ uint8_t mods = (action.kind.id == ACT_LMODS) ? action.key.mods :
+ action.key.mods<<4;
+ if (event.pressed) {
+ if (mods) {
+ if (IS_MOD(action.key.code)) {
+ // e.g. LSFT(KC_LGUI): we don't want the LSFT to be weak as it would make it useless.
+ // this also makes LSFT(KC_LGUI) behave exactly the same as LGUI(KC_LSFT)
+ add_mods(mods);
+ } else {
+ add_weak_mods(mods);
+ }
+ send_keyboard_report();
+ }
+ register_code(action.key.code);
+ } else {
+ unregister_code(action.key.code);
+ if (mods) {
+ if (IS_MOD(action.key.code)) {
+ del_mods(mods);
+ } else {
+ del_weak_mods(mods);
+ }
+ send_keyboard_report();
+ }
+ }
+ }
+ break;
+#ifndef NO_ACTION_TAPPING
+ case ACT_LMODS_TAP:
+ case ACT_RMODS_TAP:
+ {
+ uint8_t mods = (action.kind.id == ACT_LMODS_TAP) ? action.key.mods :
+ action.key.mods<<4;
+ switch (action.layer_tap.code) {
+ #ifndef NO_ACTION_ONESHOT
+ case MODS_ONESHOT:
+ // Oneshot modifier
+ if (event.pressed) {
+ if (tap_count == 0) {
+ dprint("MODS_TAP: Oneshot: 0\n");
+ register_mods(mods);
+ } else if (tap_count == 1) {
+ dprint("MODS_TAP: Oneshot: start\n");
+ set_oneshot_mods(mods);
+ #if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
+ } else if (tap_count == ONESHOT_TAP_TOGGLE) {
+ dprint("MODS_TAP: Toggling oneshot");
+ clear_oneshot_mods();
+ set_oneshot_locked_mods(mods);
+ register_mods(mods);
+ #endif
+ } else {
+ register_mods(mods);
+ }
+ } else {
+ if (tap_count == 0) {
+ clear_oneshot_mods();
+ unregister_mods(mods);
+ } else if (tap_count == 1) {
+ // Retain Oneshot mods
+ #if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
+ if (mods & get_mods()) {
+ clear_oneshot_locked_mods();
+ clear_oneshot_mods();
+ unregister_mods(mods);
+ }
+ } else if (tap_count == ONESHOT_TAP_TOGGLE) {
+ // Toggle Oneshot Layer
+ #endif
+ } else {
+ clear_oneshot_mods();
+ unregister_mods(mods);
+ }
+ }
+ break;
+ #endif
+ case MODS_TAP_TOGGLE:
+ if (event.pressed) {
+ if (tap_count <= TAPPING_TOGGLE) {
+ register_mods(mods);
+ }
+ } else {
+ if (tap_count < TAPPING_TOGGLE) {
+ unregister_mods(mods);
+ }
+ }
+ break;
+ default:
+ if (event.pressed) {
+ if (tap_count > 0) {
+#ifndef IGNORE_MOD_TAP_INTERRUPT
+ if (record->tap.interrupted) {
+ dprint("mods_tap: tap: cancel: add_mods\n");
+ // ad hoc: set 0 to cancel tap
+ record->tap.count = 0;
+ register_mods(mods);
+ } else
+#endif
+ {
+ dprint("MODS_TAP: Tap: register_code\n");
+ register_code(action.key.code);
+ }
+ } else {
+ dprint("MODS_TAP: No tap: add_mods\n");
+ register_mods(mods);
+ }
+ } else {
+ if (tap_count > 0) {
+ dprint("MODS_TAP: Tap: unregister_code\n");
+ unregister_code(action.key.code);
+ } else {
+ dprint("MODS_TAP: No tap: add_mods\n");
+ unregister_mods(mods);
+ }
+ }
+ break;
+ }
+ }
+ break;
+#endif
+#ifdef EXTRAKEY_ENABLE
+ /* other HID usage */
+ case ACT_USAGE:
+ switch (action.usage.page) {
+ case PAGE_SYSTEM:
+ if (event.pressed) {
+ host_system_send(action.usage.code);
+ } else {
+ host_system_send(0);
+ }
+ break;
+ case PAGE_CONSUMER:
+ if (event.pressed) {
+ host_consumer_send(action.usage.code);
+ } else {
+ host_consumer_send(0);
+ }
+ break;
+ }
+ break;
+#endif
+#ifdef MOUSEKEY_ENABLE
+ /* Mouse key */
+ case ACT_MOUSEKEY:
+ if (event.pressed) {
+ mousekey_on(action.key.code);
+ mousekey_send();
+ } else {
+ mousekey_off(action.key.code);
+ mousekey_send();
+ }
+ break;
+#endif
+#ifndef NO_ACTION_LAYER
+ case ACT_LAYER:
+ if (action.layer_bitop.on == 0) {
+ /* Default Layer Bitwise Operation */
+ if (!event.pressed) {
+ uint8_t shift = action.layer_bitop.part*4;
+ uint32_t bits = ((uint32_t)action.layer_bitop.bits)<<shift;
+ uint32_t mask = (action.layer_bitop.xbit) ? ~(((uint32_t)0xf)<<shift) : 0;
+ switch (action.layer_bitop.op) {
+ case OP_BIT_AND: default_layer_and(bits | mask); break;
+ case OP_BIT_OR: default_layer_or(bits | mask); break;
+ case OP_BIT_XOR: default_layer_xor(bits | mask); break;
+ case OP_BIT_SET: default_layer_and(mask); default_layer_or(bits); break;
+ }
+ }
+ } else {
+ /* Layer Bitwise Operation */
+ if (event.pressed ? (action.layer_bitop.on & ON_PRESS) :
+ (action.layer_bitop.on & ON_RELEASE)) {
+ uint8_t shift = action.layer_bitop.part*4;
+ uint32_t bits = ((uint32_t)action.layer_bitop.bits)<<shift;
+ uint32_t mask = (action.layer_bitop.xbit) ? ~(((uint32_t)0xf)<<shift) : 0;
+ switch (action.layer_bitop.op) {
+ case OP_BIT_AND: layer_and(bits | mask); break;
+ case OP_BIT_OR: layer_or(bits | mask); break;
+ case OP_BIT_XOR: layer_xor(bits | mask); break;
+ case OP_BIT_SET: layer_and(mask); layer_or(bits); break;
+ }
+ }
+ }
+ break;
+ #ifndef NO_ACTION_TAPPING
+ case ACT_LAYER_TAP:
+ case ACT_LAYER_TAP_EXT:
+ switch (action.layer_tap.code) {
+ case 0xe0 ... 0xef:
+ /* layer On/Off with modifiers(left only) */
+ if (event.pressed) {
+ layer_on(action.layer_tap.val);
+ register_mods(action.layer_tap.code & 0x0f);
+ } else {
+ layer_off(action.layer_tap.val);
+ unregister_mods(action.layer_tap.code & 0x0f);
+ }
+ break;
+ case OP_TAP_TOGGLE:
+ /* tap toggle */
+ if (event.pressed) {
+ if (tap_count < TAPPING_TOGGLE) {
+ layer_invert(action.layer_tap.val);
+ }
+ } else {
+ if (tap_count <= TAPPING_TOGGLE) {
+ layer_invert(action.layer_tap.val);
+ }
+ }
+ break;
+ case OP_ON_OFF:
+ event.pressed ? layer_on(action.layer_tap.val) :
+ layer_off(action.layer_tap.val);
+ break;
+ case OP_OFF_ON:
+ event.pressed ? layer_off(action.layer_tap.val) :
+ layer_on(action.layer_tap.val);
+ break;
+ case OP_SET_CLEAR:
+ event.pressed ? layer_move(action.layer_tap.val) :
+ layer_clear();
+ break;
+ #ifndef NO_ACTION_ONESHOT
+ case OP_ONESHOT:
+ // Oneshot modifier
+ #if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
+ do_release_oneshot = false;
+ if (event.pressed) {
+ del_mods(get_oneshot_locked_mods());
+ if (get_oneshot_layer_state() == ONESHOT_TOGGLED) {
+ reset_oneshot_layer();
+ layer_off(action.layer_tap.val);
+ break;
+ } else if (tap_count < ONESHOT_TAP_TOGGLE) {
+ layer_on(action.layer_tap.val);
+ set_oneshot_layer(action.layer_tap.val, ONESHOT_START);
+ }
+ } else {
+ add_mods(get_oneshot_locked_mods());
+ if (tap_count >= ONESHOT_TAP_TOGGLE) {
+ reset_oneshot_layer();
+ clear_oneshot_locked_mods();
+ set_oneshot_layer(action.layer_tap.val, ONESHOT_TOGGLED);
+ } else {
+ clear_oneshot_layer_state(ONESHOT_PRESSED);
+ }
+ }
+ #else
+ if (event.pressed) {
+ layer_on(action.layer_tap.val);
+ set_oneshot_layer(action.layer_tap.val, ONESHOT_START);
+ } else {
+ clear_oneshot_layer_state(ONESHOT_PRESSED);
+ if (tap_count > 1) {
+ clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
+ }
+ }
+ #endif
+ break;
+ #endif
+ default:
+ /* tap key */
+ if (event.pressed) {
+ if (tap_count > 0) {
+ dprint("KEYMAP_TAP_KEY: Tap: register_code\n");
+ register_code(action.layer_tap.code);
+ } else {
+ dprint("KEYMAP_TAP_KEY: No tap: On on press\n");
+ layer_on(action.layer_tap.val);
+ }
+ } else {
+ if (tap_count > 0) {
+ dprint("KEYMAP_TAP_KEY: Tap: unregister_code\n");
+ unregister_code(action.layer_tap.code);
+ } else {
+ dprint("KEYMAP_TAP_KEY: No tap: Off on release\n");
+ layer_off(action.layer_tap.val);
+ }
+ }
+ break;
+ }
+ break;
+ #endif
+#endif
+ /* Extentions */
+#ifndef NO_ACTION_MACRO
+ case ACT_MACRO:
+ action_macro_play(action_get_macro(record, action.func.id, action.func.opt));
+ break;
+#endif
+#ifdef BACKLIGHT_ENABLE
+ case ACT_BACKLIGHT:
+ if (!event.pressed) {
+ switch (action.backlight.opt) {
+ case BACKLIGHT_INCREASE:
+ backlight_increase();
+ break;
+ case BACKLIGHT_DECREASE:
+ backlight_decrease();
+ break;
+ case BACKLIGHT_TOGGLE:
+ backlight_toggle();
+ break;
+ case BACKLIGHT_STEP:
+ backlight_step();
+ break;
+ case BACKLIGHT_LEVEL:
+ backlight_level(action.backlight.level);
+ break;
+ }
+ }
+ break;
+#endif
+ case ACT_COMMAND:
+ break;
+#ifndef NO_ACTION_FUNCTION
+ case ACT_FUNCTION:
+ action_function(record, action.func.id, action.func.opt);
+ break;
+#endif
+ default:
+ break;
+ }
+
+#ifndef NO_ACTION_ONESHOT
+ /* Because we switch layers after a oneshot event, we need to release the
+ * key before we leave the layer or no key up event will be generated.
+ */
+ if (do_release_oneshot && !(get_oneshot_layer_state() & ONESHOT_PRESSED ) ) {
+ record->event.pressed = false;
+ layer_on(get_oneshot_layer());
+ process_record(record);
+ layer_off(get_oneshot_layer());
+ }
+#endif
+}
+
+
+
+
+/*
+ * Utilities for actions.
+ */
+void register_code(uint8_t code)
+{
+ if (code == KC_NO) {
+ return;
+ }
+
+#ifdef LOCKING_SUPPORT_ENABLE
+ else if (KC_LOCKING_CAPS == code) {
+#ifdef LOCKING_RESYNC_ENABLE
+ // Resync: ignore if caps lock already is on
+ if (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) return;
+#endif
+ add_key(KC_CAPSLOCK);
+ send_keyboard_report();
+ del_key(KC_CAPSLOCK);
+ send_keyboard_report();
+ }
+
+ else if (KC_LOCKING_NUM == code) {
+#ifdef LOCKING_RESYNC_ENABLE
+ if (host_keyboard_leds() & (1<<USB_LED_NUM_LOCK)) return;
+#endif
+ add_key(KC_NUMLOCK);
+ send_keyboard_report();
+ del_key(KC_NUMLOCK);
+ send_keyboard_report();
+ }
+
+ else if (KC_LOCKING_SCROLL == code) {
+#ifdef LOCKING_RESYNC_ENABLE
+ if (host_keyboard_leds() & (1<<USB_LED_SCROLL_LOCK)) return;
+#endif
+ add_key(KC_SCROLLLOCK);
+ send_keyboard_report();
+ del_key(KC_SCROLLLOCK);
+ send_keyboard_report();
+ }
+#endif
+
+ else if IS_KEY(code) {
+ // TODO: should push command_proc out of this block?
+ if (command_proc(code)) return;
+
+#ifndef NO_ACTION_ONESHOT
+/* TODO: remove
+ if (oneshot_state.mods && !oneshot_state.disabled) {
+ uint8_t tmp_mods = get_mods();
+ add_mods(oneshot_state.mods);
+
+ add_key(code);
+ send_keyboard_report();
+
+ set_mods(tmp_mods);
+ send_keyboard_report();
+ oneshot_cancel();
+ } else
+*/
+#endif
+ {
+ add_key(code);
+ send_keyboard_report();
+ }
+ }
+ else if IS_MOD(code) {
+ add_mods(MOD_BIT(code));
+ send_keyboard_report();
+ }
+ else if IS_SYSTEM(code) {
+ host_system_send(KEYCODE2SYSTEM(code));
+ }
+ else if IS_CONSUMER(code) {
+ host_consumer_send(KEYCODE2CONSUMER(code));
+ }
+}
+
+void unregister_code(uint8_t code)
+{
+ if (code == KC_NO) {
+ return;
+ }
+
+#ifdef LOCKING_SUPPORT_ENABLE
+ else if (KC_LOCKING_CAPS == code) {
+#ifdef LOCKING_RESYNC_ENABLE
+ // Resync: ignore if caps lock already is off
+ if (!(host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK))) return;
+#endif
+ add_key(KC_CAPSLOCK);
+ send_keyboard_report();
+ del_key(KC_CAPSLOCK);
+ send_keyboard_report();
+ }
+
+ else if (KC_LOCKING_NUM == code) {
+#ifdef LOCKING_RESYNC_ENABLE
+ if (!(host_keyboard_leds() & (1<<USB_LED_NUM_LOCK))) return;
+#endif
+ add_key(KC_NUMLOCK);
+ send_keyboard_report();
+ del_key(KC_NUMLOCK);
+ send_keyboard_report();
+ }
+
+ else if (KC_LOCKING_SCROLL == code) {
+#ifdef LOCKING_RESYNC_ENABLE
+ if (!(host_keyboard_leds() & (1<<USB_LED_SCROLL_LOCK))) return;
+#endif
+ add_key(KC_SCROLLLOCK);
+ send_keyboard_report();
+ del_key(KC_SCROLLLOCK);
+ send_keyboard_report();
+ }
+#endif
+
+ else if IS_KEY(code) {
+ del_key(code);
+ send_keyboard_report();
+ }
+ else if IS_MOD(code) {
+ del_mods(MOD_BIT(code));
+ send_keyboard_report();
+ }
+ else if IS_SYSTEM(code) {
+ host_system_send(0);
+ }
+ else if IS_CONSUMER(code) {
+ host_consumer_send(0);
+ }
+}
+
+void register_mods(uint8_t mods)
+{
+ if (mods) {
+ add_mods(mods);
+ send_keyboard_report();
+ }
+}
+
+void unregister_mods(uint8_t mods)
+{
+ if (mods) {
+ del_mods(mods);
+ send_keyboard_report();
+ }
+}
+
+void clear_keyboard(void)
+{
+ clear_mods();
+ clear_keyboard_but_mods();
+}
+
+void clear_keyboard_but_mods(void)
+{
+ clear_weak_mods();
+ clear_macro_mods();
+ clear_keys();
+ send_keyboard_report();
+#ifdef MOUSEKEY_ENABLE
+ mousekey_clear();
+ mousekey_send();
+#endif
+#ifdef EXTRAKEY_ENABLE
+ host_system_send(0);
+ host_consumer_send(0);
+#endif
+}
+
+bool is_tap_key(keypos_t key)
+{
+ action_t action = layer_switch_get_action(key);
+
+ switch (action.kind.id) {
+ case ACT_LMODS_TAP:
+ case ACT_RMODS_TAP:
+ case ACT_LAYER_TAP:
+ case ACT_LAYER_TAP_EXT:
+ switch (action.layer_tap.code) {
+ case 0x00 ... 0xdf:
+ case OP_TAP_TOGGLE:
+ case OP_ONESHOT:
+ return true;
+ }
+ return false;
+ case ACT_MACRO:
+ case ACT_FUNCTION:
+ if (action.func.opt & FUNC_TAP) { return true; }
+ return false;
+ }
+ return false;
+}
+
+
+/*
+ * debug print
+ */
+void debug_event(keyevent_t event)
+{
+ dprintf("%04X%c(%u)", (event.key.row<<8 | event.key.col), (event.pressed ? 'd' : 'u'), event.time);
+}
+
+void debug_record(keyrecord_t record)
+{
+ debug_event(record.event);
+#ifndef NO_ACTION_TAPPING
+ dprintf(":%u%c", record.tap.count, (record.tap.interrupted ? '-' : ' '));
+#endif
+}
+
+void debug_action(action_t action)
+{
+ switch (action.kind.id) {
+ case ACT_LMODS: dprint("ACT_LMODS"); break;
+ case ACT_RMODS: dprint("ACT_RMODS"); break;
+ case ACT_LMODS_TAP: dprint("ACT_LMODS_TAP"); break;
+ case ACT_RMODS_TAP: dprint("ACT_RMODS_TAP"); break;
+ case ACT_USAGE: dprint("ACT_USAGE"); break;
+ case ACT_MOUSEKEY: dprint("ACT_MOUSEKEY"); break;
+ case ACT_LAYER: dprint("ACT_LAYER"); break;
+ case ACT_LAYER_TAP: dprint("ACT_LAYER_TAP"); break;
+ case ACT_LAYER_TAP_EXT: dprint("ACT_LAYER_TAP_EXT"); break;
+ case ACT_MACRO: dprint("ACT_MACRO"); break;
+ case ACT_COMMAND: dprint("ACT_COMMAND"); break;
+ case ACT_FUNCTION: dprint("ACT_FUNCTION"); break;
+ default: dprint("UNKNOWN"); break;
+ }
+ dprintf("[%X:%02X]", action.kind.param>>8, action.kind.param&0xff);
+}
diff --git a/tmk_core/common/action.h b/tmk_core/common/action.h
new file mode 100644
index 000000000..e8aa12a7c
--- /dev/null
+++ b/tmk_core/common/action.h
@@ -0,0 +1,90 @@
+/*
+Copyright 2012,2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef ACTION_H
+#define ACTION_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "keyboard.h"
+#include "keycode.h"
+#include "action_code.h"
+#include "action_macro.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* tapping count and state */
+typedef struct {
+ bool interrupted :1;
+ bool reserved2 :1;
+ bool reserved1 :1;
+ bool reserved0 :1;
+ uint8_t count :4;
+} tap_t;
+
+/* Key event container for recording */
+typedef struct {
+ keyevent_t event;
+#ifndef NO_ACTION_TAPPING
+ tap_t tap;
+#endif
+} keyrecord_t;
+
+/* Execute action per keyevent */
+void action_exec(keyevent_t event);
+
+/* action for key */
+action_t action_for_key(uint8_t layer, keypos_t key);
+
+/* macro */
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt);
+
+/* user defined special function */
+void action_function(keyrecord_t *record, uint8_t id, uint8_t opt);
+
+/* keyboard-specific key event (pre)processing */
+bool process_record_quantum(keyrecord_t *record);
+
+/* Utilities for actions. */
+#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
+extern bool disable_action_cache;
+#endif
+void process_record_nocache(keyrecord_t *record);
+void process_record(keyrecord_t *record);
+void process_action(keyrecord_t *record, action_t action);
+void register_code(uint8_t code);
+void unregister_code(uint8_t code);
+void register_mods(uint8_t mods);
+void unregister_mods(uint8_t mods);
+//void set_mods(uint8_t mods);
+void clear_keyboard(void);
+void clear_keyboard_but_mods(void);
+void layer_switch(uint8_t new_layer);
+bool is_tap_key(keypos_t key);
+
+/* debug */
+void debug_event(keyevent_t event);
+void debug_record(keyrecord_t record);
+void debug_action(action_t action);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ACTION_H */
diff --git a/tmk_core/common/action_code.h b/tmk_core/common/action_code.h
new file mode 100644
index 000000000..ca729aaec
--- /dev/null
+++ b/tmk_core/common/action_code.h
@@ -0,0 +1,318 @@
+/*
+Copyright 2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef ACTION_CODE_H
+#define ACTION_CODE_H
+
+/* Action codes
+ * ============
+ * 16bit code: action_kind(4bit) + action_parameter(12bit)
+ *
+ *
+ * Key Actions(00xx)
+ * -----------------
+ * ACT_MODS(000r):
+ * 000r|0000|0000 0000 No action code
+ * 000r|0000|0000 0001 Transparent code
+ * 000r|0000| keycode Key
+ * 000r|mods|0000 0000 Modifiers
+ * 000r|mods| keycode Modifiers+Key(Modified key)
+ * r: Left/Right flag(Left:0, Right:1)
+ *
+ * ACT_MODS_TAP(001r):
+ * 001r|mods|0000 0000 Modifiers with OneShot
+ * 001r|mods|0000 0001 Modifiers with tap toggle
+ * 001r|mods|0000 00xx (reserved)
+ * 001r|mods| keycode Modifiers with Tap Key(Dual role)
+ *
+ *
+ * Other Keys(01xx)
+ * ----------------
+ * ACT_USAGE(0100): TODO: Not needed?
+ * 0100|00| usage(10) System control(0x80) - General Desktop page(0x01)
+ * 0100|01| usage(10) Consumer control(0x01) - Consumer page(0x0C)
+ * 0100|10| usage(10) (reserved)
+ * 0100|11| usage(10) (reserved)
+ *
+ * ACT_MOUSEKEY(0110): TODO: Not needed?
+ * 0101|xxxx| keycode Mouse key
+ *
+ * 011x|xxxx xxxx xxxx (reseved)
+ *
+ *
+ * Layer Actions(10xx)
+ * -------------------
+ * ACT_LAYER(1000):
+ * 1000|oo00|pppE BBBB Default Layer Bitwise operation
+ * oo: operation(00:AND, 01:OR, 10:XOR, 11:SET)
+ * ppp: 4-bit chunk part(0-7)
+ * EBBBB: bits and extra bit
+ * 1000|ooee|pppE BBBB Layer Bitwise Operation
+ * oo: operation(00:AND, 01:OR, 10:XOR, 11:SET)
+ * ppp: 4-bit chunk part(0-7)
+ * EBBBB: bits and extra bit
+ * ee: on event(01:press, 10:release, 11:both)
+ *
+ * 1001|xxxx|xxxx xxxx (reserved)
+ * 1001|oopp|BBBB BBBB 8-bit Bitwise Operation???
+ *
+ * ACT_LAYER_TAP(101x):
+ * 101E|LLLL| keycode On/Off with tap key (0x00-DF)[TAP]
+ * 101E|LLLL|1110 mods On/Off with modifiers (0xE0-EF)[NOT TAP]
+ * 101E|LLLL|1111 0000 Invert with tap toggle (0xF0) [TAP]
+ * 101E|LLLL|1111 0001 On/Off (0xF1) [NOT TAP]
+ * 101E|LLLL|1111 0010 Off/On (0xF2) [NOT TAP]
+ * 101E|LLLL|1111 0011 Set/Clear (0xF3) [NOT TAP]
+ * 101E|LLLL|1111 0100 One Shot Layer (0xF4) [TAP]
+ * 101E|LLLL|1111 xxxx Reserved (0xF5-FF)
+ * ELLLL: layer 0-31(E: extra bit for layer 16-31)
+ *
+ *
+ * Extensions(11xx)
+ * ----------------
+ * ACT_MACRO(1100):
+ * 1100|opt | id(8) Macro play?
+ * 1100|1111| id(8) Macro record?
+ *
+ * ACT_BACKLIGHT(1101):
+ * 1101|opt |level(8) Backlight commands
+ *
+ * ACT_COMMAND(1110):
+ * 1110|opt | id(8) Built-in Command exec
+ *
+ * ACT_FUNCTION(1111):
+ * 1111| address(12) Function?
+ * 1111|opt | id(8) Function?
+ */
+enum action_kind_id {
+ /* Key Actions */
+ ACT_MODS = 0b0000,
+ ACT_LMODS = 0b0000,
+ ACT_RMODS = 0b0001,
+ ACT_MODS_TAP = 0b0010,
+ ACT_LMODS_TAP = 0b0010,
+ ACT_RMODS_TAP = 0b0011,
+ /* Other Keys */
+ ACT_USAGE = 0b0100,
+ ACT_MOUSEKEY = 0b0101,
+ /* Layer Actions */
+ ACT_LAYER = 0b1000,
+ ACT_LAYER_TAP = 0b1010, /* Layer 0-15 */
+ ACT_LAYER_TAP_EXT = 0b1011, /* Layer 16-31 */
+ /* Extensions */
+ ACT_MACRO = 0b1100,
+ ACT_BACKLIGHT = 0b1101,
+ ACT_COMMAND = 0b1110,
+ ACT_FUNCTION = 0b1111
+};
+
+
+/* Action Code Struct
+ *
+ * NOTE:
+ * In avr-gcc bit field seems to be assigned from LSB(bit0) to MSB(bit15).
+ * AVR looks like a little endian in avr-gcc.
+ * Not portable across compiler/endianness?
+ *
+ * Byte order and bit order of 0x1234:
+ * Big endian: Little endian:
+ * -------------------- --------------------
+ * FEDC BA98 7654 3210 0123 4567 89AB CDEF
+ * 0001 0010 0011 0100 0010 1100 0100 1000
+ * 0x12 0x34 0x34 0x12
+ */
+typedef union {
+ uint16_t code;
+ struct action_kind {
+ uint16_t param :12;
+ uint8_t id :4;
+ } kind;
+ struct action_key {
+ uint8_t code :8;
+ uint8_t mods :4;
+ uint8_t kind :4;
+ } key;
+ struct action_layer_bitop {
+ uint8_t bits :4;
+ uint8_t xbit :1;
+ uint8_t part :3;
+ uint8_t on :2;
+ uint8_t op :2;
+ uint8_t kind :4;
+ } layer_bitop;
+ struct action_layer_tap {
+ uint8_t code :8;
+ uint8_t val :5;
+ uint8_t kind :3;
+ } layer_tap;
+ struct action_usage {
+ uint16_t code :10;
+ uint8_t page :2;
+ uint8_t kind :4;
+ } usage;
+ struct action_backlight {
+ uint8_t level :8;
+ uint8_t opt :4;
+ uint8_t kind :4;
+ } backlight;
+ struct action_command {
+ uint8_t id :8;
+ uint8_t opt :4;
+ uint8_t kind :4;
+ } command;
+ struct action_function {
+ uint8_t id :8;
+ uint8_t opt :4;
+ uint8_t kind :4;
+ } func;
+} action_t;
+
+
+/* action utility */
+#define ACTION_NO 0
+#define ACTION_TRANSPARENT 1
+#define ACTION(kind, param) ((kind)<<12 | (param))
+
+
+/*
+ * Key Actions
+ */
+/* Mod bits: 43210
+ * bit 0 ||||+- Control
+ * bit 1 |||+-- Shift
+ * bit 2 ||+--- Alt
+ * bit 3 |+---- Gui
+ * bit 4 +----- LR flag(Left:0, Right:1)
+ */
+enum mods_bit {
+ MOD_LCTL = 0x01,
+ MOD_LSFT = 0x02,
+ MOD_LALT = 0x04,
+ MOD_LGUI = 0x08,
+ MOD_RCTL = 0x11,
+ MOD_RSFT = 0x12,
+ MOD_RALT = 0x14,
+ MOD_RGUI = 0x18,
+};
+enum mods_codes {
+ MODS_ONESHOT = 0x00,
+ MODS_TAP_TOGGLE = 0x01,
+};
+#define ACTION_KEY(key) ACTION(ACT_MODS, (key))
+#define ACTION_MODS(mods) ACTION(ACT_MODS, ((mods)&0x1f)<<8 | 0)
+#define ACTION_MODS_KEY(mods, key) ACTION(ACT_MODS, ((mods)&0x1f)<<8 | (key))
+#define ACTION_MODS_TAP_KEY(mods, key) ACTION(ACT_MODS_TAP, ((mods)&0x1f)<<8 | (key))
+#define ACTION_MODS_ONESHOT(mods) ACTION(ACT_MODS_TAP, ((mods)&0x1f)<<8 | MODS_ONESHOT)
+#define ACTION_MODS_TAP_TOGGLE(mods) ACTION(ACT_MODS_TAP, ((mods)&0x1f)<<8 | MODS_TAP_TOGGLE)
+
+
+/*
+ * Other Keys
+ */
+enum usage_pages {
+ PAGE_SYSTEM,
+ PAGE_CONSUMER
+};
+#define ACTION_USAGE_SYSTEM(id) ACTION(ACT_USAGE, PAGE_SYSTEM<<10 | (id))
+#define ACTION_USAGE_CONSUMER(id) ACTION(ACT_USAGE, PAGE_CONSUMER<<10 | (id))
+#define ACTION_MOUSEKEY(key) ACTION(ACT_MOUSEKEY, key)
+
+
+
+/*
+ * Layer Actions
+ */
+enum layer_param_on {
+ ON_PRESS = 1,
+ ON_RELEASE = 2,
+ ON_BOTH = 3,
+};
+enum layer_param_bit_op {
+ OP_BIT_AND = 0,
+ OP_BIT_OR = 1,
+ OP_BIT_XOR = 2,
+ OP_BIT_SET = 3,
+};
+enum layer_pram_tap_op {
+ OP_TAP_TOGGLE = 0xF0,
+ OP_ON_OFF,
+ OP_OFF_ON,
+ OP_SET_CLEAR,
+ OP_ONESHOT,
+};
+#define ACTION_LAYER_BITOP(op, part, bits, on) (ACT_LAYER<<12 | (op)<<10 | (on)<<8 | (part)<<5 | ((bits)&0x1f))
+#define ACTION_LAYER_TAP(layer, key) (ACT_LAYER_TAP<<12 | (layer)<<8 | (key))
+/* Default Layer */
+#define ACTION_DEFAULT_LAYER_SET(layer) ACTION_DEFAULT_LAYER_BIT_SET((layer)/4, 1<<((layer)%4))
+/* Layer Operation */
+#define ACTION_LAYER_CLEAR(on) ACTION_LAYER_BIT_AND(0, 0, (on))
+#define ACTION_LAYER_MOMENTARY(layer) ACTION_LAYER_ON_OFF(layer)
+#define ACTION_LAYER_TOGGLE(layer) ACTION_LAYER_INVERT(layer, ON_RELEASE)
+#define ACTION_LAYER_INVERT(layer, on) ACTION_LAYER_BIT_XOR((layer)/4, 1<<((layer)%4), (on))
+#define ACTION_LAYER_ON(layer, on) ACTION_LAYER_BIT_OR( (layer)/4, 1<<((layer)%4), (on))
+#define ACTION_LAYER_OFF(layer, on) ACTION_LAYER_BIT_AND((layer)/4, ~(1<<((layer)%4)), (on))
+#define ACTION_LAYER_SET(layer, on) ACTION_LAYER_BIT_SET((layer)/4, 1<<((layer)%4), (on))
+#define ACTION_LAYER_ON_OFF(layer) ACTION_LAYER_TAP((layer), OP_ON_OFF)
+#define ACTION_LAYER_OFF_ON(layer) ACTION_LAYER_TAP((layer), OP_OFF_ON)
+#define ACTION_LAYER_SET_CLEAR(layer) ACTION_LAYER_TAP((layer), OP_SET_CLEAR)
+#define ACTION_LAYER_ONESHOT(layer) ACTION_LAYER_TAP((layer), OP_ONESHOT)
+#define ACTION_LAYER_MODS(layer, mods) ACTION_LAYER_TAP((layer), 0xe0 | ((mods)&0x0f))
+/* With Tapping */
+#define ACTION_LAYER_TAP_KEY(layer, key) ACTION_LAYER_TAP((layer), (key))
+#define ACTION_LAYER_TAP_TOGGLE(layer) ACTION_LAYER_TAP((layer), OP_TAP_TOGGLE)
+/* Bitwise Operation */
+#define ACTION_LAYER_BIT_AND(part, bits, on) ACTION_LAYER_BITOP(OP_BIT_AND, (part), (bits), (on))
+#define ACTION_LAYER_BIT_OR( part, bits, on) ACTION_LAYER_BITOP(OP_BIT_OR, (part), (bits), (on))
+#define ACTION_LAYER_BIT_XOR(part, bits, on) ACTION_LAYER_BITOP(OP_BIT_XOR, (part), (bits), (on))
+#define ACTION_LAYER_BIT_SET(part, bits, on) ACTION_LAYER_BITOP(OP_BIT_SET, (part), (bits), (on))
+/* Default Layer Bitwise Operation */
+#define ACTION_DEFAULT_LAYER_BIT_AND(part, bits) ACTION_LAYER_BITOP(OP_BIT_AND, (part), (bits), 0)
+#define ACTION_DEFAULT_LAYER_BIT_OR( part, bits) ACTION_LAYER_BITOP(OP_BIT_OR, (part), (bits), 0)
+#define ACTION_DEFAULT_LAYER_BIT_XOR(part, bits) ACTION_LAYER_BITOP(OP_BIT_XOR, (part), (bits), 0)
+#define ACTION_DEFAULT_LAYER_BIT_SET(part, bits) ACTION_LAYER_BITOP(OP_BIT_SET, (part), (bits), 0)
+
+
+/*
+ * Extensions
+ */
+enum backlight_opt {
+ BACKLIGHT_INCREASE = 0,
+ BACKLIGHT_DECREASE = 1,
+ BACKLIGHT_TOGGLE = 2,
+ BACKLIGHT_STEP = 3,
+ BACKLIGHT_LEVEL = 4,
+};
+/* Macro */
+#define ACTION_MACRO(id) ACTION(ACT_MACRO, (id))
+#define ACTION_MACRO_TAP(id) ACTION(ACT_MACRO, FUNC_TAP<<8 | (id))
+#define ACTION_MACRO_OPT(id, opt) ACTION(ACT_MACRO, (opt)<<8 | (id))
+/* Backlight */
+#define ACTION_BACKLIGHT_INCREASE() ACTION(ACT_BACKLIGHT, BACKLIGHT_INCREASE << 8)
+#define ACTION_BACKLIGHT_DECREASE() ACTION(ACT_BACKLIGHT, BACKLIGHT_DECREASE << 8)
+#define ACTION_BACKLIGHT_TOGGLE() ACTION(ACT_BACKLIGHT, BACKLIGHT_TOGGLE << 8)
+#define ACTION_BACKLIGHT_STEP() ACTION(ACT_BACKLIGHT, BACKLIGHT_STEP << 8)
+#define ACTION_BACKLIGHT_LEVEL(level) ACTION(ACT_BACKLIGHT, BACKLIGHT_LEVEL << 8 | (level))
+/* Command */
+#define ACTION_COMMAND(id, opt) ACTION(ACT_COMMAND, (opt)<<8 | (addr))
+/* Function */
+enum function_opts {
+ FUNC_TAP = 0x8, /* indciates function is tappable */
+};
+#define ACTION_FUNCTION(id) ACTION(ACT_FUNCTION, (id))
+#define ACTION_FUNCTION_TAP(id) ACTION(ACT_FUNCTION, FUNC_TAP<<8 | (id))
+#define ACTION_FUNCTION_OPT(id, opt) ACTION(ACT_FUNCTION, (opt)<<8 | (id))
+
+#endif /* ACTION_CODE_H */
diff --git a/tmk_core/common/action_layer.c b/tmk_core/common/action_layer.c
new file mode 100644
index 000000000..63fa2b5ae
--- /dev/null
+++ b/tmk_core/common/action_layer.c
@@ -0,0 +1,203 @@
+#include <stdint.h>
+#include "keyboard.h"
+#include "action.h"
+#include "util.h"
+#include "action_layer.h"
+
+#ifdef DEBUG_ACTION
+#include "debug.h"
+#else
+#include "nodebug.h"
+#endif
+
+
+/*
+ * Default Layer State
+ */
+uint32_t default_layer_state = 0;
+
+static void default_layer_state_set(uint32_t state)
+{
+ debug("default_layer_state: ");
+ default_layer_debug(); debug(" to ");
+ default_layer_state = state;
+ default_layer_debug(); debug("\n");
+ clear_keyboard_but_mods(); // To avoid stuck keys
+}
+
+void default_layer_debug(void)
+{
+ dprintf("%08lX(%u)", default_layer_state, biton32(default_layer_state));
+}
+
+void default_layer_set(uint32_t state)
+{
+ default_layer_state_set(state);
+}
+
+#ifndef NO_ACTION_LAYER
+void default_layer_or(uint32_t state)
+{
+ default_layer_state_set(default_layer_state | state);
+}
+void default_layer_and(uint32_t state)
+{
+ default_layer_state_set(default_layer_state & state);
+}
+void default_layer_xor(uint32_t state)
+{
+ default_layer_state_set(default_layer_state ^ state);
+}
+#endif
+
+
+#ifndef NO_ACTION_LAYER
+/*
+ * Keymap Layer State
+ */
+uint32_t layer_state = 0;
+
+static void layer_state_set(uint32_t state)
+{
+ dprint("layer_state: ");
+ layer_debug(); dprint(" to ");
+ layer_state = state;
+ layer_debug(); dprintln();
+ clear_keyboard_but_mods(); // To avoid stuck keys
+}
+
+void layer_clear(void)
+{
+ layer_state_set(0);
+}
+
+void layer_move(uint8_t layer)
+{
+ layer_state_set(1UL<<layer);
+}
+
+void layer_on(uint8_t layer)
+{
+ layer_state_set(layer_state | (1UL<<layer));
+}
+
+void layer_off(uint8_t layer)
+{
+ layer_state_set(layer_state & ~(1UL<<layer));
+}
+
+void layer_invert(uint8_t layer)
+{
+ layer_state_set(layer_state ^ (1UL<<layer));
+}
+
+void layer_or(uint32_t state)
+{
+ layer_state_set(layer_state | state);
+}
+void layer_and(uint32_t state)
+{
+ layer_state_set(layer_state & state);
+}
+void layer_xor(uint32_t state)
+{
+ layer_state_set(layer_state ^ state);
+}
+
+void layer_debug(void)
+{
+ dprintf("%08lX(%u)", layer_state, biton32(layer_state));
+}
+#endif
+
+#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
+uint8_t source_layers_cache[(MATRIX_ROWS * MATRIX_COLS + 7) / 8][MAX_LAYER_BITS] = {0};
+
+void update_source_layers_cache(keypos_t key, uint8_t layer)
+{
+ const uint8_t key_number = key.col + (key.row * MATRIX_COLS);
+ const uint8_t storage_row = key_number / 8;
+ const uint8_t storage_bit = key_number % 8;
+
+ for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) {
+ source_layers_cache[storage_row][bit_number] ^=
+ (-((layer & (1U << bit_number)) != 0)
+ ^ source_layers_cache[storage_row][bit_number])
+ & (1U << storage_bit);
+ }
+}
+
+uint8_t read_source_layers_cache(keypos_t key)
+{
+ const uint8_t key_number = key.col + (key.row * MATRIX_COLS);
+ const uint8_t storage_row = key_number / 8;
+ const uint8_t storage_bit = key_number % 8;
+ uint8_t layer = 0;
+
+ for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) {
+ layer |=
+ ((source_layers_cache[storage_row][bit_number]
+ & (1U << storage_bit)) != 0)
+ << bit_number;
+ }
+
+ return layer;
+}
+#endif
+
+/*
+ * Make sure the action triggered when the key is released is the same
+ * one as the one triggered on press. It's important for the mod keys
+ * when the layer is switched after the down event but before the up
+ * event as they may get stuck otherwise.
+ */
+action_t store_or_get_action(bool pressed, keypos_t key)
+{
+#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
+ if (disable_action_cache) {
+ return layer_switch_get_action(key);
+ }
+
+ uint8_t layer;
+
+ if (pressed) {
+ layer = layer_switch_get_layer(key);
+ update_source_layers_cache(key, layer);
+ }
+ else {
+ layer = read_source_layers_cache(key);
+ }
+ return action_for_key(layer, key);
+#else
+ return layer_switch_get_action(key);
+#endif
+}
+
+
+int8_t layer_switch_get_layer(keypos_t key)
+{
+ action_t action;
+ action.code = ACTION_TRANSPARENT;
+
+#ifndef NO_ACTION_LAYER
+ uint32_t layers = layer_state | default_layer_state;
+ /* check top layer first */
+ for (int8_t i = 31; i >= 0; i--) {
+ if (layers & (1UL<<i)) {
+ action = action_for_key(i, key);
+ if (action.code != ACTION_TRANSPARENT) {
+ return i;
+ }
+ }
+ }
+ /* fall back to layer 0 */
+ return 0;
+#else
+ return biton32(default_layer_state);
+#endif
+}
+
+action_t layer_switch_get_action(keypos_t key)
+{
+ return action_for_key(layer_switch_get_layer(key), key);
+}
diff --git a/tmk_core/common/action_layer.h b/tmk_core/common/action_layer.h
new file mode 100644
index 000000000..025cf5420
--- /dev/null
+++ b/tmk_core/common/action_layer.h
@@ -0,0 +1,89 @@
+/*
+Copyright 2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef ACTION_LAYER_H
+#define ACTION_LAYER_H
+
+#include <stdint.h>
+#include "keyboard.h"
+#include "action.h"
+
+
+/*
+ * Default Layer
+ */
+extern uint32_t default_layer_state;
+void default_layer_debug(void);
+void default_layer_set(uint32_t state);
+
+#ifndef NO_ACTION_LAYER
+/* bitwise operation */
+void default_layer_or(uint32_t state);
+void default_layer_and(uint32_t state);
+void default_layer_xor(uint32_t state);
+#else
+#define default_layer_or(state)
+#define default_layer_and(state)
+#define default_layer_xor(state)
+#endif
+
+
+/*
+ * Keymap Layer
+ */
+#ifndef NO_ACTION_LAYER
+extern uint32_t layer_state;
+void layer_debug(void);
+void layer_clear(void);
+void layer_move(uint8_t layer);
+void layer_on(uint8_t layer);
+void layer_off(uint8_t layer);
+void layer_invert(uint8_t layer);
+/* bitwise operation */
+void layer_or(uint32_t state);
+void layer_and(uint32_t state);
+void layer_xor(uint32_t state);
+#else
+#define layer_state 0
+#define layer_clear()
+#define layer_move(layer)
+#define layer_on(layer)
+#define layer_off(layer)
+#define layer_invert(layer)
+
+#define layer_or(state)
+#define layer_and(state)
+#define layer_xor(state)
+#define layer_debug()
+
+#endif
+
+/* pressed actions cache */
+#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
+/* The number of bits needed to represent the layer number: log2(32). */
+#define MAX_LAYER_BITS 5
+void update_source_layers_cache(keypos_t key, uint8_t layer);
+uint8_t read_source_layers_cache(keypos_t key);
+#endif
+action_t store_or_get_action(bool pressed, keypos_t key);
+
+/* return the topmost non-transparent layer currently associated with key */
+int8_t layer_switch_get_layer(keypos_t key);
+
+/* return action depending on current layer status */
+action_t layer_switch_get_action(keypos_t key);
+
+#endif
diff --git a/tmk_core/common/action_macro.c b/tmk_core/common/action_macro.c
new file mode 100644
index 000000000..7726b1190
--- /dev/null
+++ b/tmk_core/common/action_macro.c
@@ -0,0 +1,85 @@
+/*
+Copyright 2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "action.h"
+#include "action_util.h"
+#include "action_macro.h"
+#include "wait.h"
+
+#ifdef DEBUG_ACTION
+#include "debug.h"
+#else
+#include "nodebug.h"
+#endif
+
+
+#ifndef NO_ACTION_MACRO
+
+#define MACRO_READ() (macro = MACRO_GET(macro_p++))
+void action_macro_play(const macro_t *macro_p)
+{
+ macro_t macro = END;
+ uint8_t interval = 0;
+
+ if (!macro_p) return;
+ while (true) {
+ switch (MACRO_READ()) {
+ case KEY_DOWN:
+ MACRO_READ();
+ dprintf("KEY_DOWN(%02X)\n", macro);
+ if (IS_MOD(macro)) {
+ add_macro_mods(MOD_BIT(macro));
+ send_keyboard_report();
+ } else {
+ register_code(macro);
+ }
+ break;
+ case KEY_UP:
+ MACRO_READ();
+ dprintf("KEY_UP(%02X)\n", macro);
+ if (IS_MOD(macro)) {
+ del_macro_mods(MOD_BIT(macro));
+ send_keyboard_report();
+ } else {
+ unregister_code(macro);
+ }
+ break;
+ case WAIT:
+ MACRO_READ();
+ dprintf("WAIT(%u)\n", macro);
+ { uint8_t ms = macro; while (ms--) wait_ms(1); }
+ break;
+ case INTERVAL:
+ interval = MACRO_READ();
+ dprintf("INTERVAL(%u)\n", interval);
+ break;
+ case 0x04 ... 0x73:
+ dprintf("DOWN(%02X)\n", macro);
+ register_code(macro);
+ break;
+ case 0x84 ... 0xF3:
+ dprintf("UP(%02X)\n", macro);
+ unregister_code(macro&0x7F);
+ break;
+ case END:
+ default:
+ return;
+ }
+ // interval
+ { uint8_t ms = interval; while (ms--) wait_ms(1); }
+ }
+}
+#endif
diff --git a/tmk_core/common/action_macro.h b/tmk_core/common/action_macro.h
new file mode 100644
index 000000000..aedc32ec6
--- /dev/null
+++ b/tmk_core/common/action_macro.h
@@ -0,0 +1,102 @@
+/*
+Copyright 2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef ACTION_MACRO_H
+#define ACTION_MACRO_H
+#include <stdint.h>
+#include "progmem.h"
+
+
+#define MACRO_NONE 0
+#define MACRO(...) ({ static const macro_t __m[] PROGMEM = { __VA_ARGS__ }; &__m[0]; })
+#define MACRO_GET(p) pgm_read_byte(p)
+
+typedef uint8_t macro_t;
+
+
+#ifndef NO_ACTION_MACRO
+void action_macro_play(const macro_t *macro_p);
+#else
+#define action_macro_play(macro)
+#endif
+
+
+
+/* Macro commands
+ * code(0x04-73) // key down(1byte)
+ * code(0x04-73) | 0x80 // key up(1byte)
+ * { KEY_DOWN, code(0x04-0xff) } // key down(2bytes)
+ * { KEY_UP, code(0x04-0xff) } // key up(2bytes)
+ * WAIT // wait milli-seconds
+ * INTERVAL // set interval between macro commands
+ * END // stop macro execution
+ *
+ * Ideas(Not implemented):
+ * modifiers
+ * system usage
+ * consumer usage
+ * unicode usage
+ * function call
+ * conditionals
+ * loop
+ */
+enum macro_command_id{
+ /* 0x00 - 0x03 */
+ END = 0x00,
+ KEY_DOWN,
+ KEY_UP,
+
+ /* 0x04 - 0x73 (reserved for keycode down) */
+
+ /* 0x74 - 0x83 */
+ WAIT = 0x74,
+ INTERVAL,
+
+ /* 0x84 - 0xf3 (reserved for keycode up) */
+
+ /* 0xf4 - 0xff */
+};
+
+
+/* TODO: keycode:0x04-0x73 can be handled by 1byte command else 2bytes are needed
+ * if keycode between 0x04 and 0x73
+ * keycode / (keycode|0x80)
+ * else
+ * {KEY_DOWN, keycode} / {KEY_UP, keycode}
+*/
+#define DOWN(key) KEY_DOWN, (key)
+#define UP(key) KEY_UP, (key)
+#define TYPE(key) DOWN(key), UP(key)
+#define WAIT(ms) WAIT, (ms)
+#define INTERVAL(ms) INTERVAL, (ms)
+
+/* key down */
+#define D(key) DOWN(KC_##key)
+/* key up */
+#define U(key) UP(KC_##key)
+/* key type */
+#define T(key) TYPE(KC_##key)
+/* wait */
+#define W(ms) WAIT(ms)
+/* interval */
+#define I(ms) INTERVAL(ms)
+
+/* for backward comaptibility */
+#define MD(key) DOWN(KC_##key)
+#define MU(key) UP(KC_##key)
+
+
+#endif /* ACTION_MACRO_H */
diff --git a/tmk_core/common/action_tapping.c b/tmk_core/common/action_tapping.c
new file mode 100644
index 000000000..e16e11be7
--- /dev/null
+++ b/tmk_core/common/action_tapping.c
@@ -0,0 +1,377 @@
+#include <stdint.h>
+#include <stdbool.h>
+#include "action.h"
+#include "action_layer.h"
+#include "action_tapping.h"
+#include "keycode.h"
+#include "timer.h"
+
+#ifdef DEBUG_ACTION
+#include "debug.h"
+#else
+#include "nodebug.h"
+#endif
+
+#ifndef NO_ACTION_TAPPING
+
+#define IS_TAPPING() !IS_NOEVENT(tapping_key.event)
+#define IS_TAPPING_PRESSED() (IS_TAPPING() && tapping_key.event.pressed)
+#define IS_TAPPING_RELEASED() (IS_TAPPING() && !tapping_key.event.pressed)
+#define IS_TAPPING_KEY(k) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (k)))
+#define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < TAPPING_TERM)
+
+
+static keyrecord_t tapping_key = {};
+static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {};
+static uint8_t waiting_buffer_head = 0;
+static uint8_t waiting_buffer_tail = 0;
+
+static bool process_tapping(keyrecord_t *record);
+static bool waiting_buffer_enq(keyrecord_t record);
+static void waiting_buffer_clear(void);
+static bool waiting_buffer_typed(keyevent_t event);
+static bool waiting_buffer_has_anykey_pressed(void);
+static void waiting_buffer_scan_tap(void);
+static void debug_tapping_key(void);
+static void debug_waiting_buffer(void);
+
+
+void action_tapping_process(keyrecord_t record)
+{
+ if (process_tapping(&record)) {
+ if (!IS_NOEVENT(record.event)) {
+ debug("processed: "); debug_record(record); debug("\n");
+ }
+ } else {
+ if (!waiting_buffer_enq(record)) {
+ // clear all in case of overflow.
+ debug("OVERFLOW: CLEAR ALL STATES\n");
+ clear_keyboard();
+ waiting_buffer_clear();
+ tapping_key = (keyrecord_t){};
+ }
+ }
+
+ // process waiting_buffer
+ if (!IS_NOEVENT(record.event) && waiting_buffer_head != waiting_buffer_tail) {
+ debug("---- action_exec: process waiting_buffer -----\n");
+ }
+ for (; waiting_buffer_tail != waiting_buffer_head; waiting_buffer_tail = (waiting_buffer_tail + 1) % WAITING_BUFFER_SIZE) {
+ if (process_tapping(&waiting_buffer[waiting_buffer_tail])) {
+ debug("processed: waiting_buffer["); debug_dec(waiting_buffer_tail); debug("] = ");
+ debug_record(waiting_buffer[waiting_buffer_tail]); debug("\n\n");
+ } else {
+ break;
+ }
+ }
+ if (!IS_NOEVENT(record.event)) {
+ debug("\n");
+ }
+}
+
+
+/* Tapping
+ *
+ * Rule: Tap key is typed(pressed and released) within TAPPING_TERM.
+ * (without interfering by typing other key)
+ */
+/* return true when key event is processed or consumed. */
+bool process_tapping(keyrecord_t *keyp)
+{
+ keyevent_t event = keyp->event;
+
+ // if tapping
+ if (IS_TAPPING_PRESSED()) {
+ if (WITHIN_TAPPING_TERM(event)) {
+ if (tapping_key.tap.count == 0) {
+ if (IS_TAPPING_KEY(event.key) && !event.pressed) {
+ // first tap!
+ debug("Tapping: First tap(0->1).\n");
+ tapping_key.tap.count = 1;
+ debug_tapping_key();
+ process_record(&tapping_key);
+
+ // copy tapping state
+ keyp->tap = tapping_key.tap;
+ // enqueue
+ return false;
+ }
+#if TAPPING_TERM >= 500
+ /* Process a key typed within TAPPING_TERM
+ * This can register the key before settlement of tapping,
+ * useful for long TAPPING_TERM but may prevent fast typing.
+ */
+ else if (IS_RELEASED(event) && waiting_buffer_typed(event)) {
+ debug("Tapping: End. No tap. Interfered by typing key\n");
+ process_record(&tapping_key);
+ tapping_key = (keyrecord_t){};
+ debug_tapping_key();
+ // enqueue
+ return false;
+ }
+#endif
+ /* Process release event of a key pressed before tapping starts
+ * Without this unexpected repeating will occur with having fast repeating setting
+ * https://github.com/tmk/tmk_keyboard/issues/60
+ */
+ else if (IS_RELEASED(event) && !waiting_buffer_typed(event)) {
+ // Modifier should be retained till end of this tapping.
+ action_t action = layer_switch_get_action(event.key);
+ switch (action.kind.id) {
+ case ACT_LMODS:
+ case ACT_RMODS:
+ if (action.key.mods && !action.key.code) return false;
+ if (IS_MOD(action.key.code)) return false;
+ break;
+ case ACT_LMODS_TAP:
+ case ACT_RMODS_TAP:
+ if (action.key.mods && keyp->tap.count == 0) return false;
+ if (IS_MOD(action.key.code)) return false;
+ break;
+ }
+ // Release of key should be process immediately.
+ debug("Tapping: release event of a key pressed before tapping\n");
+ process_record(keyp);
+ return true;
+ }
+ else {
+ // set interrupted flag when other key preesed during tapping
+ if (event.pressed) {
+ tapping_key.tap.interrupted = true;
+ }
+ // enqueue
+ return false;
+ }
+ }
+ // tap_count > 0
+ else {
+ if (IS_TAPPING_KEY(event.key) && !event.pressed) {
+ debug("Tapping: Tap release("); debug_dec(tapping_key.tap.count); debug(")\n");
+ keyp->tap = tapping_key.tap;
+ process_record(keyp);
+ tapping_key = *keyp;
+ debug_tapping_key();
+ return true;
+ }
+ else if (is_tap_key(event.key) && event.pressed) {
+ if (tapping_key.tap.count > 1) {
+ debug("Tapping: Start new tap with releasing last tap(>1).\n");
+ // unregister key
+ process_record(&(keyrecord_t){
+ .tap = tapping_key.tap,
+ .event.key = tapping_key.event.key,
+ .event.time = event.time,
+ .event.pressed = false
+ });
+ } else {
+ debug("Tapping: Start while last tap(1).\n");
+ }
+ tapping_key = *keyp;
+ waiting_buffer_scan_tap();
+ debug_tapping_key();
+ return true;
+ }
+ else {
+ if (!IS_NOEVENT(event)) {
+ debug("Tapping: key event while last tap(>0).\n");
+ }
+ process_record(keyp);
+ return true;
+ }
+ }
+ }
+ // after TAPPING_TERM
+ else {
+ if (tapping_key.tap.count == 0) {
+ debug("Tapping: End. Timeout. Not tap(0): ");
+ debug_event(event); debug("\n");
+ process_record(&tapping_key);
+ tapping_key = (keyrecord_t){};
+ debug_tapping_key();
+ return false;
+ } else {
+ if (IS_TAPPING_KEY(event.key) && !event.pressed) {
+ debug("Tapping: End. last timeout tap release(>0).");
+ keyp->tap = tapping_key.tap;
+ process_record(keyp);
+ tapping_key = (keyrecord_t){};
+ return true;
+ }
+ else if (is_tap_key(event.key) && event.pressed) {
+ if (tapping_key.tap.count > 1) {
+ debug("Tapping: Start new tap with releasing last timeout tap(>1).\n");
+ // unregister key
+ process_record(&(keyrecord_t){
+ .tap = tapping_key.tap,
+ .event.key = tapping_key.event.key,
+ .event.time = event.time,
+ .event.pressed = false
+ });
+ } else {
+ debug("Tapping: Start while last timeout tap(1).\n");
+ }
+ tapping_key = *keyp;
+ waiting_buffer_scan_tap();
+ debug_tapping_key();
+ return true;
+ }
+ else {
+ if (!IS_NOEVENT(event)) {
+ debug("Tapping: key event while last timeout tap(>0).\n");
+ }
+ process_record(keyp);
+ return true;
+ }
+ }
+ }
+ } else if (IS_TAPPING_RELEASED()) {
+ if (WITHIN_TAPPING_TERM(event)) {
+ if (event.pressed) {
+ if (IS_TAPPING_KEY(event.key)) {
+ if (!tapping_key.tap.interrupted && tapping_key.tap.count > 0) {
+ // sequential tap.
+ keyp->tap = tapping_key.tap;
+ if (keyp->tap.count < 15) keyp->tap.count += 1;
+ debug("Tapping: Tap press("); debug_dec(keyp->tap.count); debug(")\n");
+ process_record(keyp);
+ tapping_key = *keyp;
+ debug_tapping_key();
+ return true;
+ } else {
+ // FIX: start new tap again
+ tapping_key = *keyp;
+ return true;
+ }
+ } else if (is_tap_key(event.key)) {
+ // Sequential tap can be interfered with other tap key.
+ debug("Tapping: Start with interfering other tap.\n");
+ tapping_key = *keyp;
+ waiting_buffer_scan_tap();
+ debug_tapping_key();
+ return true;
+ } else {
+ // should none in buffer
+ // FIX: interrupted when other key is pressed
+ tapping_key.tap.interrupted = true;
+ process_record(keyp);
+ return true;
+ }
+ } else {
+ if (!IS_NOEVENT(event)) debug("Tapping: other key just after tap.\n") {};
+ process_record(keyp);
+ return true;
+ }
+ } else {
+ // FIX: process_aciton here?
+ // timeout. no sequential tap.
+ debug("Tapping: End(Timeout after releasing last tap): ");
+ debug_event(event); debug("\n");
+ tapping_key = (keyrecord_t){};
+ debug_tapping_key();
+ return false;
+ }
+ }
+ // not tapping state
+ else {
+ if (event.pressed && is_tap_key(event.key)) {
+ debug("Tapping: Start(Press tap key).\n");
+ tapping_key = *keyp;
+ waiting_buffer_scan_tap();
+ debug_tapping_key();
+ return true;
+ } else {
+ process_record(keyp);
+ return true;
+ }
+ }
+}
+
+
+/*
+ * Waiting buffer
+ */
+bool waiting_buffer_enq(keyrecord_t record)
+{
+ if (IS_NOEVENT(record.event)) {
+ return true;
+ }
+
+ if ((waiting_buffer_head + 1) % WAITING_BUFFER_SIZE == waiting_buffer_tail) {
+ debug("waiting_buffer_enq: Over flow.\n");
+ return false;
+ }
+
+ waiting_buffer[waiting_buffer_head] = record;
+ waiting_buffer_head = (waiting_buffer_head + 1) % WAITING_BUFFER_SIZE;
+
+ debug("waiting_buffer_enq: "); debug_waiting_buffer();
+ return true;
+}
+
+void waiting_buffer_clear(void)
+{
+ waiting_buffer_head = 0;
+ waiting_buffer_tail = 0;
+}
+
+bool waiting_buffer_typed(keyevent_t event)
+{
+ for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
+ if (KEYEQ(event.key, waiting_buffer[i].event.key) && event.pressed != waiting_buffer[i].event.pressed) {
+ return true;
+ }
+ }
+ return false;
+}
+
+__attribute__((unused))
+bool waiting_buffer_has_anykey_pressed(void)
+{
+ for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
+ if (waiting_buffer[i].event.pressed) return true;
+ }
+ return false;
+}
+
+/* scan buffer for tapping */
+void waiting_buffer_scan_tap(void)
+{
+ // tapping already is settled
+ if (tapping_key.tap.count > 0) return;
+ // invalid state: tapping_key released && tap.count == 0
+ if (!tapping_key.event.pressed) return;
+
+ for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
+ if (IS_TAPPING_KEY(waiting_buffer[i].event.key) &&
+ !waiting_buffer[i].event.pressed &&
+ WITHIN_TAPPING_TERM(waiting_buffer[i].event)) {
+ tapping_key.tap.count = 1;
+ waiting_buffer[i].tap.count = 1;
+ process_record(&tapping_key);
+
+ debug("waiting_buffer_scan_tap: found at ["); debug_dec(i); debug("]\n");
+ debug_waiting_buffer();
+ return;
+ }
+ }
+}
+
+
+/*
+ * debug print
+ */
+static void debug_tapping_key(void)
+{
+ debug("TAPPING_KEY="); debug_record(tapping_key); debug("\n");
+}
+
+static void debug_waiting_buffer(void)
+{
+ debug("{ ");
+ for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
+ debug("["); debug_dec(i); debug("]="); debug_record(waiting_buffer[i]); debug(" ");
+ }
+ debug("}\n");
+}
+
+#endif
diff --git a/tmk_core/common/action_tapping.h b/tmk_core/common/action_tapping.h
new file mode 100644
index 000000000..9b42d50dc
--- /dev/null
+++ b/tmk_core/common/action_tapping.h
@@ -0,0 +1,39 @@
+/*
+Copyright 2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef ACTION_TAPPING_H
+#define ACTION_TAPPING_H
+
+
+
+/* period of tapping(ms) */
+#ifndef TAPPING_TERM
+#define TAPPING_TERM 200
+#endif
+
+/* tap count needed for toggling a feature */
+#ifndef TAPPING_TOGGLE
+#define TAPPING_TOGGLE 5
+#endif
+
+#define WAITING_BUFFER_SIZE 8
+
+
+#ifndef NO_ACTION_TAPPING
+void action_tapping_process(keyrecord_t record);
+#endif
+
+#endif
diff --git a/tmk_core/common/action_util.c b/tmk_core/common/action_util.c
new file mode 100644
index 000000000..61ff202be
--- /dev/null
+++ b/tmk_core/common/action_util.c
@@ -0,0 +1,378 @@
+/*
+Copyright 2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "host.h"
+#include "report.h"
+#include "debug.h"
+#include "action_util.h"
+#include "action_layer.h"
+#include "timer.h"
+
+static inline void add_key_byte(uint8_t code);
+static inline void del_key_byte(uint8_t code);
+#ifdef NKRO_ENABLE
+static inline void add_key_bit(uint8_t code);
+static inline void del_key_bit(uint8_t code);
+#endif
+
+static uint8_t real_mods = 0;
+static uint8_t weak_mods = 0;
+static uint8_t macro_mods = 0;
+
+#ifdef USB_6KRO_ENABLE
+#define RO_ADD(a, b) ((a + b) % KEYBOARD_REPORT_KEYS)
+#define RO_SUB(a, b) ((a - b + KEYBOARD_REPORT_KEYS) % KEYBOARD_REPORT_KEYS)
+#define RO_INC(a) RO_ADD(a, 1)
+#define RO_DEC(a) RO_SUB(a, 1)
+static int8_t cb_head = 0;
+static int8_t cb_tail = 0;
+static int8_t cb_count = 0;
+#endif
+
+// TODO: pointer variable is not needed
+//report_keyboard_t keyboard_report = {};
+report_keyboard_t *keyboard_report = &(report_keyboard_t){};
+
+#ifndef NO_ACTION_ONESHOT
+static int8_t oneshot_mods = 0;
+static int8_t oneshot_locked_mods = 0;
+int8_t get_oneshot_locked_mods(void) { return oneshot_locked_mods; }
+void set_oneshot_locked_mods(int8_t mods) { oneshot_locked_mods = mods; }
+void clear_oneshot_locked_mods(void) { oneshot_locked_mods = 0; }
+#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
+static int16_t oneshot_time = 0;
+inline bool has_oneshot_mods_timed_out() {
+ return TIMER_DIFF_16(timer_read(), oneshot_time) >= ONESHOT_TIMEOUT;
+}
+#endif
+#endif
+
+/* oneshot layer */
+#ifndef NO_ACTION_ONESHOT
+/* oneshot_layer_data bits
+* LLLL LSSS
+* where:
+* L => are layer bits
+* S => oneshot state bits
+*/
+static int8_t oneshot_layer_data = 0;
+
+inline uint8_t get_oneshot_layer(void) { return oneshot_layer_data >> 3; }
+inline uint8_t get_oneshot_layer_state(void) { return oneshot_layer_data & 0b111; }
+
+#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
+static int16_t oneshot_layer_time = 0;
+inline bool has_oneshot_layer_timed_out() {
+ return TIMER_DIFF_16(timer_read(), oneshot_layer_time) >= ONESHOT_TIMEOUT &&
+ !(get_oneshot_layer_state() & ONESHOT_TOGGLED);
+}
+#endif
+
+/* Oneshot layer */
+void set_oneshot_layer(uint8_t layer, uint8_t state)
+{
+ oneshot_layer_data = layer << 3 | state;
+ layer_on(layer);
+#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
+ oneshot_layer_time = timer_read();
+#endif
+}
+void reset_oneshot_layer(void) {
+ oneshot_layer_data = 0;
+#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
+ oneshot_layer_time = 0;
+#endif
+}
+void clear_oneshot_layer_state(oneshot_fullfillment_t state)
+{
+ uint8_t start_state = oneshot_layer_data;
+ oneshot_layer_data &= ~state;
+ if (!get_oneshot_layer_state() && start_state != oneshot_layer_data) {
+ layer_off(get_oneshot_layer());
+#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
+ oneshot_layer_time = 0;
+#endif
+ }
+}
+bool is_oneshot_layer_active(void)
+{
+ return get_oneshot_layer_state();
+}
+#endif
+
+void send_keyboard_report(void) {
+ keyboard_report->mods = real_mods;
+ keyboard_report->mods |= weak_mods;
+ keyboard_report->mods |= macro_mods;
+#ifndef NO_ACTION_ONESHOT
+ if (oneshot_mods) {
+#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
+ if (has_oneshot_mods_timed_out()) {
+ dprintf("Oneshot: timeout\n");
+ clear_oneshot_mods();
+ }
+#endif
+ keyboard_report->mods |= oneshot_mods;
+ if (has_anykey()) {
+ clear_oneshot_mods();
+ }
+ }
+
+#endif
+ host_keyboard_send(keyboard_report);
+}
+
+/* key */
+void add_key(uint8_t key)
+{
+#ifdef NKRO_ENABLE
+ if (keyboard_protocol && keyboard_nkro) {
+ add_key_bit(key);
+ return;
+ }
+#endif
+ add_key_byte(key);
+}
+
+void del_key(uint8_t key)
+{
+#ifdef NKRO_ENABLE
+ if (keyboard_protocol && keyboard_nkro) {
+ del_key_bit(key);
+ return;
+ }
+#endif
+ del_key_byte(key);
+}
+
+void clear_keys(void)
+{
+ // not clear mods
+ for (int8_t i = 1; i < KEYBOARD_REPORT_SIZE; i++) {
+ keyboard_report->raw[i] = 0;
+ }
+}
+
+
+/* modifier */
+uint8_t get_mods(void) { return real_mods; }
+void add_mods(uint8_t mods) { real_mods |= mods; }
+void del_mods(uint8_t mods) { real_mods &= ~mods; }
+void set_mods(uint8_t mods) { real_mods = mods; }
+void clear_mods(void) { real_mods = 0; }
+
+/* weak modifier */
+uint8_t get_weak_mods(void) { return weak_mods; }
+void add_weak_mods(uint8_t mods) { weak_mods |= mods; }
+void del_weak_mods(uint8_t mods) { weak_mods &= ~mods; }
+void set_weak_mods(uint8_t mods) { weak_mods = mods; }
+void clear_weak_mods(void) { weak_mods = 0; }
+
+/* macro modifier */
+uint8_t get_macro_mods(void) { return macro_mods; }
+void add_macro_mods(uint8_t mods) { macro_mods |= mods; }
+void del_macro_mods(uint8_t mods) { macro_mods &= ~mods; }
+void set_macro_mods(uint8_t mods) { macro_mods = mods; }
+void clear_macro_mods(void) { macro_mods = 0; }
+
+/* Oneshot modifier */
+#ifndef NO_ACTION_ONESHOT
+void set_oneshot_mods(uint8_t mods)
+{
+ oneshot_mods = mods;
+#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
+ oneshot_time = timer_read();
+#endif
+}
+void clear_oneshot_mods(void)
+{
+ oneshot_mods = 0;
+#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
+ oneshot_time = 0;
+#endif
+}
+uint8_t get_oneshot_mods(void)
+{
+ return oneshot_mods;
+}
+#endif
+
+/*
+ * inspect keyboard state
+ */
+uint8_t has_anykey(void)
+{
+ uint8_t cnt = 0;
+ for (uint8_t i = 1; i < KEYBOARD_REPORT_SIZE; i++) {
+ if (keyboard_report->raw[i])
+ cnt++;
+ }
+ return cnt;
+}
+
+uint8_t has_anymod(void)
+{
+ return bitpop(real_mods);
+}
+
+uint8_t get_first_key(void)
+{
+#ifdef NKRO_ENABLE
+ if (keyboard_protocol && keyboard_nkro) {
+ uint8_t i = 0;
+ for (; i < KEYBOARD_REPORT_BITS && !keyboard_report->nkro.bits[i]; i++)
+ ;
+ return i<<3 | biton(keyboard_report->nkro.bits[i]);
+ }
+#endif
+#ifdef USB_6KRO_ENABLE
+ uint8_t i = cb_head;
+ do {
+ if (keyboard_report->keys[i] != 0) {
+ break;
+ }
+ i = RO_INC(i);
+ } while (i != cb_tail);
+ return keyboard_report->keys[i];
+#else
+ return keyboard_report->keys[0];
+#endif
+}
+
+
+
+/* local functions */
+static inline void add_key_byte(uint8_t code)
+{
+#ifdef USB_6KRO_ENABLE
+ int8_t i = cb_head;
+ int8_t empty = -1;
+ if (cb_count) {
+ do {
+ if (keyboard_report->keys[i] == code) {
+ return;
+ }
+ if (empty == -1 && keyboard_report->keys[i] == 0) {
+ empty = i;
+ }
+ i = RO_INC(i);
+ } while (i != cb_tail);
+ if (i == cb_tail) {
+ if (cb_tail == cb_head) {
+ // buffer is full
+ if (empty == -1) {
+ // pop head when has no empty space
+ cb_head = RO_INC(cb_head);
+ cb_count--;
+ }
+ else {
+ // left shift when has empty space
+ uint8_t offset = 1;
+ i = RO_INC(empty);
+ do {
+ if (keyboard_report->keys[i] != 0) {
+ keyboard_report->keys[empty] = keyboard_report->keys[i];
+ keyboard_report->keys[i] = 0;
+ empty = RO_INC(empty);
+ }
+ else {
+ offset++;
+ }
+ i = RO_INC(i);
+ } while (i != cb_tail);
+ cb_tail = RO_SUB(cb_tail, offset);
+ }
+ }
+ }
+ }
+ // add to tail
+ keyboard_report->keys[cb_tail] = code;
+ cb_tail = RO_INC(cb_tail);
+ cb_count++;
+#else
+ int8_t i = 0;
+ int8_t empty = -1;
+ for (; i < KEYBOARD_REPORT_KEYS; i++) {
+ if (keyboard_report->keys[i] == code) {
+ break;
+ }
+ if (empty == -1 && keyboard_report->keys[i] == 0) {
+ empty = i;
+ }
+ }
+ if (i == KEYBOARD_REPORT_KEYS) {
+ if (empty != -1) {
+ keyboard_report->keys[empty] = code;
+ }
+ }
+#endif
+}
+
+static inline void del_key_byte(uint8_t code)
+{
+#ifdef USB_6KRO_ENABLE
+ uint8_t i = cb_head;
+ if (cb_count) {
+ do {
+ if (keyboard_report->keys[i] == code) {
+ keyboard_report->keys[i] = 0;
+ cb_count--;
+ if (cb_count == 0) {
+ // reset head and tail
+ cb_tail = cb_head = 0;
+ }
+ if (i == RO_DEC(cb_tail)) {
+ // left shift when next to tail
+ do {
+ cb_tail = RO_DEC(cb_tail);
+ if (keyboard_report->keys[RO_DEC(cb_tail)] != 0) {
+ break;
+ }
+ } while (cb_tail != cb_head);
+ }
+ break;
+ }
+ i = RO_INC(i);
+ } while (i != cb_tail);
+ }
+#else
+ for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
+ if (keyboard_report->keys[i] == code) {
+ keyboard_report->keys[i] = 0;
+ }
+ }
+#endif
+}
+
+#ifdef NKRO_ENABLE
+static inline void add_key_bit(uint8_t code)
+{
+ if ((code>>3) < KEYBOARD_REPORT_BITS) {
+ keyboard_report->nkro.bits[code>>3] |= 1<<(code&7);
+ } else {
+ dprintf("add_key_bit: can't add: %02X\n", code);
+ }
+}
+
+static inline void del_key_bit(uint8_t code)
+{
+ if ((code>>3) < KEYBOARD_REPORT_BITS) {
+ keyboard_report->nkro.bits[code>>3] &= ~(1<<(code&7));
+ } else {
+ dprintf("del_key_bit: can't del: %02X\n", code);
+ }
+}
+#endif
diff --git a/tmk_core/common/action_util.h b/tmk_core/common/action_util.h
new file mode 100644
index 000000000..dd0c4c2bf
--- /dev/null
+++ b/tmk_core/common/action_util.h
@@ -0,0 +1,93 @@
+/*
+Copyright 2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef ACTION_UTIL_H
+#define ACTION_UTIL_H
+
+#include <stdint.h>
+#include "report.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern report_keyboard_t *keyboard_report;
+
+void send_keyboard_report(void);
+
+/* key */
+void add_key(uint8_t key);
+void del_key(uint8_t key);
+void clear_keys(void);
+
+/* modifier */
+uint8_t get_mods(void);
+void add_mods(uint8_t mods);
+void del_mods(uint8_t mods);
+void set_mods(uint8_t mods);
+void clear_mods(void);
+
+/* weak modifier */
+uint8_t get_weak_mods(void);
+void add_weak_mods(uint8_t mods);
+void del_weak_mods(uint8_t mods);
+void set_weak_mods(uint8_t mods);
+void clear_weak_mods(void);
+
+/* macro modifier */
+uint8_t get_macro_mods(void);
+void add_macro_mods(uint8_t mods);
+void del_macro_mods(uint8_t mods);
+void set_macro_mods(uint8_t mods);
+void clear_macro_mods(void);
+
+/* oneshot modifier */
+void set_oneshot_mods(uint8_t mods);
+uint8_t get_oneshot_mods(void);
+void clear_oneshot_mods(void);
+void oneshot_toggle(void);
+void oneshot_enable(void);
+void oneshot_disable(void);
+bool has_oneshot_mods_timed_out(void);
+
+int8_t get_oneshot_locked_mods(void);
+void set_oneshot_locked_mods(int8_t mods);
+void clear_oneshot_locked_mods(void);
+
+typedef enum {
+ ONESHOT_PRESSED = 0b01,
+ ONESHOT_OTHER_KEY_PRESSED = 0b10,
+ ONESHOT_START = 0b11,
+ ONESHOT_TOGGLED = 0b100
+} oneshot_fullfillment_t;
+void set_oneshot_layer(uint8_t layer, uint8_t state);
+uint8_t get_oneshot_layer(void);
+void clear_oneshot_layer_state(oneshot_fullfillment_t state);
+void reset_oneshot_layer(void);
+bool is_oneshot_layer_active(void);
+uint8_t get_oneshot_layer_state(void);
+bool has_oneshot_layer_timed_out(void);
+
+/* inspect */
+uint8_t has_anykey(void);
+uint8_t has_anymod(void);
+uint8_t get_first_key(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/tmk_core/common/avr/bootloader.c b/tmk_core/common/avr/bootloader.c
new file mode 100644
index 000000000..7c744e8c7
--- /dev/null
+++ b/tmk_core/common/avr/bootloader.c
@@ -0,0 +1,185 @@
+#include <stdint.h>
+#include <stdbool.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/wdt.h>
+#include <util/delay.h>
+#include "bootloader.h"
+
+#ifdef PROTOCOL_LUFA
+#include <LUFA/Drivers/USB/USB.h>
+#endif
+
+
+/* Bootloader Size in *bytes*
+ *
+ * AVR Boot section size are defined by setting BOOTSZ fuse in fact. Consult with your MCU datasheet.
+ * Note that 'Word'(2 bytes) size and address are used in datasheet while TMK uses 'Byte'.
+ *
+ *
+ * Size of Bootloaders in bytes:
+ * Atmel DFU loader(ATmega32U4) 4096
+ * Atmel DFU loader(AT90USB128) 8192
+ * LUFA bootloader(ATmega32U4) 4096
+ * Arduino Caterina(ATmega32U4) 4096
+ * USBaspLoader(ATmega***) 2048
+ * Teensy halfKay(ATmega32U4) 512
+ * Teensy++ halfKay(AT90USB128) 1024
+ *
+ *
+ * AVR Boot section is located at the end of Flash memory like the followings.
+ *
+ *
+ * byte Atmel/LUFA(ATMega32u4) byte Atmel(AT90SUB128)
+ * 0x0000 +---------------+ 0x00000 +---------------+
+ * | | | |
+ * | | | |
+ * | Application | | Application |
+ * | | | |
+ * = = = =
+ * | | 32KB-4KB | | 128KB-8KB
+ * 0x6000 +---------------+ 0x1FC00 +---------------+
+ * | Bootloader | 4KB | Bootloader | 8KB
+ * 0x7FFF +---------------+ 0x1FFFF +---------------+
+ *
+ *
+ * byte Teensy(ATMega32u4) byte Teensy++(AT90SUB128)
+ * 0x0000 +---------------+ 0x00000 +---------------+
+ * | | | |
+ * | | | |
+ * | Application | | Application |
+ * | | | |
+ * = = = =
+ * | | 32KB-512B | | 128KB-1KB
+ * 0x7E00 +---------------+ 0x1FC00 +---------------+
+ * | Bootloader | 512B | Bootloader | 1KB
+ * 0x7FFF +---------------+ 0x1FFFF +---------------+
+ */
+#ifndef BOOTLOADER_SIZE
+#warning To use bootloader_jump() you need to define BOOTLOADER_SIZE in config.h.
+#define BOOTLOADER_SIZE 4096
+#endif
+
+#define FLASH_SIZE (FLASHEND + 1L)
+#define BOOTLOADER_START (FLASH_SIZE - BOOTLOADER_SIZE)
+
+
+/*
+ * Entering the Bootloader via Software
+ * http://www.fourwalledcubicle.com/files/LUFA/Doc/120730/html/_page__software_bootloader_start.html
+ */
+#define BOOTLOADER_RESET_KEY 0xB007B007
+uint32_t reset_key __attribute__ ((section (".noinit")));
+
+/* initialize MCU status by watchdog reset */
+void bootloader_jump(void) {
+#ifdef PROTOCOL_LUFA
+ USB_Disable();
+ cli();
+ _delay_ms(2000);
+#endif
+
+#ifdef PROTOCOL_PJRC
+ cli();
+ UDCON = 1;
+ USBCON = (1<<FRZCLK);
+ UCSR1B = 0;
+ _delay_ms(5);
+#endif
+
+ // watchdog reset
+ reset_key = BOOTLOADER_RESET_KEY;
+ wdt_enable(WDTO_250MS);
+ for (;;);
+}
+
+
+/* this runs before main() */
+void bootloader_jump_after_watchdog_reset(void) __attribute__ ((used, naked, section (".init3")));
+void bootloader_jump_after_watchdog_reset(void)
+{
+ if ((MCUSR & (1<<WDRF)) && reset_key == BOOTLOADER_RESET_KEY) {
+ reset_key = 0;
+
+ // My custom USBasploader requires this to come up.
+ MCUSR = 0;
+
+ // Seems like Teensy halfkay loader requires clearing WDRF and disabling watchdog.
+ MCUSR &= ~(1<<WDRF);
+ wdt_disable();
+
+ // This is compled into 'icall', address should be in word unit, not byte.
+ ((void (*)(void))(BOOTLOADER_START/2))();
+ }
+}
+
+
+#if 0
+/* Jumping To The Bootloader
+ * http://www.pjrc.com/teensy/jump_to_bootloader.html
+ *
+ * This method doen't work when using LUFA. idk why.
+ * - needs to initialize more regisers or interrupt setting?
+ */
+void bootloader_jump(void) {
+#ifdef PROTOCOL_LUFA
+ USB_Disable();
+ cli();
+ _delay_ms(2000);
+#endif
+
+#ifdef PROTOCOL_PJRC
+ cli();
+ UDCON = 1;
+ USBCON = (1<<FRZCLK);
+ UCSR1B = 0;
+ _delay_ms(5);
+#endif
+
+ /*
+ * Initialize
+ */
+#if defined(__AVR_AT90USB162__)
+ EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0;
+ TIMSK0 = 0; TIMSK1 = 0; UCSR1B = 0;
+ DDRB = 0; DDRC = 0; DDRD = 0;
+ PORTB = 0; PORTC = 0; PORTD = 0;
+#elif defined(__AVR_ATmega32U4__)
+ EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
+ TIMSK0 = 0; TIMSK1 = 0; TIMSK3 = 0; TIMSK4 = 0; UCSR1B = 0; TWCR = 0;
+ DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0; TWCR = 0;
+ PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
+#elif defined(__AVR_AT90USB646__)
+ EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
+ TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0; UCSR1B = 0; TWCR = 0;
+ DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0;
+ PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
+#elif defined(__AVR_AT90USB1286__)
+ EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
+ TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0; UCSR1B = 0; TWCR = 0;
+ DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0;
+ PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
+#endif
+
+ /*
+ * USBaspLoader
+ */
+#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
+ // This makes custom USBasploader come up.
+ MCUSR = 0;
+
+ // initialize ports
+ PORTB = 0; PORTC= 0; PORTD = 0;
+ DDRB = 0; DDRC= 0; DDRD = 0;
+
+ // disable interrupts
+ EIMSK = 0; EECR = 0; SPCR = 0;
+ ACSR = 0; SPMCSR = 0; WDTCSR = 0; PCICR = 0;
+ TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0;
+ ADCSRA = 0; TWCR = 0; UCSR0B = 0;
+#endif
+
+ // This is compled into 'icall', address should be in word unit, not byte.
+ ((void (*)(void))(BOOTLOADER_START/2))();
+}
+#endif
diff --git a/tmk_core/common/avr/sleep_led.c b/tmk_core/common/avr/sleep_led.c
new file mode 100644
index 000000000..dab3eb0f3
--- /dev/null
+++ b/tmk_core/common/avr/sleep_led.c
@@ -0,0 +1,95 @@
+#include <stdint.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/pgmspace.h>
+#include "led.h"
+#include "sleep_led.h"
+
+/* Software PWM
+ * ______ ______ __
+ * | ON |___OFF___| ON |___OFF___| ....
+ * |<-------------->|<-------------->|<- ....
+ * PWM period PWM period
+ *
+ * 256 interrupts/period[resolution]
+ * 64 periods/second[frequency]
+ * 256*64 interrupts/second
+ * F_CPU/(256*64) clocks/interrupt
+ */
+#define SLEEP_LED_TIMER_TOP F_CPU/(256*64)
+
+void sleep_led_init(void)
+{
+ /* Timer1 setup */
+ /* CTC mode */
+ TCCR1B |= _BV(WGM12);
+ /* Clock selelct: clk/1 */
+ TCCR1B |= _BV(CS10);
+ /* Set TOP value */
+ uint8_t sreg = SREG;
+ cli();
+ OCR1AH = (SLEEP_LED_TIMER_TOP>>8)&0xff;
+ OCR1AL = SLEEP_LED_TIMER_TOP&0xff;
+ SREG = sreg;
+}
+
+void sleep_led_enable(void)
+{
+ /* Enable Compare Match Interrupt */
+ TIMSK1 |= _BV(OCIE1A);
+}
+
+void sleep_led_disable(void)
+{
+ /* Disable Compare Match Interrupt */
+ TIMSK1 &= ~_BV(OCIE1A);
+}
+
+void sleep_led_toggle(void)
+{
+ /* Disable Compare Match Interrupt */
+ TIMSK1 ^= _BV(OCIE1A);
+}
+
+
+/* Breathing Sleep LED brighness(PWM On period) table
+ * (64[steps] * 4[duration]) / 64[PWM periods/s] = 4 second breath cycle
+ *
+ * http://www.wolframalpha.com/input/?i=%28sin%28+x%2F64*pi%29**8+*+255%2C+x%3D0+to+63
+ * (0..63).each {|x| p ((sin(x/64.0*PI)**8)*255).to_i }
+ */
+static const uint8_t breathing_table[64] PROGMEM = {
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 6, 10,
+15, 23, 32, 44, 58, 74, 93, 113, 135, 157, 179, 199, 218, 233, 245, 252,
+255, 252, 245, 233, 218, 199, 179, 157, 135, 113, 93, 74, 58, 44, 32, 23,
+15, 10, 6, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+ISR(TIMER1_COMPA_vect)
+{
+ /* Software PWM
+ * timer:1111 1111 1111 1111
+ * \_____/\/ \_______/____ count(0-255)
+ * \ \______________ duration of step(4)
+ * \__________________ index of step table(0-63)
+ */
+ static union {
+ uint16_t row;
+ struct {
+ uint8_t count:8;
+ uint8_t duration:2;
+ uint8_t index:6;
+ } pwm;
+ } timer = { .row = 0 };
+
+ timer.row++;
+
+ // LED on
+ if (timer.pwm.count == 0) {
+ led_set(1<<USB_LED_CAPS_LOCK);
+ }
+ // LED off
+ if (timer.pwm.count == pgm_read_byte(&breathing_table[timer.pwm.index])) {
+ led_set(0);
+ }
+}
diff --git a/tmk_core/common/avr/suspend.c b/tmk_core/common/avr/suspend.c
new file mode 100644
index 000000000..8a7272bbc
--- /dev/null
+++ b/tmk_core/common/avr/suspend.c
@@ -0,0 +1,148 @@
+#include <stdbool.h>
+#include <avr/sleep.h>
+#include <avr/wdt.h>
+#include <avr/interrupt.h>
+#include "matrix.h"
+#include "action.h"
+#include "backlight.h"
+#include "suspend_avr.h"
+#include "suspend.h"
+#include "timer.h"
+#include "led.h"
+
+#ifdef PROTOCOL_LUFA
+ #include "lufa.h"
+#endif
+
+#ifdef AUDIO_ENABLE
+ #include "audio.h"
+#endif /* AUDIO_ENABLE */
+
+
+
+#define wdt_intr_enable(value) \
+__asm__ __volatile__ ( \
+ "in __tmp_reg__,__SREG__" "\n\t" \
+ "cli" "\n\t" \
+ "wdr" "\n\t" \
+ "sts %0,%1" "\n\t" \
+ "out __SREG__,__tmp_reg__" "\n\t" \
+ "sts %0,%2" "\n\t" \
+ : /* no outputs */ \
+ : "M" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), \
+ "r" (_BV(_WD_CHANGE_BIT) | _BV(WDE)), \
+ "r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) | \
+ _BV(WDIE) | (value & 0x07)) ) \
+ : "r0" \
+)
+
+
+void suspend_idle(uint8_t time)
+{
+ cli();
+ set_sleep_mode(SLEEP_MODE_IDLE);
+ sleep_enable();
+ sei();
+ sleep_cpu();
+ sleep_disable();
+}
+
+/* Power down MCU with watchdog timer
+ * wdto: watchdog timer timeout defined in <avr/wdt.h>
+ * WDTO_15MS
+ * WDTO_30MS
+ * WDTO_60MS
+ * WDTO_120MS
+ * WDTO_250MS
+ * WDTO_500MS
+ * WDTO_1S
+ * WDTO_2S
+ * WDTO_4S
+ * WDTO_8S
+ */
+static uint8_t wdt_timeout = 0;
+static void power_down(uint8_t wdto)
+{
+#ifdef PROTOCOL_LUFA
+ if (USB_DeviceState == DEVICE_STATE_Configured) return;
+#endif
+ wdt_timeout = wdto;
+
+ // Watchdog Interrupt Mode
+ wdt_intr_enable(wdto);
+
+#ifdef BACKLIGHT_ENABLE
+ backlight_set(0);
+#endif
+
+ // Turn off LED indicators
+ led_set(0);
+
+ #ifdef AUDIO_ENABLE
+ // This sometimes disables the start-up noise, so it's been disabled
+ // stop_all_notes();
+ #endif /* AUDIO_ENABLE */
+
+ // TODO: more power saving
+ // See PicoPower application note
+ // - I/O port input with pullup
+ // - prescale clock
+ // - BOD disable
+ // - Power Reduction Register PRR
+ set_sleep_mode(SLEEP_MODE_PWR_DOWN);
+ sleep_enable();
+ sei();
+ sleep_cpu();
+ sleep_disable();
+
+ // Disable watchdog after sleep
+ wdt_disable();
+}
+
+void suspend_power_down(void)
+{
+ power_down(WDTO_15MS);
+}
+
+__attribute__ ((weak)) void matrix_power_up(void) {}
+__attribute__ ((weak)) void matrix_power_down(void) {}
+bool suspend_wakeup_condition(void)
+{
+#ifdef BACKLIGHT_ENABLE
+ backlight_set(0);
+#endif
+ matrix_power_up();
+ matrix_scan();
+ matrix_power_down();
+ for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
+ if (matrix_get_row(r)) return true;
+ }
+ return false;
+}
+
+// run immediately after wakeup
+void suspend_wakeup_init(void)
+{
+ // clear keyboard state
+ clear_keyboard();
+#ifdef BACKLIGHT_ENABLE
+ backlight_set(0);
+ backlight_init();
+#endif
+led_set(host_keyboard_leds());
+}
+
+#ifndef NO_SUSPEND_POWER_DOWN
+/* watchdog timeout */
+ISR(WDT_vect)
+{
+ // compensate timer for sleep
+ switch (wdt_timeout) {
+ case WDTO_15MS:
+ timer_count += 15 + 2; // WDTO_15MS + 2(from observation)
+ break;
+ default:
+ ;
+ }
+}
+#endif
diff --git a/tmk_core/common/avr/suspend_avr.h b/tmk_core/common/avr/suspend_avr.h
new file mode 100644
index 000000000..357102da4
--- /dev/null
+++ b/tmk_core/common/avr/suspend_avr.h
@@ -0,0 +1,27 @@
+#ifndef SUSPEND_AVR_H
+#define SUSPEND_AVR_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <avr/sleep.h>
+#include <avr/wdt.h>
+#include <avr/interrupt.h>
+
+
+#define wdt_intr_enable(value) \
+__asm__ __volatile__ ( \
+ "in __tmp_reg__,__SREG__" "\n\t" \
+ "cli" "\n\t" \
+ "wdr" "\n\t" \
+ "sts %0,%1" "\n\t" \
+ "out __SREG__,__tmp_reg__" "\n\t" \
+ "sts %0,%2" "\n\t" \
+ : /* no outputs */ \
+ : "M" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), \
+ "r" (_BV(_WD_CHANGE_BIT) | _BV(WDE)), \
+ "r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) | \
+ _BV(WDIE) | (value & 0x07)) ) \
+ : "r0" \
+)
+
+#endif
diff --git a/tmk_core/common/avr/timer.c b/tmk_core/common/avr/timer.c
new file mode 100644
index 000000000..292b41c3a
--- /dev/null
+++ b/tmk_core/common/avr/timer.c
@@ -0,0 +1,117 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <stdint.h>
+#include "timer_avr.h"
+#include "timer.h"
+
+
+// counter resolution 1ms
+// NOTE: union { uint32_t timer32; struct { uint16_t dummy; uint16_t timer16; }}
+volatile uint32_t timer_count = 0;
+
+void timer_init(void)
+{
+ // Timer0 CTC mode
+ TCCR0A = 0x02;
+
+#if TIMER_PRESCALER == 1
+ TCCR0B = 0x01;
+#elif TIMER_PRESCALER == 8
+ TCCR0B = 0x02;
+#elif TIMER_PRESCALER == 64
+ TCCR0B = 0x03;
+#elif TIMER_PRESCALER == 256
+ TCCR0B = 0x04;
+#elif TIMER_PRESCALER == 1024
+ TCCR0B = 0x05;
+#else
+# error "Timer prescaler value is NOT vaild."
+#endif
+
+ OCR0A = TIMER_RAW_TOP;
+ TIMSK0 = (1<<OCIE0A);
+}
+
+inline
+void timer_clear(void)
+{
+ uint8_t sreg = SREG;
+ cli();
+ timer_count = 0;
+ SREG = sreg;
+}
+
+inline
+uint16_t timer_read(void)
+{
+ uint32_t t;
+
+ uint8_t sreg = SREG;
+ cli();
+ t = timer_count;
+ SREG = sreg;
+
+ return (t & 0xFFFF);
+}
+
+inline
+uint32_t timer_read32(void)
+{
+ uint32_t t;
+
+ uint8_t sreg = SREG;
+ cli();
+ t = timer_count;
+ SREG = sreg;
+
+ return t;
+}
+
+inline
+uint16_t timer_elapsed(uint16_t last)
+{
+ uint32_t t;
+
+ uint8_t sreg = SREG;
+ cli();
+ t = timer_count;
+ SREG = sreg;
+
+ return TIMER_DIFF_16((t & 0xFFFF), last);
+}
+
+inline
+uint32_t timer_elapsed32(uint32_t last)
+{
+ uint32_t t;
+
+ uint8_t sreg = SREG;
+ cli();
+ t = timer_count;
+ SREG = sreg;
+
+ return TIMER_DIFF_32(t, last);
+}
+
+// excecuted once per 1ms.(excess for just timer count?)
+ISR(TIMER0_COMPA_vect)
+{
+ timer_count++;
+}
diff --git a/tmk_core/common/avr/timer_avr.h b/tmk_core/common/avr/timer_avr.h
new file mode 100644
index 000000000..0e85eb101
--- /dev/null
+++ b/tmk_core/common/avr/timer_avr.h
@@ -0,0 +1,42 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef TIMER_AVR_H
+#define TIMER_AVR_H 1
+
+#include <stdint.h>
+
+#ifndef TIMER_PRESCALER
+# if F_CPU > 16000000
+# define TIMER_PRESCALER 256
+# elif F_CPU > 2000000
+# define TIMER_PRESCALER 64
+# elif F_CPU > 250000
+# define TIMER_PRESCALER 8
+# else
+# define TIMER_PRESCALER 1
+# endif
+#endif
+#define TIMER_RAW_FREQ (F_CPU/TIMER_PRESCALER)
+#define TIMER_RAW TCNT0
+#define TIMER_RAW_TOP (TIMER_RAW_FREQ/1000)
+
+#if (TIMER_RAW_TOP > 255)
+# error "Timer0 can't count 1ms at this clock freq. Use larger prescaler."
+#endif
+
+#endif
diff --git a/tmk_core/common/avr/xprintf.S b/tmk_core/common/avr/xprintf.S
new file mode 100644
index 000000000..0cec70ce2
--- /dev/null
+++ b/tmk_core/common/avr/xprintf.S
@@ -0,0 +1,500 @@
+;---------------------------------------------------------------------------;
+; Extended itoa, puts, printf and atoi (C)ChaN, 2011
+;---------------------------------------------------------------------------;
+
+ // Base size is 152 bytes
+#define CR_CRLF 0 // Convert \n to \r\n (+10 bytes)
+#define USE_XPRINTF 1 // Enable xprintf function (+194 bytes)
+#define USE_XSPRINTF 0 // Add xsprintf function (+78 bytes)
+#define USE_XFPRINTF 0 // Add xfprintf function (+54 bytes)
+#define USE_XATOI 0 // Enable xatoi function (+182 bytes)
+
+
+#if FLASHEND > 0x1FFFF
+#error xitoa module does not support 256K devices
+#endif
+
+.nolist
+#include <avr/io.h> // Include device specific definitions.
+.list
+
+#ifdef SPM_PAGESIZE // Recent devices have "lpm Rd,Z+" and "movw".
+.macro _LPMI reg
+ lpm \reg, Z+
+.endm
+.macro _MOVW dh,dl, sh,sl
+ movw \dl, \sl
+.endm
+#else // Earlier devices do not have "lpm Rd,Z+" nor "movw".
+.macro _LPMI reg
+ lpm
+ mov \reg, r0
+ adiw ZL, 1
+.endm
+.macro _MOVW dh,dl, sh,sl
+ mov \dl, \sl
+ mov \dh, \sh
+.endm
+#endif
+
+
+
+;---------------------------------------------------------------------------
+; Stub function to forward to user output function
+;
+;Prototype: void xputc (char chr // a character to be output
+; );
+;Size: 12/12 words
+
+.section .bss
+.global xfunc_out ; xfunc_out must be initialized before using this module.
+xfunc_out: .ds.w 1
+.section .text
+
+
+.func xputc
+.global xputc
+xputc:
+#if CR_CRLF
+ cpi r24, 10 ;LF --> CRLF
+ brne 1f ;
+ ldi r24, 13 ;
+ rcall 1f ;
+ ldi r24, 10 ;/
+1:
+#endif
+ push ZH
+ push ZL
+ lds ZL, xfunc_out+0 ;Pointer to the registered output function.
+ lds ZH, xfunc_out+1 ;/
+ sbiw ZL, 0 ;Skip if null
+ breq 2f ;/
+ icall
+2: pop ZL
+ pop ZH
+ ret
+.endfunc
+
+
+
+;---------------------------------------------------------------------------
+; Direct ROM string output
+;
+;Prototype: void xputs (const char *str_p // rom string to be output
+; );
+
+.func xputs
+.global xputs
+xputs:
+ _MOVW ZH,ZL, r25,r24 ; Z = pointer to rom string
+1: _LPMI r24
+ cpi r24, 0
+ breq 2f
+ rcall xputc
+ rjmp 1b
+2: ret
+.endfunc
+
+
+;---------------------------------------------------------------------------
+; Extended direct numeral string output (32bit version)
+;
+;Prototype: void xitoa (long value, // value to be output
+; char radix, // radix
+; char width); // minimum width
+;
+
+.func xitoa
+.global xitoa
+xitoa:
+ ;r25:r22 = value, r20 = base, r18 = digits
+ clr r31 ;r31 = stack level
+ ldi r30, ' ' ;r30 = sign
+ ldi r19, ' ' ;r19 = filler
+ sbrs r20, 7 ;When base indicates signd format and the value
+ rjmp 0f ;is minus, add a '-'.
+ neg r20 ;
+ sbrs r25, 7 ;
+ rjmp 0f ;
+ ldi r30, '-' ;
+ com r22 ;
+ com r23 ;
+ com r24 ;
+ com r25 ;
+ adc r22, r1 ;
+ adc r23, r1 ;
+ adc r24, r1 ;
+ adc r25, r1 ;/
+0: sbrs r18, 7 ;When digits indicates zero filled,
+ rjmp 1f ;filler is '0'.
+ neg r18 ;
+ ldi r19, '0' ;/
+ ;----- string conversion loop
+1: ldi r21, 32 ;r26 = r25:r22 % r20
+ clr r26 ;r25:r22 /= r20
+2: lsl r22 ;
+ rol r23 ;
+ rol r24 ;
+ rol r25 ;
+ rol r26 ;
+ cp r26, r20 ;
+ brcs 3f ;
+ sub r26, r20 ;
+ inc r22 ;
+3: dec r21 ;
+ brne 2b ;/
+ cpi r26, 10 ;r26 is a numeral digit '0'-'F'
+ brcs 4f ;
+ subi r26, -7 ;
+4: subi r26, -'0' ;/
+ push r26 ;Stack it
+ inc r31 ;/
+ cp r22, r1 ;Repeat until r25:r22 gets zero
+ cpc r23, r1 ;
+ cpc r24, r1 ;
+ cpc r25, r1 ;
+ brne 1b ;/
+
+ cpi r30, '-' ;Minus sign if needed
+ brne 5f ;
+ push r30 ;
+ inc r31 ;/
+5: cp r31, r18 ;Filler
+ brcc 6f ;
+ push r19 ;
+ inc r31 ;
+ rjmp 5b ;/
+
+6: pop r24 ;Flush stacked digits and exit
+ rcall xputc ;
+ dec r31 ;
+ brne 6b ;/
+
+ ret
+.endfunc
+
+
+
+;---------------------------------------------------------------------------;
+; Formatted string output (16/32bit version)
+;
+;Prototype:
+; void __xprintf (const char *format_p, ...);
+; void __xsprintf(char*, const char *format_p, ...);
+; void __xfprintf(void(*func)(char), const char *format_p, ...);
+;
+
+#if USE_XPRINTF
+
+.func xvprintf
+xvprintf:
+ ld ZL, Y+ ;Z = pointer to format string
+ ld ZH, Y+ ;/
+
+0: _LPMI r24 ;Get a format char
+ cpi r24, 0 ;End of format string?
+ breq 90f ;/
+ cpi r24, '%' ;Is format?
+ breq 20f ;/
+1: rcall xputc ;Put a normal character
+ rjmp 0b ;/
+90: ret
+
+20: ldi r18, 0 ;r18: digits
+ clt ;T: filler
+ _LPMI r21 ;Get flags
+ cpi r21, '%' ;Is a %?
+ breq 1b ;/
+ cpi r21, '0' ;Zero filled?
+ brne 23f ;
+ set ;/
+22: _LPMI r21 ;Get width
+23: cpi r21, '9'+1 ;
+ brcc 24f ;
+ subi r21, '0' ;
+ brcs 90b ;
+ lsl r18 ;
+ mov r0, r18 ;
+ lsl r18 ;
+ lsl r18 ;
+ add r18, r0 ;
+ add r18, r21 ;
+ rjmp 22b ;/
+
+24: brtc 25f ;get value (low word)
+ neg r18 ;
+25: ld r24, Y+ ;
+ ld r25, Y+ ;/
+ cpi r21, 'c' ;Is type character?
+ breq 1b ;/
+ cpi r21, 's' ;Is type RAM string?
+ breq 50f ;/
+ cpi r21, 'S' ;Is type ROM string?
+ breq 60f ;/
+ _MOVW r23,r22,r25,r24 ;r25:r22 = value
+ clr r24 ;
+ clr r25 ;
+ clt ;/
+ cpi r21, 'l' ;Is long int?
+ brne 26f ;
+ ld r24, Y+ ;get value (high word)
+ ld r25, Y+ ;
+ set ;
+ _LPMI r21 ;/
+26: cpi r21, 'd' ;Is type signed decimal?
+ brne 27f ;/
+ ldi r20, -10 ;
+ brts 40f ;
+ sbrs r23, 7 ;
+ rjmp 40f ;
+ ldi r24, -1 ;
+ ldi r25, -1 ;
+ rjmp 40f ;/
+27: cpi r21, 'u' ;Is type unsigned decimal?
+ ldi r20, 10 ;
+ breq 40f ;/
+ cpi r21, 'X' ;Is type hexdecimal?
+ ldi r20, 16 ;
+ breq 40f ;/
+ cpi r21, 'b' ;Is type binary?
+ ldi r20, 2 ;
+ breq 40f ;/
+ ret ;abort
+40: push ZH ;Output the value
+ push ZL ;
+ rcall xitoa ;
+42: pop ZL ;
+ pop ZH ;
+ rjmp 0b ;/
+
+50: push ZH ;Put a string on the RAM
+ push ZL
+ _MOVW ZH,ZL, r25,r24
+51: ld r24, Z+
+ cpi r24, 0
+ breq 42b
+ rcall xputc
+ rjmp 51b
+
+60: push ZH ;Put a string on the ROM
+ push ZL
+ rcall xputs
+ rjmp 42b
+.endfunc
+
+
+.func __xprintf
+.global __xprintf
+__xprintf:
+ push YH
+ push YL
+ in YL, _SFR_IO_ADDR(SPL)
+#ifdef SPH
+ in YH, _SFR_IO_ADDR(SPH)
+#else
+ clr YH
+#endif
+ adiw YL, 5 ;Y = pointer to arguments
+ rcall xvprintf
+ pop YL
+ pop YH
+ ret
+.endfunc
+
+
+#if USE_XSPRINTF
+
+.func __xsprintf
+putram:
+ _MOVW ZH,ZL, r15,r14
+ st Z+, r24
+ _MOVW r15,r14, ZH,ZL
+ ret
+.global __xsprintf
+__xsprintf:
+ push YH
+ push YL
+ in YL, _SFR_IO_ADDR(SPL)
+#ifdef SPH
+ in YH, _SFR_IO_ADDR(SPH)
+#else
+ clr YH
+#endif
+ adiw YL, 5 ;Y = pointer to arguments
+ lds ZL, xfunc_out+0 ;Save registered output function
+ lds ZH, xfunc_out+1 ;
+ push ZL ;
+ push ZH ;/
+ ldi ZL, lo8(pm(putram));Set local output function
+ ldi ZH, hi8(pm(putram));
+ sts xfunc_out+0, ZL ;
+ sts xfunc_out+1, ZH ;/
+ push r15 ;Initialize pointer to string buffer
+ push r14 ;
+ ld r14, Y+ ;
+ ld r15, Y+ ;/
+ rcall xvprintf
+ _MOVW ZH,ZL, r15,r14 ;Terminate string
+ st Z, r1 ;
+ pop r14 ;
+ pop r15 ;/
+ pop ZH ;Restore registered output function
+ pop ZL ;
+ sts xfunc_out+0, ZL ;
+ sts xfunc_out+1, ZH ;/
+ pop YL
+ pop YH
+ ret
+.endfunc
+#endif
+
+
+#if USE_XFPRINTF
+.func __xfprintf
+.global __xfprintf
+__xfprintf:
+ push YH
+ push YL
+ in YL, _SFR_IO_ADDR(SPL)
+#ifdef SPH
+ in YH, _SFR_IO_ADDR(SPH)
+#else
+ clr YH
+#endif
+ adiw YL, 5 ;Y = pointer to arguments
+ lds ZL, xfunc_out+0 ;Save registered output function
+ lds ZH, xfunc_out+1 ;
+ push ZL ;
+ push ZH ;/
+ ld ZL, Y+ ;Set output function
+ ld ZH, Y+ ;
+ sts xfunc_out+0, ZL ;
+ sts xfunc_out+1, ZH ;/
+ rcall xvprintf
+ pop ZH ;Restore registered output function
+ pop ZL ;
+ sts xfunc_out+0, ZL ;
+ sts xfunc_out+1, ZH ;/
+ pop YL
+ pop YH
+ ret
+.endfunc
+#endif
+
+#endif
+
+
+
+;---------------------------------------------------------------------------
+; Extended numeral string input
+;
+;Prototype:
+; char xatoi ( /* 1: Successful, 0: Failed */
+; const char **str, /* pointer to pointer to source string */
+; long *res /* result */
+; );
+;
+
+
+#if USE_XATOI
+.func xatoi
+.global xatoi
+xatoi:
+ _MOVW r1, r0, r23, r22
+ _MOVW XH, XL, r25, r24
+ ld ZL, X+
+ ld ZH, X+
+ clr r18 ;r21:r18 = 0;
+ clr r19 ;
+ clr r20 ;
+ clr r21 ;/
+ clt ;T = 0;
+
+ ldi r25, 10 ;r25 = 10;
+ rjmp 41f ;/
+40: adiw ZL, 1 ;Z++;
+41: ld r22, Z ;r22 = *Z;
+ cpi r22, ' ' ;if(r22 == ' ') continue
+ breq 40b ;/
+ brcs 70f ;if(r22 < ' ') error;
+ cpi r22, '-' ;if(r22 == '-') {
+ brne 42f ; T = 1;
+ set ; continue;
+ rjmp 40b ;}
+42: cpi r22, '9'+1 ;if(r22 > '9') error;
+ brcc 70f ;/
+ cpi r22, '0' ;if(r22 < '0') error;
+ brcs 70f ;/
+ brne 51f ;if(r22 > '0') cv_start;
+ ldi r25, 8 ;r25 = 8;
+ adiw ZL, 1 ;r22 = *(++Z);
+ ld r22, Z ;/
+ cpi r22, ' '+1 ;if(r22 <= ' ') exit;
+ brcs 80f ;/
+ cpi r22, 'b' ;if(r22 == 'b') {
+ brne 43f ; r25 = 2;
+ ldi r25, 2 ; cv_start;
+ rjmp 50f ;}
+43: cpi r22, 'x' ;if(r22 != 'x') error;
+ brne 51f ;/
+ ldi r25, 16 ;r25 = 16;
+
+50: adiw ZL, 1 ;Z++;
+ ld r22, Z ;r22 = *Z;
+51: cpi r22, ' '+1 ;if(r22 <= ' ') break;
+ brcs 80f ;/
+ cpi r22, 'a' ;if(r22 >= 'a') r22 =- 0x20;
+ brcs 52f ;
+ subi r22, 0x20 ;/
+52: subi r22, '0' ;if((r22 -= '0') < 0) error;
+ brcs 70f ;/
+ cpi r22, 10 ;if(r22 >= 10) {
+ brcs 53f ; r22 -= 7;
+ subi r22, 7 ; if(r22 < 10)
+ cpi r22, 10 ;
+ brcs 70f ;}
+53: cp r22, r25 ;if(r22 >= r25) error;
+ brcc 70f ;/
+60: ldi r24, 33 ;r21:r18 *= r25;
+ sub r23, r23 ;
+61: brcc 62f ;
+ add r23, r25 ;
+62: lsr r23 ;
+ ror r21 ;
+ ror r20 ;
+ ror r19 ;
+ ror r18 ;
+ dec r24 ;
+ brne 61b ;/
+ add r18, r22 ;r21:r18 += r22;
+ adc r19, r24 ;
+ adc r20, r24 ;
+ adc r21, r24 ;/
+ rjmp 50b ;repeat
+
+70: ldi r24, 0
+ rjmp 81f
+80: ldi r24, 1
+81: brtc 82f
+ clr r22
+ com r18
+ com r19
+ com r20
+ com r21
+ adc r18, r22
+ adc r19, r22
+ adc r20, r22
+ adc r21, r22
+82: st -X, ZH
+ st -X, ZL
+ _MOVW XH, XL, r1, r0
+ st X+, r18
+ st X+, r19
+ st X+, r20
+ st X+, r21
+ clr r1
+ ret
+.endfunc
+#endif
+
+
diff --git a/tmk_core/common/avr/xprintf.h b/tmk_core/common/avr/xprintf.h
new file mode 100644
index 000000000..59c6f2531
--- /dev/null
+++ b/tmk_core/common/avr/xprintf.h
@@ -0,0 +1,111 @@
+/*---------------------------------------------------------------------------
+ Extended itoa, puts and printf (C)ChaN, 2011
+-----------------------------------------------------------------------------*/
+
+#ifndef XPRINTF_H
+#define XPRINTF_H
+
+#include <inttypes.h>
+#include <avr/pgmspace.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void (*xfunc_out)(uint8_t);
+#define xdev_out(func) xfunc_out = (void(*)(uint8_t))(func)
+
+/* This is a pointer to user defined output function. It must be initialized
+ before using this modle.
+*/
+
+void xputc(char chr);
+
+/* This is a stub function to forward outputs to user defined output function.
+ All outputs from this module are output via this function.
+*/
+
+
+/*-----------------------------------------------------------------------------*/
+void xputs(const char *string_p);
+
+/* The string placed in the ROM is forwarded to xputc() directly.
+*/
+
+
+/*-----------------------------------------------------------------------------*/
+void xitoa(long value, char radix, char width);
+
+/* Extended itoa().
+
+ value radix width output
+ 100 10 6 " 100"
+ 100 10 -6 "000100"
+ 100 10 0 "100"
+ 4294967295 10 0 "4294967295"
+ 4294967295 -10 0 "-1"
+ 655360 16 -8 "000A0000"
+ 1024 16 0 "400"
+ 0x55 2 -8 "01010101"
+*/
+
+
+/*-----------------------------------------------------------------------------*/
+#define xprintf(format, ...) __xprintf(PSTR(format), ##__VA_ARGS__)
+#define xsprintf(str, format, ...) __xsprintf(str, PSTR(format), ##__VA_ARGS__)
+#define xfprintf(func, format, ...) __xfprintf(func, PSTR(format), ##__VA_ARGS__)
+
+void __xprintf(const char *format_p, ...); /* Send formatted string to the registered device */
+void __xsprintf(char*, const char *format_p, ...); /* Put formatted string to the memory */
+void __xfprintf(void(*func)(uint8_t), const char *format_p, ...); /* Send formatted string to the specified device */
+
+/* Format string is placed in the ROM. The format flags is similar to printf().
+
+ %[flag][width][size]type
+
+ flag
+ A '0' means filled with '0' when output is shorter than width.
+ ' ' is used in default. This is effective only numeral type.
+ width
+ Minimum width in decimal number. This is effective only numeral type.
+ Default width is zero.
+ size
+ A 'l' means the argument is long(32bit). Default is short(16bit).
+ This is effective only numeral type.
+ type
+ 'c' : Character, argument is the value
+ 's' : String placed on the RAM, argument is the pointer
+ 'S' : String placed on the ROM, argument is the pointer
+ 'd' : Signed decimal, argument is the value
+ 'u' : Unsigned decimal, argument is the value
+ 'X' : Hexdecimal, argument is the value
+ 'b' : Binary, argument is the value
+ '%' : '%'
+
+*/
+
+
+/*-----------------------------------------------------------------------------*/
+char xatoi(char **str, long *ret);
+
+/* Get value of the numeral string.
+
+ str
+ Pointer to pointer to source string
+
+ "0b11001010" binary
+ "0377" octal
+ "0xff800" hexdecimal
+ "1250000" decimal
+ "-25000" decimal
+
+ ret
+ Pointer to return value
+*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/tmk_core/common/backlight.c b/tmk_core/common/backlight.c
new file mode 100644
index 000000000..c9e8fd3fd
--- /dev/null
+++ b/tmk_core/common/backlight.c
@@ -0,0 +1,90 @@
+/*
+Copyright 2013 Mathias Andersson <wraul@dbox.se>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "backlight.h"
+#include "eeconfig.h"
+#include "debug.h"
+
+backlight_config_t backlight_config;
+
+void backlight_init(void)
+{
+ /* check signature */
+ if (!eeconfig_is_enabled()) {
+ eeconfig_init();
+ }
+ backlight_config.raw = eeconfig_read_backlight();
+ backlight_set(backlight_config.enable ? backlight_config.level : 0);
+}
+
+void backlight_increase(void)
+{
+ if(backlight_config.level < BACKLIGHT_LEVELS)
+ {
+ backlight_config.level++;
+ backlight_config.enable = 1;
+ eeconfig_update_backlight(backlight_config.raw);
+ }
+ dprintf("backlight increase: %u\n", backlight_config.level);
+ backlight_set(backlight_config.level);
+}
+
+void backlight_decrease(void)
+{
+ if(backlight_config.level > 0)
+ {
+ backlight_config.level--;
+ backlight_config.enable = !!backlight_config.level;
+ eeconfig_update_backlight(backlight_config.raw);
+ }
+ dprintf("backlight decrease: %u\n", backlight_config.level);
+ backlight_set(backlight_config.level);
+}
+
+void backlight_toggle(void)
+{
+ backlight_config.enable ^= 1;
+ eeconfig_update_backlight(backlight_config.raw);
+ dprintf("backlight toggle: %u\n", backlight_config.enable);
+ backlight_set(backlight_config.enable ? backlight_config.level : 0);
+}
+
+void backlight_step(void)
+{
+ backlight_config.level++;
+ if(backlight_config.level > BACKLIGHT_LEVELS)
+ {
+ backlight_config.level = 0;
+ }
+ backlight_config.enable = !!backlight_config.level;
+ eeconfig_update_backlight(backlight_config.raw);
+ dprintf("backlight step: %u\n", backlight_config.level);
+ backlight_set(backlight_config.level);
+}
+
+void backlight_level(uint8_t level)
+{
+ backlight_config.level ^= level;
+ backlight_config.enable = !!backlight_config.level;
+ eeconfig_update_backlight(backlight_config.raw);
+ backlight_set(backlight_config.level);
+}
+
+uint8_t get_backlight_level(void)
+{
+ return backlight_config.level;
+} \ No newline at end of file
diff --git a/tmk_core/common/backlight.h b/tmk_core/common/backlight.h
new file mode 100644
index 000000000..f57309267
--- /dev/null
+++ b/tmk_core/common/backlight.h
@@ -0,0 +1,41 @@
+/*
+Copyright 2013 Mathias Andersson <wraul@dbox.se>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef BACKLIGHT_H
+#define BACKLIGHT_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+typedef union {
+ uint8_t raw;
+ struct {
+ bool enable :1;
+ uint8_t level :7;
+ };
+} backlight_config_t;
+
+void backlight_init(void);
+void backlight_increase(void);
+void backlight_decrease(void);
+void backlight_toggle(void);
+void backlight_step(void);
+void backlight_set(uint8_t level);
+void backlight_level(uint8_t level);
+uint8_t get_backlight_level(void);
+
+#endif
diff --git a/tmk_core/common/bootloader.h b/tmk_core/common/bootloader.h
new file mode 100644
index 000000000..44775039d
--- /dev/null
+++ b/tmk_core/common/bootloader.h
@@ -0,0 +1,25 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef BOOTLOADER_H
+#define BOOTLOADER_H
+
+
+/* give code for your bootloader to come up if needed */
+void bootloader_jump(void);
+
+#endif
diff --git a/tmk_core/common/bootmagic.c b/tmk_core/common/bootmagic.c
new file mode 100644
index 000000000..6730a2a4a
--- /dev/null
+++ b/tmk_core/common/bootmagic.c
@@ -0,0 +1,129 @@
+#include <stdint.h>
+#include <stdbool.h>
+#include "wait.h"
+#include "matrix.h"
+#include "bootloader.h"
+#include "debug.h"
+#include "keymap.h"
+#include "host.h"
+#include "action_layer.h"
+#include "eeconfig.h"
+#include "bootmagic.h"
+
+keymap_config_t keymap_config;
+
+void bootmagic(void)
+{
+ /* check signature */
+ if (!eeconfig_is_enabled()) {
+ eeconfig_init();
+ }
+
+ /* do scans in case of bounce */
+ print("bootmagic scan: ... ");
+ uint8_t scan = 100;
+ while (scan--) { matrix_scan(); wait_ms(10); }
+ print("done.\n");
+
+ /* bootmagic skip */
+ if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SKIP)) {
+ return;
+ }
+
+ /* eeconfig clear */
+ if (bootmagic_scan_keycode(BOOTMAGIC_KEY_EEPROM_CLEAR)) {
+ eeconfig_init();
+ }
+
+ /* bootloader */
+ if (bootmagic_scan_keycode(BOOTMAGIC_KEY_BOOTLOADER)) {
+ bootloader_jump();
+ }
+
+ /* debug enable */
+ debug_config.raw = eeconfig_read_debug();
+ if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_ENABLE)) {
+ if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_MATRIX)) {
+ debug_config.matrix = !debug_config.matrix;
+ } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_KEYBOARD)) {
+ debug_config.keyboard = !debug_config.keyboard;
+ } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_MOUSE)) {
+ debug_config.mouse = !debug_config.mouse;
+ } else {
+ debug_config.enable = !debug_config.enable;
+ }
+ }
+ eeconfig_update_debug(debug_config.raw);
+
+ /* keymap config */
+ keymap_config.raw = eeconfig_read_keymap();
+ if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_CONTROL_CAPSLOCK)) {
+ keymap_config.swap_control_capslock = !keymap_config.swap_control_capslock;
+ }
+ if (bootmagic_scan_keycode(BOOTMAGIC_KEY_CAPSLOCK_TO_CONTROL)) {
+ keymap_config.capslock_to_control = !keymap_config.capslock_to_control;
+ }
+ if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_LALT_LGUI)) {
+ keymap_config.swap_lalt_lgui = !keymap_config.swap_lalt_lgui;
+ }
+ if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_RALT_RGUI)) {
+ keymap_config.swap_ralt_rgui = !keymap_config.swap_ralt_rgui;
+ }
+ if (bootmagic_scan_keycode(BOOTMAGIC_KEY_NO_GUI)) {
+ keymap_config.no_gui = !keymap_config.no_gui;
+ }
+ if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_GRAVE_ESC)) {
+ keymap_config.swap_grave_esc = !keymap_config.swap_grave_esc;
+ }
+ if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_BACKSLASH_BACKSPACE)) {
+ keymap_config.swap_backslash_backspace = !keymap_config.swap_backslash_backspace;
+ }
+ if (bootmagic_scan_keycode(BOOTMAGIC_HOST_NKRO)) {
+ keymap_config.nkro = !keymap_config.nkro;
+ }
+ eeconfig_update_keymap(keymap_config.raw);
+
+#ifdef NKRO_ENABLE
+ keyboard_nkro = keymap_config.nkro;
+#endif
+
+ /* default layer */
+ uint8_t default_layer = 0;
+ if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_0)) { default_layer |= (1<<0); }
+ if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_1)) { default_layer |= (1<<1); }
+ if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_2)) { default_layer |= (1<<2); }
+ if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_3)) { default_layer |= (1<<3); }
+ if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_4)) { default_layer |= (1<<4); }
+ if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_5)) { default_layer |= (1<<5); }
+ if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_6)) { default_layer |= (1<<6); }
+ if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_7)) { default_layer |= (1<<7); }
+ if (default_layer) {
+ eeconfig_update_default_layer(default_layer);
+ default_layer_set((uint32_t)default_layer);
+ } else {
+ default_layer = eeconfig_read_default_layer();
+ default_layer_set((uint32_t)default_layer);
+ }
+}
+
+static bool scan_keycode(uint8_t keycode)
+{
+ for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
+ matrix_row_t matrix_row = matrix_get_row(r);
+ for (uint8_t c = 0; c < MATRIX_COLS; c++) {
+ if (matrix_row & ((matrix_row_t)1<<c)) {
+ if (keycode == keymap_key_to_keycode(0, (keypos_t){ .row = r, .col = c })) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+bool bootmagic_scan_keycode(uint8_t keycode)
+{
+ if (!scan_keycode(BOOTMAGIC_KEY_SALT)) return false;
+
+ return scan_keycode(keycode);
+} \ No newline at end of file
diff --git a/tmk_core/common/bootmagic.h b/tmk_core/common/bootmagic.h
new file mode 100644
index 000000000..8f6618f4b
--- /dev/null
+++ b/tmk_core/common/bootmagic.h
@@ -0,0 +1,100 @@
+#ifndef BOOTMAGIC_H
+#define BOOTMAGIC_H
+
+
+/* bootmagic salt key */
+#ifndef BOOTMAGIC_KEY_SALT
+#define BOOTMAGIC_KEY_SALT KC_SPACE
+#endif
+
+/* skip bootmagic and eeconfig */
+#ifndef BOOTMAGIC_KEY_SKIP
+#define BOOTMAGIC_KEY_SKIP KC_ESC
+#endif
+
+/* eeprom clear */
+#ifndef BOOTMAGIC_KEY_EEPROM_CLEAR
+#define BOOTMAGIC_KEY_EEPROM_CLEAR KC_BSPACE
+#endif
+
+/* kick up bootloader */
+#ifndef BOOTMAGIC_KEY_BOOTLOADER
+#define BOOTMAGIC_KEY_BOOTLOADER KC_B
+#endif
+
+/* debug enable */
+#ifndef BOOTMAGIC_KEY_DEBUG_ENABLE
+#define BOOTMAGIC_KEY_DEBUG_ENABLE KC_D
+#endif
+#ifndef BOOTMAGIC_KEY_DEBUG_MATRIX
+#define BOOTMAGIC_KEY_DEBUG_MATRIX KC_X
+#endif
+#ifndef BOOTMAGIC_KEY_DEBUG_KEYBOARD
+#define BOOTMAGIC_KEY_DEBUG_KEYBOARD KC_K
+#endif
+#ifndef BOOTMAGIC_KEY_DEBUG_MOUSE
+#define BOOTMAGIC_KEY_DEBUG_MOUSE KC_M
+#endif
+
+/*
+ * keymap config
+ */
+#ifndef BOOTMAGIC_KEY_SWAP_CONTROL_CAPSLOCK
+#define BOOTMAGIC_KEY_SWAP_CONTROL_CAPSLOCK KC_LCTRL
+#endif
+#ifndef BOOTMAGIC_KEY_CAPSLOCK_TO_CONTROL
+#define BOOTMAGIC_KEY_CAPSLOCK_TO_CONTROL KC_CAPSLOCK
+#endif
+#ifndef BOOTMAGIC_KEY_SWAP_LALT_LGUI
+#define BOOTMAGIC_KEY_SWAP_LALT_LGUI KC_LALT
+#endif
+#ifndef BOOTMAGIC_KEY_SWAP_RALT_RGUI
+#define BOOTMAGIC_KEY_SWAP_RALT_RGUI KC_RALT
+#endif
+#ifndef BOOTMAGIC_KEY_NO_GUI
+#define BOOTMAGIC_KEY_NO_GUI KC_LGUI
+#endif
+#ifndef BOOTMAGIC_KEY_SWAP_GRAVE_ESC
+#define BOOTMAGIC_KEY_SWAP_GRAVE_ESC KC_GRAVE
+#endif
+#ifndef BOOTMAGIC_KEY_SWAP_BACKSLASH_BACKSPACE
+#define BOOTMAGIC_KEY_SWAP_BACKSLASH_BACKSPACE KC_BSLASH
+#endif
+#ifndef BOOTMAGIC_HOST_NKRO
+#define BOOTMAGIC_HOST_NKRO KC_N
+#endif
+
+
+/*
+ * change default layer
+ */
+#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_0
+#define BOOTMAGIC_KEY_DEFAULT_LAYER_0 KC_0
+#endif
+#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_1
+#define BOOTMAGIC_KEY_DEFAULT_LAYER_1 KC_1
+#endif
+#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_2
+#define BOOTMAGIC_KEY_DEFAULT_LAYER_2 KC_2
+#endif
+#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_3
+#define BOOTMAGIC_KEY_DEFAULT_LAYER_3 KC_3
+#endif
+#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_4
+#define BOOTMAGIC_KEY_DEFAULT_LAYER_4 KC_4
+#endif
+#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_5
+#define BOOTMAGIC_KEY_DEFAULT_LAYER_5 KC_5
+#endif
+#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_6
+#define BOOTMAGIC_KEY_DEFAULT_LAYER_6 KC_6
+#endif
+#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_7
+#define BOOTMAGIC_KEY_DEFAULT_LAYER_7 KC_7
+#endif
+
+
+void bootmagic(void);
+bool bootmagic_scan_keycode(uint8_t keycode);
+
+#endif
diff --git a/tmk_core/common/chibios/bootloader.c b/tmk_core/common/chibios/bootloader.c
new file mode 100644
index 000000000..8a533ab6f
--- /dev/null
+++ b/tmk_core/common/chibios/bootloader.c
@@ -0,0 +1,47 @@
+#include "bootloader.h"
+
+#include "ch.h"
+#include "hal.h"
+
+#ifdef STM32_BOOTLOADER_ADDRESS
+/* STM32 */
+
+#if defined(STM32F0XX)
+/* This code should be checked whether it runs correctly on platforms */
+#define SYMVAL(sym) (uint32_t)(((uint8_t *)&(sym)) - ((uint8_t *)0))
+extern uint32_t __ram0_end__;
+
+void bootloader_jump(void) {
+ *((unsigned long *)(SYMVAL(__ram0_end__) - 4)) = 0xDEADBEEF; // set magic flag => reset handler will jump into boot loader
+ NVIC_SystemReset();
+}
+
+#else /* defined(STM32F0XX) */
+#error Check that the bootloader code works on your platform and add it to bootloader.c!
+#endif /* defined(STM32F0XX) */
+
+#elif defined(KL2x) || defined(K20x) /* STM32_BOOTLOADER_ADDRESS */
+/* Kinetis */
+
+#if defined(KIIBOHD_BOOTLOADER)
+/* Kiibohd Bootloader (MCHCK and Infinity KB) */
+#define SCB_AIRCR_VECTKEY_WRITEMAGIC 0x05FA0000
+const uint8_t sys_reset_to_loader_magic[] = "\xff\x00\x7fRESET TO LOADER\x7f\x00\xff";
+void bootloader_jump(void) {
+ __builtin_memcpy((void *)VBAT, (const void *)sys_reset_to_loader_magic, sizeof(sys_reset_to_loader_magic));
+ // request reset
+ SCB->AIRCR = SCB_AIRCR_VECTKEY_WRITEMAGIC | SCB_AIRCR_SYSRESETREQ_Msk;
+}
+
+#else /* defined(KIIBOHD_BOOTLOADER) */
+/* Default for Kinetis - expecting an ARM Teensy */
+void bootloader_jump(void) {
+ chThdSleepMilliseconds(100);
+ __BKPT(0);
+}
+#endif /* defined(KIIBOHD_BOOTLOADER) */
+
+#else /* neither STM32 nor KINETIS */
+__attribute__((weak))
+void bootloader_jump(void) {}
+#endif \ No newline at end of file
diff --git a/tmk_core/common/chibios/eeprom.c b/tmk_core/common/chibios/eeprom.c
new file mode 100644
index 000000000..5ff8ee86f
--- /dev/null
+++ b/tmk_core/common/chibios/eeprom.c
@@ -0,0 +1,588 @@
+#include "ch.h"
+#include "hal.h"
+
+#include "eeconfig.h"
+
+/*************************************/
+/* Hardware backend */
+/* */
+/* Code from PJRC/Teensyduino */
+/*************************************/
+
+/* Teensyduino Core Library
+ * http://www.pjrc.com/teensy/
+ * Copyright (c) 2013 PJRC.COM, LLC.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * 1. The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * 2. If the Software is incorporated into a build system that allows
+ * selection among a list of target devices, then similar target
+ * devices manufactured by PJRC.COM must be included in the list of
+ * target devices and selectable in the same manner.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+
+#if defined(K20x) /* chip selection */
+/* Teensy 3.0, 3.1, 3.2; mchck; infinity keyboard */
+
+// The EEPROM is really RAM with a hardware-based backup system to
+// flash memory. Selecting a smaller size EEPROM allows more wear
+// leveling, for higher write endurance. If you edit this file,
+// set this to the smallest size your application can use. Also,
+// due to Freescale's implementation, writing 16 or 32 bit words
+// (aligned to 2 or 4 byte boundaries) has twice the endurance
+// compared to writing 8 bit bytes.
+//
+#define EEPROM_SIZE 32
+
+// Writing unaligned 16 or 32 bit data is handled automatically when
+// this is defined, but at a cost of extra code size. Without this,
+// any unaligned write will cause a hard fault exception! If you're
+// absolutely sure all 16 and 32 bit writes will be aligned, you can
+// remove the extra unnecessary code.
+//
+#define HANDLE_UNALIGNED_WRITES
+
+// Minimum EEPROM Endurance
+// ------------------------
+#if (EEPROM_SIZE == 2048) // 35000 writes/byte or 70000 writes/word
+ #define EEESIZE 0x33
+#elif (EEPROM_SIZE == 1024) // 75000 writes/byte or 150000 writes/word
+ #define EEESIZE 0x34
+#elif (EEPROM_SIZE == 512) // 155000 writes/byte or 310000 writes/word
+ #define EEESIZE 0x35
+#elif (EEPROM_SIZE == 256) // 315000 writes/byte or 630000 writes/word
+ #define EEESIZE 0x36
+#elif (EEPROM_SIZE == 128) // 635000 writes/byte or 1270000 writes/word
+ #define EEESIZE 0x37
+#elif (EEPROM_SIZE == 64) // 1275000 writes/byte or 2550000 writes/word
+ #define EEESIZE 0x38
+#elif (EEPROM_SIZE == 32) // 2555000 writes/byte or 5110000 writes/word
+ #define EEESIZE 0x39
+#endif
+
+void eeprom_initialize(void)
+{
+ uint32_t count=0;
+ uint16_t do_flash_cmd[] = {
+ 0xf06f, 0x037f, 0x7003, 0x7803,
+ 0xf013, 0x0f80, 0xd0fb, 0x4770};
+ uint8_t status;
+
+ if (FTFL->FCNFG & FTFL_FCNFG_RAMRDY) {
+ // FlexRAM is configured as traditional RAM
+ // We need to reconfigure for EEPROM usage
+ FTFL->FCCOB0 = 0x80; // PGMPART = Program Partition Command
+ FTFL->FCCOB4 = EEESIZE; // EEPROM Size
+ FTFL->FCCOB5 = 0x03; // 0K for Dataflash, 32K for EEPROM backup
+ __disable_irq();
+ // do_flash_cmd() must execute from RAM. Luckily the C syntax is simple...
+ (*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&(FTFL->FSTAT));
+ __enable_irq();
+ status = FTFL->FSTAT;
+ if (status & (FTFL_FSTAT_RDCOLERR|FTFL_FSTAT_ACCERR|FTFL_FSTAT_FPVIOL)) {
+ FTFL->FSTAT = (status & (FTFL_FSTAT_RDCOLERR|FTFL_FSTAT_ACCERR|FTFL_FSTAT_FPVIOL));
+ return; // error
+ }
+ }
+ // wait for eeprom to become ready (is this really necessary?)
+ while (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) {
+ if (++count > 20000) break;
+ }
+}
+
+#define FlexRAM ((uint8_t *)0x14000000)
+
+uint8_t eeprom_read_byte(const uint8_t *addr)
+{
+ uint32_t offset = (uint32_t)addr;
+ if (offset >= EEPROM_SIZE) return 0;
+ if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
+ return FlexRAM[offset];
+}
+
+uint16_t eeprom_read_word(const uint16_t *addr)
+{
+ uint32_t offset = (uint32_t)addr;
+ if (offset >= EEPROM_SIZE-1) return 0;
+ if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
+ return *(uint16_t *)(&FlexRAM[offset]);
+}
+
+uint32_t eeprom_read_dword(const uint32_t *addr)
+{
+ uint32_t offset = (uint32_t)addr;
+ if (offset >= EEPROM_SIZE-3) return 0;
+ if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
+ return *(uint32_t *)(&FlexRAM[offset]);
+}
+
+void eeprom_read_block(void *buf, const void *addr, uint32_t len)
+{
+ uint32_t offset = (uint32_t)addr;
+ uint8_t *dest = (uint8_t *)buf;
+ uint32_t end = offset + len;
+
+ if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
+ if (end > EEPROM_SIZE) end = EEPROM_SIZE;
+ while (offset < end) {
+ *dest++ = FlexRAM[offset++];
+ }
+}
+
+int eeprom_is_ready(void)
+{
+ return (FTFL->FCNFG & FTFL_FCNFG_EEERDY) ? 1 : 0;
+}
+
+static void flexram_wait(void)
+{
+ while (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) {
+ // TODO: timeout
+ }
+}
+
+void eeprom_write_byte(uint8_t *addr, uint8_t value)
+{
+ uint32_t offset = (uint32_t)addr;
+
+ if (offset >= EEPROM_SIZE) return;
+ if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
+ if (FlexRAM[offset] != value) {
+ FlexRAM[offset] = value;
+ flexram_wait();
+ }
+}
+
+void eeprom_write_word(uint16_t *addr, uint16_t value)
+{
+ uint32_t offset = (uint32_t)addr;
+
+ if (offset >= EEPROM_SIZE-1) return;
+ if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
+#ifdef HANDLE_UNALIGNED_WRITES
+ if ((offset & 1) == 0) {
+#endif
+ if (*(uint16_t *)(&FlexRAM[offset]) != value) {
+ *(uint16_t *)(&FlexRAM[offset]) = value;
+ flexram_wait();
+ }
+#ifdef HANDLE_UNALIGNED_WRITES
+ } else {
+ if (FlexRAM[offset] != value) {
+ FlexRAM[offset] = value;
+ flexram_wait();
+ }
+ if (FlexRAM[offset + 1] != (value >> 8)) {
+ FlexRAM[offset + 1] = value >> 8;
+ flexram_wait();
+ }
+ }
+#endif
+}
+
+void eeprom_write_dword(uint32_t *addr, uint32_t value)
+{
+ uint32_t offset = (uint32_t)addr;
+
+ if (offset >= EEPROM_SIZE-3) return;
+ if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
+#ifdef HANDLE_UNALIGNED_WRITES
+ switch (offset & 3) {
+ case 0:
+#endif
+ if (*(uint32_t *)(&FlexRAM[offset]) != value) {
+ *(uint32_t *)(&FlexRAM[offset]) = value;
+ flexram_wait();
+ }
+ return;
+#ifdef HANDLE_UNALIGNED_WRITES
+ case 2:
+ if (*(uint16_t *)(&FlexRAM[offset]) != value) {
+ *(uint16_t *)(&FlexRAM[offset]) = value;
+ flexram_wait();
+ }
+ if (*(uint16_t *)(&FlexRAM[offset + 2]) != (value >> 16)) {
+ *(uint16_t *)(&FlexRAM[offset + 2]) = value >> 16;
+ flexram_wait();
+ }
+ return;
+ default:
+ if (FlexRAM[offset] != value) {
+ FlexRAM[offset] = value;
+ flexram_wait();
+ }
+ if (*(uint16_t *)(&FlexRAM[offset + 1]) != (value >> 8)) {
+ *(uint16_t *)(&FlexRAM[offset + 1]) = value >> 8;
+ flexram_wait();
+ }
+ if (FlexRAM[offset + 3] != (value >> 24)) {
+ FlexRAM[offset + 3] = value >> 24;
+ flexram_wait();
+ }
+ }
+#endif
+}
+
+void eeprom_write_block(const void *buf, void *addr, uint32_t len)
+{
+ uint32_t offset = (uint32_t)addr;
+ const uint8_t *src = (const uint8_t *)buf;
+
+ if (offset >= EEPROM_SIZE) return;
+ if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
+ if (len >= EEPROM_SIZE) len = EEPROM_SIZE;
+ if (offset + len >= EEPROM_SIZE) len = EEPROM_SIZE - offset;
+ while (len > 0) {
+ uint32_t lsb = offset & 3;
+ if (lsb == 0 && len >= 4) {
+ // write aligned 32 bits
+ uint32_t val32;
+ val32 = *src++;
+ val32 |= (*src++ << 8);
+ val32 |= (*src++ << 16);
+ val32 |= (*src++ << 24);
+ if (*(uint32_t *)(&FlexRAM[offset]) != val32) {
+ *(uint32_t *)(&FlexRAM[offset]) = val32;
+ flexram_wait();
+ }
+ offset += 4;
+ len -= 4;
+ } else if ((lsb == 0 || lsb == 2) && len >= 2) {
+ // write aligned 16 bits
+ uint16_t val16;
+ val16 = *src++;
+ val16 |= (*src++ << 8);
+ if (*(uint16_t *)(&FlexRAM[offset]) != val16) {
+ *(uint16_t *)(&FlexRAM[offset]) = val16;
+ flexram_wait();
+ }
+ offset += 2;
+ len -= 2;
+ } else {
+ // write 8 bits
+ uint8_t val8 = *src++;
+ if (FlexRAM[offset] != val8) {
+ FlexRAM[offset] = val8;
+ flexram_wait();
+ }
+ offset++;
+ len--;
+ }
+ }
+}
+
+/*
+void do_flash_cmd(volatile uint8_t *fstat)
+{
+ *fstat = 0x80;
+ while ((*fstat & 0x80) == 0) ; // wait
+}
+00000000 <do_flash_cmd>:
+ 0: f06f 037f mvn.w r3, #127 ; 0x7f
+ 4: 7003 strb r3, [r0, #0]
+ 6: 7803 ldrb r3, [r0, #0]
+ 8: f013 0f80 tst.w r3, #128 ; 0x80
+ c: d0fb beq.n 6 <do_flash_cmd+0x6>
+ e: 4770 bx lr
+*/
+
+#elif defined(KL2x) /* chip selection */
+/* Teensy LC (emulated) */
+
+#define SYMVAL(sym) (uint32_t)(((uint8_t *)&(sym)) - ((uint8_t *)0))
+
+extern uint32_t __eeprom_workarea_start__;
+extern uint32_t __eeprom_workarea_end__;
+
+#define EEPROM_SIZE 128
+
+static uint32_t flashend = 0;
+
+void eeprom_initialize(void)
+{
+ const uint16_t *p = (uint16_t *)SYMVAL(__eeprom_workarea_start__);
+
+ do {
+ if (*p++ == 0xFFFF) {
+ flashend = (uint32_t)(p - 2);
+ return;
+ }
+ } while (p < (uint16_t *)SYMVAL(__eeprom_workarea_end__));
+ flashend = (uint32_t)((uint16_t *)SYMVAL(__eeprom_workarea_end__) - 1);
+}
+
+uint8_t eeprom_read_byte(const uint8_t *addr)
+{
+ uint32_t offset = (uint32_t)addr;
+ const uint16_t *p = (uint16_t *)SYMVAL(__eeprom_workarea_start__);
+ const uint16_t *end = (const uint16_t *)((uint32_t)flashend);
+ uint16_t val;
+ uint8_t data=0xFF;
+
+ if (!end) {
+ eeprom_initialize();
+ end = (const uint16_t *)((uint32_t)flashend);
+ }
+ if (offset < EEPROM_SIZE) {
+ while (p <= end) {
+ val = *p++;
+ if ((val & 255) == offset) data = val >> 8;
+ }
+ }
+ return data;
+}
+
+static void flash_write(const uint16_t *code, uint32_t addr, uint32_t data)
+{
+ // with great power comes great responsibility....
+ uint32_t stat;
+ *(uint32_t *)&(FTFA->FCCOB3) = 0x06000000 | (addr & 0x00FFFFFC);
+ *(uint32_t *)&(FTFA->FCCOB7) = data;
+ __disable_irq();
+ (*((void (*)(volatile uint8_t *))((uint32_t)code | 1)))(&(FTFA->FSTAT));
+ __enable_irq();
+ stat = FTFA->FSTAT & (FTFA_FSTAT_RDCOLERR|FTFA_FSTAT_ACCERR|FTFA_FSTAT_FPVIOL);
+ if (stat) {
+ FTFA->FSTAT = stat;
+ }
+ MCM->PLACR |= MCM_PLACR_CFCC;
+}
+
+void eeprom_write_byte(uint8_t *addr, uint8_t data)
+{
+ uint32_t offset = (uint32_t)addr;
+ const uint16_t *p, *end = (const uint16_t *)((uint32_t)flashend);
+ uint32_t i, val, flashaddr;
+ uint16_t do_flash_cmd[] = {
+ 0x2380, 0x7003, 0x7803, 0xb25b, 0x2b00, 0xdafb, 0x4770};
+ uint8_t buf[EEPROM_SIZE];
+
+ if (offset >= EEPROM_SIZE) return;
+ if (!end) {
+ eeprom_initialize();
+ end = (const uint16_t *)((uint32_t)flashend);
+ }
+ if (++end < (uint16_t *)SYMVAL(__eeprom_workarea_end__)) {
+ val = (data << 8) | offset;
+ flashaddr = (uint32_t)end;
+ flashend = flashaddr;
+ if ((flashaddr & 2) == 0) {
+ val |= 0xFFFF0000;
+ } else {
+ val <<= 16;
+ val |= 0x0000FFFF;
+ }
+ flash_write(do_flash_cmd, flashaddr, val);
+ } else {
+ for (i=0; i < EEPROM_SIZE; i++) {
+ buf[i] = 0xFF;
+ }
+ val = 0;
+ for (p = (uint16_t *)SYMVAL(__eeprom_workarea_start__); p < (uint16_t *)SYMVAL(__eeprom_workarea_end__); p++) {
+ val = *p;
+ if ((val & 255) < EEPROM_SIZE) {
+ buf[val & 255] = val >> 8;
+ }
+ }
+ buf[offset] = data;
+ for (flashaddr=(uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_start__); flashaddr < (uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_end__); flashaddr += 1024) {
+ *(uint32_t *)&(FTFA->FCCOB3) = 0x09000000 | flashaddr;
+ __disable_irq();
+ (*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&(FTFA->FSTAT));
+ __enable_irq();
+ val = FTFA->FSTAT & (FTFA_FSTAT_RDCOLERR|FTFA_FSTAT_ACCERR|FTFA_FSTAT_FPVIOL);;
+ if (val) FTFA->FSTAT = val;
+ MCM->PLACR |= MCM_PLACR_CFCC;
+ }
+ flashaddr=(uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_start__);
+ for (i=0; i < EEPROM_SIZE; i++) {
+ if (buf[i] == 0xFF) continue;
+ if ((flashaddr & 2) == 0) {
+ val = (buf[i] << 8) | i;
+ } else {
+ val = val | (buf[i] << 24) | (i << 16);
+ flash_write(do_flash_cmd, flashaddr, val);
+ }
+ flashaddr += 2;
+ }
+ flashend = flashaddr;
+ if ((flashaddr & 2)) {
+ val |= 0xFFFF0000;
+ flash_write(do_flash_cmd, flashaddr, val);
+ }
+ }
+}
+
+/*
+void do_flash_cmd(volatile uint8_t *fstat)
+{
+ *fstat = 0x80;
+ while ((*fstat & 0x80) == 0) ; // wait
+}
+00000000 <do_flash_cmd>:
+ 0: 2380 movs r3, #128 ; 0x80
+ 2: 7003 strb r3, [r0, #0]
+ 4: 7803 ldrb r3, [r0, #0]
+ 6: b25b sxtb r3, r3
+ 8: 2b00 cmp r3, #0
+ a: dafb bge.n 4 <do_flash_cmd+0x4>
+ c: 4770 bx lr
+*/
+
+
+uint16_t eeprom_read_word(const uint16_t *addr)
+{
+ const uint8_t *p = (const uint8_t *)addr;
+ return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8);
+}
+
+uint32_t eeprom_read_dword(const uint32_t *addr)
+{
+ const uint8_t *p = (const uint8_t *)addr;
+ return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8)
+ | (eeprom_read_byte(p+2) << 16) | (eeprom_read_byte(p+3) << 24);
+}
+
+void eeprom_read_block(void *buf, const void *addr, uint32_t len)
+{
+ const uint8_t *p = (const uint8_t *)addr;
+ uint8_t *dest = (uint8_t *)buf;
+ while (len--) {
+ *dest++ = eeprom_read_byte(p++);
+ }
+}
+
+int eeprom_is_ready(void)
+{
+ return 1;
+}
+
+void eeprom_write_word(uint16_t *addr, uint16_t value)
+{
+ uint8_t *p = (uint8_t *)addr;
+ eeprom_write_byte(p++, value);
+ eeprom_write_byte(p, value >> 8);
+}
+
+void eeprom_write_dword(uint32_t *addr, uint32_t value)
+{
+ uint8_t *p = (uint8_t *)addr;
+ eeprom_write_byte(p++, value);
+ eeprom_write_byte(p++, value >> 8);
+ eeprom_write_byte(p++, value >> 16);
+ eeprom_write_byte(p, value >> 24);
+}
+
+void eeprom_write_block(const void *buf, void *addr, uint32_t len)
+{
+ uint8_t *p = (uint8_t *)addr;
+ const uint8_t *src = (const uint8_t *)buf;
+ while (len--) {
+ eeprom_write_byte(p++, *src++);
+ }
+}
+
+#else
+// No EEPROM supported, so emulate it
+
+#define EEPROM_SIZE 32
+static uint8_t buffer[EEPROM_SIZE];
+
+uint8_t eeprom_read_byte(const uint8_t *addr) {
+ uint32_t offset = (uint32_t)addr;
+ return buffer[offset];
+}
+
+void eeprom_write_byte(uint8_t *addr, uint8_t value) {
+ uint32_t offset = (uint32_t)addr;
+ buffer[offset] = value;
+}
+
+uint16_t eeprom_read_word(const uint16_t *addr) {
+ const uint8_t *p = (const uint8_t *)addr;
+ return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8);
+}
+
+uint32_t eeprom_read_dword(const uint32_t *addr) {
+ const uint8_t *p = (const uint8_t *)addr;
+ return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8)
+ | (eeprom_read_byte(p+2) << 16) | (eeprom_read_byte(p+3) << 24);
+}
+
+void eeprom_read_block(void *buf, const void *addr, uint32_t len) {
+ const uint8_t *p = (const uint8_t *)addr;
+ uint8_t *dest = (uint8_t *)buf;
+ while (len--) {
+ *dest++ = eeprom_read_byte(p++);
+ }
+}
+
+void eeprom_write_word(uint16_t *addr, uint16_t value) {
+ uint8_t *p = (uint8_t *)addr;
+ eeprom_write_byte(p++, value);
+ eeprom_write_byte(p, value >> 8);
+}
+
+void eeprom_write_dword(uint32_t *addr, uint32_t value) {
+ uint8_t *p = (uint8_t *)addr;
+ eeprom_write_byte(p++, value);
+ eeprom_write_byte(p++, value >> 8);
+ eeprom_write_byte(p++, value >> 16);
+ eeprom_write_byte(p, value >> 24);
+}
+
+void eeprom_write_block(const void *buf, void *addr, uint32_t len) {
+ uint8_t *p = (uint8_t *)addr;
+ const uint8_t *src = (const uint8_t *)buf;
+ while (len--) {
+ eeprom_write_byte(p++, *src++);
+ }
+}
+
+#endif /* chip selection */
+// The update functions just calls write for now, but could probably be optimized
+
+void eeprom_update_byte(uint8_t *addr, uint8_t value) {
+ eeprom_write_byte(addr, value);
+}
+
+void eeprom_update_word(uint16_t *addr, uint16_t value) {
+ uint8_t *p = (uint8_t *)addr;
+ eeprom_write_byte(p++, value);
+ eeprom_write_byte(p, value >> 8);
+}
+
+void eeprom_update_dword(uint32_t *addr, uint32_t value) {
+ uint8_t *p = (uint8_t *)addr;
+ eeprom_write_byte(p++, value);
+ eeprom_write_byte(p++, value >> 8);
+ eeprom_write_byte(p++, value >> 16);
+ eeprom_write_byte(p, value >> 24);
+}
+
+void eeprom_update_block(const void *buf, void *addr, uint32_t len) {
+ uint8_t *p = (uint8_t *)addr;
+ const uint8_t *src = (const uint8_t *)buf;
+ while (len--) {
+ eeprom_write_byte(p++, *src++);
+ }
+}
diff --git a/tmk_core/common/chibios/printf.c b/tmk_core/common/chibios/printf.c
new file mode 100644
index 000000000..72e3d4f8c
--- /dev/null
+++ b/tmk_core/common/chibios/printf.c
@@ -0,0 +1,240 @@
+/*
+ * found at: http://www.sparetimelabs.com/tinyprintf/tinyprintf.php
+ * and: http://www.sparetimelabs.com/printfrevisited/printfrevisited.php
+ */
+
+/*
+File: printf.c
+
+Copyright (C) 2004 Kustaa Nyholm
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+#include "printf.h"
+
+typedef void (*putcf) (void*,char);
+static putcf stdout_putf;
+static void* stdout_putp;
+
+// this adds cca 400 bytes
+#define PRINTF_LONG_SUPPORT
+
+#ifdef PRINTF_LONG_SUPPORT
+
+static void uli2a(unsigned long int num, unsigned int base, int uc,char * bf)
+ {
+ int n=0;
+ unsigned int d=1;
+ while (num/d >= base)
+ d*=base;
+ while (d!=0) {
+ int dgt = num / d;
+ num%=d;
+ d/=base;
+ if (n || dgt>0|| d==0) {
+ *bf++ = dgt+(dgt<10 ? '0' : (uc ? 'A' : 'a')-10);
+ ++n;
+ }
+ }
+ *bf=0;
+ }
+
+static void li2a (long num, char * bf)
+ {
+ if (num<0) {
+ num=-num;
+ *bf++ = '-';
+ }
+ uli2a(num,10,0,bf);
+ }
+
+#endif
+
+static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
+ {
+ int n=0;
+ unsigned int d=1;
+ while (num/d >= base)
+ d*=base;
+ while (d!=0) {
+ int dgt = num / d;
+ num%= d;
+ d/=base;
+ if (n || dgt>0 || d==0) {
+ *bf++ = dgt+(dgt<10 ? '0' : (uc ? 'A' : 'a')-10);
+ ++n;
+ }
+ }
+ *bf=0;
+ }
+
+static void i2a (int num, char * bf)
+ {
+ if (num<0) {
+ num=-num;
+ *bf++ = '-';
+ }
+ ui2a(num,10,0,bf);
+ }
+
+static int a2d(char ch)
+ {
+ if (ch>='0' && ch<='9')
+ return ch-'0';
+ else if (ch>='a' && ch<='f')
+ return ch-'a'+10;
+ else if (ch>='A' && ch<='F')
+ return ch-'A'+10;
+ else return -1;
+ }
+
+static char a2i(char ch, char** src,int base,int* nump)
+ {
+ char* p= *src;
+ int num=0;
+ int digit;
+ while ((digit=a2d(ch))>=0) {
+ if (digit>base) break;
+ num=num*base+digit;
+ ch=*p++;
+ }
+ *src=p;
+ *nump=num;
+ return ch;
+ }
+
+static void putchw(void* putp,putcf putf,int n, char z, char* bf)
+ {
+ char fc=z? '0' : ' ';
+ char ch;
+ char* p=bf;
+ while (*p++ && n > 0)
+ n--;
+ while (n-- > 0)
+ putf(putp,fc);
+ while ((ch= *bf++))
+ putf(putp,ch);
+ }
+
+void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
+ {
+ char bf[12];
+
+ char ch;
+
+
+ while ((ch=*(fmt++))) {
+ if (ch!='%')
+ putf(putp,ch);
+ else {
+ char lz=0;
+#ifdef PRINTF_LONG_SUPPORT
+ char lng=0;
+#endif
+ int w=0;
+ ch=*(fmt++);
+ if (ch=='0') {
+ ch=*(fmt++);
+ lz=1;
+ }
+ if (ch>='0' && ch<='9') {
+ ch=a2i(ch,&fmt,10,&w);
+ }
+#ifdef PRINTF_LONG_SUPPORT
+ if (ch=='l') {
+ ch=*(fmt++);
+ lng=1;
+ }
+#endif
+ switch (ch) {
+ case 0:
+ goto abort;
+ case 'u' : {
+#ifdef PRINTF_LONG_SUPPORT
+ if (lng)
+ uli2a(va_arg(va, unsigned long int),10,0,bf);
+ else
+#endif
+ ui2a(va_arg(va, unsigned int),10,0,bf);
+ putchw(putp,putf,w,lz,bf);
+ break;
+ }
+ case 'd' : {
+#ifdef PRINTF_LONG_SUPPORT
+ if (lng)
+ li2a(va_arg(va, unsigned long int),bf);
+ else
+#endif
+ i2a(va_arg(va, int),bf);
+ putchw(putp,putf,w,lz,bf);
+ break;
+ }
+ case 'x': case 'X' :
+#ifdef PRINTF_LONG_SUPPORT
+ if (lng)
+ uli2a(va_arg(va, unsigned long int),16,(ch=='X'),bf);
+ else
+#endif
+ ui2a(va_arg(va, unsigned int),16,(ch=='X'),bf);
+ putchw(putp,putf,w,lz,bf);
+ break;
+ case 'c' :
+ putf(putp,(char)(va_arg(va, int)));
+ break;
+ case 's' :
+ putchw(putp,putf,w,0,va_arg(va, char*));
+ break;
+ case '%' :
+ putf(putp,ch);
+ default:
+ break;
+ }
+ }
+ }
+ abort:;
+ }
+
+
+void init_printf(void* putp,void (*putf) (void*,char))
+ {
+ stdout_putf=putf;
+ stdout_putp=putp;
+ }
+
+void tfp_printf(char *fmt, ...)
+ {
+ va_list va;
+ va_start(va,fmt);
+ tfp_format(stdout_putp,stdout_putf,fmt,va);
+ va_end(va);
+ }
+
+static void putcp(void* p,char c)
+ {
+ *(*((char**)p))++ = c;
+ }
+
+
+
+void tfp_sprintf(char* s,char *fmt, ...)
+ {
+ va_list va;
+ va_start(va,fmt);
+ tfp_format(&s,putcp,fmt,va);
+ putcp(&s,0);
+ va_end(va);
+ }
diff --git a/tmk_core/common/chibios/printf.h b/tmk_core/common/chibios/printf.h
new file mode 100644
index 000000000..678a100c6
--- /dev/null
+++ b/tmk_core/common/chibios/printf.h
@@ -0,0 +1,111 @@
+/*
+ * found at: http://www.sparetimelabs.com/tinyprintf/tinyprintf.php
+ * and: http://www.sparetimelabs.com/printfrevisited/printfrevisited.php
+ */
+
+/*
+File: printf.h
+
+Copyright (C) 2004 Kustaa Nyholm
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+This library is realy just two files: 'printf.h' and 'printf.c'.
+
+They provide a simple and small (+200 loc) printf functionality to
+be used in embedded systems.
+
+I've found them so usefull in debugging that I do not bother with a
+debugger at all.
+
+They are distributed in source form, so to use them, just compile them
+into your project.
+
+Two printf variants are provided: printf and sprintf.
+
+The formats supported by this implementation are: 'd' 'u' 'c' 's' 'x' 'X'.
+
+Zero padding and field width are also supported.
+
+If the library is compiled with 'PRINTF_SUPPORT_LONG' defined then the
+long specifier is also
+supported. Note that this will pull in some long math routines (pun intended!)
+and thus make your executable noticably longer.
+
+The memory foot print of course depends on the target cpu, compiler and
+compiler options, but a rough guestimate (based on a H8S target) is about
+1.4 kB for code and some twenty 'int's and 'char's, say 60 bytes of stack space.
+Not too bad. Your milage may vary. By hacking the source code you can
+get rid of some hunred bytes, I'm sure, but personally I feel the balance of
+functionality and flexibility versus code size is close to optimal for
+many embedded systems.
+
+To use the printf you need to supply your own character output function,
+something like :
+
+ void putc ( void* p, char c)
+ {
+ while (!SERIAL_PORT_EMPTY) ;
+ SERIAL_PORT_TX_REGISTER = c;
+ }
+
+Before you can call printf you need to initialize it to use your
+character output function with something like:
+
+ init_printf(NULL,putc);
+
+Notice the 'NULL' in 'init_printf' and the parameter 'void* p' in 'putc',
+the NULL (or any pointer) you pass into the 'init_printf' will eventually be
+passed to your 'putc' routine. This allows you to pass some storage space (or
+anything realy) to the character output function, if necessary.
+This is not often needed but it was implemented like that because it made
+implementing the sprintf function so neat (look at the source code).
+
+The code is re-entrant, except for the 'init_printf' function, so it
+is safe to call it from interupts too, although this may result in mixed output.
+If you rely on re-entrancy, take care that your 'putc' function is re-entrant!
+
+The printf and sprintf functions are actually macros that translate to
+'tfp_printf' and 'tfp_sprintf'. This makes it possible
+to use them along with 'stdio.h' printf's in a single source file.
+You just need to undef the names before you include the 'stdio.h'.
+Note that these are not function like macros, so if you have variables
+or struct members with these names, things will explode in your face.
+Without variadic macros this is the best we can do to wrap these
+fucnction. If it is a problem just give up the macros and use the
+functions directly or rename them.
+
+For further details see source code.
+
+regs Kusti, 23.10.2004
+*/
+
+
+#ifndef __TFP_PRINTF__
+#define __TFP_PRINTF__
+
+#include <stdarg.h>
+
+void init_printf(void* putp,void (*putf) (void*,char));
+
+void tfp_printf(char *fmt, ...);
+void tfp_sprintf(char* s,char *fmt, ...);
+
+void tfp_format(void* putp,void (*putf) (void*,char),char *fmt, va_list va);
+
+#define printf tfp_printf
+#define sprintf tfp_sprintf
+
+#endif
diff --git a/tmk_core/common/chibios/sleep_led.c b/tmk_core/common/chibios/sleep_led.c
new file mode 100644
index 000000000..4c35cfcba
--- /dev/null
+++ b/tmk_core/common/chibios/sleep_led.c
@@ -0,0 +1,226 @@
+#include "ch.h"
+#include "hal.h"
+
+#include "led.h"
+#include "sleep_led.h"
+
+/* All right, we go the "software" way: timer, toggle LED in interrupt.
+ * Based on hasu's code for AVRs.
+ * Use LP timer on Kinetises, TIM14 on STM32F0.
+ */
+
+#if defined(KL2x) || defined(K20x)
+
+/* Use Low Power Timer (LPTMR) */
+#define TIMER_INTERRUPT_VECTOR KINETIS_LPTMR0_IRQ_VECTOR
+#define RESET_COUNTER LPTMR0->CSR |= LPTMRx_CSR_TCF
+
+#elif defined(STM32F0XX)
+
+/* Use TIM14 manually */
+#define TIMER_INTERRUPT_VECTOR STM32_TIM14_HANDLER
+#define RESET_COUNTER STM32_TIM14->SR &= ~STM32_TIM_SR_UIF
+
+#endif
+
+#if defined(KL2x) || defined(K20x) || defined(STM32F0XX) /* common parts for timers/interrupts */
+
+/* Breathing Sleep LED brighness(PWM On period) table
+ * (64[steps] * 4[duration]) / 64[PWM periods/s] = 4 second breath cycle
+ *
+ * http://www.wolframalpha.com/input/?i=%28sin%28+x%2F64*pi%29**8+*+255%2C+x%3D0+to+63
+ * (0..63).each {|x| p ((sin(x/64.0*PI)**8)*255).to_i }
+ */
+static const uint8_t breathing_table[64] = {
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 6, 10,
+15, 23, 32, 44, 58, 74, 93, 113, 135, 157, 179, 199, 218, 233, 245, 252,
+255, 252, 245, 233, 218, 199, 179, 157, 135, 113, 93, 74, 58, 44, 32, 23,
+15, 10, 6, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* interrupt handler */
+OSAL_IRQ_HANDLER(TIMER_INTERRUPT_VECTOR) {
+ OSAL_IRQ_PROLOGUE();
+
+ /* Software PWM
+ * timer:1111 1111 1111 1111
+ * \_____/\/ \_______/____ count(0-255)
+ * \ \______________ duration of step(4)
+ * \__________________ index of step table(0-63)
+ */
+
+ // this works for cca 65536 irqs/sec
+ static union {
+ uint16_t row;
+ struct {
+ uint8_t count:8;
+ uint8_t duration:2;
+ uint8_t index:6;
+ } pwm;
+ } timer = { .row = 0 };
+
+ timer.row++;
+
+ // LED on
+ if (timer.pwm.count == 0) {
+ led_set(1<<USB_LED_CAPS_LOCK);
+ }
+ // LED off
+ if (timer.pwm.count == breathing_table[timer.pwm.index]) {
+ led_set(0);
+ }
+
+ /* Reset the counter */
+ RESET_COUNTER;
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#endif /* common parts for known platforms */
+
+
+#if defined(KL2x) || defined(K20x) /* platform selection: familiar Kinetis chips */
+
+/* LPTMR clock options */
+#define LPTMR_CLOCK_MCGIRCLK 0 /* 4MHz clock */
+#define LPTMR_CLOCK_LPO 1 /* 1kHz clock */
+#define LPTMR_CLOCK_ERCLK32K 2 /* external 32kHz crystal */
+#define LPTMR_CLOCK_OSCERCLK 3 /* output from OSC */
+
+/* Work around inconsistencies in Freescale naming */
+#if !defined(SIM_SCGC5_LPTMR)
+#define SIM_SCGC5_LPTMR SIM_SCGC5_LPTIMER
+#endif
+
+/* Initialise the timer */
+void sleep_led_init(void) {
+ /* Make sure the clock to the LPTMR is enabled */
+ SIM->SCGC5 |= SIM_SCGC5_LPTMR;
+ /* Reset LPTMR settings */
+ LPTMR0->CSR = 0;
+ /* Set the compare value */
+ LPTMR0->CMR = 0; // trigger on counter value (i.e. every time)
+
+ /* Set up clock source and prescaler */
+ /* Software PWM
+ * ______ ______ __
+ * | ON |___OFF___| ON |___OFF___| ....
+ * |<-------------->|<-------------->|<- ....
+ * PWM period PWM period
+ *
+ * R interrupts/period[resolution]
+ * F periods/second[frequency]
+ * R * F interrupts/second
+ */
+
+ /* === OPTION 1 === */
+ #if 0
+ // 1kHz LPO
+ // No prescaler => 1024 irqs/sec
+ // Note: this is too slow for a smooth breathe
+ LPTMR0->PSR = LPTMRx_PSR_PCS(LPTMR_CLOCK_LPO)|LPTMRx_PSR_PBYP;
+ #endif /* OPTION 1 */
+
+ /* === OPTION 2 === */
+ #if 1
+ // nMHz IRC (n=4 on KL25Z, KL26Z and K20x; n=2 or 8 on KL27Z)
+ MCG->C2 |= MCG_C2_IRCS; // fast (4MHz) internal ref clock
+ #if defined(KL27) // divide the 8MHz IRC by 2, to have the same MCGIRCLK speed as others
+ MCG->MC |= MCG_MC_LIRC_DIV2_DIV2;
+ #endif /* KL27 */
+ MCG->C1 |= MCG_C1_IRCLKEN; // enable internal ref clock
+ // to work in stop mode, also MCG_C1_IREFSTEN
+ // Divide 4MHz by 2^N (N=6) => 62500 irqs/sec =>
+ // => approx F=61, R=256, duration = 4
+ LPTMR0->PSR = LPTMRx_PSR_PCS(LPTMR_CLOCK_MCGIRCLK)|LPTMRx_PSR_PRESCALE(6);
+ #endif /* OPTION 2 */
+
+ /* === OPTION 3 === */
+ #if 0
+ // OSC output (external crystal), usually 8MHz or 16MHz
+ OSC0->CR |= OSC_CR_ERCLKEN; // enable ext ref clock
+ // to work in stop mode, also OSC_CR_EREFSTEN
+ // Divide by 2^N
+ LPTMR0->PSR = LPTMRx_PSR_PCS(LPTMR_CLOCK_OSCERCLK)|LPTMRx_PSR_PRESCALE(7);
+ #endif /* OPTION 3 */
+ /* === END OPTIONS === */
+
+ /* Interrupt on TCF set (compare flag) */
+ nvicEnableVector(LPTMR0_IRQn, 2); // vector, priority
+ LPTMR0->CSR |= LPTMRx_CSR_TIE;
+}
+
+void sleep_led_enable(void) {
+ /* Enable the timer */
+ LPTMR0->CSR |= LPTMRx_CSR_TEN;
+}
+
+void sleep_led_disable(void) {
+ /* Disable the timer */
+ LPTMR0->CSR &= ~LPTMRx_CSR_TEN;
+}
+
+void sleep_led_toggle(void) {
+ /* Toggle the timer */
+ LPTMR0->CSR ^= LPTMRx_CSR_TEN;
+}
+
+#elif defined(STM32F0XX) /* platform selection: STM32F0XX */
+
+/* Initialise the timer */
+void sleep_led_init(void) {
+ /* enable clock */
+ rccEnableTIM14(FALSE); /* low power enable = FALSE */
+ rccResetTIM14();
+
+ /* prescale */
+ /* Assuming 48MHz internal clock */
+ /* getting cca 65484 irqs/sec */
+ STM32_TIM14->PSC = 733;
+
+ /* auto-reload */
+ /* 0 => interrupt every time */
+ STM32_TIM14->ARR = 3;
+
+ /* enable counter update event interrupt */
+ STM32_TIM14->DIER |= STM32_TIM_DIER_UIE;
+
+ /* register interrupt vector */
+ nvicEnableVector(STM32_TIM14_NUMBER, 2); /* vector, priority */
+}
+
+void sleep_led_enable(void) {
+ /* Enable the timer */
+ STM32_TIM14->CR1 = STM32_TIM_CR1_CEN | STM32_TIM_CR1_URS;
+ /* URS => update event only on overflow; setting UG bit disabled */
+}
+
+void sleep_led_disable(void) {
+ /* Disable the timer */
+ STM32_TIM14->CR1 = 0;
+}
+
+void sleep_led_toggle(void) {
+ /* Toggle the timer */
+ STM32_TIM14->CR1 ^= STM32_TIM_CR1_CEN;
+}
+
+
+#else /* platform selection: not on familiar chips */
+
+void sleep_led_init(void) {
+}
+
+void sleep_led_enable(void) {
+ led_set(1<<USB_LED_CAPS_LOCK);
+}
+
+void sleep_led_disable(void) {
+ led_set(0);
+}
+
+void sleep_led_toggle(void) {
+ // not implemented
+}
+
+#endif /* platform selection */ \ No newline at end of file
diff --git a/tmk_core/common/chibios/suspend.c b/tmk_core/common/chibios/suspend.c
new file mode 100644
index 000000000..6ca16034f
--- /dev/null
+++ b/tmk_core/common/chibios/suspend.c
@@ -0,0 +1,65 @@
+/* TODO */
+
+#include "ch.h"
+#include "hal.h"
+
+#include "matrix.h"
+#include "action.h"
+#include "action_util.h"
+#include "mousekey.h"
+#include "host.h"
+#include "backlight.h"
+#include "suspend.h"
+
+void suspend_idle(uint8_t time) {
+ // TODO: this is not used anywhere - what units is 'time' in?
+ chThdSleepMilliseconds(time);
+}
+
+void suspend_power_down(void) {
+ // TODO: figure out what to power down and how
+ // shouldn't power down TPM/FTM if we want a breathing LED
+ // also shouldn't power down USB
+
+ // on AVR, this enables the watchdog for 15ms (max), and goes to
+ // SLEEP_MODE_PWR_DOWN
+
+ chThdSleepMilliseconds(17);
+}
+
+__attribute__ ((weak)) void matrix_power_up(void) {}
+__attribute__ ((weak)) void matrix_power_down(void) {}
+bool suspend_wakeup_condition(void)
+{
+ matrix_power_up();
+ matrix_scan();
+ matrix_power_down();
+ for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
+ if (matrix_get_row(r)) return true;
+ }
+ return false;
+}
+
+// run immediately after wakeup
+void suspend_wakeup_init(void)
+{
+ // clear keyboard state
+ // need to do it manually, because we're running from ISR
+ // and clear_keyboard() calls print
+ // so only clear the variables in memory
+ // the reports will be sent from main.c afterwards
+ // or if the PC asks for GET_REPORT
+ clear_mods();
+ clear_weak_mods();
+ clear_keys();
+#ifdef MOUSEKEY_ENABLE
+ mousekey_clear();
+#endif /* MOUSEKEY_ENABLE */
+#ifdef EXTRAKEY_ENABLE
+ host_system_send(0);
+ host_consumer_send(0);
+#endif /* EXTRAKEY_ENABLE */
+#ifdef BACKLIGHT_ENABLE
+ backlight_init();
+#endif /* BACKLIGHT_ENABLE */
+}
diff --git a/tmk_core/common/chibios/timer.c b/tmk_core/common/chibios/timer.c
new file mode 100644
index 000000000..3de4cc368
--- /dev/null
+++ b/tmk_core/common/chibios/timer.c
@@ -0,0 +1,27 @@
+#include "ch.h"
+
+#include "timer.h"
+
+void timer_init(void) {}
+
+void timer_clear(void) {}
+
+uint16_t timer_read(void)
+{
+ return (uint16_t)ST2MS(chVTGetSystemTime());
+}
+
+uint32_t timer_read32(void)
+{
+ return ST2MS(chVTGetSystemTime());
+}
+
+uint16_t timer_elapsed(uint16_t last)
+{
+ return (uint16_t)(ST2MS(chVTTimeElapsedSinceX(MS2ST(last))));
+}
+
+uint32_t timer_elapsed32(uint32_t last)
+{
+ return ST2MS(chVTTimeElapsedSinceX(MS2ST(last)));
+}
diff --git a/tmk_core/common/command.c b/tmk_core/common/command.c
new file mode 100644
index 000000000..084c9fe15
--- /dev/null
+++ b/tmk_core/common/command.c
@@ -0,0 +1,794 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <stdint.h>
+#include <stdbool.h>
+#include "wait.h"
+#include "keycode.h"
+#include "host.h"
+#include "keymap.h"
+#include "print.h"
+#include "debug.h"
+#include "util.h"
+#include "timer.h"
+#include "keyboard.h"
+#include "bootloader.h"
+#include "action_layer.h"
+#include "action_util.h"
+#include "eeconfig.h"
+#include "sleep_led.h"
+#include "led.h"
+#include "command.h"
+#include "backlight.h"
+#include "quantum.h"
+
+#ifdef MOUSEKEY_ENABLE
+#include "mousekey.h"
+#endif
+
+#ifdef PROTOCOL_PJRC
+ #include "usb_keyboard.h"
+ #ifdef EXTRAKEY_ENABLE
+ #include "usb_extra.h"
+ #endif
+#endif
+
+#ifdef PROTOCOL_VUSB
+ #include "usbdrv.h"
+#endif
+
+#ifdef AUDIO_ENABLE
+ #include "audio.h"
+#endif /* AUDIO_ENABLE */
+
+
+static bool command_common(uint8_t code);
+static void command_common_help(void);
+static void print_version(void);
+static void print_status(void);
+static bool command_console(uint8_t code);
+static void command_console_help(void);
+#ifdef MOUSEKEY_ENABLE
+static bool mousekey_console(uint8_t code);
+static void mousekey_console_help(void);
+#endif
+
+static void switch_default_layer(uint8_t layer);
+
+
+command_state_t command_state = ONESHOT;
+
+
+bool command_proc(uint8_t code)
+{
+ switch (command_state) {
+ case ONESHOT:
+ if (!IS_COMMAND())
+ return false;
+ return (command_extra(code) || command_common(code));
+ break;
+ case CONSOLE:
+ if (IS_COMMAND())
+ return (command_extra(code) || command_common(code));
+ else
+ return (command_console_extra(code) || command_console(code));
+ break;
+#ifdef MOUSEKEY_ENABLE
+ case MOUSEKEY:
+ mousekey_console(code);
+ break;
+#endif
+ default:
+ command_state = ONESHOT;
+ return false;
+ }
+ return true;
+}
+
+/* TODO: Refactoring is needed. */
+/* This allows to define extra commands. return false when not processed. */
+bool command_extra(uint8_t code) __attribute__ ((weak));
+bool command_extra(uint8_t code)
+{
+ (void)code;
+ return false;
+}
+
+bool command_console_extra(uint8_t code) __attribute__ ((weak));
+bool command_console_extra(uint8_t code)
+{
+ (void)code;
+ return false;
+}
+
+
+/***********************************************************
+ * Command common
+ ***********************************************************/
+static void command_common_help(void)
+{
+ print( "\n\t- Magic -\n"
+ STR(MAGIC_KEY_DEBUG ) ": Debug Message Toggle\n"
+ STR(MAGIC_KEY_DEBUG_MATRIX) ": Matrix Debug Mode Toggle - Show keypresses in matrix grid\n"
+ STR(MAGIC_KEY_DEBUG_KBD ) ": Keyboard Debug Toggle - Show keypress report\n"
+ STR(MAGIC_KEY_DEBUG_MOUSE ) ": Debug Mouse Toggle\n"
+ STR(MAGIC_KEY_VERSION ) ": Version\n"
+ STR(MAGIC_KEY_STATUS ) ": Status\n"
+ STR(MAGIC_KEY_CONSOLE ) ": Activate Console Mode\n"
+
+#if MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM
+ STR(MAGIC_KEY_LAYER0 ) ": Switch to Layer 0\n"
+ STR(MAGIC_KEY_LAYER1 ) ": Switch to Layer 1\n"
+ STR(MAGIC_KEY_LAYER2 ) ": Switch to Layer 2\n"
+ STR(MAGIC_KEY_LAYER3 ) ": Switch to Layer 3\n"
+ STR(MAGIC_KEY_LAYER4 ) ": Switch to Layer 4\n"
+ STR(MAGIC_KEY_LAYER5 ) ": Switch to Layer 5\n"
+ STR(MAGIC_KEY_LAYER6 ) ": Switch to Layer 6\n"
+ STR(MAGIC_KEY_LAYER7 ) ": Switch to Layer 7\n"
+ STR(MAGIC_KEY_LAYER8 ) ": Switch to Layer 8\n"
+ STR(MAGIC_KEY_LAYER9 ) ": Switch to Layer 9\n"
+#endif
+
+#if MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS
+ "F1-F10: Switch to Layer 0-9 (F10 = L0)\n"
+#endif
+
+#if MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS
+ "0-9: Switch to Layer 0-9\n"
+#endif
+
+ STR(MAGIC_KEY_LAYER0_ALT1 ) ": Switch to Layer 0 (alternate key 1)\n"
+ STR(MAGIC_KEY_LAYER0_ALT2 ) ": Switch to Layer 0 (alternate key 2)\n"
+ STR(MAGIC_KEY_BOOTLOADER ) ": Jump to Bootloader (Reset)\n"
+
+#ifdef KEYBOARD_LOCK_ENABLE
+ STR(MAGIC_KEY_LOCK ) ": Lock\n"
+#endif
+
+#ifdef BOOTMAGIC_ENABLE
+ STR(MAGIC_KEY_EEPROM ) ": Print EEPROM Settings\n"
+#endif
+
+#ifdef NKRO_ENABLE
+ STR(MAGIC_KEY_NKRO ) ": NKRO Toggle\n"
+#endif
+
+#ifdef SLEEP_LED_ENABLE
+ STR(MAGIC_KEY_SLEEP_LED ) ": Sleep LED Test\n"
+#endif
+ );
+}
+
+static void print_version(void)
+{
+ // print version & information
+ print("\n\t- Version -\n");
+ print("DESC: " STR(DESCRIPTION) "\n");
+ print("VID: " STR(VENDOR_ID) "(" STR(MANUFACTURER) ") "
+ "PID: " STR(PRODUCT_ID) "(" STR(PRODUCT) ") "
+ "VER: " STR(DEVICE_VER) "\n");
+ print("BUILD: " STR(VERSION) " (" __TIME__ " " __DATE__ ")\n");
+
+ /* build options */
+ print("OPTIONS:"
+
+#ifdef PROTOCOL_PJRC
+ " PJRC"
+#endif
+#ifdef PROTOCOL_LUFA
+ " LUFA"
+#endif
+#ifdef PROTOCOL_VUSB
+ " VUSB"
+#endif
+#ifdef BOOTMAGIC_ENABLE
+ " BOOTMAGIC"
+#endif
+#ifdef MOUSEKEY_ENABLE
+ " MOUSEKEY"
+#endif
+#ifdef EXTRAKEY_ENABLE
+ " EXTRAKEY"
+#endif
+#ifdef CONSOLE_ENABLE
+ " CONSOLE"
+#endif
+#ifdef COMMAND_ENABLE
+ " COMMAND"
+#endif
+#ifdef NKRO_ENABLE
+ " NKRO"
+#endif
+#ifdef KEYMAP_SECTION_ENABLE
+ " KEYMAP_SECTION"
+#endif
+
+ " " STR(BOOTLOADER_SIZE) "\n");
+
+ print("GCC: " STR(__GNUC__) "." STR(__GNUC_MINOR__) "." STR(__GNUC_PATCHLEVEL__)
+#if defined(__AVR__)
+ " AVR-LIBC: " __AVR_LIBC_VERSION_STRING__
+ " AVR_ARCH: avr" STR(__AVR_ARCH__)
+#endif
+ "\n");
+
+ return;
+}
+
+static void print_status(void)
+{
+
+ print("\n\t- Status -\n");
+
+ print_val_hex8(host_keyboard_leds());
+ print_val_hex8(keyboard_protocol);
+ print_val_hex8(keyboard_idle);
+#ifdef NKRO_ENABLE
+ print_val_hex8(keyboard_nkro);
+#endif
+ print_val_hex32(timer_read32());
+
+#ifdef PROTOCOL_PJRC
+ print_val_hex8(UDCON);
+ print_val_hex8(UDIEN);
+ print_val_hex8(UDINT);
+ print_val_hex8(usb_keyboard_leds);
+ print_val_hex8(usb_keyboard_idle_count);
+#endif
+
+#ifdef PROTOCOL_PJRC
+# if USB_COUNT_SOF
+ print_val_hex8(usbSofCount);
+# endif
+#endif
+ return;
+}
+
+#ifdef BOOTMAGIC_ENABLE
+static void print_eeconfig(void)
+{
+#ifndef NO_PRINT
+ print("default_layer: "); print_dec(eeconfig_read_default_layer()); print("\n");
+
+ debug_config_t dc;
+ dc.raw = eeconfig_read_debug();
+ print("debug_config.raw: "); print_hex8(dc.raw); print("\n");
+ print(".enable: "); print_dec(dc.enable); print("\n");
+ print(".matrix: "); print_dec(dc.matrix); print("\n");
+ print(".keyboard: "); print_dec(dc.keyboard); print("\n");
+ print(".mouse: "); print_dec(dc.mouse); print("\n");
+
+ keymap_config_t kc;
+ kc.raw = eeconfig_read_keymap();
+ print("keymap_config.raw: "); print_hex8(kc.raw); print("\n");
+ print(".swap_control_capslock: "); print_dec(kc.swap_control_capslock); print("\n");
+ print(".capslock_to_control: "); print_dec(kc.capslock_to_control); print("\n");
+ print(".swap_lalt_lgui: "); print_dec(kc.swap_lalt_lgui); print("\n");
+ print(".swap_ralt_rgui: "); print_dec(kc.swap_ralt_rgui); print("\n");
+ print(".no_gui: "); print_dec(kc.no_gui); print("\n");
+ print(".swap_grave_esc: "); print_dec(kc.swap_grave_esc); print("\n");
+ print(".swap_backslash_backspace: "); print_dec(kc.swap_backslash_backspace); print("\n");
+ print(".nkro: "); print_dec(kc.nkro); print("\n");
+
+#ifdef BACKLIGHT_ENABLE
+ backlight_config_t bc;
+ bc.raw = eeconfig_read_backlight();
+ print("backlight_config.raw: "); print_hex8(bc.raw); print("\n");
+ print(".enable: "); print_dec(bc.enable); print("\n");
+ print(".level: "); print_dec(bc.level); print("\n");
+#endif /* BACKLIGHT_ENABLE */
+
+#endif /* !NO_PRINT */
+
+}
+#endif /* BOOTMAGIC_ENABLE */
+
+static bool command_common(uint8_t code)
+{
+
+#ifdef KEYBOARD_LOCK_ENABLE
+ static host_driver_t *host_driver = 0;
+#endif
+
+ switch (code) {
+
+#ifdef SLEEP_LED_ENABLE
+
+ // test breathing sleep LED
+ case MAGIC_KC(MAGIC_KEY_SLEEP_LED):
+ print("Sleep LED Test\n");
+ sleep_led_toggle();
+ led_set(host_keyboard_leds());
+ break;
+#endif
+
+#ifdef BOOTMAGIC_ENABLE
+
+ // print stored eeprom config
+ case MAGIC_KC(MAGIC_KEY_EEPROM):
+ print("eeconfig:\n");
+ print_eeconfig();
+ break;
+#endif
+
+#ifdef KEYBOARD_LOCK_ENABLE
+
+ // lock/unlock keyboard
+ case MAGIC_KC(MAGIC_KEY_LOCK):
+ if (host_get_driver()) {
+ host_driver = host_get_driver();
+ clear_keyboard();
+ host_set_driver(0);
+ print("Locked.\n");
+ } else {
+ host_set_driver(host_driver);
+ print("Unlocked.\n");
+ }
+ break;
+#endif
+
+ // print help
+ case MAGIC_KC(MAGIC_KEY_HELP1):
+ case MAGIC_KC(MAGIC_KEY_HELP2):
+ command_common_help();
+ break;
+
+ // activate console
+ case MAGIC_KC(MAGIC_KEY_CONSOLE):
+ debug_matrix = false;
+ debug_keyboard = false;
+ debug_mouse = false;
+ debug_enable = false;
+ command_console_help();
+ print("C> ");
+ command_state = CONSOLE;
+ break;
+
+ // jump to bootloader
+ case MAGIC_KC(MAGIC_KEY_BOOTLOADER):
+ clear_keyboard(); // clear to prevent stuck keys
+ print("\n\nJumping to bootloader... ");
+ #ifdef AUDIO_ENABLE
+ stop_all_notes();
+ shutdown_user();
+ #else
+ wait_ms(1000);
+ #endif
+ bootloader_jump(); // not return
+ break;
+
+ // debug toggle
+ case MAGIC_KC(MAGIC_KEY_DEBUG):
+ debug_enable = !debug_enable;
+ if (debug_enable) {
+ print("\ndebug: on\n");
+ debug_matrix = true;
+ debug_keyboard = true;
+ debug_mouse = true;
+ } else {
+ print("\ndebug: off\n");
+ debug_matrix = false;
+ debug_keyboard = false;
+ debug_mouse = false;
+ }
+ break;
+
+ // debug matrix toggle
+ case MAGIC_KC(MAGIC_KEY_DEBUG_MATRIX):
+ debug_matrix = !debug_matrix;
+ if (debug_matrix) {
+ print("\nmatrix: on\n");
+ debug_enable = true;
+ } else {
+ print("\nmatrix: off\n");
+ }
+ break;
+
+ // debug keyboard toggle
+ case MAGIC_KC(MAGIC_KEY_DEBUG_KBD):
+ debug_keyboard = !debug_keyboard;
+ if (debug_keyboard) {
+ print("\nkeyboard: on\n");
+ debug_enable = true;
+ } else {
+ print("\nkeyboard: off\n");
+ }
+ break;
+
+ // debug mouse toggle
+ case MAGIC_KC(MAGIC_KEY_DEBUG_MOUSE):
+ debug_mouse = !debug_mouse;
+ if (debug_mouse) {
+ print("\nmouse: on\n");
+ debug_enable = true;
+ } else {
+ print("\nmouse: off\n");
+ }
+ break;
+
+ // print version
+ case MAGIC_KC(MAGIC_KEY_VERSION):
+ print_version();
+ break;
+
+ // print status
+ case MAGIC_KC(MAGIC_KEY_STATUS):
+ print_status();
+ break;
+
+#ifdef NKRO_ENABLE
+
+ // NKRO toggle
+ case MAGIC_KC(MAGIC_KEY_NKRO):
+ clear_keyboard(); // clear to prevent stuck keys
+ keyboard_nkro = !keyboard_nkro;
+ if (keyboard_nkro) {
+ print("NKRO: on\n");
+ } else {
+ print("NKRO: off\n");
+ }
+ break;
+#endif
+
+ // switch layers
+
+ case MAGIC_KC(MAGIC_KEY_LAYER0_ALT1):
+ case MAGIC_KC(MAGIC_KEY_LAYER0_ALT2):
+ switch_default_layer(0);
+ break;
+
+#if MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM
+
+ case MAGIC_KC(MAGIC_KEY_LAYER0):
+ switch_default_layer(0);
+ break;
+
+ case MAGIC_KC(MAGIC_KEY_LAYER1):
+ switch_default_layer(1);
+ break;
+
+ case MAGIC_KC(MAGIC_KEY_LAYER2):
+ switch_default_layer(2);
+ break;
+
+ case MAGIC_KC(MAGIC_KEY_LAYER3):
+ switch_default_layer(3);
+ break;
+
+ case MAGIC_KC(MAGIC_KEY_LAYER4):
+ switch_default_layer(4);
+ break;
+
+ case MAGIC_KC(MAGIC_KEY_LAYER5):
+ switch_default_layer(5);
+ break;
+
+ case MAGIC_KC(MAGIC_KEY_LAYER6):
+ switch_default_layer(6);
+ break;
+
+ case MAGIC_KC(MAGIC_KEY_LAYER7):
+ switch_default_layer(7);
+ break;
+
+ case MAGIC_KC(MAGIC_KEY_LAYER8):
+ switch_default_layer(8);
+ break;
+
+ case MAGIC_KC(MAGIC_KEY_LAYER9):
+ switch_default_layer(9);
+ break;
+#endif
+
+
+#if MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS
+
+ case KC_F1 ... KC_F9:
+ switch_default_layer((code - KC_F1) + 1);
+ break;
+ case KC_F10:
+ switch_default_layer(0);
+ break;
+#endif
+
+#if MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS
+
+ case KC_1 ... KC_9:
+ switch_default_layer((code - KC_1) + 1);
+ break;
+ case KC_0:
+ switch_default_layer(0);
+ break;
+#endif
+
+ default:
+ print("?");
+ return false;
+ }
+ return true;
+}
+
+
+/***********************************************************
+ * Command console
+ ***********************************************************/
+static void command_console_help(void)
+{
+ print("\n\t- Console -\n"
+ "ESC/q: quit\n"
+#ifdef MOUSEKEY_ENABLE
+ "m: mousekey\n"
+#endif
+ );
+}
+
+static bool command_console(uint8_t code)
+{
+ switch (code) {
+ case KC_H:
+ case KC_SLASH: /* ? */
+ command_console_help();
+ break;
+ case KC_Q:
+ case KC_ESC:
+ command_state = ONESHOT;
+ return false;
+#ifdef MOUSEKEY_ENABLE
+ case KC_M:
+ mousekey_console_help();
+ print("M> ");
+ command_state = MOUSEKEY;
+ return true;
+#endif
+ default:
+ print("?");
+ return false;
+ }
+ print("C> ");
+ return true;
+}
+
+
+#ifdef MOUSEKEY_ENABLE
+/***********************************************************
+ * Mousekey console
+ ***********************************************************/
+static uint8_t mousekey_param = 0;
+
+static void mousekey_param_print(void)
+{
+#ifndef NO_PRINT
+ print("\n\t- Values -\n");
+ print("1: delay(*10ms): "); pdec(mk_delay); print("\n");
+ print("2: interval(ms): "); pdec(mk_interval); print("\n");
+ print("3: max_speed: "); pdec(mk_max_speed); print("\n");
+ print("4: time_to_max: "); pdec(mk_time_to_max); print("\n");
+ print("5: wheel_max_speed: "); pdec(mk_wheel_max_speed); print("\n");
+ print("6: wheel_time_to_max: "); pdec(mk_wheel_time_to_max); print("\n");
+#endif /* !NO_PRINT */
+
+}
+
+//#define PRINT_SET_VAL(v) print(#v " = "); print_dec(v); print("\n");
+#define PRINT_SET_VAL(v) xprintf(#v " = %d\n", (v))
+static void mousekey_param_inc(uint8_t param, uint8_t inc)
+{
+ switch (param) {
+ case 1:
+ if (mk_delay + inc < UINT8_MAX)
+ mk_delay += inc;
+ else
+ mk_delay = UINT8_MAX;
+ PRINT_SET_VAL(mk_delay);
+ break;
+ case 2:
+ if (mk_interval + inc < UINT8_MAX)
+ mk_interval += inc;
+ else
+ mk_interval = UINT8_MAX;
+ PRINT_SET_VAL(mk_interval);
+ break;
+ case 3:
+ if (mk_max_speed + inc < UINT8_MAX)
+ mk_max_speed += inc;
+ else
+ mk_max_speed = UINT8_MAX;
+ PRINT_SET_VAL(mk_max_speed);
+ break;
+ case 4:
+ if (mk_time_to_max + inc < UINT8_MAX)
+ mk_time_to_max += inc;
+ else
+ mk_time_to_max = UINT8_MAX;
+ PRINT_SET_VAL(mk_time_to_max);
+ break;
+ case 5:
+ if (mk_wheel_max_speed + inc < UINT8_MAX)
+ mk_wheel_max_speed += inc;
+ else
+ mk_wheel_max_speed = UINT8_MAX;
+ PRINT_SET_VAL(mk_wheel_max_speed);
+ break;
+ case 6:
+ if (mk_wheel_time_to_max + inc < UINT8_MAX)
+ mk_wheel_time_to_max += inc;
+ else
+ mk_wheel_time_to_max = UINT8_MAX;
+ PRINT_SET_VAL(mk_wheel_time_to_max);
+ break;
+ }
+}
+
+static void mousekey_param_dec(uint8_t param, uint8_t dec)
+{
+ switch (param) {
+ case 1:
+ if (mk_delay > dec)
+ mk_delay -= dec;
+ else
+ mk_delay = 0;
+ PRINT_SET_VAL(mk_delay);
+ break;
+ case 2:
+ if (mk_interval > dec)
+ mk_interval -= dec;
+ else
+ mk_interval = 0;
+ PRINT_SET_VAL(mk_interval);
+ break;
+ case 3:
+ if (mk_max_speed > dec)
+ mk_max_speed -= dec;
+ else
+ mk_max_speed = 0;
+ PRINT_SET_VAL(mk_max_speed);
+ break;
+ case 4:
+ if (mk_time_to_max > dec)
+ mk_time_to_max -= dec;
+ else
+ mk_time_to_max = 0;
+ PRINT_SET_VAL(mk_time_to_max);
+ break;
+ case 5:
+ if (mk_wheel_max_speed > dec)
+ mk_wheel_max_speed -= dec;
+ else
+ mk_wheel_max_speed = 0;
+ PRINT_SET_VAL(mk_wheel_max_speed);
+ break;
+ case 6:
+ if (mk_wheel_time_to_max > dec)
+ mk_wheel_time_to_max -= dec;
+ else
+ mk_wheel_time_to_max = 0;
+ PRINT_SET_VAL(mk_wheel_time_to_max);
+ break;
+ }
+}
+
+static void mousekey_console_help(void)
+{
+ print("\n\t- Mousekey -\n"
+ "ESC/q: quit\n"
+ "1: delay(*10ms)\n"
+ "2: interval(ms)\n"
+ "3: max_speed\n"
+ "4: time_to_max\n"
+ "5: wheel_max_speed\n"
+ "6: wheel_time_to_max\n"
+ "\n"
+ "p: print values\n"
+ "d: set defaults\n"
+ "up: +1\n"
+ "down: -1\n"
+ "pgup: +10\n"
+ "pgdown: -10\n"
+ "\n"
+ "speed = delta * max_speed * (repeat / time_to_max)\n");
+ xprintf("where delta: cursor=%d, wheel=%d\n"
+ "See http://en.wikipedia.org/wiki/Mouse_keys\n", MOUSEKEY_MOVE_DELTA, MOUSEKEY_WHEEL_DELTA);
+}
+
+static bool mousekey_console(uint8_t code)
+{
+ switch (code) {
+ case KC_H:
+ case KC_SLASH: /* ? */
+ mousekey_console_help();
+ break;
+ case KC_Q:
+ case KC_ESC:
+ if (mousekey_param) {
+ mousekey_param = 0;
+ } else {
+ print("C> ");
+ command_state = CONSOLE;
+ return false;
+ }
+ break;
+ case KC_P:
+ mousekey_param_print();
+ break;
+ case KC_1:
+ case KC_2:
+ case KC_3:
+ case KC_4:
+ case KC_5:
+ case KC_6:
+ mousekey_param = numkey2num(code);
+ break;
+ case KC_UP:
+ mousekey_param_inc(mousekey_param, 1);
+ break;
+ case KC_DOWN:
+ mousekey_param_dec(mousekey_param, 1);
+ break;
+ case KC_PGUP:
+ mousekey_param_inc(mousekey_param, 10);
+ break;
+ case KC_PGDN:
+ mousekey_param_dec(mousekey_param, 10);
+ break;
+ case KC_D:
+ mk_delay = MOUSEKEY_DELAY/10;
+ mk_interval = MOUSEKEY_INTERVAL;
+ mk_max_speed = MOUSEKEY_MAX_SPEED;
+ mk_time_to_max = MOUSEKEY_TIME_TO_MAX;
+ mk_wheel_max_speed = MOUSEKEY_WHEEL_MAX_SPEED;
+ mk_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX;
+ print("set default\n");
+ break;
+ default:
+ print("?");
+ return false;
+ }
+ if (mousekey_param) {
+ xprintf("M%d> ", mousekey_param);
+ } else {
+ print("M>" );
+ }
+ return true;
+}
+#endif
+
+
+/***********************************************************
+ * Utilities
+ ***********************************************************/
+uint8_t numkey2num(uint8_t code)
+{
+ switch (code) {
+ case KC_1: return 1;
+ case KC_2: return 2;
+ case KC_3: return 3;
+ case KC_4: return 4;
+ case KC_5: return 5;
+ case KC_6: return 6;
+ case KC_7: return 7;
+ case KC_8: return 8;
+ case KC_9: return 9;
+ case KC_0: return 0;
+ }
+ return 0;
+}
+
+static void switch_default_layer(uint8_t layer)
+{
+ xprintf("L%d\n", layer);
+ default_layer_set(1UL<<layer);
+ clear_keyboard();
+}
diff --git a/tmk_core/common/command.h b/tmk_core/common/command.h
new file mode 100644
index 000000000..a729e4b1e
--- /dev/null
+++ b/tmk_core/common/command.h
@@ -0,0 +1,157 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef COMMAND_H
+#define COMMAND
+
+/* TODO: Refactoring */
+typedef enum { ONESHOT, CONSOLE, MOUSEKEY } command_state_t;
+extern command_state_t command_state;
+
+/* This allows to extend commands. Return false when command is not processed. */
+bool command_extra(uint8_t code);
+bool command_console_extra(uint8_t code);
+
+#ifdef COMMAND_ENABLE
+uint8_t numkey2num(uint8_t code);
+bool command_proc(uint8_t code);
+#else
+#define command_proc(code) false
+#endif
+
+
+#ifndef MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS
+#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS true
+#endif
+
+#ifndef MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS
+#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS true
+#endif
+
+#ifndef MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM
+#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM false
+#endif
+
+#ifndef MAGIC_KEY_HELP1
+#define MAGIC_KEY_HELP1 H
+#endif
+
+#ifndef MAGIC_KEY_HELP2
+#define MAGIC_KEY_HELP2 SLASH
+#endif
+
+#ifndef MAGIC_KEY_DEBUG
+#define MAGIC_KEY_DEBUG D
+#endif
+
+#ifndef MAGIC_KEY_DEBUG_MATRIX
+#define MAGIC_KEY_DEBUG_MATRIX X
+#endif
+
+#ifndef MAGIC_KEY_DEBUG_KBD
+#define MAGIC_KEY_DEBUG_KBD K
+#endif
+
+#ifndef MAGIC_KEY_DEBUG_MOUSE
+#define MAGIC_KEY_DEBUG_MOUSE M
+#endif
+
+#ifndef MAGIC_KEY_VERSION
+#define MAGIC_KEY_VERSION V
+#endif
+
+#ifndef MAGIC_KEY_STATUS
+#define MAGIC_KEY_STATUS S
+#endif
+
+#ifndef MAGIC_KEY_CONSOLE
+#define MAGIC_KEY_CONSOLE C
+#endif
+
+#ifndef MAGIC_KEY_LAYER0_ALT1
+#define MAGIC_KEY_LAYER0_ALT1 ESC
+#endif
+
+#ifndef MAGIC_KEY_LAYER0_ALT2
+#define MAGIC_KEY_LAYER0_ALT2 GRAVE
+#endif
+
+#ifndef MAGIC_KEY_LAYER0
+#define MAGIC_KEY_LAYER0 0
+#endif
+
+#ifndef MAGIC_KEY_LAYER1
+#define MAGIC_KEY_LAYER1 1
+#endif
+
+#ifndef MAGIC_KEY_LAYER2
+#define MAGIC_KEY_LAYER2 2
+#endif
+
+#ifndef MAGIC_KEY_LAYER3
+#define MAGIC_KEY_LAYER3 3
+#endif
+
+#ifndef MAGIC_KEY_LAYER4
+#define MAGIC_KEY_LAYER4 4
+#endif
+
+#ifndef MAGIC_KEY_LAYER5
+#define MAGIC_KEY_LAYER5 5
+#endif
+
+#ifndef MAGIC_KEY_LAYER6
+#define MAGIC_KEY_LAYER6 6
+#endif
+
+#ifndef MAGIC_KEY_LAYER7
+#define MAGIC_KEY_LAYER7 7
+#endif
+
+#ifndef MAGIC_KEY_LAYER8
+#define MAGIC_KEY_LAYER8 8
+#endif
+
+#ifndef MAGIC_KEY_LAYER9
+#define MAGIC_KEY_LAYER9 9
+#endif
+
+#ifndef MAGIC_KEY_BOOTLOADER
+#define MAGIC_KEY_BOOTLOADER PAUSE
+#endif
+
+#ifndef MAGIC_KEY_LOCK
+#define MAGIC_KEY_LOCK CAPS
+#endif
+
+#ifndef MAGIC_KEY_EEPROM
+#define MAGIC_KEY_EEPROM E
+#endif
+
+#ifndef MAGIC_KEY_NKRO
+#define MAGIC_KEY_NKRO N
+#endif
+
+#ifndef MAGIC_KEY_SLEEP_LED
+#define MAGIC_KEY_SLEEP_LED Z
+
+#endif
+
+#define XMAGIC_KC(key) KC_##key
+#define MAGIC_KC(key) XMAGIC_KC(key)
+
+#endif \ No newline at end of file
diff --git a/tmk_core/common/debug.c b/tmk_core/common/debug.c
new file mode 100644
index 000000000..18613fc28
--- /dev/null
+++ b/tmk_core/common/debug.c
@@ -0,0 +1,24 @@
+#include <stdbool.h>
+#include "debug.h"
+
+#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+
+debug_config_t debug_config = {
+/* GCC Bug 10676 - Using unnamed fields in initializers
+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=10676 */
+#if GCC_VERSION >= 40600
+ .enable = false,
+ .matrix = false,
+ .keyboard = false,
+ .mouse = false,
+ .reserved = 0
+#else
+ {
+ false, // .enable
+ false, // .matrix
+ false, // .keyboard
+ false, // .mouse
+ 0 // .reserved
+ }
+#endif
+};
diff --git a/tmk_core/common/debug.h b/tmk_core/common/debug.h
new file mode 100644
index 000000000..3cbe2092d
--- /dev/null
+++ b/tmk_core/common/debug.h
@@ -0,0 +1,117 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef DEBUG_H
+#define DEBUG_H 1
+
+#include <stdbool.h>
+#include "print.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Debug output control
+ */
+typedef union {
+ struct {
+ bool enable:1;
+ bool matrix:1;
+ bool keyboard:1;
+ bool mouse:1;
+ uint8_t reserved:4;
+ };
+ uint8_t raw;
+} debug_config_t;
+
+extern debug_config_t debug_config;
+
+#ifdef __cplusplus
+}
+#endif
+
+/* for backward compatibility */
+#define debug_enable (debug_config.enable)
+#define debug_matrix (debug_config.matrix)
+#define debug_keyboard (debug_config.keyboard)
+#define debug_mouse (debug_config.mouse)
+
+
+/*
+ * Debug print utils
+ */
+#ifndef NO_DEBUG
+
+#define dprint(s) do { if (debug_enable) print(s); } while (0)
+#define dprintln(s) do { if (debug_enable) println(s); } while (0)
+#define dprintf(fmt, ...) do { if (debug_enable) xprintf(fmt, ##__VA_ARGS__); } while (0)
+#define dmsg(s) dprintf("%s at %s: %S\n", __FILE__, __LINE__, PSTR(s))
+
+/* Deprecated. DO NOT USE these anymore, use dprintf instead. */
+#define debug(s) do { if (debug_enable) print(s); } while (0)
+#define debugln(s) do { if (debug_enable) println(s); } while (0)
+#define debug_msg(s) do { \
+ if (debug_enable) { \
+ print(__FILE__); print(" at "); print_dec(__LINE__); print(" in "); print(": "); print(s); \
+ } \
+} while (0)
+#define debug_dec(data) do { if (debug_enable) print_dec(data); } while (0)
+#define debug_decs(data) do { if (debug_enable) print_decs(data); } while (0)
+#define debug_hex4(data) do { if (debug_enable) print_hex4(data); } while (0)
+#define debug_hex8(data) do { if (debug_enable) print_hex8(data); } while (0)
+#define debug_hex16(data) do { if (debug_enable) print_hex16(data); } while (0)
+#define debug_hex32(data) do { if (debug_enable) print_hex32(data); } while (0)
+#define debug_bin8(data) do { if (debug_enable) print_bin8(data); } while (0)
+#define debug_bin16(data) do { if (debug_enable) print_bin16(data); } while (0)
+#define debug_bin32(data) do { if (debug_enable) print_bin32(data); } while (0)
+#define debug_bin_reverse8(data) do { if (debug_enable) print_bin_reverse8(data); } while (0)
+#define debug_bin_reverse16(data) do { if (debug_enable) print_bin_reverse16(data); } while (0)
+#define debug_bin_reverse32(data) do { if (debug_enable) print_bin_reverse32(data); } while (0)
+#define debug_hex(data) debug_hex8(data)
+#define debug_bin(data) debug_bin8(data)
+#define debug_bin_reverse(data) debug_bin8(data)
+
+#else /* NO_DEBUG */
+
+#define dprint(s)
+#define dprintln(s)
+#define dprintf(fmt, ...)
+#define dmsg(s)
+#define debug(s)
+#define debugln(s)
+#define debug_msg(s)
+#define debug_dec(data)
+#define debug_decs(data)
+#define debug_hex4(data)
+#define debug_hex8(data)
+#define debug_hex16(data)
+#define debug_hex32(data)
+#define debug_bin8(data)
+#define debug_bin16(data)
+#define debug_bin32(data)
+#define debug_bin_reverse8(data)
+#define debug_bin_reverse16(data)
+#define debug_bin_reverse32(data)
+#define debug_hex(data)
+#define debug_bin(data)
+#define debug_bin_reverse(data)
+
+#endif /* NO_DEBUG */
+
+#endif
diff --git a/tmk_core/common/eeconfig.c b/tmk_core/common/eeconfig.c
new file mode 100644
index 000000000..140d2b85b
--- /dev/null
+++ b/tmk_core/common/eeconfig.c
@@ -0,0 +1,56 @@
+#include <stdint.h>
+#include <stdbool.h>
+#include "eeprom.h"
+#include "eeconfig.h"
+
+void eeconfig_init(void)
+{
+ eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER);
+ eeprom_update_byte(EECONFIG_DEBUG, 0);
+ eeprom_update_byte(EECONFIG_DEFAULT_LAYER, 0);
+ eeprom_update_byte(EECONFIG_KEYMAP, 0);
+ eeprom_update_byte(EECONFIG_MOUSEKEY_ACCEL, 0);
+#ifdef BACKLIGHT_ENABLE
+ eeprom_update_byte(EECONFIG_BACKLIGHT, 0);
+#endif
+#ifdef AUDIO_ENABLE
+ eeprom_update_byte(EECONFIG_AUDIO, 0xFF); // On by default
+#endif
+#ifdef RGBLIGHT_ENABLE
+ eeprom_update_dword(EECONFIG_RGBLIGHT, 0);
+#endif
+}
+
+void eeconfig_enable(void)
+{
+ eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER);
+}
+
+void eeconfig_disable(void)
+{
+ eeprom_update_word(EECONFIG_MAGIC, 0xFFFF);
+}
+
+bool eeconfig_is_enabled(void)
+{
+ return (eeprom_read_word(EECONFIG_MAGIC) == EECONFIG_MAGIC_NUMBER);
+}
+
+uint8_t eeconfig_read_debug(void) { return eeprom_read_byte(EECONFIG_DEBUG); }
+void eeconfig_update_debug(uint8_t val) { eeprom_update_byte(EECONFIG_DEBUG, val); }
+
+uint8_t eeconfig_read_default_layer(void) { return eeprom_read_byte(EECONFIG_DEFAULT_LAYER); }
+void eeconfig_update_default_layer(uint8_t val) { eeprom_update_byte(EECONFIG_DEFAULT_LAYER, val); }
+
+uint8_t eeconfig_read_keymap(void) { return eeprom_read_byte(EECONFIG_KEYMAP); }
+void eeconfig_update_keymap(uint8_t val) { eeprom_update_byte(EECONFIG_KEYMAP, val); }
+
+#ifdef BACKLIGHT_ENABLE
+uint8_t eeconfig_read_backlight(void) { return eeprom_read_byte(EECONFIG_BACKLIGHT); }
+void eeconfig_update_backlight(uint8_t val) { eeprom_update_byte(EECONFIG_BACKLIGHT, val); }
+#endif
+
+#ifdef AUDIO_ENABLE
+uint8_t eeconfig_read_audio(void) { return eeprom_read_byte(EECONFIG_AUDIO); }
+void eeconfig_update_audio(uint8_t val) { eeprom_update_byte(EECONFIG_AUDIO, val); }
+#endif
diff --git a/tmk_core/common/eeconfig.h b/tmk_core/common/eeconfig.h
new file mode 100644
index 000000000..d8caa346f
--- /dev/null
+++ b/tmk_core/common/eeconfig.h
@@ -0,0 +1,82 @@
+/*
+Copyright 2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef EECONFIG_H
+#define EECONFIG_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+
+#define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEED
+
+/* eeprom parameteter address */
+#define EECONFIG_MAGIC (uint16_t *)0
+#define EECONFIG_DEBUG (uint8_t *)2
+#define EECONFIG_DEFAULT_LAYER (uint8_t *)3
+#define EECONFIG_KEYMAP (uint8_t *)4
+#define EECONFIG_MOUSEKEY_ACCEL (uint8_t *)5
+#define EECONFIG_BACKLIGHT (uint8_t *)6
+#define EECONFIG_AUDIO (uint8_t *)7
+#define EECONFIG_RGBLIGHT (uint32_t *)8
+
+
+/* debug bit */
+#define EECONFIG_DEBUG_ENABLE (1<<0)
+#define EECONFIG_DEBUG_MATRIX (1<<1)
+#define EECONFIG_DEBUG_KEYBOARD (1<<2)
+#define EECONFIG_DEBUG_MOUSE (1<<3)
+
+/* keyconf bit */
+#define EECONFIG_KEYMAP_SWAP_CONTROL_CAPSLOCK (1<<0)
+#define EECONFIG_KEYMAP_CAPSLOCK_TO_CONTROL (1<<1)
+#define EECONFIG_KEYMAP_SWAP_LALT_LGUI (1<<2)
+#define EECONFIG_KEYMAP_SWAP_RALT_RGUI (1<<3)
+#define EECONFIG_KEYMAP_NO_GUI (1<<4)
+#define EECONFIG_KEYMAP_SWAP_GRAVE_ESC (1<<5)
+#define EECONFIG_KEYMAP_SWAP_BACKSLASH_BACKSPACE (1<<6)
+#define EECONFIG_KEYMAP_NKRO (1<<7)
+
+
+bool eeconfig_is_enabled(void);
+
+void eeconfig_init(void);
+
+void eeconfig_enable(void);
+
+void eeconfig_disable(void);
+
+uint8_t eeconfig_read_debug(void);
+void eeconfig_update_debug(uint8_t val);
+
+uint8_t eeconfig_read_default_layer(void);
+void eeconfig_update_default_layer(uint8_t val);
+
+uint8_t eeconfig_read_keymap(void);
+void eeconfig_update_keymap(uint8_t val);
+
+#ifdef BACKLIGHT_ENABLE
+uint8_t eeconfig_read_backlight(void);
+void eeconfig_update_backlight(uint8_t val);
+#endif
+
+#ifdef AUDIO_ENABLE
+uint8_t eeconfig_read_audio(void);
+void eeconfig_update_audio(uint8_t val);
+#endif
+
+#endif
diff --git a/tmk_core/common/eeprom.h b/tmk_core/common/eeprom.h
new file mode 100644
index 000000000..2cc2ccee3
--- /dev/null
+++ b/tmk_core/common/eeprom.h
@@ -0,0 +1,22 @@
+#ifndef TMK_CORE_COMMON_EEPROM_H_
+#define TMK_CORE_COMMON_EEPROM_H_
+
+#if defined(__AVR__)
+#include <avr/eeprom.h>
+#else
+uint8_t eeprom_read_byte (const uint8_t *__p);
+uint16_t eeprom_read_word (const uint16_t *__p);
+uint32_t eeprom_read_dword (const uint32_t *__p);
+void eeprom_read_block (void *__dst, const void *__src, uint32_t __n);
+void eeprom_write_byte (uint8_t *__p, uint8_t __value);
+void eeprom_write_word (uint16_t *__p, uint16_t __value);
+void eeprom_write_dword (uint32_t *__p, uint32_t __value);
+void eeprom_write_block (const void *__src, void *__dst, uint32_t __n);
+void eeprom_update_byte (uint8_t *__p, uint8_t __value);
+void eeprom_update_word (uint16_t *__p, uint16_t __value);
+void eeprom_update_dword (uint32_t *__p, uint32_t __value);
+void eeprom_update_block (const void *__src, void *__dst, uint32_t __n);
+#endif
+
+
+#endif /* TMK_CORE_COMMON_EEPROM_H_ */
diff --git a/tmk_core/common/host.c b/tmk_core/common/host.c
new file mode 100644
index 000000000..11a05c2dd
--- /dev/null
+++ b/tmk_core/common/host.c
@@ -0,0 +1,97 @@
+/*
+Copyright 2011,2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdint.h>
+//#include <avr/interrupt.h>
+#include "keycode.h"
+#include "host.h"
+#include "util.h"
+#include "debug.h"
+
+
+#ifdef NKRO_ENABLE
+bool keyboard_nkro = true;
+#endif
+
+static host_driver_t *driver;
+static uint16_t last_system_report = 0;
+static uint16_t last_consumer_report = 0;
+
+
+void host_set_driver(host_driver_t *d)
+{
+ driver = d;
+}
+
+host_driver_t *host_get_driver(void)
+{
+ return driver;
+}
+
+uint8_t host_keyboard_leds(void)
+{
+ if (!driver) return 0;
+ return (*driver->keyboard_leds)();
+}
+/* send report */
+void host_keyboard_send(report_keyboard_t *report)
+{
+ if (!driver) return;
+ (*driver->send_keyboard)(report);
+
+ if (debug_keyboard) {
+ dprint("keyboard_report: ");
+ for (uint8_t i = 0; i < KEYBOARD_REPORT_SIZE; i++) {
+ dprintf("%02X ", report->raw[i]);
+ }
+ dprint("\n");
+ }
+}
+
+void host_mouse_send(report_mouse_t *report)
+{
+ if (!driver) return;
+ (*driver->send_mouse)(report);
+}
+
+void host_system_send(uint16_t report)
+{
+ if (report == last_system_report) return;
+ last_system_report = report;
+
+ if (!driver) return;
+ (*driver->send_system)(report);
+}
+
+void host_consumer_send(uint16_t report)
+{
+ if (report == last_consumer_report) return;
+ last_consumer_report = report;
+
+ if (!driver) return;
+ (*driver->send_consumer)(report);
+}
+
+uint16_t host_last_system_report(void)
+{
+ return last_system_report;
+}
+
+uint16_t host_last_consumer_report(void)
+{
+ return last_consumer_report;
+}
diff --git a/tmk_core/common/host.h b/tmk_core/common/host.h
new file mode 100644
index 000000000..9814b10d2
--- /dev/null
+++ b/tmk_core/common/host.h
@@ -0,0 +1,57 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef HOST_H
+#define HOST_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "report.h"
+#include "host_driver.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef NKRO_ENABLE
+extern bool keyboard_nkro;
+#endif
+
+extern uint8_t keyboard_idle;
+extern uint8_t keyboard_protocol;
+
+
+/* host driver */
+void host_set_driver(host_driver_t *driver);
+host_driver_t *host_get_driver(void);
+
+/* host driver interface */
+uint8_t host_keyboard_leds(void);
+void host_keyboard_send(report_keyboard_t *report);
+void host_mouse_send(report_mouse_t *report);
+void host_system_send(uint16_t data);
+void host_consumer_send(uint16_t data);
+
+uint16_t host_last_system_report(void);
+uint16_t host_last_consumer_report(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/tmk_core/common/host_driver.h b/tmk_core/common/host_driver.h
new file mode 100644
index 000000000..edb9e5dd9
--- /dev/null
+++ b/tmk_core/common/host_driver.h
@@ -0,0 +1,33 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef HOST_DRIVER_H
+#define HOST_DRIVER_H
+
+#include <stdint.h>
+#include "report.h"
+
+
+typedef struct {
+ uint8_t (*keyboard_leds)(void);
+ void (*send_keyboard)(report_keyboard_t *);
+ void (*send_mouse)(report_mouse_t *);
+ void (*send_system)(uint16_t);
+ void (*send_consumer)(uint16_t);
+} host_driver_t;
+
+#endif
diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c
new file mode 100644
index 000000000..81df8eb73
--- /dev/null
+++ b/tmk_core/common/keyboard.c
@@ -0,0 +1,188 @@
+/*
+Copyright 2011, 2012, 2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <stdint.h>
+#include "keyboard.h"
+#include "matrix.h"
+#include "keymap.h"
+#include "host.h"
+#include "led.h"
+#include "keycode.h"
+#include "timer.h"
+#include "print.h"
+#include "debug.h"
+#include "command.h"
+#include "util.h"
+#include "sendchar.h"
+#include "eeconfig.h"
+#include "backlight.h"
+#ifdef BOOTMAGIC_ENABLE
+# include "bootmagic.h"
+#else
+# include "magic.h"
+#endif
+#ifdef MOUSEKEY_ENABLE
+# include "mousekey.h"
+#endif
+#ifdef PS2_MOUSE_ENABLE
+# include "ps2_mouse.h"
+#endif
+#ifdef SERIAL_MOUSE_ENABLE
+# include "serial_mouse.h"
+#endif
+#ifdef ADB_MOUSE_ENABLE
+# include "adb.h"
+#endif
+#ifdef RGBLIGHT_ENABLE
+# include "rgblight.h"
+#endif
+
+#ifdef MATRIX_HAS_GHOST
+static bool has_ghost_in_row(uint8_t row)
+{
+ matrix_row_t matrix_row = matrix_get_row(row);
+ // No ghost exists when less than 2 keys are down on the row
+ if (((matrix_row - 1) & matrix_row) == 0)
+ return false;
+
+ // Ghost occurs when the row shares column line with other row
+ for (uint8_t i=0; i < MATRIX_ROWS; i++) {
+ if (i != row && (matrix_get_row(i) & matrix_row))
+ return true;
+ }
+ return false;
+}
+#endif
+
+__attribute__ ((weak))
+void matrix_setup(void) {
+}
+
+void keyboard_setup(void) {
+ matrix_setup();
+}
+
+void keyboard_init(void) {
+ timer_init();
+ matrix_init();
+#ifdef PS2_MOUSE_ENABLE
+ ps2_mouse_init();
+#endif
+#ifdef SERIAL_MOUSE_ENABLE
+ serial_mouse_init();
+#endif
+#ifdef ADB_MOUSE_ENABLE
+ adb_mouse_init();
+#endif
+#ifdef BOOTMAGIC_ENABLE
+ bootmagic();
+#else
+ magic();
+#endif
+#ifdef BACKLIGHT_ENABLE
+ backlight_init();
+#endif
+#ifdef RGBLIGHT_ENABLE
+ rgblight_init();
+#endif
+#if defined(NKRO_ENABLE) && defined(FORCE_NKRO)
+ keyboard_nkro = true;
+#endif
+}
+
+/*
+ * Do keyboard routine jobs: scan mantrix, light LEDs, ...
+ * This is repeatedly called as fast as possible.
+ */
+void keyboard_task(void)
+{
+ static matrix_row_t matrix_prev[MATRIX_ROWS];
+#ifdef MATRIX_HAS_GHOST
+ static matrix_row_t matrix_ghost[MATRIX_ROWS];
+#endif
+ static uint8_t led_status = 0;
+ matrix_row_t matrix_row = 0;
+ matrix_row_t matrix_change = 0;
+
+ matrix_scan();
+ for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
+ matrix_row = matrix_get_row(r);
+ matrix_change = matrix_row ^ matrix_prev[r];
+ if (matrix_change) {
+#ifdef MATRIX_HAS_GHOST
+ if (has_ghost_in_row(r)) {
+ /* Keep track of whether ghosted status has changed for
+ * debugging. But don't update matrix_prev until un-ghosted, or
+ * the last key would be lost.
+ */
+ if (debug_matrix && matrix_ghost[r] != matrix_row) {
+ matrix_print();
+ }
+ matrix_ghost[r] = matrix_row;
+ continue;
+ }
+ matrix_ghost[r] = matrix_row;
+#endif
+ if (debug_matrix) matrix_print();
+ for (uint8_t c = 0; c < MATRIX_COLS; c++) {
+ if (matrix_change & ((matrix_row_t)1<<c)) {
+ action_exec((keyevent_t){
+ .key = (keypos_t){ .row = r, .col = c },
+ .pressed = (matrix_row & ((matrix_row_t)1<<c)),
+ .time = (timer_read() | 1) /* time should not be 0 */
+ });
+ // record a processed key
+ matrix_prev[r] ^= ((matrix_row_t)1<<c);
+ // process a key per task call
+ goto MATRIX_LOOP_END;
+ }
+ }
+ }
+ }
+ // call with pseudo tick event when no real key event.
+ action_exec(TICK);
+
+MATRIX_LOOP_END:
+
+#ifdef MOUSEKEY_ENABLE
+ // mousekey repeat & acceleration
+ mousekey_task();
+#endif
+
+#ifdef PS2_MOUSE_ENABLE
+ ps2_mouse_task();
+#endif
+
+#ifdef SERIAL_MOUSE_ENABLE
+ serial_mouse_task();
+#endif
+
+#ifdef ADB_MOUSE_ENABLE
+ adb_mouse_task();
+#endif
+
+ // update LED
+ if (led_status != host_keyboard_leds()) {
+ led_status = host_keyboard_leds();
+ keyboard_set_leds(led_status);
+ }
+}
+
+void keyboard_set_leds(uint8_t leds)
+{
+ if (debug_keyboard) { debug("keyboard_set_led: "); debug_hex8(leds); debug("\n"); }
+ led_set(leds);
+}
diff --git a/tmk_core/common/keyboard.h b/tmk_core/common/keyboard.h
new file mode 100644
index 000000000..7738251b6
--- /dev/null
+++ b/tmk_core/common/keyboard.h
@@ -0,0 +1,74 @@
+/*
+Copyright 2011,2012,2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef KEYBOARD_H
+#define KEYBOARD_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* key matrix position */
+typedef struct {
+ uint8_t col;
+ uint8_t row;
+} keypos_t;
+
+/* key event */
+typedef struct {
+ keypos_t key;
+ bool pressed;
+ uint16_t time;
+} keyevent_t;
+
+/* equivalent test of keypos_t */
+#define KEYEQ(keya, keyb) ((keya).row == (keyb).row && (keya).col == (keyb).col)
+
+/* Rules for No Event:
+ * 1) (time == 0) to handle (keyevent_t){} as empty event
+ * 2) Matrix(255, 255) to make TICK event available
+ */
+static inline bool IS_NOEVENT(keyevent_t event) { return event.time == 0 || (event.key.row == 255 && event.key.col == 255); }
+static inline bool IS_PRESSED(keyevent_t event) { return (!IS_NOEVENT(event) && event.pressed); }
+static inline bool IS_RELEASED(keyevent_t event) { return (!IS_NOEVENT(event) && !event.pressed); }
+
+/* Tick event */
+#define TICK (keyevent_t){ \
+ .key = (keypos_t){ .row = 255, .col = 255 }, \
+ .pressed = false, \
+ .time = (timer_read() | 1) \
+}
+
+
+/* it runs once at early stage of startup before keyboard_init. */
+void keyboard_setup(void);
+/* it runs once after initializing host side protocol, debug and MCU peripherals. */
+void keyboard_init(void);
+/* it runs repeatedly in main loop */
+void keyboard_task(void);
+/* it runs when host LED status is updated */
+void keyboard_set_leds(uint8_t leds);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/tmk_core/common/keycode.h b/tmk_core/common/keycode.h
new file mode 100644
index 000000000..448195306
--- /dev/null
+++ b/tmk_core/common/keycode.h
@@ -0,0 +1,494 @@
+/*
+Copyright 2011,2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Keycodes based on HID Usage Keyboard/Keypad Page(0x07) plus special codes
+ * http://www.usb.org/developers/devclass_docs/Hut1_12.pdf
+ */
+#ifndef KEYCODE_H
+#define KEYCODE_H
+
+
+#define IS_ERROR(code) (KC_ROLL_OVER <= (code) && (code) <= KC_UNDEFINED)
+#define IS_ANY(code) (KC_A <= (code) && (code) <= 0xFF)
+#define IS_KEY(code) (KC_A <= (code) && (code) <= KC_EXSEL)
+#define IS_MOD(code) (KC_LCTRL <= (code) && (code) <= KC_RGUI)
+
+
+#define IS_SPECIAL(code) ((0xA5 <= (code) && (code) <= 0xDF) || (0xE8 <= (code) && (code) <= 0xFF))
+#define IS_SYSTEM(code) (KC_PWR <= (code) && (code) <= KC_WAKE)
+#define IS_CONSUMER(code) (KC_MUTE <= (code) && (code) <= KC_WFAV)
+#define IS_FN(code) (KC_FN0 <= (code) && (code) <= KC_FN31)
+#define IS_MOUSEKEY(code) (KC_MS_UP <= (code) && (code) <= KC_MS_ACCEL2)
+#define IS_MOUSEKEY_MOVE(code) (KC_MS_UP <= (code) && (code) <= KC_MS_RIGHT)
+#define IS_MOUSEKEY_BUTTON(code) (KC_MS_BTN1 <= (code) && (code) <= KC_MS_BTN5)
+#define IS_MOUSEKEY_WHEEL(code) (KC_MS_WH_UP <= (code) && (code) <= KC_MS_WH_RIGHT)
+#define IS_MOUSEKEY_ACCEL(code) (KC_MS_ACCEL0 <= (code) && (code) <= KC_MS_ACCEL2)
+
+#define MOD_BIT(code) (1<<MOD_INDEX(code))
+#define MOD_INDEX(code) ((code) & 0x07)
+#define FN_BIT(code) (1<<FN_INDEX(code))
+#define FN_INDEX(code) ((code) - KC_FN0)
+#define FN_MIN KC_FN0
+#define FN_MAX KC_FN31
+
+
+/*
+ * Short names for ease of definition of keymap
+ */
+#define KC_LCTL KC_LCTRL
+#define KC_RCTL KC_RCTRL
+#define KC_LSFT KC_LSHIFT
+#define KC_RSFT KC_RSHIFT
+#define KC_ESC KC_ESCAPE
+#define KC_BSPC KC_BSPACE
+#define KC_ENT KC_ENTER
+#define KC_DEL KC_DELETE
+#define KC_INS KC_INSERT
+#define KC_CAPS KC_CAPSLOCK
+#define KC_CLCK KC_CAPSLOCK
+#define KC_RGHT KC_RIGHT
+#define KC_PGDN KC_PGDOWN
+#define KC_PSCR KC_PSCREEN
+#define KC_SLCK KC_SCROLLLOCK
+#define KC_PAUS KC_PAUSE
+#define KC_BRK KC_PAUSE
+#define KC_NLCK KC_NUMLOCK
+#define KC_SPC KC_SPACE
+#define KC_MINS KC_MINUS
+#define KC_EQL KC_EQUAL
+#define KC_GRV KC_GRAVE
+#define KC_RBRC KC_RBRACKET
+#define KC_LBRC KC_LBRACKET
+#define KC_COMM KC_COMMA
+#define KC_BSLS KC_BSLASH
+#define KC_SLSH KC_SLASH
+#define KC_SCLN KC_SCOLON
+#define KC_QUOT KC_QUOTE
+#define KC_APP KC_APPLICATION
+#define KC_NUHS KC_NONUS_HASH
+#define KC_NUBS KC_NONUS_BSLASH
+#define KC_LCAP KC_LOCKING_CAPS
+#define KC_LNUM KC_LOCKING_NUM
+#define KC_LSCR KC_LOCKING_SCROLL
+#define KC_ERAS KC_ALT_ERASE,
+#define KC_CLR KC_CLEAR
+/* Japanese specific */
+#define KC_ZKHK KC_GRAVE
+#define KC_RO KC_INT1
+#define KC_KANA KC_INT2
+#define KC_JYEN KC_INT3
+#define KC_HENK KC_INT4
+#define KC_MHEN KC_INT5
+/* Keypad */
+#define KC_P1 KC_KP_1
+#define KC_P2 KC_KP_2
+#define KC_P3 KC_KP_3
+#define KC_P4 KC_KP_4
+#define KC_P5 KC_KP_5
+#define KC_P6 KC_KP_6
+#define KC_P7 KC_KP_7
+#define KC_P8 KC_KP_8
+#define KC_P9 KC_KP_9
+#define KC_P0 KC_KP_0
+#define KC_PDOT KC_KP_DOT
+#define KC_PCMM KC_KP_COMMA
+#define KC_PSLS KC_KP_SLASH
+#define KC_PAST KC_KP_ASTERISK
+#define KC_PMNS KC_KP_MINUS
+#define KC_PPLS KC_KP_PLUS
+#define KC_PEQL KC_KP_EQUAL
+#define KC_PENT KC_KP_ENTER
+/* Mousekey */
+#define KC_MS_U KC_MS_UP
+#define KC_MS_D KC_MS_DOWN
+#define KC_MS_L KC_MS_LEFT
+#define KC_MS_R KC_MS_RIGHT
+#define KC_BTN1 KC_MS_BTN1
+#define KC_BTN2 KC_MS_BTN2
+#define KC_BTN3 KC_MS_BTN3
+#define KC_BTN4 KC_MS_BTN4
+#define KC_BTN5 KC_MS_BTN5
+#define KC_WH_U KC_MS_WH_UP
+#define KC_WH_D KC_MS_WH_DOWN
+#define KC_WH_L KC_MS_WH_LEFT
+#define KC_WH_R KC_MS_WH_RIGHT
+#define KC_ACL0 KC_MS_ACCEL0
+#define KC_ACL1 KC_MS_ACCEL1
+#define KC_ACL2 KC_MS_ACCEL2
+/* Sytem Control */
+#define KC_PWR KC_SYSTEM_POWER
+#define KC_SLEP KC_SYSTEM_SLEEP
+#define KC_WAKE KC_SYSTEM_WAKE
+/* Consumer Page */
+#define KC_MUTE KC_AUDIO_MUTE
+#define KC_VOLU KC_AUDIO_VOL_UP
+#define KC_VOLD KC_AUDIO_VOL_DOWN
+#define KC_MNXT KC_MEDIA_NEXT_TRACK
+#define KC_MPRV KC_MEDIA_PREV_TRACK
+#define KC_MFFD KC_MEDIA_FAST_FORWARD
+#define KC_MRWD KC_MEDIA_REWIND
+#define KC_MSTP KC_MEDIA_STOP
+#define KC_MPLY KC_MEDIA_PLAY_PAUSE
+#define KC_MSEL KC_MEDIA_SELECT
+#define KC_EJCT KC_MEDIA_EJECT
+#define KC_MAIL KC_MAIL
+#define KC_CALC KC_CALCULATOR
+#define KC_MYCM KC_MY_COMPUTER
+#define KC_WSCH KC_WWW_SEARCH
+#define KC_WHOM KC_WWW_HOME
+#define KC_WBAK KC_WWW_BACK
+#define KC_WFWD KC_WWW_FORWARD
+#define KC_WSTP KC_WWW_STOP
+#define KC_WREF KC_WWW_REFRESH
+#define KC_WFAV KC_WWW_FAVORITES
+/* Jump to bootloader */
+#define KC_BTLD KC_BOOTLOADER
+/* Transparent */
+#define KC_TRANSPARENT 1
+#define KC_TRNS KC_TRANSPARENT
+
+
+
+/* USB HID Keyboard/Keypad Usage(0x07) */
+enum hid_keyboard_keypad_usage {
+ KC_NO = 0x00,
+ KC_ROLL_OVER,
+ KC_POST_FAIL,
+ KC_UNDEFINED,
+ KC_A,
+ KC_B,
+ KC_C,
+ KC_D,
+ KC_E,
+ KC_F,
+ KC_G,
+ KC_H,
+ KC_I,
+ KC_J,
+ KC_K,
+ KC_L,
+ KC_M, /* 0x10 */
+ KC_N,
+ KC_O,
+ KC_P,
+ KC_Q,
+ KC_R,
+ KC_S,
+ KC_T,
+ KC_U,
+ KC_V,
+ KC_W,
+ KC_X,
+ KC_Y,
+ KC_Z,
+ KC_1,
+ KC_2,
+ KC_3, /* 0x20 */
+ KC_4,
+ KC_5,
+ KC_6,
+ KC_7,
+ KC_8,
+ KC_9,
+ KC_0,
+ KC_ENTER,
+ KC_ESCAPE,
+ KC_BSPACE,
+ KC_TAB,
+ KC_SPACE,
+ KC_MINUS,
+ KC_EQUAL,
+ KC_LBRACKET,
+ KC_RBRACKET, /* 0x30 */
+ KC_BSLASH, /* \ (and |) */
+ KC_NONUS_HASH, /* Non-US # and ~ (Typically near the Enter key) */
+ KC_SCOLON, /* ; (and :) */
+ KC_QUOTE, /* ' and " */
+ KC_GRAVE, /* Grave accent and tilde */
+ KC_COMMA, /* , and < */
+ KC_DOT, /* . and > */
+ KC_SLASH, /* / and ? */
+ KC_CAPSLOCK,
+ KC_F1,
+ KC_F2,
+ KC_F3,
+ KC_F4,
+ KC_F5,
+ KC_F6,
+ KC_F7, /* 0x40 */
+ KC_F8,
+ KC_F9,
+ KC_F10,
+ KC_F11,
+ KC_F12,
+ KC_PSCREEN,
+ KC_SCROLLLOCK,
+ KC_PAUSE,
+ KC_INSERT,
+ KC_HOME,
+ KC_PGUP,
+ KC_DELETE,
+ KC_END,
+ KC_PGDOWN,
+ KC_RIGHT,
+ KC_LEFT, /* 0x50 */
+ KC_DOWN,
+ KC_UP,
+ KC_NUMLOCK,
+ KC_KP_SLASH,
+ KC_KP_ASTERISK,
+ KC_KP_MINUS,
+ KC_KP_PLUS,
+ KC_KP_ENTER,
+ KC_KP_1,
+ KC_KP_2,
+ KC_KP_3,
+ KC_KP_4,
+ KC_KP_5,
+ KC_KP_6,
+ KC_KP_7,
+ KC_KP_8, /* 0x60 */
+ KC_KP_9,
+ KC_KP_0,
+ KC_KP_DOT,
+ KC_NONUS_BSLASH, /* Non-US \ and | (Typically near the Left-Shift key) */
+ KC_APPLICATION,
+ KC_POWER,
+ KC_KP_EQUAL,
+ KC_F13,
+ KC_F14,
+ KC_F15,
+ KC_F16,
+ KC_F17,
+ KC_F18,
+ KC_F19,
+ KC_F20,
+ KC_F21, /* 0x70 */
+ KC_F22,
+ KC_F23,
+ KC_F24,
+ KC_EXECUTE,
+ KC_HELP,
+ KC_MENU,
+ KC_SELECT,
+ KC_STOP,
+ KC_AGAIN,
+ KC_UNDO,
+ KC_CUT,
+ KC_COPY,
+ KC_PASTE,
+ KC_FIND,
+ KC__MUTE,
+ KC__VOLUP, /* 0x80 */
+ KC__VOLDOWN,
+ KC_LOCKING_CAPS, /* locking Caps Lock */
+ KC_LOCKING_NUM, /* locking Num Lock */
+ KC_LOCKING_SCROLL, /* locking Scroll Lock */
+ KC_KP_COMMA,
+ KC_KP_EQUAL_AS400, /* equal sign on AS/400 */
+ KC_INT1,
+ KC_INT2,
+ KC_INT3,
+ KC_INT4,
+ KC_INT5,
+ KC_INT6,
+ KC_INT7,
+ KC_INT8,
+ KC_INT9,
+ KC_LANG1, /* 0x90 */
+ KC_LANG2,
+ KC_LANG3,
+ KC_LANG4,
+ KC_LANG5,
+ KC_LANG6,
+ KC_LANG7,
+ KC_LANG8,
+ KC_LANG9,
+ KC_ALT_ERASE,
+ KC_SYSREQ,
+ KC_CANCEL,
+ KC_CLEAR,
+ KC_PRIOR,
+ KC_RETURN,
+ KC_SEPARATOR,
+ KC_OUT, /* 0xA0 */
+ KC_OPER,
+ KC_CLEAR_AGAIN,
+ KC_CRSEL,
+ KC_EXSEL, /* 0xA4 */
+
+ /* NOTE: 0xA5-DF are used for internal special purpose */
+
+#if 0
+ /* NOTE: Following codes(0xB0-DD) are not used. Leave them for reference. */
+ KC_KP_00 = 0xB0,
+ KC_KP_000,
+ KC_THOUSANDS_SEPARATOR,
+ KC_DECIMAL_SEPARATOR,
+ KC_CURRENCY_UNIT,
+ KC_CURRENCY_SUB_UNIT,
+ KC_KP_LPAREN,
+ KC_KP_RPAREN,
+ KC_KP_LCBRACKET, /* { */
+ KC_KP_RCBRACKET, /* } */
+ KC_KP_TAB,
+ KC_KP_BSPACE,
+ KC_KP_A,
+ KC_KP_B,
+ KC_KP_C,
+ KC_KP_D,
+ KC_KP_E, /* 0xC0 */
+ KC_KP_F,
+ KC_KP_XOR,
+ KC_KP_HAT,
+ KC_KP_PERC,
+ KC_KP_LT,
+ KC_KP_GT,
+ KC_KP_AND,
+ KC_KP_LAZYAND,
+ KC_KP_OR,
+ KC_KP_LAZYOR,
+ KC_KP_COLON,
+ KC_KP_HASH,
+ KC_KP_SPACE,
+ KC_KP_ATMARK,
+ KC_KP_EXCLAMATION,
+ KC_KP_MEM_STORE, /* 0xD0 */
+ KC_KP_MEM_RECALL,
+ KC_KP_MEM_CLEAR,
+ KC_KP_MEM_ADD,
+ KC_KP_MEM_SUB,
+ KC_KP_MEM_MUL,
+ KC_KP_MEM_DIV,
+ KC_KP_PLUS_MINUS,
+ KC_KP_CLEAR,
+ KC_KP_CLEAR_ENTRY,
+ KC_KP_BINARY,
+ KC_KP_OCTAL,
+ KC_KP_DECIMAL,
+ KC_KP_HEXADECIMAL, /* 0xDD */
+#endif
+
+ /* Modifiers */
+ KC_LCTRL = 0xE0,
+ KC_LSHIFT,
+ KC_LALT,
+ KC_LGUI,
+ KC_RCTRL,
+ KC_RSHIFT,
+ KC_RALT,
+ KC_RGUI,
+
+ /* NOTE: 0xE8-FF are used for internal special purpose */
+};
+
+/* Special keycodes */
+/* NOTE: 0xA5-DF and 0xE8-FF are used for internal special purpose */
+enum internal_special_keycodes {
+ /* System Control */
+ KC_SYSTEM_POWER = 0xA5,
+ KC_SYSTEM_SLEEP,
+ KC_SYSTEM_WAKE,
+
+ /* Media Control */
+ KC_AUDIO_MUTE,
+ KC_AUDIO_VOL_UP,
+ KC_AUDIO_VOL_DOWN,
+ KC_MEDIA_NEXT_TRACK,
+ KC_MEDIA_PREV_TRACK,
+ KC_MEDIA_STOP,
+ KC_MEDIA_PLAY_PAUSE,
+ KC_MEDIA_SELECT,
+ KC_MEDIA_EJECT,
+ KC_MAIL,
+ KC_CALCULATOR,
+ KC_MY_COMPUTER,
+ KC_WWW_SEARCH,
+ KC_WWW_HOME,
+ KC_WWW_BACK,
+ KC_WWW_FORWARD,
+ KC_WWW_STOP,
+ KC_WWW_REFRESH,
+ KC_WWW_FAVORITES,
+ KC_MEDIA_FAST_FORWARD,
+ KC_MEDIA_REWIND, /* 0xBC */
+
+ /* Jump to bootloader */
+ KC_BOOTLOADER = 0xBF,
+
+ /* Fn key */
+ KC_FN0 = 0xC0,
+ KC_FN1,
+ KC_FN2,
+ KC_FN3,
+ KC_FN4,
+ KC_FN5,
+ KC_FN6,
+ KC_FN7,
+ KC_FN8,
+ KC_FN9,
+ KC_FN10,
+ KC_FN11,
+ KC_FN12,
+ KC_FN13,
+ KC_FN14,
+ KC_FN15,
+
+ KC_FN16 = 0xD0,
+ KC_FN17,
+ KC_FN18,
+ KC_FN19,
+ KC_FN20,
+ KC_FN21,
+ KC_FN22,
+ KC_FN23,
+ KC_FN24,
+ KC_FN25,
+ KC_FN26,
+ KC_FN27,
+ KC_FN28,
+ KC_FN29,
+ KC_FN30,
+ KC_FN31, /* 0xDF */
+
+ /**************************************/
+ /* 0xE0-E7 for Modifiers. DO NOT USE. */
+ /**************************************/
+
+ /* Mousekey */
+ KC_MS_UP = 0xF0,
+ KC_MS_DOWN,
+ KC_MS_LEFT,
+ KC_MS_RIGHT,
+ KC_MS_BTN1,
+ KC_MS_BTN2,
+ KC_MS_BTN3,
+ KC_MS_BTN4,
+ KC_MS_BTN5, /* 0xF8 */
+ /* Mousekey wheel */
+ KC_MS_WH_UP,
+ KC_MS_WH_DOWN,
+ KC_MS_WH_LEFT,
+ KC_MS_WH_RIGHT, /* 0xFC */
+ /* Mousekey accel */
+ KC_MS_ACCEL0,
+ KC_MS_ACCEL1,
+ KC_MS_ACCEL2 /* 0xFF */
+};
+
+#endif /* KEYCODE_H */
diff --git a/tmk_core/common/led.h b/tmk_core/common/led.h
new file mode 100644
index 000000000..61c971c10
--- /dev/null
+++ b/tmk_core/common/led.h
@@ -0,0 +1,43 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef LED_H
+#define LED_H
+#include "stdint.h"
+
+
+/* keyboard LEDs */
+#define USB_LED_NUM_LOCK 0
+#define USB_LED_CAPS_LOCK 1
+#define USB_LED_SCROLL_LOCK 2
+#define USB_LED_COMPOSE 3
+#define USB_LED_KANA 4
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void led_set(uint8_t usb_led);
+
+void led_init_ports(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif \ No newline at end of file
diff --git a/tmk_core/common/magic.c b/tmk_core/common/magic.c
new file mode 100644
index 000000000..194e4cc02
--- /dev/null
+++ b/tmk_core/common/magic.c
@@ -0,0 +1,38 @@
+#include <stdint.h>
+#include <stdbool.h>
+#if defined(__AVR__)
+#include <util/delay.h>
+#endif
+#include "matrix.h"
+#include "bootloader.h"
+#include "debug.h"
+#include "keymap.h"
+#include "host.h"
+#include "action_layer.h"
+#include "eeconfig.h"
+#include "magic.h"
+
+keymap_config_t keymap_config;
+
+void magic(void)
+{
+ /* check signature */
+ if (!eeconfig_is_enabled()) {
+ eeconfig_init();
+ }
+
+ /* debug enable */
+ debug_config.raw = eeconfig_read_debug();
+
+ /* keymap config */
+ keymap_config.raw = eeconfig_read_keymap();
+
+#ifdef NKRO_ENABLE
+ keyboard_nkro = keymap_config.nkro;
+#endif
+
+ uint8_t default_layer = 0;
+ default_layer = eeconfig_read_default_layer();
+ default_layer_set((uint32_t)default_layer);
+
+}
diff --git a/tmk_core/common/magic.h b/tmk_core/common/magic.h
new file mode 100644
index 000000000..3fa2d8b81
--- /dev/null
+++ b/tmk_core/common/magic.h
@@ -0,0 +1,6 @@
+#ifndef MAGIC_H
+#define MAGIC_H
+
+void magic(void);
+
+#endif
diff --git a/tmk_core/common/matrix.h b/tmk_core/common/matrix.h
new file mode 100644
index 000000000..71153a5f5
--- /dev/null
+++ b/tmk_core/common/matrix.h
@@ -0,0 +1,79 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef MATRIX_H
+#define MATRIX_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+
+#if (MATRIX_COLS <= 8)
+typedef uint8_t matrix_row_t;
+#elif (MATRIX_COLS <= 16)
+typedef uint16_t matrix_row_t;
+#elif (MATRIX_COLS <= 32)
+typedef uint32_t matrix_row_t;
+#else
+#error "MATRIX_COLS: invalid value"
+#endif
+
+#define MATRIX_IS_ON(row, col) (matrix_get_row(row) && (1<<col))
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* number of matrix rows */
+uint8_t matrix_rows(void);
+/* number of matrix columns */
+uint8_t matrix_cols(void);
+/* should be called at early stage of startup before matrix_init.(optional) */
+void matrix_setup(void);
+/* intialize matrix for scaning. */
+void matrix_init(void);
+/* scan all key states on matrix */
+uint8_t matrix_scan(void);
+/* whether modified from previous scan. used after matrix_scan. */
+bool matrix_is_modified(void) __attribute__ ((deprecated));
+/* whether a swtich is on */
+bool matrix_is_on(uint8_t row, uint8_t col);
+/* matrix state on row */
+matrix_row_t matrix_get_row(uint8_t row);
+/* print matrix for debug */
+void matrix_print(void);
+
+
+/* power control */
+void matrix_power_up(void);
+void matrix_power_down(void);
+
+/* executes code for Quantum */
+void matrix_init_quantum(void);
+void matrix_scan_quantum(void);
+
+void matrix_init_kb(void);
+void matrix_scan_kb(void);
+
+void matrix_init_user(void);
+void matrix_scan_user(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/tmk_core/common/mbed/bootloader.c b/tmk_core/common/mbed/bootloader.c
new file mode 100644
index 000000000..b51e83943
--- /dev/null
+++ b/tmk_core/common/mbed/bootloader.c
@@ -0,0 +1,4 @@
+#include "bootloader.h"
+
+
+void bootloader_jump(void) {}
diff --git a/tmk_core/common/mbed/suspend.c b/tmk_core/common/mbed/suspend.c
new file mode 100644
index 000000000..32651574f
--- /dev/null
+++ b/tmk_core/common/mbed/suspend.c
@@ -0,0 +1,6 @@
+#include <stdbool.h>
+
+
+void suspend_power_down(void) {}
+bool suspend_wakeup_condition(void) { return true; }
+void suspend_wakeup_init(void) {}
diff --git a/tmk_core/common/mbed/timer.c b/tmk_core/common/mbed/timer.c
new file mode 100644
index 000000000..c357ceb78
--- /dev/null
+++ b/tmk_core/common/mbed/timer.c
@@ -0,0 +1,41 @@
+#include "cmsis.h"
+#include "timer.h"
+
+/* Mill second tick count */
+volatile uint32_t timer_count = 0;
+
+/* Timer interrupt handler */
+void SysTick_Handler(void) {
+ timer_count++;
+}
+
+void timer_init(void)
+{
+ timer_count = 0;
+ SysTick_Config(SystemCoreClock / 1000); /* 1ms tick */
+}
+
+void timer_clear(void)
+{
+ timer_count = 0;
+}
+
+uint16_t timer_read(void)
+{
+ return (uint16_t)(timer_count & 0xFFFF);
+}
+
+uint32_t timer_read32(void)
+{
+ return timer_count;
+}
+
+uint16_t timer_elapsed(uint16_t last)
+{
+ return TIMER_DIFF_16(timer_read(), last);
+}
+
+uint32_t timer_elapsed32(uint32_t last)
+{
+ return TIMER_DIFF_32(timer_read32(), last);
+}
diff --git a/tmk_core/common/mbed/xprintf.cpp b/tmk_core/common/mbed/xprintf.cpp
new file mode 100644
index 000000000..3647ece75
--- /dev/null
+++ b/tmk_core/common/mbed/xprintf.cpp
@@ -0,0 +1,51 @@
+#include <cstdarg>
+//#include <stdarg.h>
+#include "mbed.h"
+#include "mbed/xprintf.h"
+
+
+#define STRING_STACK_LIMIT 120
+
+//TODO
+int xprintf(const char* format, ...) { return 0; }
+
+#if 0
+/* mbed Serial */
+Serial ser(UART_TX, UART_RX);
+
+/* TODO: Need small implementation for embedded */
+int xprintf(const char* format, ...)
+{
+ /* copy from mbed/common/RawSerial.cpp */
+ std::va_list arg;
+ va_start(arg, format);
+ int len = vsnprintf(NULL, 0, format, arg);
+ if (len < STRING_STACK_LIMIT) {
+ char temp[STRING_STACK_LIMIT];
+ vsprintf(temp, format, arg);
+ ser.puts(temp);
+ } else {
+ char *temp = new char[len + 1];
+ vsprintf(temp, format, arg);
+ ser.puts(temp);
+ delete[] temp;
+ }
+ va_end(arg);
+ return len;
+
+/* Fail: __builtin_va_arg_pack?
+ * https://gcc.gnu.org/onlinedocs/gcc-4.3.5/gcc/Constructing-Calls.html#Constructing-Calls
+ void *arg = __builtin_apply_args();
+ void *ret = __builtin_apply((void*)(&(ser.printf)), arg, 100);
+ __builtin_return(ret)
+*/
+/* Fail: varargs can not be passed to printf
+ //int r = ser.printf("test %i\r\n", 123);
+ va_list arg;
+ va_start(arg, format);
+ int r = ser.printf(format, arg);
+ va_end(arg);
+ return r;
+*/
+}
+#endif
diff --git a/tmk_core/common/mbed/xprintf.h b/tmk_core/common/mbed/xprintf.h
new file mode 100644
index 000000000..26bc529e5
--- /dev/null
+++ b/tmk_core/common/mbed/xprintf.h
@@ -0,0 +1,17 @@
+#ifndef XPRINTF_H
+#define XPRINTF_H
+
+//#define xprintf(format, ...) __xprintf(format, ##__VA_ARGS__)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int xprintf(const char *format, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/tmk_core/common/mousekey.c b/tmk_core/common/mousekey.c
new file mode 100644
index 000000000..23469476e
--- /dev/null
+++ b/tmk_core/common/mousekey.c
@@ -0,0 +1,196 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdint.h>
+#include "keycode.h"
+#include "host.h"
+#include "timer.h"
+#include "print.h"
+#include "debug.h"
+#include "mousekey.h"
+
+
+
+static report_mouse_t mouse_report = {};
+static uint8_t mousekey_repeat = 0;
+static uint8_t mousekey_accel = 0;
+
+static void mousekey_debug(void);
+
+
+/*
+ * Mouse keys acceleration algorithm
+ * http://en.wikipedia.org/wiki/Mouse_keys
+ *
+ * speed = delta * max_speed * (repeat / time_to_max)**((1000+curve)/1000)
+ */
+/* milliseconds between the initial key press and first repeated motion event (0-2550) */
+uint8_t mk_delay = MOUSEKEY_DELAY/10;
+/* milliseconds between repeated motion events (0-255) */
+uint8_t mk_interval = MOUSEKEY_INTERVAL;
+/* steady speed (in action_delta units) applied each event (0-255) */
+uint8_t mk_max_speed = MOUSEKEY_MAX_SPEED;
+/* number of events (count) accelerating to steady speed (0-255) */
+uint8_t mk_time_to_max = MOUSEKEY_TIME_TO_MAX;
+/* ramp used to reach maximum pointer speed (NOT SUPPORTED) */
+//int8_t mk_curve = 0;
+/* wheel params */
+uint8_t mk_wheel_max_speed = MOUSEKEY_WHEEL_MAX_SPEED;
+uint8_t mk_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX;
+
+
+static uint16_t last_timer = 0;
+
+
+static uint8_t move_unit(void)
+{
+ uint16_t unit;
+ if (mousekey_accel & (1<<0)) {
+ unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed)/4;
+ } else if (mousekey_accel & (1<<1)) {
+ unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed)/2;
+ } else if (mousekey_accel & (1<<2)) {
+ unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed);
+ } else if (mousekey_repeat == 0) {
+ unit = MOUSEKEY_MOVE_DELTA;
+ } else if (mousekey_repeat >= mk_time_to_max) {
+ unit = MOUSEKEY_MOVE_DELTA * mk_max_speed;
+ } else {
+ unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed * mousekey_repeat) / mk_time_to_max;
+ }
+ return (unit > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : (unit == 0 ? 1 : unit));
+}
+
+static uint8_t wheel_unit(void)
+{
+ uint16_t unit;
+ if (mousekey_accel & (1<<0)) {
+ unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed)/4;
+ } else if (mousekey_accel & (1<<1)) {
+ unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed)/2;
+ } else if (mousekey_accel & (1<<2)) {
+ unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed);
+ } else if (mousekey_repeat == 0) {
+ unit = MOUSEKEY_WHEEL_DELTA;
+ } else if (mousekey_repeat >= mk_wheel_time_to_max) {
+ unit = MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed;
+ } else {
+ unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed * mousekey_repeat) / mk_wheel_time_to_max;
+ }
+ return (unit > MOUSEKEY_WHEEL_MAX ? MOUSEKEY_WHEEL_MAX : (unit == 0 ? 1 : unit));
+}
+
+void mousekey_task(void)
+{
+ if (timer_elapsed(last_timer) < (mousekey_repeat ? mk_interval : mk_delay*10))
+ return;
+
+ if (mouse_report.x == 0 && mouse_report.y == 0 && mouse_report.v == 0 && mouse_report.h == 0)
+ return;
+
+ if (mousekey_repeat != UINT8_MAX)
+ mousekey_repeat++;
+
+
+ if (mouse_report.x > 0) mouse_report.x = move_unit();
+ if (mouse_report.x < 0) mouse_report.x = move_unit() * -1;
+ if (mouse_report.y > 0) mouse_report.y = move_unit();
+ if (mouse_report.y < 0) mouse_report.y = move_unit() * -1;
+
+ /* diagonal move [1/sqrt(2) = 0.7] */
+ if (mouse_report.x && mouse_report.y) {
+ mouse_report.x *= 0.7;
+ mouse_report.y *= 0.7;
+ }
+
+ if (mouse_report.v > 0) mouse_report.v = wheel_unit();
+ if (mouse_report.v < 0) mouse_report.v = wheel_unit() * -1;
+ if (mouse_report.h > 0) mouse_report.h = wheel_unit();
+ if (mouse_report.h < 0) mouse_report.h = wheel_unit() * -1;
+
+ mousekey_send();
+}
+
+void mousekey_on(uint8_t code)
+{
+ if (code == KC_MS_UP) mouse_report.y = move_unit() * -1;
+ else if (code == KC_MS_DOWN) mouse_report.y = move_unit();
+ else if (code == KC_MS_LEFT) mouse_report.x = move_unit() * -1;
+ else if (code == KC_MS_RIGHT) mouse_report.x = move_unit();
+ else if (code == KC_MS_WH_UP) mouse_report.v = wheel_unit();
+ else if (code == KC_MS_WH_DOWN) mouse_report.v = wheel_unit() * -1;
+ else if (code == KC_MS_WH_LEFT) mouse_report.h = wheel_unit() * -1;
+ else if (code == KC_MS_WH_RIGHT) mouse_report.h = wheel_unit();
+ else if (code == KC_MS_BTN1) mouse_report.buttons |= MOUSE_BTN1;
+ else if (code == KC_MS_BTN2) mouse_report.buttons |= MOUSE_BTN2;
+ else if (code == KC_MS_BTN3) mouse_report.buttons |= MOUSE_BTN3;
+ else if (code == KC_MS_BTN4) mouse_report.buttons |= MOUSE_BTN4;
+ else if (code == KC_MS_BTN5) mouse_report.buttons |= MOUSE_BTN5;
+ else if (code == KC_MS_ACCEL0) mousekey_accel |= (1<<0);
+ else if (code == KC_MS_ACCEL1) mousekey_accel |= (1<<1);
+ else if (code == KC_MS_ACCEL2) mousekey_accel |= (1<<2);
+}
+
+void mousekey_off(uint8_t code)
+{
+ if (code == KC_MS_UP && mouse_report.y < 0) mouse_report.y = 0;
+ else if (code == KC_MS_DOWN && mouse_report.y > 0) mouse_report.y = 0;
+ else if (code == KC_MS_LEFT && mouse_report.x < 0) mouse_report.x = 0;
+ else if (code == KC_MS_RIGHT && mouse_report.x > 0) mouse_report.x = 0;
+ else if (code == KC_MS_WH_UP && mouse_report.v > 0) mouse_report.v = 0;
+ else if (code == KC_MS_WH_DOWN && mouse_report.v < 0) mouse_report.v = 0;
+ else if (code == KC_MS_WH_LEFT && mouse_report.h < 0) mouse_report.h = 0;
+ else if (code == KC_MS_WH_RIGHT && mouse_report.h > 0) mouse_report.h = 0;
+ else if (code == KC_MS_BTN1) mouse_report.buttons &= ~MOUSE_BTN1;
+ else if (code == KC_MS_BTN2) mouse_report.buttons &= ~MOUSE_BTN2;
+ else if (code == KC_MS_BTN3) mouse_report.buttons &= ~MOUSE_BTN3;
+ else if (code == KC_MS_BTN4) mouse_report.buttons &= ~MOUSE_BTN4;
+ else if (code == KC_MS_BTN5) mouse_report.buttons &= ~MOUSE_BTN5;
+ else if (code == KC_MS_ACCEL0) mousekey_accel &= ~(1<<0);
+ else if (code == KC_MS_ACCEL1) mousekey_accel &= ~(1<<1);
+ else if (code == KC_MS_ACCEL2) mousekey_accel &= ~(1<<2);
+
+ if (mouse_report.x == 0 && mouse_report.y == 0 && mouse_report.v == 0 && mouse_report.h == 0)
+ mousekey_repeat = 0;
+}
+
+void mousekey_send(void)
+{
+ mousekey_debug();
+ host_mouse_send(&mouse_report);
+ last_timer = timer_read();
+}
+
+void mousekey_clear(void)
+{
+ mouse_report = (report_mouse_t){};
+ mousekey_repeat = 0;
+ mousekey_accel = 0;
+}
+
+static void mousekey_debug(void)
+{
+ if (!debug_mouse) return;
+ print("mousekey [btn|x y v h](rep/acl): [");
+ phex(mouse_report.buttons); print("|");
+ print_decs(mouse_report.x); print(" ");
+ print_decs(mouse_report.y); print(" ");
+ print_decs(mouse_report.v); print(" ");
+ print_decs(mouse_report.h); print("](");
+ print_dec(mousekey_repeat); print("/");
+ print_dec(mousekey_accel); print(")\n");
+}
diff --git a/tmk_core/common/mousekey.h b/tmk_core/common/mousekey.h
new file mode 100644
index 000000000..6eede06b4
--- /dev/null
+++ b/tmk_core/common/mousekey.h
@@ -0,0 +1,77 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef MOUSEKEY_H
+#define MOUSEKEY_H
+
+#include <stdbool.h>
+#include "host.h"
+
+
+/* max value on report descriptor */
+#define MOUSEKEY_MOVE_MAX 127
+#define MOUSEKEY_WHEEL_MAX 127
+
+#ifndef MOUSEKEY_MOVE_DELTA
+#define MOUSEKEY_MOVE_DELTA 5
+#endif
+#ifndef MOUSEKEY_WHEEL_DELTA
+#define MOUSEKEY_WHEEL_DELTA 1
+#endif
+#ifndef MOUSEKEY_DELAY
+#define MOUSEKEY_DELAY 300
+#endif
+#ifndef MOUSEKEY_INTERVAL
+#define MOUSEKEY_INTERVAL 50
+#endif
+#ifndef MOUSEKEY_MAX_SPEED
+#define MOUSEKEY_MAX_SPEED 10
+#endif
+#ifndef MOUSEKEY_TIME_TO_MAX
+#define MOUSEKEY_TIME_TO_MAX 20
+#endif
+#ifndef MOUSEKEY_WHEEL_MAX_SPEED
+#define MOUSEKEY_WHEEL_MAX_SPEED 8
+#endif
+#ifndef MOUSEKEY_WHEEL_TIME_TO_MAX
+#define MOUSEKEY_WHEEL_TIME_TO_MAX 40
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern uint8_t mk_delay;
+extern uint8_t mk_interval;
+extern uint8_t mk_max_speed;
+extern uint8_t mk_time_to_max;
+extern uint8_t mk_wheel_max_speed;
+extern uint8_t mk_wheel_time_to_max;
+
+
+void mousekey_task(void);
+void mousekey_on(uint8_t code);
+void mousekey_off(uint8_t code);
+void mousekey_clear(void);
+void mousekey_send(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/tmk_core/common/nodebug.h b/tmk_core/common/nodebug.h
new file mode 100644
index 000000000..5e18656e5
--- /dev/null
+++ b/tmk_core/common/nodebug.h
@@ -0,0 +1,29 @@
+/*
+Copyright 2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef NODEBUG_H
+#define NODEBUG_H
+
+#ifndef NO_DEBUG
+ #define NO_DEBUG
+ #include "debug.h"
+ #undef NO_DEBUG
+#else
+ #include "debug.h"
+#endif
+
+#endif
diff --git a/tmk_core/common/print.c b/tmk_core/common/print.c
new file mode 100644
index 000000000..00489557f
--- /dev/null
+++ b/tmk_core/common/print.c
@@ -0,0 +1,52 @@
+/* Copyright 2012,2013 Jun Wako <wakojun@gmail.com> */
+/* Very basic print functions, intended to be used with usb_debug_only.c
+ * http://www.pjrc.com/teensy/
+ * Copyright (c) 2008 PJRC.COM, LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdint.h>
+#include "print.h"
+
+
+#ifndef NO_PRINT
+
+#if defined(__AVR__)
+
+#define sendchar(c) xputc(c)
+
+
+void print_set_sendchar(int8_t (*sendchar_func)(uint8_t))
+{
+ xdev_out(sendchar_func);
+}
+
+#elif defined(PROTOCOL_CHIBIOS) /* __AVR__ */
+
+// don't need anything extra
+
+#elif defined(__arm__) /* __AVR__ */
+
+// TODO
+//void print_set_sendchar(int8_t (*sendchar_func)(uint8_t)) { }
+
+#endif /* __AVR__ */
+
+#endif
diff --git a/tmk_core/common/print.h b/tmk_core/common/print.h
new file mode 100644
index 000000000..0368bcd4a
--- /dev/null
+++ b/tmk_core/common/print.h
@@ -0,0 +1,145 @@
+/* Copyright 2012 Jun Wako <wakojun@gmail.com> */
+/* Very basic print functions, intended to be used with usb_debug_only.c
+ * http://www.pjrc.com/teensy/
+ * Copyright (c) 2008 PJRC.COM, LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef PRINT_H__
+#define PRINT_H__ 1
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "util.h"
+
+
+
+
+#ifndef NO_PRINT
+
+
+#if defined(__AVR__)
+
+#include "avr/xprintf.h"
+#define print(s) xputs(PSTR(s))
+#define println(s) xputs(PSTR(s "\r\n"))
+
+#ifdef __cplusplus
+extern "C"
+#endif
+/* function pointer of sendchar to be used by print utility */
+void print_set_sendchar(int8_t (*print_sendchar_func)(uint8_t));
+
+#elif defined(PROTOCOL_CHIBIOS) /* __AVR__ */
+
+#include "chibios/printf.h"
+
+#define print(s) printf(s)
+#define println(s) printf(s "\r\n")
+#define xprintf printf
+
+#elif defined(__arm__) /* __AVR__ */
+
+#include "mbed/xprintf.h"
+
+#define print(s) xprintf(s)
+#define println(s) xprintf(s "\r\n")
+
+/* TODO: to select output destinations: UART/USBSerial */
+#define print_set_sendchar(func)
+
+#endif /* __AVR__ */
+
+
+/* decimal */
+#define print_dec(i) xprintf("%u", i)
+#define print_decs(i) xprintf("%d", i)
+/* hex */
+#define print_hex4(i) xprintf("%X", i)
+#define print_hex8(i) xprintf("%02X", i)
+#define print_hex16(i) xprintf("%04X", i)
+#define print_hex32(i) xprintf("%08lX", i)
+/* binary */
+#define print_bin4(i) xprintf("%04b", i)
+#define print_bin8(i) xprintf("%08b", i)
+#define print_bin16(i) xprintf("%016b", i)
+#define print_bin32(i) xprintf("%032lb", i)
+#define print_bin_reverse8(i) xprintf("%08b", bitrev(i))
+#define print_bin_reverse16(i) xprintf("%016b", bitrev16(i))
+#define print_bin_reverse32(i) xprintf("%032lb", bitrev32(i))
+/* print value utility */
+#define print_val_dec(v) xprintf(#v ": %u\n", v)
+#define print_val_decs(v) xprintf(#v ": %d\n", v)
+#define print_val_hex8(v) xprintf(#v ": %X\n", v)
+#define print_val_hex16(v) xprintf(#v ": %02X\n", v)
+#define print_val_hex32(v) xprintf(#v ": %04lX\n", v)
+#define print_val_bin8(v) xprintf(#v ": %08b\n", v)
+#define print_val_bin16(v) xprintf(#v ": %016b\n", v)
+#define print_val_bin32(v) xprintf(#v ": %032lb\n", v)
+#define print_val_bin_reverse8(v) xprintf(#v ": %08b\n", bitrev(v))
+#define print_val_bin_reverse16(v) xprintf(#v ": %016b\n", bitrev16(v))
+#define print_val_bin_reverse32(v) xprintf(#v ": %032lb\n", bitrev32(v))
+
+#else /* NO_PRINT */
+
+#define xprintf(fmt, ...)
+#define print(s)
+#define println(s)
+#define print_set_sendchar(func)
+#define print_dec(data)
+#define print_decs(data)
+#define print_hex4(data)
+#define print_hex8(data)
+#define print_hex16(data)
+#define print_hex32(data)
+#define print_bin4(data)
+#define print_bin8(data)
+#define print_bin16(data)
+#define print_bin32(data)
+#define print_bin_reverse8(data)
+#define print_bin_reverse16(data)
+#define print_bin_reverse32(data)
+#define print_val_dec(v)
+#define print_val_decs(v)
+#define print_val_hex8(v)
+#define print_val_hex16(v)
+#define print_val_hex32(v)
+#define print_val_bin8(v)
+#define print_val_bin16(v)
+#define print_val_bin32(v)
+#define print_val_bin_reverse8(v)
+#define print_val_bin_reverse16(v)
+#define print_val_bin_reverse32(v)
+
+#endif /* NO_PRINT */
+
+
+/* Backward compatiblitly for old name */
+#define pdec(data) print_dec(data)
+#define pdec16(data) print_dec(data)
+#define phex(data) print_hex8(data)
+#define phex16(data) print_hex16(data)
+#define pbin(data) print_bin8(data)
+#define pbin16(data) print_bin16(data)
+#define pbin_reverse(data) print_bin_reverse8(data)
+#define pbin_reverse16(data) print_bin_reverse16(data)
+
+
+#endif
diff --git a/tmk_core/common/progmem.h b/tmk_core/common/progmem.h
new file mode 100644
index 000000000..5b2765625
--- /dev/null
+++ b/tmk_core/common/progmem.h
@@ -0,0 +1,12 @@
+#ifndef PROGMEM_H
+#define PROGMEM_H 1
+
+#if defined(__AVR__)
+# include <avr/pgmspace.h>
+#elif defined(__arm__)
+# define PROGMEM
+# define pgm_read_byte(p) *((unsigned char*)p)
+# define pgm_read_word(p) *((uint16_t*)p)
+#endif
+
+#endif
diff --git a/tmk_core/common/report.h b/tmk_core/common/report.h
new file mode 100644
index 000000000..0c799eca3
--- /dev/null
+++ b/tmk_core/common/report.h
@@ -0,0 +1,188 @@
+/*
+Copyright 2011,2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef REPORT_H
+#define REPORT_H
+
+#include <stdint.h>
+#include "keycode.h"
+
+
+/* report id */
+#define REPORT_ID_MOUSE 1
+#define REPORT_ID_SYSTEM 2
+#define REPORT_ID_CONSUMER 3
+
+/* mouse buttons */
+#define MOUSE_BTN1 (1<<0)
+#define MOUSE_BTN2 (1<<1)
+#define MOUSE_BTN3 (1<<2)
+#define MOUSE_BTN4 (1<<3)
+#define MOUSE_BTN5 (1<<4)
+
+/* Consumer Page(0x0C)
+ * following are supported by Windows: http://msdn.microsoft.com/en-us/windows/hardware/gg463372.aspx
+ */
+#define AUDIO_MUTE 0x00E2
+#define AUDIO_VOL_UP 0x00E9
+#define AUDIO_VOL_DOWN 0x00EA
+#define TRANSPORT_NEXT_TRACK 0x00B5
+#define TRANSPORT_PREV_TRACK 0x00B6
+#define TRANSPORT_STOP 0x00B7
+#define TRANSPORT_STOP_EJECT 0x00CC
+#define TRANSPORT_PLAY_PAUSE 0x00CD
+/* application launch */
+#define AL_CC_CONFIG 0x0183
+#define AL_EMAIL 0x018A
+#define AL_CALCULATOR 0x0192
+#define AL_LOCAL_BROWSER 0x0194
+/* application control */
+#define AC_SEARCH 0x0221
+#define AC_HOME 0x0223
+#define AC_BACK 0x0224
+#define AC_FORWARD 0x0225
+#define AC_STOP 0x0226
+#define AC_REFRESH 0x0227
+#define AC_BOOKMARKS 0x022A
+/* supplement for Bluegiga iWRAP HID(not supported by Windows?) */
+#define AL_LOCK 0x019E
+#define TRANSPORT_RECORD 0x00B2
+#define TRANSPORT_FAST_FORWARD 0x00B3
+#define TRANSPORT_REWIND 0x00B4
+#define TRANSPORT_EJECT 0x00B8
+#define AC_MINIMIZE 0x0206
+
+/* Generic Desktop Page(0x01) - system power control */
+#define SYSTEM_POWER_DOWN 0x0081
+#define SYSTEM_SLEEP 0x0082
+#define SYSTEM_WAKE_UP 0x0083
+
+
+/* key report size(NKRO or boot mode) */
+#if defined(PROTOCOL_PJRC) && defined(NKRO_ENABLE)
+# include "usb.h"
+# define KEYBOARD_REPORT_SIZE KBD2_SIZE
+# define KEYBOARD_REPORT_KEYS (KBD2_SIZE - 2)
+# define KEYBOARD_REPORT_BITS (KBD2_SIZE - 1)
+
+#elif defined(PROTOCOL_LUFA) && defined(NKRO_ENABLE)
+# include "protocol/lufa/descriptor.h"
+# define KEYBOARD_REPORT_SIZE NKRO_EPSIZE
+# define KEYBOARD_REPORT_KEYS (NKRO_EPSIZE - 2)
+# define KEYBOARD_REPORT_BITS (NKRO_EPSIZE - 1)
+#elif defined(PROTOCOL_CHIBIOS) && defined(NKRO_ENABLE)
+# include "protocol/chibios/usb_main.h"
+# define KEYBOARD_REPORT_SIZE NKRO_EPSIZE
+# define KEYBOARD_REPORT_KEYS (NKRO_EPSIZE - 2)
+# define KEYBOARD_REPORT_BITS (NKRO_EPSIZE - 1)
+
+#else
+# define KEYBOARD_REPORT_SIZE 8
+# define KEYBOARD_REPORT_KEYS 6
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * keyboard report is 8-byte array retains state of 8 modifiers and 6 keys.
+ *
+ * byte |0 |1 |2 |3 |4 |5 |6 |7
+ * -----+--------+--------+--------+--------+--------+--------+--------+--------
+ * desc |mods |reserved|keys[0] |keys[1] |keys[2] |keys[3] |keys[4] |keys[5]
+ *
+ * It is exended to 16 bytes to retain 120keys+8mods when NKRO mode.
+ *
+ * byte |0 |1 |2 |3 |4 |5 |6 |7 ... |15
+ * -----+--------+--------+--------+--------+--------+--------+--------+-------- +--------
+ * desc |mods |bits[0] |bits[1] |bits[2] |bits[3] |bits[4] |bits[5] |bits[6] ... |bit[14]
+ *
+ * mods retains state of 8 modifiers.
+ *
+ * bit |0 |1 |2 |3 |4 |5 |6 |7
+ * -----+--------+--------+--------+--------+--------+--------+--------+--------
+ * desc |Lcontrol|Lshift |Lalt |Lgui |Rcontrol|Rshift |Ralt |Rgui
+ *
+ */
+typedef union {
+ uint8_t raw[KEYBOARD_REPORT_SIZE];
+ struct {
+ uint8_t mods;
+ uint8_t reserved;
+ uint8_t keys[KEYBOARD_REPORT_KEYS];
+ };
+#ifdef NKRO_ENABLE
+ struct {
+ uint8_t mods;
+ uint8_t bits[KEYBOARD_REPORT_BITS];
+ } nkro;
+#endif
+} __attribute__ ((packed)) report_keyboard_t;
+/*
+typedef struct {
+ uint8_t mods;
+ uint8_t reserved;
+ uint8_t keys[REPORT_KEYS];
+} __attribute__ ((packed)) report_keyboard_t;
+*/
+
+typedef struct {
+ uint8_t buttons;
+ int8_t x;
+ int8_t y;
+ int8_t v;
+ int8_t h;
+} __attribute__ ((packed)) report_mouse_t;
+
+
+/* keycode to system usage */
+#define KEYCODE2SYSTEM(key) \
+ (key == KC_SYSTEM_POWER ? SYSTEM_POWER_DOWN : \
+ (key == KC_SYSTEM_SLEEP ? SYSTEM_SLEEP : \
+ (key == KC_SYSTEM_WAKE ? SYSTEM_WAKE_UP : 0)))
+
+/* keycode to consumer usage */
+#define KEYCODE2CONSUMER(key) \
+ (key == KC_AUDIO_MUTE ? AUDIO_MUTE : \
+ (key == KC_AUDIO_VOL_UP ? AUDIO_VOL_UP : \
+ (key == KC_AUDIO_VOL_DOWN ? AUDIO_VOL_DOWN : \
+ (key == KC_MEDIA_NEXT_TRACK ? TRANSPORT_NEXT_TRACK : \
+ (key == KC_MEDIA_PREV_TRACK ? TRANSPORT_PREV_TRACK : \
+ (key == KC_MEDIA_FAST_FORWARD ? TRANSPORT_FAST_FORWARD : \
+ (key == KC_MEDIA_REWIND ? TRANSPORT_REWIND : \
+ (key == KC_MEDIA_STOP ? TRANSPORT_STOP : \
+ (key == KC_MEDIA_EJECT ? TRANSPORT_STOP_EJECT : \
+ (key == KC_MEDIA_PLAY_PAUSE ? TRANSPORT_PLAY_PAUSE : \
+ (key == KC_MEDIA_SELECT ? AL_CC_CONFIG : \
+ (key == KC_MAIL ? AL_EMAIL : \
+ (key == KC_CALCULATOR ? AL_CALCULATOR : \
+ (key == KC_MY_COMPUTER ? AL_LOCAL_BROWSER : \
+ (key == KC_WWW_SEARCH ? AC_SEARCH : \
+ (key == KC_WWW_HOME ? AC_HOME : \
+ (key == KC_WWW_BACK ? AC_BACK : \
+ (key == KC_WWW_FORWARD ? AC_FORWARD : \
+ (key == KC_WWW_STOP ? AC_STOP : \
+ (key == KC_WWW_REFRESH ? AC_REFRESH : \
+ (key == KC_WWW_FAVORITES ? AC_BOOKMARKS : 0)))))))))))))))))))))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/tmk_core/common/sendchar.h b/tmk_core/common/sendchar.h
new file mode 100644
index 000000000..7a64d00c7
--- /dev/null
+++ b/tmk_core/common/sendchar.h
@@ -0,0 +1,35 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef SENDCHAR_H
+#define SENDCHAR_H
+
+#include <stdint.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* transmit a character. return 0 on success, -1 on error. */
+int8_t sendchar(uint8_t c);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/tmk_core/common/sendchar_null.c b/tmk_core/common/sendchar_null.c
new file mode 100644
index 000000000..293330622
--- /dev/null
+++ b/tmk_core/common/sendchar_null.c
@@ -0,0 +1,23 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "sendchar.h"
+
+
+int8_t sendchar(uint8_t c)
+{
+ return 0;
+}
diff --git a/tmk_core/common/sendchar_uart.c b/tmk_core/common/sendchar_uart.c
new file mode 100644
index 000000000..0241859eb
--- /dev/null
+++ b/tmk_core/common/sendchar_uart.c
@@ -0,0 +1,25 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "uart.h"
+#include "sendchar.h"
+
+
+int8_t sendchar(uint8_t c)
+{
+ uart_putchar(c);
+ return 0;
+}
diff --git a/tmk_core/common/sleep_led.h b/tmk_core/common/sleep_led.h
new file mode 100644
index 000000000..6bdcf558a
--- /dev/null
+++ b/tmk_core/common/sleep_led.h
@@ -0,0 +1,21 @@
+#ifndef SLEEP_LED_H
+#define SLEEP_LED_H
+
+
+#ifdef SLEEP_LED_ENABLE
+
+void sleep_led_init(void);
+void sleep_led_enable(void);
+void sleep_led_disable(void);
+void sleep_led_toggle(void);
+
+#else
+
+#define sleep_led_init()
+#define sleep_led_enable()
+#define sleep_led_disable()
+#define sleep_led_toggle()
+
+#endif
+
+#endif
diff --git a/tmk_core/common/suspend.h b/tmk_core/common/suspend.h
new file mode 100644
index 000000000..80617a824
--- /dev/null
+++ b/tmk_core/common/suspend.h
@@ -0,0 +1,13 @@
+#ifndef SUSPEND_H
+#define SUSPEND_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+
+void suspend_idle(uint8_t timeout);
+void suspend_power_down(void);
+bool suspend_wakeup_condition(void);
+void suspend_wakeup_init(void);
+
+#endif
diff --git a/tmk_core/common/timer.h b/tmk_core/common/timer.h
new file mode 100644
index 000000000..fe23f87ae
--- /dev/null
+++ b/tmk_core/common/timer.h
@@ -0,0 +1,53 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef TIMER_H
+#define TIMER_H 1
+
+#include <stdint.h>
+
+#if defined(__AVR__)
+#include "avr/timer_avr.h"
+#endif
+
+
+#define TIMER_DIFF(a, b, max) ((a) >= (b) ? (a) - (b) : (max) - (b) + (a))
+#define TIMER_DIFF_8(a, b) TIMER_DIFF(a, b, UINT8_MAX)
+#define TIMER_DIFF_16(a, b) TIMER_DIFF(a, b, UINT16_MAX)
+#define TIMER_DIFF_32(a, b) TIMER_DIFF(a, b, UINT32_MAX)
+#define TIMER_DIFF_RAW(a, b) TIMER_DIFF_8(a, b)
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern volatile uint32_t timer_count;
+
+
+void timer_init(void);
+void timer_clear(void);
+uint16_t timer_read(void);
+uint32_t timer_read32(void);
+uint16_t timer_elapsed(uint16_t last);
+uint32_t timer_elapsed32(uint32_t last);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/tmk_core/common/uart.c b/tmk_core/common/uart.c
new file mode 100644
index 000000000..c17649b08
--- /dev/null
+++ b/tmk_core/common/uart.c
@@ -0,0 +1,129 @@
+// TODO: Teensy support(ATMega32u4/AT90USB128)
+// Fixed for Arduino Duemilanove ATmega168p by Jun Wako
+/* UART Example for Teensy USB Development Board
+ * http://www.pjrc.com/teensy/
+ * Copyright (c) 2009 PJRC.COM, LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+// Version 1.0: Initial Release
+// Version 1.1: Add support for Teensy 2.0, minor optimizations
+
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+
+#include "uart.h"
+
+// These buffers may be any size from 2 to 256 bytes.
+#define RX_BUFFER_SIZE 64
+#define TX_BUFFER_SIZE 40
+
+static volatile uint8_t tx_buffer[TX_BUFFER_SIZE];
+static volatile uint8_t tx_buffer_head;
+static volatile uint8_t tx_buffer_tail;
+static volatile uint8_t rx_buffer[RX_BUFFER_SIZE];
+static volatile uint8_t rx_buffer_head;
+static volatile uint8_t rx_buffer_tail;
+
+// Initialize the UART
+void uart_init(uint32_t baud)
+{
+ cli();
+ UBRR0 = (F_CPU / 4 / baud - 1) / 2;
+ UCSR0A = (1<<U2X0);
+ UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0);
+ UCSR0C = (1<<UCSZ01) | (1<<UCSZ00);
+ tx_buffer_head = tx_buffer_tail = 0;
+ rx_buffer_head = rx_buffer_tail = 0;
+ sei();
+}
+
+// Transmit a byte
+void uart_putchar(uint8_t c)
+{
+ uint8_t i;
+
+ i = tx_buffer_head + 1;
+ if (i >= TX_BUFFER_SIZE) i = 0;
+ while (tx_buffer_tail == i) ; // wait until space in buffer
+ //cli();
+ tx_buffer[i] = c;
+ tx_buffer_head = i;
+ UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0) | (1<<UDRIE0);
+ //sei();
+}
+
+// Receive a byte
+uint8_t uart_getchar(void)
+{
+ uint8_t c, i;
+
+ while (rx_buffer_head == rx_buffer_tail) ; // wait for character
+ i = rx_buffer_tail + 1;
+ if (i >= RX_BUFFER_SIZE) i = 0;
+ c = rx_buffer[i];
+ rx_buffer_tail = i;
+ return c;
+}
+
+// Return the number of bytes waiting in the receive buffer.
+// Call this before uart_getchar() to check if it will need
+// to wait for a byte to arrive.
+uint8_t uart_available(void)
+{
+ uint8_t head, tail;
+
+ head = rx_buffer_head;
+ tail = rx_buffer_tail;
+ if (head >= tail) return head - tail;
+ return RX_BUFFER_SIZE + head - tail;
+}
+
+// Transmit Interrupt
+ISR(USART_UDRE_vect)
+{
+ uint8_t i;
+
+ if (tx_buffer_head == tx_buffer_tail) {
+ // buffer is empty, disable transmit interrupt
+ UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0);
+ } else {
+ i = tx_buffer_tail + 1;
+ if (i >= TX_BUFFER_SIZE) i = 0;
+ UDR0 = tx_buffer[i];
+ tx_buffer_tail = i;
+ }
+}
+
+// Receive Interrupt
+ISR(USART_RX_vect)
+{
+ uint8_t c, i;
+
+ c = UDR0;
+ i = rx_buffer_head + 1;
+ if (i >= RX_BUFFER_SIZE) i = 0;
+ if (i != rx_buffer_tail) {
+ rx_buffer[i] = c;
+ rx_buffer_head = i;
+ }
+}
+
diff --git a/tmk_core/common/uart.h b/tmk_core/common/uart.h
new file mode 100644
index 000000000..41136a396
--- /dev/null
+++ b/tmk_core/common/uart.h
@@ -0,0 +1,11 @@
+#ifndef _uart_included_h_
+#define _uart_included_h_
+
+#include <stdint.h>
+
+void uart_init(uint32_t baud);
+void uart_putchar(uint8_t c);
+uint8_t uart_getchar(void);
+uint8_t uart_available(void);
+
+#endif
diff --git a/tmk_core/common/util.c b/tmk_core/common/util.c
new file mode 100644
index 000000000..7e0d54299
--- /dev/null
+++ b/tmk_core/common/util.c
@@ -0,0 +1,101 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "util.h"
+
+// bit population - return number of on-bit
+uint8_t bitpop(uint8_t bits)
+{
+ uint8_t c;
+ for (c = 0; bits; c++)
+ bits &= bits - 1;
+ return c;
+/*
+ const uint8_t bit_count[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
+ return bit_count[bits>>4] + bit_count[bits&0x0F]
+*/
+}
+
+uint8_t bitpop16(uint16_t bits)
+{
+ uint8_t c;
+ for (c = 0; bits; c++)
+ bits &= bits - 1;
+ return c;
+}
+
+uint8_t bitpop32(uint32_t bits)
+{
+ uint8_t c;
+ for (c = 0; bits; c++)
+ bits &= bits - 1;
+ return c;
+}
+
+// most significant on-bit - return highest location of on-bit
+// NOTE: return 0 when bit0 is on or all bits are off
+uint8_t biton(uint8_t bits)
+{
+ uint8_t n = 0;
+ if (bits >> 4) { bits >>= 4; n += 4;}
+ if (bits >> 2) { bits >>= 2; n += 2;}
+ if (bits >> 1) { bits >>= 1; n += 1;}
+ return n;
+}
+
+uint8_t biton16(uint16_t bits)
+{
+ uint8_t n = 0;
+ if (bits >> 8) { bits >>= 8; n += 8;}
+ if (bits >> 4) { bits >>= 4; n += 4;}
+ if (bits >> 2) { bits >>= 2; n += 2;}
+ if (bits >> 1) { bits >>= 1; n += 1;}
+ return n;
+}
+
+uint8_t biton32(uint32_t bits)
+{
+ uint8_t n = 0;
+ if (bits >>16) { bits >>=16; n +=16;}
+ if (bits >> 8) { bits >>= 8; n += 8;}
+ if (bits >> 4) { bits >>= 4; n += 4;}
+ if (bits >> 2) { bits >>= 2; n += 2;}
+ if (bits >> 1) { bits >>= 1; n += 1;}
+ return n;
+}
+
+
+
+uint8_t bitrev(uint8_t bits)
+{
+ bits = (bits & 0x0f)<<4 | (bits & 0xf0)>>4;
+ bits = (bits & 0b00110011)<<2 | (bits & 0b11001100)>>2;
+ bits = (bits & 0b01010101)<<1 | (bits & 0b10101010)>>1;
+ return bits;
+}
+
+uint16_t bitrev16(uint16_t bits)
+{
+ bits = bitrev(bits & 0x00ff)<<8 | bitrev((bits & 0xff00)>>8);
+ return bits;
+}
+
+uint32_t bitrev32(uint32_t bits)
+{
+ bits = (uint32_t)bitrev16(bits & 0x0000ffff)<<16 | bitrev16((bits & 0xffff0000)>>16);
+ return bits;
+}
diff --git a/tmk_core/common/util.h b/tmk_core/common/util.h
new file mode 100644
index 000000000..7451cc084
--- /dev/null
+++ b/tmk_core/common/util.h
@@ -0,0 +1,43 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef UTIL_H
+#define UTIL_H
+
+#include <stdint.h>
+
+// convert to L string
+#define LSTR(s) XLSTR(s)
+#define XLSTR(s) L ## #s
+// convert to string
+#define STR(s) XSTR(s)
+#define XSTR(s) #s
+
+
+uint8_t bitpop(uint8_t bits);
+uint8_t bitpop16(uint16_t bits);
+uint8_t bitpop32(uint32_t bits);
+
+uint8_t biton(uint8_t bits);
+uint8_t biton16(uint16_t bits);
+uint8_t biton32(uint32_t bits);
+
+uint8_t bitrev(uint8_t bits);
+uint16_t bitrev16(uint16_t bits);
+uint32_t bitrev32(uint32_t bits);
+
+#endif
diff --git a/tmk_core/common/wait.h b/tmk_core/common/wait.h
new file mode 100644
index 000000000..82727be01
--- /dev/null
+++ b/tmk_core/common/wait.h
@@ -0,0 +1,24 @@
+#ifndef WAIT_H
+#define WAIT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(__AVR__)
+# include <util/delay.h>
+# define wait_ms(ms) _delay_ms(ms)
+# define wait_us(us) _delay_us(us)
+#elif defined(PROTOCOL_CHIBIOS) /* __AVR__ */
+# include "ch.h"
+# define wait_ms(ms) chThdSleepMilliseconds(ms)
+# define wait_us(us) chThdSleepMicroseconds(us)
+#elif defined(__arm__) /* __AVR__ */
+# include "wait_api.h"
+#endif /* __AVR__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/tmk_core/ldscript_keymap_avr35.x b/tmk_core/ldscript_keymap_avr35.x
new file mode 100644
index 000000000..6665020af
--- /dev/null
+++ b/tmk_core/ldscript_keymap_avr35.x
@@ -0,0 +1,268 @@
+/*
+ * linker script for configurable keymap
+ *
+ * This adds keymap section which places keymap at fixed address and
+ * is based on binutils-avr ldscripts(/usr/lib/ldscripts/avr5.x).
+ */
+OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr")
+OUTPUT_ARCH(avr:35)
+MEMORY
+{
+ /* With keymap section
+ *
+ * Flash Map of ATMega32U4(32KB)
+ * +------------+ 0x0000
+ * | .vectors |
+ * | .progmem |
+ * | .init0-9 | > text region
+ * | .text |
+ * | .fini9-0 |
+ * | |
+ * |------------| _etext
+ * | .data |
+ * | .bss | > data region
+ * | .noinit |
+ * | |
+ * |------------| 0x6800
+ * | .keymap | > keymap region(2KB)
+ * |------------| 0x7000
+ * | bootloader | 4KB
+ * +------------+ 0x7FFF
+ */
+ text (rx) : ORIGIN = 0, LENGTH = 64K
+ keymap (rw!x) : ORIGIN = 0x6800, LENGTH = 2K
+ data (rw!x) : ORIGIN = 0x800060, LENGTH = 0xffa0
+ eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K
+ fuse (rw!x) : ORIGIN = 0x820000, LENGTH = 1K
+ lock (rw!x) : ORIGIN = 0x830000, LENGTH = 1K
+ signature (rw!x) : ORIGIN = 0x840000, LENGTH = 1K
+}
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+ .rel.init : { *(.rel.init) }
+ .rela.init : { *(.rela.init) }
+ .rel.text :
+ {
+ *(.rel.text)
+ *(.rel.text.*)
+ *(.rel.gnu.linkonce.t*)
+ }
+ .rela.text :
+ {
+ *(.rela.text)
+ *(.rela.text.*)
+ *(.rela.gnu.linkonce.t*)
+ }
+ .rel.fini : { *(.rel.fini) }
+ .rela.fini : { *(.rela.fini) }
+ .rel.rodata :
+ {
+ *(.rel.rodata)
+ *(.rel.rodata.*)
+ *(.rel.gnu.linkonce.r*)
+ }
+ .rela.rodata :
+ {
+ *(.rela.rodata)
+ *(.rela.rodata.*)
+ *(.rela.gnu.linkonce.r*)
+ }
+ .rel.data :
+ {
+ *(.rel.data)
+ *(.rel.data.*)
+ *(.rel.gnu.linkonce.d*)
+ }
+ .rela.data :
+ {
+ *(.rela.data)
+ *(.rela.data.*)
+ *(.rela.gnu.linkonce.d*)
+ }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ /* Internal text space or external memory. */
+ .text :
+ {
+ *(.vectors)
+ KEEP(*(.vectors))
+ /* For data that needs to reside in the lower 64k of progmem. */
+ *(.progmem.gcc*)
+ *(.progmem*)
+ . = ALIGN(2);
+ __trampolines_start = . ;
+ /* The jump trampolines for the 16-bit limited relocs will reside here. */
+ *(.trampolines)
+ *(.trampolines*)
+ __trampolines_end = . ;
+ /* For future tablejump instruction arrays for 3 byte pc devices.
+ We don't relax jump/call instructions within these sections. */
+ *(.jumptables)
+ *(.jumptables*)
+ /* For code that needs to reside in the lower 128k progmem. */
+ *(.lowtext)
+ *(.lowtext*)
+ __ctors_start = . ;
+ *(.ctors)
+ __ctors_end = . ;
+ __dtors_start = . ;
+ *(.dtors)
+ __dtors_end = . ;
+ KEEP(SORT(*)(.ctors))
+ KEEP(SORT(*)(.dtors))
+ /* From this point on, we don't bother about wether the insns are
+ below or above the 16 bits boundary. */
+ *(.init0) /* Start here after reset. */
+ KEEP (*(.init0))
+ *(.init1)
+ KEEP (*(.init1))
+ *(.init2) /* Clear __zero_reg__, set up stack pointer. */
+ KEEP (*(.init2))
+ *(.init3)
+ KEEP (*(.init3))
+ *(.init4) /* Initialize data and BSS. */
+ KEEP (*(.init4))
+ *(.init5)
+ KEEP (*(.init5))
+ *(.init6) /* C++ constructors. */
+ KEEP (*(.init6))
+ *(.init7)
+ KEEP (*(.init7))
+ *(.init8)
+ KEEP (*(.init8))
+ *(.init9) /* Call main(). */
+ KEEP (*(.init9))
+ *(.text)
+ . = ALIGN(2);
+ *(.text.*)
+ . = ALIGN(2);
+ *(.fini9) /* _exit() starts here. */
+ KEEP (*(.fini9))
+ *(.fini8)
+ KEEP (*(.fini8))
+ *(.fini7)
+ KEEP (*(.fini7))
+ *(.fini6) /* C++ destructors. */
+ KEEP (*(.fini6))
+ *(.fini5)
+ KEEP (*(.fini5))
+ *(.fini4)
+ KEEP (*(.fini4))
+ *(.fini3)
+ KEEP (*(.fini3))
+ *(.fini2)
+ KEEP (*(.fini2))
+ *(.fini1)
+ KEEP (*(.fini1))
+ *(.fini0) /* Infinite loop after program termination. */
+ KEEP (*(.fini0))
+ _etext = . ;
+ } > text
+ .data : AT (ADDR (.text) + SIZEOF (.text))
+ {
+ PROVIDE (__data_start = .) ;
+ *(.data)
+ *(.data*)
+ *(.rodata) /* We need to include .rodata here if gcc is used */
+ *(.rodata*) /* with -fdata-sections. */
+ *(.gnu.linkonce.d*)
+ . = ALIGN(2);
+ _edata = . ;
+ PROVIDE (__data_end = .) ;
+ } > data
+ .bss : AT (ADDR (.bss))
+ {
+ PROVIDE (__bss_start = .) ;
+ *(.bss)
+ *(.bss*)
+ *(COMMON)
+ PROVIDE (__bss_end = .) ;
+ } > data
+ __data_load_start = LOADADDR(.data);
+ __data_load_end = __data_load_start + SIZEOF(.data);
+ /* Global data not cleared after reset. */
+ .noinit :
+ {
+ PROVIDE (__noinit_start = .) ;
+ *(.noinit*)
+ PROVIDE (__noinit_end = .) ;
+ _end = . ;
+ PROVIDE (__heap_start = .) ;
+ } > data
+ /* keymap region is located at end of flash
+ * .fn_actions Fn actions definitions
+ * .keymaps Mapping layers
+ */
+ .keymap :
+ {
+ PROVIDE(__keymap_start = .) ;
+ *(.keymap.fn_actions) /* 32*actions = 64bytes */
+ . = ALIGN(0x40);
+ *(.keymap.keymaps) /* rest of .keymap section */
+ *(.keymap*)
+ /* . = ALIGN(0x800); */ /* keymap section takes 2KB- */
+ } > keymap = 0x00 /* zero fill */
+ .eeprom :
+ {
+ *(.eeprom*)
+ __eeprom_end = . ;
+ } > eeprom
+ .fuse :
+ {
+ KEEP(*(.fuse))
+ KEEP(*(.lfuse))
+ KEEP(*(.hfuse))
+ KEEP(*(.efuse))
+ } > fuse
+ .lock :
+ {
+ KEEP(*(.lock*))
+ } > lock
+ .signature :
+ {
+ KEEP(*(.signature*))
+ } > signature
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+}
diff --git a/tmk_core/ldscript_keymap_avr5.x b/tmk_core/ldscript_keymap_avr5.x
new file mode 100644
index 000000000..9b46e6c36
--- /dev/null
+++ b/tmk_core/ldscript_keymap_avr5.x
@@ -0,0 +1,268 @@
+/*
+ * linker script for configurable keymap
+ *
+ * This adds keymap section which places keymap at fixed address and
+ * is based on binutils-avr ldscripts(/usr/lib/ldscripts/avr5.x).
+ */
+OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr")
+OUTPUT_ARCH(avr:5)
+MEMORY
+{
+ /* With keymap section
+ *
+ * Flash Map of ATMega32U4(32KB)
+ * +------------+ 0x0000
+ * | .vectors |
+ * | .progmem |
+ * | .init0-9 | > text region
+ * | .text |
+ * | .fini9-0 |
+ * | |
+ * |------------| _etext
+ * | .data |
+ * | .bss | > data region
+ * | .noinit |
+ * | |
+ * |------------| 0x6800
+ * | .keymap | > keymap region(2KB)
+ * |------------| 0x7000
+ * | bootloader | 4KB
+ * +------------+ 0x7FFF
+ */
+ text (rx) : ORIGIN = 0, LENGTH = 128K
+ keymap (rw!x) : ORIGIN = 0x6800, LENGTH = 2K
+ data (rw!x) : ORIGIN = 0x800060, LENGTH = 0xffa0
+ eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 64K
+ fuse (rw!x) : ORIGIN = 0x820000, LENGTH = 1K
+ lock (rw!x) : ORIGIN = 0x830000, LENGTH = 1K
+ signature (rw!x) : ORIGIN = 0x840000, LENGTH = 1K
+}
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+ .rel.init : { *(.rel.init) }
+ .rela.init : { *(.rela.init) }
+ .rel.text :
+ {
+ *(.rel.text)
+ *(.rel.text.*)
+ *(.rel.gnu.linkonce.t*)
+ }
+ .rela.text :
+ {
+ *(.rela.text)
+ *(.rela.text.*)
+ *(.rela.gnu.linkonce.t*)
+ }
+ .rel.fini : { *(.rel.fini) }
+ .rela.fini : { *(.rela.fini) }
+ .rel.rodata :
+ {
+ *(.rel.rodata)
+ *(.rel.rodata.*)
+ *(.rel.gnu.linkonce.r*)
+ }
+ .rela.rodata :
+ {
+ *(.rela.rodata)
+ *(.rela.rodata.*)
+ *(.rela.gnu.linkonce.r*)
+ }
+ .rel.data :
+ {
+ *(.rel.data)
+ *(.rel.data.*)
+ *(.rel.gnu.linkonce.d*)
+ }
+ .rela.data :
+ {
+ *(.rela.data)
+ *(.rela.data.*)
+ *(.rela.gnu.linkonce.d*)
+ }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ /* Internal text space or external memory. */
+ .text :
+ {
+ *(.vectors)
+ KEEP(*(.vectors))
+ /* For data that needs to reside in the lower 64k of progmem. */
+ *(.progmem.gcc*)
+ *(.progmem*)
+ . = ALIGN(2);
+ __trampolines_start = . ;
+ /* The jump trampolines for the 16-bit limited relocs will reside here. */
+ *(.trampolines)
+ *(.trampolines*)
+ __trampolines_end = . ;
+ /* For future tablejump instruction arrays for 3 byte pc devices.
+ We don't relax jump/call instructions within these sections. */
+ *(.jumptables)
+ *(.jumptables*)
+ /* For code that needs to reside in the lower 128k progmem. */
+ *(.lowtext)
+ *(.lowtext*)
+ __ctors_start = . ;
+ *(.ctors)
+ __ctors_end = . ;
+ __dtors_start = . ;
+ *(.dtors)
+ __dtors_end = . ;
+ KEEP(SORT(*)(.ctors))
+ KEEP(SORT(*)(.dtors))
+ /* From this point on, we don't bother about wether the insns are
+ below or above the 16 bits boundary. */
+ *(.init0) /* Start here after reset. */
+ KEEP (*(.init0))
+ *(.init1)
+ KEEP (*(.init1))
+ *(.init2) /* Clear __zero_reg__, set up stack pointer. */
+ KEEP (*(.init2))
+ *(.init3)
+ KEEP (*(.init3))
+ *(.init4) /* Initialize data and BSS. */
+ KEEP (*(.init4))
+ *(.init5)
+ KEEP (*(.init5))
+ *(.init6) /* C++ constructors. */
+ KEEP (*(.init6))
+ *(.init7)
+ KEEP (*(.init7))
+ *(.init8)
+ KEEP (*(.init8))
+ *(.init9) /* Call main(). */
+ KEEP (*(.init9))
+ *(.text)
+ . = ALIGN(2);
+ *(.text.*)
+ . = ALIGN(2);
+ *(.fini9) /* _exit() starts here. */
+ KEEP (*(.fini9))
+ *(.fini8)
+ KEEP (*(.fini8))
+ *(.fini7)
+ KEEP (*(.fini7))
+ *(.fini6) /* C++ destructors. */
+ KEEP (*(.fini6))
+ *(.fini5)
+ KEEP (*(.fini5))
+ *(.fini4)
+ KEEP (*(.fini4))
+ *(.fini3)
+ KEEP (*(.fini3))
+ *(.fini2)
+ KEEP (*(.fini2))
+ *(.fini1)
+ KEEP (*(.fini1))
+ *(.fini0) /* Infinite loop after program termination. */
+ KEEP (*(.fini0))
+ _etext = . ;
+ } > text
+ .data : AT (ADDR (.text) + SIZEOF (.text))
+ {
+ PROVIDE (__data_start = .) ;
+ *(.data)
+ *(.data*)
+ *(.rodata) /* We need to include .rodata here if gcc is used */
+ *(.rodata*) /* with -fdata-sections. */
+ *(.gnu.linkonce.d*)
+ . = ALIGN(2);
+ _edata = . ;
+ PROVIDE (__data_end = .) ;
+ } > data
+ .bss : AT (ADDR (.bss))
+ {
+ PROVIDE (__bss_start = .) ;
+ *(.bss)
+ *(.bss*)
+ *(COMMON)
+ PROVIDE (__bss_end = .) ;
+ } > data
+ __data_load_start = LOADADDR(.data);
+ __data_load_end = __data_load_start + SIZEOF(.data);
+ /* Global data not cleared after reset. */
+ .noinit :
+ {
+ PROVIDE (__noinit_start = .) ;
+ *(.noinit*)
+ PROVIDE (__noinit_end = .) ;
+ _end = . ;
+ PROVIDE (__heap_start = .) ;
+ } > data
+ /* keymap region is located at end of flash
+ * .fn_actions Fn actions definitions
+ * .keymaps Mapping layers
+ */
+ .keymap :
+ {
+ PROVIDE(__keymap_start = .) ;
+ *(.keymap.fn_actions) /* 32*actions = 64bytes */
+ . = ALIGN(0x40);
+ *(.keymap.keymaps) /* rest of .keymap section */
+ *(.keymap*)
+ /* . = ALIGN(0x800); */ /* keymap section takes 2KB- */
+ } > keymap = 0x00 /* zero fill */
+ .eeprom :
+ {
+ *(.eeprom*)
+ __eeprom_end = . ;
+ } > eeprom
+ .fuse :
+ {
+ KEEP(*(.fuse))
+ KEEP(*(.lfuse))
+ KEEP(*(.hfuse))
+ KEEP(*(.efuse))
+ } > fuse
+ .lock :
+ {
+ KEEP(*(.lock*))
+ } > lock
+ .signature :
+ {
+ KEEP(*(.signature*))
+ } > signature
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+}
diff --git a/tmk_core/protocol.mk b/tmk_core/protocol.mk
new file mode 100644
index 000000000..54913329e
--- /dev/null
+++ b/tmk_core/protocol.mk
@@ -0,0 +1,54 @@
+PROTOCOL_DIR = protocol
+
+
+ifdef PS2_MOUSE_ENABLE
+ SRC += $(PROTOCOL_DIR)/ps2_mouse.c
+ OPT_DEFS += -DPS2_MOUSE_ENABLE
+ OPT_DEFS += -DMOUSE_ENABLE
+endif
+
+ifdef PS2_USE_BUSYWAIT
+ SRC += protocol/ps2_busywait.c
+ SRC += protocol/ps2_io_avr.c
+ OPT_DEFS += -DPS2_USE_BUSYWAIT
+endif
+
+ifdef PS2_USE_INT
+ SRC += protocol/ps2_interrupt.c
+ SRC += protocol/ps2_io_avr.c
+ OPT_DEFS += -DPS2_USE_INT
+endif
+
+ifdef PS2_USE_USART
+ SRC += protocol/ps2_usart.c
+ SRC += protocol/ps2_io_avr.c
+ OPT_DEFS += -DPS2_USE_USART
+endif
+
+
+ifdef SERIAL_MOUSE_MICROSOFT_ENABLE
+ SRC += $(PROTOCOL_DIR)/serial_mouse_microsoft.c
+ OPT_DEFS += -DSERIAL_MOUSE_ENABLE -DSERIAL_MOUSE_MICROSOFT \
+ -DMOUSE_ENABLE
+endif
+
+ifdef SERIAL_MOUSE_MOUSESYSTEMS_ENABLE
+ SRC += $(PROTOCOL_DIR)/serial_mouse_mousesystems.c
+ OPT_DEFS += -DSERIAL_MOUSE_ENABLE -DSERIAL_MOUSE_MOUSESYSTEMS \
+ -DMOUSE_ENABLE
+endif
+
+ifdef SERIAL_MOUSE_USE_SOFT
+ SRC += $(PROTOCOL_DIR)/serial_soft.c
+endif
+
+ifdef SERIAL_MOUSE_USE_UART
+ SRC += $(PROTOCOL_DIR)/serial_uart.c
+endif
+
+ifdef ADB_MOUSE_ENABLE
+ OPT_DEFS += -DADB_MOUSE_ENABLE -DMOUSE_ENABLE
+endif
+
+# Search Path
+VPATH += $(TMK_DIR)/protocol
diff --git a/tmk_core/protocol/adb.c b/tmk_core/protocol/adb.c
new file mode 100644
index 000000000..5c6c99b4f
--- /dev/null
+++ b/tmk_core/protocol/adb.c
@@ -0,0 +1,478 @@
+/*
+Copyright 2011 Jun WAKO <wakojun@gmail.com>
+Copyright 2013 Shay Green <gblargg@gmail.com>
+
+This software is licensed with a Modified BSD License.
+All of this is supposed to be Free Software, Open Source, DFSG-free,
+GPL-compatible, and OK to use in both free and proprietary applications.
+Additions and corrections to this file are welcome.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+* Neither the name of the copyright holders nor the names of
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdbool.h>
+#include <util/delay.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include "adb.h"
+
+
+// GCC doesn't inline functions normally
+#define data_lo() (ADB_DDR |= (1<<ADB_DATA_BIT))
+#define data_hi() (ADB_DDR &= ~(1<<ADB_DATA_BIT))
+#define data_in() (ADB_PIN & (1<<ADB_DATA_BIT))
+
+#ifdef ADB_PSW_BIT
+static inline void psw_lo(void);
+static inline void psw_hi(void);
+static inline bool psw_in(void);
+#endif
+
+static inline void attention(void);
+static inline void place_bit0(void);
+static inline void place_bit1(void);
+static inline void send_byte(uint8_t data);
+static inline uint16_t wait_data_lo(uint16_t us);
+static inline uint16_t wait_data_hi(uint16_t us);
+static inline uint16_t adb_host_dev_recv(uint8_t device);
+
+
+void adb_host_init(void)
+{
+ ADB_PORT &= ~(1<<ADB_DATA_BIT);
+ data_hi();
+#ifdef ADB_PSW_BIT
+ psw_hi();
+#endif
+}
+
+#ifdef ADB_PSW_BIT
+bool adb_host_psw(void)
+{
+ return psw_in();
+}
+#endif
+
+/*
+ * Don't call this in a row without the delay, otherwise it makes some of poor controllers
+ * overloaded and misses strokes. Recommended interval is 12ms.
+ *
+ * Thanks a lot, blargg!
+ * <http://geekhack.org/index.php?topic=14290.msg1068919#msg1068919>
+ * <http://geekhack.org/index.php?topic=14290.msg1070139#msg1070139>
+ */
+
+// ADB Bit Cells
+//
+// bit cell time: 70-130us
+// low part of bit0: 60-70% of bit cell
+// low part of bit1: 30-40% of bit cell
+//
+// bit cell time 70us 130us
+// --------------------------------------------
+// low part of bit0 42-49 78-91
+// high part of bit0 21-28 39-52
+// low part of bit1 21-28 39-52
+// high part of bit1 42-49 78-91
+//
+//
+// bit0:
+// 70us bit cell:
+// ____________~~~~~~
+// 42-49 21-28
+//
+// 130us bit cell:
+// ____________~~~~~~
+// 78-91 39-52
+//
+// bit1:
+// 70us bit cell:
+// ______~~~~~~~~~~~~
+// 21-28 42-49
+//
+// 130us bit cell:
+// ______~~~~~~~~~~~~
+// 39-52 78-91
+//
+// [from Apple IIgs Hardware Reference Second Edition]
+
+enum {
+ ADDR_KEYB = 0x20,
+ ADDR_MOUSE = 0x30
+};
+
+uint16_t adb_host_kbd_recv(void)
+{
+ return adb_host_dev_recv(ADDR_KEYB);
+}
+
+#ifdef ADB_MOUSE_ENABLE
+void adb_mouse_init(void) {
+ return;
+}
+
+uint16_t adb_host_mouse_recv(void)
+{
+ return adb_host_dev_recv(ADDR_MOUSE);
+}
+#endif
+
+static inline uint16_t adb_host_dev_recv(uint8_t device)
+{
+ uint16_t data = 0;
+ cli();
+ attention();
+ send_byte(device|0x0C); // Addr:Keyboard(0010)/Mouse(0011), Cmd:Talk(11), Register0(00)
+ place_bit0(); // Stopbit(0)
+ if (!wait_data_hi(500)) { // Service Request(310us Adjustable Keyboard): just ignored
+ sei();
+ return -30; // something wrong
+ }
+ if (!wait_data_lo(500)) { // Tlt/Stop to Start(140-260us)
+ sei();
+ return 0; // No data to send
+ }
+
+ uint8_t n = 17; // start bit + 16 data bits
+ do {
+ uint8_t lo = (uint8_t) wait_data_hi(130);
+ if (!lo)
+ goto error;
+
+ uint8_t hi = (uint8_t) wait_data_lo(lo);
+ if (!hi)
+ goto error;
+
+ hi = lo - hi;
+ lo = 130 - lo;
+
+ data <<= 1;
+ if (lo < hi) {
+ data |= 1;
+ }
+ else if (n == 17) {
+ sei();
+ return -20;
+ }
+ }
+ while ( --n );
+
+ // Stop bit can't be checked normally since it could have service request lenghtening
+ // and its high state never goes low.
+ if (!wait_data_hi(351) || wait_data_lo(91)) {
+ sei();
+ return -21;
+ }
+ sei();
+ return data;
+
+error:
+ sei();
+ return -n;
+}
+
+void adb_host_listen(uint8_t cmd, uint8_t data_h, uint8_t data_l)
+{
+ cli();
+ attention();
+ send_byte(cmd);
+ place_bit0(); // Stopbit(0)
+ _delay_us(200); // Tlt/Stop to Start
+ place_bit1(); // Startbit(1)
+ send_byte(data_h);
+ send_byte(data_l);
+ place_bit0(); // Stopbit(0);
+ sei();
+}
+
+// send state of LEDs
+void adb_host_kbd_led(uint8_t led)
+{
+ // Addr:Keyboard(0010), Cmd:Listen(10), Register2(10)
+ // send upper byte (not used)
+ // send lower byte (bit2: ScrollLock, bit1: CapsLock, bit0:
+ adb_host_listen(0x2A,0,led&0x07);
+}
+
+
+#ifdef ADB_PSW_BIT
+static inline void psw_lo()
+{
+ ADB_DDR |= (1<<ADB_PSW_BIT);
+ ADB_PORT &= ~(1<<ADB_PSW_BIT);
+}
+static inline void psw_hi()
+{
+ ADB_PORT |= (1<<ADB_PSW_BIT);
+ ADB_DDR &= ~(1<<ADB_PSW_BIT);
+}
+static inline bool psw_in()
+{
+ ADB_PORT |= (1<<ADB_PSW_BIT);
+ ADB_DDR &= ~(1<<ADB_PSW_BIT);
+ return ADB_PIN&(1<<ADB_PSW_BIT);
+}
+#endif
+
+static inline void attention(void)
+{
+ data_lo();
+ _delay_us(800-35); // bit1 holds lo for 35 more
+ place_bit1();
+}
+
+static inline void place_bit0(void)
+{
+ data_lo();
+ _delay_us(65);
+ data_hi();
+ _delay_us(35);
+}
+
+static inline void place_bit1(void)
+{
+ data_lo();
+ _delay_us(35);
+ data_hi();
+ _delay_us(65);
+}
+
+static inline void send_byte(uint8_t data)
+{
+ for (int i = 0; i < 8; i++) {
+ if (data&(0x80>>i))
+ place_bit1();
+ else
+ place_bit0();
+ }
+}
+
+// These are carefully coded to take 6 cycles of overhead.
+// inline asm approach became too convoluted
+static inline uint16_t wait_data_lo(uint16_t us)
+{
+ do {
+ if ( !data_in() )
+ break;
+ _delay_us(1 - (6 * 1000000.0 / F_CPU));
+ }
+ while ( --us );
+ return us;
+}
+
+static inline uint16_t wait_data_hi(uint16_t us)
+{
+ do {
+ if ( data_in() )
+ break;
+ _delay_us(1 - (6 * 1000000.0 / F_CPU));
+ }
+ while ( --us );
+ return us;
+}
+
+
+/*
+ADB Protocol
+============
+
+Resources
+---------
+ADB - The Untold Story: Space Aliens Ate My Mouse
+ http://developer.apple.com/legacy/mac/library/#technotes/hw/hw_01.html
+ADB Manager
+ http://developer.apple.com/legacy/mac/library/documentation/mac/pdf/Devices/ADB_Manager.pdf
+ Service request(5-17)
+Apple IIgs Hardware Reference Second Edition [Chapter6 p121]
+ ftp://ftp.apple.asimov.net/pub/apple_II/documentation/Apple%20IIgs%20Hardware%20Reference.pdf
+ADB Keycode
+ http://72.0.193.250/Documentation/macppc/adbkeycodes/
+ http://m0115.web.fc2.com/m0115.jpg
+ [Inside Macintosh volume V, pages 191-192]
+ http://www.opensource.apple.com/source/IOHIDFamily/IOHIDFamily-421.18.3/IOHIDFamily/Cosmo_USB2ADB.c
+ADB Signaling
+ http://kbdbabel.sourceforge.net/doc/kbd_signaling_pcxt_ps2_adb.pdf
+ADB Overview & History
+ http://en.wikipedia.org/wiki/Apple_Desktop_Bus
+Microchip Application Note: ADB device(with code for PIC16C)
+ http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1824&appnote=en011062
+AVR ATtiny2131 ADB to PS/2 converter(Japanese)
+ http://hp.vector.co.jp/authors/VA000177/html/KeyBoardA5DEA5CBA5A2II.html
+
+
+Pinouts
+-------
+ ADB female socket from the front:
+ __________
+ | | <--- top
+ | 4o o3 |
+ |2o o1|
+ | == |
+ |________| <--- bottom
+ | | <--- 4pins
+
+
+ ADB female socket from bottom:
+
+ ========== <--- front
+ | |
+ | |
+ |2o o1|
+ |4o o3|
+ ---------- <--- back
+
+ 1: Data
+ 2: Power SW(low when press Power key)
+ 3: Vcc(5V)
+ 4: GND
+
+
+Commands
+--------
+ ADB command is 1byte and consists of 4bit-address, 2bit-command
+ type and 2bit-register. The commands are always sent by Host.
+
+ Command format:
+ 7 6 5 4 3 2 1 0
+ | | | |------------ address
+ | |-------- command type
+ | |---- register
+
+ bits commands
+ ------------------------------------------------------
+ - - - - 0 0 0 0 Send Request(reset all devices)
+ A A A A 0 0 0 1 Flush(reset a device)
+ - - - - 0 0 1 0 Reserved
+ - - - - 0 0 1 1 Reserved
+ - - - - 0 1 - - Reserved
+ A A A A 1 0 R R Listen(write to a device)
+ A A A A 1 1 R R Talk(read from a device)
+
+ The command to read keycodes from keyboard is 0x2C which
+ consist of keyboard address 2 and Talk against register 0.
+
+ Address:
+ 2: keyboard
+ 3: mice
+
+ Registers:
+ 0: application(keyboard uses this to store its data.)
+ 1: application
+ 2: application(keyboard uses this for LEDs and state of modifiers)
+ 3: status and command
+
+
+Communication
+-------------
+ This is a minimum information for keyboard communication.
+ See "Resources" for detail.
+
+ Signaling:
+
+ ~~~~____________~~||||||||||||__~~~~~_~~|||||||||||||||__~~~~
+
+ |800us | |7 Command 0| | | |15-64 Data 0|Stopbit(0)
+ +Attention | | | +Startbit(1)
+ +Startbit(1) | +Tlt(140-260us)
+ +stopbit(0)
+
+ Bit cells:
+
+ bit0: ______~~~
+ 65 :35us
+
+ bit1: ___~~~~~~
+ 35 :65us
+
+ bit0 low time: 60-70% of bit cell(42-91us)
+ bit1 low time: 30-40% of bit cell(21-52us)
+ bit cell time: 70-130us
+ [from Apple IIgs Hardware Reference Second Edition]
+
+ Criterion for bit0/1:
+ After 55us if line is low/high then bit is 0/1.
+
+ Attention & start bit:
+ Host asserts low in 560-1040us then places start bit(1).
+
+ Tlt(Stop to Start):
+ Bus stays high in 140-260us then device places start bit(1).
+
+ Global reset:
+ Host asserts low in 2.8-5.2ms. All devices are forced to reset.
+
+ Service request from device(Srq):
+ Device can request to send at commad(Global only?) stop bit.
+ Requesting device keeps low for 140-260us at stop bit of command.
+
+
+Keyboard Data(Register0)
+ This 16bit data can contains two keycodes and two released flags.
+ First keycode is palced in upper byte. When one keyocode is sent,
+ lower byte is 0xFF.
+ Release flag is 1 when key is released.
+
+ 1514 . . . . . 8 7 6 . . . . . 0
+ | | | | | | | | | +-+-+-+-+-+-+- Keycode2
+ | | | | | | | | +--------------- Released2(1 when the key is released)
+ | +-+-+-+-+-+-+----------------- Keycode1
+ +------------------------------- Released1(1 when the key is released)
+
+ Keycodes:
+ Scancode consists of 7bit keycode and 1bit release flag.
+ Device can send two keycodes at once. If just one keycode is sent
+ keycode1 contains it and keyocode2 is 0xFF.
+
+ Power switch:
+ You can read the state from PSW line(active low) however
+ the switch has a special scancode 0x7F7F, so you can
+ also read from Data line. It uses 0xFFFF for release scancode.
+
+Keyboard LEDs & state of keys(Register2)
+ This register hold current state of three LEDs and nine keys.
+ The state of LEDs can be changed by sending Listen command.
+
+ 1514 . . . . . . 7 6 5 . 3 2 1 0
+ | | | | | | | | | | | | | | | +- LED1(NumLock)
+ | | | | | | | | | | | | | | +--- LED2(CapsLock)
+ | | | | | | | | | | | | | +----- LED3(ScrollLock)
+ | | | | | | | | | | +-+-+------- Reserved
+ | | | | | | | | | +------------- ScrollLock
+ | | | | | | | | +--------------- NumLock
+ | | | | | | | +----------------- Apple/Command
+ | | | | | | +------------------- Option
+ | | | | | +--------------------- Shift
+ | | | | +----------------------- Control
+ | | | +------------------------- Reset/Power
+ | | +--------------------------- CapsLock
+ | +----------------------------- Delete
+ +------------------------------- Reserved
+
+END_OF_ADB
+*/
diff --git a/tmk_core/protocol/adb.h b/tmk_core/protocol/adb.h
new file mode 100644
index 000000000..b4b3633cf
--- /dev/null
+++ b/tmk_core/protocol/adb.h
@@ -0,0 +1,66 @@
+/*
+Copyright 2011 Jun WAKO <wakojun@gmail.com>
+
+This software is licensed with a Modified BSD License.
+All of this is supposed to be Free Software, Open Source, DFSG-free,
+GPL-compatible, and OK to use in both free and proprietary applications.
+Additions and corrections to this file are welcome.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+* Neither the name of the copyright holders nor the names of
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef ADB_H
+#define ADB_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#if !(defined(ADB_PORT) && \
+ defined(ADB_PIN) && \
+ defined(ADB_DDR) && \
+ defined(ADB_DATA_BIT))
+# error "ADB port setting is required in config.h"
+#endif
+
+#define ADB_POWER 0x7F
+#define ADB_CAPS 0x39
+
+
+// ADB host
+void adb_host_init(void);
+bool adb_host_psw(void);
+uint16_t adb_host_kbd_recv(void);
+uint16_t adb_host_mouse_recv(void);
+void adb_host_listen(uint8_t cmd, uint8_t data_h, uint8_t data_l);
+void adb_host_kbd_led(uint8_t led);
+void adb_mouse_task(void);
+void adb_mouse_init(void);
+
+
+#endif
diff --git a/tmk_core/protocol/bluefruit.mk b/tmk_core/protocol/bluefruit.mk
new file mode 100644
index 000000000..e1c5fff77
--- /dev/null
+++ b/tmk_core/protocol/bluefruit.mk
@@ -0,0 +1,27 @@
+BLUEFRUIT_DIR = protocol/bluefruit
+PJRC_DIR = protocol/pjrc
+
+SRC += $(BLUEFRUIT_DIR)/main.c \
+ $(BLUEFRUIT_DIR)/bluefruit.c \
+ serial_uart.c \
+ $(PJRC_DIR)/pjrc.c \
+ $(PJRC_DIR)/usb_keyboard.c \
+ $(PJRC_DIR)/usb_debug.c \
+ $(PJRC_DIR)/usb.c
+
+# Option modules
+ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE)
+ SRC += $(PJRC_DIR)/usb_mouse.c
+endif
+
+ifdef EXTRAKEY_ENABLE
+ SRC += $(PJRC_DIR)/usb_extra.c
+endif
+
+# Search Path
+VPATH += $(TMK_DIR)/$(BLUEFRUIT_DIR)
+#VPATH += $(TMK_DIR)/$(BLUEFRUIT_DIR)/usb_debug_only
+VPATH += $(TMK_DIR)/$(PJRC_DIR)
+
+OPT_DEFS += -DPROTOCOL_BLUEFRUIT
+OPT_DEFS += -DPROTOCOL_PJRC
diff --git a/tmk_core/protocol/bluefruit/bluefruit.c b/tmk_core/protocol/bluefruit/bluefruit.c
new file mode 100644
index 000000000..47c63555c
--- /dev/null
+++ b/tmk_core/protocol/bluefruit/bluefruit.c
@@ -0,0 +1,205 @@
+/*
+Bluefruit Protocol for TMK firmware
+Author: Benjamin Gould, 2013
+Based on code Copyright 2011 Jun Wako <wakojun@gmail.com>
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdint.h>
+#include "host.h"
+#include "report.h"
+#include "print.h"
+#include "debug.h"
+#include "host_driver.h"
+#include "serial.h"
+#include "bluefruit.h"
+
+#define BLUEFRUIT_TRACE_SERIAL 1
+
+static uint8_t bluefruit_keyboard_leds = 0;
+
+static void bluefruit_serial_send(uint8_t);
+
+void bluefruit_keyboard_print_report(report_keyboard_t *report)
+{
+ if (!debug_keyboard) return;
+ dprintf("keys: "); for (int i = 0; i < KEYBOARD_REPORT_KEYS; i++) { debug_hex8(report->keys[i]); dprintf(" "); }
+ dprintf(" mods: "); debug_hex8(report->mods);
+ dprintf(" reserved: "); debug_hex8(report->reserved);
+ dprintf("\n");
+}
+
+#ifdef BLUEFRUIT_TRACE_SERIAL
+static void bluefruit_trace_header()
+{
+ dprintf("+------------------------------------+\n");
+ dprintf("| HID report to Bluefruit via serial |\n");
+ dprintf("+------------------------------------+\n|");
+}
+
+static void bluefruit_trace_footer()
+{
+ dprintf("|\n+------------------------------------+\n\n");
+}
+#endif
+
+static void bluefruit_serial_send(uint8_t data)
+{
+#ifdef BLUEFRUIT_TRACE_SERIAL
+ dprintf(" ");
+ debug_hex8(data);
+ dprintf(" ");
+#endif
+ serial_send(data);
+}
+
+/*------------------------------------------------------------------*
+ * Host driver
+ *------------------------------------------------------------------*/
+
+static uint8_t keyboard_leds(void);
+static void send_keyboard(report_keyboard_t *report);
+static void send_mouse(report_mouse_t *report);
+static void send_system(uint16_t data);
+static void send_consumer(uint16_t data);
+
+
+void sendString(char string[], int length) {
+ for(int i = 0; i < length; i++) {
+ serial_send(string[i]);
+ }
+}
+
+static host_driver_t driver = {
+ keyboard_leds,
+ send_keyboard,
+ send_mouse,
+ send_system,
+ send_consumer
+};
+
+host_driver_t *bluefruit_driver(void)
+{
+ return &driver;
+}
+
+static uint8_t keyboard_leds(void) {
+ return bluefruit_keyboard_leds;
+}
+
+static void send_keyboard(report_keyboard_t *report)
+{
+#ifdef BLUEFRUIT_TRACE_SERIAL
+ bluefruit_trace_header();
+#endif
+ bluefruit_serial_send(0xFD);
+ for (uint8_t i = 0; i < KEYBOARD_REPORT_SIZE; i++) {
+
+ bluefruit_serial_send(report->raw[i]);
+ }
+#ifdef BLUEFRUIT_TRACE_SERIAL
+ bluefruit_trace_footer();
+#endif
+}
+
+static void send_mouse(report_mouse_t *report)
+{
+#ifdef BLUEFRUIT_TRACE_SERIAL
+ bluefruit_trace_header();
+#endif
+ bluefruit_serial_send(0xFD);
+ bluefruit_serial_send(0x00);
+ bluefruit_serial_send(0x03);
+ bluefruit_serial_send(report->buttons);
+ bluefruit_serial_send(report->x);
+ bluefruit_serial_send(report->y);
+ bluefruit_serial_send(report->v); // should try sending the wheel v here
+ bluefruit_serial_send(report->h); // should try sending the wheel h here
+ bluefruit_serial_send(0x00);
+#ifdef BLUEFRUIT_TRACE_SERIAL
+ bluefruit_trace_footer();
+#endif
+}
+
+static void send_system(uint16_t data)
+{
+}
+
+/*
++-----------------+-------------------+-------+
+| Consumer Key | Bit Map | Hex |
++-----------------+-------------------+-------+
+| Home | 00000001 00000000 | 01 00 |
+| KeyboardLayout | 00000010 00000000 | 02 00 |
+| Search | 00000100 00000000 | 04 00 |
+| Snapshot | 00001000 00000000 | 08 00 |
+| VolumeUp | 00010000 00000000 | 10 00 |
+| VolumeDown | 00100000 00000000 | 20 00 |
+| Play/Pause | 01000000 00000000 | 40 00 |
+| Fast Forward | 10000000 00000000 | 80 00 |
+| Rewind | 00000000 00000001 | 00 01 |
+| Scan Next Track | 00000000 00000010 | 00 02 |
+| Scan Prev Track | 00000000 00000100 | 00 04 |
+| Random Play | 00000000 00001000 | 00 08 |
+| Stop | 00000000 00010000 | 00 10 |
++-------------------------------------+-------+
+*/
+#define CONSUMER2BLUEFRUIT(usage) \
+ (usage == AUDIO_MUTE ? 0x0000 : \
+ (usage == AUDIO_VOL_UP ? 0x1000 : \
+ (usage == AUDIO_VOL_DOWN ? 0x2000 : \
+ (usage == TRANSPORT_NEXT_TRACK ? 0x0002 : \
+ (usage == TRANSPORT_PREV_TRACK ? 0x0004 : \
+ (usage == TRANSPORT_STOP ? 0x0010 : \
+ (usage == TRANSPORT_STOP_EJECT ? 0x0000 : \
+ (usage == TRANSPORT_PLAY_PAUSE ? 0x4000 : \
+ (usage == AL_CC_CONFIG ? 0x0000 : \
+ (usage == AL_EMAIL ? 0x0000 : \
+ (usage == AL_CALCULATOR ? 0x0000 : \
+ (usage == AL_LOCAL_BROWSER ? 0x0000 : \
+ (usage == AC_SEARCH ? 0x0400 : \
+ (usage == AC_HOME ? 0x0100 : \
+ (usage == AC_BACK ? 0x0000 : \
+ (usage == AC_FORWARD ? 0x0000 : \
+ (usage == AC_STOP ? 0x0000 : \
+ (usage == AC_REFRESH ? 0x0000 : \
+ (usage == AC_BOOKMARKS ? 0x0000 : 0)))))))))))))))))))
+
+static void send_consumer(uint16_t data)
+{
+ static uint16_t last_data = 0;
+ if (data == last_data) return;
+ last_data = data;
+
+ uint16_t bitmap = CONSUMER2BLUEFRUIT(data);
+
+#ifdef BLUEFRUIT_TRACE_SERIAL
+ dprintf("\nData: ");
+ debug_hex16(data);
+ dprintf("; bitmap: ");
+ debug_hex16(bitmap);
+ dprintf("\n");
+ bluefruit_trace_header();
+#endif
+ bluefruit_serial_send(0xFD);
+ bluefruit_serial_send(0x00);
+ bluefruit_serial_send(0x02);
+ bluefruit_serial_send((bitmap>>8)&0xFF);
+ bluefruit_serial_send(bitmap&0xFF);
+ bluefruit_serial_send(0x00);
+ bluefruit_serial_send(0x00);
+ bluefruit_serial_send(0x00);
+ bluefruit_serial_send(0x00);
+#ifdef BLUEFRUIT_TRACE_SERIAL
+ bluefruit_trace_footer();
+#endif
+} \ No newline at end of file
diff --git a/tmk_core/protocol/bluefruit/bluefruit.h b/tmk_core/protocol/bluefruit/bluefruit.h
new file mode 100644
index 000000000..ceacc4a36
--- /dev/null
+++ b/tmk_core/protocol/bluefruit/bluefruit.h
@@ -0,0 +1,25 @@
+/*
+Bluefruit Protocol for TMK firmware
+Author: Benjamin Gould, 2013
+Based on code Copyright 2011 Jun Wako <wakojun@gmail.com>
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef VUSB_H
+#define VUSB_H
+
+#include "host_driver.h"
+
+
+host_driver_t *bluefruit_driver(void);
+
+#endif \ No newline at end of file
diff --git a/tmk_core/protocol/bluefruit/main.c b/tmk_core/protocol/bluefruit/main.c
new file mode 100644
index 000000000..0dbb637e2
--- /dev/null
+++ b/tmk_core/protocol/bluefruit/main.c
@@ -0,0 +1,138 @@
+/*
+Bluefruit Protocol for TMK firmware
+Author: Benjamin Gould, 2013
+Based on code Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdint.h>
+#include <avr/interrupt.h>
+#include <avr/wdt.h>
+#include <avr/sleep.h>
+#include <util/delay.h>
+#include "../serial.h"
+#include "keyboard.h"
+#include "usb.h"
+#include "host.h"
+#include "timer.h"
+#include "print.h"
+#include "debug.h"
+#include "sendchar.h"
+#include "suspend.h"
+#include "bluefruit.h"
+#include "pjrc.h"
+
+#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
+
+#define HOST_DRIVER_NOT_SET 0
+#define BLUEFRUIT_HOST_DRIVER 1
+#define PJRC_HOST_DRIVER 2
+
+
+int main(void)
+{
+
+ CPU_PRESCALE(0);
+
+ // DDRD = _BV(PD5);
+ // DDRB = _BV(PB0);
+
+ // PORTD = _BV(PD5);
+ // PORTB = _BV(PB0);
+
+ print_set_sendchar(sendchar);
+
+ // usb_init();
+ // _delay_ms(2000);
+ // while (!usb_configured()) /* wait */
+
+
+
+ dprintf("Initializing keyboard...\n");
+ keyboard_init();
+
+ // This implementation is pretty simplistic... if the USB connection
+ // is not configured, choose the Bluefruit, otherwise use USB
+ // Definitely would prefer to have this driven by an input pin and make
+ // it switch dynamically - BCG
+ // if (!usb_configured()) {
+
+ // // Send power to Bluefruit... Adafruit says it takes 27 mA, I think
+ // // the pins should provide 40 mA, but just in case I switch the
+ // // Bluefruit using a transistor - BCG
+ // DDRB = _BV(PB6);
+ // PORTB |= _BV(PB6);
+
+ dprintf("Setting host driver to bluefruit...\n");
+ host_set_driver(bluefruit_driver());
+
+ dprintf("Initializing serial...\n");
+ serial_init();
+
+ // char swpa[] = "+++\r\n";
+ // for (int i = 0; i < 5; i++) {
+ // serial_send(swpa[i]);
+ // }
+
+ // char ble_enable[] = "AT+BLEKEYBOARDEN=1\r\n";
+ // for (int i = 0; i < 20; i++) {
+ // serial_send(ble_enable[i]);
+ // }
+
+ // char reset[] = "ATZ\r\n";
+ // for (int i = 0; i < 5; i++) {
+ // serial_send(reset[i]);
+ // }
+
+ // for (int i = 0; i < 5; i++) {
+ // serial_send(swpa[i]);
+ // }
+
+ // wait an extra second for the PC's operating system
+ // to load drivers and do whatever it does to actually
+ // be ready for input
+ _delay_ms(1000);
+ // PORTD = ~_BV(PD5);
+ dprintf("Starting main loop");
+ while (1) {
+ keyboard_task();
+ }
+
+// } else {
+
+// // I'm not smart enough to get this done with LUFA - BCG
+// dprintf("Setting host driver to PJRC...\n");
+// host_set_driver(pjrc_driver());
+// #ifdef SLEEP_LED_ENABLE
+// sleep_led_init();
+// #endif
+// // wait an extra second for the PC's operating system
+// // to load drivers and do whatever it does to actually
+// // be ready for input
+// _delay_ms(1000);
+// PORTB = ~_BV(PB0);
+// dprintf("Starting main loop");
+// while (1) {
+// while (suspend) {
+// suspend_power_down();
+// if (remote_wakeup && suspend_wakeup_condition()) {
+// usb_remote_wakeup();
+// }
+// }
+// keyboard_task();
+// }
+// }
+
+}
diff --git a/tmk_core/protocol/chibios.mk b/tmk_core/protocol/chibios.mk
new file mode 100644
index 000000000..3f4e0a71f
--- /dev/null
+++ b/tmk_core/protocol/chibios.mk
@@ -0,0 +1,10 @@
+PROTOCOL_DIR = protocol
+CHIBIOS_DIR = $(PROTOCOL_DIR)/chibios
+
+
+SRC += $(CHIBIOS_DIR)/usb_main.c
+SRC += $(CHIBIOS_DIR)/main.c
+
+VPATH += $(TMK_PATH)/$(PROTOCOL_DIR)
+VPATH += $(TMK_PATH)/$(CHIBIOS_DIR)
+
diff --git a/tmk_core/protocol/chibios/README.md b/tmk_core/protocol/chibios/README.md
new file mode 100644
index 000000000..63e6641f8
--- /dev/null
+++ b/tmk_core/protocol/chibios/README.md
@@ -0,0 +1,55 @@
+## TMK running on top of ChibiOS
+
+This code can be used to run TMK keyboard logic on top of [ChibiOS], meaning that you can run TMK on whatever [ChibiOS] supports. The notable examples are ARM-based Teensies (3.x and LC) and on the boards with STM32 MCUs.
+
+### Usage
+
+- To use, [get a zip of chibios](https://github.com/ChibiOS/ChibiOS/archive/a7df9a891067621e8e1a5c2a2c0ceada82403afe.zip) and unpack/rename it to `tmk_core/tool/chibios/chibios`; or you can just clone [the repo](https://github.com/ChibiOS/ChibiOS) there. For Freescale/NXP Kinetis support (meaning ARM Teensies and the Infinity keyboard), you'll also need [a zip of chibios-contrib](https://github.com/ChibiOS/ChibiOS-Contrib/archive/e1311c4db6cd366cf760673f769e925741ac0ad3.zip), unpacked/renamed to `tmk_core/tool/chibios/chibios-contrib`. Likewise, for git-savvy people, just clone [the repo](https://github.com/ChibiOS/ChibiOS-Contrib) there.
+- Note: the abovementioned directories are the defaults. You can have the two chibios repositories wherever you want, just define their location in `CHIBIOS` and `CHIBIOS_CONTRIB` variables in your `Makefile`.
+- You will also need to install an ARM toolchain, for instance from [here](https://launchpad.net/gcc-arm-embedded). On linux, this is usually also present as a package for your distribution (as `gcc-arm` or something similar). On OS X, you can use [homebrew](http://brew.sh/) with an appropriate tap.
+
+### Notes
+
+- Some comments about ChibiOS syntax and the most commonly used GPIO functions are, as well as an example for ARM Teensies, is [here](https://github.com/tmk/tmk_keyboard/blob/master/keyboard/teensy_lc_onekey/instructions.md).
+- For gcc options, inspect `tmk_core/tool/chibios/chibios.mk`. For instance, I enabled `-Wno-missing-field-initializers`, because TMK common bits generated a lot of warnings on that.
+- For debugging, it is sometimes useful disable gcc optimisations, you can do that by adding `-O0` to `OPT_DEFS` in your `Makefile`.
+- USB string descriptors are messy. I did not find a way to cleanly generate the right structures from actual strings, so the definitions in individual keyboards' `config.h` are ugly as heck.
+- It is easy to add some code for testing (e.g. blink LED, do stuff on button press, etc...) - just create another thread in `main.c`, it will run independently of the keyboard business.
+- Jumping to (the built-in) bootloaders on STM32 works, but it is not entirely pleasant, since it is very much MCU dependent. So, one needs to dig out the right address to jump to, and either pass it to the compiler in the `Makefile`, or better, define it in `<your_kb>/bootloader_defs.h`. An additional startup code is also needed; the best way to deal with this is to define custom board files. (Example forthcoming.) In any case, there are no problems for Teensies.
+
+
+### Immediate todo
+
+- power saving for suspend
+
+### Not tested, but possibly working
+
+- backlight
+
+### Missing / not working (TMK vs ChibiOS bits)
+
+- eeprom / bootmagic for STM32 (will be chip dependent; eeprom needs to be emulated in flash, which means less writes; wear-levelling?) There is a semi-official ST "driver" for eeprom, with wear-levelling, but I think it consumes a lot of RAM (like 2 pages, i.e. 1kB or so).
+
+### Tried with
+
+- Infinity, WhiteFox keyboards
+- all ARM-based Teensies
+- some STM32-based boards (e.g. ST-F072RB-DISCOVERY board, STM32F042 breakout board, Maple Mini (STM32F103-based))
+
+## ChibiOS-supported MCUs
+
+- Pretty much all STM32 chips.
+- K20x and KL2x Freescale/NXP chips (i.e. Teensy 3.x/LC, mchck, FRDM-KL2{5,6}Z, FRDM-K20D50M), via the [ChibiOS-Contrib](https://github.com/ChibiOS/ChibiOS-Contrib) repository.
+- There is also support for AVR8, but the USB stack is not implemented for them yet (some news on that front recently though), and also the kernel itself takes about 1k of RAM. I think people managed to get ChibiOS running on atmega32[8p/u4] though.
+- There is also support for Nordic NRF51822 (the chip in Adafruit's Bluefruit bluetooth-low-energy boards), but be aware that that chip does *not* have USB, and the BLE softdevice (i.e. Bluetooth) is not supported directly at the moment.
+
+## STM32-based keyboard design considerations
+
+- STM32F0x2 chips can do crystal-less USB, but they still need a 3.3V voltage regulator.
+- The BOOT0 pin should be tied to GND.
+- For a hardware way of accessing the in-built DFU bootloader, in addition to the reset button, put another button between the BOOT0 pin and 3V3.
+- There is a working example of a STM32F042-based keyboard: [firmware here](https://github.com/flabbergast/flabber_kbs/tree/master/kb45p) and [hardware (kicad) here](https://github.com/flabbergast/kicad/tree/master/kb45p). You can check this example firmware for custom board files, and a more complicated matrix than just one key.
+
+
+
+[ChibiOS]: http://chibios.org
diff --git a/tmk_core/protocol/chibios/main.c b/tmk_core/protocol/chibios/main.c
new file mode 100644
index 000000000..54bb6a8f5
--- /dev/null
+++ b/tmk_core/protocol/chibios/main.c
@@ -0,0 +1,147 @@
+/*
+ * (c) 2015 flabberast <s3+flabbergast@sdfeu.org>
+ *
+ * Based on the following work:
+ * - Guillaume Duc's raw hid example (MIT License)
+ * https://github.com/guiduc/usb-hid-chibios-example
+ * - PJRC Teensy examples (MIT License)
+ * https://www.pjrc.com/teensy/usb_keyboard.html
+ * - hasu's TMK keyboard code (GPL v2 and some code Modified BSD)
+ * https://github.com/tmk/tmk_keyboard/
+ * - ChibiOS demo code (Apache 2.0 License)
+ * http://www.chibios.org
+ *
+ * Since some GPL'd code is used, this work is licensed under
+ * GPL v2 or later.
+ */
+
+#include "ch.h"
+#include "hal.h"
+
+#include "usb_main.h"
+
+/* TMK includes */
+#include "report.h"
+#include "host.h"
+#include "host_driver.h"
+#include "keyboard.h"
+#include "action.h"
+#include "action_util.h"
+#include "mousekey.h"
+#include "led.h"
+#include "sendchar.h"
+#include "debug.h"
+#include "printf.h"
+#ifdef SLEEP_LED_ENABLE
+#include "sleep_led.h"
+#endif
+#include "suspend.h"
+
+
+/* -------------------------
+ * TMK host driver defs
+ * -------------------------
+ */
+
+/* declarations */
+uint8_t keyboard_leds(void);
+void send_keyboard(report_keyboard_t *report);
+void send_mouse(report_mouse_t *report);
+void send_system(uint16_t data);
+void send_consumer(uint16_t data);
+
+/* host struct */
+host_driver_t chibios_driver = {
+ keyboard_leds,
+ send_keyboard,
+ send_mouse,
+ send_system,
+ send_consumer
+};
+
+
+/* TESTING
+ * Amber LED blinker thread, times are in milliseconds.
+ */
+/* set this variable to non-zero anywhere to blink once */
+// uint8_t blinkLed = 0;
+// static THD_WORKING_AREA(waBlinkerThread, 128);
+// static THD_FUNCTION(blinkerThread, arg) {
+// (void)arg;
+// chRegSetThreadName("blinkOrange");
+// while(true) {
+// if(blinkLed) {
+// blinkLed = 0;
+// palSetPad(TEENSY_PIN13_IOPORT, TEENSY_PIN13);
+// chThdSleepMilliseconds(100);
+// palClearPad(TEENSY_PIN13_IOPORT, TEENSY_PIN13);
+// }
+// chThdSleepMilliseconds(100);
+// }
+// }
+
+
+
+/* Main thread
+ */
+int main(void) {
+ /* ChibiOS/RT init */
+ halInit();
+ chSysInit();
+
+ // TESTING
+ // chThdCreateStatic(waBlinkerThread, sizeof(waBlinkerThread), NORMALPRIO, blinkerThread, NULL);
+
+ /* Init USB */
+ init_usb_driver(&USB_DRIVER);
+
+ /* init printf */
+ init_printf(NULL,sendchar_pf);
+
+ /* Wait until the USB is active */
+ while(USB_DRIVER.state != USB_ACTIVE)
+ chThdSleepMilliseconds(50);
+
+ /* Do need to wait here!
+ * Otherwise the next print might start a transfer on console EP
+ * before the USB is completely ready, which sometimes causes
+ * HardFaults.
+ */
+ chThdSleepMilliseconds(50);
+
+ print("USB configured.\n");
+
+ /* init TMK modules */
+ keyboard_init();
+ host_set_driver(&chibios_driver);
+
+#ifdef SLEEP_LED_ENABLE
+ sleep_led_init();
+#endif
+
+ print("Keyboard start.\n");
+
+ /* Main loop */
+ while(true) {
+
+ if(USB_DRIVER.state == USB_SUSPENDED) {
+ print("[s]");
+ while(USB_DRIVER.state == USB_SUSPENDED) {
+ /* Do this in the suspended state */
+ suspend_power_down(); // on AVR this deep sleeps for 15ms
+ /* Remote wakeup */
+ if((USB_DRIVER.status & 2) && suspend_wakeup_condition()) {
+ send_remote_wakeup(&USB_DRIVER);
+ }
+ }
+ /* Woken up */
+ // variables has been already cleared by the wakeup hook
+ send_keyboard_report();
+#ifdef MOUSEKEY_ENABLE
+ mousekey_send();
+#endif /* MOUSEKEY_ENABLE */
+ }
+
+ keyboard_task();
+ }
+}
diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c
new file mode 100644
index 000000000..e2c9d9bf1
--- /dev/null
+++ b/tmk_core/protocol/chibios/usb_main.c
@@ -0,0 +1,1372 @@
+/*
+ * (c) 2015 flabberast <s3+flabbergast@sdfeu.org>
+ *
+ * Based on the following work:
+ * - Guillaume Duc's raw hid example (MIT License)
+ * https://github.com/guiduc/usb-hid-chibios-example
+ * - PJRC Teensy examples (MIT License)
+ * https://www.pjrc.com/teensy/usb_keyboard.html
+ * - hasu's TMK keyboard code (GPL v2 and some code Modified BSD)
+ * https://github.com/tmk/tmk_keyboard/
+ * - ChibiOS demo code (Apache 2.0 License)
+ * http://www.chibios.org
+ *
+ * Since some GPL'd code is used, this work is licensed under
+ * GPL v2 or later.
+ */
+
+#include "ch.h"
+#include "hal.h"
+
+#include "usb_main.h"
+
+#include "host.h"
+#include "debug.h"
+#include "suspend.h"
+#ifdef SLEEP_LED_ENABLE
+#include "sleep_led.h"
+#include "led.h"
+#endif
+
+/* ---------------------------------------------------------
+ * Global interface variables and declarations
+ * ---------------------------------------------------------
+ */
+
+uint8_t keyboard_idle __attribute__((aligned(2))) = 0;
+uint8_t keyboard_protocol __attribute__((aligned(2))) = 1;
+uint16_t keyboard_led_stats __attribute__((aligned(2))) = 0;
+volatile uint16_t keyboard_idle_count = 0;
+static virtual_timer_t keyboard_idle_timer;
+static void keyboard_idle_timer_cb(void *arg);
+#ifdef NKRO_ENABLE
+extern bool keyboard_nkro;
+#endif /* NKRO_ENABLE */
+
+report_keyboard_t keyboard_report_sent = {{0}};
+#ifdef MOUSE_ENABLE
+report_mouse_t mouse_report_blank = {0};
+#endif /* MOUSE_ENABLE */
+#ifdef EXTRAKEY_ENABLE
+uint8_t extra_report_blank[3] = {0};
+#endif /* EXTRAKEY_ENABLE */
+
+#ifdef CONSOLE_ENABLE
+/* The emission buffers queue */
+output_buffers_queue_t console_buf_queue;
+static uint8_t console_queue_buffer[BQ_BUFFER_SIZE(CONSOLE_QUEUE_CAPACITY, CONSOLE_EPSIZE)];
+
+static virtual_timer_t console_flush_timer;
+void console_queue_onotify(io_buffers_queue_t *bqp);
+static void console_flush_cb(void *arg);
+#endif /* CONSOLE_ENABLE */
+
+/* ---------------------------------------------------------
+ * Descriptors and USB driver objects
+ * ---------------------------------------------------------
+ */
+
+/* HID specific constants */
+#define USB_DESCRIPTOR_HID 0x21
+#define USB_DESCRIPTOR_HID_REPORT 0x22
+#define HID_GET_REPORT 0x01
+#define HID_GET_IDLE 0x02
+#define HID_GET_PROTOCOL 0x03
+#define HID_SET_REPORT 0x09
+#define HID_SET_IDLE 0x0A
+#define HID_SET_PROTOCOL 0x0B
+
+/* USB Device Descriptor */
+static const uint8_t usb_device_descriptor_data[] = {
+ USB_DESC_DEVICE(0x0200, // bcdUSB (1.1)
+ 0, // bDeviceClass (defined in later in interface)
+ 0, // bDeviceSubClass
+ 0, // bDeviceProtocol
+ 64, // bMaxPacketSize (64 bytes) (the driver didn't work with 32)
+ VENDOR_ID, // idVendor
+ PRODUCT_ID, // idProduct
+ DEVICE_VER, // bcdDevice
+ 1, // iManufacturer
+ 2, // iProduct
+ 3, // iSerialNumber
+ 1) // bNumConfigurations
+};
+
+/* Device Descriptor wrapper */
+static const USBDescriptor usb_device_descriptor = {
+ sizeof usb_device_descriptor_data,
+ usb_device_descriptor_data
+};
+
+/*
+ * HID Report Descriptor
+ *
+ * See "Device Class Definition for Human Interface Devices (HID)"
+ * (http://www.usb.org/developers/hidpage/HID1_11.pdf) for the
+ * detailed descrition of all the fields
+ */
+
+/* Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60 */
+static const uint8_t keyboard_hid_report_desc_data[] = {
+ 0x05, 0x01, // Usage Page (Generic Desktop),
+ 0x09, 0x06, // Usage (Keyboard),
+ 0xA1, 0x01, // Collection (Application),
+ 0x75, 0x01, // Report Size (1),
+ 0x95, 0x08, // Report Count (8),
+ 0x05, 0x07, // Usage Page (Key Codes),
+ 0x19, 0xE0, // Usage Minimum (224),
+ 0x29, 0xE7, // Usage Maximum (231),
+ 0x15, 0x00, // Logical Minimum (0),
+ 0x25, 0x01, // Logical Maximum (1),
+ 0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte
+ 0x95, 0x01, // Report Count (1),
+ 0x75, 0x08, // Report Size (8),
+ 0x81, 0x03, // Input (Constant), ;Reserved byte
+ 0x95, 0x05, // Report Count (5),
+ 0x75, 0x01, // Report Size (1),
+ 0x05, 0x08, // Usage Page (LEDs),
+ 0x19, 0x01, // Usage Minimum (1),
+ 0x29, 0x05, // Usage Maximum (5),
+ 0x91, 0x02, // Output (Data, Variable, Absolute), ;LED report
+ 0x95, 0x01, // Report Count (1),
+ 0x75, 0x03, // Report Size (3),
+ 0x91, 0x03, // Output (Constant), ;LED report padding
+ 0x95, KBD_REPORT_KEYS, // Report Count (),
+ 0x75, 0x08, // Report Size (8),
+ 0x15, 0x00, // Logical Minimum (0),
+ 0x25, 0xFF, // Logical Maximum(255),
+ 0x05, 0x07, // Usage Page (Key Codes),
+ 0x19, 0x00, // Usage Minimum (0),
+ 0x29, 0xFF, // Usage Maximum (255),
+ 0x81, 0x00, // Input (Data, Array),
+ 0xc0 // End Collection
+};
+/* wrapper */
+static const USBDescriptor keyboard_hid_report_descriptor = {
+ sizeof keyboard_hid_report_desc_data,
+ keyboard_hid_report_desc_data
+};
+
+#ifdef NKRO_ENABLE
+static const uint8_t nkro_hid_report_desc_data[] = {
+ 0x05, 0x01, // Usage Page (Generic Desktop),
+ 0x09, 0x06, // Usage (Keyboard),
+ 0xA1, 0x01, // Collection (Application),
+ // bitmap of modifiers
+ 0x75, 0x01, // Report Size (1),
+ 0x95, 0x08, // Report Count (8),
+ 0x05, 0x07, // Usage Page (Key Codes),
+ 0x19, 0xE0, // Usage Minimum (224),
+ 0x29, 0xE7, // Usage Maximum (231),
+ 0x15, 0x00, // Logical Minimum (0),
+ 0x25, 0x01, // Logical Maximum (1),
+ 0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte
+ // LED output report
+ 0x95, 0x05, // Report Count (5),
+ 0x75, 0x01, // Report Size (1),
+ 0x05, 0x08, // Usage Page (LEDs),
+ 0x19, 0x01, // Usage Minimum (1),
+ 0x29, 0x05, // Usage Maximum (5),
+ 0x91, 0x02, // Output (Data, Variable, Absolute),
+ 0x95, 0x01, // Report Count (1),
+ 0x75, 0x03, // Report Size (3),
+ 0x91, 0x03, // Output (Constant),
+ // bitmap of keys
+ 0x95, NKRO_REPORT_KEYS * 8, // Report Count (),
+ 0x75, 0x01, // Report Size (1),
+ 0x15, 0x00, // Logical Minimum (0),
+ 0x25, 0x01, // Logical Maximum(1),
+ 0x05, 0x07, // Usage Page (Key Codes),
+ 0x19, 0x00, // Usage Minimum (0),
+ 0x29, NKRO_REPORT_KEYS * 8 - 1, // Usage Maximum (),
+ 0x81, 0x02, // Input (Data, Variable, Absolute),
+ 0xc0 // End Collection
+};
+/* wrapper */
+static const USBDescriptor nkro_hid_report_descriptor = {
+ sizeof nkro_hid_report_desc_data,
+ nkro_hid_report_desc_data
+};
+#endif /* NKRO_ENABLE */
+
+#ifdef MOUSE_ENABLE
+/* Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension
+ * http://www.microchip.com/forums/tm.aspx?high=&m=391435&mpage=1#391521
+ * http://www.keil.com/forum/15671/
+ * http://www.microsoft.com/whdc/device/input/wheel.mspx */
+static const uint8_t mouse_hid_report_desc_data[] = {
+ /* mouse */
+ 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+ 0x09, 0x02, // USAGE (Mouse)
+ 0xa1, 0x01, // COLLECTION (Application)
+ //0x85, REPORT_ID_MOUSE, // REPORT_ID (1)
+ 0x09, 0x01, // USAGE (Pointer)
+ 0xa1, 0x00, // COLLECTION (Physical)
+ // ---------------------------- Buttons
+ 0x05, 0x09, // USAGE_PAGE (Button)
+ 0x19, 0x01, // USAGE_MINIMUM (Button 1)
+ 0x29, 0x05, // USAGE_MAXIMUM (Button 5)
+ 0x15, 0x00, // LOGICAL_MINIMUM (0)
+ 0x25, 0x01, // LOGICAL_MAXIMUM (1)
+ 0x75, 0x01, // REPORT_SIZE (1)
+ 0x95, 0x05, // REPORT_COUNT (5)
+ 0x81, 0x02, // INPUT (Data,Var,Abs)
+ 0x75, 0x03, // REPORT_SIZE (3)
+ 0x95, 0x01, // REPORT_COUNT (1)
+ 0x81, 0x03, // INPUT (Cnst,Var,Abs)
+ // ---------------------------- X,Y position
+ 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+ 0x09, 0x30, // USAGE (X)
+ 0x09, 0x31, // USAGE (Y)
+ 0x15, 0x81, // LOGICAL_MINIMUM (-127)
+ 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
+ 0x75, 0x08, // REPORT_SIZE (8)
+ 0x95, 0x02, // REPORT_COUNT (2)
+ 0x81, 0x06, // INPUT (Data,Var,Rel)
+ // ---------------------------- Vertical wheel
+ 0x09, 0x38, // USAGE (Wheel)
+ 0x15, 0x81, // LOGICAL_MINIMUM (-127)
+ 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
+ 0x35, 0x00, // PHYSICAL_MINIMUM (0) - reset physical
+ 0x45, 0x00, // PHYSICAL_MAXIMUM (0)
+ 0x75, 0x08, // REPORT_SIZE (8)
+ 0x95, 0x01, // REPORT_COUNT (1)
+ 0x81, 0x06, // INPUT (Data,Var,Rel)
+ // ---------------------------- Horizontal wheel
+ 0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
+ 0x0a, 0x38, 0x02, // USAGE (AC Pan)
+ 0x15, 0x81, // LOGICAL_MINIMUM (-127)
+ 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
+ 0x75, 0x08, // REPORT_SIZE (8)
+ 0x95, 0x01, // REPORT_COUNT (1)
+ 0x81, 0x06, // INPUT (Data,Var,Rel)
+ 0xc0, // END_COLLECTION
+ 0xc0, // END_COLLECTION
+};
+/* wrapper */
+static const USBDescriptor mouse_hid_report_descriptor = {
+ sizeof mouse_hid_report_desc_data,
+ mouse_hid_report_desc_data
+};
+#endif /* MOUSE_ENABLE */
+
+#ifdef CONSOLE_ENABLE
+static const uint8_t console_hid_report_desc_data[] = {
+ 0x06, 0x31, 0xFF, // Usage Page 0xFF31 (vendor defined)
+ 0x09, 0x74, // Usage 0x74
+ 0xA1, 0x53, // Collection 0x53
+ 0x75, 0x08, // report size = 8 bits
+ 0x15, 0x00, // logical minimum = 0
+ 0x26, 0xFF, 0x00, // logical maximum = 255
+ 0x95, CONSOLE_EPSIZE, // report count
+ 0x09, 0x75, // usage
+ 0x81, 0x02, // Input (array)
+ 0xC0 // end collection
+};
+/* wrapper */
+static const USBDescriptor console_hid_report_descriptor = {
+ sizeof console_hid_report_desc_data,
+ console_hid_report_desc_data
+};
+#endif /* CONSOLE_ENABLE */
+
+#ifdef EXTRAKEY_ENABLE
+/* audio controls & system controls
+ * http://www.microsoft.com/whdc/archive/w2kbd.mspx */
+static const uint8_t extra_hid_report_desc_data[] = {
+ /* system control */
+ 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+ 0x09, 0x80, // USAGE (System Control)
+ 0xa1, 0x01, // COLLECTION (Application)
+ 0x85, REPORT_ID_SYSTEM, // REPORT_ID (2)
+ 0x15, 0x01, // LOGICAL_MINIMUM (0x1)
+ 0x25, 0xb7, // LOGICAL_MAXIMUM (0xb7)
+ 0x19, 0x01, // USAGE_MINIMUM (0x1)
+ 0x29, 0xb7, // USAGE_MAXIMUM (0xb7)
+ 0x75, 0x10, // REPORT_SIZE (16)
+ 0x95, 0x01, // REPORT_COUNT (1)
+ 0x81, 0x00, // INPUT (Data,Array,Abs)
+ 0xc0, // END_COLLECTION
+ /* consumer */
+ 0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
+ 0x09, 0x01, // USAGE (Consumer Control)
+ 0xa1, 0x01, // COLLECTION (Application)
+ 0x85, REPORT_ID_CONSUMER, // REPORT_ID (3)
+ 0x15, 0x01, // LOGICAL_MINIMUM (0x1)
+ 0x26, 0x9c, 0x02, // LOGICAL_MAXIMUM (0x29c)
+ 0x19, 0x01, // USAGE_MINIMUM (0x1)
+ 0x2a, 0x9c, 0x02, // USAGE_MAXIMUM (0x29c)
+ 0x75, 0x10, // REPORT_SIZE (16)
+ 0x95, 0x01, // REPORT_COUNT (1)
+ 0x81, 0x00, // INPUT (Data,Array,Abs)
+ 0xc0, // END_COLLECTION
+};
+/* wrapper */
+static const USBDescriptor extra_hid_report_descriptor = {
+ sizeof extra_hid_report_desc_data,
+ extra_hid_report_desc_data
+};
+#endif /* EXTRAKEY_ENABLE */
+
+
+/*
+ * Configuration Descriptor tree for a HID device
+ *
+ * The HID Specifications version 1.11 require the following order:
+ * - Configuration Descriptor
+ * - Interface Descriptor
+ * - HID Descriptor
+ * - Endpoints Descriptors
+ */
+#define KBD_HID_DESC_NUM 0
+#define KBD_HID_DESC_OFFSET (9 + (9 + 9 + 7) * KBD_HID_DESC_NUM + 9)
+
+#ifdef MOUSE_ENABLE
+# define MOUSE_HID_DESC_NUM (KBD_HID_DESC_NUM + 1)
+# define MOUSE_HID_DESC_OFFSET (9 + (9 + 9 + 7) * MOUSE_HID_DESC_NUM + 9)
+#else /* MOUSE_ENABLE */
+# define MOUSE_HID_DESC_NUM (KBD_HID_DESC_NUM + 0)
+#endif /* MOUSE_ENABLE */
+
+#ifdef CONSOLE_ENABLE
+#define CONSOLE_HID_DESC_NUM (MOUSE_HID_DESC_NUM + 1)
+#define CONSOLE_HID_DESC_OFFSET (9 + (9 + 9 + 7) * CONSOLE_HID_DESC_NUM + 9)
+#else /* CONSOLE_ENABLE */
+# define CONSOLE_HID_DESC_NUM (MOUSE_HID_DESC_NUM + 0)
+#endif /* CONSOLE_ENABLE */
+
+#ifdef EXTRAKEY_ENABLE
+# define EXTRA_HID_DESC_NUM (CONSOLE_HID_DESC_NUM + 1)
+# define EXTRA_HID_DESC_OFFSET (9 + (9 + 9 + 7) * EXTRA_HID_DESC_NUM + 9)
+#else /* EXTRAKEY_ENABLE */
+# define EXTRA_HID_DESC_NUM (CONSOLE_HID_DESC_NUM + 0)
+#endif /* EXTRAKEY_ENABLE */
+
+#ifdef NKRO_ENABLE
+# define NKRO_HID_DESC_NUM (EXTRA_HID_DESC_NUM + 1)
+# define NKRO_HID_DESC_OFFSET (9 + (9 + 9 + 7) * EXTRA_HID_DESC_NUM + 9)
+#else /* NKRO_ENABLE */
+# define NKRO_HID_DESC_NUM (EXTRA_HID_DESC_NUM + 0)
+#endif /* NKRO_ENABLE */
+
+#define NUM_INTERFACES (NKRO_HID_DESC_NUM + 1)
+#define CONFIG1_DESC_SIZE (9 + (9 + 9 + 7) * NUM_INTERFACES)
+
+static const uint8_t hid_configuration_descriptor_data[] = {
+ /* Configuration Descriptor (9 bytes) USB spec 9.6.3, page 264-266, Table 9-10 */
+ USB_DESC_CONFIGURATION(CONFIG1_DESC_SIZE, // wTotalLength
+ NUM_INTERFACES, // bNumInterfaces
+ 1, // bConfigurationValue
+ 0, // iConfiguration
+ 0xA0, // bmAttributes (RESERVED|REMOTEWAKEUP)
+ 50), // bMaxPower (50mA)
+
+ /* Interface Descriptor (9 bytes) USB spec 9.6.5, page 267-269, Table 9-12 */
+ USB_DESC_INTERFACE(KBD_INTERFACE, // bInterfaceNumber
+ 0, // bAlternateSetting
+ 1, // bNumEndpoints
+ 0x03, // bInterfaceClass: HID
+ 0x01, // bInterfaceSubClass: Boot
+ 0x01, // bInterfaceProtocol: Keyboard
+ 0), // iInterface
+
+ /* HID descriptor (9 bytes) HID 1.11 spec, section 6.2.1 */
+ USB_DESC_BYTE(9), // bLength
+ USB_DESC_BYTE(0x21), // bDescriptorType (HID class)
+ USB_DESC_BCD(0x0111), // bcdHID: HID version 1.11
+ USB_DESC_BYTE(0), // bCountryCode
+ USB_DESC_BYTE(1), // bNumDescriptors
+ USB_DESC_BYTE(0x22), // bDescriptorType (report desc)
+ USB_DESC_WORD(sizeof(keyboard_hid_report_desc_data)), // wDescriptorLength
+
+ /* Endpoint Descriptor (7 bytes) USB spec 9.6.6, page 269-271, Table 9-13 */
+ USB_DESC_ENDPOINT(KBD_ENDPOINT | 0x80, // bEndpointAddress
+ 0x03, // bmAttributes (Interrupt)
+ KBD_EPSIZE,// wMaxPacketSize
+ 10), // bInterval
+
+ #ifdef MOUSE_ENABLE
+ /* Interface Descriptor (9 bytes) USB spec 9.6.5, page 267-269, Table 9-12 */
+ USB_DESC_INTERFACE(MOUSE_INTERFACE, // bInterfaceNumber
+ 0, // bAlternateSetting
+ 1, // bNumEndpoints
+ 0x03, // bInterfaceClass (0x03 = HID)
+ // ThinkPad T23 BIOS doesn't work with boot mouse.
+ 0x00, // bInterfaceSubClass (0x01 = Boot)
+ 0x00, // bInterfaceProtocol (0x02 = Mouse)
+ /*
+ 0x01, // bInterfaceSubClass (0x01 = Boot)
+ 0x02, // bInterfaceProtocol (0x02 = Mouse)
+ */
+ 0), // iInterface
+
+ /* HID descriptor (9 bytes) HID 1.11 spec, section 6.2.1 */
+ USB_DESC_BYTE(9), // bLength
+ USB_DESC_BYTE(0x21), // bDescriptorType (HID class)
+ USB_DESC_BCD(0x0111), // bcdHID: HID version 1.11
+ USB_DESC_BYTE(0), // bCountryCode
+ USB_DESC_BYTE(1), // bNumDescriptors
+ USB_DESC_BYTE(0x22), // bDescriptorType (report desc)
+ USB_DESC_WORD(sizeof(mouse_hid_report_desc_data)), // wDescriptorLength
+
+ /* Endpoint Descriptor (7 bytes) USB spec 9.6.6, page 269-271, Table 9-13 */
+ USB_DESC_ENDPOINT(MOUSE_ENDPOINT | 0x80, // bEndpointAddress
+ 0x03, // bmAttributes (Interrupt)
+ MOUSE_EPSIZE, // wMaxPacketSize
+ 1), // bInterval
+ #endif /* MOUSE_ENABLE */
+
+ #ifdef CONSOLE_ENABLE
+ /* Interface Descriptor (9 bytes) USB spec 9.6.5, page 267-269, Table 9-12 */
+ USB_DESC_INTERFACE(CONSOLE_INTERFACE, // bInterfaceNumber
+ 0, // bAlternateSetting
+ 1, // bNumEndpoints
+ 0x03, // bInterfaceClass: HID
+ 0x00, // bInterfaceSubClass: None
+ 0x00, // bInterfaceProtocol: None
+ 0), // iInterface
+
+ /* HID descriptor (9 bytes) HID 1.11 spec, section 6.2.1 */
+ USB_DESC_BYTE(9), // bLength
+ USB_DESC_BYTE(0x21), // bDescriptorType (HID class)
+ USB_DESC_BCD(0x0111), // bcdHID: HID version 1.11
+ USB_DESC_BYTE(0), // bCountryCode
+ USB_DESC_BYTE(1), // bNumDescriptors
+ USB_DESC_BYTE(0x22), // bDescriptorType (report desc)
+ USB_DESC_WORD(sizeof(console_hid_report_desc_data)), // wDescriptorLength
+
+ /* Endpoint Descriptor (7 bytes) USB spec 9.6.6, page 269-271, Table 9-13 */
+ USB_DESC_ENDPOINT(CONSOLE_ENDPOINT | 0x80, // bEndpointAddress
+ 0x03, // bmAttributes (Interrupt)
+ CONSOLE_EPSIZE, // wMaxPacketSize
+ 1), // bInterval
+ #endif /* CONSOLE_ENABLE */
+
+ #ifdef EXTRAKEY_ENABLE
+ /* Interface Descriptor (9 bytes) USB spec 9.6.5, page 267-269, Table 9-12 */
+ USB_DESC_INTERFACE(EXTRA_INTERFACE, // bInterfaceNumber
+ 0, // bAlternateSetting
+ 1, // bNumEndpoints
+ 0x03, // bInterfaceClass: HID
+ 0x00, // bInterfaceSubClass: None
+ 0x00, // bInterfaceProtocol: None
+ 0), // iInterface
+
+ /* HID descriptor (9 bytes) HID 1.11 spec, section 6.2.1 */
+ USB_DESC_BYTE(9), // bLength
+ USB_DESC_BYTE(0x21), // bDescriptorType (HID class)
+ USB_DESC_BCD(0x0111), // bcdHID: HID version 1.11
+ USB_DESC_BYTE(0), // bCountryCode
+ USB_DESC_BYTE(1), // bNumDescriptors
+ USB_DESC_BYTE(0x22), // bDescriptorType (report desc)
+ USB_DESC_WORD(sizeof(extra_hid_report_desc_data)), // wDescriptorLength
+
+ /* Endpoint Descriptor (7 bytes) USB spec 9.6.6, page 269-271, Table 9-13 */
+ USB_DESC_ENDPOINT(EXTRA_ENDPOINT | 0x80, // bEndpointAddress
+ 0x03, // bmAttributes (Interrupt)
+ EXTRA_EPSIZE, // wMaxPacketSize
+ 10), // bInterval
+ #endif /* EXTRAKEY_ENABLE */
+
+ #ifdef NKRO_ENABLE
+ /* Interface Descriptor (9 bytes) USB spec 9.6.5, page 267-269, Table 9-12 */
+ USB_DESC_INTERFACE(NKRO_INTERFACE, // bInterfaceNumber
+ 0, // bAlternateSetting
+ 1, // bNumEndpoints
+ 0x03, // bInterfaceClass: HID
+ 0x00, // bInterfaceSubClass: None
+ 0x00, // bInterfaceProtocol: None
+ 0), // iInterface
+
+ /* HID descriptor (9 bytes) HID 1.11 spec, section 6.2.1 */
+ USB_DESC_BYTE(9), // bLength
+ USB_DESC_BYTE(0x21), // bDescriptorType (HID class)
+ USB_DESC_BCD(0x0111), // bcdHID: HID version 1.11
+ USB_DESC_BYTE(0), // bCountryCode
+ USB_DESC_BYTE(1), // bNumDescriptors
+ USB_DESC_BYTE(0x22), // bDescriptorType (report desc)
+ USB_DESC_WORD(sizeof(nkro_hid_report_desc_data)), // wDescriptorLength
+
+ /* Endpoint Descriptor (7 bytes) USB spec 9.6.6, page 269-271, Table 9-13 */
+ USB_DESC_ENDPOINT(NKRO_ENDPOINT | 0x80, // bEndpointAddress
+ 0x03, // bmAttributes (Interrupt)
+ NKRO_EPSIZE, // wMaxPacketSize
+ 1), // bInterval
+ #endif /* NKRO_ENABLE */
+};
+
+/* Configuration Descriptor wrapper */
+static const USBDescriptor hid_configuration_descriptor = {
+ sizeof hid_configuration_descriptor_data,
+ hid_configuration_descriptor_data
+};
+
+/* wrappers */
+#define HID_DESCRIPTOR_SIZE 9
+static const USBDescriptor keyboard_hid_descriptor = {
+ HID_DESCRIPTOR_SIZE,
+ &hid_configuration_descriptor_data[KBD_HID_DESC_OFFSET]
+};
+#ifdef MOUSE_ENABLE
+static const USBDescriptor mouse_hid_descriptor = {
+ HID_DESCRIPTOR_SIZE,
+ &hid_configuration_descriptor_data[MOUSE_HID_DESC_OFFSET]
+};
+#endif /* MOUSE_ENABLE */
+#ifdef CONSOLE_ENABLE
+static const USBDescriptor console_hid_descriptor = {
+ HID_DESCRIPTOR_SIZE,
+ &hid_configuration_descriptor_data[CONSOLE_HID_DESC_OFFSET]
+};
+#endif /* CONSOLE_ENABLE */
+#ifdef EXTRAKEY_ENABLE
+static const USBDescriptor extra_hid_descriptor = {
+ HID_DESCRIPTOR_SIZE,
+ &hid_configuration_descriptor_data[EXTRA_HID_DESC_OFFSET]
+};
+#endif /* EXTRAKEY_ENABLE */
+#ifdef NKRO_ENABLE
+static const USBDescriptor nkro_hid_descriptor = {
+ HID_DESCRIPTOR_SIZE,
+ &hid_configuration_descriptor_data[NKRO_HID_DESC_OFFSET]
+};
+#endif /* NKRO_ENABLE */
+
+
+/* U.S. English language identifier */
+static const uint8_t usb_string_langid[] = {
+ USB_DESC_BYTE(4), // bLength
+ USB_DESC_BYTE(USB_DESCRIPTOR_STRING), // bDescriptorType
+ USB_DESC_WORD(0x0409) // wLANGID (U.S. English)
+};
+
+/* ugly ugly hack */
+#define PP_NARG(...) \
+ PP_NARG_(__VA_ARGS__,PP_RSEQ_N())
+#define PP_NARG_(...) \
+ PP_ARG_N(__VA_ARGS__)
+#define PP_ARG_N( \
+ _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
+ _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
+ _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
+ _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
+ _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
+ _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
+ _61,_62,_63,N,...) N
+#define PP_RSEQ_N() \
+ 63,62,61,60, \
+ 59,58,57,56,55,54,53,52,51,50, \
+ 49,48,47,46,45,44,43,42,41,40, \
+ 39,38,37,36,35,34,33,32,31,30, \
+ 29,28,27,26,25,24,23,22,21,20, \
+ 19,18,17,16,15,14,13,12,11,10, \
+ 9,8,7,6,5,4,3,2,1,0
+
+/* Vendor string = manufacturer */
+static const uint8_t usb_string_vendor[] = {
+ USB_DESC_BYTE(PP_NARG(USBSTR_MANUFACTURER)+2), // bLength
+ USB_DESC_BYTE(USB_DESCRIPTOR_STRING), // bDescriptorType
+ USBSTR_MANUFACTURER
+};
+
+/* Device Description string = product */
+static const uint8_t usb_string_description[] = {
+ USB_DESC_BYTE(PP_NARG(USBSTR_PRODUCT)+2), // bLength
+ USB_DESC_BYTE(USB_DESCRIPTOR_STRING), // bDescriptorType
+ USBSTR_PRODUCT
+};
+
+/* Serial Number string (will be filled by the function init_usb_serial_string) */
+static uint8_t usb_string_serial[] = {
+ USB_DESC_BYTE(22), // bLength
+ USB_DESC_BYTE(USB_DESCRIPTOR_STRING), // bDescriptorType
+ '0', 0, 'x', 0, 'D', 0, 'E', 0, 'A', 0, 'D', 0, 'B', 0, 'E', 0, 'E', 0, 'F', 0
+};
+
+/* Strings wrappers array */
+static const USBDescriptor usb_strings[] = {
+ { sizeof usb_string_langid, usb_string_langid }
+ ,
+ { sizeof usb_string_vendor, usb_string_vendor }
+ ,
+ { sizeof usb_string_description, usb_string_description }
+ ,
+ { sizeof usb_string_serial, usb_string_serial }
+};
+
+/*
+ * Handles the GET_DESCRIPTOR callback
+ *
+ * Returns the proper descriptor
+ */
+static const USBDescriptor *usb_get_descriptor_cb(USBDriver *usbp, uint8_t dtype, uint8_t dindex, uint16_t lang) {
+ (void)usbp;
+ (void)lang;
+ switch(dtype) {
+ /* Generic descriptors */
+ case USB_DESCRIPTOR_DEVICE: /* Device Descriptor */
+ return &usb_device_descriptor;
+
+ case USB_DESCRIPTOR_CONFIGURATION: /* Configuration Descriptor */
+ return &hid_configuration_descriptor;
+
+ case USB_DESCRIPTOR_STRING: /* Strings */
+ if(dindex < 4)
+ return &usb_strings[dindex];
+ break;
+
+ /* HID specific descriptors */
+ case USB_DESCRIPTOR_HID: /* HID Descriptors */
+ switch(lang) { /* yea, poor label, it's actually wIndex from the setup packet */
+ case KBD_INTERFACE:
+ return &keyboard_hid_descriptor;
+
+#ifdef MOUSE_ENABLE
+ case MOUSE_INTERFACE:
+ return &mouse_hid_descriptor;
+#endif /* MOUSE_ENABLE */
+#ifdef CONSOLE_ENABLE
+ case CONSOLE_INTERFACE:
+ return &console_hid_descriptor;
+#endif /* CONSOLE_ENABLE */
+#ifdef EXTRAKEY_ENABLE
+ case EXTRA_INTERFACE:
+ return &extra_hid_descriptor;
+#endif /* EXTRAKEY_ENABLE */
+#ifdef NKRO_ENABLE
+ case NKRO_INTERFACE:
+ return &nkro_hid_descriptor;
+#endif /* NKRO_ENABLE */
+ }
+
+ case USB_DESCRIPTOR_HID_REPORT: /* HID Report Descriptor */
+ switch(lang) {
+ case KBD_INTERFACE:
+ return &keyboard_hid_report_descriptor;
+
+#ifdef MOUSE_ENABLE
+ case MOUSE_INTERFACE:
+ return &mouse_hid_report_descriptor;
+#endif /* MOUSE_ENABLE */
+#ifdef CONSOLE_ENABLE
+ case CONSOLE_INTERFACE:
+ return &console_hid_report_descriptor;
+#endif /* CONSOLE_ENABLE */
+#ifdef EXTRAKEY_ENABLE
+ case EXTRA_INTERFACE:
+ return &extra_hid_report_descriptor;
+#endif /* EXTRAKEY_ENABLE */
+#ifdef NKRO_ENABLE
+ case NKRO_INTERFACE:
+ return &nkro_hid_report_descriptor;
+#endif /* NKRO_ENABLE */
+ }
+ }
+ return NULL;
+}
+
+/* keyboard endpoint state structure */
+static USBInEndpointState kbd_ep_state;
+/* keyboard endpoint initialization structure (IN) */
+static const USBEndpointConfig kbd_ep_config = {
+ USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
+ NULL, /* SETUP packet notification callback */
+ kbd_in_cb, /* IN notification callback */
+ NULL, /* OUT notification callback */
+ KBD_EPSIZE, /* IN maximum packet size */
+ 0, /* OUT maximum packet size */
+ &kbd_ep_state, /* IN Endpoint state */
+ NULL, /* OUT endpoint state */
+ 2, /* IN multiplier */
+ NULL /* SETUP buffer (not a SETUP endpoint) */
+};
+
+#ifdef MOUSE_ENABLE
+/* mouse endpoint state structure */
+static USBInEndpointState mouse_ep_state;
+
+/* mouse endpoint initialization structure (IN) */
+static const USBEndpointConfig mouse_ep_config = {
+ USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
+ NULL, /* SETUP packet notification callback */
+ mouse_in_cb, /* IN notification callback */
+ NULL, /* OUT notification callback */
+ MOUSE_EPSIZE, /* IN maximum packet size */
+ 0, /* OUT maximum packet size */
+ &mouse_ep_state, /* IN Endpoint state */
+ NULL, /* OUT endpoint state */
+ 2, /* IN multiplier */
+ NULL /* SETUP buffer (not a SETUP endpoint) */
+};
+#endif /* MOUSE_ENABLE */
+
+#ifdef CONSOLE_ENABLE
+/* console endpoint state structure */
+static USBInEndpointState console_ep_state;
+
+/* console endpoint initialization structure (IN) */
+static const USBEndpointConfig console_ep_config = {
+ USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
+ NULL, /* SETUP packet notification callback */
+ console_in_cb, /* IN notification callback */
+ NULL, /* OUT notification callback */
+ CONSOLE_EPSIZE, /* IN maximum packet size */
+ 0, /* OUT maximum packet size */
+ &console_ep_state, /* IN Endpoint state */
+ NULL, /* OUT endpoint state */
+ 2, /* IN multiplier */
+ NULL /* SETUP buffer (not a SETUP endpoint) */
+};
+#endif /* CONSOLE_ENABLE */
+
+#ifdef EXTRAKEY_ENABLE
+/* extrakey endpoint state structure */
+static USBInEndpointState extra_ep_state;
+
+/* extrakey endpoint initialization structure (IN) */
+static const USBEndpointConfig extra_ep_config = {
+ USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
+ NULL, /* SETUP packet notification callback */
+ extra_in_cb, /* IN notification callback */
+ NULL, /* OUT notification callback */
+ EXTRA_EPSIZE, /* IN maximum packet size */
+ 0, /* OUT maximum packet size */
+ &extra_ep_state, /* IN Endpoint state */
+ NULL, /* OUT endpoint state */
+ 2, /* IN multiplier */
+ NULL /* SETUP buffer (not a SETUP endpoint) */
+};
+#endif /* EXTRAKEY_ENABLE */
+
+#ifdef NKRO_ENABLE
+/* nkro endpoint state structure */
+static USBInEndpointState nkro_ep_state;
+
+/* nkro endpoint initialization structure (IN) */
+static const USBEndpointConfig nkro_ep_config = {
+ USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
+ NULL, /* SETUP packet notification callback */
+ nkro_in_cb, /* IN notification callback */
+ NULL, /* OUT notification callback */
+ NKRO_EPSIZE, /* IN maximum packet size */
+ 0, /* OUT maximum packet size */
+ &nkro_ep_state, /* IN Endpoint state */
+ NULL, /* OUT endpoint state */
+ 2, /* IN multiplier */
+ NULL /* SETUP buffer (not a SETUP endpoint) */
+};
+#endif /* NKRO_ENABLE */
+
+/* ---------------------------------------------------------
+ * USB driver functions
+ * ---------------------------------------------------------
+ */
+
+/* Handles the USB driver global events
+ * TODO: maybe disable some things when connection is lost? */
+static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
+ switch(event) {
+ case USB_EVENT_RESET:
+ //TODO: from ISR! print("[R]");
+ return;
+
+ case USB_EVENT_ADDRESS:
+ return;
+
+ case USB_EVENT_CONFIGURED:
+ osalSysLockFromISR();
+ /* Enable the endpoints specified into the configuration. */
+ usbInitEndpointI(usbp, KBD_ENDPOINT, &kbd_ep_config);
+#ifdef MOUSE_ENABLE
+ usbInitEndpointI(usbp, MOUSE_ENDPOINT, &mouse_ep_config);
+#endif /* MOUSE_ENABLE */
+#ifdef CONSOLE_ENABLE
+ usbInitEndpointI(usbp, CONSOLE_ENDPOINT, &console_ep_config);
+ /* don't need to start the flush timer, it starts from console_in_cb automatically */
+#endif /* CONSOLE_ENABLE */
+#ifdef EXTRAKEY_ENABLE
+ usbInitEndpointI(usbp, EXTRA_ENDPOINT, &extra_ep_config);
+#endif /* EXTRAKEY_ENABLE */
+#ifdef NKRO_ENABLE
+ usbInitEndpointI(usbp, NKRO_ENDPOINT, &nkro_ep_config);
+#endif /* NKRO_ENABLE */
+ osalSysUnlockFromISR();
+ return;
+
+ case USB_EVENT_SUSPEND:
+ //TODO: from ISR! print("[S]");
+#ifdef SLEEP_LED_ENABLE
+ sleep_led_enable();
+#endif /* SLEEP_LED_ENABLE */
+ return;
+
+ case USB_EVENT_WAKEUP:
+ //TODO: from ISR! print("[W]");
+ suspend_wakeup_init();
+#ifdef SLEEP_LED_ENABLE
+ sleep_led_disable();
+ // NOTE: converters may not accept this
+ led_set(host_keyboard_leds());
+#endif /* SLEEP_LED_ENABLE */
+ return;
+
+ case USB_EVENT_STALLED:
+ return;
+ }
+}
+
+/* Function used locally in os/hal/src/usb.c for getting descriptors
+ * need it here for HID descriptor */
+static uint16_t get_hword(uint8_t *p) {
+ uint16_t hw;
+
+ hw = (uint16_t)*p++;
+ hw |= (uint16_t)*p << 8U;
+ return hw;
+}
+
+/*
+ * Appendix G: HID Request Support Requirements
+ *
+ * The following table enumerates the requests that need to be supported by various types of HID class devices.
+ * Device type GetReport SetReport GetIdle SetIdle GetProtocol SetProtocol
+ * ------------------------------------------------------------------------------------------
+ * Boot Mouse Required Optional Optional Optional Required Required
+ * Non-Boot Mouse Required Optional Optional Optional Optional Optional
+ * Boot Keyboard Required Optional Required Required Required Required
+ * Non-Boot Keybrd Required Optional Required Required Optional Optional
+ * Other Device Required Optional Optional Optional Optional Optional
+ */
+
+/* Callback for SETUP request on the endpoint 0 (control) */
+static bool usb_request_hook_cb(USBDriver *usbp) {
+ const USBDescriptor *dp;
+
+ /* usbp->setup fields:
+ * 0: bmRequestType (bitmask)
+ * 1: bRequest
+ * 2,3: (LSB,MSB) wValue
+ * 4,5: (LSB,MSB) wIndex
+ * 6,7: (LSB,MSB) wLength (number of bytes to transfer if there is a data phase) */
+
+ /* Handle HID class specific requests */
+ if(((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) &&
+ ((usbp->setup[0] & USB_RTYPE_RECIPIENT_MASK) == USB_RTYPE_RECIPIENT_INTERFACE)) {
+ switch(usbp->setup[0] & USB_RTYPE_DIR_MASK) {
+ case USB_RTYPE_DIR_DEV2HOST:
+ switch(usbp->setup[1]) { /* bRequest */
+ case HID_GET_REPORT:
+ switch(usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */
+ case KBD_INTERFACE:
+#ifdef NKRO_ENABLE
+ case NKRO_INTERFACE:
+#endif /* NKRO_ENABLE */
+ usbSetupTransfer(usbp, (uint8_t *)&keyboard_report_sent, sizeof(keyboard_report_sent), NULL);
+ return TRUE;
+ break;
+
+#ifdef MOUSE_ENABLE
+ case MOUSE_INTERFACE:
+ usbSetupTransfer(usbp, (uint8_t *)&mouse_report_blank, sizeof(mouse_report_blank), NULL);
+ return TRUE;
+ break;
+#endif /* MOUSE_ENABLE */
+
+#ifdef CONSOLE_ENABLE
+ case CONSOLE_INTERFACE:
+ usbSetupTransfer(usbp, console_queue_buffer, CONSOLE_EPSIZE, NULL);
+ return TRUE;
+ break;
+#endif /* CONSOLE_ENABLE */
+
+#ifdef EXTRAKEY_ENABLE
+ case EXTRA_INTERFACE:
+ if(usbp->setup[3] == 1) { /* MSB(wValue) [Report Type] == 1 [Input Report] */
+ switch(usbp->setup[2]) { /* LSB(wValue) [Report ID] */
+ case REPORT_ID_SYSTEM:
+ extra_report_blank[0] = REPORT_ID_SYSTEM;
+ usbSetupTransfer(usbp, (uint8_t *)extra_report_blank, sizeof(extra_report_blank), NULL);
+ return TRUE;
+ break;
+ case REPORT_ID_CONSUMER:
+ extra_report_blank[0] = REPORT_ID_CONSUMER;
+ usbSetupTransfer(usbp, (uint8_t *)extra_report_blank, sizeof(extra_report_blank), NULL);
+ return TRUE;
+ break;
+ default:
+ return FALSE;
+ }
+ } else {
+ return FALSE;
+ }
+ break;
+#endif /* EXTRAKEY_ENABLE */
+
+ default:
+ usbSetupTransfer(usbp, NULL, 0, NULL);
+ return TRUE;
+ break;
+ }
+ break;
+
+ case HID_GET_PROTOCOL:
+ if((usbp->setup[4] == KBD_INTERFACE) && (usbp->setup[5] == 0)) { /* wIndex */
+ usbSetupTransfer(usbp, &keyboard_protocol, 1, NULL);
+ return TRUE;
+ }
+ break;
+
+ case HID_GET_IDLE:
+ usbSetupTransfer(usbp, &keyboard_idle, 1, NULL);
+ return TRUE;
+ break;
+ }
+ break;
+
+ case USB_RTYPE_DIR_HOST2DEV:
+ switch(usbp->setup[1]) { /* bRequest */
+ case HID_SET_REPORT:
+ switch(usbp->setup[4]) { /* LSB(wIndex) (check MSB==0 and wLength==1?) */
+ case KBD_INTERFACE:
+#ifdef NKRO_ENABLE
+ case NKRO_INTERFACE:
+#endif /* NKRO_ENABLE */
+ /* keyboard_led_stats = <read byte from next OUT report>
+ * keyboard_led_stats needs be word (or dword), otherwise we get an exception on F0 */
+ usbSetupTransfer(usbp, (uint8_t *)&keyboard_led_stats, 1, NULL);
+ return TRUE;
+ break;
+ }
+ break;
+
+ case HID_SET_PROTOCOL:
+ if((usbp->setup[4] == KBD_INTERFACE) && (usbp->setup[5] == 0)) { /* wIndex */
+ keyboard_protocol = ((usbp->setup[2]) != 0x00); /* LSB(wValue) */
+#ifdef NKRO_ENABLE
+ keyboard_nkro = !!keyboard_protocol;
+ if(!keyboard_nkro && keyboard_idle) {
+#else /* NKRO_ENABLE */
+ if(keyboard_idle) {
+#endif /* NKRO_ENABLE */
+ /* arm the idle timer if boot protocol & idle */
+ osalSysLockFromISR();
+ chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
+ osalSysUnlockFromISR();
+ }
+ }
+ usbSetupTransfer(usbp, NULL, 0, NULL);
+ return TRUE;
+ break;
+
+ case HID_SET_IDLE:
+ keyboard_idle = usbp->setup[3]; /* MSB(wValue) */
+ /* arm the timer */
+#ifdef NKRO_ENABLE
+ if(!keyboard_nkro && keyboard_idle) {
+#else /* NKRO_ENABLE */
+ if(keyboard_idle) {
+#endif /* NKRO_ENABLE */
+ osalSysLockFromISR();
+ chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
+ osalSysUnlockFromISR();
+ }
+ usbSetupTransfer(usbp, NULL, 0, NULL);
+ return TRUE;
+ break;
+ }
+ break;
+ }
+ }
+
+ /* Handle the Get_Descriptor Request for HID class (not handled by the default hook) */
+ if((usbp->setup[0] == 0x81) && (usbp->setup[1] == USB_REQ_GET_DESCRIPTOR)) {
+ dp = usbp->config->get_descriptor_cb(usbp, usbp->setup[3], usbp->setup[2], get_hword(&usbp->setup[4]));
+ if(dp == NULL)
+ return FALSE;
+ usbSetupTransfer(usbp, (uint8_t *)dp->ud_string, dp->ud_size, NULL);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/* Start-of-frame callback */
+static void usb_sof_cb(USBDriver *usbp) {
+ kbd_sof_cb(usbp);
+}
+
+
+/* USB driver configuration */
+static const USBConfig usbcfg = {
+ usb_event_cb, /* USB events callback */
+ usb_get_descriptor_cb, /* Device GET_DESCRIPTOR request callback */
+ usb_request_hook_cb, /* Requests hook callback */
+ usb_sof_cb /* Start Of Frame callback */
+};
+
+/*
+ * Initialize the USB driver
+ */
+void init_usb_driver(USBDriver *usbp) {
+ /*
+ * Activates the USB driver and then the USB bus pull-up on D+.
+ * Note, a delay is inserted in order to not have to disconnect the cable
+ * after a reset.
+ */
+ usbDisconnectBus(usbp);
+ chThdSleepMilliseconds(1500);
+ usbStart(usbp, &usbcfg);
+ usbConnectBus(usbp);
+
+ chVTObjectInit(&keyboard_idle_timer);
+#ifdef CONSOLE_ENABLE
+ obqObjectInit(&console_buf_queue, console_queue_buffer, CONSOLE_EPSIZE, CONSOLE_QUEUE_CAPACITY, console_queue_onotify, (void*)usbp);
+ chVTObjectInit(&console_flush_timer);
+#endif
+}
+
+/*
+ * Send remote wakeup packet
+ * Note: should not be called from ISR
+ */
+void send_remote_wakeup(USBDriver *usbp) {
+ (void)usbp;
+#if defined(K20x) || defined(KL2x)
+#if KINETIS_USB_USE_USB0
+ USB0->CTL |= USBx_CTL_RESUME;
+ chThdSleepMilliseconds(15);
+ USB0->CTL &= ~USBx_CTL_RESUME;
+#endif /* KINETIS_USB_USE_USB0 */
+#elif defined(STM32F0XX) || defined(STM32F1XX) /* K20x || KL2x */
+ STM32_USB->CNTR |= CNTR_RESUME;
+ chThdSleepMilliseconds(15);
+ STM32_USB->CNTR &= ~CNTR_RESUME;
+#else /* STM32F0XX || STM32F1XX */
+#warning Sending remote wakeup packet not implemented for your platform.
+#endif /* K20x || KL2x */
+}
+
+/* ---------------------------------------------------------
+ * Keyboard functions
+ * ---------------------------------------------------------
+ */
+
+/* keyboard IN callback hander (a kbd report has made it IN) */
+void kbd_in_cb(USBDriver *usbp, usbep_t ep) {
+ /* STUB */
+ (void)usbp;
+ (void)ep;
+}
+
+#ifdef NKRO_ENABLE
+/* nkro IN callback hander (a nkro report has made it IN) */
+void nkro_in_cb(USBDriver *usbp, usbep_t ep) {
+ /* STUB */
+ (void)usbp;
+ (void)ep;
+}
+#endif /* NKRO_ENABLE */
+
+/* start-of-frame handler
+ * TODO: i guess it would be better to re-implement using timers,
+ * so that this is not going to have to be checked every 1ms */
+void kbd_sof_cb(USBDriver *usbp) {
+ (void)usbp;
+}
+
+/* Idle requests timer code
+ * callback (called from ISR, unlocked state) */
+static void keyboard_idle_timer_cb(void *arg) {
+ USBDriver *usbp = (USBDriver *)arg;
+
+ osalSysLockFromISR();
+
+ /* check that the states of things are as they're supposed to */
+ if(usbGetDriverStateI(usbp) != USB_ACTIVE) {
+ /* do not rearm the timer, should be enabled on IDLE request */
+ osalSysUnlockFromISR();
+ return;
+ }
+
+#ifdef NKRO_ENABLE
+ if(!keyboard_nkro && keyboard_idle) {
+#else /* NKRO_ENABLE */
+ if(keyboard_idle) {
+#endif /* NKRO_ENABLE */
+ /* TODO: are we sure we want the KBD_ENDPOINT? */
+ if(!usbGetTransmitStatusI(usbp, KBD_ENDPOINT)) {
+ usbStartTransmitI(usbp, KBD_ENDPOINT, (uint8_t *)&keyboard_report_sent, KBD_EPSIZE);
+ }
+ /* rearm the timer */
+ chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
+ }
+
+ /* do not rearm the timer if the condition above fails
+ * it should be enabled again on either IDLE or SET_PROTOCOL requests */
+ osalSysUnlockFromISR();
+}
+
+/* LED status */
+uint8_t keyboard_leds(void) {
+ return (uint8_t)(keyboard_led_stats & 0xFF);
+}
+
+/* prepare and start sending a report IN
+ * not callable from ISR or locked state */
+void send_keyboard(report_keyboard_t *report) {
+ osalSysLock();
+ if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
+ osalSysUnlock();
+ return;
+ }
+ osalSysUnlock();
+
+#ifdef NKRO_ENABLE
+ if(keyboard_nkro) { /* NKRO protocol */
+ /* need to wait until the previous packet has made it through */
+ /* can rewrite this using the synchronous API, then would wait
+ * until *after* the packet has been transmitted. I think
+ * this is more efficient */
+ /* busy wait, should be short and not very common */
+ osalSysLock();
+ if(usbGetTransmitStatusI(&USB_DRIVER, NKRO_ENDPOINT)) {
+ /* Need to either suspend, or loop and call unlock/lock during
+ * every iteration - otherwise the system will remain locked,
+ * no interrupts served, so USB not going through as well.
+ * Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */
+ osalThreadSuspendS(&(&USB_DRIVER)->epc[NKRO_ENDPOINT]->in_state->thread);
+ }
+ usbStartTransmitI(&USB_DRIVER, NKRO_ENDPOINT, (uint8_t *)report, sizeof(report_keyboard_t));
+ osalSysUnlock();
+ } else
+#endif /* NKRO_ENABLE */
+ { /* boot protocol */
+ /* need to wait until the previous packet has made it through */
+ /* busy wait, should be short and not very common */
+ osalSysLock();
+ if(usbGetTransmitStatusI(&USB_DRIVER, KBD_ENDPOINT)) {
+ /* Need to either suspend, or loop and call unlock/lock during
+ * every iteration - otherwise the system will remain locked,
+ * no interrupts served, so USB not going through as well.
+ * Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */
+ osalThreadSuspendS(&(&USB_DRIVER)->epc[KBD_ENDPOINT]->in_state->thread);
+ }
+ usbStartTransmitI(&USB_DRIVER, KBD_ENDPOINT, (uint8_t *)report, KBD_EPSIZE);
+ osalSysUnlock();
+ }
+ keyboard_report_sent = *report;
+}
+
+/* ---------------------------------------------------------
+ * Mouse functions
+ * ---------------------------------------------------------
+ */
+
+#ifdef MOUSE_ENABLE
+
+/* mouse IN callback hander (a mouse report has made it IN) */
+void mouse_in_cb(USBDriver *usbp, usbep_t ep) {
+ (void)usbp;
+ (void)ep;
+}
+
+void send_mouse(report_mouse_t *report) {
+ osalSysLock();
+ if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
+ osalSysUnlock();
+ return;
+ }
+ osalSysUnlock();
+
+ /* TODO: LUFA manually waits for the endpoint to become ready
+ * for about 10ms for mouse, kbd, system; 1ms for nkro
+ * is this really needed?
+ */
+
+ osalSysLock();
+ usbStartTransmitI(&USB_DRIVER, MOUSE_ENDPOINT, (uint8_t *)report, sizeof(report_mouse_t));
+ osalSysUnlock();
+}
+
+#else /* MOUSE_ENABLE */
+void send_mouse(report_mouse_t *report) {
+ (void)report;
+}
+#endif /* MOUSE_ENABLE */
+
+/* ---------------------------------------------------------
+ * Extrakey functions
+ * ---------------------------------------------------------
+ */
+
+#ifdef EXTRAKEY_ENABLE
+
+/* extrakey IN callback hander */
+void extra_in_cb(USBDriver *usbp, usbep_t ep) {
+ /* STUB */
+ (void)usbp;
+ (void)ep;
+}
+
+static void send_extra_report(uint8_t report_id, uint16_t data) {
+ osalSysLock();
+ if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
+ osalSysUnlock();
+ return;
+ }
+
+ report_extra_t report = {
+ .report_id = report_id,
+ .usage = data
+ };
+
+ usbStartTransmitI(&USB_DRIVER, EXTRA_ENDPOINT, (uint8_t *)&report, sizeof(report_extra_t));
+ osalSysUnlock();
+}
+
+void send_system(uint16_t data) {
+ send_extra_report(REPORT_ID_SYSTEM, data);
+}
+
+void send_consumer(uint16_t data) {
+ send_extra_report(REPORT_ID_CONSUMER, data);
+}
+
+#else /* EXTRAKEY_ENABLE */
+void send_system(uint16_t data) {
+ (void)data;
+}
+void send_consumer(uint16_t data) {
+ (void)data;
+}
+#endif /* EXTRAKEY_ENABLE */
+
+/* ---------------------------------------------------------
+ * Console functions
+ * ---------------------------------------------------------
+ */
+
+#ifdef CONSOLE_ENABLE
+
+/* console IN callback hander */
+void console_in_cb(USBDriver *usbp, usbep_t ep) {
+ (void)ep; /* should have ep == CONSOLE_ENDPOINT, so use that to save time/space */
+ uint8_t *buf;
+ size_t n;
+
+ osalSysLockFromISR();
+
+ /* rearm the timer */
+ chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
+
+ /* Freeing the buffer just transmitted, if it was not a zero size packet.*/
+ if (usbp->epc[CONSOLE_ENDPOINT]->in_state->txsize > 0U) {
+ obqReleaseEmptyBufferI(&console_buf_queue);
+ }
+
+ /* Checking if there is a buffer ready for transmission.*/
+ buf = obqGetFullBufferI(&console_buf_queue, &n);
+
+ if (buf != NULL) {
+ /* The endpoint cannot be busy, we are in the context of the callback,
+ so it is safe to transmit without a check.*/
+ /* Should have n == CONSOLE_EPSIZE; check it? */
+ usbStartTransmitI(usbp, CONSOLE_ENDPOINT, buf, CONSOLE_EPSIZE);
+ } else {
+ /* Nothing to transmit.*/
+ }
+
+ osalSysUnlockFromISR();
+}
+
+/* Callback when data is inserted into the output queue
+ * Called from a locked state */
+void console_queue_onotify(io_buffers_queue_t *bqp) {
+ size_t n;
+ USBDriver *usbp = bqGetLinkX(bqp);
+
+ if(usbGetDriverStateI(usbp) != USB_ACTIVE)
+ return;
+
+ /* Checking if there is already a transaction ongoing on the endpoint.*/
+ if (!usbGetTransmitStatusI(usbp, CONSOLE_ENDPOINT)) {
+ /* Trying to get a full buffer.*/
+ uint8_t *buf = obqGetFullBufferI(&console_buf_queue, &n);
+ if (buf != NULL) {
+ /* Buffer found, starting a new transaction.*/
+ /* Should have n == CONSOLE_EPSIZE; check this? */
+ usbStartTransmitI(usbp, CONSOLE_ENDPOINT, buf, CONSOLE_EPSIZE);
+ }
+ }
+}
+
+/* Flush timer code
+ * callback (called from ISR, unlocked state) */
+static void console_flush_cb(void *arg) {
+ USBDriver *usbp = (USBDriver *)arg;
+ osalSysLockFromISR();
+
+ /* check that the states of things are as they're supposed to */
+ if(usbGetDriverStateI(usbp) != USB_ACTIVE) {
+ /* rearm the timer */
+ chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
+ osalSysUnlockFromISR();
+ return;
+ }
+
+ /* If there is already a transaction ongoing then another one cannot be
+ started.*/
+ if (usbGetTransmitStatusI(usbp, CONSOLE_ENDPOINT)) {
+ /* rearm the timer */
+ chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
+ osalSysUnlockFromISR();
+ return;
+ }
+
+ /* Checking if there only a buffer partially filled, if so then it is
+ enforced in the queue and transmitted.*/
+ if(obqTryFlushI(&console_buf_queue)) {
+ size_t n,i;
+ uint8_t *buf = obqGetFullBufferI(&console_buf_queue, &n);
+
+ osalDbgAssert(buf != NULL, "queue is empty");
+
+ /* zero the rest of the buffer (buf should point to allocated space) */
+ for(i=n; i<CONSOLE_EPSIZE; i++)
+ buf[i]=0;
+ usbStartTransmitI(usbp, CONSOLE_ENDPOINT, buf, CONSOLE_EPSIZE);
+ }
+
+ /* rearm the timer */
+ chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
+ osalSysUnlockFromISR();
+}
+
+
+int8_t sendchar(uint8_t c) {
+ osalSysLock();
+ if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
+ osalSysUnlock();
+ return 0;
+ }
+ osalSysUnlock();
+ /* Timeout after 100us if the queue is full.
+ * Increase this timeout if too much stuff is getting
+ * dropped (i.e. the buffer is getting full too fast
+ * for USB/HIDRAW to dequeue). Another possibility
+ * for fixing this kind of thing is to increase
+ * CONSOLE_QUEUE_CAPACITY. */
+ return(obqPutTimeout(&console_buf_queue, c, US2ST(100)));
+}
+
+#else /* CONSOLE_ENABLE */
+int8_t sendchar(uint8_t c) {
+ (void)c;
+ return 0;
+}
+#endif /* CONSOLE_ENABLE */
+
+void sendchar_pf(void *p, char c) {
+ (void)p;
+ sendchar((uint8_t)c);
+}
diff --git a/tmk_core/protocol/chibios/usb_main.h b/tmk_core/protocol/chibios/usb_main.h
new file mode 100644
index 000000000..30d8fcaef
--- /dev/null
+++ b/tmk_core/protocol/chibios/usb_main.h
@@ -0,0 +1,139 @@
+/*
+ * (c) 2015 flabberast <s3+flabbergast@sdfeu.org>
+ *
+ * Based on the following work:
+ * - Guillaume Duc's raw hid example (MIT License)
+ * https://github.com/guiduc/usb-hid-chibios-example
+ * - PJRC Teensy examples (MIT License)
+ * https://www.pjrc.com/teensy/usb_keyboard.html
+ * - hasu's TMK keyboard code (GPL v2 and some code Modified BSD)
+ * https://github.com/tmk/tmk_keyboard/
+ * - ChibiOS demo code (Apache 2.0 License)
+ * http://www.chibios.org
+ *
+ * Since some GPL'd code is used, this work is licensed under
+ * GPL v2 or later.
+ */
+
+
+#ifndef _USB_MAIN_H_
+#define _USB_MAIN_H_
+
+// TESTING
+// extern uint8_t blinkLed;
+
+#include "ch.h"
+#include "hal.h"
+
+/* -------------------------
+ * General USB driver header
+ * -------------------------
+ */
+
+/* The USB driver to use */
+#define USB_DRIVER USBD1
+
+/* Initialize the USB driver and bus */
+void init_usb_driver(USBDriver *usbp);
+
+/* Send remote wakeup packet */
+void send_remote_wakeup(USBDriver *usbp);
+
+/* ---------------
+ * Keyboard header
+ * ---------------
+ */
+
+/* main keyboard (6kro) */
+#define KBD_INTERFACE 0
+#define KBD_ENDPOINT 1
+#define KBD_EPSIZE 8
+#define KBD_REPORT_KEYS (KBD_EPSIZE - 2)
+
+/* secondary keyboard */
+#ifdef NKRO_ENABLE
+#define NKRO_INTERFACE 4
+#define NKRO_ENDPOINT 5
+#define NKRO_EPSIZE 16
+#define NKRO_REPORT_KEYS (NKRO_EPSIZE - 1)
+#endif
+
+/* extern report_keyboard_t keyboard_report_sent; */
+
+/* keyboard IN request callback handler */
+void kbd_in_cb(USBDriver *usbp, usbep_t ep);
+
+/* start-of-frame handler */
+void kbd_sof_cb(USBDriver *usbp);
+
+#ifdef NKRO_ENABLE
+/* nkro IN callback hander */
+void nkro_in_cb(USBDriver *usbp, usbep_t ep);
+#endif /* NKRO_ENABLE */
+
+/* ------------
+ * Mouse header
+ * ------------
+ */
+
+#ifdef MOUSE_ENABLE
+
+#define MOUSE_INTERFACE 1
+#define MOUSE_ENDPOINT 2
+#define MOUSE_EPSIZE 8
+
+/* mouse IN request callback handler */
+void mouse_in_cb(USBDriver *usbp, usbep_t ep);
+#endif /* MOUSE_ENABLE */
+
+/* ---------------
+ * Extrakey header
+ * ---------------
+ */
+
+#ifdef EXTRAKEY_ENABLE
+
+#define EXTRA_INTERFACE 3
+#define EXTRA_ENDPOINT 4
+#define EXTRA_EPSIZE 8
+
+/* extrakey IN request callback handler */
+void extra_in_cb(USBDriver *usbp, usbep_t ep);
+
+/* extra report structure */
+typedef struct {
+ uint8_t report_id;
+ uint16_t usage;
+} __attribute__ ((packed)) report_extra_t;
+#endif /* EXTRAKEY_ENABLE */
+
+/* --------------
+ * Console header
+ * --------------
+ */
+
+#ifdef CONSOLE_ENABLE
+
+#define CONSOLE_INTERFACE 2
+#define CONSOLE_ENDPOINT 3
+#define CONSOLE_EPSIZE 16
+
+/* Number of IN reports that can be stored inside the output queue */
+#define CONSOLE_QUEUE_CAPACITY 4
+
+/* Console flush time */
+#define CONSOLE_FLUSH_MS 50
+
+/* Putchar over the USB console */
+int8_t sendchar(uint8_t c);
+
+/* Flush output (send everything immediately) */
+void console_flush_output(void);
+
+/* console IN request callback handler */
+void console_in_cb(USBDriver *usbp, usbep_t ep);
+#endif /* CONSOLE_ENABLE */
+
+void sendchar_pf(void *p, char c);
+
+#endif /* _USB_MAIN_H_ */
diff --git a/tmk_core/protocol/ibm4704.c b/tmk_core/protocol/ibm4704.c
new file mode 100644
index 000000000..6a03cd441
--- /dev/null
+++ b/tmk_core/protocol/ibm4704.c
@@ -0,0 +1,189 @@
+/*
+Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com>
+*/
+#include <stdbool.h>
+#include <util/delay.h>
+#include "debug.h"
+#include "ring_buffer.h"
+#include "ibm4704.h"
+
+
+#define WAIT(stat, us, err) do { \
+ if (!wait_##stat(us)) { \
+ ibm4704_error = err; \
+ goto ERROR; \
+ } \
+} while (0)
+
+
+uint8_t ibm4704_error = 0;
+
+
+void ibm4704_init(void)
+{
+ inhibit(); // keep keyboard from sending
+ IBM4704_INT_INIT();
+ IBM4704_INT_ON();
+ idle(); // allow keyboard sending
+}
+
+/*
+Host to Keyboard
+----------------
+Data bits are LSB first and Parity is odd. Clock has around 60us high and 30us low part.
+
+ ____ __ __ __ __ __ __ __ __ __ ________
+Clock \______/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
+ ^ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ___
+Data ____|__/ X____X____X____X____X____X____X____X____X____X \___
+ | Start 0 1 2 3 4 5 6 7 P Stop
+ Request by host
+
+Start bit: can be long as 300-350us.
+Request: Host pulls Clock line down to request to send a command.
+Timing: After Request keyboard pull up Data and down Clock line to low for start bit.
+ After request host release Clock line once Data line becomes hi.
+ Host writes a bit while Clock is hi and Keyboard reads while low.
+Stop bit: Host releases or pulls up Data line to hi after 9th clock and waits for keyboard pull down the line to lo.
+*/
+uint8_t ibm4704_send(uint8_t data)
+{
+ bool parity = true; // odd parity
+ ibm4704_error = 0;
+
+ IBM4704_INT_OFF();
+
+ /* Request to send */
+ idle();
+ clock_lo();
+
+ /* wait for Start bit(Clock:lo/Data:hi) */
+ WAIT(data_hi, 300, 0x30);
+
+ /* Data bit */
+ for (uint8_t i = 0; i < 8; i++) {
+ WAIT(clock_hi, 100, 0x40+i);
+ if (data&(1<<i)) {
+ parity = !parity;
+ data_hi();
+ } else {
+ data_lo();
+ }
+ WAIT(clock_lo, 100, 0x48+i);
+ }
+
+ /* Parity bit */
+ WAIT(clock_hi, 100, 0x34);
+ if (parity) { data_hi(); } else { data_lo(); }
+ WAIT(clock_lo, 100, 0x35);
+
+ /* Stop bit */
+ WAIT(clock_hi, 100, 0x34);
+ data_hi();
+
+ /* End */
+ WAIT(data_lo, 100, 0x36);
+
+ idle();
+ IBM4704_INT_ON();
+ return 0;
+ERROR:
+ idle();
+ if (ibm4704_error > 0x30) {
+ xprintf("S:%02X ", ibm4704_error);
+ }
+ IBM4704_INT_ON();
+ return -1;
+}
+
+/* wait forever to receive data */
+uint8_t ibm4704_recv_response(void)
+{
+ while (!rbuf_has_data()) {
+ _delay_ms(1);
+ }
+ return rbuf_dequeue();
+}
+
+uint8_t ibm4704_recv(void)
+{
+ if (rbuf_has_data()) {
+ return rbuf_dequeue();
+ } else {
+ return -1;
+ }
+}
+
+/*
+Keyboard to Host
+----------------
+Data bits are LSB first and Parity is odd. Clock has around 60us high and 30us low part.
+
+ ____ __ __ __ __ __ __ __ __ __ _______
+Clock \_____/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
+ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____
+Data ____/ X____X____X____X____X____X____X____X____X____X________
+ Start 0 1 2 3 4 5 6 7 P Stop
+
+Start bit: can be long as 300-350us.
+Inhibit: Pull Data line down to inhibit keyboard to send.
+Timing: Host reads bit while Clock is hi.(rising edge)
+Stop bit: Keyboard pulls down Data line to lo after 9th clock.
+*/
+ISR(IBM4704_INT_VECT)
+{
+ static enum {
+ BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7, PARITY, STOP
+ } state = BIT0;
+ // LSB first
+ static uint8_t data = 0;
+ // Odd parity
+ static uint8_t parity = false;
+
+ ibm4704_error = 0;
+
+ switch (state) {
+ case BIT0:
+ case BIT1:
+ case BIT2:
+ case BIT3:
+ case BIT4:
+ case BIT5:
+ case BIT6:
+ case BIT7:
+ data >>= 1;
+ if (data_in()) {
+ data |= 0x80;
+ parity = !parity;
+ }
+ break;
+ case PARITY:
+ if (data_in()) {
+ parity = !parity;
+ }
+ if (!parity)
+ goto ERROR;
+ break;
+ case STOP:
+ // Data:Low
+ WAIT(data_lo, 100, state);
+ rbuf_enqueue(data);
+ ibm4704_error = IBM4704_ERR_NONE;
+ goto DONE;
+ break;
+ default:
+ goto ERROR;
+ }
+ state++;
+ goto RETURN;
+ERROR:
+ ibm4704_error = state;
+ while (ibm4704_send(0xFE)) _delay_ms(1); // resend
+ xprintf("R:%02X%02X\n", state, data);
+DONE:
+ state = BIT0;
+ data = 0;
+ parity = false;
+RETURN:
+ return;
+}
diff --git a/tmk_core/protocol/ibm4704.h b/tmk_core/protocol/ibm4704.h
new file mode 100644
index 000000000..618cce6be
--- /dev/null
+++ b/tmk_core/protocol/ibm4704.h
@@ -0,0 +1,110 @@
+/*
+Copyright 2014 Jun WAKO <wakojun@gmail.com>
+*/
+#ifndef IBM4704_H
+#define IBM4704_H
+
+#define IBM4704_ERR_NONE 0
+#define IBM4704_ERR_PARITY 0x70
+
+
+void ibm4704_init(void);
+uint8_t ibm4704_send(uint8_t data);
+uint8_t ibm4704_recv_response(void);
+uint8_t ibm4704_recv(void);
+
+
+/* Check pin configuration */
+#if !(defined(IBM4704_CLOCK_PORT) && \
+ defined(IBM4704_CLOCK_PIN) && \
+ defined(IBM4704_CLOCK_DDR) && \
+ defined(IBM4704_CLOCK_BIT))
+# error "ibm4704 clock pin configuration is required in config.h"
+#endif
+
+#if !(defined(IBM4704_DATA_PORT) && \
+ defined(IBM4704_DATA_PIN) && \
+ defined(IBM4704_DATA_DDR) && \
+ defined(IBM4704_DATA_BIT))
+# error "ibm4704 data pin configuration is required in config.h"
+#endif
+
+
+/*--------------------------------------------------------------------
+ * static functions
+ *------------------------------------------------------------------*/
+static inline void clock_lo(void)
+{
+ IBM4704_CLOCK_PORT &= ~(1<<IBM4704_CLOCK_BIT);
+ IBM4704_CLOCK_DDR |= (1<<IBM4704_CLOCK_BIT);
+}
+static inline void clock_hi(void)
+{
+ /* input with pull up */
+ IBM4704_CLOCK_DDR &= ~(1<<IBM4704_CLOCK_BIT);
+ IBM4704_CLOCK_PORT |= (1<<IBM4704_CLOCK_BIT);
+}
+static inline bool clock_in(void)
+{
+ IBM4704_CLOCK_DDR &= ~(1<<IBM4704_CLOCK_BIT);
+ IBM4704_CLOCK_PORT |= (1<<IBM4704_CLOCK_BIT);
+ _delay_us(1);
+ return IBM4704_CLOCK_PIN&(1<<IBM4704_CLOCK_BIT);
+}
+static inline void data_lo(void)
+{
+ IBM4704_DATA_PORT &= ~(1<<IBM4704_DATA_BIT);
+ IBM4704_DATA_DDR |= (1<<IBM4704_DATA_BIT);
+}
+static inline void data_hi(void)
+{
+ /* input with pull up */
+ IBM4704_DATA_DDR &= ~(1<<IBM4704_DATA_BIT);
+ IBM4704_DATA_PORT |= (1<<IBM4704_DATA_BIT);
+}
+static inline bool data_in(void)
+{
+ IBM4704_DATA_DDR &= ~(1<<IBM4704_DATA_BIT);
+ IBM4704_DATA_PORT |= (1<<IBM4704_DATA_BIT);
+ _delay_us(1);
+ return IBM4704_DATA_PIN&(1<<IBM4704_DATA_BIT);
+}
+
+static inline uint16_t wait_clock_lo(uint16_t us)
+{
+ while (clock_in() && us) { asm(""); _delay_us(1); us--; }
+ return us;
+}
+static inline uint16_t wait_clock_hi(uint16_t us)
+{
+ while (!clock_in() && us) { asm(""); _delay_us(1); us--; }
+ return us;
+}
+static inline uint16_t wait_data_lo(uint16_t us)
+{
+ while (data_in() && us) { asm(""); _delay_us(1); us--; }
+ return us;
+}
+static inline uint16_t wait_data_hi(uint16_t us)
+{
+ while (!data_in() && us) { asm(""); _delay_us(1); us--; }
+ return us;
+}
+
+/* idle state that device can send */
+static inline void idle(void)
+{
+ clock_hi();
+ data_hi();
+}
+
+/* inhibit device to send
+ * keyboard checks Data line on start bit(Data:hi) and it stops sending if Data line is low.
+ */
+static inline void inhibit(void)
+{
+ clock_hi();
+ data_lo();
+}
+
+#endif
diff --git a/tmk_core/protocol/iwrap.mk b/tmk_core/protocol/iwrap.mk
new file mode 100644
index 000000000..eeedd83af
--- /dev/null
+++ b/tmk_core/protocol/iwrap.mk
@@ -0,0 +1,26 @@
+IWRAP_DIR = protocol/iwrap
+
+OPT_DEFS += -DPROTOCOL_IWRAP
+
+SRC += $(IWRAP_DIR)/main.c \
+ $(IWRAP_DIR)/iwrap.c \
+ $(IWRAP_DIR)/suart.S \
+ $(COMMON_DIR)/sendchar_uart.c \
+ $(COMMON_DIR)/uart.c
+
+# Search Path
+VPATH += $(TMK_DIR)/protocol/iwrap
+
+
+# TODO: compatible with LUFA and PJRC
+# V-USB
+#
+VUSB_DIR = protocol/vusb
+OPT_DEFS += -DPROTOCOL_VUSB
+SRC += $(VUSB_DIR)/vusb.c \
+ $(VUSB_DIR)/usbdrv/usbdrv.c \
+ $(VUSB_DIR)/usbdrv/usbdrvasm.S \
+ $(VUSB_DIR)/usbdrv/oddebug.c
+VPATH += $(TMK_DIR)/protocol/vusb:$(TMK_DIR)/protocol/vusb/usbdrv
+
+
diff --git a/tmk_core/protocol/iwrap/iWRAP4.txt b/tmk_core/protocol/iwrap/iWRAP4.txt
new file mode 100644
index 000000000..2a062d9d9
--- /dev/null
+++ b/tmk_core/protocol/iwrap/iWRAP4.txt
@@ -0,0 +1,376 @@
+Bulegiga WT12
+=============
+WT12 is a bluetooth module from Bluegiga. http://www.bluegiga.com/
+
+iWRAP
+ higher layer interface for bluetooth firmware
+ communicate with UART
+
+iWRAP HID
+default setting
+ 115200 8bit/n/1/n
+
+
+TODO
+----
+KiCAD circuit/PCB design
+power saving
+ AVR sleep(15ms by watch dog timer)
+ WT12 sleep
+ measuring current consumption
+ measuring battery life of normal usage/idle/intensive usage
+software reset/bootloarder
+LED indicator(chaging/paring/connecting)
+license confirmation of suart.c
+consumer page is not working
+authenticate method/SSP
+SPP keyboard support
+SPP debug console support
+mouse wheel feature request to Bluegiga
+
+
+Problems
+--------
+power consumption
+no consumer page support(bug?)
+no mouse wheel support
+no paring management
+no interactive auth method
+
+
+UART hardware flow control
+--------------------------
+(iWRAP4 User Guide 9.5)
+Hardware flow control is enabled by default and it should not be disabled unless mandatory, because without the hardware flow control the data transmission may not be reliable.
+If the hardware flow control is enabled from PS-keys, but no flow control is used, the following steps should be implemented in the hardware design:
+- CTS pin must be grounded
+- RTS pin must be left floating
+
+
+Power Saving
+------------
+power consume
+ without opimization: 4hr to shutdown(310mAh)
+ 2011/08/25: 9hr(310mAh) SNIFF MASTER sleep/WDTO_120MS
+
+measure current consumption
+ HHKB keyswitch matrix board
+ idle
+ scanning
+ Bluegiga WT12 module
+ SLEEP command
+ deep sleep on/off in config bits
+
+HHKB keyswich
+ how to power off
+ I/O pin configuration when sleeping
+ FET switch for 5V regulator
+
+Bluetooth module
+ power off when in USB mode
+ power off by FET switch
+
+AVR configuration
+ unused pins
+ ADC
+
+
+
+SET CONTROL CONFIG
+------------------
+ SET CONTROL CONFIG 4810
+ SET CONTROL CONFIG LIST
+ SET CONTROL CONFIG 0000 0000 4910 DEEP_SLEEP KLUDGE INTERACTIVE_PIN UART_LATENCY
+
+ Bit14 UART low latency
+ Bit11 Interactive pairing mode
+ Bit04 Deep sleep
+
+
+Reconnection
+------------
+SET CONTROL AUTOCALL 1124 5000 HID
+ 1124 HID service class
+ 5000 interval ms
+
+HID profile
+-----------
+This is needed to configure only once.
+ SET PROFILE HID ON
+ RESET
+
+HID class
+---------
+ SET BT CLASS 005C0 // keyboard/mouse combined devie
+
+Pairing Security
+----------------
+Secure Simple Pairing(SSP)
+ SET BT SSP 2 0 // Enables SSP for keyboard and Man-in-the-middle protection
+ SET BT SSP 3 0 // Enables SSP just works mode
+
+for keyboard with SSP
+ SET BT AUTH * 0000
+ SET BT SSP 2 0
+ SET CONTROL CONFIG 800
+ RESET
+
+for keyboard without SSP
+ SET BT AUTH * 0000
+ SET CONTROL CONFIG 800
+ RESET
+
+AUTH
+ AUTH xx:xx:xx:xx:xx:xx? // Pairing request event
+ AUTH xx:xx:xx:xx:xx:xx 0000
+
+ SSP PASSKEY 78:dd:08:b7:e4:a2 ?
+ SSP PASSKEY 78:dd:08:b7:e4:a2 xxxxx
+ (SSP COMPLETE 78:dd:08:b7:e4:a2 HCI_ERROR_AUTH_FAIL // failed)
+ RING 0 78:dd:08:b7:e4:a2 11 HID
+
+Connecton
+ RING xx:xx:xx:xx:xx:xx xx HID // connection event
+
+ KILL xx:xx:xx:xx:xx:xx
+
+Mode
+----
+Command mode
+Data mode
+ Raw mode
+ (Simple mode not for a real keyboard)
+
+Raw mode
+ Keyboard:
+ 0x9f, length(10), 0xa1, 0x01, mods, 0x00, key1, key2, key3, key4, key5, key6
+
+ Mouse:
+ 0x9f, length(5), 0xa1, 0x02, buttons, X, Y
+
+ Consumer page:
+ 0x9f, length(5), 0xa1, 0x03, bitfield1, bitfield2, bitfield3
+
+ consumer page suage
+ Bitfield 1:
+ 0x01 Volume Increment
+ 0x02 Volume Decrement
+ 0x04 Mute
+ 0x08 Play/Pause
+ 0x10 Scan Next Track
+ 0x20 Scan Previous Track
+ 0x40 Stop
+ 0x80 Eject
+ Bitfield 2:
+ 0x01 Email Reader
+ 0x02 Application Control Search
+ 0x04 AC Bookmarks
+ 0x08 AC Home
+ 0x10 AC Back
+ 0x20 AC Forward
+ 0x40 AC Stop
+ 0x80 AC Refresh
+ Bitfield 3:
+ 0x01 Application Launch Generic Consumer Control
+ 0x02 AL Internet Browser
+ 0x04 AL Calculator
+ 0x08 AL Terminal Lock / Screensaver
+ 0x10 AL Local Machine Browser
+ 0x20 AC Minimize
+ 0x40 Record
+ 0x80 Rewind
+
+
+
+
+
+2011/07/13
+set
+SET BT BDADDR 00:07:80:47:22:14
+SET BT NAME HHKB pro BT
+SET BT CLASS 0005c0
+SET BT AUTH * 0000
+SET BT IDENT BT:47 f000 4.1.0 Bluegiga iWRAP
+SET BT LAP 9e8b33
+SET BT PAGEMODE 4 2000 1
+SET BT PAIR 78:dd:08:b7:e4:a2 a191189cd7e51030ad6a07848ce879bb
+SET BT POWER 3 3 3
+SET BT ROLE 0 f 7d00
+SET BT SNIFF 0 20 1 8
+SET BT SSP 2 1
+SET BT MTU 667
+SET CONTROL AUTOCALL 1124 3000 HID
+SET CONTROL BAUD 38400,8n1
+SET CONTROL CD 00 0
+SET CONTROL ECHO 7
+SET CONTROL ESCAPE 43 00 1
+SET CONTROL GAIN 0 5
+SET CONTROL INIT SET CONTROL MUX 0
+SET CONTROL MSC DTE 00 00 00 00 00 00
+SET CONTROL MUX 1
+SET CONTROL PIO 00 00
+SET CONTROL READY 00
+SET PROFILE HID f HID
+SET
+
+info config
+
+!!! THIS IS BETA RELEASE AND MAY BE USED FOR EVALUATION PURPOSES ONLY !!!
+
+WRAP THOR AI (4.1.0 build 435)
+Copyright (c) 2003-2011 Bluegiga Technologies Inc.
+Compiled on Jun 28 2011 17:19:51, running on WT12-A module, psr v31
+ AVRCP BGIO FTP HFP HFP_AG HID HID_CONSUMER_PAGE HSP LEDS MAP OTA PBAP PIO=0x00fc SSP SUBRATE TEST VOLUME
+ - BOCK3 version 435 (Jun 28 2011 17:19:37) (max acl/sco 7/1)
+ - Bluetooth version 2.1, Power class 2
+ - Loader 4279, firmware 6297 (56-bit encryption), native execution mode
+ - up 0 days, 06:23, 2 connections (pool 2)
+ - User configuration:
+&028a = 0001 0000 0000 0011 0024 0000 0000 0010 0000 0080 0000 0000 0080 005f 009b 0034 00fb 0006
+&028b = 0000 0bb8
+&028d = 0001
+&0295 = 0000 0005 000b 0000 0003 0000 0000 0000 0000 0000 0000
+&0298 = a006
+&0299 = 0000 0000
+&02a3 = 0030 0030 0030 0030
+&02a4 = 009d 0000
+&02a5 = 0053 0045 0054 0020 0043 004f 004e 0054 0052 004f 004c 0020 004d 0055 0058 0020 0030
+&02a7 = 0000 05c0
+&02a8 = 4910 0000 0000
+&02aa = 0004 2000 0001 0033 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+&02ac = 0000 0000 002b 0000 0000 0000 0000 0000 0000 0000 0002 0000 0000 0000 0010 0000 0000 0000 0000 029b 0000 0000 0000 0000
+&02ad = 4848 424b 7020 6f72 4220 0054
+&02b3 = 0005 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003
+&02b7 = 000f 4948 0044
+&02bb = 8000
+READY.
+
+
+
+
+2011/07/07 settings:
+set
+SET BT BDADDR 00:07:80:47:22:14
+SET BT NAME HHKB Pro BT
+SET BT CLASS 0005c0
+SET BT AUTH * 000
+SET BT IDENT BT:47 f000 4.0.0 Bluegiga iWRAP
+SET BT LAP 9e8b33
+SET BT PAGEMODE 4 2000 1
+SET BT PAIR 78:dd:08:b7:e4:a2 9e54d0aabb1b4d73cfccddb1ea4ef2d6
+SET BT POWER 3 3 3
+SET BT ROLE 0 f 7d00
+SET BT SNIFF 0 20 1 8
+SET BT SSP 3 0
+SET BT MTU 667
+SET CONTROL BAUD 38400,8n1
+SET CONTROL CD 00 0
+SET CONTROL ECHO 7
+SET CONTROL ESCAPE 255 00 1
+SET CONTROL GAIN 0 5
+SET CONTROL INIT set control mux 0
+SET CONTROL MSC DTE 00 00 00 00 00 00
+SET CONTROL PREAMP 1 1
+SET CONTROL READY 00
+SET PROFILE HID HID
+SET PROFILE SPP Bluetooth Serial Port
+SET
+
+info config
+WRAP THOR AI (4.0.0 build 317)
+Copyright (c) 2003-2010 Bluegiga Technologies Inc.
+Compiled on Apr 20 2010 16:44:28, running on WT12-A module, psr v31
+ AVRCP FTP PBAP PIO=0x00fc SSP SUBRATE VOLUME
+ - BOCK3 version 317 (Apr 20 2010 16:44:21) (max acl/sco 7/1)
+ - Bluetooth version 2.1, Power class 2
+ - Loader 4279, firmware 6297 (56-bit encryption), native execution mode
+ - up 0 days, 00:00, 0 connections (pool 1)
+ - User configuration:
+&028c = 0001 0020 0000 0001 0008 0000
+&028d = 0000
+&0296 = 0047 0001 f000 0400 6c42 6575 6967 6167 6920 5257 5041
+&0298 = c006
+&02a3 = 0030 0030 0030
+&02a4 = 009d 0000
+&02a5 = 0073 0065 0074 0020 0063 006f 006e 0074 0072 006f 006c 0020 006d 0075 0078 0020 0030
+&02a7 = 0000 05c0
+&02a8 = 0800 0000 0000
+&02ac = 0000 0000 00ff 0000 0000 0000 0000 0000 0000 0000 0002 0000 0000 0000 0010 0000 0000 0000 0000 029b 0000 0000 0000 0000
+&02ad = 4848 424b 5020 6f72 4220 0054
+&02b3 = 0004 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003
+&02b7 = 0000
+&02bb = 6c42 6575 6f74 746f 2068 6553 6972 6c61 5020 726f 0074
+READY.
+
+
+
+2011/08/23:
+SET BT BDADDR 00:07:80:47:22:14
+SET BT NAME HHKB pro BT
+SET BT CLASS 0005c0
+SET BT AUTH * 0000
+SET BT IDENT BT:47 f000 4.1.0 Bluegiga iWRAP
+SET BT LAP 9e8b33
+SET BT PAGEMODE 4 2000 1
+SET BT PAIRCOUNT 4
+SET BT POWER 3 3 3
+SET BT ROLE 1 f 12c0
+SET BT SNIFF 10 2 1 8
+SET BT SSP 3 0
+SET BT MTU 667
+SET CONTROL BAUD 38400,8n1
+SET CONTROL CD 00 0
+SET CONTROL ECHO 7
+SET CONTROL ESCAPE 43 00 1
+SET CONTROL GAIN 0 5
+SET CONTROL INIT SET CONTROL MUX 0
+SET CONTROL MSC DTE 00 00 00 00 00 00
+SET CONTROL MUX 1
+SET CONTROL PIO 00 00
+SET CONTROL READY 00
+SET PROFILE HID 7 HIDKeyboardMouse
+SET
+
+SET CONTROL CONFIG 0000 0004 481e CLOCK_CACHE INTERLACED_INQ INTERLACED_PAGE DEEP_SLEEP INTERACTIVE_PIN UART_LATENCY 23D_NOKLUDGE
+
+
+
+2011/08/25:
+SET BT BDADDR 00:07:80:47:22:14
+SET BT NAME HHKB pro BT
+SET BT CLASS 0005c0
+
+SET BT IDENT BT:47 f000 4.1.0 Bluegiga iWRAP
+SET BT LAP 9e8b33
+SET BT PAGEMODE 4 2000 1
+SET BT PAIRCOUNT 4
+SET BT PAIR 78:dd:08:b7:e4:a2 0be83335a03fed8ededae42e99554e28
+SET BT POWER 3 3 3
+SET BT ROLE 1 f 12c0
+SET BT SNIFF 100 20 1 8
+SET BT SSP 3 0
+SET BT MTU 667
+SET CONTROL BAUD 38400,8n1
+SET CONTROL CD 00 0
+SET CONTROL ECHO 7
+SET CONTROL ESCAPE - 20 1
+SET CONTROL GAIN 0 5
+SET CONTROL INIT SET CONTROL MUX 0
+SET CONTROL MSC DTE 00 00 00 00 00 00
+SET CONTROL MUX 1
+SET CONTROL PIO 00 00
+SET CONTROL READY 00
+SET PROFILE HID f HIDKeyboardMouse
+SET
+
+
+SET CONTROL CONFIG 0000 0000 490e CLOCK_CACHE INTERLACED_INQ INTERLACED_PAGE KLUDGE INTERACTIVE_PIN UART_LATENCY
+
+
+2011/09/08:
+SET CONTROL CONFIG 0000 0000 410e CLOCK_CACHE INTERLACED_INQ INTERLACED_PAGE KLUDGE UART_LATENCY
+
+ Removed INTERACTIVE_PIN to avoid interactive auth and use SET BT AUTH pin(0000).
+
+
+EOF
diff --git a/tmk_core/protocol/iwrap/iWRAP5.txt b/tmk_core/protocol/iwrap/iWRAP5.txt
new file mode 100644
index 000000000..ce3310f1b
--- /dev/null
+++ b/tmk_core/protocol/iwrap/iWRAP5.txt
@@ -0,0 +1,356 @@
+Terminology
+===========
+PSM
+HIDP HID Protocol
+L2CAP Logical Link Control Adaptation Protocol
+MTU Maximum Transmission Unit
+
+
+
+HID Protocol
+============
+3 of HID_SPEC_V11.pdf
+
+Channel
+-------
+Control channel PSM=0x0011
+Interrupt channel PSM=0x0013
+
+Message
+-------
+HANDSHAKE(0)
+HID_CONTROL(1)
+
+GET_REPORT(4)
+ Host requests report(DATA payload on Control channel) from Device
+ Size Desc
+ ------------------------------------------------------------------------------
+ HIDP-Hdr 1 7..4: HIDP Message TYpe(4: GET_REPORT)
+ 3: Size(1:2-octed buffer size, 0:size of the report)
+ 2: 0
+ 1..0: Report Type(1:input, 2:output, 3: feature)
+ ReportID 1 Optional
+ BufferSize 2 Optional(specified when Size=1)
+
+SET_REPORT(5)
+GET_PROTOCOL(6)
+SET_PROTOCOL(7)
+
+DATA(A)
+ Input/Output Report: All DATA payloads flow on Interrupt channel.
+ Other: flows on Control channel.
+ Size Desc
+ ------------------------------------------------------------------------------
+ HIDP-Hdr 1 7..4 0xA
+ 3..2 Reserved(0)
+ 1..0 Report Type(0:Other, 1:Input, 2:Output, 3:Feature)
+ Payload N Data
+
+
+
+
+Boot Protocol
+=============
+3.3.2
+No report descriptor, fixed report descriptors defined.
+
+Device ReportID Size
+---------------------------------
+Reserved 0
+Keyboard 1 9octets
+Mouse 2 4octets
+Reserved 3-255
+
+Report descriptor
+-----------------
+Report ID is added to USB HID boot protocol descriptor.
+Boot Protocol device doesn't need to supply descriptors. and can send extra data on end of boot report this data will be ignored unless host supports report descriptor.
+
+Report Protocol devices can have specific descriptors. Using Boot protocol descriptor followed by extra data may be useful for compatibility to Boot protocol only supported host.
+
+NOTE:
+Bluegiga HID sample say report ID of mouse is 1 but 2?
+Bluegiga HID sample say report ID of consumer page is 2 but 3?
+** mouse.desc and consumer.desc were fixed.
+ size
+keyboard.desc 67 0x43
+mouse.desc 60 0x3c
+consumer.desc 82 0x52
+combo.desc 209 0xd1
+
+
+
+SDP
+===
+attributes(3.3.2)
+----------
+HIDDeviceSubclass
+ which type is supported in Boot Protocol Mode
+ 7 6
+ ---
+ 0 1 Keyboard
+ 1 0 Pointing device
+ 1 1 Combo keyboard/pointing device
+
+HIDBootDevice
+ TRUE
+HIDReconnectInitiate
+ TRUE
+
+
+Class of Device/Service
+=======================
+http://phys.sci.hokudai.ac.jp/LABS/yts/pic/GB002/Bluetooth_assigned_numbers_baseband.pdf
+
+0x0005C0 Keyboard and Pointing deivce(combo)
+
+
+ 23 16 15 8 7 0
+ ---------------------------------
+ Service |Major |Minor |Format
+
+ Format type
+ 1 0
+ ---
+ 0 0
+
+ Minor Device Class of Peripheral Major
+ 7 6
+ ---
+ 0 1 Keyboard
+ 1 0 Pointing device
+ 1 1 Combo keyboard/pointing device
+
+
+ Major device classes
+ 12 11 10 9 8
+ --------------
+ 0 0 0 0 0 Miscellaneous
+ 0 0 0 0 1 Computer
+ 0 0 0 1 0 Phone
+ 0 0 0 1 1 LAN /Network Access point
+ 0 0 1 0 0 Audio/Video (headset,speaker,stereo, video display, vcr.....
+ 0 0 1 0 1 *Peripheral (mouse, joystick, keyboards, ..... )
+ 0 0 1 1 0 Imaging (printing, scanner, camera, display, ...)
+ 1 1 1 1 1 Uncategorized, specific device code not specified
+ X X X X X All other values reserved
+
+
+ Major service classes
+ bit
+ --------------------------------------
+ 13 Limited Discoverable Mode [Ref #1]
+ 14 (reserved)
+ 15 (reserved)
+ 16 Positioning (Location identification)
+ 17 Networking (LAN, Ad hoc, ...)
+ 18 Rendering (Printing, Speaker, ...)
+ 19 Capturing (Scanner, Microphone, ...)
+ 20 Object Transfer (v-Inbox, v-Folder, ...)
+ 21 Audio (Speaker, Microphone, Headset service, ...)
+ 22 Telephony (Cordless telephony, Modem, Headset service, ...)
+ 23 Information (WEB-server, WAP-server, ...)
+
+
+
+
+Authentication SSP
+-------------------
+SET BT SSP 2 0 PASS KEY entering
+SET BT SSP 3 0 NO PASS KEY entering
+SET BT SSP <capabilities> <mitm>
+ <capabilities>: 0:display only 1:display+yes/no button 2:keyboard only 3:none
+SET BT SSP 2 1 # 2:keyboard only 1:Man-in-the-middle protection is needed
+SET BT SSP 2 0 # 2:keyboard only 0:Man-in-the-middle protection is not needed
+
+
+SET BT SSP 2 1
+ bond only if MITM protection is supported by host
+SET BT SSP 2 0
+ bond even if MITM protection is not supported by host
+
+On Windows 'Add device' causes SSP PASSKEY event on iWRAP
+ SSP PASSKEY 78:dd:08:b7:e4:a2 ?
+
+If device has display(0 or 1) this event occurs. User should be shown this code on the device.
+ SSP CONFIRM 78:dd:08:b7:e4:a2 517572
+
+
+SET BT SSP 3 0
+ No input/output, No MITM protection.
+ Without procedure of authentication the divice is bond to host.
+
+
+Connect
+=======
+CALL 78:dd:08:b7:e4:a2 11 HID
+
+
+Setting
+========
+Following settings need to be done before wiring into keyboard.
+- UART speed: 38400bps(115200bps didn't work with software serial)
+- No SSP procedure(without MITM protection)
+- No Power Saving
+
+# clear pairing record and set default
+SET BT PAIR *
+SET RESET
+
+SET CONTROL INIT SET CONTROL MUX 0
+SET CONTROL BAUD 38400,8n1
+SET BT NAME TMK Blootooth WT12
+SET BT CLASS 0005c0
+SET BT AUTH * 0000
+SET BT SSP 3 0
+SET CONTROL CONFIG 4800
+SET PROFILE HID 0f c0 0100 00 en 0409 TMK Bluetooth keyboard(WT12)
+SET PROFILE SPP
+
+# power saving?
+SET BT SNIFF 100 20 1 8
+
+
+# Report Descriptor
+# combo keyboard + mouse + consumer
+HID SET d2 05010906a1010507850119e029e715002501750195088102950175088101950575010508850119012905910295017503910395067508150025650507190029658100c005010902a1010901a1008502050919012908150025017501950881020501093009311581257f750895028106093895018106050c0a380295018106c0c0050c0901a1018503050c1500250109e909ea09e209cd19b529b87501950881020a8a010a21020a2a021a23022a27027501950881020a83010a96010a92010a9e010a94010a060209b209b4750195088102c0
+
+
+
+SET PROFILE HID
+---------------
+ SET PROFILE HID 0d c0 100 0 en 0409 HHKB pro Bluetooth keyboard
+ {function bit} uint8
+ {subclass} uint8
+ {version} uint16
+ {country} uint8
+ {BTlang} char[2]
+ {USBlang} uint16
+ {name} string
+
+
+SET BT CLASS
+------------
+ See Class of Device
+ composite device: keyboard and mouse
+ SET BT CLASS 005c0
+
+
+
+
+
+
+----------
+after setting
+----------
+set
+SET BT BDADDR 00:07:80:47:22:14
+SET BT NAME TMK Blootooth WT12
+SET BT CLASS 0005c0
+SET BT AUTH * 0000
+SET BT IDENT BT:47 f000 5.0.1 Bluegiga iWRAP
+SET BT LAP 9e8b33
+SET BT PAGEMODE 4 2000 1
+SET BT PAIR 78:dd:08:b7:e4:a2 9e3d85c91bcae73fef8cc10bec18b42f
+SET BT POWER 3 3 3
+SET BT ROLE 0 f 7d00
+SET BT SNIFF 0 20 1 8
+SET BT SSP 3 0
+SET BT MTU 667
+SET CONTROL BAUD 38400,8n1
+SET CONTROL CD 00 0
+SET CONTROL ECHO 7
+SET CONTROL ESCAPE 43 00 1
+SET CONTROL GAIN 0 5
+SET CONTROL INIT SET CONTROL MUX 0
+SET CONTROL MSC DTE 00 00 00 00 00 00
+SET CONTROL MUX 1
+SET CONTROL PIO 00 00
+SET CONTROL READY 00
+SET PROFILE HID 0f c0 0100 00 en 0409 TMK Bluetooth keyboard(WT12)
+SET
+
+set control config list
+SET CONTROL CONFIG 0000 0000 0000 4900 KLUDGE INTERACTIVE_PIN UART_LATENCY
+
+
+info config
+WRAP THOR AI (5.0.1 build 620)
+Copyright (c) 2003-2012 Bluegiga Technologies Inc.
+Compiled on Oct 1 2012 10:56:21, running on WT12-A module, psr v31
+ BGIO FTP HFP HFP_AG HID HID_CONSUMER_PAGE HSP MAP MDP OTA PBAP PIO=0x00fc SSP SUBRATE TEST VOLUME
+ - BOCK4 version 620 (Oct 1 2012 10:56:03) (max acl/sco 7/1)
+ - Bluetooth version 3.0, Power class 2
+ - Loader 8615, firmware 8825 (56-bit encryption), native execution mode
+ - up 0 days, 01:50, 2 connections (pool 2)
+ - User configuration:
+&028d = 0001
+&0295 = 0000 0005 000b 0000 0003 0000 0000 0000 0000 0000 0000
+&0298 = c053
+&0299 = 0000 0000
+&02a3 = 0030 0030 0030 0030
+&02a4 = 009d 0000
+&02a5 = 0053 0045 0054 0020 0043 004f 004e 0054 0052 004f 004c 0020 004d 0055 0058 0020 0030
+&02a7 = 0000 05c0
+&02a8 = 0800 0000 0000 0000
+&02aa = 0004 2000 0001 0033 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+&02ac = 0000 0000 002b 0000 0000 0000 0000 0000 0000 0000 0002 0000 0000 0000 0010 0000 0000 0000 0000 029b 0000 0000 0000 0000
+&02ad = 4d54 204b 6c42 6f6f 6f74 746f 2068 5457 3231
+&02b0 = fa65 b0aa 934a 077b a600 d1cc fe58 8dd5
+&02b3 = 0004 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0003 0005 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0005
+&02b7 = 000f 00c0 0100 0000 0065 006e 0409 4d54 204b 6c42 6575 6f74 746f &02bb = 8000
+READY.
+----------
+
+
+
+-----
+After 5.0.1 Firmware update
+Firmware: ai-5.0.1-620-25b.bc4.dfu
+PSR: wt12-a.ai-5.0.1-620-25b.psrf
+-----
+info config
+WRAP THOR AI (5.0.1 build 620)
+Copyright (c) 2003-2012 Bluegiga Technologies Inc.
+Compiled on Oct 1 2012 10:56:21, running on WT12-A module, psr v31
+ BGIO FTP HFP HFP_AG HID HID_CONSUMER_PAGE HSP MAP MDP OTA PBAP PIO=0x00fc SSP SUBRATE TEST VOLUME
+ - BOCK4 version 620 (Oct 1 2012 10:56:03) (max acl/sco 7/1)
+ - Bluetooth version 3.0, Power class 2
+ - Loader 8615, firmware 8825 (56-bit encryption), native execution mode
+ - up 0 days, 00:03, 0 connections (pool 1)
+ - User configuration:
+&0295 = 0000 0005 000b 0000 0003 0000 0000 0000 0000 0000 0000
+&0299 = 0000 0000
+&02aa = 0004 2000 0001 0033 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
+&02ac = 0000 0000 002b 0000 0000 0000 0000 0000 0000 0000 0002 0000 0000 0000 0010 0000 0000 0000 0000 029b 0000 0000 0000 0000
+&02ad = 5457 3231 412d
+&02b0 = fa65 b0aa 934a 077b a600 d1cc fe58 8dd5
+READY.
+
+set
+SET BT BDADDR 00:07:80:47:22:14
+SET BT NAME WT12-A
+SET BT CLASS 001f00
+SET BT IDENT BT:47 f000 5.0.1 Bluegiga iWRAP
+SET BT LAP 9e8b33
+SET BT PAGEMODE 4 2000 1
+SET BT PAIR 78:dd:08:b7:e4:a2 af18f81faa107e6dd068762ef921f48b
+SET BT POWER 3 3 3
+SET BT ROLE 0 f 7d00
+SET BT SNIFF 0 20 1 8
+SET BT SSP 3 0
+SET BT MTU 667
+SET CONTROL BAUD 115200,8n1
+SET CONTROL CD 00 0
+SET CONTROL ECHO 7
+SET CONTROL ESCAPE 43 00 1
+SET CONTROL GAIN 0 5
+SET CONTROL MSC DTE 00 00 00 00 00 00
+SET CONTROL PIO 00 00
+SET CONTROL READY 00
+SET PROFILE SPP Bluetooth Serial Port
+SET
+
+set control config list
+SET CONTROL CONFIG 0000 0000 0000 0100 KLUDGE
+---------
diff --git a/tmk_core/protocol/iwrap/iwrap.c b/tmk_core/protocol/iwrap/iwrap.c
new file mode 100644
index 000000000..6a404116a
--- /dev/null
+++ b/tmk_core/protocol/iwrap/iwrap.c
@@ -0,0 +1,469 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* host driver for Bulegiga iWRAP */
+/* Bluegiga BT12
+ * Connections
+ * Hardware UART Software UART BlueTooth
+ * PC=====UART=======AVR=====SUART====iWRAP(BT12)-----------PC
+ *
+ * - Hardware UART for Debug Console to communicate iWRAP
+ * - Software UART for iWRAP control to send keyboard/mouse data
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <avr/interrupt.h>
+#include <util/delay.h>
+#include "keycode.h"
+#include "suart.h"
+#include "uart.h"
+#include "report.h"
+#include "host_driver.h"
+#include "iwrap.h"
+#include "print.h"
+
+
+/* iWRAP MUX mode utils. 3.10 HID raw mode(iWRAP_HID_Application_Note.pdf) */
+#define MUX_HEADER(LINK, LENGTH) do { \
+ xmit(0xbf); /* SOF */ \
+ xmit(LINK); /* Link */ \
+ xmit(0x00); /* Flags */ \
+ xmit(LENGTH); /* Length */ \
+} while (0)
+#define MUX_FOOTER(LINK) xmit(LINK^0xff)
+
+
+static uint8_t connected = 0;
+//static uint8_t channel = 1;
+
+/* iWRAP buffer */
+#define MUX_BUF_SIZE 64
+static char buf[MUX_BUF_SIZE];
+static uint8_t snd_pos = 0;
+
+#define MUX_RCV_BUF_SIZE 256
+static char rcv_buf[MUX_RCV_BUF_SIZE];
+static uint8_t rcv_head = 0;
+static uint8_t rcv_tail = 0;
+
+
+/* receive buffer */
+static void rcv_enq(char c)
+{
+ uint8_t next = (rcv_head + 1) % MUX_RCV_BUF_SIZE;
+ if (next != rcv_tail) {
+ rcv_buf[rcv_head] = c;
+ rcv_head = next;
+ }
+}
+
+static char rcv_deq(void)
+{
+ char c = 0;
+ if (rcv_head != rcv_tail) {
+ c = rcv_buf[rcv_tail++];
+ rcv_tail %= MUX_RCV_BUF_SIZE;
+ }
+ return c;
+}
+
+/*
+static char rcv_peek(void)
+{
+ if (rcv_head == rcv_tail)
+ return 0;
+ return rcv_buf[rcv_tail];
+}
+*/
+
+static void rcv_clear(void)
+{
+ rcv_tail = rcv_head = 0;
+}
+
+/* iWRAP response */
+ISR(PCINT1_vect, ISR_BLOCK) // recv() runs away in case of ISR_NOBLOCK
+{
+ if ((SUART_IN_PIN & (1<<SUART_IN_BIT)))
+ return;
+
+ static volatile uint8_t mux_state = 0xff;
+ static volatile uint8_t mux_link = 0xff;
+ uint8_t c = recv();
+ switch (mux_state) {
+ case 0xff: // SOF
+ if (c == 0xbf)
+ mux_state--;
+ break;
+ case 0xfe: // Link
+ mux_state--;
+ mux_link = c;
+ break;
+ case 0xfd: // Flags
+ mux_state--;
+ break;
+ case 0xfc: // Length
+ mux_state = c;
+ break;
+ case 0x00:
+ mux_state = 0xff;
+ mux_link = 0xff;
+ break;
+ default:
+ if (mux_state--) {
+ uart_putchar(c);
+ rcv_enq(c);
+ }
+ }
+}
+
+
+/*------------------------------------------------------------------*
+ * iWRAP communication
+ *------------------------------------------------------------------*/
+void iwrap_init(void)
+{
+ // reset iWRAP if in already MUX mode after AVR software-reset
+ iwrap_send("RESET");
+ iwrap_mux_send("RESET");
+ _delay_ms(3000);
+ iwrap_send("\r\nSET CONTROL MUX 1\r\n");
+ _delay_ms(500);
+ iwrap_check_connection();
+}
+
+void iwrap_mux_send(const char *s)
+{
+ rcv_clear();
+ MUX_HEADER(0xff, strlen((char *)s));
+ iwrap_send(s);
+ MUX_FOOTER(0xff);
+}
+
+void iwrap_send(const char *s)
+{
+ while (*s)
+ xmit(*s++);
+}
+
+/* send buffer */
+void iwrap_buf_add(uint8_t c)
+{
+ // need space for '\0'
+ if (snd_pos < MUX_BUF_SIZE-1)
+ buf[snd_pos++] = c;
+}
+
+void iwrap_buf_del(void)
+{
+ if (snd_pos)
+ snd_pos--;
+}
+
+void iwrap_buf_send(void)
+{
+ buf[snd_pos] = '\0';
+ snd_pos = 0;
+ iwrap_mux_send(buf);
+}
+
+void iwrap_call(void)
+{
+ char *p;
+
+ iwrap_mux_send("SET BT PAIR");
+ _delay_ms(500);
+
+ p = rcv_buf + rcv_tail;
+ while (!strncmp(p, "SET BT PAIR", 11)) {
+ p += 7;
+ strncpy(p, "CALL", 4);
+ strncpy(p+22, " 11 HID\n\0", 9);
+ print_S(p);
+ iwrap_mux_send(p);
+ // TODO: skip to next line
+ p += 57;
+
+ DEBUG_LED_CONFIG;
+ DEBUG_LED_ON;
+ _delay_ms(500);
+ DEBUG_LED_OFF;
+ _delay_ms(500);
+ DEBUG_LED_ON;
+ _delay_ms(500);
+ DEBUG_LED_OFF;
+ _delay_ms(500);
+ DEBUG_LED_ON;
+ _delay_ms(500);
+ DEBUG_LED_OFF;
+ _delay_ms(500);
+ DEBUG_LED_ON;
+ _delay_ms(500);
+ DEBUG_LED_OFF;
+ _delay_ms(500);
+ DEBUG_LED_ON;
+ _delay_ms(500);
+ DEBUG_LED_OFF;
+ _delay_ms(500);
+ }
+ iwrap_check_connection();
+}
+
+void iwrap_kill(void)
+{
+ char c;
+ iwrap_mux_send("LIST");
+ _delay_ms(500);
+
+ while ((c = rcv_deq()) && c != '\n') ;
+ if (strncmp(rcv_buf + rcv_tail, "LIST ", 5)) {
+ print("no connection to kill.\n");
+ return;
+ }
+ // skip 10 'space' chars
+ for (uint8_t i = 10; i; i--)
+ while ((c = rcv_deq()) && c != ' ') ;
+
+ char *p = rcv_buf + rcv_tail - 5;
+ strncpy(p, "KILL ", 5);
+ strncpy(p + 22, "\n\0", 2);
+ print_S(p);
+ iwrap_mux_send(p);
+ _delay_ms(500);
+
+ iwrap_check_connection();
+}
+
+void iwrap_unpair(void)
+{
+ iwrap_mux_send("SET BT PAIR");
+ _delay_ms(500);
+
+ char *p = rcv_buf + rcv_tail;
+ if (!strncmp(p, "SET BT PAIR", 11)) {
+ strncpy(p+29, "\n\0", 2);
+ print_S(p);
+ iwrap_mux_send(p);
+ }
+}
+
+void iwrap_sleep(void)
+{
+ iwrap_mux_send("SLEEP");
+}
+
+void iwrap_sniff(void)
+{
+}
+
+void iwrap_subrate(void)
+{
+}
+
+bool iwrap_failed(void)
+{
+ if (strncmp(rcv_buf, "SYNTAX ERROR", 12))
+ return true;
+ else
+ return false;
+}
+
+uint8_t iwrap_connected(void)
+{
+ return connected;
+}
+
+uint8_t iwrap_check_connection(void)
+{
+ iwrap_mux_send("LIST");
+ _delay_ms(100);
+
+ if (strncmp(rcv_buf, "LIST ", 5) || !strncmp(rcv_buf, "LIST 0", 6))
+ connected = 0;
+ else
+ connected = 1;
+ return connected;
+}
+
+
+/*------------------------------------------------------------------*
+ * Host driver
+ *------------------------------------------------------------------*/
+static uint8_t keyboard_leds(void);
+static void send_keyboard(report_keyboard_t *report);
+static void send_mouse(report_mouse_t *report);
+static void send_system(uint16_t data);
+static void send_consumer(uint16_t data);
+
+static host_driver_t driver = {
+ keyboard_leds,
+ send_keyboard,
+ send_mouse,
+ send_system,
+ send_consumer
+};
+
+host_driver_t *iwrap_driver(void)
+{
+ return &driver;
+}
+
+static uint8_t keyboard_leds(void) {
+ return 0;
+}
+
+static void send_keyboard(report_keyboard_t *report)
+{
+ if (!iwrap_connected() && !iwrap_check_connection()) return;
+ MUX_HEADER(0x01, 0x0c);
+ // HID raw mode header
+ xmit(0x9f);
+ xmit(0x0a); // Length
+ xmit(0xa1); // DATA(Input)
+ xmit(0x01); // Report ID
+ xmit(report->mods);
+ xmit(0x00); // reserved byte(always 0)
+ xmit(report->keys[0]);
+ xmit(report->keys[1]);
+ xmit(report->keys[2]);
+ xmit(report->keys[3]);
+ xmit(report->keys[4]);
+ xmit(report->keys[5]);
+ MUX_FOOTER(0x01);
+}
+
+static void send_mouse(report_mouse_t *report)
+{
+#if defined(MOUSEKEY_ENABLE) || defined(PS2_MOUSE_ENABLE)
+ if (!iwrap_connected() && !iwrap_check_connection()) return;
+ MUX_HEADER(0x01, 0x09);
+ // HID raw mode header
+ xmit(0x9f);
+ xmit(0x07); // Length
+ xmit(0xa1); // DATA(Input)
+ xmit(0x02); // Report ID
+ xmit(report->buttons);
+ xmit(report->x);
+ xmit(report->y);
+ xmit(report->v);
+ xmit(report->h);
+ MUX_FOOTER(0x01);
+#endif
+}
+
+static void send_system(uint16_t data)
+{
+ /* not supported */
+}
+
+static void send_consumer(uint16_t data)
+{
+#ifdef EXTRAKEY_ENABLE
+ static uint16_t last_data = 0;
+ uint8_t bits1 = 0;
+ uint8_t bits2 = 0;
+ uint8_t bits3 = 0;
+
+ if (!iwrap_connected() && !iwrap_check_connection()) return;
+ if (data == last_data) return;
+ last_data = data;
+
+ // 3.10 HID raw mode(iWRAP_HID_Application_Note.pdf)
+ switch (data) {
+ case AUDIO_VOL_UP:
+ bits1 = 0x01;
+ break;
+ case AUDIO_VOL_DOWN:
+ bits1 = 0x02;
+ break;
+ case AUDIO_MUTE:
+ bits1 = 0x04;
+ break;
+ case TRANSPORT_PLAY_PAUSE:
+ bits1 = 0x08;
+ break;
+ case TRANSPORT_NEXT_TRACK:
+ bits1 = 0x10;
+ break;
+ case TRANSPORT_PREV_TRACK:
+ bits1 = 0x20;
+ break;
+ case TRANSPORT_STOP:
+ bits1 = 0x40;
+ break;
+ case TRANSPORT_EJECT:
+ bits1 = 0x80;
+ break;
+ case AL_EMAIL:
+ bits2 = 0x01;
+ break;
+ case AC_SEARCH:
+ bits2 = 0x02;
+ break;
+ case AC_BOOKMARKS:
+ bits2 = 0x04;
+ break;
+ case AC_HOME:
+ bits2 = 0x08;
+ break;
+ case AC_BACK:
+ bits2 = 0x10;
+ break;
+ case AC_FORWARD:
+ bits2 = 0x20;
+ break;
+ case AC_STOP:
+ bits2 = 0x40;
+ break;
+ case AC_REFRESH:
+ bits2 = 0x80;
+ break;
+ case AL_CC_CONFIG:
+ bits3 = 0x01;
+ break;
+ case AL_CALCULATOR:
+ bits3 = 0x04;
+ break;
+ case AL_LOCK:
+ bits3 = 0x08;
+ break;
+ case AL_LOCAL_BROWSER:
+ bits3 = 0x10;
+ break;
+ case AC_MINIMIZE:
+ bits3 = 0x20;
+ break;
+ case TRANSPORT_RECORD:
+ bits3 = 0x40;
+ break;
+ case TRANSPORT_REWIND:
+ bits3 = 0x80;
+ break;
+ }
+
+ MUX_HEADER(0x01, 0x07);
+ xmit(0x9f);
+ xmit(0x05); // Length
+ xmit(0xa1); // DATA(Input)
+ xmit(0x03); // Report ID
+ xmit(bits1);
+ xmit(bits2);
+ xmit(bits3);
+ MUX_FOOTER(0x01);
+#endif
+}
diff --git a/tmk_core/protocol/iwrap/iwrap.h b/tmk_core/protocol/iwrap/iwrap.h
new file mode 100644
index 000000000..ffaad9395
--- /dev/null
+++ b/tmk_core/protocol/iwrap/iwrap.h
@@ -0,0 +1,49 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef IWRAP_H
+#define IWRAP_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "host_driver.h"
+
+
+/* enable iWRAP MUX mode */
+#define MUX_MODE
+
+
+host_driver_t *iwrap_driver(void);
+
+void iwrap_init(void);
+void iwrap_send(const char *s);
+void iwrap_mux_send(const char *s);
+void iwrap_buf_send(void);
+void iwrap_buf_add(uint8_t c);
+void iwrap_buf_del(void);
+
+void iwrap_call(void);
+void iwrap_kill(void);
+void iwrap_unpair(void);
+void iwrap_sleep(void);
+void iwrap_sniff(void);
+void iwrap_subrate(void);
+bool iwrap_failed(void);
+uint8_t iwrap_connected(void);
+uint8_t iwrap_check_connection(void);
+
+#endif
diff --git a/tmk_core/protocol/iwrap/main.c b/tmk_core/protocol/iwrap/main.c
new file mode 100644
index 000000000..3abdce8df
--- /dev/null
+++ b/tmk_core/protocol/iwrap/main.c
@@ -0,0 +1,376 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <stdint.h>
+#include <avr/interrupt.h>
+#include <avr/io.h>
+//#include <avr/wdt.h>
+#include "wd.h" // in order to use watchdog in interrupt mode
+#include <avr/sleep.h>
+#include <util/delay.h>
+#include <avr/power.h>
+#include "keyboard.h"
+#include "matrix.h"
+#include "host.h"
+#include "action.h"
+#include "iwrap.h"
+#ifdef PROTOCOL_VUSB
+# include "vusb.h"
+# include "usbdrv.h"
+#endif
+#include "uart.h"
+#include "suart.h"
+#include "timer.h"
+#include "debug.h"
+#include "keycode.h"
+#include "command.h"
+
+
+static void sleep(uint8_t term);
+static bool console(void);
+static bool console_command(uint8_t c);
+static uint8_t key2asc(uint8_t key);
+
+
+/*
+static void set_prr(void)
+{
+ power_adc_disable();
+ power_spi_disable();
+ power_twi_disable();
+#ifndef TIMER_H
+ //power_timer0_disable(); // used in timer.c
+#endif
+ power_timer1_disable();
+ power_timer2_disable();
+}
+*/
+
+/*
+static void pullup_pins(void)
+{
+ // DDRs are set to 0(input) by default.
+#ifdef PORTA
+ PORTA = 0xFF;
+#endif
+ PORTB = 0xFF;
+ PORTC = 0xFF;
+ PORTD = 0xFF;
+#ifdef PORTE
+ PORTE = 0xFF;
+#endif
+#ifdef PORTE
+ PORTF = 0xFF;
+#endif
+}
+*/
+
+
+#ifdef PROTOCOL_VUSB
+static void disable_vusb(void)
+{
+ // disable interrupt & disconnect to prevent host from enumerating
+ USB_INTR_ENABLE &= ~(1 << USB_INTR_ENABLE_BIT);
+ usbDeviceDisconnect();
+}
+
+static void enable_vusb(void)
+{
+ USB_INTR_ENABLE |= (1 << USB_INTR_ENABLE_BIT);
+ usbDeviceConnect();
+}
+
+static void init_vusb(void)
+{
+ uint8_t i = 0;
+
+ usbInit();
+ disable_vusb();
+ /* fake USB disconnect for > 250 ms */
+ while(--i){
+ _delay_ms(1);
+ }
+ enable_vusb();
+}
+#endif
+
+void change_driver(host_driver_t *driver)
+{
+ /*
+ host_clear_keyboard_report();
+ host_swap_keyboard_report();
+ host_clear_keyboard_report();
+ host_send_keyboard_report();
+ */
+ clear_keyboard();
+ _delay_ms(1000);
+ host_set_driver(driver);
+}
+
+
+static bool sleeping = false;
+static bool insomniac = false; // TODO: should be false for power saving
+static uint16_t last_timer = 0;
+
+int main(void)
+{
+ MCUSR = 0;
+ clock_prescale_set(clock_div_1);
+ WD_SET(WD_OFF);
+
+ // power saving: the result is worse than nothing... why?
+ //pullup_pins();
+ //set_prr();
+
+#ifdef PROTOCOL_VUSB
+ disable_vusb();
+#endif
+ uart_init(115200);
+ keyboard_init();
+ print("\nSend BREAK for UART Console Commands.\n");
+
+ // TODO: move to iWRAP/suart file
+ print("suart init\n");
+ // suart init
+ // PC4: Tx Output IDLE(Hi)
+ PORTC |= (1<<4);
+ DDRC |= (1<<4);
+ // PC5: Rx Input(pull-up)
+ PORTC |= (1<<5);
+ DDRC &= ~(1<<5);
+ // suart receive interrut(PC5/PCINT13)
+ PCMSK1 = 0b00100000;
+ PCICR = 0b00000010;
+
+ host_set_driver(iwrap_driver());
+
+ print("iwrap_init()\n");
+ iwrap_init();
+ iwrap_call();
+
+ last_timer = timer_read();
+ while (true) {
+#ifdef PROTOCOL_VUSB
+ if (host_get_driver() == vusb_driver())
+ usbPoll();
+#endif
+ keyboard_task();
+#ifdef PROTOCOL_VUSB
+ if (host_get_driver() == vusb_driver())
+ vusb_transfer_keyboard();
+#endif
+ // TODO: depricated
+ if (matrix_is_modified() || console()) {
+ last_timer = timer_read();
+ sleeping = false;
+ } else if (!sleeping && timer_elapsed(last_timer) > 4000) {
+ sleeping = true;
+ iwrap_check_connection();
+ }
+
+ // TODO: suspend.h
+ if (host_get_driver() == iwrap_driver()) {
+ if (sleeping && !insomniac) {
+ _delay_ms(1); // wait for UART to send
+ iwrap_sleep();
+ sleep(WDTO_60MS);
+ }
+ }
+ }
+}
+
+static void sleep(uint8_t term)
+{
+ WD_SET(WD_IRQ, term);
+
+ cli();
+ set_sleep_mode(SLEEP_MODE_PWR_DOWN);
+ sleep_enable();
+ sleep_bod_disable();
+ sei();
+ sleep_cpu();
+ sleep_disable();
+
+ WD_SET(WD_OFF);
+}
+
+static bool console(void)
+{
+ // Send to Bluetoot module WT12
+ static bool breaked = false;
+ if (!uart_available())
+ return false;
+ else {
+ uint8_t c;
+ c = uart_getchar();
+ uart_putchar(c);
+ switch (c) {
+ case 0x00: // BREAK signal
+ if (!breaked) {
+ print("break(? for help): ");
+ breaked = true;
+ }
+ break;
+ case '\r':
+ uart_putchar('\n');
+ iwrap_buf_send();
+ break;
+ case '\b':
+ iwrap_buf_del();
+ break;
+ default:
+ if (breaked) {
+ print("\n");
+ console_command(c);
+ breaked = false;
+ } else {
+ iwrap_buf_add(c);
+ }
+ break;
+ }
+ return true;
+ }
+}
+
+bool command_extra(uint8_t code)
+{
+ return console_command(key2asc(code));
+}
+
+static bool console_command(uint8_t c)
+{
+ switch (c) {
+ case 'h':
+ case '?':
+ print("\nCommands for Bluetooth(WT12/iWRAP):\n");
+ print("r: reset. software reset by watchdog\n");
+ print("i: insomniac. prevent KB from sleeping\n");
+ print("c: iwrap_call. CALL for BT connection.\n");
+#ifdef PROTOCOL_VUSB
+ print("u: USB mode. switch to USB.\n");
+ print("w: BT mode. switch to Bluetooth.\n");
+#endif
+ print("k: kill first connection.\n");
+ print("Del: unpair first pairing.\n");
+ print("\n");
+ return 0;
+ case 'r':
+ print("reset\n");
+ WD_AVR_RESET();
+ return 1;
+ case 'i':
+ insomniac = !insomniac;
+ if (insomniac)
+ print("insomniac\n");
+ else
+ print("not insomniac\n");
+ return 1;
+ case 'c':
+ print("iwrap_call()\n");
+ iwrap_call();
+ return 1;
+#ifdef PROTOCOL_VUSB
+ case 'u':
+ print("USB mode\n");
+ init_vusb();
+ change_driver(vusb_driver());
+ //iwrap_kill();
+ //iwrap_sleep();
+ // disable suart receive interrut(PC5/PCINT13)
+ PCMSK1 &= ~(0b00100000);
+ PCICR &= ~(0b00000010);
+ return 1;
+ case 'w':
+ print("iWRAP mode\n");
+ change_driver(iwrap_driver());
+ disable_vusb();
+ // enable suart receive interrut(PC5/PCINT13)
+ PCMSK1 |= 0b00100000;
+ PCICR |= 0b00000010;
+ return 1;
+#endif
+ case 'k':
+ print("kill\n");
+ iwrap_kill();
+ return 1;
+ case 0x7F: // DELETE
+ print("unpair\n");
+ iwrap_unpair();
+ return 1;
+ }
+ return 0;
+}
+
+// convert keycode into ascii charactor
+static uint8_t key2asc(uint8_t key)
+{
+ switch (key) {
+ case KC_A: return 'a';
+ case KC_B: return 'b';
+ case KC_C: return 'c';
+ case KC_D: return 'd';
+ case KC_E: return 'e';
+ case KC_F: return 'f';
+ case KC_G: return 'g';
+ case KC_H: return 'h';
+ case KC_I: return 'i';
+ case KC_J: return 'j';
+ case KC_K: return 'k';
+ case KC_L: return 'l';
+ case KC_M: return 'm';
+ case KC_N: return 'n';
+ case KC_O: return 'o';
+ case KC_P: return 'p';
+ case KC_Q: return 'q';
+ case KC_R: return 'r';
+ case KC_S: return 's';
+ case KC_T: return 't';
+ case KC_U: return 'u';
+ case KC_V: return 'v';
+ case KC_W: return 'w';
+ case KC_X: return 'x';
+ case KC_Y: return 'y';
+ case KC_Z: return 'z';
+ case KC_1: return '1';
+ case KC_2: return '2';
+ case KC_3: return '3';
+ case KC_4: return '4';
+ case KC_5: return '5';
+ case KC_6: return '6';
+ case KC_7: return '7';
+ case KC_8: return '8';
+ case KC_9: return '9';
+ case KC_0: return '0';
+ case KC_ENTER: return '\n';
+ case KC_ESCAPE: return 0x1B;
+ case KC_BSPACE: return '\b';
+ case KC_TAB: return '\t';
+ case KC_SPACE: return ' ';
+ case KC_MINUS: return '-';
+ case KC_EQUAL: return '=';
+ case KC_LBRACKET: return '[';
+ case KC_RBRACKET: return ']';
+ case KC_BSLASH: return '\\';
+ case KC_NONUS_HASH: return '\\';
+ case KC_SCOLON: return ';';
+ case KC_QUOTE: return '\'';
+ case KC_GRAVE: return '`';
+ case KC_COMMA: return ',';
+ case KC_DOT: return '.';
+ case KC_SLASH: return '/';
+ default: return 0x00;
+ }
+}
diff --git a/tmk_core/protocol/iwrap/mux_exit.rb b/tmk_core/protocol/iwrap/mux_exit.rb
new file mode 100644
index 000000000..1f6be48af
--- /dev/null
+++ b/tmk_core/protocol/iwrap/mux_exit.rb
@@ -0,0 +1,7 @@
+#
+# Rescue from Bluegiga iWRAP MUX mode
+# 6.75 of iWRAP5_User_Guid.pdf
+#
+[0xBF, 0xFF, 0x00, 0x11, 0x53, 0x45, 0x54, 0x20, 0x43, 0x4f, 0x4e, 0x54, 0x52, 0x4f, 0x4c, 0x20, 0x4d, 0x55, 0x58, 0x20, 0x30, 0x00].each do |x|
+ print x.chr
+end
diff --git a/tmk_core/protocol/iwrap/suart.S b/tmk_core/protocol/iwrap/suart.S
new file mode 100644
index 000000000..1b0290963
--- /dev/null
+++ b/tmk_core/protocol/iwrap/suart.S
@@ -0,0 +1,156 @@
+;---------------------------------------------------------------------------;
+; Software implemented UART module ;
+; (C)ChaN, 2005 (http://elm-chan.org/) ;
+;---------------------------------------------------------------------------;
+; Bit rate settings:
+;
+; 1MHz 2MHz 4MHz 6MHz 8MHz 10MHz 12MHz 16MHz 20MHz
+; 2.4kbps 138 - - - - - - - -
+; 4.8kbps 68 138 - - - - - - -
+; 9.6kbps 33 68 138 208 - - - - -
+; 19.2kbps - 33 68 102 138 173 208 - -
+; 38.4kbps - - 33 50 68 85 102 138 172
+; 57.6kbps - - 21 33 44 56 68 91 114
+; 115.2kbps - - - - 21 27 33 44 56
+
+.nolist
+#include <avr/io.h>
+.list
+
+#define BPS 102 /* Bit delay. (see above table) */
+#define BIDIR 0 /* 0:Separated Tx/Rx, 1:Shared Tx/Rx */
+
+#define OUT_1 sbi _SFR_IO_ADDR(SUART_OUT_PORT), SUART_OUT_BIT /* Output 1 */
+#define OUT_0 cbi _SFR_IO_ADDR(SUART_OUT_PORT), SUART_OUT_BIT /* Output 0 */
+#define SKIP_IN_1 sbis _SFR_IO_ADDR(SUART_IN_PIN), SUART_IN_BIT /* Skip if 1 */
+#define SKIP_IN_0 sbic _SFR_IO_ADDR(SUART_IN_PIN), SUART_IN_BIT /* Skip if 0 */
+
+
+
+#ifdef SPM_PAGESIZE
+.macro _LPMI reg
+ lpm \reg, Z+
+.endm
+.macro _MOVW dh,dl, sh,sl
+ movw \dl, \sl
+.endm
+#else
+.macro _LPMI reg
+ lpm
+ mov \reg, r0
+ adiw ZL, 1
+.endm
+.macro _MOVW dh,dl, sh,sl
+ mov \dl, \sl
+ mov \dh, \sh
+.endm
+#endif
+
+
+
+;---------------------------------------------------------------------------;
+; Transmit a byte in serial format of N81
+;
+;Prototype: void xmit (uint8_t data);
+;Size: 16 words
+
+.global xmit
+.func xmit
+xmit:
+#if BIDIR
+ ldi r23, BPS-1 ;Pre-idle time for bidirectional data line
+5: dec r23 ;
+ brne 5b ;/
+#endif
+ in r0, _SFR_IO_ADDR(SREG) ;Save flags
+
+ com r24 ;C = start bit
+ ldi r25, 10 ;Bit counter
+ cli ;Start critical section
+
+1: ldi r23, BPS-1 ;----- Bit transferring loop
+2: dec r23 ;Wait for a bit time
+ brne 2b ;/
+ brcs 3f ;MISO = bit to be sent
+ OUT_1 ;
+3: brcc 4f ;
+ OUT_0 ;/
+4: lsr r24 ;Get next bit into C
+ dec r25 ;All bits sent?
+ brne 1b ; no, coutinue
+
+ out _SFR_IO_ADDR(SREG), r0 ;End of critical section
+ ret
+.endfunc
+
+
+
+;---------------------------------------------------------------------------;
+; Receive a byte
+;
+;Prototype: uint8_t rcvr (void);
+;Size: 19 words
+
+.global rcvr
+.func rcvr
+rcvr:
+ in r0, _SFR_IO_ADDR(SREG) ;Save flags
+
+ ldi r24, 0x80 ;Receiving shift reg
+ cli ;Start critical section
+
+1: SKIP_IN_1 ;Wait for idle
+ rjmp 1b
+2: SKIP_IN_0 ;Wait for start bit
+ rjmp 2b
+ ldi r25, BPS/2 ;Wait for half bit time
+3: dec r25
+ brne 3b
+
+4: ldi r25, BPS ;----- Bit receiving loop
+5: dec r25 ;Wait for a bit time
+ brne 5b ;/
+ lsr r24 ;Next bit
+ SKIP_IN_0 ;Get a data bit into r24.7
+ ori r24, 0x80
+ brcc 4b ;All bits received? no, continue
+
+ out _SFR_IO_ADDR(SREG), r0 ;End of critical section
+ ret
+.endfunc
+
+
+; Not wait for start bit. This should be called after detecting start bit.
+.global recv
+.func recv
+recv:
+ in r0, _SFR_IO_ADDR(SREG) ;Save flags
+
+ ldi r24, 0x80 ;Receiving shift reg
+ cli ;Start critical section
+
+;1: SKIP_IN_1 ;Wait for idle
+; rjmp 1b
+;2: SKIP_IN_0 ;Wait for start bit
+; rjmp 2b
+ ldi r25, BPS/2 ;Wait for half bit time
+3: dec r25
+ brne 3b
+
+4: ldi r25, BPS ;----- Bit receiving loop
+5: dec r25 ;Wait for a bit time
+ brne 5b ;/
+ lsr r24 ;Next bit
+ SKIP_IN_0 ;Get a data bit into r24.7
+ ori r24, 0x80
+ brcc 4b ;All bits received? no, continue
+
+ ldi r25, BPS/2 ;Wait for half bit time
+6: dec r25
+ brne 6b
+7: SKIP_IN_1 ;Wait for stop bit
+ rjmp 7b
+
+ out _SFR_IO_ADDR(SREG), r0 ;End of critical section
+ ret
+.endfunc
diff --git a/tmk_core/protocol/iwrap/suart.h b/tmk_core/protocol/iwrap/suart.h
new file mode 100644
index 000000000..72725b998
--- /dev/null
+++ b/tmk_core/protocol/iwrap/suart.h
@@ -0,0 +1,8 @@
+#ifndef SUART
+#define SUART
+
+void xmit(uint8_t);
+uint8_t rcvr(void);
+uint8_t recv(void);
+
+#endif /* SUART */
diff --git a/tmk_core/protocol/iwrap/wd.h b/tmk_core/protocol/iwrap/wd.h
new file mode 100644
index 000000000..99058f033
--- /dev/null
+++ b/tmk_core/protocol/iwrap/wd.h
@@ -0,0 +1,159 @@
+/* This is from http://www.mtcnet.net/~henryvm/wdt/ */
+#ifndef _AVR_WD_H_
+#define _AVR_WD_H_
+
+#include <avr/io.h>
+
+/*
+Copyright (c) 2009, Curt Van Maanen
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+
+include usage-
+ #include "wd.h" //if in same directory as project
+ #include <avr/wd.h> //if wd.h is in avr directory
+
+set watchdog modes and prescale
+
+usage-
+ WD_SET(mode,[timeout]); //prescale always set
+
+modes-
+ WD_OFF disabled
+ WD_RST normal reset mode
+ WD_IRQ interrupt only mode (if supported)
+ WD_RST_IRQ interrupt+reset mode (if supported)
+
+timeout-
+ WDTO_15MS default if no timeout provided
+ WDTO_30MS
+ WDTO_60MS
+ WDTO_120MS
+ WDTO_250MS
+ WDTO_500MS
+ WDTO_1S
+ WDTO_2S
+ WDTO_4S (if supported)
+ WDTO_8S (if supported)
+
+examples-
+ WD_SET(WD_RST,WDTO_1S); //reset mode, 1s timeout
+ WD_SET(WD_OFF); //watchdog disabled (if not fused on)
+ WD_SET(WD_RST); //reset mode, 15ms (default timeout)
+ WD_SET(WD_IRQ,WDTO_120MS); //interrupt only mode, 120ms timeout
+ WD_SET(WD_RST_IRQ,WDTO_2S); //interrupt+reset mode, 2S timeout
+
+
+for enhanced watchdogs, if the watchdog is not being used WDRF should be
+cleared on every power up or reset, along with disabling the watchdog-
+ WD_DISABLE(); //clear WDRF, then turn off watchdog
+
+*/
+
+//reset registers to the same name (MCUCSR)
+#if !defined(MCUCSR)
+#define MCUCSR MCUSR
+#endif
+
+//watchdog registers to the same name (WDTCSR)
+#if !defined(WDTCSR)
+#define WDTCSR WDTCR
+#endif
+
+//if enhanced watchdog, define irq values, create disable macro
+#if defined(WDIF)
+#define WD_IRQ 0xC0
+#define WD_RST_IRQ 0xC8
+#define WD_DISABLE() do{ \
+ MCUCSR &= ~(1<<WDRF); \
+ WD_SET(WD_OFF); \
+ }while(0)
+#endif
+
+//all watchdogs
+#define WD_RST 8
+#define WD_OFF 0
+
+//prescale values
+#define WDTO_15MS 0
+#define WDTO_30MS 1
+#define WDTO_60MS 2
+#define WDTO_120MS 3
+#define WDTO_250MS 4
+#define WDTO_500MS 5
+#define WDTO_1S 6
+#define WDTO_2S 7
+
+//prescale values for avrs with WDP3
+#if defined(WDP3)
+#define WDTO_4S 0x20
+#define WDTO_8S 0x21
+#endif
+
+//watchdog reset
+#define WDR() __asm__ __volatile__("wdr")
+
+//avr reset using watchdog
+#define WD_AVR_RESET() do{ \
+ __asm__ __volatile__("cli"); \
+ WD_SET_UNSAFE(WD_RST); \
+ while(1); \
+ }while(0)
+
+/*set the watchdog-
+1. save SREG
+2. turn off irq's
+3. reset watchdog timer
+4. enable watchdog change
+5. write watchdog value
+6. restore SREG (restoring irq status)
+*/
+#define WD_SET(val,...) \
+ __asm__ __volatile__( \
+ "in __tmp_reg__,__SREG__" "\n\t" \
+ "cli" "\n\t" \
+ "wdr" "\n\t" \
+ "sts %[wdreg],%[wden]" "\n\t" \
+ "sts %[wdreg],%[wdval]" "\n\t" \
+ "out __SREG__,__tmp_reg__" "\n\t" \
+ : \
+ : [wdreg] "M" (&WDTCSR), \
+ [wden] "r" ((uint8_t)(0x18)), \
+ [wdval] "r" ((uint8_t)(val|(__VA_ARGS__+0))) \
+ : "r0" \
+)
+
+/*set the watchdog when I bit in SREG known to be clear-
+1. reset watchdog timer
+2. enable watchdog change
+5. write watchdog value
+*/
+#define WD_SET_UNSAFE(val,...) \
+ __asm__ __volatile__( \
+ "wdr" "\n\t" \
+ "sts %[wdreg],%[wden]" "\n\t" \
+ "sts %[wdreg],%[wdval]" "\n\t" \
+ : \
+ : [wdreg] "M" (&WDTCSR), \
+ [wden] "r" ((uint8_t)(0x18)), \
+ [wdval] "r" ((uint8_t)(val|(__VA_ARGS__+0))) \
+)
+
+
+//for compatibility with avr/wdt.h
+#define wdt_enable(val) WD_SET(WD_RST,val)
+#define wdt_disable() WD_SET(WD_OFF)
+
+
+#endif /* _AVR_WD_H_ */
diff --git a/tmk_core/protocol/lufa.mk b/tmk_core/protocol/lufa.mk
new file mode 100644
index 000000000..0eeace44e
--- /dev/null
+++ b/tmk_core/protocol/lufa.mk
@@ -0,0 +1,60 @@
+LUFA_DIR = protocol/lufa
+
+# Path to the LUFA library
+LUFA_PATH ?= $(LUFA_DIR)/LUFA-git
+
+
+# Create the LUFA source path variables by including the LUFA makefile
+ifneq (, $(wildcard $(TMK_PATH)/$(LUFA_PATH)/LUFA/Build/lufa_sources.mk))
+ # New build system from 20120730
+ LUFA_ROOT_PATH = $(LUFA_PATH)/LUFA
+ include $(TMK_PATH)/$(LUFA_PATH)/LUFA/Build/lufa_sources.mk
+else
+ include $(TMK_PATH)/$(LUFA_PATH)/LUFA/makefile
+endif
+
+LUFA_SRC = lufa.c \
+ descriptor.c \
+ $(LUFA_SRC_USB)
+
+ifeq ($(strip $(MIDI_ENABLE)), yes)
+ include $(TMK_PATH)/protocol/midi.mk
+endif
+
+ifeq ($(strip $(BLUETOOTH_ENABLE)), yes)
+ LUFA_SRC += $(LUFA_DIR)/bluetooth.c \
+ $(TMK_DIR)/protocol/serial_uart.c
+endif
+
+SRC += $(LUFA_SRC)
+
+# Search Path
+VPATH += $(TMK_PATH)/$(LUFA_DIR)
+VPATH += $(TMK_PATH)/$(LUFA_PATH)
+
+# Option modules
+#ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE)
+#endif
+
+#ifdef EXTRAKEY_ENABLE
+#endif
+
+# LUFA library compile-time options and predefined tokens
+LUFA_OPTS = -DUSB_DEVICE_ONLY
+LUFA_OPTS += -DUSE_FLASH_DESCRIPTORS
+LUFA_OPTS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"
+#LUFA_OPTS += -DINTERRUPT_CONTROL_ENDPOINT
+LUFA_OPTS += -DFIXED_CONTROL_ENDPOINT_SIZE=8
+LUFA_OPTS += -DFIXED_NUM_CONFIGURATIONS=1
+
+# Remote wakeup fix for ATmega32U2 https://github.com/tmk/tmk_keyboard/issues/361
+ifeq ($(MCU),atmega32u2)
+ LUFA_OPTS += -DNO_LIMITED_CONTROLLER_CONNECT
+endif
+
+OPT_DEFS += -DF_USB=$(F_USB)UL
+OPT_DEFS += -DARCH=ARCH_$(ARCH)
+OPT_DEFS += $(LUFA_OPTS)
+
+# This indicates using LUFA stack
+OPT_DEFS += -DPROTOCOL_LUFA
diff --git a/tmk_core/protocol/lufa/LUFA-git/.gitignore b/tmk_core/protocol/lufa/LUFA-git/.gitignore
new file mode 100644
index 000000000..045f96980
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/.gitignore
@@ -0,0 +1,14 @@
+*.o
+*.d
+*.elf
+*.hex
+*.eep
+*.sym
+*.bin
+*.lss
+*.map
+*.bak
+*.class
+Documentation/
+LUFA/StudioIntegration/ProjectGenerator/*
+LUFA/StudioIntegration/DocBook/*
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/BootloaderAPI.c b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/BootloaderAPI.c
new file mode 100644
index 000000000..f7564e982
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/BootloaderAPI.c
@@ -0,0 +1,75 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Bootloader user application API functions.
+ */
+
+#include "BootloaderAPI.h"
+
+void BootloaderAPI_ErasePage(const uint32_t Address)
+{
+ boot_page_erase_safe(Address);
+ boot_spm_busy_wait();
+ boot_rww_enable();
+}
+
+void BootloaderAPI_WritePage(const uint32_t Address)
+{
+ boot_page_write_safe(Address);
+ boot_spm_busy_wait();
+ boot_rww_enable();
+}
+
+void BootloaderAPI_FillWord(const uint32_t Address, const uint16_t Word)
+{
+ boot_page_fill_safe(Address, Word);
+}
+
+uint8_t BootloaderAPI_ReadSignature(const uint16_t Address)
+{
+ return boot_signature_byte_get(Address);
+}
+
+uint8_t BootloaderAPI_ReadFuse(const uint16_t Address)
+{
+ return boot_lock_fuse_bits_get(Address);
+}
+
+uint8_t BootloaderAPI_ReadLock(void)
+{
+ return boot_lock_fuse_bits_get(GET_LOCK_BITS);
+}
+
+void BootloaderAPI_WriteLock(const uint8_t LockBits)
+{
+ boot_lock_bits_set_safe(LockBits);
+}
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/BootloaderAPI.h b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/BootloaderAPI.h
new file mode 100644
index 000000000..2462cacdd
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/BootloaderAPI.h
@@ -0,0 +1,58 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Header file for BootloaderAPI.c.
+ */
+
+#ifndef _BOOTLOADER_API_H_
+#define _BOOTLOADER_API_H_
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <avr/boot.h>
+ #include <stdbool.h>
+
+ #include <LUFA/Common/Common.h>
+
+ #include "Config/AppConfig.h"
+
+ /* Function Prototypes: */
+ void BootloaderAPI_ErasePage(const uint32_t Address);
+ void BootloaderAPI_WritePage(const uint32_t Address);
+ void BootloaderAPI_FillWord(const uint32_t Address, const uint16_t Word);
+ uint8_t BootloaderAPI_ReadSignature(const uint16_t Address);
+ uint8_t BootloaderAPI_ReadFuse(const uint16_t Address);
+ uint8_t BootloaderAPI_ReadLock(void);
+ void BootloaderAPI_WriteLock(const uint8_t LockBits);
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/BootloaderAPITable.S b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/BootloaderAPITable.S
new file mode 100644
index 000000000..69ebd387a
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/BootloaderAPITable.S
@@ -0,0 +1,91 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+; Trampolines to actual API implementations if the target address is outside the
+; range of a rjmp instruction (can happen with large bootloader sections)
+.section .apitable_trampolines, "ax"
+.global BootloaderAPI_Trampolines
+BootloaderAPI_Trampolines:
+
+ BootloaderAPI_ErasePage_Trampoline:
+ jmp BootloaderAPI_ErasePage
+ BootloaderAPI_WritePage_Trampoline:
+ jmp BootloaderAPI_WritePage
+ BootloaderAPI_FillWord_Trampoline:
+ jmp BootloaderAPI_FillWord
+ BootloaderAPI_ReadSignature_Trampoline:
+ jmp BootloaderAPI_ReadSignature
+ BootloaderAPI_ReadFuse_Trampoline:
+ jmp BootloaderAPI_ReadFuse
+ BootloaderAPI_ReadLock_Trampoline:
+ jmp BootloaderAPI_ReadLock
+ BootloaderAPI_WriteLock_Trampoline:
+ jmp BootloaderAPI_WriteLock
+ BootloaderAPI_UNUSED1:
+ ret
+ BootloaderAPI_UNUSED2:
+ ret
+ BootloaderAPI_UNUSED3:
+ ret
+ BootloaderAPI_UNUSED4:
+ ret
+ BootloaderAPI_UNUSED5:
+ ret
+
+
+
+; API function jump table
+.section .apitable_jumptable, "ax"
+.global BootloaderAPI_JumpTable
+BootloaderAPI_JumpTable:
+
+ rjmp BootloaderAPI_ErasePage_Trampoline
+ rjmp BootloaderAPI_WritePage_Trampoline
+ rjmp BootloaderAPI_FillWord_Trampoline
+ rjmp BootloaderAPI_ReadSignature_Trampoline
+ rjmp BootloaderAPI_ReadFuse_Trampoline
+ rjmp BootloaderAPI_ReadLock_Trampoline
+ rjmp BootloaderAPI_WriteLock_Trampoline
+ rjmp BootloaderAPI_UNUSED1 ; UNUSED ENTRY 1
+ rjmp BootloaderAPI_UNUSED2 ; UNUSED ENTRY 2
+ rjmp BootloaderAPI_UNUSED3 ; UNUSED ENTRY 3
+ rjmp BootloaderAPI_UNUSED4 ; UNUSED ENTRY 4
+ rjmp BootloaderAPI_UNUSED5 ; UNUSED ENTRY 5
+
+
+
+; Bootloader table signatures and information
+.section .apitable_signatures, "ax"
+.global BootloaderAPI_Signatures
+BootloaderAPI_Signatures:
+
+ .long BOOT_START_ADDR ; Start address of the bootloader
+ .word 0xDF00 ; Signature for the CDC class bootloader
+ .word 0xDCFB ; Signature for a LUFA class bootloader
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/BootloaderCDC.c b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/BootloaderCDC.c
new file mode 100644
index 000000000..58bb33892
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/BootloaderCDC.c
@@ -0,0 +1,641 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Main source file for the CDC class bootloader. This file contains the complete bootloader logic.
+ */
+
+#define INCLUDE_FROM_BOOTLOADERCDC_C
+#include "BootloaderCDC.h"
+
+/** Contains the current baud rate and other settings of the first virtual serial port. This must be retained as some
+ * operating systems will not open the port unless the settings can be set successfully.
+ */
+static CDC_LineEncoding_t LineEncoding = { .BaudRateBPS = 0,
+ .CharFormat = CDC_LINEENCODING_OneStopBit,
+ .ParityType = CDC_PARITY_None,
+ .DataBits = 8 };
+
+/** Current address counter. This stores the current address of the FLASH or EEPROM as set by the host,
+ * and is used when reading or writing to the AVRs memory (either FLASH or EEPROM depending on the issued
+ * command.)
+ */
+static uint32_t CurrAddress;
+
+/** Flag to indicate if the bootloader should be running, or should exit and allow the application code to run
+ * via a watchdog reset. When cleared the bootloader will exit, starting the watchdog and entering an infinite
+ * loop until the AVR restarts and the application runs.
+ */
+static bool RunBootloader = true;
+
+/** Magic lock for forced application start. If the HWBE fuse is programmed and BOOTRST is unprogrammed, the bootloader
+ * will start if the /HWB line of the AVR is held low and the system is reset. However, if the /HWB line is still held
+ * low when the application attempts to start via a watchdog reset, the bootloader will re-start. If set to the value
+ * \ref MAGIC_BOOT_KEY the special init function \ref Application_Jump_Check() will force the application to start.
+ */
+uint16_t MagicBootKey ATTR_NO_INIT;
+
+
+/** Special startup routine to check if the bootloader was started via a watchdog reset, and if the magic application
+ * start key has been loaded into \ref MagicBootKey. If the bootloader started via the watchdog and the key is valid,
+ * this will force the user application to start via a software jump.
+ */
+void Application_Jump_Check(void)
+{
+ bool JumpToApplication = false;
+
+ #if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
+ /* Disable JTAG debugging */
+ JTAG_DISABLE();
+
+ /* Enable pull-up on the JTAG TCK pin so we can use it to select the mode */
+ PORTF |= (1 << 4);
+ Delay_MS(10);
+
+ /* If the TCK pin is not jumpered to ground, start the user application instead */
+ JumpToApplication |= ((PINF & (1 << 4)) != 0);
+
+ /* Re-enable JTAG debugging */
+ JTAG_ENABLE();
+ #endif
+
+ /* If the reset source was the bootloader and the key is correct, clear it and jump to the application */
+ if ((MCUSR & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY))
+ JumpToApplication |= true;
+
+ /* If a request has been made to jump to the user application, honor it */
+ if (JumpToApplication)
+ {
+ /* Turn off the watchdog */
+ MCUSR &= ~(1<<WDRF);
+ wdt_disable();
+
+ /* Clear the boot key and jump to the user application */
+ MagicBootKey = 0;
+
+ // cppcheck-suppress constStatement
+ ((void (*)(void))0x0000)();
+ }
+}
+
+/** Main program entry point. This routine configures the hardware required by the bootloader, then continuously
+ * runs the bootloader processing routine until instructed to soft-exit, or hard-reset via the watchdog to start
+ * the loaded application code.
+ */
+int main(void)
+{
+ /* Setup hardware required for the bootloader */
+ SetupHardware();
+
+ /* Turn on first LED on the board to indicate that the bootloader has started */
+ LEDs_SetAllLEDs(LEDS_LED1);
+
+ /* Enable global interrupts so that the USB stack can function */
+ GlobalInterruptEnable();
+
+ while (RunBootloader)
+ {
+ CDC_Task();
+ USB_USBTask();
+ }
+
+ /* Disconnect from the host - USB interface will be reset later along with the AVR */
+ USB_Detach();
+
+ /* Unlock the forced application start mode of the bootloader if it is restarted */
+ MagicBootKey = MAGIC_BOOT_KEY;
+
+ /* Enable the watchdog and force a timeout to reset the AVR */
+ wdt_enable(WDTO_250MS);
+
+ for (;;);
+}
+
+/** Configures all hardware required for the bootloader. */
+static void SetupHardware(void)
+{
+ /* Disable watchdog if enabled by bootloader/fuses */
+ MCUSR &= ~(1 << WDRF);
+ wdt_disable();
+
+ /* Disable clock division */
+ clock_prescale_set(clock_div_1);
+
+ /* Relocate the interrupt vector table to the bootloader section */
+ MCUCR = (1 << IVCE);
+ MCUCR = (1 << IVSEL);
+
+ /* Initialize the USB and other board hardware drivers */
+ USB_Init();
+ LEDs_Init();
+
+ /* Bootloader active LED toggle timer initialization */
+ TIMSK1 = (1 << TOIE1);
+ TCCR1B = ((1 << CS11) | (1 << CS10));
+}
+
+/** ISR to periodically toggle the LEDs on the board to indicate that the bootloader is active. */
+ISR(TIMER1_OVF_vect, ISR_BLOCK)
+{
+ LEDs_ToggleLEDs(LEDS_LED1 | LEDS_LED2);
+}
+
+/** Event handler for the USB_ConfigurationChanged event. This configures the device's endpoints ready
+ * to relay data to and from the attached USB host.
+ */
+void EVENT_USB_Device_ConfigurationChanged(void)
+{
+ /* Setup CDC Notification, Rx and Tx Endpoints */
+ Endpoint_ConfigureEndpoint(CDC_NOTIFICATION_EPADDR, EP_TYPE_INTERRUPT,
+ CDC_NOTIFICATION_EPSIZE, 1);
+
+ Endpoint_ConfigureEndpoint(CDC_TX_EPADDR, EP_TYPE_BULK, CDC_TXRX_EPSIZE, 1);
+
+ Endpoint_ConfigureEndpoint(CDC_RX_EPADDR, EP_TYPE_BULK, CDC_TXRX_EPSIZE, 1);
+}
+
+/** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent to
+ * the device from the USB host before passing along unhandled control requests to the library for processing
+ * internally.
+ */
+void EVENT_USB_Device_ControlRequest(void)
+{
+ /* Ignore any requests that aren't directed to the CDC interface */
+ if ((USB_ControlRequest.bmRequestType & (CONTROL_REQTYPE_TYPE | CONTROL_REQTYPE_RECIPIENT)) !=
+ (REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ return;
+ }
+
+ /* Activity - toggle indicator LEDs */
+ LEDs_ToggleLEDs(LEDS_LED1 | LEDS_LED2);
+
+ /* Process CDC specific control requests */
+ switch (USB_ControlRequest.bRequest)
+ {
+ case CDC_REQ_GetLineEncoding:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+
+ /* Write the line coding data to the control endpoint */
+ Endpoint_Write_Control_Stream_LE(&LineEncoding, sizeof(CDC_LineEncoding_t));
+ Endpoint_ClearOUT();
+ }
+
+ break;
+ case CDC_REQ_SetLineEncoding:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+
+ /* Read the line coding data in from the host into the global struct */
+ Endpoint_Read_Control_Stream_LE(&LineEncoding, sizeof(CDC_LineEncoding_t));
+ Endpoint_ClearIN();
+ }
+
+ break;
+ case CDC_REQ_SetControlLineState:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+ Endpoint_ClearStatusStage();
+ }
+
+ break;
+ }
+}
+
+#if !defined(NO_BLOCK_SUPPORT)
+/** Reads or writes a block of EEPROM or FLASH memory to or from the appropriate CDC data endpoint, depending
+ * on the AVR109 protocol command issued.
+ *
+ * \param[in] Command Single character AVR109 protocol command indicating what memory operation to perform
+ */
+static void ReadWriteMemoryBlock(const uint8_t Command)
+{
+ uint16_t BlockSize;
+ char MemoryType;
+
+ uint8_t HighByte = 0;
+ uint8_t LowByte = 0;
+
+ BlockSize = (FetchNextCommandByte() << 8);
+ BlockSize |= FetchNextCommandByte();
+
+ MemoryType = FetchNextCommandByte();
+
+ if ((MemoryType != MEMORY_TYPE_FLASH) && (MemoryType != MEMORY_TYPE_EEPROM))
+ {
+ /* Send error byte back to the host */
+ WriteNextResponseByte('?');
+
+ return;
+ }
+
+ /* Check if command is to read a memory block */
+ if (Command == AVR109_COMMAND_BlockRead)
+ {
+ /* Re-enable RWW section */
+ boot_rww_enable();
+
+ while (BlockSize--)
+ {
+ if (MemoryType == MEMORY_TYPE_FLASH)
+ {
+ /* Read the next FLASH byte from the current FLASH page */
+ #if (FLASHEND > 0xFFFF)
+ WriteNextResponseByte(pgm_read_byte_far(CurrAddress | HighByte));
+ #else
+ WriteNextResponseByte(pgm_read_byte(CurrAddress | HighByte));
+ #endif
+
+ /* If both bytes in current word have been read, increment the address counter */
+ if (HighByte)
+ CurrAddress += 2;
+
+ HighByte = !HighByte;
+ }
+ else
+ {
+ /* Read the next EEPROM byte into the endpoint */
+ WriteNextResponseByte(eeprom_read_byte((uint8_t*)(intptr_t)(CurrAddress >> 1)));
+
+ /* Increment the address counter after use */
+ CurrAddress += 2;
+ }
+ }
+ }
+ else
+ {
+ uint32_t PageStartAddress = CurrAddress;
+
+ if (MemoryType == MEMORY_TYPE_FLASH)
+ {
+ boot_page_erase(PageStartAddress);
+ boot_spm_busy_wait();
+ }
+
+ while (BlockSize--)
+ {
+ if (MemoryType == MEMORY_TYPE_FLASH)
+ {
+ /* If both bytes in current word have been written, increment the address counter */
+ if (HighByte)
+ {
+ /* Write the next FLASH word to the current FLASH page */
+ boot_page_fill(CurrAddress, ((FetchNextCommandByte() << 8) | LowByte));
+
+ /* Increment the address counter after use */
+ CurrAddress += 2;
+ }
+ else
+ {
+ LowByte = FetchNextCommandByte();
+ }
+
+ HighByte = !HighByte;
+ }
+ else
+ {
+ /* Write the next EEPROM byte from the endpoint */
+ eeprom_update_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)), FetchNextCommandByte());
+
+ /* Increment the address counter after use */
+ CurrAddress += 2;
+ }
+ }
+
+ /* If in FLASH programming mode, commit the page after writing */
+ if (MemoryType == MEMORY_TYPE_FLASH)
+ {
+ /* Commit the flash page to memory */
+ boot_page_write(PageStartAddress);
+
+ /* Wait until write operation has completed */
+ boot_spm_busy_wait();
+ }
+
+ /* Send response byte back to the host */
+ WriteNextResponseByte('\r');
+ }
+}
+#endif
+
+/** Retrieves the next byte from the host in the CDC data OUT endpoint, and clears the endpoint bank if needed
+ * to allow reception of the next data packet from the host.
+ *
+ * \return Next received byte from the host in the CDC data OUT endpoint
+ */
+static uint8_t FetchNextCommandByte(void)
+{
+ /* Select the OUT endpoint so that the next data byte can be read */
+ Endpoint_SelectEndpoint(CDC_RX_EPADDR);
+
+ /* If OUT endpoint empty, clear it and wait for the next packet from the host */
+ while (!(Endpoint_IsReadWriteAllowed()))
+ {
+ Endpoint_ClearOUT();
+
+ while (!(Endpoint_IsOUTReceived()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return 0;
+ }
+ }
+
+ /* Fetch the next byte from the OUT endpoint */
+ return Endpoint_Read_8();
+}
+
+/** Writes the next response byte to the CDC data IN endpoint, and sends the endpoint back if needed to free up the
+ * bank when full ready for the next byte in the packet to the host.
+ *
+ * \param[in] Response Next response byte to send to the host
+ */
+static void WriteNextResponseByte(const uint8_t Response)
+{
+ /* Select the IN endpoint so that the next data byte can be written */
+ Endpoint_SelectEndpoint(CDC_TX_EPADDR);
+
+ /* If IN endpoint full, clear it and wait until ready for the next packet to the host */
+ if (!(Endpoint_IsReadWriteAllowed()))
+ {
+ Endpoint_ClearIN();
+
+ while (!(Endpoint_IsINReady()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+ }
+
+ /* Write the next byte to the IN endpoint */
+ Endpoint_Write_8(Response);
+}
+
+/** Task to read in AVR109 commands from the CDC data OUT endpoint, process them, perform the required actions
+ * and send the appropriate response back to the host.
+ */
+static void CDC_Task(void)
+{
+ /* Select the OUT endpoint */
+ Endpoint_SelectEndpoint(CDC_RX_EPADDR);
+
+ /* Check if endpoint has a command in it sent from the host */
+ if (!(Endpoint_IsOUTReceived()))
+ return;
+
+ /* Read in the bootloader command (first byte sent from host) */
+ uint8_t Command = FetchNextCommandByte();
+
+ if (Command == AVR109_COMMAND_ExitBootloader)
+ {
+ RunBootloader = false;
+
+ /* Send confirmation byte back to the host */
+ WriteNextResponseByte('\r');
+ }
+ else if ((Command == AVR109_COMMAND_SetLED) || (Command == AVR109_COMMAND_ClearLED) ||
+ (Command == AVR109_COMMAND_SelectDeviceType))
+ {
+ FetchNextCommandByte();
+
+ /* Send confirmation byte back to the host */
+ WriteNextResponseByte('\r');
+ }
+ else if ((Command == AVR109_COMMAND_EnterProgrammingMode) || (Command == AVR109_COMMAND_LeaveProgrammingMode))
+ {
+ /* Send confirmation byte back to the host */
+ WriteNextResponseByte('\r');
+ }
+ else if (Command == AVR109_COMMAND_ReadPartCode)
+ {
+ /* Return ATMEGA128 part code - this is only to allow AVRProg to use the bootloader */
+ WriteNextResponseByte(0x44);
+ WriteNextResponseByte(0x00);
+ }
+ else if (Command == AVR109_COMMAND_ReadAutoAddressIncrement)
+ {
+ /* Indicate auto-address increment is supported */
+ WriteNextResponseByte('Y');
+ }
+ else if (Command == AVR109_COMMAND_SetCurrentAddress)
+ {
+ /* Set the current address to that given by the host (translate 16-bit word address to byte address) */
+ CurrAddress = (FetchNextCommandByte() << 9);
+ CurrAddress |= (FetchNextCommandByte() << 1);
+
+ /* Send confirmation byte back to the host */
+ WriteNextResponseByte('\r');
+ }
+ else if (Command == AVR109_COMMAND_ReadBootloaderInterface)
+ {
+ /* Indicate serial programmer back to the host */
+ WriteNextResponseByte('S');
+ }
+ else if (Command == AVR109_COMMAND_ReadBootloaderIdentifier)
+ {
+ /* Write the 7-byte software identifier to the endpoint */
+ for (uint8_t CurrByte = 0; CurrByte < 7; CurrByte++)
+ WriteNextResponseByte(SOFTWARE_IDENTIFIER[CurrByte]);
+ }
+ else if (Command == AVR109_COMMAND_ReadBootloaderSWVersion)
+ {
+ WriteNextResponseByte('0' + BOOTLOADER_VERSION_MAJOR);
+ WriteNextResponseByte('0' + BOOTLOADER_VERSION_MINOR);
+ }
+ else if (Command == AVR109_COMMAND_ReadSignature)
+ {
+ WriteNextResponseByte(AVR_SIGNATURE_3);
+ WriteNextResponseByte(AVR_SIGNATURE_2);
+ WriteNextResponseByte(AVR_SIGNATURE_1);
+ }
+ else if (Command == AVR109_COMMAND_EraseFLASH)
+ {
+ /* Clear the application section of flash */
+ for (uint32_t CurrFlashAddress = 0; CurrFlashAddress < (uint32_t)BOOT_START_ADDR; CurrFlashAddress += SPM_PAGESIZE)
+ {
+ boot_page_erase(CurrFlashAddress);
+ boot_spm_busy_wait();
+ boot_page_write(CurrFlashAddress);
+ boot_spm_busy_wait();
+ }
+
+ /* Send confirmation byte back to the host */
+ WriteNextResponseByte('\r');
+ }
+ #if !defined(NO_LOCK_BYTE_WRITE_SUPPORT)
+ else if (Command == AVR109_COMMAND_WriteLockbits)
+ {
+ /* Set the lock bits to those given by the host */
+ boot_lock_bits_set(FetchNextCommandByte());
+
+ /* Send confirmation byte back to the host */
+ WriteNextResponseByte('\r');
+ }
+ #endif
+ else if (Command == AVR109_COMMAND_ReadLockbits)
+ {
+ WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOCK_BITS));
+ }
+ else if (Command == AVR109_COMMAND_ReadLowFuses)
+ {
+ WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS));
+ }
+ else if (Command == AVR109_COMMAND_ReadHighFuses)
+ {
+ WriteNextResponseByte(boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS));
+ }
+ else if (Command == AVR109_COMMAND_ReadExtendedFuses)
+ {
+ WriteNextResponseByte(boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS));
+ }
+ #if !defined(NO_BLOCK_SUPPORT)
+ else if (Command == AVR109_COMMAND_GetBlockWriteSupport)
+ {
+ WriteNextResponseByte('Y');
+
+ /* Send block size to the host */
+ WriteNextResponseByte(SPM_PAGESIZE >> 8);
+ WriteNextResponseByte(SPM_PAGESIZE & 0xFF);
+ }
+ else if ((Command == AVR109_COMMAND_BlockWrite) || (Command == AVR109_COMMAND_BlockRead))
+ {
+ /* Delegate the block write/read to a separate function for clarity */
+ ReadWriteMemoryBlock(Command);
+ }
+ #endif
+ #if !defined(NO_FLASH_BYTE_SUPPORT)
+ else if (Command == AVR109_COMMAND_FillFlashPageWordHigh)
+ {
+ /* Write the high byte to the current flash page */
+ boot_page_fill(CurrAddress, FetchNextCommandByte());
+
+ /* Send confirmation byte back to the host */
+ WriteNextResponseByte('\r');
+ }
+ else if (Command == AVR109_COMMAND_FillFlashPageWordLow)
+ {
+ /* Write the low byte to the current flash page */
+ boot_page_fill(CurrAddress | 0x01, FetchNextCommandByte());
+
+ /* Increment the address */
+ CurrAddress += 2;
+
+ /* Send confirmation byte back to the host */
+ WriteNextResponseByte('\r');
+ }
+ else if (Command == AVR109_COMMAND_WriteFlashPage)
+ {
+ /* Commit the flash page to memory */
+ boot_page_write(CurrAddress);
+
+ /* Wait until write operation has completed */
+ boot_spm_busy_wait();
+
+ /* Send confirmation byte back to the host */
+ WriteNextResponseByte('\r');
+ }
+ else if (Command == AVR109_COMMAND_ReadFLASHWord)
+ {
+ #if (FLASHEND > 0xFFFF)
+ uint16_t ProgramWord = pgm_read_word_far(CurrAddress);
+ #else
+ uint16_t ProgramWord = pgm_read_word(CurrAddress);
+ #endif
+
+ WriteNextResponseByte(ProgramWord >> 8);
+ WriteNextResponseByte(ProgramWord & 0xFF);
+ }
+ #endif
+ #if !defined(NO_EEPROM_BYTE_SUPPORT)
+ else if (Command == AVR109_COMMAND_WriteEEPROM)
+ {
+ /* Read the byte from the endpoint and write it to the EEPROM */
+ eeprom_update_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)), FetchNextCommandByte());
+
+ /* Increment the address after use */
+ CurrAddress += 2;
+
+ /* Send confirmation byte back to the host */
+ WriteNextResponseByte('\r');
+ }
+ else if (Command == AVR109_COMMAND_ReadEEPROM)
+ {
+ /* Read the EEPROM byte and write it to the endpoint */
+ WriteNextResponseByte(eeprom_read_byte((uint8_t*)((intptr_t)(CurrAddress >> 1))));
+
+ /* Increment the address after use */
+ CurrAddress += 2;
+ }
+ #endif
+ else if (Command != AVR109_COMMAND_Sync)
+ {
+ /* Unknown (non-sync) command, return fail code */
+ WriteNextResponseByte('?');
+ }
+
+ /* Select the IN endpoint */
+ Endpoint_SelectEndpoint(CDC_TX_EPADDR);
+
+ /* Remember if the endpoint is completely full before clearing it */
+ bool IsEndpointFull = !(Endpoint_IsReadWriteAllowed());
+
+ /* Send the endpoint data to the host */
+ Endpoint_ClearIN();
+
+ /* If a full endpoint's worth of data was sent, we need to send an empty packet afterwards to signal end of transfer */
+ if (IsEndpointFull)
+ {
+ while (!(Endpoint_IsINReady()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+
+ Endpoint_ClearIN();
+ }
+
+ /* Wait until the data has been sent to the host */
+ while (!(Endpoint_IsINReady()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+
+ /* Select the OUT endpoint */
+ Endpoint_SelectEndpoint(CDC_RX_EPADDR);
+
+ /* Acknowledge the command from the host */
+ Endpoint_ClearOUT();
+}
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/BootloaderCDC.h b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/BootloaderCDC.h
new file mode 100644
index 000000000..9b326abc3
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/BootloaderCDC.h
@@ -0,0 +1,144 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Header file for BootloaderCDC.c.
+ */
+
+#ifndef _CDC_H_
+#define _CDC_H_
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <avr/wdt.h>
+ #include <avr/boot.h>
+ #include <avr/eeprom.h>
+ #include <avr/power.h>
+ #include <avr/interrupt.h>
+ #include <stdbool.h>
+
+ #include "Descriptors.h"
+ #include "BootloaderAPI.h"
+ #include "Config/AppConfig.h"
+
+ #include <LUFA/Drivers/USB/USB.h>
+ #include <LUFA/Drivers/Board/LEDs.h>
+ #include <LUFA/Platform/Platform.h>
+
+ /* Preprocessor Checks: */
+ #if !defined(__OPTIMIZE_SIZE__)
+ #error This bootloader requires that it be optimized for size, not speed, to fit into the target device. Change optimization settings and try again.
+ #endif
+
+ /* Macros: */
+ /** Version major of the CDC bootloader. */
+ #define BOOTLOADER_VERSION_MAJOR 0x01
+
+ /** Version minor of the CDC bootloader. */
+ #define BOOTLOADER_VERSION_MINOR 0x00
+
+ /** Hardware version major of the CDC bootloader. */
+ #define BOOTLOADER_HWVERSION_MAJOR 0x01
+
+ /** Hardware version minor of the CDC bootloader. */
+ #define BOOTLOADER_HWVERSION_MINOR 0x00
+
+ /** Eight character bootloader firmware identifier reported to the host when requested. */
+ #define SOFTWARE_IDENTIFIER "LUFACDC"
+
+ /** Magic bootloader key to unlock forced application start mode. */
+ #define MAGIC_BOOT_KEY 0xDC42
+
+ /* Enums: */
+ /** Possible memory types that can be addressed via the bootloader. */
+ enum AVR109_Memories
+ {
+ MEMORY_TYPE_FLASH = 'F',
+ MEMORY_TYPE_EEPROM = 'E',
+ };
+
+ /** Possible commands that can be issued to the bootloader. */
+ enum AVR109_Commands
+ {
+ AVR109_COMMAND_Sync = 27,
+ AVR109_COMMAND_ReadEEPROM = 'd',
+ AVR109_COMMAND_WriteEEPROM = 'D',
+ AVR109_COMMAND_ReadFLASHWord = 'R',
+ AVR109_COMMAND_WriteFlashPage = 'm',
+ AVR109_COMMAND_FillFlashPageWordLow = 'c',
+ AVR109_COMMAND_FillFlashPageWordHigh = 'C',
+ AVR109_COMMAND_GetBlockWriteSupport = 'b',
+ AVR109_COMMAND_BlockWrite = 'B',
+ AVR109_COMMAND_BlockRead = 'g',
+ AVR109_COMMAND_ReadExtendedFuses = 'Q',
+ AVR109_COMMAND_ReadHighFuses = 'N',
+ AVR109_COMMAND_ReadLowFuses = 'F',
+ AVR109_COMMAND_ReadLockbits = 'r',
+ AVR109_COMMAND_WriteLockbits = 'l',
+ AVR109_COMMAND_EraseFLASH = 'e',
+ AVR109_COMMAND_ReadSignature = 's',
+ AVR109_COMMAND_ReadBootloaderSWVersion = 'V',
+ AVR109_COMMAND_ReadBootloaderHWVersion = 'v',
+ AVR109_COMMAND_ReadBootloaderIdentifier = 'S',
+ AVR109_COMMAND_ReadBootloaderInterface = 'p',
+ AVR109_COMMAND_SetCurrentAddress = 'A',
+ AVR109_COMMAND_ReadAutoAddressIncrement = 'a',
+ AVR109_COMMAND_ReadPartCode = 't',
+ AVR109_COMMAND_EnterProgrammingMode = 'P',
+ AVR109_COMMAND_LeaveProgrammingMode = 'L',
+ AVR109_COMMAND_SelectDeviceType = 'T',
+ AVR109_COMMAND_SetLED = 'x',
+ AVR109_COMMAND_ClearLED = 'y',
+ AVR109_COMMAND_ExitBootloader = 'E',
+ };
+
+ /* Type Defines: */
+ /** Type define for a non-returning pointer to the start of the loaded application in flash memory. */
+ typedef void (*AppPtr_t)(void) ATTR_NO_RETURN;
+
+ /* Function Prototypes: */
+ static void CDC_Task(void);
+ static void SetupHardware(void);
+
+ void Application_Jump_Check(void) ATTR_INIT_SECTION(3);
+
+ void EVENT_USB_Device_ConfigurationChanged(void);
+
+ #if defined(INCLUDE_FROM_BOOTLOADERCDC_C) || defined(__DOXYGEN__)
+ #if !defined(NO_BLOCK_SUPPORT)
+ static void ReadWriteMemoryBlock(const uint8_t Command);
+ #endif
+ static uint8_t FetchNextCommandByte(void);
+ static void WriteNextResponseByte(const uint8_t Response);
+ #endif
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/BootloaderCDC.txt b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/BootloaderCDC.txt
new file mode 100644
index 000000000..55e5e55a4
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/BootloaderCDC.txt
@@ -0,0 +1,240 @@
+/** \file
+ *
+ * This file contains special DoxyGen information for the generation of the main page and other special
+ * documentation pages. It is not a project source file.
+ */
+
+/** \mainpage CDC Class USB AVR Bootloader
+ *
+ * \section Sec_Compat Demo Compatibility:
+ *
+ * The following list indicates what microcontrollers are compatible with this demo.
+ *
+ * \li Series 7 USB AVRs (AT90USBxxx7)
+ * \li Series 6 USB AVRs (AT90USBxxx6)
+ * \li Series 4 USB AVRs (ATMEGAxxU4)
+ * \li Series 2 USB AVRs (AT90USBxx2, ATMEGAxxU2)
+ *
+ * \section Sec_Info USB Information:
+ *
+ * The following table gives a rundown of the USB utilization of this demo.
+ *
+ * <table>
+ * <tr>
+ * <td><b>USB Mode:</b></td>
+ * <td>Device</td>
+ * </tr>
+ * <tr>
+ * <td><b>USB Class:</b></td>
+ * <td>Communications Device Class (CDC)</td>
+ * </tr>
+ * <tr>
+ * <td><b>USB Subclass:</b></td>
+ * <td>Abstract Control Model (ACM)</td>
+ * </tr>
+ * <tr>
+ * <td><b>Relevant Standards:</b></td>
+ * <td>USBIF CDC Class Standard</td>
+ * </tr>
+ * <tr>
+ * <td><b>Supported USB Speeds:</b></td>
+ * <td>Full Speed Mode</td>
+ * </tr>
+ * </table>
+ *
+ * \section Sec_Description Project Description:
+ *
+ * This bootloader enumerates to the host as a CDC Class device (virtual serial port), allowing for AVR109
+ * protocol compatible programming software to load firmware onto the AVR.
+ *
+ * Out of the box this bootloader builds for the AT90USB1287 with an 8KB bootloader section size, and will fit
+ * into 4KB of bootloader space. If you wish to alter this size and/or change the AVR model, you will need to
+ * edit the MCU, FLASH_SIZE_KB and BOOT_SECTION_SIZE_KB values in the accompanying makefile.
+ *
+ * When the bootloader is running, the board's LED(s) will flash at regular intervals to distinguish the
+ * bootloader from the normal user application.
+ *
+ * \warning <b>THIS BOOTLOADER IS NOT SECURE.</b> Malicious entities can recover written data, even if the device
+ * lockbits are set.
+ *
+ * \section Sec_Running Running the Bootloader
+ *
+ * This bootloader is designed to be started via the HWB mechanism of the USB AVRs; ground the HWB pin (see device
+ * datasheet) then momentarily ground /RESET to start the bootloader. This assumes the HWBE fuse is set and the BOOTRST
+ * fuse is cleared.
+ *
+ * For board specific exceptions to the above, see below.
+ *
+ * \subsection SSec_XPLAIN Atmel Xplain Board
+ * Ground the USB AVR JTAG's \c TCK pin to ground when powering on the board to start the bootloader. This assumes the
+ * \c HWBE fuse is cleared and the \c BOOTRST fuse is set as the HWBE pin is not user accessible on this board.
+ *
+ * \subsection SSec_Leonardo Arduino Leonardo Board
+ * Ground \c IO13 when powering the board to start the bootloader. This assumes the \c HWBE fuse is cleared and the
+ * \c BOOTRST fuse is set as the HWBE pin is not user accessible on this board.
+ *
+ * \section Sec_Installation Driver Installation
+ *
+ * After running this bootloader for the first time on a new computer, you will need to supply the .INF
+ * file located in this bootloader project's directory as the device's driver when running under Windows.
+ * This will enable Windows to use its inbuilt CDC drivers, negating the need for custom drivers for the
+ * device. Other Operating Systems should automatically use their own inbuilt CDC-ACM drivers.
+ *
+ * \section Sec_HostApp Host Controller Application
+ *
+ * This bootloader is compatible with the open source application AVRDUDE, Atmel's AVRPROG, or other
+ * applications implementing the AVR109 protocol, which is documented on the Atmel website as an application
+ * note.
+ *
+ * \subsection SSec_AVRDude AVRDUDE (Windows, Mac, Linux)
+ *
+ * AVRDude is a free, cross-platform and open source command line programmer for Atmel and third party AVR
+ * programmers. It is available on the the Windows platform as part of the "WinAVR" package, or on other systems
+ * either from a build from the official source code, or in many distributions as a precompiled binary package.
+ *
+ * To load a new HEX file with AVRDude, specify "AVR109" as the programmer, with the allocated COM port. On Windows
+ * platforms this will be a COMx port name:
+ * \code
+ * avrdude -c AVR109 -p at90usb1287 -P COM0 -U flash:w:Mouse.hex
+ * \endcode
+ *
+ * On Linux systems, this will typically be a /dev/ttyACMx port name:
+ * \code
+ * avrdude -c AVR109 -p at90usb1287 -P /dev/ttyACM0 -U flash:w:Mouse.hex
+ * \endcode
+ *
+ * Refer to the AVRDude project documentation for additional usage instructions.
+ *
+ * \section Sec_API User Application API
+ *
+ * Several user application functions for FLASH and other special memory area manipulations are exposed by the bootloader,
+ * allowing the user application to call into the bootloader at runtime to read and write FLASH data.
+ *
+ * By default, the bootloader API jump table is located 32 bytes from the end of the device's FLASH memory, and follows the
+ * following layout:
+ *
+ * \code
+ * #define BOOTLOADER_API_TABLE_SIZE 32
+ * #define BOOTLOADER_API_TABLE_START ((FLASHEND + 1UL) - BOOTLOADER_API_TABLE_SIZE)
+ * #define BOOTLOADER_API_CALL(Index) (void*)((BOOTLOADER_API_TABLE_START + (Index * 2)) / 2)
+ *
+ * void (*BootloaderAPI_ErasePage)(uint32_t Address) = BOOTLOADER_API_CALL(0);
+ * void (*BootloaderAPI_WritePage)(uint32_t Address) = BOOTLOADER_API_CALL(1);
+ * void (*BootloaderAPI_FillWord)(uint32_t Address, uint16_t Word) = BOOTLOADER_API_CALL(2);
+ * uint8_t (*BootloaderAPI_ReadSignature)(uint16_t Address) = BOOTLOADER_API_CALL(3);
+ * uint8_t (*BootloaderAPI_ReadFuse)(uint16_t Address) = BOOTLOADER_API_CALL(4);
+ * uint8_t (*BootloaderAPI_ReadLock)(void) = BOOTLOADER_API_CALL(5);
+ * void (*BootloaderAPI_WriteLock)(uint8_t LockBits) = BOOTLOADER_API_CALL(6);
+ *
+ * #define BOOTLOADER_MAGIC_SIGNATURE_START (BOOTLOADER_API_TABLE_START + (BOOTLOADER_API_TABLE_SIZE - 2))
+ * #define BOOTLOADER_MAGIC_SIGNATURE 0xDCFB
+ *
+ * #define BOOTLOADER_CLASS_SIGNATURE_START (BOOTLOADER_API_TABLE_START + (BOOTLOADER_API_TABLE_SIZE - 4))
+ * #define BOOTLOADER_CDC_SIGNATURE 0xDF00
+ *
+ * #define BOOTLOADER_ADDRESS_START (BOOTLOADER_API_TABLE_START + (BOOTLOADER_API_TABLE_SIZE - 8))
+ * #define BOOTLOADER_ADDRESS_LENGTH 4
+ * \endcode
+ *
+ * From the application the API support of the bootloader can be detected by reading the FLASH memory bytes located at address
+ * \c BOOTLOADER_MAGIC_SIGNATURE_START and comparing them to the value \c BOOTLOADER_MAGIC_SIGNATURE. The class of bootloader
+ * can be determined by reading the FLASH memory bytes located at address \c BOOTLOADER_CLASS_SIGNATURE_START and comparing them
+ * to the value \c BOOTLOADER_CDC_SIGNATURE. The start address of the bootloader can be retrieved by reading the bytes of FLASH
+ * memory starting from address \c BOOTLOADER_ADDRESS_START.
+ *
+ * \subsection SSec_API_MemLayout Device Memory Map
+ * The following illustration indicates the final memory map of the device when loaded with the bootloader.
+ *
+ * \verbatim
+ * +----------------------------+ 0x0000
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | User Application |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * +----------------------------+ FLASHEND - BOOT_SECTION_SIZE
+ * | |
+ * | Bootloader Application |
+ * | (Not User App. Accessible) |
+ * | |
+ * +----------------------------+ FLASHEND - 96
+ * | API Table Trampolines |
+ * | (Not User App. Accessible) |
+ * +----------------------------+ FLASHEND - 32
+ * | Bootloader API Table |
+ * | (User App. Accessible) |
+ * +----------------------------+ FLASHEND - 8
+ * | Bootloader ID Constants |
+ * | (User App. Accessible) |
+ * +----------------------------+ FLASHEND
+ * \endverbatim
+ *
+ * \section Sec_KnownIssues Known Issues:
+ *
+ * \par On Linux machines, the CDC bootloader is unstable or inaccessible.
+ * A change to the \c ModemManager module in many Linux distributions causes
+ * this module to try to take control over inserted CDC devices, corrupting the
+ * datastream. A UDEV rule is required to prevent this.
+ * See <a href=https://groups.google.com/d/msg/lufa-support/CP9cy2bc8yo/kBqsOu-RBeMJ>here</a> for resolution steps.
+ * If the issue still persists then uninstall modemmanager by executing <tt>sudo apt-get remove modemmanager</tt>, or
+ * the equivalent using your chosen distribution's package manager.
+ *
+ * \par On Linux machines, the CDC bootloader is inaccessible.
+ * On many Linux systems, non-root users do not have automatic access to newly
+ * inserted CDC devices. Root privileges or a UDEV rule is required to gain
+ * access.
+ * See <a href=https://groups.google.com/d/msg/lufa-support/CP9cy2bc8yo/kBqsOu-RBeMJ>here</a> for resolution steps.
+ *
+ * \par After loading an application, it is not run automatically on startup.
+ * Some USB AVR boards ship with the BOOTRST fuse set, causing the bootloader
+ * to run automatically when the device is reset. In most cases, the BOOTRST
+ * fuse should be disabled and the HWBE fuse used instead to run the bootloader
+ * when needed.
+ *
+ * \section Sec_Options Project Options
+ *
+ * The following defines can be found in this demo, which can control the demo behaviour when defined, or changed in value.
+ *
+ * <table>
+ * <tr>
+ * <th><b>Define Name:</b></th>
+ * <th><b>Location:</b></th>
+ * <th><b>Description:</b></th>
+ * </tr>
+ * <tr>
+ * <td>NO_BLOCK_SUPPORT</td>
+ * <td>AppConfig.h</td>
+ * <td>Define to disable memory block read/write support in the bootloader, requiring all reads and writes to be made
+ * using the byte-level commands.</td>
+ * </tr>
+ * <tr>
+ * <td>NO_EEPROM_BYTE_SUPPORT</td>
+ * <td>AppConfig.h</td>
+ * <td>Define to disable EEPROM memory byte read/write support in the bootloader, requiring all EEPROM reads and writes
+ * to be made using the block-level commands.</td>
+ * </tr>
+ * <tr>
+ * <td>NO_FLASH_BYTE_SUPPORT</td>
+ * <td>AppConfig.h</td>
+ * <td>Define to disable FLASH memory byte read/write support in the bootloader, requiring all FLASH reads and writes
+ * to be made using the block-level commands.</td>
+ * </tr>
+ * <tr>
+ * <td>NO_LOCK_BYTE_WRITE_SUPPORT</td>
+ * <td>AppConfig.h</td>
+ * <td>Define to disable lock byte write support in the bootloader, preventing the lock bits from being set programmatically.</td>
+ * </tr>
+ * </table>
+ */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/Config/AppConfig.h b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/Config/AppConfig.h
new file mode 100644
index 000000000..bbb5cb227
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/Config/AppConfig.h
@@ -0,0 +1,50 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Application Configuration Header File
+ *
+ * This is a header file which is be used to configure LUFA's
+ * compile time options, as an alternative to the compile time
+ * constants supplied through a makefile.
+ *
+ * For information on what each token does, refer to the
+ * \ref Sec_Options section of the application documentation.
+ */
+
+#ifndef _APP_CONFIG_H_
+#define _APP_CONFIG_H_
+
+// #define NO_BLOCK_SUPPORT
+// #define NO_EEPROM_BYTE_SUPPORT
+// #define NO_FLASH_BYTE_SUPPORT
+// #define NO_LOCK_BYTE_WRITE_SUPPORT
+
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/Config/LUFAConfig.h b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/Config/LUFAConfig.h
new file mode 100644
index 000000000..af2dd3060
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/Config/LUFAConfig.h
@@ -0,0 +1,93 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief LUFA Library Configuration Header File
+ *
+ * This header file is used to configure LUFA's compile time options,
+ * as an alternative to the compile time constants supplied through
+ * a makefile.
+ *
+ * For information on what each token does, refer to the LUFA
+ * manual section "Summary of Compile Tokens".
+ */
+
+#ifndef _LUFA_CONFIG_H_
+#define _LUFA_CONFIG_H_
+
+ #if (ARCH == ARCH_AVR8)
+
+ /* Non-USB Related Configuration Tokens: */
+// #define DISABLE_TERMINAL_CODES
+
+ /* USB Class Driver Related Tokens: */
+// #define HID_HOST_BOOT_PROTOCOL_ONLY
+// #define HID_STATETABLE_STACK_DEPTH {Insert Value Here}
+// #define HID_USAGE_STACK_DEPTH {Insert Value Here}
+// #define HID_MAX_COLLECTIONS {Insert Value Here}
+// #define HID_MAX_REPORTITEMS {Insert Value Here}
+// #define HID_MAX_REPORT_IDS {Insert Value Here}
+// #define NO_CLASS_DRIVER_AUTOFLUSH
+
+ /* General USB Driver Related Tokens: */
+ #define ORDERED_EP_CONFIG
+ #define USE_STATIC_OPTIONS (USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)
+ #define USB_DEVICE_ONLY
+// #define USB_HOST_ONLY
+// #define USB_STREAM_TIMEOUT_MS {Insert Value Here}
+// #define NO_LIMITED_CONTROLLER_CONNECT
+ #define NO_SOF_EVENTS
+
+ /* USB Device Mode Driver Related Tokens: */
+ #define USE_RAM_DESCRIPTORS
+// #define USE_FLASH_DESCRIPTORS
+// #define USE_EEPROM_DESCRIPTORS
+ #define NO_INTERNAL_SERIAL
+ #define FIXED_CONTROL_ENDPOINT_SIZE 8
+ #define DEVICE_STATE_AS_GPIOR 0
+ #define FIXED_NUM_CONFIGURATIONS 1
+// #define CONTROL_ONLY_DEVICE
+// #define INTERRUPT_CONTROL_ENDPOINT
+ #define NO_DEVICE_REMOTE_WAKEUP
+ #define NO_DEVICE_SELF_POWER
+
+ /* USB Host Mode Driver Related Tokens: */
+// #define HOST_STATE_AS_GPIOR {Insert Value Here}
+// #define USB_HOST_TIMEOUT_MS {Insert Value Here}
+// #define HOST_DEVICE_SETTLE_DELAY_MS {Insert Value Here}
+// #define NO_AUTO_VBUS_MANAGEMENT
+// #define INVERTED_VBUS_ENABLE_LINE
+
+ #else
+
+ #error Unsupported architecture for this LUFA configuration file.
+
+ #endif
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/Descriptors.c b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/Descriptors.c
new file mode 100644
index 000000000..2ff6b503b
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/Descriptors.c
@@ -0,0 +1,244 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * USB Device Descriptors, for library use when in USB device mode. Descriptors are special
+ * computer-readable structures which the host requests upon device enumeration, to determine
+ * the device's capabilities and functions.
+ */
+
+#include "Descriptors.h"
+
+/** Device descriptor structure. This descriptor, located in SRAM memory, describes the overall
+ * device characteristics, including the supported USB version, control endpoint size and the
+ * number of device configurations. The descriptor is read out by the USB host when the enumeration
+ * process begins.
+ */
+const USB_Descriptor_Device_t DeviceDescriptor =
+{
+ .Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
+
+ .USBSpecification = VERSION_BCD(1,1,0),
+ .Class = CDC_CSCP_CDCClass,
+ .SubClass = CDC_CSCP_NoSpecificSubclass,
+ .Protocol = CDC_CSCP_NoSpecificProtocol,
+
+ .Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
+
+ .VendorID = 0x03EB,
+ .ProductID = 0x204A,
+ .ReleaseNumber = VERSION_BCD(1,0,0),
+
+ .ManufacturerStrIndex = STRING_ID_Manufacturer,
+ .ProductStrIndex = STRING_ID_Product,
+ .SerialNumStrIndex = NO_DESCRIPTOR,
+
+ .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
+};
+
+/** Configuration descriptor structure. This descriptor, located in SRAM memory, describes the usage
+ * of the device in one of its supported configurations, including information about any device interfaces
+ * and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting
+ * a configuration so that the host may correctly communicate with the USB device.
+ */
+const USB_Descriptor_Configuration_t ConfigurationDescriptor =
+{
+ .Config =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration},
+
+ .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
+ .TotalInterfaces = 2,
+
+ .ConfigurationNumber = 1,
+ .ConfigurationStrIndex = NO_DESCRIPTOR,
+
+ .ConfigAttributes = USB_CONFIG_ATTR_RESERVED,
+
+ .MaxPowerConsumption = USB_CONFIG_POWER_MA(100)
+ },
+
+ .CDC_CCI_Interface =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
+
+ .InterfaceNumber = INTERFACE_ID_CDC_CCI,
+ .AlternateSetting = 0,
+
+ .TotalEndpoints = 1,
+
+ .Class = CDC_CSCP_CDCClass,
+ .SubClass = CDC_CSCP_ACMSubclass,
+ .Protocol = CDC_CSCP_ATCommandProtocol,
+
+ .InterfaceStrIndex = NO_DESCRIPTOR
+ },
+
+ .CDC_Functional_Header =
+ {
+ .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalHeader_t), .Type = DTYPE_CSInterface},
+ .Subtype = 0x00,
+
+ .CDCSpecification = VERSION_BCD(1,1,0),
+ },
+
+ .CDC_Functional_ACM =
+ {
+ .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalACM_t), .Type = DTYPE_CSInterface},
+ .Subtype = 0x02,
+
+ .Capabilities = 0x02,
+ },
+
+ .CDC_Functional_Union =
+ {
+ .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalUnion_t), .Type = DTYPE_CSInterface},
+ .Subtype = 0x06,
+
+ .MasterInterfaceNumber = INTERFACE_ID_CDC_CCI,
+ .SlaveInterfaceNumber = INTERFACE_ID_CDC_DCI,
+ },
+
+ .CDC_NotificationEndpoint =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
+
+ .EndpointAddress = CDC_NOTIFICATION_EPADDR,
+ .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
+ .EndpointSize = CDC_NOTIFICATION_EPSIZE,
+ .PollingIntervalMS = 0xFF
+ },
+
+ .CDC_DCI_Interface =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
+
+ .InterfaceNumber = INTERFACE_ID_CDC_DCI,
+ .AlternateSetting = 0,
+
+ .TotalEndpoints = 2,
+
+ .Class = CDC_CSCP_CDCDataClass,
+ .SubClass = CDC_CSCP_NoDataSubclass,
+ .Protocol = CDC_CSCP_NoDataProtocol,
+
+ .InterfaceStrIndex = NO_DESCRIPTOR
+ },
+
+ .CDC_DataOutEndpoint =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
+
+ .EndpointAddress = CDC_RX_EPADDR,
+ .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
+ .EndpointSize = CDC_TXRX_EPSIZE,
+ .PollingIntervalMS = 0x05
+ },
+
+ .CDC_DataInEndpoint =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
+
+ .EndpointAddress = CDC_TX_EPADDR,
+ .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
+ .EndpointSize = CDC_TXRX_EPSIZE,
+ .PollingIntervalMS = 0x05
+ }
+};
+
+/** Language descriptor structure. This descriptor, located in SRAM memory, is returned when the host requests
+ * the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which indicate
+ * via the language ID table available at USB.org what languages the device supports for its string descriptors.
+ */
+const USB_Descriptor_String_t LanguageString = USB_STRING_DESCRIPTOR_ARRAY(LANGUAGE_ID_ENG);
+
+/** Manufacturer descriptor string. This is a Unicode string containing the manufacturer's details in human readable
+ * form, and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
+ * Descriptor.
+ */
+const USB_Descriptor_String_t ManufacturerString = USB_STRING_DESCRIPTOR(L"Dean Camera");
+
+/** Product descriptor string. This is a Unicode string containing the product's details in human readable form,
+ * and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
+ * Descriptor.
+ */
+const USB_Descriptor_String_t ProductString = USB_STRING_DESCRIPTOR(L"LUFA CDC");
+
+/** This function is called by the library when in device mode, and must be overridden (see LUFA library "USB Descriptors"
+ * documentation) by the application code so that the address and size of a requested descriptor can be given
+ * to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function
+ * is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the
+ * USB host.
+ */
+uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+ const uint8_t wIndex,
+ const void** const DescriptorAddress)
+{
+ const uint8_t DescriptorType = (wValue >> 8);
+ const uint8_t DescriptorNumber = (wValue & 0xFF);
+
+ const void* Address = NULL;
+ uint16_t Size = NO_DESCRIPTOR;
+
+ switch (DescriptorType)
+ {
+ case DTYPE_Device:
+ Address = &DeviceDescriptor;
+ Size = sizeof(USB_Descriptor_Device_t);
+ break;
+ case DTYPE_Configuration:
+ Address = &ConfigurationDescriptor;
+ Size = sizeof(USB_Descriptor_Configuration_t);
+ break;
+ case DTYPE_String:
+ if (DescriptorNumber == STRING_ID_Language)
+ {
+ Address = &LanguageString;
+ Size = LanguageString.Header.Size;
+ }
+ else if (DescriptorNumber == STRING_ID_Manufacturer)
+ {
+ Address = &ManufacturerString;
+ Size = ManufacturerString.Header.Size;
+ }
+ else if (DescriptorNumber == STRING_ID_Product)
+ {
+ Address = &ProductString;
+ Size = ProductString.Header.Size;
+ }
+
+ break;
+ }
+
+ *DescriptorAddress = Address;
+ return Size;
+}
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/Descriptors.h b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/Descriptors.h
new file mode 100644
index 000000000..ef0437917
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/Descriptors.h
@@ -0,0 +1,158 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Header file for Descriptors.c.
+ */
+
+#ifndef _DESCRIPTORS_H_
+#define _DESCRIPTORS_H_
+
+ /* Includes: */
+ #include <LUFA/Drivers/USB/USB.h>
+
+ #include "Config/AppConfig.h"
+
+ /* Macros: */
+ #if defined(__AVR_AT90USB1287__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x97
+ #define AVR_SIGNATURE_3 0x82
+ #elif defined(__AVR_AT90USB647__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x96
+ #define AVR_SIGNATURE_3 0x82
+ #elif defined(__AVR_AT90USB1286__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x97
+ #define AVR_SIGNATURE_3 0x82
+ #elif defined(__AVR_AT90USB646__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x96
+ #define AVR_SIGNATURE_3 0x82
+ #elif defined(__AVR_ATmega32U4__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x95
+ #define AVR_SIGNATURE_3 0x87
+ #elif defined(__AVR_ATmega16U4__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x94
+ #define AVR_SIGNATURE_3 0x88
+ #elif defined(__AVR_ATmega32U2__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x95
+ #define AVR_SIGNATURE_3 0x8A
+ #elif defined(__AVR_ATmega16U2__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x94
+ #define AVR_SIGNATURE_3 0x89
+ #elif defined(__AVR_AT90USB162__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x94
+ #define AVR_SIGNATURE_3 0x82
+ #elif defined(__AVR_ATmega8U2__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x93
+ #define AVR_SIGNATURE_3 0x89
+ #elif defined(__AVR_AT90USB82__)
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x94
+ #define AVR_SIGNATURE_3 0x82
+ #else
+ #error The selected AVR part is not currently supported by this bootloader.
+ #endif
+
+ /** Endpoint address for the CDC control interface event notification endpoint. */
+ #define CDC_NOTIFICATION_EPADDR (ENDPOINT_DIR_IN | 2)
+
+ /** Endpoint address for the CDC data interface TX (data IN) endpoint. */
+ #define CDC_TX_EPADDR (ENDPOINT_DIR_IN | 3)
+
+ /** Endpoint address for the CDC data interface RX (data OUT) endpoint. */
+ #define CDC_RX_EPADDR (ENDPOINT_DIR_OUT | 4)
+
+ /** Size of the CDC data interface TX and RX data endpoint banks, in bytes. */
+ #define CDC_TXRX_EPSIZE 16
+
+ /** Size of the CDC control interface notification endpoint bank, in bytes. */
+ #define CDC_NOTIFICATION_EPSIZE 8
+
+ /* Type Defines: */
+ /** Type define for the device configuration descriptor structure. This must be defined in the
+ * application code, as the configuration descriptor contains several sub-descriptors which
+ * vary between devices, and which describe the device's usage to the host.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Configuration_Header_t Config;
+
+ // CDC Control Interface
+ USB_Descriptor_Interface_t CDC_CCI_Interface;
+ USB_CDC_Descriptor_FunctionalHeader_t CDC_Functional_Header;
+ USB_CDC_Descriptor_FunctionalACM_t CDC_Functional_ACM;
+ USB_CDC_Descriptor_FunctionalUnion_t CDC_Functional_Union;
+ USB_Descriptor_Endpoint_t CDC_NotificationEndpoint;
+
+ // CDC Data Interface
+ USB_Descriptor_Interface_t CDC_DCI_Interface;
+ USB_Descriptor_Endpoint_t CDC_DataOutEndpoint;
+ USB_Descriptor_Endpoint_t CDC_DataInEndpoint;
+ } USB_Descriptor_Configuration_t;
+
+ /** Enum for the device interface descriptor IDs within the device. Each interface descriptor
+ * should have a unique ID index associated with it, which can be used to refer to the
+ * interface from other descriptors.
+ */
+ enum InterfaceDescriptors_t
+ {
+ INTERFACE_ID_CDC_CCI = 0, /**< CDC CCI interface descriptor ID */
+ INTERFACE_ID_CDC_DCI = 1, /**< CDC DCI interface descriptor ID */
+ };
+
+ /** Enum for the device string descriptor IDs within the device. Each string descriptor should
+ * have a unique ID index associated with it, which can be used to refer to the string from
+ * other descriptors.
+ */
+ enum StringDescriptors_t
+ {
+ STRING_ID_Language = 0, /**< Supported Languages string descriptor ID (must be zero) */
+ STRING_ID_Manufacturer = 1, /**< Manufacturer string ID */
+ STRING_ID_Product = 2, /**< Product string ID */
+ };
+
+ /* Function Prototypes: */
+ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+ const uint8_t wIndex,
+ const void** const DescriptorAddress)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/LUFA CDC Bootloader.inf b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/LUFA CDC Bootloader.inf
new file mode 100644
index 000000000..61624c731
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/LUFA CDC Bootloader.inf
@@ -0,0 +1,66 @@
+;************************************************************
+; Windows USB CDC ACM Setup File
+; Copyright (c) 2000 Microsoft Corporation
+;************************************************************
+
+[DefaultInstall]
+CopyINF="LUFA CDC Bootloader.inf"
+
+[Version]
+Signature="$Windows NT$"
+Class=Ports
+ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318}
+Provider=%MFGNAME%
+DriverVer=7/1/2012,10.0.0.0
+
+[Manufacturer]
+%MFGNAME%=DeviceList, NTx86, NTamd64, NTia64
+
+[SourceDisksNames]
+
+[SourceDisksFiles]
+
+[DestinationDirs]
+DefaultDestDir=12
+
+[DriverInstall]
+Include=mdmcpq.inf
+CopyFiles=FakeModemCopyFileSection
+AddReg=DriverInstall.AddReg
+
+[DriverInstall.Services]
+Include=mdmcpq.inf
+AddService=usbser, 0x00000002, LowerFilter_Service_Inst
+
+[DriverInstall.AddReg]
+HKR,,EnumPropPages32,,"msports.dll,SerialPortPropPageProvider"
+
+;------------------------------------------------------------------------------
+; Vendor and Product ID Definitions
+;------------------------------------------------------------------------------
+; When developing your USB device, the VID and PID used in the PC side
+; application program and the firmware on the microcontroller must match.
+; Modify the below line to use your VID and PID. Use the format as shown below.
+; Note: One INF file can be used for multiple devices with different VID and PIDs.
+; For each supported device, append ",USB\VID_xxxx&PID_yyyy" to the end of the line.
+;------------------------------------------------------------------------------
+[DeviceList]
+%DESCRIPTION%=DriverInstall, USB\VID_03EB&PID_204A
+
+[DeviceList.NTx86]
+%DESCRIPTION%=DriverInstall, USB\VID_03EB&PID_204A
+
+[DeviceList.NTamd64]
+%DESCRIPTION%=DriverInstall, USB\VID_03EB&PID_204A
+
+[DeviceList.NTia64]
+%DESCRIPTION%=DriverInstall, USB\VID_03EB&PID_204A
+
+;------------------------------------------------------------------------------
+; String Definitions
+;------------------------------------------------------------------------------
+;Modify these strings to customize your device
+;------------------------------------------------------------------------------
+[Strings]
+MFGNAME="http://www.lufa-lib.org"
+DESCRIPTION="LUFA CDC Class Bootloader"
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/asf.xml b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/asf.xml
new file mode 100644
index 000000000..72f3ff04c
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/asf.xml
@@ -0,0 +1,161 @@
+<asf xmlversion="1.0">
+ <project caption="CDC Bootloader - 128KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.cdc.avr8.128_4" force-caption="true" workspace-name="lufa_cdc_128kb_4kb_">
+ <require idref="lufa.bootloaders.cdc"/>
+ <require idref="lufa.boards.dummy.avr8"/>
+ <generator value="as5_8"/>
+
+ <device-support value="at90usb1287"/>
+ <config name="lufa.drivers.board.name" value="none"/>
+
+ <config name="config.compiler.optimization.level" value="size"/>
+
+ <build type="define" name="F_CPU" value="16000000UL"/>
+ <build type="define" name="F_USB" value="16000000UL"/>
+
+ <build type="define" name="BOOT_START_ADDR" value="0x1F000"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.text=0x1F000"/>
+
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x1FFA0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x1FFE0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x1FFF8"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
+ </project>
+
+ <project caption="CDC Bootloader - 64KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.cdc.avr8.64_4" force-caption="true" workspace-name="lufa_cdc_64kb_4kb_">
+ <require idref="lufa.bootloaders.cdc"/>
+ <require idref="lufa.boards.dummy.avr8"/>
+ <generator value="as5_8"/>
+
+ <device-support value="at90usb647"/>
+ <config name="lufa.drivers.board.name" value="none"/>
+
+ <config name="config.compiler.optimization.level" value="size"/>
+
+ <build type="define" name="F_CPU" value="16000000UL"/>
+ <build type="define" name="F_USB" value="16000000UL"/>
+
+ <build type="define" name="BOOT_START_ADDR" value="0xF000"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.text=0xF000"/>
+
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0xFFA0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0xFFE0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0xFFF8"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
+ </project>
+
+ <project caption="CDC Bootloader - 32KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.cdc.avr8.32_4" force-caption="true" workspace-name="lufa_cdc_32kb_4kb_">
+ <require idref="lufa.bootloaders.cdc"/>
+ <require idref="lufa.boards.dummy.avr8"/>
+ <generator value="as5_8"/>
+
+ <device-support value="atmega32u4"/>
+ <config name="lufa.drivers.board.name" value="none"/>
+
+ <config name="config.compiler.optimization.level" value="size"/>
+
+ <build type="define" name="F_CPU" value="16000000UL"/>
+ <build type="define" name="F_USB" value="16000000UL"/>
+
+ <build type="define" name="BOOT_START_ADDR" value="0x7000"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.text=0x7000"/>
+
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x7FA0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x7FE0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x7FF8"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
+ </project>
+
+ <project caption="CDC Bootloader - 16KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.cdc.avr8.16_4" force-caption="true" workspace-name="lufa_cdc_16kb_4kb_">
+ <require idref="lufa.bootloaders.cdc"/>
+ <require idref="lufa.boards.dummy.avr8"/>
+ <generator value="as5_8"/>
+
+ <device-support value="atmega16u2"/>
+ <config name="lufa.drivers.board.name" value="none"/>
+
+ <config name="config.compiler.optimization.level" value="size"/>
+
+ <build type="define" name="F_CPU" value="16000000UL"/>
+ <build type="define" name="F_USB" value="16000000UL"/>
+
+ <build type="define" name="BOOT_START_ADDR" value="0x3000"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.text=0x3000"/>
+
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x3FA0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x3FE0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x3FF8"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
+ </project>
+
+ <project caption="CDC Bootloader - 8KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.cdc.avr8.8_4" force-caption="true" workspace-name="lufa_cdc_8kb_4kb_">
+ <require idref="lufa.bootloaders.cdc"/>
+ <require idref="lufa.boards.dummy.avr8"/>
+ <generator value="as5_8"/>
+
+ <device-support value="atmega8u2"/>
+ <config name="lufa.drivers.board.name" value="none"/>
+
+ <config name="config.compiler.optimization.level" value="size"/>
+
+ <build type="define" name="F_CPU" value="16000000UL"/>
+ <build type="define" name="F_USB" value="16000000UL"/>
+
+ <build type="define" name="BOOT_START_ADDR" value="0x1000"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.text=0x1000"/>
+
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x1FA0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x1FE0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x1FF8"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
+ </project>
+
+ <module type="application" id="lufa.bootloaders.cdc" caption="CDC Bootloader">
+ <info type="description" value="summary">
+ CDC Class Bootloader, capable of reprogramming a device using avrdude or other AVR109 protocol compliant software when plugged into a host.
+ </info>
+
+ <info type="gui-flag" value="move-to-root"/>
+
+ <info type="keyword" value="Technology">
+ <keyword value="Bootloaders"/>
+ <keyword value="USB Device"/>
+ </info>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="include-path" value="."/>
+ <build type="c-source" value="BootloaderCDC.c"/>
+ <build type="header-file" value="BootloaderCDC.h"/>
+ <build type="c-source" value="Descriptors.c"/>
+ <build type="header-file" value="Descriptors.h"/>
+ <build type="c-source" value="BootloaderAPI.c"/>
+ <build type="header-file" value="BootloaderAPI.h"/>
+ <build type="asm-source" value="BootloaderAPITable.S"/>
+
+ <build type="module-config" subtype="path" value="Config"/>
+ <build type="header-file" value="Config/LUFAConfig.h"/>
+ <build type="header-file" value="Config/AppConfig.h"/>
+
+ <build type="distribute" subtype="user-file" value="doxyfile"/>
+ <build type="distribute" subtype="user-file" value="BootloaderCDC.txt"/>
+ <build type="distribute" subtype="user-file" value="LUFA CDC Bootloader.inf"/>
+
+ <require idref="lufa.common"/>
+ <require idref="lufa.platform"/>
+ <require idref="lufa.drivers.usb"/>
+ <require idref="lufa.drivers.board"/>
+ <require idref="lufa.drivers.board.leds"/>
+ </module>
+</asf>
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/doxyfile b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/doxyfile
new file mode 100644
index 000000000..2dfb2a08a
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/doxyfile
@@ -0,0 +1,2365 @@
+# Doxyfile 1.8.8
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME = "LUFA Library - CDC Class Bootloader"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
+# the documentation. The maximum height of the logo should not exceed 55 pixels
+# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
+# to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = ./Documentation/
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES = YES
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
+# new page for each member. If set to NO, the documentation of a member will be
+# part of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
+# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
+# Fortran. In the later case the parser tries to guess whether the code is fixed
+# or free formatted code, this is the default for Fortran type files), VHDL. For
+# instance to make doxygen treat .inc files as Fortran files (default is PHP),
+# and .f files as C (default is Fortran), use: inc=Fortran f=C.
+#
+# Note For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT = NO
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by by putting a % sign in front of the word
+# or globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE = YES
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO these classes will be included in the various overviews. This option has
+# no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
+# todo list. This list is created by putting \todo commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST = NO
+
+# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
+# test list. This list is created by putting \test commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST = NO
+
+# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST = NO
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES the list
+# will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET = YES
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO doxygen will only warn about wrong or incomplete parameter
+# documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces.
+# Note: If this tag is empty the current directory is searched.
+
+INPUT = ./
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank the
+# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
+# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
+# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
+# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
+# *.qsf, *.as and *.js.
+
+FILE_PATTERNS = *.h \
+ *.c \
+ *.txt
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE = Documentation/
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS = __* \
+ INCLUDE_FROM_*
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER ) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = NO
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS = NO
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the
+# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
+# cost of reduced performance. This can be particularly helpful with template
+# rich C++ code for which doxygen's built-in parser lacks the necessary type
+# information.
+# Note: The availability of this option depends on whether or not doxygen was
+# compiled with the --with-libclang option.
+# The default value is: NO.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_OPTIONS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefor more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra stylesheet files is of importance (e.g. the last
+# stylesheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the stylesheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP = NO
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS = YES
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated (
+# YES) or that it should be included in the master .chm file ( NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated (
+# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND = YES
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX = YES
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW = YES
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE = 1
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. To get the times font for
+# instance you can specify
+# EXTRA_PACKAGES=times
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empy string,
+# for the replacement values of the other commands the user is refered to
+# HTML_HEADER.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE = plain
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT = docbook
+
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
+# Definitions (see http://autogen.sf.net) file that captures the structure of
+# the code including all documentation. Note that this feature is still
+# experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
+# in the source code. If set to NO only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF = YES
+
+# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED = __DOXYGEN__ \
+ PROGMEM \
+ ATTR_NO_INIT
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
+# class index. If set to NO only the inherited external classes will be listed.
+# The default value is: NO.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
+# the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS = YES
+
+# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS = NO
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME =
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH = NO
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH = NO
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS = NO
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH = NO
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH = NO
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY = NO
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH = NO
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot.
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif and svg.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+PLANTUML_JAR_PATH =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES = 15
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH = 2
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT = YES
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP = YES
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/makefile b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/makefile
new file mode 100644
index 000000000..161e64c08
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/CDC/makefile
@@ -0,0 +1,55 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2014.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+# --------------------------------------
+# LUFA Project Makefile.
+# --------------------------------------
+
+# Run "make help" for target help.
+
+MCU = at90usb1287
+ARCH = AVR8
+BOARD = USBKEY
+F_CPU = 8000000
+F_USB = $(F_CPU)
+OPTIMIZATION = s
+TARGET = BootloaderCDC
+SRC = $(TARGET).c Descriptors.c BootloaderAPI.c BootloaderAPITable.S $(LUFA_SRC_USB)
+LUFA_PATH = ../../LUFA
+CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -IConfig/ -DBOOT_START_ADDR=$(BOOT_START_OFFSET)
+LD_FLAGS = -Wl,--section-start=.text=$(BOOT_START_OFFSET) $(BOOT_API_LD_FLAGS)
+
+# Flash size and bootloader section sizes of the target, in KB. These must
+# match the target's total FLASH size and the bootloader size set in the
+# device's fuses.
+FLASH_SIZE_KB = 128
+BOOT_SECTION_SIZE_KB = 8
+
+# Bootloader address calculation formulas
+# Do not modify these macros, but rather modify the dependent values above.
+CALC_ADDRESS_IN_HEX = $(shell printf "0x%X" $$(( $(1) )) )
+BOOT_START_OFFSET = $(call CALC_ADDRESS_IN_HEX, ($(FLASH_SIZE_KB) - $(BOOT_SECTION_SIZE_KB)) * 1024 )
+BOOT_SEC_OFFSET = $(call CALC_ADDRESS_IN_HEX, ($(FLASH_SIZE_KB) * 1024) - ($(strip $(1))) )
+
+# Bootloader linker section flags for relocating the API table sections to
+# known FLASH addresses - these should not normally be user-edited.
+BOOT_SECTION_LD_FLAG = -Wl,--section-start=$(strip $(1))=$(call BOOT_SEC_OFFSET, $(3)) -Wl,--undefined=$(strip $(2))
+BOOT_API_LD_FLAGS = $(call BOOT_SECTION_LD_FLAG, .apitable_trampolines, BootloaderAPI_Trampolines, 96)
+BOOT_API_LD_FLAGS += $(call BOOT_SECTION_LD_FLAG, .apitable_jumptable, BootloaderAPI_JumpTable, 32)
+BOOT_API_LD_FLAGS += $(call BOOT_SECTION_LD_FLAG, .apitable_signatures, BootloaderAPI_Signatures, 8)
+
+# Default target
+all:
+
+# Include LUFA build script makefiles
+include $(LUFA_PATH)/Build/lufa_core.mk
+include $(LUFA_PATH)/Build/lufa_sources.mk
+include $(LUFA_PATH)/Build/lufa_build.mk
+include $(LUFA_PATH)/Build/lufa_cppcheck.mk
+include $(LUFA_PATH)/Build/lufa_doxygen.mk
+include $(LUFA_PATH)/Build/lufa_avrdude.mk
+include $(LUFA_PATH)/Build/lufa_atprogram.mk
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/BootloaderAPI.c b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/BootloaderAPI.c
new file mode 100644
index 000000000..cad59c8ca
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/BootloaderAPI.c
@@ -0,0 +1,76 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Bootloader user application API functions.
+ */
+
+#include "BootloaderAPI.h"
+
+void BootloaderAPI_ErasePage(const uint32_t Address)
+{
+ boot_page_erase_safe(Address);
+ boot_spm_busy_wait();
+ boot_rww_enable();
+}
+
+void BootloaderAPI_WritePage(const uint32_t Address)
+{
+ boot_page_write_safe(Address);
+ boot_spm_busy_wait();
+ boot_rww_enable();
+}
+
+void BootloaderAPI_FillWord(const uint32_t Address, const uint16_t Word)
+{
+ boot_page_fill_safe(Address, Word);
+}
+
+uint8_t BootloaderAPI_ReadSignature(const uint16_t Address)
+{
+ return boot_signature_byte_get(Address);
+}
+
+uint8_t BootloaderAPI_ReadFuse(const uint16_t Address)
+{
+ return boot_lock_fuse_bits_get(Address);
+}
+
+uint8_t BootloaderAPI_ReadLock(void)
+{
+ return boot_lock_fuse_bits_get(GET_LOCK_BITS);
+}
+
+void BootloaderAPI_WriteLock(const uint8_t LockBits)
+{
+ boot_lock_bits_set_safe(LockBits);
+}
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/BootloaderAPI.h b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/BootloaderAPI.h
new file mode 100644
index 000000000..2462cacdd
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/BootloaderAPI.h
@@ -0,0 +1,58 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Header file for BootloaderAPI.c.
+ */
+
+#ifndef _BOOTLOADER_API_H_
+#define _BOOTLOADER_API_H_
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <avr/boot.h>
+ #include <stdbool.h>
+
+ #include <LUFA/Common/Common.h>
+
+ #include "Config/AppConfig.h"
+
+ /* Function Prototypes: */
+ void BootloaderAPI_ErasePage(const uint32_t Address);
+ void BootloaderAPI_WritePage(const uint32_t Address);
+ void BootloaderAPI_FillWord(const uint32_t Address, const uint16_t Word);
+ uint8_t BootloaderAPI_ReadSignature(const uint16_t Address);
+ uint8_t BootloaderAPI_ReadFuse(const uint16_t Address);
+ uint8_t BootloaderAPI_ReadLock(void);
+ void BootloaderAPI_WriteLock(const uint8_t LockBits);
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/BootloaderAPITable.S b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/BootloaderAPITable.S
new file mode 100644
index 000000000..101dcbd72
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/BootloaderAPITable.S
@@ -0,0 +1,91 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+; Trampolines to actual API implementations if the target address is outside the
+; range of a rjmp instruction (can happen with large bootloader sections)
+.section .apitable_trampolines, "ax"
+.global BootloaderAPI_Trampolines
+BootloaderAPI_Trampolines:
+
+ BootloaderAPI_ErasePage_Trampoline:
+ jmp BootloaderAPI_ErasePage
+ BootloaderAPI_WritePage_Trampoline:
+ jmp BootloaderAPI_WritePage
+ BootloaderAPI_FillWord_Trampoline:
+ jmp BootloaderAPI_FillWord
+ BootloaderAPI_ReadSignature_Trampoline:
+ jmp BootloaderAPI_ReadSignature
+ BootloaderAPI_ReadFuse_Trampoline:
+ jmp BootloaderAPI_ReadFuse
+ BootloaderAPI_ReadLock_Trampoline:
+ jmp BootloaderAPI_ReadLock
+ BootloaderAPI_WriteLock_Trampoline:
+ jmp BootloaderAPI_WriteLock
+ BootloaderAPI_UNUSED1:
+ ret
+ BootloaderAPI_UNUSED2:
+ ret
+ BootloaderAPI_UNUSED3:
+ ret
+ BootloaderAPI_UNUSED4:
+ ret
+ BootloaderAPI_UNUSED5:
+ ret
+
+
+
+; API function jump table
+.section .apitable_jumptable, "ax"
+.global BootloaderAPI_JumpTable
+BootloaderAPI_JumpTable:
+
+ rjmp BootloaderAPI_ErasePage_Trampoline
+ rjmp BootloaderAPI_WritePage_Trampoline
+ rjmp BootloaderAPI_FillWord_Trampoline
+ rjmp BootloaderAPI_ReadSignature_Trampoline
+ rjmp BootloaderAPI_ReadFuse_Trampoline
+ rjmp BootloaderAPI_ReadLock_Trampoline
+ rjmp BootloaderAPI_WriteLock_Trampoline
+ rjmp BootloaderAPI_UNUSED1 ; UNUSED ENTRY 1
+ rjmp BootloaderAPI_UNUSED2 ; UNUSED ENTRY 2
+ rjmp BootloaderAPI_UNUSED3 ; UNUSED ENTRY 3
+ rjmp BootloaderAPI_UNUSED4 ; UNUSED ENTRY 4
+ rjmp BootloaderAPI_UNUSED5 ; UNUSED ENTRY 5
+
+
+
+; Bootloader table signatures and information
+.section .apitable_signatures, "ax"
+.global BootloaderAPI_Signatures
+BootloaderAPI_Signatures:
+
+ .long BOOT_START_ADDR ; Start address of the bootloader
+ .word 0xDF10 ; Signature for the DFU class bootloader, V1
+ .word 0xDCFB ; Signature for a LUFA class bootloader
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/BootloaderDFU.c b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/BootloaderDFU.c
new file mode 100644
index 000000000..00e673268
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/BootloaderDFU.c
@@ -0,0 +1,804 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Main source file for the DFU class bootloader. This file contains the complete bootloader logic.
+ */
+
+#define INCLUDE_FROM_BOOTLOADER_C
+#include "BootloaderDFU.h"
+
+/** Flag to indicate if the bootloader is currently running in secure mode, disallowing memory operations
+ * other than erase. This is initially set to the value set by SECURE_MODE, and cleared by the bootloader
+ * once a memory erase has completed in a bootloader session.
+ */
+static bool IsSecure = SECURE_MODE;
+
+/** Flag to indicate if the bootloader should be running, or should exit and allow the application code to run
+ * via a soft reset. When cleared, the bootloader will abort, the USB interface will shut down and the application
+ * jumped to via an indirect jump to location 0x0000 (or other location specified by the host).
+ */
+static bool RunBootloader = true;
+
+/** Flag to indicate if the bootloader is waiting to exit. When the host requests the bootloader to exit and
+ * jump to the application address it specifies, it sends two sequential commands which must be properly
+ * acknowledged. Upon reception of the first the RunBootloader flag is cleared and the WaitForExit flag is set,
+ * causing the bootloader to wait for the final exit command before shutting down.
+ */
+static bool WaitForExit = false;
+
+/** Current DFU state machine state, one of the values in the DFU_State_t enum. */
+static uint8_t DFU_State = dfuIDLE;
+
+/** Status code of the last executed DFU command. This is set to one of the values in the DFU_Status_t enum after
+ * each operation, and returned to the host when a Get Status DFU request is issued.
+ */
+static uint8_t DFU_Status = OK;
+
+/** Data containing the DFU command sent from the host. */
+static DFU_Command_t SentCommand;
+
+/** Response to the last issued Read Data DFU command. Unlike other DFU commands, the read command
+ * requires a single byte response from the bootloader containing the read data when the next DFU_UPLOAD command
+ * is issued by the host.
+ */
+static uint8_t ResponseByte;
+
+/** Pointer to the start of the user application. By default this is 0x0000 (the reset vector), however the host
+ * may specify an alternate address when issuing the application soft-start command.
+ */
+static AppPtr_t AppStartPtr = (AppPtr_t)0x0000;
+
+/** 64-bit flash page number. This is concatenated with the current 16-bit address on USB AVRs containing more than
+ * 64KB of flash memory.
+ */
+static uint8_t Flash64KBPage = 0;
+
+/** Memory start address, indicating the current address in the memory being addressed (either FLASH or EEPROM
+ * depending on the issued command from the host).
+ */
+static uint16_t StartAddr = 0x0000;
+
+/** Memory end address, indicating the end address to read from/write to in the memory being addressed (either FLASH
+ * of EEPROM depending on the issued command from the host).
+ */
+static uint16_t EndAddr = 0x0000;
+
+/** Magic lock for forced application start. If the HWBE fuse is programmed and BOOTRST is unprogrammed, the bootloader
+ * will start if the /HWB line of the AVR is held low and the system is reset. However, if the /HWB line is still held
+ * low when the application attempts to start via a watchdog reset, the bootloader will re-start. If set to the value
+ * \ref MAGIC_BOOT_KEY the special init function \ref Application_Jump_Check() will force the application to start.
+ */
+uint16_t MagicBootKey ATTR_NO_INIT;
+
+
+/** Special startup routine to check if the bootloader was started via a watchdog reset, and if the magic application
+ * start key has been loaded into \ref MagicBootKey. If the bootloader started via the watchdog and the key is valid,
+ * this will force the user application to start via a software jump.
+ */
+void Application_Jump_Check(void)
+{
+ bool JumpToApplication = false;
+
+ #if ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
+ /* Disable JTAG debugging */
+ JTAG_DISABLE();
+
+ /* Enable pull-up on the JTAG TCK pin so we can use it to select the mode */
+ PORTF |= (1 << 4);
+ Delay_MS(10);
+
+ /* If the TCK pin is not jumpered to ground, start the user application instead */
+ JumpToApplication |= ((PINF & (1 << 4)) != 0);
+
+ /* Re-enable JTAG debugging */
+ JTAG_ENABLE();
+ #endif
+
+ /* If the reset source was the bootloader and the key is correct, clear it and jump to the application */
+ if ((MCUSR & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY))
+ JumpToApplication |= true;
+
+ /* If a request has been made to jump to the user application, honor it */
+ if (JumpToApplication)
+ {
+ /* Turn off the watchdog */
+ MCUSR &= ~(1<<WDRF);
+ wdt_disable();
+
+ /* Clear the boot key and jump to the user application */
+ MagicBootKey = 0;
+
+ // cppcheck-suppress constStatement
+ ((void (*)(void))0x0000)();
+ }
+}
+
+/** Main program entry point. This routine configures the hardware required by the bootloader, then continuously
+ * runs the bootloader processing routine until instructed to soft-exit, or hard-reset via the watchdog to start
+ * the loaded application code.
+ */
+int main(void)
+{
+ /* Configure hardware required by the bootloader */
+ SetupHardware();
+
+ /* Turn on first LED on the board to indicate that the bootloader has started */
+ LEDs_SetAllLEDs(LEDS_LED1);
+
+ /* Enable global interrupts so that the USB stack can function */
+ GlobalInterruptEnable();
+
+ /* Run the USB management task while the bootloader is supposed to be running */
+ while (RunBootloader || WaitForExit)
+ USB_USBTask();
+
+ /* Reset configured hardware back to their original states for the user application */
+ ResetHardware();
+
+ /* Start the user application */
+ AppStartPtr();
+}
+
+/** Configures all hardware required for the bootloader. */
+static void SetupHardware(void)
+{
+ /* Disable watchdog if enabled by bootloader/fuses */
+ MCUSR &= ~(1 << WDRF);
+ wdt_disable();
+
+ /* Disable clock division */
+ clock_prescale_set(clock_div_1);
+
+ /* Relocate the interrupt vector table to the bootloader section */
+ MCUCR = (1 << IVCE);
+ MCUCR = (1 << IVSEL);
+
+ /* Initialize the USB and other board hardware drivers */
+ USB_Init();
+ LEDs_Init();
+
+ /* Bootloader active LED toggle timer initialization */
+ TIMSK1 = (1 << TOIE1);
+ TCCR1B = ((1 << CS11) | (1 << CS10));
+}
+
+/** Resets all configured hardware required for the bootloader back to their original states. */
+static void ResetHardware(void)
+{
+ /* Shut down the USB and other board hardware drivers */
+ USB_Disable();
+ LEDs_Disable();
+
+ /* Disable Bootloader active LED toggle timer */
+ TIMSK1 = 0;
+ TCCR1B = 0;
+
+ /* Relocate the interrupt vector table back to the application section */
+ MCUCR = (1 << IVCE);
+ MCUCR = 0;
+}
+
+/** ISR to periodically toggle the LEDs on the board to indicate that the bootloader is active. */
+ISR(TIMER1_OVF_vect, ISR_BLOCK)
+{
+ LEDs_ToggleLEDs(LEDS_LED1 | LEDS_LED2);
+}
+
+/** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent to
+ * the device from the USB host before passing along unhandled control requests to the library for processing
+ * internally.
+ */
+void EVENT_USB_Device_ControlRequest(void)
+{
+ /* Ignore any requests that aren't directed to the DFU interface */
+ if ((USB_ControlRequest.bmRequestType & (CONTROL_REQTYPE_TYPE | CONTROL_REQTYPE_RECIPIENT)) !=
+ (REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ return;
+ }
+
+ /* Activity - toggle indicator LEDs */
+ LEDs_ToggleLEDs(LEDS_LED1 | LEDS_LED2);
+
+ /* Get the size of the command and data from the wLength value */
+ SentCommand.DataSize = USB_ControlRequest.wLength;
+
+ switch (USB_ControlRequest.bRequest)
+ {
+ case DFU_REQ_DNLOAD:
+ Endpoint_ClearSETUP();
+
+ /* Check if bootloader is waiting to terminate */
+ if (WaitForExit)
+ {
+ /* Bootloader is terminating - process last received command */
+ ProcessBootloaderCommand();
+
+ /* Indicate that the last command has now been processed - free to exit bootloader */
+ WaitForExit = false;
+ }
+
+ /* If the request has a data stage, load it into the command struct */
+ if (SentCommand.DataSize)
+ {
+ while (!(Endpoint_IsOUTReceived()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+
+ /* First byte of the data stage is the DNLOAD request's command */
+ SentCommand.Command = Endpoint_Read_8();
+
+ /* One byte of the data stage is the command, so subtract it from the total data bytes */
+ SentCommand.DataSize--;
+
+ /* Load in the rest of the data stage as command parameters */
+ for (uint8_t DataByte = 0; (DataByte < sizeof(SentCommand.Data)) &&
+ Endpoint_BytesInEndpoint(); DataByte++)
+ {
+ SentCommand.Data[DataByte] = Endpoint_Read_8();
+ SentCommand.DataSize--;
+ }
+
+ /* Process the command */
+ ProcessBootloaderCommand();
+ }
+
+ /* Check if currently downloading firmware */
+ if (DFU_State == dfuDNLOAD_IDLE)
+ {
+ if (!(SentCommand.DataSize))
+ {
+ DFU_State = dfuIDLE;
+ }
+ else
+ {
+ /* Throw away the filler bytes before the start of the firmware */
+ DiscardFillerBytes(DFU_FILLER_BYTES_SIZE);
+
+ /* Throw away the packet alignment filler bytes before the start of the firmware */
+ DiscardFillerBytes(StartAddr % FIXED_CONTROL_ENDPOINT_SIZE);
+
+ /* Calculate the number of bytes remaining to be written */
+ uint16_t BytesRemaining = ((EndAddr - StartAddr) + 1);
+
+ if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x00)) // Write flash
+ {
+ /* Calculate the number of words to be written from the number of bytes to be written */
+ uint16_t WordsRemaining = (BytesRemaining >> 1);
+
+ union
+ {
+ uint16_t Words[2];
+ uint32_t Long;
+ } CurrFlashAddress = {.Words = {StartAddr, Flash64KBPage}};
+
+ uint32_t CurrFlashPageStartAddress = CurrFlashAddress.Long;
+ uint8_t WordsInFlashPage = 0;
+
+ while (WordsRemaining--)
+ {
+ /* Check if endpoint is empty - if so clear it and wait until ready for next packet */
+ if (!(Endpoint_BytesInEndpoint()))
+ {
+ Endpoint_ClearOUT();
+
+ while (!(Endpoint_IsOUTReceived()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+ }
+
+ /* Write the next word into the current flash page */
+ boot_page_fill(CurrFlashAddress.Long, Endpoint_Read_16_LE());
+
+ /* Adjust counters */
+ WordsInFlashPage += 1;
+ CurrFlashAddress.Long += 2;
+
+ /* See if an entire page has been written to the flash page buffer */
+ if ((WordsInFlashPage == (SPM_PAGESIZE >> 1)) || !(WordsRemaining))
+ {
+ /* Commit the flash page to memory */
+ boot_page_write(CurrFlashPageStartAddress);
+ boot_spm_busy_wait();
+
+ /* Check if programming incomplete */
+ if (WordsRemaining)
+ {
+ CurrFlashPageStartAddress = CurrFlashAddress.Long;
+ WordsInFlashPage = 0;
+
+ /* Erase next page's temp buffer */
+ boot_page_erase(CurrFlashAddress.Long);
+ boot_spm_busy_wait();
+ }
+ }
+ }
+
+ /* Once programming complete, start address equals the end address */
+ StartAddr = EndAddr;
+
+ /* Re-enable the RWW section of flash */
+ boot_rww_enable();
+ }
+ else // Write EEPROM
+ {
+ while (BytesRemaining--)
+ {
+ /* Check if endpoint is empty - if so clear it and wait until ready for next packet */
+ if (!(Endpoint_BytesInEndpoint()))
+ {
+ Endpoint_ClearOUT();
+
+ while (!(Endpoint_IsOUTReceived()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+ }
+
+ /* Read the byte from the USB interface and write to to the EEPROM */
+ eeprom_update_byte((uint8_t*)StartAddr, Endpoint_Read_8());
+
+ /* Adjust counters */
+ StartAddr++;
+ }
+ }
+
+ /* Throw away the currently unused DFU file suffix */
+ DiscardFillerBytes(DFU_FILE_SUFFIX_SIZE);
+ }
+ }
+
+ Endpoint_ClearOUT();
+
+ Endpoint_ClearStatusStage();
+
+ break;
+ case DFU_REQ_UPLOAD:
+ Endpoint_ClearSETUP();
+
+ while (!(Endpoint_IsINReady()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+
+ if (DFU_State != dfuUPLOAD_IDLE)
+ {
+ if ((DFU_State == dfuERROR) && IS_ONEBYTE_COMMAND(SentCommand.Data, 0x01)) // Blank Check
+ {
+ /* Blank checking is performed in the DFU_DNLOAD request - if we get here we've told the host
+ that the memory isn't blank, and the host is requesting the first non-blank address */
+ Endpoint_Write_16_LE(StartAddr);
+ }
+ else
+ {
+ /* Idle state upload - send response to last issued command */
+ Endpoint_Write_8(ResponseByte);
+ }
+ }
+ else
+ {
+ /* Determine the number of bytes remaining in the current block */
+ uint16_t BytesRemaining = ((EndAddr - StartAddr) + 1);
+
+ if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x00)) // Read FLASH
+ {
+ /* Calculate the number of words to be written from the number of bytes to be written */
+ uint16_t WordsRemaining = (BytesRemaining >> 1);
+
+ union
+ {
+ uint16_t Words[2];
+ uint32_t Long;
+ } CurrFlashAddress = {.Words = {StartAddr, Flash64KBPage}};
+
+ while (WordsRemaining--)
+ {
+ /* Check if endpoint is full - if so clear it and wait until ready for next packet */
+ if (Endpoint_BytesInEndpoint() == FIXED_CONTROL_ENDPOINT_SIZE)
+ {
+ Endpoint_ClearIN();
+
+ while (!(Endpoint_IsINReady()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+ }
+
+ /* Read the flash word and send it via USB to the host */
+ #if (FLASHEND > 0xFFFF)
+ Endpoint_Write_16_LE(pgm_read_word_far(CurrFlashAddress.Long));
+ #else
+ Endpoint_Write_16_LE(pgm_read_word(CurrFlashAddress.Long));
+ #endif
+
+ /* Adjust counters */
+ CurrFlashAddress.Long += 2;
+ }
+
+ /* Once reading is complete, start address equals the end address */
+ StartAddr = EndAddr;
+ }
+ else if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x02)) // Read EEPROM
+ {
+ while (BytesRemaining--)
+ {
+ /* Check if endpoint is full - if so clear it and wait until ready for next packet */
+ if (Endpoint_BytesInEndpoint() == FIXED_CONTROL_ENDPOINT_SIZE)
+ {
+ Endpoint_ClearIN();
+
+ while (!(Endpoint_IsINReady()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+ }
+
+ /* Read the EEPROM byte and send it via USB to the host */
+ Endpoint_Write_8(eeprom_read_byte((uint8_t*)StartAddr));
+
+ /* Adjust counters */
+ StartAddr++;
+ }
+ }
+
+ /* Return to idle state */
+ DFU_State = dfuIDLE;
+ }
+
+ Endpoint_ClearIN();
+
+ Endpoint_ClearStatusStage();
+ break;
+ case DFU_REQ_GETSTATUS:
+ Endpoint_ClearSETUP();
+
+ while (!(Endpoint_IsINReady()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+
+ /* Write 8-bit status value */
+ Endpoint_Write_8(DFU_Status);
+
+ /* Write 24-bit poll timeout value */
+ Endpoint_Write_8(0);
+ Endpoint_Write_16_LE(0);
+
+ /* Write 8-bit state value */
+ Endpoint_Write_8(DFU_State);
+
+ /* Write 8-bit state string ID number */
+ Endpoint_Write_8(0);
+
+ Endpoint_ClearIN();
+
+ Endpoint_ClearStatusStage();
+ break;
+ case DFU_REQ_CLRSTATUS:
+ Endpoint_ClearSETUP();
+
+ /* Reset the status value variable to the default OK status */
+ DFU_Status = OK;
+
+ Endpoint_ClearStatusStage();
+ break;
+ case DFU_REQ_GETSTATE:
+ Endpoint_ClearSETUP();
+
+ while (!(Endpoint_IsINReady()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+
+ /* Write the current device state to the endpoint */
+ Endpoint_Write_8(DFU_State);
+
+ Endpoint_ClearIN();
+
+ Endpoint_ClearStatusStage();
+ break;
+ case DFU_REQ_ABORT:
+ Endpoint_ClearSETUP();
+
+ /* Reset the current state variable to the default idle state */
+ DFU_State = dfuIDLE;
+
+ Endpoint_ClearStatusStage();
+ break;
+ }
+}
+
+/** Routine to discard the specified number of bytes from the control endpoint stream. This is used to
+ * discard unused bytes in the stream from the host, including the memory program block suffix.
+ *
+ * \param[in] NumberOfBytes Number of bytes to discard from the host from the control endpoint
+ */
+static void DiscardFillerBytes(uint8_t NumberOfBytes)
+{
+ while (NumberOfBytes--)
+ {
+ if (!(Endpoint_BytesInEndpoint()))
+ {
+ Endpoint_ClearOUT();
+
+ /* Wait until next data packet received */
+ while (!(Endpoint_IsOUTReceived()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+ }
+ else
+ {
+ Endpoint_Discard_8();
+ }
+ }
+}
+
+/** Routine to process an issued command from the host, via a DFU_DNLOAD request wrapper. This routine ensures
+ * that the command is allowed based on the current secure mode flag value, and passes the command off to the
+ * appropriate handler function.
+ */
+static void ProcessBootloaderCommand(void)
+{
+ /* Check if device is in secure mode */
+ if (IsSecure)
+ {
+ /* Don't process command unless it is a READ or chip erase command */
+ if (!(((SentCommand.Command == COMMAND_WRITE) &&
+ IS_TWOBYTE_COMMAND(SentCommand.Data, 0x00, 0xFF)) ||
+ (SentCommand.Command == COMMAND_READ)))
+ {
+ /* Set the state and status variables to indicate the error */
+ DFU_State = dfuERROR;
+ DFU_Status = errWRITE;
+
+ /* Stall command */
+ Endpoint_StallTransaction();
+
+ /* Don't process the command */
+ return;
+ }
+ }
+
+ /* Dispatch the required command processing routine based on the command type */
+ switch (SentCommand.Command)
+ {
+ case COMMAND_PROG_START:
+ ProcessMemProgCommand();
+ break;
+ case COMMAND_DISP_DATA:
+ ProcessMemReadCommand();
+ break;
+ case COMMAND_WRITE:
+ ProcessWriteCommand();
+ break;
+ case COMMAND_READ:
+ ProcessReadCommand();
+ break;
+ case COMMAND_CHANGE_BASE_ADDR:
+ if (IS_TWOBYTE_COMMAND(SentCommand.Data, 0x03, 0x00)) // Set 64KB flash page command
+ Flash64KBPage = SentCommand.Data[2];
+
+ break;
+ }
+}
+
+/** Routine to concatenate the given pair of 16-bit memory start and end addresses from the host, and store them
+ * in the StartAddr and EndAddr global variables.
+ */
+static void LoadStartEndAddresses(void)
+{
+ union
+ {
+ uint8_t Bytes[2];
+ uint16_t Word;
+ } Address[2] = {{.Bytes = {SentCommand.Data[2], SentCommand.Data[1]}},
+ {.Bytes = {SentCommand.Data[4], SentCommand.Data[3]}}};
+
+ /* Load in the start and ending read addresses from the sent data packet */
+ StartAddr = Address[0].Word;
+ EndAddr = Address[1].Word;
+}
+
+/** Handler for a Memory Program command issued by the host. This routine handles the preparations needed
+ * to write subsequent data from the host into the specified memory.
+ */
+static void ProcessMemProgCommand(void)
+{
+ if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x00) || // Write FLASH command
+ IS_ONEBYTE_COMMAND(SentCommand.Data, 0x01)) // Write EEPROM command
+ {
+ /* Load in the start and ending read addresses */
+ LoadStartEndAddresses();
+
+ /* If FLASH is being written to, we need to pre-erase the first page to write to */
+ if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x00))
+ {
+ union
+ {
+ uint16_t Words[2];
+ uint32_t Long;
+ } CurrFlashAddress = {.Words = {StartAddr, Flash64KBPage}};
+
+ /* Erase the current page's temp buffer */
+ boot_page_erase(CurrFlashAddress.Long);
+ boot_spm_busy_wait();
+ }
+
+ /* Set the state so that the next DNLOAD requests reads in the firmware */
+ DFU_State = dfuDNLOAD_IDLE;
+ }
+}
+
+/** Handler for a Memory Read command issued by the host. This routine handles the preparations needed
+ * to read subsequent data from the specified memory out to the host, as well as implementing the memory
+ * blank check command.
+ */
+static void ProcessMemReadCommand(void)
+{
+ if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x00) || // Read FLASH command
+ IS_ONEBYTE_COMMAND(SentCommand.Data, 0x02)) // Read EEPROM command
+ {
+ /* Load in the start and ending read addresses */
+ LoadStartEndAddresses();
+
+ /* Set the state so that the next UPLOAD requests read out the firmware */
+ DFU_State = dfuUPLOAD_IDLE;
+ }
+ else if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x01)) // Blank check FLASH command
+ {
+ uint32_t CurrFlashAddress = 0;
+
+ while (CurrFlashAddress < (uint32_t)BOOT_START_ADDR)
+ {
+ /* Check if the current byte is not blank */
+ #if (FLASHEND > 0xFFFF)
+ if (pgm_read_byte_far(CurrFlashAddress) != 0xFF)
+ #else
+ if (pgm_read_byte(CurrFlashAddress) != 0xFF)
+ #endif
+ {
+ /* Save the location of the first non-blank byte for response back to the host */
+ Flash64KBPage = (CurrFlashAddress >> 16);
+ StartAddr = CurrFlashAddress;
+
+ /* Set state and status variables to the appropriate error values */
+ DFU_State = dfuERROR;
+ DFU_Status = errCHECK_ERASED;
+
+ break;
+ }
+
+ CurrFlashAddress++;
+ }
+ }
+}
+
+/** Handler for a Data Write command issued by the host. This routine handles non-programming commands such as
+ * bootloader exit (both via software jumps and hardware watchdog resets) and flash memory erasure.
+ */
+static void ProcessWriteCommand(void)
+{
+ if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x03)) // Start application
+ {
+ /* Indicate that the bootloader is terminating */
+ WaitForExit = true;
+
+ /* Check if data supplied for the Start Program command - no data executes the program */
+ if (SentCommand.DataSize)
+ {
+ if (SentCommand.Data[1] == 0x01) // Start via jump
+ {
+ union
+ {
+ uint8_t Bytes[2];
+ AppPtr_t FuncPtr;
+ } Address = {.Bytes = {SentCommand.Data[4], SentCommand.Data[3]}};
+
+ /* Load in the jump address into the application start address pointer */
+ AppStartPtr = Address.FuncPtr;
+ }
+ }
+ else
+ {
+ if (SentCommand.Data[1] == 0x00) // Start via watchdog
+ {
+ /* Unlock the forced application start mode of the bootloader if it is restarted */
+ MagicBootKey = MAGIC_BOOT_KEY;
+
+ /* Start the watchdog to reset the AVR once the communications are finalized */
+ wdt_enable(WDTO_250MS);
+ }
+ else // Start via jump
+ {
+ /* Set the flag to terminate the bootloader at next opportunity */
+ RunBootloader = false;
+ }
+ }
+ }
+ else if (IS_TWOBYTE_COMMAND(SentCommand.Data, 0x00, 0xFF)) // Erase flash
+ {
+ uint32_t CurrFlashAddress = 0;
+
+ /* Clear the application section of flash */
+ while (CurrFlashAddress < (uint32_t)BOOT_START_ADDR)
+ {
+ boot_page_erase(CurrFlashAddress);
+ boot_spm_busy_wait();
+ boot_page_write(CurrFlashAddress);
+ boot_spm_busy_wait();
+
+ CurrFlashAddress += SPM_PAGESIZE;
+ }
+
+ /* Re-enable the RWW section of flash as writing to the flash locks it out */
+ boot_rww_enable();
+
+ /* Memory has been erased, reset the security bit so that programming/reading is allowed */
+ IsSecure = false;
+ }
+}
+
+/** Handler for a Data Read command issued by the host. This routine handles bootloader information retrieval
+ * commands such as device signature and bootloader version retrieval.
+ */
+static void ProcessReadCommand(void)
+{
+ const uint8_t BootloaderInfo[3] = {BOOTLOADER_VERSION, BOOTLOADER_ID_BYTE1, BOOTLOADER_ID_BYTE2};
+ const uint8_t SignatureInfo[4] = {0x58, AVR_SIGNATURE_1, AVR_SIGNATURE_2, AVR_SIGNATURE_3};
+
+ uint8_t DataIndexToRead = SentCommand.Data[1];
+
+ if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x00)) // Read bootloader info
+ {
+ ResponseByte = BootloaderInfo[DataIndexToRead];
+ }
+ else if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x01)) // Read signature byte
+ {
+ if (DataIndexToRead < 0x60)
+ ResponseByte = SignatureInfo[DataIndexToRead - 0x30];
+ else
+ ResponseByte = SignatureInfo[DataIndexToRead - 0x60 + 3];
+ }
+}
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/BootloaderDFU.h b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/BootloaderDFU.h
new file mode 100644
index 000000000..c5d812847
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/BootloaderDFU.h
@@ -0,0 +1,216 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Header file for BootloaderDFU.c.
+ */
+
+#ifndef _BOOTLOADER_H_
+#define _BOOTLOADER_H_
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <avr/wdt.h>
+ #include <avr/boot.h>
+ #include <avr/pgmspace.h>
+ #include <avr/eeprom.h>
+ #include <avr/power.h>
+ #include <avr/interrupt.h>
+ #include <util/delay.h>
+ #include <stdbool.h>
+
+ #include "Descriptors.h"
+ #include "BootloaderAPI.h"
+ #include "Config/AppConfig.h"
+
+ #include <LUFA/Drivers/USB/USB.h>
+ #include <LUFA/Drivers/Board/LEDs.h>
+ #include <LUFA/Platform/Platform.h>
+
+ /* Preprocessor Checks: */
+ #if !defined(__OPTIMIZE_SIZE__)
+ #error This bootloader requires that it be optimized for size, not speed, to fit into the target device. Change optimization settings and try again.
+ #endif
+
+ /* Macros: */
+ /** Major bootloader version number. */
+ #define BOOTLOADER_VERSION_MINOR 2
+
+ /** Minor bootloader version number. */
+ #define BOOTLOADER_VERSION_REV 0
+
+ /** Magic bootloader key to unlock forced application start mode. */
+ #define MAGIC_BOOT_KEY 0xDC42
+
+ /** Complete bootloader version number expressed as a packed byte, constructed from the
+ * two individual bootloader version macros.
+ */
+ #define BOOTLOADER_VERSION ((BOOTLOADER_VERSION_MINOR << 4) | BOOTLOADER_VERSION_REV)
+
+ /** First byte of the bootloader identification bytes, used to identify a device's bootloader. */
+ #define BOOTLOADER_ID_BYTE1 0xDC
+
+ /** Second byte of the bootloader identification bytes, used to identify a device's bootloader. */
+ #define BOOTLOADER_ID_BYTE2 0xFB
+
+ /** Convenience macro, used to determine if the issued command is the given one-byte long command.
+ *
+ * \param[in] dataarr Command byte array to check against
+ * \param[in] cb1 First command byte to check
+ */
+ #define IS_ONEBYTE_COMMAND(dataarr, cb1) (dataarr[0] == (cb1))
+
+ /** Convenience macro, used to determine if the issued command is the given two-byte long command.
+ *
+ * \param[in] dataarr Command byte array to check against
+ * \param[in] cb1 First command byte to check
+ * \param[in] cb2 Second command byte to check
+ */
+ #define IS_TWOBYTE_COMMAND(dataarr, cb1, cb2) ((dataarr[0] == (cb1)) && (dataarr[1] == (cb2)))
+
+ /** Length of the DFU file suffix block, appended to the end of each complete memory write command.
+ * The DFU file suffix is currently unused (but is designed to give extra file information, such as
+ * a CRC of the complete firmware for error checking) and so is discarded.
+ */
+ #define DFU_FILE_SUFFIX_SIZE 16
+
+ /** Length of the DFU file filler block, appended to the start of each complete memory write command.
+ * Filler bytes are added to the start of each complete memory write command, and must be discarded.
+ */
+ #define DFU_FILLER_BYTES_SIZE 26
+
+ /** DFU class command request to detach from the host. */
+ #define DFU_REQ_DETATCH 0x00
+
+ /** DFU class command request to send data from the host to the bootloader. */
+ #define DFU_REQ_DNLOAD 0x01
+
+ /** DFU class command request to send data from the bootloader to the host. */
+ #define DFU_REQ_UPLOAD 0x02
+
+ /** DFU class command request to get the current DFU status and state from the bootloader. */
+ #define DFU_REQ_GETSTATUS 0x03
+
+ /** DFU class command request to reset the current DFU status and state variables to their defaults. */
+ #define DFU_REQ_CLRSTATUS 0x04
+
+ /** DFU class command request to get the current DFU state of the bootloader. */
+ #define DFU_REQ_GETSTATE 0x05
+
+ /** DFU class command request to abort the current multi-request transfer and return to the dfuIDLE state. */
+ #define DFU_REQ_ABORT 0x06
+
+ /** DFU command to begin programming the device's memory. */
+ #define COMMAND_PROG_START 0x01
+
+ /** DFU command to begin reading the device's memory. */
+ #define COMMAND_DISP_DATA 0x03
+
+ /** DFU command to issue a write command. */
+ #define COMMAND_WRITE 0x04
+
+ /** DFU command to issue a read command. */
+ #define COMMAND_READ 0x05
+
+ /** DFU command to issue a memory base address change command, to set the current 64KB flash page
+ * that subsequent flash operations should use. */
+ #define COMMAND_CHANGE_BASE_ADDR 0x06
+
+ /* Type Defines: */
+ /** Type define for a non-returning function pointer to the loaded application. */
+ typedef void (*AppPtr_t)(void) ATTR_NO_RETURN;
+
+ /** Type define for a structure containing a complete DFU command issued by the host. */
+ typedef struct
+ {
+ uint8_t Command; /**< Single byte command to perform, one of the \c COMMAND_* macro values */
+ uint8_t Data[5]; /**< Command parameters */
+ uint16_t DataSize; /**< Size of the command parameters */
+ } DFU_Command_t;
+
+ /* Enums: */
+ /** DFU bootloader states. Refer to the DFU class specification for information on each state. */
+ enum DFU_State_t
+ {
+ appIDLE = 0,
+ appDETACH = 1,
+ dfuIDLE = 2,
+ dfuDNLOAD_SYNC = 3,
+ dfuDNBUSY = 4,
+ dfuDNLOAD_IDLE = 5,
+ dfuMANIFEST_SYNC = 6,
+ dfuMANIFEST = 7,
+ dfuMANIFEST_WAIT_RESET = 8,
+ dfuUPLOAD_IDLE = 9,
+ dfuERROR = 10
+ };
+
+ /** DFU command status error codes. Refer to the DFU class specification for information on each error code. */
+ enum DFU_Status_t
+ {
+ OK = 0,
+ errTARGET = 1,
+ errFILE = 2,
+ errWRITE = 3,
+ errERASE = 4,
+ errCHECK_ERASED = 5,
+ errPROG = 6,
+ errVERIFY = 7,
+ errADDRESS = 8,
+ errNOTDONE = 9,
+ errFIRMWARE = 10,
+ errVENDOR = 11,
+ errUSBR = 12,
+ errPOR = 13,
+ errUNKNOWN = 14,
+ errSTALLEDPKT = 15
+ };
+
+ /* Function Prototypes: */
+ static void SetupHardware(void);
+ static void ResetHardware(void);
+
+ void EVENT_USB_Device_ControlRequest(void);
+
+ #if defined(INCLUDE_FROM_BOOTLOADER_C)
+ static void DiscardFillerBytes(uint8_t NumberOfBytes);
+ static void ProcessBootloaderCommand(void);
+ static void LoadStartEndAddresses(void);
+ static void ProcessMemProgCommand(void);
+ static void ProcessMemReadCommand(void);
+ static void ProcessWriteCommand(void);
+ static void ProcessReadCommand(void);
+ #endif
+
+ void Application_Jump_Check(void) ATTR_INIT_SECTION(3);
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/BootloaderDFU.txt b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/BootloaderDFU.txt
new file mode 100644
index 000000000..e63bcc1f0
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/BootloaderDFU.txt
@@ -0,0 +1,233 @@
+/** \file
+ *
+ * This file contains special DoxyGen information for the generation of the main page and other special
+ * documentation pages. It is not a project source file.
+ */
+
+/** \mainpage DFU Class USB AVR Bootloader
+ *
+ * \section Sec_Compat Demo Compatibility:
+ *
+ * The following list indicates what microcontrollers are compatible with this demo.
+ *
+ * \li Series 7 USB AVRs (AT90USBxxx7)
+ * \li Series 6 USB AVRs (AT90USBxxx6)
+ * \li Series 4 USB AVRs (ATMEGAxxU4) - <i>See \ref SSec_Aux_Space</i>
+ * \li Series 2 USB AVRs (AT90USBxx2, ATMEGAxxU2) - <i>See \ref SSec_Aux_Space</i>
+ *
+ * \section Sec_Info USB Information:
+ *
+ * The following table gives a rundown of the USB utilization of this demo.
+ *
+ * <table>
+ * <tr>
+ * <td><b>USB Mode:</b></td>
+ * <td>Device</td>
+ * </tr>
+ * <tr>
+ * <td><b>USB Class:</b></td>
+ * <td>Device Firmware Update Class (DFU)</td>
+ * </tr>
+ * <tr>
+ * <td><b>USB Subclass:</b></td>
+ * <td>None</td>
+ * </tr>
+ * <tr>
+ * <td><b>Relevant Standards:</b></td>
+ * <td>USBIF DFU Class Standard, Atmel USB Bootloader Datasheet</td>
+ * </tr>
+ * <tr>
+ * <td><b>Supported USB Speeds:</b></td>
+ * <td>Low Speed Mode \n
+ * Full Speed Mode</td>
+ * </tr>
+ * </table>
+ *
+ * \section Sec_Description Project Description:
+ *
+ * This bootloader enumerates to the host as a DFU Class device, allowing for DFU-compatible programming
+ * software to load firmware onto the AVR.
+ *
+ * Out of the box this bootloader builds for the AT90USB1287 with an 8KB bootloader section size, and will fit
+ * into 4KB of bootloader space. If you wish to alter this size and/or change the AVR model, you will need to
+ * edit the MCU, FLASH_SIZE_KB and BOOT_SECTION_SIZE_KB values in the accompanying makefile.
+ *
+ * When the bootloader is running, the board's LED(s) will flash at regular intervals to distinguish the
+ * bootloader from the normal user application.
+ *
+ * \section Sec_Running Running the Bootloader
+ *
+ * This bootloader is designed to be started via the HWB mechanism of the USB AVRs; ground the HWB pin (see device
+ * datasheet) then momentarily ground /RESET to start the bootloader. This assumes the HWBE fuse is set and the BOOTRST
+ * fuse is cleared.
+ *
+ * For board specific exceptions to the above, see below.
+ *
+ * \subsection SSec_XPLAIN Atmel Xplain Board
+ * Ground the USB AVR JTAG's \c TCK pin to ground when powering on the board to start the bootloader. This assumes the
+ * \c HWBE fuse is cleared and the \c BOOTRST fuse is set as the HWBE pin is not user accessible on this board.
+ *
+ * \subsection SSec_Leonardo Arduino Leonardo Board
+ * Ground \c IO13 when powering the board to start the bootloader. This assumes the \c HWBE fuse is cleared and the
+ * \c BOOTRST fuse is set as the HWBE pin is not user accessible on this board.
+ *
+ * \section Sec_Installation Driver Installation
+ *
+ * This bootloader is designed to be compatible with Atmel's provided Windows DFU class drivers. You will need to
+ * install Atmel's DFU drivers prior to using this bootloader on Windows platforms. If you are using a 64 bit Windows
+ * OS, you will need to either disable the driver signing requirement (see online tutorials for details) or use a
+ * digitally signed version of the official Atmel driver provided by a third party AVR user at
+ * <a>http://www.avrfreaks.net/index.php?module=Freaks%20Academy&func=viewItem&item_id=2196&item_type=project</a>.
+ *
+ * \note This device spoofs Atmel's DFU Bootloader USB VID and PID so that the Atmel DFU bootloader
+ * drivers included with FLIP will work. If you do not wish to use Atmel's ID codes, please
+ * manually change them in Descriptors.c and alter your driver's INF file accordingly.
+ *
+ * \section Sec_HostApp Host Controller Application
+ *
+ * This bootloader is compatible with Atmel's FLIP utility on Windows machines, and dfu-programmer on Linux machines.
+ *
+ * \subsection SSec_FLIP FLIP (Windows)
+ *
+ * FLIP (Flexible In-System Programmer) is a utility written by Atmel, and distributed for free on the Atmel website.
+ * The FLIP utility is designed to assist in the bootloader programming of a range of Atmel devices, through several
+ * popular physical interfaces including USB. It is written in Java, however makes use of native extensions for USB
+ * support and thus is only offered on Windows.
+ *
+ * To program a device using FLIP, refer to the Atmel FLIP documentation.
+ *
+ * \subsection SSec_DFUProgrammer dfu-programmer (Linux)
+ *
+ * dfu-programmer is an open-source command line solution for the bootloader programming of Atmel devices through a
+ * USB connection, using the DFU protocol, available for download at <a>http://sourceforge.net/projects/dfu-programmer/</a>.
+ *
+ * The following example loads a HEX file into the AVR's FLASH memory using dfu-programmer:
+ * \code
+ * dfu-programmer at90usb1287 erase flash Mouse.hex
+ * \endcode
+ *
+ * \section Sec_API User Application API
+ *
+ * Several user application functions for FLASH and other special memory area manipulations are exposed by the bootloader,
+ * allowing the user application to call into the bootloader at runtime to read and write FLASH data.
+ *
+ * \warning The APIs exposed by the DFU class bootloader are \b NOT compatible with the API exposed by the official Atmel DFU bootloader.
+ *
+ * By default, the bootloader API jump table is located 32 bytes from the end of the device's FLASH memory, and follows the
+ * following layout:
+ *
+ * \code
+ * #define BOOTLOADER_API_TABLE_SIZE 32
+ * #define BOOTLOADER_API_TABLE_START ((FLASHEND + 1UL) - BOOTLOADER_API_TABLE_SIZE)
+ * #define BOOTLOADER_API_CALL(Index) (void*)((BOOTLOADER_API_TABLE_START + (Index * 2)) / 2)
+ *
+ * void (*BootloaderAPI_ErasePage)(uint32_t Address) = BOOTLOADER_API_CALL(0);
+ * void (*BootloaderAPI_WritePage)(uint32_t Address) = BOOTLOADER_API_CALL(1);
+ * void (*BootloaderAPI_FillWord)(uint32_t Address, uint16_t Word) = BOOTLOADER_API_CALL(2);
+ * uint8_t (*BootloaderAPI_ReadSignature)(uint16_t Address) = BOOTLOADER_API_CALL(3);
+ * uint8_t (*BootloaderAPI_ReadFuse)(uint16_t Address) = BOOTLOADER_API_CALL(4);
+ * uint8_t (*BootloaderAPI_ReadLock)(void) = BOOTLOADER_API_CALL(5);
+ * void (*BootloaderAPI_WriteLock)(uint8_t LockBits) = BOOTLOADER_API_CALL(6);
+ *
+ * #define BOOTLOADER_MAGIC_SIGNATURE_START (BOOTLOADER_API_TABLE_START + (BOOTLOADER_API_TABLE_SIZE - 2))
+ * #define BOOTLOADER_MAGIC_SIGNATURE 0xDCFB
+ *
+ * #define BOOTLOADER_CLASS_SIGNATURE_START (BOOTLOADER_API_TABLE_START + (BOOTLOADER_API_TABLE_SIZE - 4))
+ * #define BOOTLOADER_DFU_SIGNATURE 0xDF10
+ *
+ * #define BOOTLOADER_ADDRESS_START (BOOTLOADER_API_TABLE_START + (BOOTLOADER_API_TABLE_SIZE - 8))
+ * #define BOOTLOADER_ADDRESS_LENGTH 4
+ * \endcode
+ *
+ * From the application the API support of the bootloader can be detected by reading the FLASH memory bytes located at address
+ * \c BOOTLOADER_MAGIC_SIGNATURE_START and comparing them to the value \c BOOTLOADER_MAGIC_SIGNATURE. The class of bootloader
+ * can be determined by reading the FLASH memory bytes located at address \c BOOTLOADER_CLASS_SIGNATURE_START and comparing them
+ * to the value \c BOOTLOADER_DFU_SIGNATURE. The start address of the bootloader can be retrieved by reading the bytes of FLASH
+ * memory starting from address \c BOOTLOADER_ADDRESS_START.
+ *
+ * \subsection SSec_API_MemLayout Device Memory Map
+ * The following illustration indicates the final memory map of the device when loaded with the bootloader.
+ *
+ * \verbatim
+ * +----------------------------+ 0x0000
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | User Application |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * +----------------------------+ FLASHEND - BOOT_AUX_SECTION_SIZE
+ * | Booloader Start Trampoline |
+ * | (Not User App. Accessible) |
+ * +----------------------------+ FLASHEND - (BOOT_AUX_SECTION_SIZE - 4)
+ * | |
+ * | Auxillery Bootloader |
+ * | Space for Smaller Devices |
+ * | (Not User App. Accessible) |
+ * | |
+ * +----------------------------+ FLASHEND - BOOT_SECTION_SIZE
+ * | |
+ * | Bootloader Application |
+ * | (Not User App. Accessible) |
+ * | |
+ * +----------------------------+ FLASHEND - 96
+ * | API Table Trampolines |
+ * | (Not User App. Accessible) |
+ * +----------------------------+ FLASHEND - 32
+ * | Bootloader API Table |
+ * | (User App. Accessible) |
+ * +----------------------------+ FLASHEND - 8
+ * | Bootloader ID Constants |
+ * | (User App. Accessible) |
+ * +----------------------------+ FLASHEND
+ * \endverbatim
+ *
+ * \subsection SSec_Aux_Space Auxiliary Bootloader Section
+ * To make the bootloader function on smaller devices (those with a physical
+ * bootloader section of smaller than 6KB)
+ *
+ * \section Sec_KnownIssues Known Issues:
+ *
+ * \par On Linux machines, the DFU bootloader is inaccessible.
+ * On many Linux systems, non-root users do not have automatic access to newly
+ * inserted DFU devices. Root privileges or a UDEV rule is required to gain
+ * access.
+ * See <a href=https://groups.google.com/d/msg/lufa-support/CP9cy2bc8yo/kBqsOu-RBeMJ>here</a> for resolution steps.
+ *
+ * \par After loading an application, it is not run automatically on startup.
+ * Some USB AVR boards ship with the BOOTRST fuse set, causing the bootloader
+ * to run automatically when the device is reset. In most cases, the BOOTRST
+ * fuse should be disabled and the HWBE fuse used instead to run the bootloader
+ * when needed.
+ *
+ * \section Sec_Options Project Options
+ *
+ * The following defines can be found in this demo, which can control the demo behaviour when defined, or changed in value.
+ *
+ * <table>
+ * <tr>
+ * <th><b>Define Name:</b></th>
+ * <th><b>Location:</b></th>
+ * <th><b>Description:</b></th>
+ * </tr>
+ * <tr>
+ * <td>SECURE_MODE</td>
+ * <td>AppConfig.h</td>
+ * <td>If defined to \c true, the bootloader will not accept any memory commands other than a chip erase on start-up, until an
+ * erase has been performed. This can be used in conjunction with the AVR's lockbits to prevent the AVRs firmware from
+ * being dumped by unauthorized persons. When false, all memory operations are allowed at any time.</td>
+ * </tr>
+ * </table>
+ */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/Config/AppConfig.h b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/Config/AppConfig.h
new file mode 100644
index 000000000..260a8f4cd
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/Config/AppConfig.h
@@ -0,0 +1,48 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Application Configuration Header File
+ *
+ * This is a header file which is be used to configure some of
+ * the application's compile time options, as an alternative to
+ * specifying the compile time constants supplied through a
+ * makefile or build system.
+ *
+ * For information on what each token does, refer to the
+ * \ref Sec_Options section of the application documentation.
+ */
+
+#ifndef _APP_CONFIG_H_
+#define _APP_CONFIG_H_
+
+ #define SECURE_MODE false
+
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/Config/LUFAConfig.h b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/Config/LUFAConfig.h
new file mode 100644
index 000000000..f123dd5aa
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/Config/LUFAConfig.h
@@ -0,0 +1,93 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief LUFA Library Configuration Header File
+ *
+ * This header file is used to configure LUFA's compile time options,
+ * as an alternative to the compile time constants supplied through
+ * a makefile.
+ *
+ * For information on what each token does, refer to the LUFA
+ * manual section "Summary of Compile Tokens".
+ */
+
+#ifndef _LUFA_CONFIG_H_
+#define _LUFA_CONFIG_H_
+
+ #if (ARCH == ARCH_AVR8)
+
+ /* Non-USB Related Configuration Tokens: */
+// #define DISABLE_TERMINAL_CODES
+
+ /* USB Class Driver Related Tokens: */
+// #define HID_HOST_BOOT_PROTOCOL_ONLY
+// #define HID_STATETABLE_STACK_DEPTH {Insert Value Here}
+// #define HID_USAGE_STACK_DEPTH {Insert Value Here}
+// #define HID_MAX_COLLECTIONS {Insert Value Here}
+// #define HID_MAX_REPORTITEMS {Insert Value Here}
+// #define HID_MAX_REPORT_IDS {Insert Value Here}
+// #define NO_CLASS_DRIVER_AUTOFLUSH
+
+ /* General USB Driver Related Tokens: */
+// #define ORDERED_EP_CONFIG
+ #define USE_STATIC_OPTIONS (USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)
+ #define USB_DEVICE_ONLY
+// #define USB_HOST_ONLY
+// #define USB_STREAM_TIMEOUT_MS {Insert Value Here}
+// #define NO_LIMITED_CONTROLLER_CONNECT
+ #define NO_SOF_EVENTS
+
+ /* USB Device Mode Driver Related Tokens: */
+ #define USE_RAM_DESCRIPTORS
+// #define USE_FLASH_DESCRIPTORS
+// #define USE_EEPROM_DESCRIPTORS
+ #define NO_INTERNAL_SERIAL
+ #define FIXED_CONTROL_ENDPOINT_SIZE 32
+ #define DEVICE_STATE_AS_GPIOR 0
+ #define FIXED_NUM_CONFIGURATIONS 1
+ #define CONTROL_ONLY_DEVICE
+// #define INTERRUPT_CONTROL_ENDPOINT
+ #define NO_DEVICE_REMOTE_WAKEUP
+ #define NO_DEVICE_SELF_POWER
+
+ /* USB Host Mode Driver Related Tokens: */
+// #define HOST_STATE_AS_GPIOR {Insert Value Here}
+// #define USB_HOST_TIMEOUT_MS {Insert Value Here}
+// #define HOST_DEVICE_SETTLE_DELAY_MS {Insert Value Here}
+// #define NO_AUTO_VBUS_MANAGEMENT
+// #define INVERTED_VBUS_ENABLE_LINE
+
+ #else
+
+ #error Unsupported architecture for this LUFA configuration file.
+
+ #endif
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/Descriptors.c b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/Descriptors.c
new file mode 100644
index 000000000..922c06bcd
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/Descriptors.c
@@ -0,0 +1,185 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * USB Device Descriptors, for library use when in USB device mode. Descriptors are special
+ * computer-readable structures which the host requests upon device enumeration, to determine
+ * the device's capabilities and functions.
+ */
+
+#include "Descriptors.h"
+
+/** Device descriptor structure. This descriptor, located in SRAM memory, describes the overall
+ * device characteristics, including the supported USB version, control endpoint size and the
+ * number of device configurations. The descriptor is read out by the USB host when the enumeration
+ * process begins.
+ */
+const USB_Descriptor_Device_t DeviceDescriptor =
+{
+ .Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
+
+ .USBSpecification = VERSION_BCD(1,1,0),
+ .Class = USB_CSCP_NoDeviceClass,
+ .SubClass = USB_CSCP_NoDeviceSubclass,
+ .Protocol = USB_CSCP_NoDeviceProtocol,
+
+ .Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
+
+ .VendorID = 0x03EB,
+ .ProductID = PRODUCT_ID_CODE,
+ .ReleaseNumber = VERSION_BCD(0,0,0),
+
+ .ManufacturerStrIndex = STRING_ID_Manufacturer,
+ .ProductStrIndex = STRING_ID_Product,
+ .SerialNumStrIndex = NO_DESCRIPTOR,
+
+ .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
+};
+
+/** Configuration descriptor structure. This descriptor, located in SRAM memory, describes the usage
+ * of the device in one of its supported configurations, including information about any device interfaces
+ * and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting
+ * a configuration so that the host may correctly communicate with the USB device.
+ */
+const USB_Descriptor_Configuration_t ConfigurationDescriptor =
+{
+ .Config =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration},
+
+ .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
+ .TotalInterfaces = 1,
+
+ .ConfigurationNumber = 1,
+ .ConfigurationStrIndex = NO_DESCRIPTOR,
+
+ .ConfigAttributes = USB_CONFIG_ATTR_RESERVED,
+
+ .MaxPowerConsumption = USB_CONFIG_POWER_MA(100)
+ },
+
+ .DFU_Interface =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
+
+ .InterfaceNumber = INTERFACE_ID_DFU,
+ .AlternateSetting = 0,
+
+ .TotalEndpoints = 0,
+
+ .Class = 0xFE,
+ .SubClass = 0x01,
+ .Protocol = 0x02,
+
+ .InterfaceStrIndex = NO_DESCRIPTOR
+ },
+
+ .DFU_Functional =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_DFU_Functional_t), .Type = DTYPE_DFUFunctional},
+
+ .Attributes = (ATTR_CAN_UPLOAD | ATTR_CAN_DOWNLOAD),
+
+ .DetachTimeout = 0x0000,
+ .TransferSize = 0x0C00,
+
+ .DFUSpecification = VERSION_BCD(1,1,0)
+ }
+};
+
+/** Language descriptor structure. This descriptor, located in SRAM memory, is returned when the host requests
+ * the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which indicate
+ * via the language ID table available at USB.org what languages the device supports for its string descriptors.
+ */
+const USB_Descriptor_String_t LanguageString = USB_STRING_DESCRIPTOR_ARRAY(LANGUAGE_ID_ENG);
+
+/** Manufacturer descriptor string. This is a Unicode string containing the manufacturer's details in human readable
+ * form, and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
+ * Descriptor.
+ */
+const USB_Descriptor_String_t ManufacturerString = USB_STRING_DESCRIPTOR(L"Dean Camera");
+
+/** Product descriptor string. This is a Unicode string containing the product's details in human readable form,
+ * and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
+ * Descriptor.
+ */
+const USB_Descriptor_String_t ProductString = USB_STRING_DESCRIPTOR(L"LUFA DFU");
+
+/** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
+ * documentation) by the application code so that the address and size of a requested descriptor can be given
+ * to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function
+ * is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the
+ * USB host.
+ */
+uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+ const uint8_t wIndex,
+ const void** const DescriptorAddress)
+{
+ const uint8_t DescriptorType = (wValue >> 8);
+ const uint8_t DescriptorNumber = (wValue & 0xFF);
+
+ const void* Address = NULL;
+ uint16_t Size = NO_DESCRIPTOR;
+
+ switch (DescriptorType)
+ {
+ case DTYPE_Device:
+ Address = &DeviceDescriptor;
+ Size = sizeof(USB_Descriptor_Device_t);
+ break;
+ case DTYPE_Configuration:
+ Address = &ConfigurationDescriptor;
+ Size = sizeof(USB_Descriptor_Configuration_t);
+ break;
+ case DTYPE_String:
+ if (DescriptorNumber == STRING_ID_Language)
+ {
+ Address = &LanguageString;
+ Size = LanguageString.Header.Size;
+ }
+ else if (DescriptorNumber == STRING_ID_Manufacturer)
+ {
+ Address = &ManufacturerString;
+ Size = ManufacturerString.Header.Size;
+ }
+ else if (DescriptorNumber == STRING_ID_Product)
+ {
+ Address = &ProductString;
+ Size = ProductString.Header.Size;
+ }
+
+ break;
+ }
+
+ *DescriptorAddress = Address;
+ return Size;
+}
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/Descriptors.h b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/Descriptors.h
new file mode 100644
index 000000000..249172b6d
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/Descriptors.h
@@ -0,0 +1,194 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Header file for Descriptors.c.
+ */
+
+#ifndef _DESCRIPTORS_H_
+#define _DESCRIPTORS_H_
+
+ /* Includes: */
+ #include <LUFA/Drivers/USB/USB.h>
+
+ #include "Config/AppConfig.h"
+
+ /* Macros: */
+ /** Descriptor type value for a DFU class functional descriptor. */
+ #define DTYPE_DFUFunctional 0x21
+
+ /** DFU attribute mask, indicating that the DFU device will detach and re-attach when a DFU_DETACH
+ * command is issued, rather than the host issuing a USB Reset.
+ */
+ #define ATTR_WILL_DETATCH (1 << 3)
+
+ /** DFU attribute mask, indicating that the DFU device can communicate during the manifestation phase
+ * (memory programming phase).
+ */
+ #define ATTR_MANEFESTATION_TOLLERANT (1 << 2)
+
+ /** DFU attribute mask, indicating that the DFU device can accept DFU_UPLOAD requests to send data from
+ * the device to the host.
+ */
+ #define ATTR_CAN_UPLOAD (1 << 1)
+
+ /** DFU attribute mask, indicating that the DFU device can accept DFU_DNLOAD requests to send data from
+ * the host to the device.
+ */
+ #define ATTR_CAN_DOWNLOAD (1 << 0)
+
+ #if defined(__AVR_AT90USB1287__)
+ #define PRODUCT_ID_CODE 0x2FFB
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x97
+ #define AVR_SIGNATURE_3 0x82
+ #elif defined(__AVR_AT90USB647__)
+ #define PRODUCT_ID_CODE 0x2FF9
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x96
+ #define AVR_SIGNATURE_3 0x82
+ #elif defined(__AVR_AT90USB1286__)
+ #define PRODUCT_ID_CODE 0x2FFB
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x97
+ #define AVR_SIGNATURE_3 0x82
+ #elif defined(__AVR_AT90USB646__)
+ #define PRODUCT_ID_CODE 0x2FF9
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x96
+ #define AVR_SIGNATURE_3 0x82
+ #elif defined(__AVR_ATmega32U4__)
+ #define PRODUCT_ID_CODE 0x2FF4
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x95
+ #define AVR_SIGNATURE_3 0x87
+ #elif defined(__AVR_ATmega16U4__)
+ #define PRODUCT_ID_CODE 0x2FF3
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x94
+ #define AVR_SIGNATURE_3 0x88
+ #elif defined(__AVR_ATmega32U2__)
+ #define PRODUCT_ID_CODE 0x2FF0
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x95
+ #define AVR_SIGNATURE_3 0x8A
+ #elif defined(__AVR_ATmega16U2__)
+ #define PRODUCT_ID_CODE 0x2FEF
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x94
+ #define AVR_SIGNATURE_3 0x89
+ #elif defined(__AVR_AT90USB162__)
+ #define PRODUCT_ID_CODE 0x2FFA
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x94
+ #define AVR_SIGNATURE_3 0x82
+ #elif defined(__AVR_ATmega8U2__)
+ #define PRODUCT_ID_CODE 0x2FEE
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x93
+ #define AVR_SIGNATURE_3 0x89
+ #elif defined(__AVR_AT90USB82__)
+ #define PRODUCT_ID_CODE 0x2FF7
+ #define AVR_SIGNATURE_1 0x1E
+ #define AVR_SIGNATURE_2 0x94
+ #define AVR_SIGNATURE_3 0x82
+ #else
+ #error The selected AVR part is not currently supported by this bootloader.
+ #endif
+
+ #if !defined(PRODUCT_ID_CODE)
+ #error Current AVR model is not supported by this bootloader.
+ #endif
+
+ /* Type Defines: */
+ /** Type define for a DFU class function descriptor. This descriptor gives DFU class information
+ * to the host when read, indicating the DFU device's capabilities.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Header_t Header; /**< Standard descriptor header structure */
+
+ uint8_t Attributes; /**< DFU device attributes, a mask comprising of the
+ * ATTR_* macros listed in this source file
+ */
+ uint16_t DetachTimeout; /**< Timeout in milliseconds between a USB_DETACH
+ * command being issued and the device detaching
+ * from the USB bus
+ */
+ uint16_t TransferSize; /**< Maximum number of bytes the DFU device can accept
+ * from the host in a transaction
+ */
+ uint16_t DFUSpecification; /**< BCD packed DFU specification number this DFU
+ * device complies with
+ */
+ } USB_Descriptor_DFU_Functional_t;
+
+ /** Type define for the device configuration descriptor structure. This must be defined in the
+ * application code, as the configuration descriptor contains several sub-descriptors which
+ * vary between devices, and which describe the device's usage to the host.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Configuration_Header_t Config;
+
+ // DFU Interface
+ USB_Descriptor_Interface_t DFU_Interface;
+ USB_Descriptor_DFU_Functional_t DFU_Functional;
+ } USB_Descriptor_Configuration_t;
+
+ /** Enum for the device interface descriptor IDs within the device. Each interface descriptor
+ * should have a unique ID index associated with it, which can be used to refer to the
+ * interface from other descriptors.
+ */
+ enum InterfaceDescriptors_t
+ {
+ INTERFACE_ID_DFU = 0, /**< DFU interface descriptor ID */
+ };
+
+ /** Enum for the device string descriptor IDs within the device. Each string descriptor should
+ * have a unique ID index associated with it, which can be used to refer to the string from
+ * other descriptors.
+ */
+ enum StringDescriptors_t
+ {
+ STRING_ID_Language = 0, /**< Supported Languages string descriptor ID (must be zero) */
+ STRING_ID_Manufacturer = 1, /**< Manufacturer string ID */
+ STRING_ID_Product = 2, /**< Product string ID */
+ };
+
+ /* Function Prototypes: */
+ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+ const uint8_t wIndex,
+ const void** const DescriptorAddress)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/asf.xml b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/asf.xml
new file mode 100644
index 000000000..6f3312b76
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/asf.xml
@@ -0,0 +1,156 @@
+<asf xmlversion="1.0">
+ <project caption="DFU Bootloader - 128KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.dfu.avr8.128_4" force-caption="true" workspace-name="lufa_dfu_128kb_4kb_">
+ <require idref="lufa.bootloaders.dfu"/>
+ <require idref="lufa.boards.dummy.avr8"/>
+ <generator value="as5_8"/>
+
+ <device-support value="at90usb1287"/>
+ <config name="lufa.drivers.board.name" value="none"/>
+
+ <config name="config.compiler.optimization.level" value="size"/>
+
+ <build type="define" name="F_CPU" value="16000000UL"/>
+ <build type="define" name="F_USB" value="16000000UL"/>
+
+ <build type="define" name="BOOT_START_ADDR" value="0x1F000"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.text=0x1F000"/>
+
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x1FFA0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x1FFE0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x1FFF8"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
+ </project>
+
+ <project caption="DFU Bootloader - 64KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.dfu.avr8.64_4" force-caption="true" workspace-name="lufa_dfu_64kb_4kb_">
+ <require idref="lufa.bootloaders.dfu"/>
+ <require idref="lufa.boards.dummy.avr8"/>
+ <generator value="as5_8"/>
+
+ <device-support value="at90usb647"/>
+ <config name="lufa.drivers.board.name" value="none"/>
+
+ <config name="config.compiler.optimization.level" value="size"/>
+
+ <build type="define" name="F_CPU" value="16000000UL"/>
+ <build type="define" name="F_USB" value="16000000UL"/>
+
+ <build type="define" name="BOOT_START_ADDR" value="0xF000"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.text=0xF000"/>
+
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0xFFA0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0xFFE0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0xFFF8"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
+ </project>
+
+ <project caption="DFU Bootloader - 32KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.dfu.avr8.32_4" force-caption="true" workspace-name="lufa_dfu_32kb_4kb_">
+ <require idref="lufa.bootloaders.dfu"/>
+ <require idref="lufa.boards.dummy.avr8"/>
+ <generator value="as5_8"/>
+
+ <device-support value="atmega32u4"/>
+ <config name="lufa.drivers.board.name" value="none"/>
+
+ <config name="config.compiler.optimization.level" value="size"/>
+
+ <build type="define" name="F_CPU" value="16000000UL"/>
+ <build type="define" name="F_USB" value="16000000UL"/>
+
+ <build type="define" name="BOOT_START_ADDR" value="0x7000"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.text=0x7000"/>
+
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x7FA0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x7FE0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x7FF8"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
+ </project>
+
+ <project caption="DFU Bootloader - 16KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.dfu.avr8.16_4" force-caption="true" workspace-name="lufa_dfu_16kb_4kb_">
+ <require idref="lufa.bootloaders.dfu"/>
+ <require idref="lufa.boards.dummy.avr8"/>
+ <generator value="as5_8"/>
+
+ <device-support value="atmega16u2"/>
+ <config name="lufa.drivers.board.name" value="none"/>
+
+ <build type="define" name="F_CPU" value="16000000UL"/>
+ <build type="define" name="F_USB" value="16000000UL"/>
+
+ <build type="define" name="BOOT_START_ADDR" value="0x3000"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.text=0x3000"/>
+
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x3FA0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x3FE0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x3FF8"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
+ </project>
+
+ <project caption="DFU Bootloader - 8KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.dfu.avr8.8_4" force-caption="true" workspace-name="lufa_dfu_8kb_4kb_">
+ <require idref="lufa.bootloaders.dfu"/>
+ <require idref="lufa.boards.dummy.avr8"/>
+ <generator value="as5_8"/>
+
+ <device-support value="atmega8u2"/>
+ <config name="lufa.drivers.board.name" value="none"/>
+
+ <build type="define" name="F_CPU" value="16000000UL"/>
+ <build type="define" name="F_USB" value="16000000UL"/>
+
+ <build type="define" name="BOOT_START_ADDR" value="0x1000"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.text=0x1000"/>
+
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x1FA0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x1FE0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x1FF8"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
+ </project>
+
+ <module type="application" id="lufa.bootloaders.dfu" caption="DFU Bootloader">
+ <info type="description" value="summary">
+ DFU Class Bootloader, capable of reprogramming a device using the Atmel FLIP or other AVR DFU programming software when plugged into a host.
+ </info>
+
+ <info type="gui-flag" value="move-to-root"/>
+
+ <info type="keyword" value="Technology">
+ <keyword value="Bootloaders"/>
+ <keyword value="USB Device"/>
+ </info>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="include-path" value="."/>
+ <build type="c-source" value="BootloaderDFU.c"/>
+ <build type="header-file" value="BootloaderDFU.h"/>
+ <build type="c-source" value="Descriptors.c"/>
+ <build type="header-file" value="Descriptors.h"/>
+ <build type="c-source" value="BootloaderAPI.c"/>
+ <build type="header-file" value="BootloaderAPI.h"/>
+ <build type="asm-source" value="BootloaderAPITable.S"/>
+
+ <build type="module-config" subtype="path" value="Config"/>
+ <build type="header-file" value="Config/LUFAConfig.h"/>
+ <build type="header-file" value="Config/AppConfig.h"/>
+
+ <build type="distribute" subtype="user-file" value="doxyfile"/>
+ <build type="distribute" subtype="user-file" value="BootloaderDFU.txt"/>
+
+ <require idref="lufa.common"/>
+ <require idref="lufa.platform"/>
+ <require idref="lufa.drivers.usb"/>
+ <require idref="lufa.drivers.board"/>
+ <require idref="lufa.drivers.board.leds"/>
+ </module>
+</asf>
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/doxyfile b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/doxyfile
new file mode 100644
index 000000000..6cc42af79
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/doxyfile
@@ -0,0 +1,2365 @@
+# Doxyfile 1.8.8
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME = "LUFA Library - DFU Class Bootloader"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
+# the documentation. The maximum height of the logo should not exceed 55 pixels
+# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
+# to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = ./Documentation/
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES = YES
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
+# new page for each member. If set to NO, the documentation of a member will be
+# part of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
+# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
+# Fortran. In the later case the parser tries to guess whether the code is fixed
+# or free formatted code, this is the default for Fortran type files), VHDL. For
+# instance to make doxygen treat .inc files as Fortran files (default is PHP),
+# and .f files as C (default is Fortran), use: inc=Fortran f=C.
+#
+# Note For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT = NO
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by by putting a % sign in front of the word
+# or globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE = YES
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO these classes will be included in the various overviews. This option has
+# no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
+# todo list. This list is created by putting \todo commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST = NO
+
+# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
+# test list. This list is created by putting \test commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST = NO
+
+# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST = NO
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES the list
+# will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET = YES
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO doxygen will only warn about wrong or incomplete parameter
+# documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces.
+# Note: If this tag is empty the current directory is searched.
+
+INPUT = ./
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank the
+# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
+# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
+# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
+# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
+# *.qsf, *.as and *.js.
+
+FILE_PATTERNS = *.h \
+ *.c \
+ *.txt
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE = Documentation/
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS = __* \
+ INCLUDE_FROM_*
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER ) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = NO
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS = NO
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the
+# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
+# cost of reduced performance. This can be particularly helpful with template
+# rich C++ code for which doxygen's built-in parser lacks the necessary type
+# information.
+# Note: The availability of this option depends on whether or not doxygen was
+# compiled with the --with-libclang option.
+# The default value is: NO.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_OPTIONS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefor more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra stylesheet files is of importance (e.g. the last
+# stylesheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the stylesheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP = NO
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS = YES
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated (
+# YES) or that it should be included in the master .chm file ( NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated (
+# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND = YES
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX = YES
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW = YES
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE = 1
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. To get the times font for
+# instance you can specify
+# EXTRA_PACKAGES=times
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empy string,
+# for the replacement values of the other commands the user is refered to
+# HTML_HEADER.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE = plain
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT = docbook
+
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
+# Definitions (see http://autogen.sf.net) file that captures the structure of
+# the code including all documentation. Note that this feature is still
+# experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
+# in the source code. If set to NO only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF = YES
+
+# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED = __DOXYGEN__ \
+ PROGMEM \
+ ATTR_NO_INIT
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
+# class index. If set to NO only the inherited external classes will be listed.
+# The default value is: NO.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
+# the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS = YES
+
+# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS = NO
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME =
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH = NO
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH = NO
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS = NO
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH = NO
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH = NO
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY = NO
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH = NO
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot.
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif and svg.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+PLANTUML_JAR_PATH =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES = 15
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH = 2
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT = YES
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP = YES
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/makefile b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/makefile
new file mode 100644
index 000000000..9b91cc63f
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/DFU/makefile
@@ -0,0 +1,55 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2014.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+# --------------------------------------
+# LUFA Project Makefile.
+# --------------------------------------
+
+# Run "make help" for target help.
+
+MCU = at90usb1287
+ARCH = AVR8
+BOARD = USBKEY
+F_CPU = 8000000
+F_USB = $(F_CPU)
+OPTIMIZATION = s
+TARGET = BootloaderDFU
+SRC = $(TARGET).c Descriptors.c BootloaderAPI.c BootloaderAPITable.S $(LUFA_SRC_USB)
+LUFA_PATH = ../../LUFA
+CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -IConfig/ -DBOOT_START_ADDR=$(BOOT_START_OFFSET)
+LD_FLAGS = -Wl,--section-start=.text=$(BOOT_START_OFFSET) $(BOOT_API_LD_FLAGS)
+
+# Flash size and bootloader section sizes of the target, in KB. These must
+# match the target's total FLASH size and the bootloader size set in the
+# device's fuses.
+FLASH_SIZE_KB = 128
+BOOT_SECTION_SIZE_KB = 8
+
+# Bootloader address calculation formulas
+# Do not modify these macros, but rather modify the dependent values above.
+CALC_ADDRESS_IN_HEX = $(shell printf "0x%X" $$(( $(1) )) )
+BOOT_START_OFFSET = $(call CALC_ADDRESS_IN_HEX, ($(FLASH_SIZE_KB) - $(BOOT_SECTION_SIZE_KB)) * 1024 )
+BOOT_SEC_OFFSET = $(call CALC_ADDRESS_IN_HEX, ($(FLASH_SIZE_KB) * 1024) - ($(strip $(1))) )
+
+# Bootloader linker section flags for relocating the API table sections to
+# known FLASH addresses - these should not normally be user-edited.
+BOOT_SECTION_LD_FLAG = -Wl,--section-start=$(strip $(1))=$(call BOOT_SEC_OFFSET, $(3)) -Wl,--undefined=$(strip $(2))
+BOOT_API_LD_FLAGS = $(call BOOT_SECTION_LD_FLAG, .apitable_trampolines, BootloaderAPI_Trampolines, 96)
+BOOT_API_LD_FLAGS += $(call BOOT_SECTION_LD_FLAG, .apitable_jumptable, BootloaderAPI_JumpTable, 32)
+BOOT_API_LD_FLAGS += $(call BOOT_SECTION_LD_FLAG, .apitable_signatures, BootloaderAPI_Signatures, 8)
+
+# Default target
+all:
+
+# Include LUFA build script makefiles
+include $(LUFA_PATH)/Build/lufa_core.mk
+include $(LUFA_PATH)/Build/lufa_sources.mk
+include $(LUFA_PATH)/Build/lufa_build.mk
+include $(LUFA_PATH)/Build/lufa_cppcheck.mk
+include $(LUFA_PATH)/Build/lufa_doxygen.mk
+include $(LUFA_PATH)/Build/lufa_avrdude.mk
+include $(LUFA_PATH)/Build/lufa_atprogram.mk
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/BootloaderHID.c b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/BootloaderHID.c
new file mode 100644
index 000000000..518029ac4
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/BootloaderHID.c
@@ -0,0 +1,190 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Main source file for the HID class bootloader. This file contains the complete bootloader logic.
+ */
+
+#include "BootloaderHID.h"
+
+/** Flag to indicate if the bootloader should be running, or should exit and allow the application code to run
+ * via a soft reset. When cleared, the bootloader will abort, the USB interface will shut down and the application
+ * started via a forced watchdog reset.
+ */
+static bool RunBootloader = true;
+
+/** Magic lock for forced application start. If the HWBE fuse is programmed and BOOTRST is unprogrammed, the bootloader
+ * will start if the /HWB line of the AVR is held low and the system is reset. However, if the /HWB line is still held
+ * low when the application attempts to start via a watchdog reset, the bootloader will re-start. If set to the value
+ * \ref MAGIC_BOOT_KEY the special init function \ref Application_Jump_Check() will force the application to start.
+ */
+uint16_t MagicBootKey ATTR_NO_INIT;
+
+
+/** Special startup routine to check if the bootloader was started via a watchdog reset, and if the magic application
+ * start key has been loaded into \ref MagicBootKey. If the bootloader started via the watchdog and the key is valid,
+ * this will force the user application to start via a software jump.
+ */
+void Application_Jump_Check(void)
+{
+ /* If the reset source was the bootloader and the key is correct, clear it and jump to the application */
+ if ((MCUSR & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY))
+ {
+ MagicBootKey = 0;
+
+ // cppcheck-suppress constStatement
+ ((void (*)(void))0x0000)();
+ }
+}
+
+/** Main program entry point. This routine configures the hardware required by the bootloader, then continuously
+ * runs the bootloader processing routine until instructed to soft-exit.
+ */
+int main(void)
+{
+ /* Setup hardware required for the bootloader */
+ SetupHardware();
+
+ /* Enable global interrupts so that the USB stack can function */
+ GlobalInterruptEnable();
+
+ while (RunBootloader)
+ USB_USBTask();
+
+ /* Disconnect from the host - USB interface will be reset later along with the AVR */
+ USB_Detach();
+
+ /* Unlock the forced application start mode of the bootloader if it is restarted */
+ MagicBootKey = MAGIC_BOOT_KEY;
+
+ /* Enable the watchdog and force a timeout to reset the AVR */
+ wdt_enable(WDTO_250MS);
+
+ for (;;);
+}
+
+/** Configures all hardware required for the bootloader. */
+static void SetupHardware(void)
+{
+ /* Disable watchdog if enabled by bootloader/fuses */
+ MCUSR &= ~(1 << WDRF);
+ wdt_disable();
+
+ /* Relocate the interrupt vector table to the bootloader section */
+ MCUCR = (1 << IVCE);
+ MCUCR = (1 << IVSEL);
+
+ /* Initialize USB subsystem */
+ USB_Init();
+}
+
+/** Event handler for the USB_ConfigurationChanged event. This configures the device's endpoints ready
+ * to relay data to and from the attached USB host.
+ */
+void EVENT_USB_Device_ConfigurationChanged(void)
+{
+ /* Setup HID Report Endpoint */
+ Endpoint_ConfigureEndpoint(HID_IN_EPADDR, EP_TYPE_INTERRUPT, HID_IN_EPSIZE, 1);
+}
+
+/** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent to
+ * the device from the USB host before passing along unhandled control requests to the library for processing
+ * internally.
+ */
+void EVENT_USB_Device_ControlRequest(void)
+{
+ /* Ignore any requests that aren't directed to the HID interface */
+ if ((USB_ControlRequest.bmRequestType & (CONTROL_REQTYPE_TYPE | CONTROL_REQTYPE_RECIPIENT)) !=
+ (REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ return;
+ }
+
+ /* Process HID specific control requests */
+ switch (USB_ControlRequest.bRequest)
+ {
+ case HID_REQ_SetReport:
+ Endpoint_ClearSETUP();
+
+ /* Wait until the command has been sent by the host */
+ while (!(Endpoint_IsOUTReceived()));
+
+ /* Read in the write destination address */
+ #if (FLASHEND > 0xFFFF)
+ uint32_t PageAddress = ((uint32_t)Endpoint_Read_16_LE() << 8);
+ #else
+ uint16_t PageAddress = Endpoint_Read_16_LE();
+ #endif
+
+ /* Check if the command is a program page command, or a start application command */
+ #if (FLASHEND > 0xFFFF)
+ if ((uint16_t)(PageAddress >> 8) == COMMAND_STARTAPPLICATION)
+ #else
+ if (PageAddress == COMMAND_STARTAPPLICATION)
+ #endif
+ {
+ RunBootloader = false;
+ }
+ else
+ {
+ /* Erase the given FLASH page, ready to be programmed */
+ boot_page_erase(PageAddress);
+ boot_spm_busy_wait();
+
+ /* Write each of the FLASH page's bytes in sequence */
+ for (uint8_t PageWord = 0; PageWord < (SPM_PAGESIZE / 2); PageWord++)
+ {
+ /* Check if endpoint is empty - if so clear it and wait until ready for next packet */
+ if (!(Endpoint_BytesInEndpoint()))
+ {
+ Endpoint_ClearOUT();
+ while (!(Endpoint_IsOUTReceived()));
+ }
+
+ /* Write the next data word to the FLASH page */
+ boot_page_fill(PageAddress + ((uint16_t)PageWord << 1), Endpoint_Read_16_LE());
+ }
+
+ /* Write the filled FLASH page to memory */
+ boot_page_write(PageAddress);
+ boot_spm_busy_wait();
+
+ /* Re-enable RWW section */
+ boot_rww_enable();
+ }
+
+ Endpoint_ClearOUT();
+
+ Endpoint_ClearStatusStage();
+ break;
+ }
+}
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/BootloaderHID.h b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/BootloaderHID.h
new file mode 100644
index 000000000..8efd47ec2
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/BootloaderHID.h
@@ -0,0 +1,73 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Header file for BootloaderHID.c.
+ */
+
+#ifndef _BOOTLOADERHID_H_
+#define _BOOTLOADERHID_H_
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <avr/wdt.h>
+ #include <avr/boot.h>
+ #include <avr/power.h>
+ #include <avr/interrupt.h>
+ #include <stdbool.h>
+
+ #include "Descriptors.h"
+
+ #include <LUFA/Drivers/USB/USB.h>
+ #include <LUFA/Platform/Platform.h>
+
+ /* Preprocessor Checks: */
+ #if !defined(__OPTIMIZE_SIZE__)
+ #error This bootloader requires that it be optimized for size, not speed, to fit into the target device. Change optimization settings and try again.
+ #endif
+
+ /* Macros: */
+ /** Bootloader special address to start the user application */
+ #define COMMAND_STARTAPPLICATION 0xFFFF
+
+ /** Magic bootloader key to unlock forced application start mode. */
+ #define MAGIC_BOOT_KEY 0xDC42
+
+ /* Function Prototypes: */
+ static void SetupHardware(void);
+
+ void Application_Jump_Check(void) ATTR_INIT_SECTION(3);
+
+ void EVENT_USB_Device_ConfigurationChanged(void);
+ void EVENT_USB_Device_UnhandledControlRequest(void);
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/BootloaderHID.txt b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/BootloaderHID.txt
new file mode 100644
index 000000000..63c1505cc
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/BootloaderHID.txt
@@ -0,0 +1,105 @@
+/** \file
+ *
+ * This file contains special DoxyGen information for the generation of the main page and other special
+ * documentation pages. It is not a project source file.
+ */
+
+/** \mainpage HID Class USB AVR Bootloader
+ *
+ * \section SSec_Compat Demo Compatibility:
+ *
+ * The following list indicates what microcontrollers are compatible with this demo.
+ *
+ * \li Series 7 USB AVRs (AT90USBxxx7)
+ * \li Series 6 USB AVRs (AT90USBxxx6)
+ * \li Series 4 USB AVRs (ATMEGAxxU4)
+ * \li Series 2 USB AVRs (AT90USBxx2, ATMEGAxxU2)
+ *
+ * \section SSec_Info USB Information:
+ *
+ * The following table gives a rundown of the USB utilization of this demo.
+ *
+ * <table>
+ * <tr>
+ * <td><b>USB Mode:</b></td>
+ * <td>Device</td>
+ * </tr>
+ * <tr>
+ * <td><b>USB Class:</b></td>
+ * <td>Human Interface Device Class (HID)</td>
+ * </tr>
+ * <tr>
+ * <td><b>USB Subclass:</b></td>
+ * <td>N/A</td>
+ * </tr>
+ * <tr>
+ * <td><b>Relevant Standards:</b></td>
+ * <td>USBIF HID Class Standard \n
+ * Teensy Programming Protocol Specification</td>
+ * </tr>
+ * <tr>
+ * <td><b>Supported USB Speeds:</b></td>
+ * <td>Low Speed Mode \n
+ * Full Speed Mode</td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_Description Project Description:
+ *
+ * This bootloader enumerates to the host as a HID Class device, allowing for device FLASH programming through
+ * the supplied command line software, which is a modified version of Paul's TeensyHID Command Line loader code
+ * from PJRC (used with permission). This bootloader is deliberately non-compatible with the proprietary PJRC
+ * HalfKay bootloader GUI; only the command line interface software accompanying this bootloader will work with it.
+ *
+ * Out of the box this bootloader builds for the AT90USB1287 with an 8KB bootloader section size, and will fit
+ * into 2KB of bootloader space for the Series 2 USB AVRs (ATMEGAxxU2, AT90USBxx2) or 4KB of bootloader space for
+ * all other models. If you wish to alter this size and/or change the AVR model, you will need to edit the MCU,
+ * FLASH_SIZE_KB and BOOT_SECTION_SIZE_KB values in the accompanying makefile.
+ *
+ * \warning <b>THIS BOOTLOADER IS NOT SECURE.</b> Malicious entities can recover written data, even if the device
+ * lockbits are set.
+ *
+ * \section Sec_Running Running the Bootloader
+ *
+ * This bootloader is designed to be started via the HWB mechanism of the USB AVRs; ground the HWB pin (see device
+ * datasheet) then momentarily ground /RESET to start the bootloader. This assumes the HWBE fuse is set and the BOOTRST
+ * fuse is cleared.
+ *
+ * \section Sec_Installation Driver Installation
+ *
+ * This bootloader uses the HID class driver inbuilt into all modern operating systems, thus no additional drivers
+ * need to be supplied for correct operation.
+ *
+ * \section Sec_HostApp Host Controller Application
+ *
+ * Due to licensing issues, the supplied bootloader is compatible with the HalfKay bootloader protocol designed
+ * by PJRC, but is non-compatible with the cross-platform loader GUI. A modified version of the open source
+ * cross-platform TeensyLoader application is supplied, which can be compiled under most operating systems. The
+ * command-line loader application should remain compatible with genuine Teensy boards in addition to boards using
+ * this custom bootloader.
+ *
+ * Once compiled, programs can be loaded into the AVR's FLASH memory through the following example command:
+ * \code
+ * hid_bootloader_cli -mmcu=at90usb1287 Mouse.hex
+ * \endcode
+ *
+ * \section Sec_KnownIssues Known Issues:
+ *
+ * \par After loading an application, it is not run automatically on startup.
+ * Some USB AVR boards ship with the BOOTRST fuse set, causing the bootloader
+ * to run automatically when the device is reset. In most cases, the BOOTRST
+ * fuse should be disabled and the HWBE fuse used instead to run the bootloader
+ * when needed.
+ *
+ * \section SSec_Options Project Options
+ *
+ * The following defines can be found in this demo, which can control the demo behaviour when defined, or changed in value.
+ *
+ * <table>
+ * <tr>
+ * <td>
+ * None
+ * </td>
+ * </tr>
+ * </table>
+ */
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/Config/LUFAConfig.h b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/Config/LUFAConfig.h
new file mode 100644
index 000000000..af2dd3060
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/Config/LUFAConfig.h
@@ -0,0 +1,93 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief LUFA Library Configuration Header File
+ *
+ * This header file is used to configure LUFA's compile time options,
+ * as an alternative to the compile time constants supplied through
+ * a makefile.
+ *
+ * For information on what each token does, refer to the LUFA
+ * manual section "Summary of Compile Tokens".
+ */
+
+#ifndef _LUFA_CONFIG_H_
+#define _LUFA_CONFIG_H_
+
+ #if (ARCH == ARCH_AVR8)
+
+ /* Non-USB Related Configuration Tokens: */
+// #define DISABLE_TERMINAL_CODES
+
+ /* USB Class Driver Related Tokens: */
+// #define HID_HOST_BOOT_PROTOCOL_ONLY
+// #define HID_STATETABLE_STACK_DEPTH {Insert Value Here}
+// #define HID_USAGE_STACK_DEPTH {Insert Value Here}
+// #define HID_MAX_COLLECTIONS {Insert Value Here}
+// #define HID_MAX_REPORTITEMS {Insert Value Here}
+// #define HID_MAX_REPORT_IDS {Insert Value Here}
+// #define NO_CLASS_DRIVER_AUTOFLUSH
+
+ /* General USB Driver Related Tokens: */
+ #define ORDERED_EP_CONFIG
+ #define USE_STATIC_OPTIONS (USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)
+ #define USB_DEVICE_ONLY
+// #define USB_HOST_ONLY
+// #define USB_STREAM_TIMEOUT_MS {Insert Value Here}
+// #define NO_LIMITED_CONTROLLER_CONNECT
+ #define NO_SOF_EVENTS
+
+ /* USB Device Mode Driver Related Tokens: */
+ #define USE_RAM_DESCRIPTORS
+// #define USE_FLASH_DESCRIPTORS
+// #define USE_EEPROM_DESCRIPTORS
+ #define NO_INTERNAL_SERIAL
+ #define FIXED_CONTROL_ENDPOINT_SIZE 8
+ #define DEVICE_STATE_AS_GPIOR 0
+ #define FIXED_NUM_CONFIGURATIONS 1
+// #define CONTROL_ONLY_DEVICE
+// #define INTERRUPT_CONTROL_ENDPOINT
+ #define NO_DEVICE_REMOTE_WAKEUP
+ #define NO_DEVICE_SELF_POWER
+
+ /* USB Host Mode Driver Related Tokens: */
+// #define HOST_STATE_AS_GPIOR {Insert Value Here}
+// #define USB_HOST_TIMEOUT_MS {Insert Value Here}
+// #define HOST_DEVICE_SETTLE_DELAY_MS {Insert Value Here}
+// #define NO_AUTO_VBUS_MANAGEMENT
+// #define INVERTED_VBUS_ENABLE_LINE
+
+ #else
+
+ #error Unsupported architecture for this LUFA configuration file.
+
+ #endif
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/Descriptors.c b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/Descriptors.c
new file mode 100644
index 000000000..3eaa19295
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/Descriptors.c
@@ -0,0 +1,187 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * USB Device Descriptors, for library use when in USB device mode. Descriptors are special
+ * computer-readable structures which the host requests upon device enumeration, to determine
+ * the device's capabilities and functions.
+ */
+
+#include "Descriptors.h"
+
+/** HID class report descriptor. This is a special descriptor constructed with values from the
+ * USBIF HID class specification to describe the reports and capabilities of the HID device. This
+ * descriptor is parsed by the host and its contents used to determine what data (and in what encoding)
+ * the device will send, and what it may be sent back from the host. Refer to the HID specification for
+ * more details on HID report descriptors.
+ */
+const USB_Descriptor_HIDReport_Datatype_t HIDReport[] =
+{
+ HID_RI_USAGE_PAGE(16, 0xFFDC), /* Vendor Page 0xDC */
+ HID_RI_USAGE(8, 0xFB), /* Vendor Usage 0xFB */
+ HID_RI_COLLECTION(8, 0x01), /* Vendor Usage 1 */
+ HID_RI_USAGE(8, 0x02), /* Vendor Usage 2 */
+ HID_RI_LOGICAL_MINIMUM(8, 0x00),
+ HID_RI_LOGICAL_MAXIMUM(8, 0xFF),
+ HID_RI_REPORT_SIZE(8, 0x08),
+ HID_RI_REPORT_COUNT(16, (sizeof(uint16_t) + SPM_PAGESIZE)),
+ HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
+ HID_RI_END_COLLECTION(0),
+};
+
+/** Device descriptor structure. This descriptor, located in SRAM memory, describes the overall
+ * device characteristics, including the supported USB version, control endpoint size and the
+ * number of device configurations. The descriptor is read out by the USB host when the enumeration
+ * process begins.
+ */
+const USB_Descriptor_Device_t DeviceDescriptor =
+{
+ .Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
+
+ .USBSpecification = VERSION_BCD(1,1,0),
+ .Class = USB_CSCP_NoDeviceClass,
+ .SubClass = USB_CSCP_NoDeviceSubclass,
+ .Protocol = USB_CSCP_NoDeviceProtocol,
+
+ .Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
+
+ .VendorID = 0x03EB,
+ .ProductID = 0x2067,
+ .ReleaseNumber = VERSION_BCD(0,0,1),
+
+ .ManufacturerStrIndex = NO_DESCRIPTOR,
+ .ProductStrIndex = NO_DESCRIPTOR,
+ .SerialNumStrIndex = NO_DESCRIPTOR,
+
+ .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
+};
+
+/** Configuration descriptor structure. This descriptor, located in SRAM memory, describes the usage
+ * of the device in one of its supported configurations, including information about any device interfaces
+ * and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting
+ * a configuration so that the host may correctly communicate with the USB device.
+ */
+const USB_Descriptor_Configuration_t ConfigurationDescriptor =
+{
+ .Config =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration},
+
+ .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
+ .TotalInterfaces = 1,
+
+ .ConfigurationNumber = 1,
+ .ConfigurationStrIndex = NO_DESCRIPTOR,
+
+ .ConfigAttributes = USB_CONFIG_ATTR_RESERVED,
+
+ .MaxPowerConsumption = USB_CONFIG_POWER_MA(100)
+ },
+
+ .HID_Interface =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
+
+ .InterfaceNumber = INTERFACE_ID_Printer,
+ .AlternateSetting = 0x00,
+
+ .TotalEndpoints = 1,
+
+ .Class = HID_CSCP_HIDClass,
+ .SubClass = HID_CSCP_NonBootSubclass,
+ .Protocol = HID_CSCP_NonBootProtocol,
+
+ .InterfaceStrIndex = NO_DESCRIPTOR
+ },
+
+ .HID_VendorHID =
+ {
+ .Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
+
+ .HIDSpec = VERSION_BCD(1,1,1),
+ .CountryCode = 0x00,
+ .TotalReportDescriptors = 1,
+ .HIDReportType = HID_DTYPE_Report,
+ .HIDReportLength = sizeof(HIDReport)
+ },
+
+ .HID_ReportINEndpoint =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
+
+ .EndpointAddress = HID_IN_EPADDR,
+ .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
+ .EndpointSize = HID_IN_EPSIZE,
+ .PollingIntervalMS = 0x05
+ },
+};
+
+/** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
+ * documentation) by the application code so that the address and size of a requested descriptor can be given
+ * to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function
+ * is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the
+ * USB host.
+ */
+uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+ const uint8_t wIndex,
+ const void** const DescriptorAddress)
+{
+ const uint8_t DescriptorType = (wValue >> 8);
+
+ const void* Address = NULL;
+ uint16_t Size = NO_DESCRIPTOR;
+
+ /* If/Else If chain compiles slightly smaller than a switch case */
+ if (DescriptorType == DTYPE_Device)
+ {
+ Address = &DeviceDescriptor;
+ Size = sizeof(USB_Descriptor_Device_t);
+ }
+ else if (DescriptorType == DTYPE_Configuration)
+ {
+ Address = &ConfigurationDescriptor;
+ Size = sizeof(USB_Descriptor_Configuration_t);
+ }
+ else if (DescriptorType == HID_DTYPE_HID)
+ {
+ Address = &ConfigurationDescriptor.HID_VendorHID;
+ Size = sizeof(USB_HID_Descriptor_HID_t);
+ }
+ else
+ {
+ Address = &HIDReport;
+ Size = sizeof(HIDReport);
+ }
+
+ *DescriptorAddress = Address;
+ return Size;
+}
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/Descriptors.h b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/Descriptors.h
new file mode 100644
index 000000000..4c7d08b51
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/Descriptors.h
@@ -0,0 +1,80 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Header file for Descriptors.c.
+ */
+
+#ifndef _DESCRIPTORS_H_
+#define _DESCRIPTORS_H_
+
+ /* Includes: */
+ #include <LUFA/Drivers/USB/USB.h>
+
+ /* Type Defines: */
+ /** Type define for the device configuration descriptor structure. This must be defined in the
+ * application code, as the configuration descriptor contains several sub-descriptors which
+ * vary between devices, and which describe the device's usage to the host.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Configuration_Header_t Config;
+
+ // Generic HID Interface
+ USB_Descriptor_Interface_t HID_Interface;
+ USB_HID_Descriptor_HID_t HID_VendorHID;
+ USB_Descriptor_Endpoint_t HID_ReportINEndpoint;
+ } USB_Descriptor_Configuration_t;
+
+ /** Enum for the device interface descriptor IDs within the device. Each interface descriptor
+ * should have a unique ID index associated with it, which can be used to refer to the
+ * interface from other descriptors.
+ */
+ enum InterfaceDescriptors_t
+ {
+ INTERFACE_ID_Printer = 0, /**< Printer interface descriptor ID */
+ };
+
+ /* Macros: */
+ /** Endpoint address of the HID data IN endpoint. */
+ #define HID_IN_EPADDR (ENDPOINT_DIR_IN | 1)
+
+ /** Size in bytes of the HID reporting IN endpoint. */
+ #define HID_IN_EPSIZE 64
+
+ /* Function Prototypes: */
+ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+ const uint8_t wIndex,
+ const void** const DescriptorAddress)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/HostLoaderApp/Makefile b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/HostLoaderApp/Makefile
new file mode 100644
index 000000000..7b2833e62
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/HostLoaderApp/Makefile
@@ -0,0 +1,39 @@
+OS ?= LINUX
+#OS ?= WINDOWS
+#OS ?= MACOSX
+#OS ?= BSD
+
+ifeq ($(OS), LINUX) # also works on FreeBSD
+CC ?= gcc
+CFLAGS ?= -O2 -Wall
+hid_bootloader_cli: hid_bootloader_cli.c
+ $(CC) $(CFLAGS) -s -DUSE_LIBUSB -o hid_bootloader_cli hid_bootloader_cli.c -lusb
+
+
+else ifeq ($(OS), WINDOWS)
+CC = i586-mingw32msvc-gcc
+CFLAGS ?= -O2 -Wall
+hid_bootloader_cli.exe: hid_bootloader_cli.c
+ $(CC) $(CFLAGS) -s -DUSE_WIN32 -o hid_bootloader_cli.exe hid_bootloader_cli.c -lhid -lsetupapi
+
+
+else ifeq ($(OS), MACOSX)
+CC ?= gcc
+SDK ?= /Developer/SDKs/MacOSX10.5.sdk
+CFLAGS ?= -O2 -Wall
+hid_bootloader_cli: hid_bootloader_cli.c
+ $(CC) $(CFLAGS) -DUSE_APPLE_IOKIT -isysroot $(SDK) -o hid_bootloader_cli hid_bootloader_cli.c -Wl,-syslibroot,$(SDK) -framework IOKit -framework CoreFoundation
+
+
+else ifeq ($(OS), BSD) # works on NetBSD and OpenBSD
+CC ?= gcct
+CFLAGS ?= -O2 -Wall
+hid_bootloader_cli: hid_bootloader_cli.c
+ $(CC) $(CFLAGS) -s -DUSE_UHID -o hid_bootloader_cli hid_bootloader_cli.c
+
+
+endif
+
+
+clean:
+ rm -f hid_bootloader_cli hid_bootloader_cli.exe
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/HostLoaderApp/Makefile.bsd b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/HostLoaderApp/Makefile.bsd
new file mode 100644
index 000000000..a15a66405
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/HostLoaderApp/Makefile.bsd
@@ -0,0 +1,21 @@
+OS ?= FreeBSD
+#OS ?= NetBSD
+#OS ?= OpenBSD
+
+CFLAGS ?= -O2 -Wall
+CC ?= gcc
+
+.if $(OS) == "FreeBSD"
+CFLAGS += -DUSE_LIBUSB
+LIBS = -lusb
+.elif $(OS) == "NetBSD" || $(OS) == "OpenBSD"
+CFLAGS += -DUSE_UHID
+LIBS =
+.endif
+
+
+hid_bootloader_cli: hid_bootloader_cli.c
+ $(CC) $(CFLAGS) -s -o hid_bootloader_cli hid_bootloader_cli.c $(LIBS)
+
+clean:
+ rm -f hid_bootloader_cli
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/HostLoaderApp/gpl3.txt b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/HostLoaderApp/gpl3.txt
new file mode 100644
index 000000000..94a9ed024
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/HostLoaderApp/gpl3.txt
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/HostLoaderApp/hid_bootloader_cli.c b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/HostLoaderApp/hid_bootloader_cli.c
new file mode 100644
index 000000000..058ccc63d
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/HostLoaderApp/hid_bootloader_cli.c
@@ -0,0 +1,1010 @@
+/* Modified for the LUFA HID Bootloader by Dean Camera
+ * http://www.lufa-lib.org
+ *
+ * THIS MODIFIED VERSION IS UNSUPPORTED BY PJRC.
+ */
+
+/* Teensy Loader, Command Line Interface
+ * Program and Reboot Teensy Board with HalfKay Bootloader
+ * http://www.pjrc.com/teensy/loader_cli.html
+ * Copyright 2008-2010, PJRC.COM, LLC
+ *
+ *
+ * You may redistribute this program and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software
+ * Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/
+ */
+
+/* Want to incorporate this code into a proprietary application??
+ * Just email paul@pjrc.com to ask. Usually it's not a problem,
+ * but you do need to ask to use this code in any way other than
+ * those permitted by the GNU General Public License, version 3 */
+
+/* For non-root permissions on ubuntu or similar udev-based linux
+ * http://www.pjrc.com/teensy/49-teensy.rules
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+
+void usage(void)
+{
+ fprintf(stderr, "Usage: hid_bootloader_cli -mmcu=<MCU> [-w] [-h] [-n] [-v] <file.hex>\n");
+ fprintf(stderr, "\t-w : Wait for device to appear\n");
+ fprintf(stderr, "\t-r : Use hard reboot if device not online\n");
+ fprintf(stderr, "\t-n : No reboot after programming\n");
+ fprintf(stderr, "\t-v : Verbose output\n");
+ fprintf(stderr, "\n<MCU> = atmegaXXuY or at90usbXXXY");
+
+ fprintf(stderr, "\nFor support and more information, please visit:\n");
+ fprintf(stderr, "http://www.lufa-lib.org\n");
+
+ fprintf(stderr, "\nBased on the TeensyHID command line programmer software:\n");
+ fprintf(stderr, "http://www.pjrc.com/teensy/loader_cli.html\n");
+ exit(1);
+}
+
+// USB Access Functions
+int teensy_open(void);
+int teensy_write(void *buf, int len, double timeout);
+void teensy_close(void);
+int hard_reboot(void);
+
+// Intel Hex File Functions
+int read_intel_hex(const char *filename);
+int ihex_bytes_within_range(int begin, int end);
+void ihex_get_data(int addr, int len, unsigned char *bytes);
+
+// Misc stuff
+int printf_verbose(const char *format, ...);
+void delay(double seconds);
+void die(const char *str, ...);
+void parse_options(int argc, char **argv);
+
+// options (from user via command line args)
+int wait_for_device_to_appear = 0;
+int hard_reboot_device = 0;
+int reboot_after_programming = 1;
+int verbose = 0;
+int code_size = 0, block_size = 0;
+const char *filename=NULL;
+
+
+/****************************************************************/
+/* */
+/* Main Program */
+/* */
+/****************************************************************/
+
+int main(int argc, char **argv)
+{
+ unsigned char buf[260];
+ int num, addr, r, first_block=1, waited=0;
+
+ // parse command line arguments
+ parse_options(argc, argv);
+ if (!filename) {
+ fprintf(stderr, "Filename must be specified\n\n");
+ usage();
+ }
+ if (!code_size) {
+ fprintf(stderr, "MCU type must be specified\n\n");
+ usage();
+ }
+ printf_verbose("Teensy Loader, Command Line, Version 2.0\n");
+
+ // read the intel hex file
+ // this is done first so any error is reported before using USB
+ num = read_intel_hex(filename);
+ if (num < 0) die("error reading intel hex file \"%s\"", filename);
+ printf_verbose("Read \"%s\": %d bytes, %.1f%% usage\n",
+ filename, num, (double)num / (double)code_size * 100.0);
+
+ // open the USB device
+ while (1) {
+ if (teensy_open()) break;
+ if (hard_reboot_device) {
+ if (!hard_reboot()) die("Unable to find rebootor\n");
+ printf_verbose("Hard Reboot performed\n");
+ hard_reboot_device = 0; // only hard reboot once
+ wait_for_device_to_appear = 1;
+ }
+ if (!wait_for_device_to_appear) die("Unable to open device\n");
+ if (!waited) {
+ printf_verbose("Waiting for Teensy device...\n");
+ printf_verbose(" (hint: press the reset button)\n");
+ waited = 1;
+ }
+ delay(0.25);
+ }
+ printf_verbose("Found HalfKay Bootloader\n");
+
+ // if we waited for the device, read the hex file again
+ // perhaps it changed while we were waiting?
+ if (waited) {
+ num = read_intel_hex(filename);
+ if (num < 0) die("error reading intel hex file \"%s\"", filename);
+ printf_verbose("Read \"%s\": %d bytes, %.1f%% usage\n",
+ filename, num, (double)num / (double)code_size * 100.0);
+ }
+
+ // program the data
+ printf_verbose("Programming");
+ fflush(stdout);
+ for (addr = 0; addr < code_size; addr += block_size) {
+ if (addr > 0 && !ihex_bytes_within_range(addr, addr + block_size - 1)) {
+ // don't waste time on blocks that are unused,
+ // but always do the first one to erase the chip
+ continue;
+ }
+ printf_verbose(".");
+ if (code_size < 0x10000) {
+ buf[0] = addr & 255;
+ buf[1] = (addr >> 8) & 255;
+ } else {
+ buf[0] = (addr >> 8) & 255;
+ buf[1] = (addr >> 16) & 255;
+ }
+ ihex_get_data(addr, block_size, buf + 2);
+ r = teensy_write(buf, block_size + 2, first_block ? 3.0 : 0.25);
+ if (!r) die("error writing to Teensy\n");
+ first_block = 0;
+ }
+ printf_verbose("\n");
+
+ // reboot to the user's new code
+ if (reboot_after_programming) {
+ printf_verbose("Booting\n");
+ buf[0] = 0xFF;
+ buf[1] = 0xFF;
+ memset(buf + 2, 0, sizeof(buf) - 2);
+ teensy_write(buf, block_size + 2, 0.25);
+ }
+ teensy_close();
+ return 0;
+}
+
+
+
+
+/****************************************************************/
+/* */
+/* USB Access - libusb (Linux & FreeBSD) */
+/* */
+/****************************************************************/
+
+#if defined(USE_LIBUSB)
+
+// http://libusb.sourceforge.net/doc/index.html
+#include <usb.h>
+
+usb_dev_handle * open_usb_device(int vid, int pid)
+{
+ struct usb_bus *bus;
+ struct usb_device *dev;
+ usb_dev_handle *h;
+ #ifdef LIBUSB_HAS_GET_DRIVER_NP
+ char buf[128];
+ #endif
+ int r;
+
+ usb_init();
+ usb_find_busses();
+ usb_find_devices();
+ //printf_verbose("\nSearching for USB device:\n");
+ for (bus = usb_get_busses(); bus; bus = bus->next) {
+ for (dev = bus->devices; dev; dev = dev->next) {
+ //printf_verbose("bus \"%s\", device \"%s\" vid=%04X, pid=%04X\n",
+ // bus->dirname, dev->filename,
+ // dev->descriptor.idVendor,
+ // dev->descriptor.idProduct
+ //);
+ if (dev->descriptor.idVendor != vid) continue;
+ if (dev->descriptor.idProduct != pid) continue;
+ h = usb_open(dev);
+ if (!h) {
+ printf_verbose("Found device but unable to open");
+ continue;
+ }
+ #ifdef LIBUSB_HAS_GET_DRIVER_NP
+ r = usb_get_driver_np(h, 0, buf, sizeof(buf));
+ if (r >= 0) {
+ r = usb_detach_kernel_driver_np(h, 0);
+ if (r < 0) {
+ usb_close(h);
+ printf_verbose("Device is in use by \"%s\" driver", buf);
+ continue;
+ }
+ }
+ #endif
+ // Mac OS-X - removing this call to usb_claim_interface() might allow
+ // this to work, even though it is a clear misuse of the libusb API.
+ // normally Apple's IOKit should be used on Mac OS-X
+ r = usb_claim_interface(h, 0);
+ if (r < 0) {
+ usb_close(h);
+ printf_verbose("Unable to claim interface, check USB permissions");
+ continue;
+ }
+ return h;
+ }
+ }
+ return NULL;
+}
+
+static usb_dev_handle *libusb_teensy_handle = NULL;
+
+int teensy_open(void)
+{
+ teensy_close();
+ libusb_teensy_handle = open_usb_device(0x16C0, 0x0478);
+
+ if (!libusb_teensy_handle)
+ libusb_teensy_handle = open_usb_device(0x03eb, 0x2067);
+
+ if (!libusb_teensy_handle) return 0;
+ return 1;
+}
+
+int teensy_write(void *buf, int len, double timeout)
+{
+ int r;
+
+ if (!libusb_teensy_handle) return 0;
+ r = usb_control_msg(libusb_teensy_handle, 0x21, 9, 0x0200, 0, (char *)buf,
+ len, (int)(timeout * 1000.0));
+ if (r < 0) return 0;
+ return 1;
+}
+
+void teensy_close(void)
+{
+ if (!libusb_teensy_handle) return;
+ usb_release_interface(libusb_teensy_handle, 0);
+ usb_close(libusb_teensy_handle);
+ libusb_teensy_handle = NULL;
+}
+
+int hard_reboot(void)
+{
+ usb_dev_handle *rebootor;
+ int r;
+
+ rebootor = open_usb_device(0x16C0, 0x0477);
+
+ if (!rebootor)
+ rebootor = open_usb_device(0x03eb, 0x2067);
+
+ if (!rebootor) return 0;
+ r = usb_control_msg(rebootor, 0x21, 9, 0x0200, 0, "reboot", 6, 100);
+ usb_release_interface(rebootor, 0);
+ usb_close(rebootor);
+ if (r < 0) return 0;
+ return 1;
+}
+
+#endif
+
+
+/****************************************************************/
+/* */
+/* USB Access - Microsoft WIN32 */
+/* */
+/****************************************************************/
+
+#if defined(USE_WIN32)
+
+// http://msdn.microsoft.com/en-us/library/ms790932.aspx
+#include <windows.h>
+#include <setupapi.h>
+#include <ddk/hidsdi.h>
+#include <ddk/hidclass.h>
+
+HANDLE open_usb_device(int vid, int pid)
+{
+ GUID guid;
+ HDEVINFO info;
+ DWORD index, required_size;
+ SP_DEVICE_INTERFACE_DATA iface;
+ SP_DEVICE_INTERFACE_DETAIL_DATA *details;
+ HIDD_ATTRIBUTES attrib;
+ HANDLE h;
+ BOOL ret;
+
+ HidD_GetHidGuid(&guid);
+ info = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
+ if (info == INVALID_HANDLE_VALUE) return NULL;
+ for (index=0; 1 ;index++) {
+ iface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
+ ret = SetupDiEnumDeviceInterfaces(info, NULL, &guid, index, &iface);
+ if (!ret) {
+ SetupDiDestroyDeviceInfoList(info);
+ break;
+ }
+ SetupDiGetInterfaceDeviceDetail(info, &iface, NULL, 0, &required_size, NULL);
+ details = (SP_DEVICE_INTERFACE_DETAIL_DATA *)malloc(required_size);
+ if (details == NULL) continue;
+ memset(details, 0, required_size);
+ details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
+ ret = SetupDiGetDeviceInterfaceDetail(info, &iface, details,
+ required_size, NULL, NULL);
+ if (!ret) {
+ free(details);
+ continue;
+ }
+ h = CreateFile(details->DevicePath, GENERIC_READ|GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
+ FILE_FLAG_OVERLAPPED, NULL);
+ free(details);
+ if (h == INVALID_HANDLE_VALUE) continue;
+ attrib.Size = sizeof(HIDD_ATTRIBUTES);
+ ret = HidD_GetAttributes(h, &attrib);
+ if (!ret) {
+ CloseHandle(h);
+ continue;
+ }
+ if (attrib.VendorID != vid || attrib.ProductID != pid) {
+ CloseHandle(h);
+ continue;
+ }
+ SetupDiDestroyDeviceInfoList(info);
+ return h;
+ }
+ return NULL;
+}
+
+int write_usb_device(HANDLE h, void *buf, int len, int timeout)
+{
+ static HANDLE event = NULL;
+ unsigned char tmpbuf[1040];
+ OVERLAPPED ov;
+ DWORD n, r;
+
+ if (len > sizeof(tmpbuf) - 1) return 0;
+ if (event == NULL) {
+ event = CreateEvent(NULL, TRUE, TRUE, NULL);
+ if (!event) return 0;
+ }
+ ResetEvent(&event);
+ memset(&ov, 0, sizeof(ov));
+ ov.hEvent = event;
+ tmpbuf[0] = 0;
+ memcpy(tmpbuf + 1, buf, len);
+ if (!WriteFile(h, tmpbuf, len + 1, NULL, &ov)) {
+ if (GetLastError() != ERROR_IO_PENDING) return 0;
+ r = WaitForSingleObject(event, timeout);
+ if (r == WAIT_TIMEOUT) {
+ CancelIo(h);
+ return 0;
+ }
+ if (r != WAIT_OBJECT_0) return 0;
+ }
+ if (!GetOverlappedResult(h, &ov, &n, FALSE)) return 0;
+ return 1;
+}
+
+static HANDLE win32_teensy_handle = NULL;
+
+int teensy_open(void)
+{
+ teensy_close();
+ win32_teensy_handle = open_usb_device(0x16C0, 0x0478);
+
+ if (!win32_teensy_handle)
+ win32_teensy_handle = open_usb_device(0x03eb, 0x2067);
+
+ if (!win32_teensy_handle) return 0;
+ return 1;
+}
+
+int teensy_write(void *buf, int len, double timeout)
+{
+ int r;
+ if (!win32_teensy_handle) return 0;
+ r = write_usb_device(win32_teensy_handle, buf, len, (int)(timeout * 1000.0));
+ return r;
+}
+
+void teensy_close(void)
+{
+ if (!win32_teensy_handle) return;
+ CloseHandle(win32_teensy_handle);
+ win32_teensy_handle = NULL;
+}
+
+int hard_reboot(void)
+{
+ HANDLE rebootor;
+ int r;
+
+ rebootor = open_usb_device(0x16C0, 0x0477);
+
+ if (!rebootor)
+ rebootor = open_usb_device(0x03eb, 0x2067);
+
+ if (!rebootor) return 0;
+ r = write_usb_device(rebootor, "reboot", 6, 100);
+ CloseHandle(rebootor);
+ return r;
+}
+
+#endif
+
+
+
+/****************************************************************/
+/* */
+/* USB Access - Apple's IOKit, Mac OS-X */
+/* */
+/****************************************************************/
+
+#if defined(USE_APPLE_IOKIT)
+
+// http://developer.apple.com/technotes/tn2007/tn2187.html
+#include <IOKit/IOKitLib.h>
+#include <IOKit/hid/IOHIDLib.h>
+#include <IOKit/hid/IOHIDDevice.h>
+
+struct usb_list_struct {
+ IOHIDDeviceRef ref;
+ int pid;
+ int vid;
+ struct usb_list_struct *next;
+};
+
+static struct usb_list_struct *usb_list=NULL;
+static IOHIDManagerRef hid_manager=NULL;
+
+void attach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev)
+{
+ CFTypeRef type;
+ struct usb_list_struct *n, *p;
+ int32_t pid, vid;
+
+ if (!dev) return;
+ type = IOHIDDeviceGetProperty(dev, CFSTR(kIOHIDVendorIDKey));
+ if (!type || CFGetTypeID(type) != CFNumberGetTypeID()) return;
+ if (!CFNumberGetValue((CFNumberRef)type, kCFNumberSInt32Type, &vid)) return;
+ type = IOHIDDeviceGetProperty(dev, CFSTR(kIOHIDProductIDKey));
+ if (!type || CFGetTypeID(type) != CFNumberGetTypeID()) return;
+ if (!CFNumberGetValue((CFNumberRef)type, kCFNumberSInt32Type, &pid)) return;
+ n = (struct usb_list_struct *)malloc(sizeof(struct usb_list_struct));
+ if (!n) return;
+ //printf("attach callback: vid=%04X, pid=%04X\n", vid, pid);
+ n->ref = dev;
+ n->vid = vid;
+ n->pid = pid;
+ n->next = NULL;
+ if (usb_list == NULL) {
+ usb_list = n;
+ } else {
+ for (p = usb_list; p->next; p = p->next) ;
+ p->next = n;
+ }
+}
+
+void detach_callback(void *context, IOReturn r, void *hid_mgr, IOHIDDeviceRef dev)
+{
+ struct usb_list_struct *p, *tmp, *prev=NULL;
+
+ p = usb_list;
+ while (p) {
+ if (p->ref == dev) {
+ if (prev) {
+ prev->next = p->next;
+ } else {
+ usb_list = p->next;
+ }
+ tmp = p;
+ p = p->next;
+ free(tmp);
+ } else {
+ prev = p;
+ p = p->next;
+ }
+ }
+}
+
+void init_hid_manager(void)
+{
+ CFMutableDictionaryRef dict;
+ IOReturn ret;
+
+ if (hid_manager) return;
+ hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
+ if (hid_manager == NULL || CFGetTypeID(hid_manager) != IOHIDManagerGetTypeID()) {
+ if (hid_manager) CFRelease(hid_manager);
+ printf_verbose("no HID Manager - maybe this is a pre-Leopard (10.5) system?\n");
+ return;
+ }
+ dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
+ &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ if (!dict) return;
+ IOHIDManagerSetDeviceMatching(hid_manager, dict);
+ CFRelease(dict);
+ IOHIDManagerScheduleWithRunLoop(hid_manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
+ IOHIDManagerRegisterDeviceMatchingCallback(hid_manager, attach_callback, NULL);
+ IOHIDManagerRegisterDeviceRemovalCallback(hid_manager, detach_callback, NULL);
+ ret = IOHIDManagerOpen(hid_manager, kIOHIDOptionsTypeNone);
+ if (ret != kIOReturnSuccess) {
+ IOHIDManagerUnscheduleFromRunLoop(hid_manager,
+ CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
+ CFRelease(hid_manager);
+ printf_verbose("Error opening HID Manager");
+ }
+}
+
+static void do_run_loop(void)
+{
+ while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true) == kCFRunLoopRunHandledSource) ;
+}
+
+IOHIDDeviceRef open_usb_device(int vid, int pid)
+{
+ struct usb_list_struct *p;
+ IOReturn ret;
+
+ init_hid_manager();
+ do_run_loop();
+ for (p = usb_list; p; p = p->next) {
+ if (p->vid == vid && p->pid == pid) {
+ ret = IOHIDDeviceOpen(p->ref, kIOHIDOptionsTypeNone);
+ if (ret == kIOReturnSuccess) return p->ref;
+ }
+ }
+ return NULL;
+}
+
+void close_usb_device(IOHIDDeviceRef dev)
+{
+ struct usb_list_struct *p;
+
+ do_run_loop();
+ for (p = usb_list; p; p = p->next) {
+ if (p->ref == dev) {
+ IOHIDDeviceClose(dev, kIOHIDOptionsTypeNone);
+ return;
+ }
+ }
+}
+
+static IOHIDDeviceRef iokit_teensy_reference = NULL;
+
+int teensy_open(void)
+{
+ teensy_close();
+ iokit_teensy_reference = open_usb_device(0x16C0, 0x0478);
+
+ if (!iokit_teensy_reference)
+ iokit_teensy_reference = open_usb_device(0x03eb, 0x2067);
+
+ if (!iokit_teensy_reference) return 0;
+ return 1;
+}
+
+int teensy_write(void *buf, int len, double timeout)
+{
+ IOReturn ret;
+
+ // timeouts do not work on OS-X
+ // IOHIDDeviceSetReportWithCallback is not implemented
+ // even though Apple documents it with a code example!
+ // submitted to Apple on 22-sep-2009, problem ID 7245050
+ if (!iokit_teensy_reference) return 0;
+ ret = IOHIDDeviceSetReport(iokit_teensy_reference,
+ kIOHIDReportTypeOutput, 0, buf, len);
+ if (ret == kIOReturnSuccess) return 1;
+ return 0;
+}
+
+void teensy_close(void)
+{
+ if (!iokit_teensy_reference) return;
+ close_usb_device(iokit_teensy_reference);
+ iokit_teensy_reference = NULL;
+}
+
+int hard_reboot(void)
+{
+ IOHIDDeviceRef rebootor;
+ IOReturn ret;
+
+ rebootor = open_usb_device(0x16C0, 0x0477);
+
+ if (!rebootor)
+ rebootor = open_usb_device(0x03eb, 0x2067);
+
+ if (!rebootor) return 0;
+ ret = IOHIDDeviceSetReport(rebootor,
+ kIOHIDReportTypeOutput, 0, (uint8_t *)("reboot"), 6);
+ close_usb_device(rebootor);
+ if (ret == kIOReturnSuccess) return 1;
+ return 0;
+}
+
+#endif
+
+
+
+/****************************************************************/
+/* */
+/* USB Access - BSD's UHID driver */
+/* */
+/****************************************************************/
+
+#if defined(USE_UHID)
+
+// Thanks to Todd T Fries for help getting this working on OpenBSD
+// and to Chris Kuethe for the initial patch to use UHID.
+
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <dev/usb/usb.h>
+#ifndef USB_GET_DEVICEINFO
+#include <dev/usb/usb_ioctl.h>
+#endif
+
+#ifndef USB_GET_DEVICEINFO
+# define USB_GET_DEVICEINFO 0
+# error The USB_GET_DEVICEINFO ioctl() value is not defined for your system.
+#endif
+
+int open_usb_device(int vid, int pid)
+{
+ int r, fd;
+ DIR *dir;
+ struct dirent *d;
+ struct usb_device_info info;
+ char buf[256];
+
+ dir = opendir("/dev");
+ if (!dir) return -1;
+ while ((d = readdir(dir)) != NULL) {
+ if (strncmp(d->d_name, "uhid", 4) != 0) continue;
+ snprintf(buf, sizeof(buf), "/dev/%s", d->d_name);
+ fd = open(buf, O_RDWR);
+ if (fd < 0) continue;
+ r = ioctl(fd, USB_GET_DEVICEINFO, &info);
+ if (r < 0) {
+ // NetBSD: added in 2004
+ // OpenBSD: added November 23, 2009
+ // FreeBSD: missing (FreeBSD 8.0) - USE_LIBUSB works!
+ die("Error: your uhid driver does not support"
+ " USB_GET_DEVICEINFO, please upgrade!\n");
+ close(fd);
+ closedir(dir);
+ exit(1);
+ }
+ //printf("%s: v=%d, p=%d\n", buf, info.udi_vendorNo, info.udi_productNo);
+ if (info.udi_vendorNo == vid && info.udi_productNo == pid) {
+ closedir(dir);
+ return fd;
+ }
+ close(fd);
+ }
+ closedir(dir);
+ return -1;
+}
+
+static int uhid_teensy_fd = -1;
+
+int teensy_open(void)
+{
+ teensy_close();
+ uhid_teensy_fd = open_usb_device(0x16C0, 0x0478);
+
+ if (uhid_teensy_fd < 0)
+ uhid_teensy_fd = open_usb_device(0x03eb, 0x2067);
+
+ if (uhid_teensy_fd < 0) return 0;
+ return 1;
+}
+
+int teensy_write(void *buf, int len, double timeout)
+{
+ int r;
+
+ // TODO: implement timeout... how??
+ r = write(uhid_teensy_fd, buf, len);
+ if (r == len) return 1;
+ return 0;
+}
+
+void teensy_close(void)
+{
+ if (uhid_teensy_fd >= 0) {
+ close(uhid_teensy_fd);
+ uhid_teensy_fd = -1;
+ }
+}
+
+int hard_reboot(void)
+{
+ int r, rebootor_fd;
+
+ rebootor_fd = open_usb_device(0x16C0, 0x0477);
+
+ if (rebootor_fd < 0)
+ rebootor_fd = open_usb_device(0x03eb, 0x2067);
+
+ if (rebootor_fd < 0) return 0;
+ r = write(rebootor_fd, "reboot", 6);
+ delay(0.1);
+ close(rebootor_fd);
+ if (r == 6) return 1;
+ return 0;
+}
+
+#endif
+
+
+
+/****************************************************************/
+/* */
+/* Read Intel Hex File */
+/* */
+/****************************************************************/
+
+// the maximum flash image size we can support
+// chips with larger memory may be used, but only this
+// much intel-hex data can be loaded into memory!
+#define MAX_MEMORY_SIZE 0x10000
+
+static unsigned char firmware_image[MAX_MEMORY_SIZE];
+static unsigned char firmware_mask[MAX_MEMORY_SIZE];
+static int end_record_seen=0;
+static int byte_count;
+static unsigned int extended_addr = 0;
+static int parse_hex_line(char *line);
+
+int read_intel_hex(const char *filename)
+{
+ FILE *fp;
+ int i, lineno=0;
+ char buf[1024];
+
+ byte_count = 0;
+ end_record_seen = 0;
+ for (i=0; i<MAX_MEMORY_SIZE; i++) {
+ firmware_image[i] = 0xFF;
+ firmware_mask[i] = 0;
+ }
+ extended_addr = 0;
+
+ fp = fopen(filename, "r");
+ if (fp == NULL) {
+ //printf("Unable to read file %s\n", filename);
+ return -1;
+ }
+ while (!feof(fp)) {
+ *buf = '\0';
+ if (!fgets(buf, sizeof(buf), fp)) break;
+ lineno++;
+ if (*buf) {
+ if (parse_hex_line(buf) == 0) {
+ //printf("Warning, parse error line %d\n", lineno);
+ fclose(fp);
+ return -2;
+ }
+ }
+ if (end_record_seen) break;
+ if (feof(stdin)) break;
+ }
+ fclose(fp);
+ return byte_count;
+}
+
+
+/* from ihex.c, at http://www.pjrc.com/tech/8051/pm2_docs/intel-hex.html */
+
+/* parses a line of intel hex code, stores the data in bytes[] */
+/* and the beginning address in addr, and returns a 1 if the */
+/* line was valid, or a 0 if an error occurred. The variable */
+/* num gets the number of bytes that were stored into bytes[] */
+
+
+int
+parse_hex_line(char *line)
+{
+ int addr, code, num;
+ int sum, len, cksum, i;
+ char *ptr;
+
+ num = 0;
+ if (line[0] != ':') return 0;
+ if (strlen(line) < 11) return 0;
+ ptr = line+1;
+ if (!sscanf(ptr, "%02x", &len)) return 0;
+ ptr += 2;
+ if ((int)strlen(line) < (11 + (len * 2)) ) return 0;
+ if (!sscanf(ptr, "%04x", &addr)) return 0;
+ ptr += 4;
+ /* printf("Line: length=%d Addr=%d\n", len, addr); */
+ if (!sscanf(ptr, "%02x", &code)) return 0;
+ if (addr + extended_addr + len >= MAX_MEMORY_SIZE) return 0;
+ ptr += 2;
+ sum = (len & 255) + ((addr >> 8) & 255) + (addr & 255) + (code & 255);
+ if (code != 0) {
+ if (code == 1) {
+ end_record_seen = 1;
+ return 1;
+ }
+ if (code == 2 && len == 2) {
+ if (!sscanf(ptr, "%04x", &i)) return 1;
+ ptr += 4;
+ sum += ((i >> 8) & 255) + (i & 255);
+ if (!sscanf(ptr, "%02x", &cksum)) return 1;
+ if (((sum & 255) + (cksum & 255)) & 255) return 1;
+ extended_addr = i << 4;
+ //printf("ext addr = %05X\n", extended_addr);
+ }
+ if (code == 4 && len == 2) {
+ if (!sscanf(ptr, "%04x", &i)) return 1;
+ ptr += 4;
+ sum += ((i >> 8) & 255) + (i & 255);
+ if (!sscanf(ptr, "%02x", &cksum)) return 1;
+ if (((sum & 255) + (cksum & 255)) & 255) return 1;
+ extended_addr = i << 16;
+ //printf("ext addr = %08X\n", extended_addr);
+ }
+ return 1; // non-data line
+ }
+ byte_count += len;
+ while (num != len) {
+ if (sscanf(ptr, "%02x", &i) != 1) return 0;
+ i &= 255;
+ firmware_image[addr + extended_addr + num] = i;
+ firmware_mask[addr + extended_addr + num] = 1;
+ ptr += 2;
+ sum += i;
+ (num)++;
+ if (num >= 256) return 0;
+ }
+ if (!sscanf(ptr, "%02x", &cksum)) return 0;
+ if (((sum & 255) + (cksum & 255)) & 255) return 0; /* checksum error */
+ return 1;
+}
+
+int ihex_bytes_within_range(int begin, int end)
+{
+ int i;
+
+ if (begin < 0 || begin >= MAX_MEMORY_SIZE ||
+ end < 0 || end >= MAX_MEMORY_SIZE) {
+ return 0;
+ }
+ for (i=begin; i<=end; i++) {
+ if (firmware_mask[i]) return 1;
+ }
+ return 0;
+}
+
+void ihex_get_data(int addr, int len, unsigned char *bytes)
+{
+ int i;
+
+ if (addr < 0 || len < 0 || addr + len >= MAX_MEMORY_SIZE) {
+ for (i=0; i<len; i++) {
+ bytes[i] = 255;
+ }
+ return;
+ }
+ for (i=0; i<len; i++) {
+ if (firmware_mask[addr]) {
+ bytes[i] = firmware_image[addr];
+ } else {
+ bytes[i] = 255;
+ }
+ addr++;
+ }
+}
+
+/****************************************************************/
+/* */
+/* Misc Functions */
+/* */
+/****************************************************************/
+
+int printf_verbose(const char *format, ...)
+{
+ va_list ap;
+ int r;
+
+ va_start(ap, format);
+ if (verbose) {
+ r = vprintf(format, ap);
+ fflush(stdout);
+ return r;
+ }
+ return 0;
+}
+
+void delay(double seconds)
+{
+ #ifdef WIN32
+ Sleep(seconds * 1000.0);
+ #else
+ usleep(seconds * 1000000.0);
+ #endif
+}
+
+void die(const char *str, ...)
+{
+ va_list ap;
+
+ va_start(ap, str);
+ vfprintf(stderr, str, ap);
+ fprintf(stderr, "\n");
+ exit(1);
+}
+
+#if defined(WIN32)
+#define strcasecmp stricmp
+#endif
+
+void parse_options(int argc, char **argv)
+{
+ int i;
+ const char *arg;
+
+ for (i=1; i<argc; i++) {
+ arg = argv[i];
+
+ if (*arg == '-') {
+ if (strcmp(arg, "-w") == 0) {
+ wait_for_device_to_appear = 1;
+ } else if (strcmp(arg, "-r") == 0) {
+ hard_reboot_device = 1;
+ } else if (strcmp(arg, "-n") == 0) {
+ reboot_after_programming = 0;
+ } else if (strcmp(arg, "-v") == 0) {
+ verbose = 1;
+ } else if (strncmp(arg, "-mmcu=", 6) == 0) {
+ arg += 6;
+
+ if (strncmp(arg, "at90usb", 7) == 0) {
+ arg += 7;
+ } else if (strncmp(arg, "atmega", 6) == 0) {
+ arg += 6;
+ } else {
+ die("Unknown MCU type\n");
+ }
+
+ if (strncmp(arg, "128", 3) == 0) {
+ code_size = 128 * 1024;
+ block_size = 256;
+ } else if (strncmp(arg, "64", 2) == 0) {
+ code_size = 64 * 1024;
+ block_size = 256;
+ } else if (strncmp(arg, "32", 2) == 0) {
+ code_size = 32 * 1024;
+ block_size = 128;
+ } else if (strncmp(arg, "16", 2) == 0) {
+ code_size = 16 * 1024;
+ block_size = 128;
+ } else if (strncmp(arg, "8", 1) == 0) {
+ code_size = 8 * 1024;
+ block_size = 128;
+ } else {
+ die("Unknown MCU type\n");
+ }
+ }
+ } else {
+ filename = argv[i];
+ }
+ }
+}
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/HostLoaderApp_Python/hid_bootloader_loader.py b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/HostLoaderApp_Python/hid_bootloader_loader.py
new file mode 100644
index 000000000..2598fde60
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/HostLoaderApp_Python/hid_bootloader_loader.py
@@ -0,0 +1,120 @@
+"""
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+"""
+
+"""
+ Front-end programmer for the LUFA HID class bootloader.
+
+ Usage:
+ python hid_bootloader_loader.py <Device> <Input>.hex
+
+ Example:
+ python hid_bootloader_loader.py at90usb1287 Mouse.hex
+
+ Requires the pywinusb (https://pypi.python.org/pypi/pywinusb/) and
+ IntelHex (http://bialix.com/intelhex/) libraries.
+"""
+
+import sys
+from pywinusb import hid
+from intelhex import IntelHex
+
+
+# Device information table
+device_info_map = dict()
+device_info_map['at90usb1287'] = {'page_size': 256, 'flash_kb': 128}
+device_info_map['at90usb1286'] = {'page_size': 256, 'flash_kb': 128}
+device_info_map['at90usb647'] = {'page_size': 256, 'flash_kb': 64}
+device_info_map['at90usb646'] = {'page_size': 256, 'flash_kb': 64}
+device_info_map['atmega32u4'] = {'page_size': 128, 'flash_kb': 32}
+device_info_map['atmega32u2'] = {'page_size': 128, 'flash_kb': 32}
+device_info_map['atmega16u4'] = {'page_size': 128, 'flash_kb': 16}
+device_info_map['atmega16u2'] = {'page_size': 128, 'flash_kb': 16}
+device_info_map['at90usb162'] = {'page_size': 128, 'flash_kb': 16}
+device_info_map['atmega8u2'] = {'page_size': 128, 'flash_kb': 8}
+device_info_map['at90usb82'] = {'page_size': 128, 'flash_kb': 8}
+
+
+def get_hid_device_handle():
+ hid_device_filter = hid.HidDeviceFilter(vendor_id=0x03EB,
+ product_id=0x2067)
+
+ valid_hid_devices = hid_device_filter.get_devices()
+
+ if len(valid_hid_devices) is 0:
+ return None
+ else:
+ return valid_hid_devices[0]
+
+
+def send_page_data(hid_device, address, data):
+ # Bootloader page data should be the HID Report ID (always zero) followed
+ # by the starting address to program, then one device's flash page worth
+ # of data
+ output_report_data = [0]
+ output_report_data.extend([address & 0xFF, address >> 8])
+ output_report_data.extend(data)
+
+ hid_device.send_output_report(output_report_data)
+
+
+def program_device(hex_data, device_info):
+ hid_device = get_hid_device_handle()
+
+ if hid_device is None:
+ print("No valid HID device found.")
+ sys.exit(1)
+
+ try:
+ hid_device.open()
+ print("Connected to bootloader.")
+
+ # Program in all data from the loaded HEX file, in a number of device
+ # page sized chunks
+ for addr in range(0, hex_data.maxaddr(), device_info['page_size']):
+ # Compute the address range of the current page in the device
+ current_page_range = range(addr, addr+device_info['page_size'])
+
+ # Extract the data from the hex file at the specified start page
+ # address and convert it to a regular list of bytes
+ page_data = [hex_data[i] for i in current_page_range]
+
+ print("Writing address 0x%04X-0x%04X" % (current_page_range[0], current_page_range[-1]))
+
+ # Devices with more than 64KB of flash should shift down the page
+ # address so that it is 16-bit (page size is guaranteed to be
+ # >= 256 bytes so no non-zero address bits are discarded)
+ if device_info['flash_kb'] < 64:
+ send_page_data(hid_device, addr, page_data)
+ else:
+ send_page_data(hid_device, addr >> 8, page_data)
+
+ # Once programming is complete, start the application via a dummy page
+ # program to the page address 0xFFFF
+ print("Programming complete, starting application.")
+ send_page_data(hid_device, 0xFFFF, [0] * device_info['page_size'])
+
+ finally:
+ hid_device.close()
+
+
+if __name__ == '__main__':
+ # Load the specified HEX file
+ try:
+ hex_data = IntelHex(sys.argv[2])
+ except:
+ print("Could not open the specified HEX file.")
+ sys.exit(1)
+
+ # Retrieve the device information entry for the specified device
+ try:
+ device_info = device_info_map[sys.argv[1]]
+ except:
+ print("Unknown device name specified.")
+ sys.exit(1)
+
+ program_device(hex_data, device_info)
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/asf.xml b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/asf.xml
new file mode 100644
index 000000000..9394b1353
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/asf.xml
@@ -0,0 +1,123 @@
+<asf xmlversion="1.0">
+ <project caption="HID Bootloader - 128KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.hid.avr8.128_4" force-caption="true" workspace-name="lufa_hid_128kb_4kb_">
+ <require idref="lufa.bootloaders.hid"/>
+ <require idref="lufa.boards.dummy.avr8"/>
+ <generator value="as5_8"/>
+
+ <device-support value="at90usb1287"/>
+ <config name="lufa.drivers.board.name" value="none"/>
+
+ <config name="config.compiler.optimization.level" value="size"/>
+
+ <build type="define" name="F_CPU" value="16000000UL"/>
+ <build type="define" name="F_USB" value="16000000UL"/>
+
+ <build type="define" name="BOOT_START_ADDR" value="0x1F000"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.text=0x1F000"/>
+ </project>
+
+ <project caption="HID Bootloader - 64KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.hid.avr8.64_4" force-caption="true" workspace-name="lufa_hid_64kb_4kb_">
+ <require idref="lufa.bootloaders.hid"/>
+ <require idref="lufa.boards.dummy.avr8"/>
+ <generator value="as5_8"/>
+
+ <device-support value="at90usb647"/>
+ <config name="lufa.drivers.board.name" value="none"/>
+
+ <config name="config.compiler.optimization.level" value="size"/>
+
+ <build type="define" name="F_CPU" value="16000000UL"/>
+ <build type="define" name="F_USB" value="16000000UL"/>
+
+ <build type="define" name="BOOT_START_ADDR" value="0xF000"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.text=0xF000"/>
+ </project>
+
+ <project caption="HID Bootloader - 32KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.hid.avr8.32_4" force-caption="true" workspace-name="lufa_hid_32kb_4kb_">
+ <require idref="lufa.bootloaders.hid"/>
+ <require idref="lufa.boards.dummy.avr8"/>
+ <generator value="as5_8"/>
+
+ <device-support value="atmega32u4"/>
+ <config name="lufa.drivers.board.name" value="none"/>
+
+ <config name="config.compiler.optimization.level" value="size"/>
+
+ <build type="define" name="F_CPU" value="16000000UL"/>
+ <build type="define" name="F_USB" value="16000000UL"/>
+
+ <build type="define" name="BOOT_START_ADDR" value="0x7000"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.text=0x7000"/>
+ </project>
+
+ <project caption="HID Bootloader - 16KB FLASH / 2KB Boot - AVR8 Architecture" id="lufa.bootloaders.hid.avr8.16_2" force-caption="true" workspace-name="lufa_hid_16kb_2kb_">
+ <require idref="lufa.bootloaders.hid"/>
+ <require idref="lufa.boards.dummy.avr8"/>
+ <generator value="as5_8"/>
+
+ <device-support value="atmega16u2"/>
+ <config name="lufa.drivers.board.name" value="none"/>
+
+ <config name="config.compiler.optimization.level" value="size"/>
+
+ <build type="define" name="F_CPU" value="16000000UL"/>
+ <build type="define" name="F_USB" value="16000000UL"/>
+
+ <build type="define" name="BOOT_START_ADDR" value="0x3800"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.text=0x3800"/>
+ </project>
+
+ <project caption="HID Bootloader - 8KB FLASH / 2KB Boot - AVR8 Architecture" id="lufa.bootloaders.hid.avr8.8_2" force-caption="true" workspace-name="lufa_hid_8kb_2kb_">
+ <require idref="lufa.bootloaders.hid"/>
+ <require idref="lufa.boards.dummy.avr8"/>
+ <generator value="as5_8"/>
+
+ <device-support value="atmega8u2"/>
+ <config name="lufa.drivers.board.name" value="none"/>
+
+ <config name="config.compiler.optimization.level" value="size"/>
+
+ <build type="define" name="F_CPU" value="16000000UL"/>
+ <build type="define" name="F_USB" value="16000000UL"/>
+
+ <build type="define" name="BOOT_START_ADDR" value="0x1800"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.text=0x1800"/>
+ </project>
+
+ <module type="application" id="lufa.bootloaders.hid" caption="HID Bootloader">
+ <info type="description" value="summary">
+ HID Class Bootloader, capable of reprogramming a device via a custom cross-platform command line utility when plugged into a host.
+ </info>
+
+ <info type="gui-flag" value="move-to-root"/>
+
+ <info type="keyword" value="Technology">
+ <keyword value="Bootloaders"/>
+ <keyword value="USB Device"/>
+ </info>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="include-path" value="."/>
+ <build type="c-source" value="BootloaderHID.c"/>
+ <build type="header-file" value="BootloaderHID.h"/>
+ <build type="c-source" value="Descriptors.c"/>
+ <build type="header-file" value="Descriptors.h"/>
+
+ <build type="module-config" subtype="path" value="Config"/>
+ <build type="header-file" value="Config/LUFAConfig.h"/>
+
+ <build type="distribute" subtype="user-file" value="doxyfile"/>
+ <build type="distribute" subtype="user-file" value="BootloaderHID.txt"/>
+ <build type="distribute" subtype="directory" value="HostLoaderApp"/>
+ <build type="distribute" subtype="directory" value="HostLoaderApp_Python"/>
+
+ <require idref="lufa.common"/>
+ <require idref="lufa.platform"/>
+ <require idref="lufa.drivers.usb"/>
+ <require idref="lufa.drivers.board"/>
+ <require idref="lufa.drivers.board.leds"/>
+ </module>
+</asf>
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/doxyfile b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/doxyfile
new file mode 100644
index 000000000..281792ac9
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/doxyfile
@@ -0,0 +1,2367 @@
+# Doxyfile 1.8.8
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME = "LUFA Library - HID Class Bootloader"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
+# the documentation. The maximum height of the logo should not exceed 55 pixels
+# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
+# to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = ./Documentation/
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES = YES
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
+# new page for each member. If set to NO, the documentation of a member will be
+# part of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
+# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
+# Fortran. In the later case the parser tries to guess whether the code is fixed
+# or free formatted code, this is the default for Fortran type files), VHDL. For
+# instance to make doxygen treat .inc files as Fortran files (default is PHP),
+# and .f files as C (default is Fortran), use: inc=Fortran f=C.
+#
+# Note For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT = NO
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by by putting a % sign in front of the word
+# or globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE = YES
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO these classes will be included in the various overviews. This option has
+# no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
+# todo list. This list is created by putting \todo commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST = NO
+
+# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
+# test list. This list is created by putting \test commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST = NO
+
+# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST = NO
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES the list
+# will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET = YES
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO doxygen will only warn about wrong or incomplete parameter
+# documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces.
+# Note: If this tag is empty the current directory is searched.
+
+INPUT = ./
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank the
+# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
+# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
+# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
+# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
+# *.qsf, *.as and *.js.
+
+FILE_PATTERNS = *.h \
+ *.c \
+ *.txt
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE = Documentation/ \
+ HostLoaderApp/ \
+ HostLoaderApp_Python/
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS = __* \
+ INCLUDE_FROM_*
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER ) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = NO
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS = NO
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the
+# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
+# cost of reduced performance. This can be particularly helpful with template
+# rich C++ code for which doxygen's built-in parser lacks the necessary type
+# information.
+# Note: The availability of this option depends on whether or not doxygen was
+# compiled with the --with-libclang option.
+# The default value is: NO.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_OPTIONS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefor more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra stylesheet files is of importance (e.g. the last
+# stylesheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the stylesheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP = NO
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS = YES
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated (
+# YES) or that it should be included in the master .chm file ( NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated (
+# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND = YES
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX = YES
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW = YES
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE = 1
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. To get the times font for
+# instance you can specify
+# EXTRA_PACKAGES=times
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empy string,
+# for the replacement values of the other commands the user is refered to
+# HTML_HEADER.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE = plain
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT = docbook
+
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
+# Definitions (see http://autogen.sf.net) file that captures the structure of
+# the code including all documentation. Note that this feature is still
+# experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
+# in the source code. If set to NO only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF = YES
+
+# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED = __DOXYGEN__ \
+ PROGMEM \
+ ATTR_NO_INIT
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
+# class index. If set to NO only the inherited external classes will be listed.
+# The default value is: NO.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
+# the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS = YES
+
+# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS = NO
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME =
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH = NO
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH = NO
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS = NO
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH = NO
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH = NO
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY = NO
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH = NO
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot.
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif and svg.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+PLANTUML_JAR_PATH =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES = 15
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH = 2
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT = YES
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP = YES
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/makefile b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/makefile
new file mode 100644
index 000000000..6589d75aa
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/HID/makefile
@@ -0,0 +1,48 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2014.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+# --------------------------------------
+# LUFA Project Makefile.
+# --------------------------------------
+
+# Run "make help" for target help.
+
+MCU = at90usb1287
+ARCH = AVR8
+BOARD = USBKEY
+F_CPU = 8000000
+F_USB = $(F_CPU)
+OPTIMIZATION = s
+TARGET = BootloaderHID
+SRC = $(TARGET).c Descriptors.c $(LUFA_SRC_USB)
+LUFA_PATH = ../../LUFA
+CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -IConfig/
+LD_FLAGS = -Wl,--section-start=.text=$(BOOT_START_OFFSET)
+
+# Flash size and bootloader section sizes of the target, in KB. These must
+# match the target's total FLASH size and the bootloader size set in the
+# device's fuses.
+FLASH_SIZE_KB := 128
+BOOT_SECTION_SIZE_KB := 8
+
+# Bootloader address calculation formulas
+# Do not modify these macros, but rather modify the dependent values above.
+CALC_ADDRESS_IN_HEX = $(shell printf "0x%X" $$(( $(1) )) )
+BOOT_START_OFFSET = $(call CALC_ADDRESS_IN_HEX, ($(FLASH_SIZE_KB) - $(BOOT_SECTION_SIZE_KB)) * 1024 )
+BOOT_SEC_OFFSET = $(call CALC_ADDRESS_IN_HEX, ($(FLASH_SIZE_KB) * 1024) - ($(strip $(1))) )
+
+# Default target
+all:
+
+# Include LUFA build script makefiles
+include $(LUFA_PATH)/Build/lufa_core.mk
+include $(LUFA_PATH)/Build/lufa_sources.mk
+include $(LUFA_PATH)/Build/lufa_build.mk
+include $(LUFA_PATH)/Build/lufa_cppcheck.mk
+include $(LUFA_PATH)/Build/lufa_doxygen.mk
+include $(LUFA_PATH)/Build/lufa_avrdude.mk
+include $(LUFA_PATH)/Build/lufa_atprogram.mk
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/BootloaderAPI.c b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/BootloaderAPI.c
new file mode 100644
index 000000000..cad59c8ca
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/BootloaderAPI.c
@@ -0,0 +1,76 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Bootloader user application API functions.
+ */
+
+#include "BootloaderAPI.h"
+
+void BootloaderAPI_ErasePage(const uint32_t Address)
+{
+ boot_page_erase_safe(Address);
+ boot_spm_busy_wait();
+ boot_rww_enable();
+}
+
+void BootloaderAPI_WritePage(const uint32_t Address)
+{
+ boot_page_write_safe(Address);
+ boot_spm_busy_wait();
+ boot_rww_enable();
+}
+
+void BootloaderAPI_FillWord(const uint32_t Address, const uint16_t Word)
+{
+ boot_page_fill_safe(Address, Word);
+}
+
+uint8_t BootloaderAPI_ReadSignature(const uint16_t Address)
+{
+ return boot_signature_byte_get(Address);
+}
+
+uint8_t BootloaderAPI_ReadFuse(const uint16_t Address)
+{
+ return boot_lock_fuse_bits_get(Address);
+}
+
+uint8_t BootloaderAPI_ReadLock(void)
+{
+ return boot_lock_fuse_bits_get(GET_LOCK_BITS);
+}
+
+void BootloaderAPI_WriteLock(const uint8_t LockBits)
+{
+ boot_lock_bits_set_safe(LockBits);
+}
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/BootloaderAPI.h b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/BootloaderAPI.h
new file mode 100644
index 000000000..0f0cd7040
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/BootloaderAPI.h
@@ -0,0 +1,63 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Header file for BootloaderAPI.c.
+ */
+
+#ifndef _BOOTLOADER_API_H_
+#define _BOOTLOADER_API_H_
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <avr/boot.h>
+ #include <stdbool.h>
+
+ #include <LUFA/Common/Common.h>
+
+ /* Macros: */
+ #if AUX_BOOT_SECTION_SIZE > 0
+ #define AUX_BOOT_SECTION __attribute__((section(".boot_aux")))
+ #else
+ #define AUX_BOOT_SECTION
+ #endif
+
+ /* Function Prototypes: */
+ void BootloaderAPI_ErasePage(const uint32_t Address);
+ void BootloaderAPI_WritePage(const uint32_t Address);
+ void BootloaderAPI_FillWord(const uint32_t Address, const uint16_t Word);
+ uint8_t BootloaderAPI_ReadSignature(const uint16_t Address);
+ uint8_t BootloaderAPI_ReadFuse(const uint16_t Address);
+ uint8_t BootloaderAPI_ReadLock(void);
+ void BootloaderAPI_WriteLock(const uint8_t LockBits);
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/BootloaderAPITable.S b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/BootloaderAPITable.S
new file mode 100644
index 000000000..6844d4b01
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/BootloaderAPITable.S
@@ -0,0 +1,102 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#if AUX_BOOT_SECTION_SIZE > 0
+#warning Using a AUX bootloader section in addition to the defined bootloader space (see documentation).
+
+; Trampoline to jump over the AUX bootloader section to the start of the bootloader,
+; on devices where an AUX bootloader section is used.
+.section .boot_aux_trampoline, "ax"
+.global Boot_AUX_Trampoline
+Boot_AUX_Trampoline:
+ jmp BOOT_START_ADDR
+#endif
+
+; Trampolines to actual API implementations if the target address is outside the
+; range of a rjmp instruction (can happen with large bootloader sections)
+.section .apitable_trampolines, "ax"
+.global BootloaderAPI_Trampolines
+BootloaderAPI_Trampolines:
+
+ BootloaderAPI_ErasePage_Trampoline:
+ jmp BootloaderAPI_ErasePage
+ BootloaderAPI_WritePage_Trampoline:
+ jmp BootloaderAPI_WritePage
+ BootloaderAPI_FillWord_Trampoline:
+ jmp BootloaderAPI_FillWord
+ BootloaderAPI_ReadSignature_Trampoline:
+ jmp BootloaderAPI_ReadSignature
+ BootloaderAPI_ReadFuse_Trampoline:
+ jmp BootloaderAPI_ReadFuse
+ BootloaderAPI_ReadLock_Trampoline:
+ jmp BootloaderAPI_ReadLock
+ BootloaderAPI_WriteLock_Trampoline:
+ jmp BootloaderAPI_WriteLock
+ BootloaderAPI_UNUSED1:
+ ret
+ BootloaderAPI_UNUSED2:
+ ret
+ BootloaderAPI_UNUSED3:
+ ret
+ BootloaderAPI_UNUSED4:
+ ret
+ BootloaderAPI_UNUSED5:
+ ret
+
+
+
+; API function jump table
+.section .apitable_jumptable, "ax"
+.global BootloaderAPI_JumpTable
+BootloaderAPI_JumpTable:
+
+ rjmp BootloaderAPI_ErasePage_Trampoline
+ rjmp BootloaderAPI_WritePage_Trampoline
+ rjmp BootloaderAPI_FillWord_Trampoline
+ rjmp BootloaderAPI_ReadSignature_Trampoline
+ rjmp BootloaderAPI_ReadFuse_Trampoline
+ rjmp BootloaderAPI_ReadLock_Trampoline
+ rjmp BootloaderAPI_WriteLock_Trampoline
+ rjmp BootloaderAPI_UNUSED1 ; UNUSED ENTRY 1
+ rjmp BootloaderAPI_UNUSED2 ; UNUSED ENTRY 2
+ rjmp BootloaderAPI_UNUSED3 ; UNUSED ENTRY 3
+ rjmp BootloaderAPI_UNUSED4 ; UNUSED ENTRY 4
+ rjmp BootloaderAPI_UNUSED5 ; UNUSED ENTRY 5
+
+
+
+; Bootloader table signatures and information
+.section .apitable_signatures, "ax"
+.global BootloaderAPI_Signatures
+BootloaderAPI_Signatures:
+
+ .long BOOT_START_ADDR ; Start address of the bootloader
+ .word 0xDF30 ; Signature for the MS class bootloader, V1
+ .word 0xDCFB ; Signature for a LUFA class bootloader
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/BootloaderMassStorage.c b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/BootloaderMassStorage.c
new file mode 100644
index 000000000..cfe0cdbf8
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/BootloaderMassStorage.c
@@ -0,0 +1,238 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Main source file for the Mass Storage class bootloader. This file contains the complete bootloader logic.
+ */
+
+#define INCLUDE_FROM_BOOTLOADER_MASSSTORAGE_C
+#include "BootloaderMassStorage.h"
+
+/** LUFA Mass Storage Class driver interface configuration and state information. This structure is
+ * passed to all Mass Storage Class driver functions, so that multiple instances of the same class
+ * within a device can be differentiated from one another.
+ */
+USB_ClassInfo_MS_Device_t Disk_MS_Interface =
+ {
+ .Config =
+ {
+ .InterfaceNumber = INTERFACE_ID_MassStorage,
+ .DataINEndpoint =
+ {
+ .Address = MASS_STORAGE_IN_EPADDR,
+ .Size = MASS_STORAGE_IO_EPSIZE,
+ .Banks = 1,
+ },
+ .DataOUTEndpoint =
+ {
+ .Address = MASS_STORAGE_OUT_EPADDR,
+ .Size = MASS_STORAGE_IO_EPSIZE,
+ .Banks = 1,
+ },
+ .TotalLUNs = 1,
+ },
+ };
+
+/** Flag to indicate if the bootloader should be running, or should exit and allow the application code to run
+ * via a soft reset. When cleared, the bootloader will abort, the USB interface will shut down and the application
+ * started via a forced watchdog reset.
+ */
+bool RunBootloader = true;
+
+/** Magic lock for forced application start. If the HWBE fuse is programmed and BOOTRST is unprogrammed, the bootloader
+ * will start if the /HWB line of the AVR is held low and the system is reset. However, if the /HWB line is still held
+ * low when the application attempts to start via a watchdog reset, the bootloader will re-start. If set to the value
+ * \ref MAGIC_BOOT_KEY the special init function \ref Application_Jump_Check() will force the application to start.
+ */
+uint16_t MagicBootKey ATTR_NO_INIT;
+
+/** Indicates if the bootloader is allowed to exit immediately if \ref RunBootloader is \c false. During shutdown all
+ * pending commands must be processed before jumping to the user-application, thus this tracks the main program loop
+ * iterations since a SCSI command from the host was received.
+ */
+static uint8_t TicksSinceLastCommand = 0;
+
+
+/** Special startup routine to check if the bootloader was started via a watchdog reset, and if the magic application
+ * start key has been loaded into \ref MagicBootKey. If the bootloader started via the watchdog and the key is valid,
+ * this will force the user application to start via a software jump.
+ */
+void Application_Jump_Check(void)
+{
+ bool JumpToApplication = false;
+
+ #if (BOARD == BOARD_LEONARDO)
+ /* Enable pull-up on the IO13 pin so we can use it to select the mode */
+ PORTC |= (1 << 7);
+ Delay_MS(10);
+
+ /* If IO13 is not jumpered to ground, start the user application instead */
+ JumpToApplication |= ((PINC & (1 << 7)) != 0);
+
+ /* Disable pull-up after the check has completed */
+ PORTC &= ~(1 << 7);
+ #elif ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
+ /* Disable JTAG debugging */
+ JTAG_DISABLE();
+
+ /* Enable pull-up on the JTAG TCK pin so we can use it to select the mode */
+ PORTF |= (1 << 4);
+ Delay_MS(10);
+
+ /* If the TCK pin is not jumpered to ground, start the user application instead */
+ JumpToApplication |= ((PINF & (1 << 4)) != 0);
+
+ /* Re-enable JTAG debugging */
+ JTAG_ENABLE();
+ #endif
+
+ /* If the reset source was the bootloader and the key is correct, clear it and jump to the application */
+ if ((MCUSR & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY))
+ {
+ MagicBootKey = 0;
+ JumpToApplication = true;
+ }
+
+ if (JumpToApplication)
+ {
+ // cppcheck-suppress constStatement
+ ((void (*)(void))0x0000)();
+ }
+}
+
+/** Main program entry point. This routine configures the hardware required by the application, then
+ * enters a loop to run the application tasks in sequence.
+ */
+int main(void)
+{
+ SetupHardware();
+
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
+ GlobalInterruptEnable();
+
+ while (RunBootloader || TicksSinceLastCommand++ < 0xFF)
+ {
+ MS_Device_USBTask(&Disk_MS_Interface);
+ USB_USBTask();
+ }
+
+ /* Disconnect from the host - USB interface will be reset later along with the AVR */
+ USB_Detach();
+
+ /* Unlock the forced application start mode of the bootloader if it is restarted */
+ MagicBootKey = MAGIC_BOOT_KEY;
+
+ /* Enable the watchdog and force a timeout to reset the AVR */
+ wdt_enable(WDTO_250MS);
+
+ for (;;);
+}
+
+/** Configures the board hardware and chip peripherals for the demo's functionality. */
+static void SetupHardware(void)
+{
+ /* Disable watchdog if enabled by bootloader/fuses */
+ MCUSR &= ~(1 << WDRF);
+ wdt_disable();
+
+ /* Disable clock division */
+ clock_prescale_set(clock_div_1);
+
+ /* Relocate the interrupt vector table to the bootloader section */
+ MCUCR = (1 << IVCE);
+ MCUCR = (1 << IVSEL);
+
+ /* Hardware Initialization */
+ LEDs_Init();
+ USB_Init();
+
+ /* Bootloader active LED toggle timer initialization */
+ TIMSK1 = (1 << TOIE1);
+ TCCR1B = ((1 << CS11) | (1 << CS10));
+}
+
+/** ISR to periodically toggle the LEDs on the board to indicate that the bootloader is active. */
+ISR(TIMER1_OVF_vect, ISR_BLOCK)
+{
+ LEDs_ToggleLEDs(LEDS_LED1 | LEDS_LED2);
+}
+
+/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs. */
+void EVENT_USB_Device_Connect(void)
+{
+ /* Indicate USB enumerating */
+ LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
+}
+
+/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
+ * the status LEDs and stops the Mass Storage management task.
+ */
+void EVENT_USB_Device_Disconnect(void)
+{
+ /* Indicate USB not ready */
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
+}
+
+/** Event handler for the library USB Configuration Changed event. */
+void EVENT_USB_Device_ConfigurationChanged(void)
+{
+ bool ConfigSuccess = true;
+
+ /* Setup Mass Storage Data Endpoints */
+ ConfigSuccess &= MS_Device_ConfigureEndpoints(&Disk_MS_Interface);
+
+ /* Indicate endpoint configuration success or failure */
+ LEDs_SetAllLEDs(ConfigSuccess ? LEDMASK_USB_READY : LEDMASK_USB_ERROR);
+}
+
+/** Event handler for the library USB Control Request reception event. */
+void EVENT_USB_Device_ControlRequest(void)
+{
+ MS_Device_ProcessControlRequest(&Disk_MS_Interface);
+}
+
+/** Mass Storage class driver callback function the reception of SCSI commands from the host, which must be processed.
+ *
+ * \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface configuration structure being referenced
+ */
+bool CALLBACK_MS_Device_SCSICommandReceived(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
+{
+ bool CommandSuccess;
+
+ LEDs_SetAllLEDs(LEDMASK_USB_BUSY);
+ CommandSuccess = SCSI_DecodeSCSICommand(MSInterfaceInfo);
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);
+
+ /* Signal that a command was processed, must not exit bootloader yet */
+ TicksSinceLastCommand = 0;
+
+ return CommandSuccess;
+}
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/BootloaderMassStorage.h b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/BootloaderMassStorage.h
new file mode 100644
index 000000000..c1bd00410
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/BootloaderMassStorage.h
@@ -0,0 +1,99 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Header file for BootloaderMassStorage.c.
+ */
+
+#ifndef _BOOTLOADER_MASS_STORAGE_H_
+#define _BOOTLOADER_MASS_STORAGE_H_
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <avr/wdt.h>
+ #include <avr/power.h>
+ #include <avr/interrupt.h>
+ #include <string.h>
+
+ #include "Descriptors.h"
+ #include "Config/AppConfig.h"
+
+ #include "Lib/SCSI.h"
+
+ #include <LUFA/Drivers/Board/LEDs.h>
+ #include <LUFA/Drivers/USB/USB.h>
+ #include <LUFA/Platform/Platform.h>
+
+ /* Preprocessor Checks: */
+ #if !defined(__OPTIMIZE_SIZE__)
+ #error This bootloader requires that it be optimized for size, not speed, to fit into the target device. Change optimization settings and try again.
+ #endif
+
+ /* Macros: */
+ /** LED mask for the library LED driver, to indicate that the USB interface is not ready. */
+ #define LEDMASK_USB_NOTREADY LEDS_LED1
+
+ /** LED mask for the library LED driver, to indicate that the USB interface is enumerating. */
+ #define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)
+
+ /** LED mask for the library LED driver, to indicate that the USB interface is ready. */
+ #define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)
+
+ /** LED mask for the library LED driver, to indicate that an error has occurred in the USB interface. */
+ #define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)
+
+ /** LED mask for the library LED driver, to indicate that the USB interface is busy. */
+ #define LEDMASK_USB_BUSY LEDS_LED2
+
+ /** Magic bootloader key to unlock forced application start mode. */
+ #define MAGIC_BOOT_KEY 0xDC42
+
+ /* Global Variables: */
+ extern bool RunBootloader;
+
+ /* Function Prototypes: */
+ int main(void) AUX_BOOT_SECTION;
+
+ void Application_Jump_Check(void) ATTR_INIT_SECTION(3);
+
+ void EVENT_USB_Device_Connect(void) AUX_BOOT_SECTION;
+ void EVENT_USB_Device_Disconnect(void) AUX_BOOT_SECTION;
+ void EVENT_USB_Device_ConfigurationChanged(void) AUX_BOOT_SECTION;
+ void EVENT_USB_Device_ControlRequest(void) AUX_BOOT_SECTION;
+
+ bool CALLBACK_MS_Device_SCSICommandReceived(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) AUX_BOOT_SECTION;
+
+ #if defined(INCLUDE_FROM_BOOTLOADER_MASSSTORAGE_C)
+ static void SetupHardware(void) AUX_BOOT_SECTION;
+ #endif
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/BootloaderMassStorage.txt b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/BootloaderMassStorage.txt
new file mode 100644
index 000000000..e09484793
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/BootloaderMassStorage.txt
@@ -0,0 +1,225 @@
+/** \file
+ *
+ * This file contains special DoxyGen information for the generation of the main page and other special
+ * documentation pages. It is not a project source file.
+ */
+
+/** \mainpage Mass Storage Class USB AVR Bootloader
+ *
+ * \section Sec_Compat Demo Compatibility:
+ *
+ * The following list indicates what microcontrollers are compatible with this demo.
+ *
+ * \li Series 7 USB AVRs (AT90USBxxx7)
+ * \li Series 6 USB AVRs (AT90USBxxx6)
+ * \li Series 4 USB AVRs (ATMEGAxxU4) - <i>See \ref SSec_Aux_Space</i>
+ * \li ATMEGA32U2 - <i>See \ref SSec_Aux_Space</i>
+ *
+ * \section Sec_Info USB Information:
+ *
+ * The following table gives a rundown of the USB utilization of this demo.
+ *
+ * <table>
+ * <tr>
+ * <td><b>USB Mode:</b></td>
+ * <td>Device</td>
+ * </tr>
+ * <tr>
+ * <td><b>USB Class:</b></td>
+ * <td>Mass Storage Device</td>
+ * </tr>
+ * <tr>
+ * <td><b>USB Subclass:</b></td>
+ * <td>Bulk-Only Transport</td>
+ * </tr>
+ * <tr>
+ * <td><b>Relevant Standards:</b></td>
+ * <td>USBIF Mass Storage Standard \n
+ * USB Bulk-Only Transport Standard \n
+ * SCSI Primary Commands Specification \n
+ * SCSI Block Commands Specification</td>
+ * </tr>
+ * <tr>
+ * <td><b>Supported USB Speeds:</b></td>
+ * <td>Full Speed Mode</td>
+ * </tr>
+ * </table>
+ *
+ * \section Sec_Description Project Description:
+ *
+ * This bootloader enumerates to the host as a Mass Storage device, capable of reading and writing a new binary
+ * firmware image file, to load firmware onto the AVR.
+ *
+ * Out of the box this bootloader builds for the AT90USB1287 with an 8KB bootloader section size, and will fit
+ * into 6KB of bootloader space. If you wish to alter this size and/or change the AVR model, you will need to
+ * edit the MCU, FLASH_SIZE_KB and BOOT_SECTION_SIZE_KB values in the accompanying makefile.
+ *
+ * When the bootloader is running, the board's LED(s) will flash at regular intervals to distinguish the
+ * bootloader from the normal user application.
+ *
+ * \warning <b>THIS BOOTLOADER IS NOT SECURE.</b> Malicious entities can recover written data, even if the device
+ * lockbits are set.
+ *
+ * \section Sec_Running Running the Bootloader
+ *
+ * This bootloader is designed to be started via the HWB mechanism of the USB AVRs; ground the HWB pin (see device
+ * datasheet) then momentarily ground /RESET to start the bootloader. This assumes the HWBE fuse is set and the BOOTRST
+ * fuse is cleared.
+ *
+ * For board specific exceptions to the above, see below.
+ *
+ * \subsection SSec_XPLAIN Atmel Xplain Board
+ * Ground the USB AVR JTAG's \c TCK pin to ground when powering on the board to start the bootloader. This assumes the
+ * \c HWBE fuse is cleared and the \c BOOTRST fuse is set as the HWBE pin is not user accessible on this board.
+ *
+ * \subsection SSec_Leonardo Arduino Leonardo Board
+ * Ground \c IO13 when powering the board to start the bootloader. This assumes the \c HWBE fuse is cleared and the
+ * \c BOOTRST fuse is set as the HWBE pin is not user accessible on this board.
+ *
+ * \section Sec_Installation Driver Installation
+ *
+ * This bootloader uses the Mass Storage drivers inbuilt into all modern operating systems, thus no additional
+ * drivers need to be supplied for correct operation.
+ *
+ * \section Sec_HostApp Host Controller Application
+ *
+ * This bootloader is compatible with all operating systems that support the FAT12 file system format. To reprogram the
+ * device, overwrite a file stored on the virtual FAT filesystem with a new binary (BIN format) image. Remember to safely
+ * remove your device from the host using the host OS's ejection APIs, to ensure all data is correctly flushed to the
+ * bootloader's virtual filesystem and not cached in the OS's file system driver.
+ *
+ * The current device firmware can be read from the device by reading a file from the virtual FAT filesystem.
+ *
+ * \warning This bootloader is currently <b>incompatible with the Apple MacOS X OS Finder GUI</b>, due to the
+ * large amount of meta files this OS attempts to write to the disk along with the new binaries. On
+ * this platform, firmwares must be copied to the disk via the Terminal application only to prevent
+ * firmware corruption.
+ *
+ * \section Sec_API User Application API
+ *
+ * Several user application functions for FLASH and other special memory area manipulations are exposed by the bootloader,
+ * allowing the user application to call into the bootloader at runtime to read and write FLASH data.
+ *
+ * By default, the bootloader API jump table is located 32 bytes from the end of the device's FLASH memory, and follows the
+ * following layout:
+ *
+ * \code
+ * #define BOOTLOADER_API_TABLE_SIZE 32
+ * #define BOOTLOADER_API_TABLE_START ((FLASHEND + 1UL) - BOOTLOADER_API_TABLE_SIZE)
+ * #define BOOTLOADER_API_CALL(Index) (void*)((BOOTLOADER_API_TABLE_START + (Index * 2)) / 2)
+ *
+ * void (*BootloaderAPI_ErasePage)(uint32_t Address) = BOOTLOADER_API_CALL(0);
+ * void (*BootloaderAPI_WritePage)(uint32_t Address) = BOOTLOADER_API_CALL(1);
+ * void (*BootloaderAPI_FillWord)(uint32_t Address, uint16_t Word) = BOOTLOADER_API_CALL(2);
+ * uint8_t (*BootloaderAPI_ReadSignature)(uint16_t Address) = BOOTLOADER_API_CALL(3);
+ * uint8_t (*BootloaderAPI_ReadFuse)(uint16_t Address) = BOOTLOADER_API_CALL(4);
+ * uint8_t (*BootloaderAPI_ReadLock)(void) = BOOTLOADER_API_CALL(5);
+ * void (*BootloaderAPI_WriteLock)(uint8_t LockBits) = BOOTLOADER_API_CALL(6);
+ *
+ * #define BOOTLOADER_MAGIC_SIGNATURE_START (BOOTLOADER_API_TABLE_START + (BOOTLOADER_API_TABLE_SIZE - 2))
+ * #define BOOTLOADER_MAGIC_SIGNATURE 0xDCFB
+ *
+ * #define BOOTLOADER_CLASS_SIGNATURE_START (BOOTLOADER_API_TABLE_START + (BOOTLOADER_API_TABLE_SIZE - 4))
+ * #define BOOTLOADER_MASS_STORAGE_SIGNATURE 0xDF30
+ *
+ * #define BOOTLOADER_ADDRESS_START (BOOTLOADER_API_TABLE_START + (BOOTLOADER_API_TABLE_SIZE - 8))
+ * #define BOOTLOADER_ADDRESS_LENGTH 4
+ * \endcode
+ *
+ * From the application the API support of the bootloader can be detected by reading the FLASH memory bytes located at address
+ * \c BOOTLOADER_MAGIC_SIGNATURE_START and comparing them to the value \c BOOTLOADER_MAGIC_SIGNATURE. The class of bootloader
+ * can be determined by reading the FLASH memory bytes located at address \c BOOTLOADER_CLASS_SIGNATURE_START and comparing them
+ * to the value \c BOOTLOADER_MASS_STORAGE_SIGNATURE. The start address of the bootloader can be retrieved by reading the bytes
+ * of FLASH memory starting from address \c BOOTLOADER_ADDRESS_START.
+ *
+ * \subsection SSec_Aux_Space Auxiliary Bootloader Section
+ * To make the bootloader function on smaller devices (those with a physical bootloader section of smaller than 6KB) a second
+ * section of memory (called the <i>Auxiliary Bootloader Section</i>) is added before the start of the real bootloader section,
+ * and is filled with a portion of the bootloader code. This allows smaller devices to run the bootloader, at the cost of an
+ * additional portion of the device's FLASH (the bootloader section size in KB subtracted from the 6KB total size). A small
+ * trampoline is inserted at the start of the auxiliary section so that the bootloader will run normally in the case of a blank
+ * application section.
+ *
+ * On devices supporting a 8KB bootloader section size, the AUX section is not created in the final binary.
+ *
+ * \subsection SSec_API_MemLayout Device Memory Map
+ * The following illustration indicates the final memory map of the device when loaded with the bootloader.
+ *
+ * \verbatim
+ * +----------------------------+ 0x0000
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | User Application |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * +----------------------------+ FLASHEND - BOOT_SECTION_SIZE - BOOT_AUX_SECTION_SIZE
+ * | Booloader Start Trampoline |
+ * | (Not User App. Accessible) |
+ * +----------------------------+ FLASHEND - BOOT_SECTION_SIZE - BOOT_AUX_SECTION_SIZE + 4
+ * | |
+ * | Auxiliary Bootloader |
+ * | Space for Smaller Devices |
+ * | (Not User App. Accessible) |
+ * | |
+ * +----------------------------+ FLASHEND - BOOT_SECTION_SIZE
+ * | |
+ * | Bootloader Application |
+ * | (Not User App. Accessible) |
+ * | |
+ * +----------------------------+ FLASHEND - 96
+ * | API Table Trampolines |
+ * | (Not User App. Accessible) |
+ * +----------------------------+ FLASHEND - 32
+ * | Bootloader API Table |
+ * | (User App. Accessible) |
+ * +----------------------------+ FLASHEND - 8
+ * | Bootloader ID Constants |
+ * | (User App. Accessible) |
+ * +----------------------------+ FLASHEND
+ * \endverbatim
+ *
+ * \section Sec_KnownIssues Known Issues:
+ *
+ * \par In some cases, the application is not fully loaded into the device.
+ * Write-caching on some operating systems may interfere with the normal
+ * operation of the bootloader. Write caching should be disabled when using the
+ * Mass Storage bootloader, or the file system synced via an appropriate command
+ * (such as the OS's normal disk ejection command) before disconnecting the device.
+ *
+ * \par After loading an application, it is not run automatically on startup.
+ * Some USB AVR boards ship with the BOOTRST fuse set, causing the bootloader
+ * to run automatically when the device is reset. In most cases, the BOOTRST
+ * fuse should be disabled and the HWBE fuse used instead to run the bootloader
+ * when needed.
+ *
+ * \section Sec_Options Project Options
+ *
+ * The following defines can be found in this demo, which can control the demo behaviour when defined, or changed in value.
+ *
+ * <table>
+ * <tr>
+ * <th><b>Define Name:</b></th>
+ * <th><b>Location:</b></th>
+ * <th><b>Description:</b></th>
+ * </tr>
+ * <tr>
+ * <td>NO_APP_START_ON_EJECT</td>
+ * <td>AppConfig.h</td>
+ * <td>Define to disable automatic start of the loaded application when the virtual
+ * Mass Storage disk is ejected on the host.</td>
+ * </tr>
+ * </table>
+ */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Config/AppConfig.h b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Config/AppConfig.h
new file mode 100644
index 000000000..6745a86e3
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Config/AppConfig.h
@@ -0,0 +1,47 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Application Configuration Header File
+ *
+ * This is a header file which is be used to configure LUFA's
+ * compile time options, as an alternative to the compile time
+ * constants supplied through a makefile.
+ *
+ * For information on what each token does, refer to the
+ * \ref Sec_Options section of the application documentation.
+ */
+
+#ifndef _APP_CONFIG_H_
+#define _APP_CONFIG_H_
+
+// #define NO_APP_START_ON_EJECT
+
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Config/LUFAConfig.h b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Config/LUFAConfig.h
new file mode 100644
index 000000000..c0648160c
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Config/LUFAConfig.h
@@ -0,0 +1,93 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief LUFA Library Configuration Header File
+ *
+ * This header file is used to configure LUFA's compile time options,
+ * as an alternative to the compile time constants supplied through
+ * a makefile.
+ *
+ * For information on what each token does, refer to the LUFA
+ * manual section "Summary of Compile Tokens".
+ */
+
+#ifndef _LUFA_CONFIG_H_
+#define _LUFA_CONFIG_H_
+
+ #if (ARCH == ARCH_AVR8)
+
+ /* Non-USB Related Configuration Tokens: */
+// #define DISABLE_TERMINAL_CODES
+
+ /* USB Class Driver Related Tokens: */
+// #define HID_HOST_BOOT_PROTOCOL_ONLY
+// #define HID_STATETABLE_STACK_DEPTH {Insert Value Here}
+// #define HID_USAGE_STACK_DEPTH {Insert Value Here}
+// #define HID_MAX_COLLECTIONS {Insert Value Here}
+// #define HID_MAX_REPORTITEMS {Insert Value Here}
+// #define HID_MAX_REPORT_IDS {Insert Value Here}
+// #define NO_CLASS_DRIVER_AUTOFLUSH
+
+ /* General USB Driver Related Tokens: */
+ #define ORDERED_EP_CONFIG
+ #define USE_STATIC_OPTIONS (USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)
+ #define USB_DEVICE_ONLY
+// #define USB_HOST_ONLY
+// #define USB_STREAM_TIMEOUT_MS {Insert Value Here}
+// #define NO_LIMITED_CONTROLLER_CONNECT
+ #define NO_SOF_EVENTS
+
+ /* USB Device Mode Driver Related Tokens: */
+ #define USE_RAM_DESCRIPTORS
+// #define USE_FLASH_DESCRIPTORS
+// #define USE_EEPROM_DESCRIPTORS
+ #define NO_INTERNAL_SERIAL
+ #define FIXED_CONTROL_ENDPOINT_SIZE 8
+ #define DEVICE_STATE_AS_GPIOR 0
+ #define FIXED_NUM_CONFIGURATIONS 1
+// #define CONTROL_ONLY_DEVICE
+ #define INTERRUPT_CONTROL_ENDPOINT
+ #define NO_DEVICE_REMOTE_WAKEUP
+ #define NO_DEVICE_SELF_POWER
+
+ /* USB Host Mode Driver Related Tokens: */
+// #define HOST_STATE_AS_GPIOR {Insert Value Here}
+// #define USB_HOST_TIMEOUT_MS {Insert Value Here}
+// #define HOST_DEVICE_SETTLE_DELAY_MS {Insert Value Here}
+// #define NO_AUTO_VBUS_MANAGEMENT
+// #define INVERTED_VBUS_ENABLE_LINE
+
+ #else
+
+ #error Unsupported architecture for this LUFA configuration file.
+
+ #endif
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Descriptors.c b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Descriptors.c
new file mode 100644
index 000000000..a1cefa351
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Descriptors.c
@@ -0,0 +1,157 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * USB Device Descriptors, for library use when in USB device mode. Descriptors are special
+ * computer-readable structures which the host requests upon device enumeration, to determine
+ * the device's capabilities and functions.
+ */
+
+#include "Descriptors.h"
+
+
+/** Device descriptor structure. This descriptor, located in SRAM memory, describes the overall
+ * device characteristics, including the supported USB version, control endpoint size and the
+ * number of device configurations. The descriptor is read out by the USB host when the enumeration
+ * process begins.
+ */
+const USB_Descriptor_Device_t DeviceDescriptor =
+{
+ .Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
+
+ .USBSpecification = VERSION_BCD(1,1,0),
+ .Class = USB_CSCP_NoDeviceClass,
+ .SubClass = USB_CSCP_NoDeviceSubclass,
+ .Protocol = USB_CSCP_NoDeviceProtocol,
+
+ .Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
+
+ .VendorID = 0x03EB,
+ .ProductID = 0x2045,
+ .ReleaseNumber = VERSION_BCD(0,0,1),
+
+ .ManufacturerStrIndex = NO_DESCRIPTOR,
+ .ProductStrIndex = NO_DESCRIPTOR,
+ .SerialNumStrIndex = NO_DESCRIPTOR,
+
+ .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
+};
+
+/** Configuration descriptor structure. This descriptor, located in FLASH memory, describes the usage
+ * of the device in one of its supported configurations, including information about any device interfaces
+ * and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting
+ * a configuration so that the host may correctly communicate with the USB device.
+ */
+const USB_Descriptor_Configuration_t ConfigurationDescriptor =
+{
+ .Config =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration},
+
+ .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
+ .TotalInterfaces = 1,
+
+ .ConfigurationNumber = 1,
+ .ConfigurationStrIndex = NO_DESCRIPTOR,
+
+ .ConfigAttributes = USB_CONFIG_ATTR_RESERVED,
+
+ .MaxPowerConsumption = USB_CONFIG_POWER_MA(100)
+ },
+
+ .MS_Interface =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
+
+ .InterfaceNumber = INTERFACE_ID_MassStorage,
+ .AlternateSetting = 0,
+
+ .TotalEndpoints = 2,
+
+ .Class = MS_CSCP_MassStorageClass,
+ .SubClass = MS_CSCP_SCSITransparentSubclass,
+ .Protocol = MS_CSCP_BulkOnlyTransportProtocol,
+
+ .InterfaceStrIndex = NO_DESCRIPTOR
+ },
+
+ .MS_DataInEndpoint =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
+
+ .EndpointAddress = MASS_STORAGE_IN_EPADDR,
+ .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
+ .EndpointSize = MASS_STORAGE_IO_EPSIZE,
+ .PollingIntervalMS = 0x05
+ },
+
+ .MS_DataOutEndpoint =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
+
+ .EndpointAddress = MASS_STORAGE_OUT_EPADDR,
+ .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
+ .EndpointSize = MASS_STORAGE_IO_EPSIZE,
+ .PollingIntervalMS = 0x05
+ }
+};
+
+/** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
+ * documentation) by the application code so that the address and size of a requested descriptor can be given
+ * to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function
+ * is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the
+ * USB host.
+ */
+uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+ const uint8_t wIndex,
+ const void** const DescriptorAddress)
+{
+ const uint8_t DescriptorType = (wValue >> 8);
+
+ const void* Address = NULL;
+ uint16_t Size = NO_DESCRIPTOR;
+
+ /* If/Else If chain compiles slightly smaller than a switch case */
+ if (DescriptorType == DTYPE_Device)
+ {
+ Address = &DeviceDescriptor;
+ Size = sizeof(USB_Descriptor_Device_t);
+ }
+ else if (DescriptorType == DTYPE_Configuration)
+ {
+ Address = &ConfigurationDescriptor;
+ Size = sizeof(USB_Descriptor_Configuration_t);
+ }
+
+ *DescriptorAddress = Address;
+ return Size;
+}
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Descriptors.h b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Descriptors.h
new file mode 100644
index 000000000..31747e4c8
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Descriptors.h
@@ -0,0 +1,88 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Header file for Descriptors.c.
+ */
+
+#ifndef _DESCRIPTORS_H_
+#define _DESCRIPTORS_H_
+
+ /* Includes: */
+ #include <avr/pgmspace.h>
+
+ #include <LUFA/Drivers/USB/USB.h>
+
+ #include "BootloaderAPI.h"
+
+ /* Macros: */
+ /** Endpoint address of the Mass Storage device-to-host data IN endpoint. */
+ #define MASS_STORAGE_IN_EPADDR (ENDPOINT_DIR_IN | 3)
+
+ /** Endpoint address of the Mass Storage host-to-device data OUT endpoint. */
+ #define MASS_STORAGE_OUT_EPADDR (ENDPOINT_DIR_OUT | 4)
+
+ /** Size in bytes of the Mass Storage data endpoints. */
+ #define MASS_STORAGE_IO_EPSIZE 64
+
+ /* Type Defines: */
+ /** Type define for the device configuration descriptor structure. This must be defined in the
+ * application code, as the configuration descriptor contains several sub-descriptors which
+ * vary between devices, and which describe the device's usage to the host.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Configuration_Header_t Config;
+
+ // Mass Storage Interface
+ USB_Descriptor_Interface_t MS_Interface;
+ USB_Descriptor_Endpoint_t MS_DataInEndpoint;
+ USB_Descriptor_Endpoint_t MS_DataOutEndpoint;
+ } USB_Descriptor_Configuration_t;
+
+
+ /** Enum for the device interface descriptor IDs within the device. Each interface descriptor
+ * should have a unique ID index associated with it, which can be used to refer to the
+ * interface from other descriptors.
+ */
+ enum InterfaceDescriptors_t
+ {
+ INTERFACE_ID_MassStorage = 0, /**< Mass storage interface descriptor ID */
+ };
+
+ /* Function Prototypes: */
+ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+ const uint8_t wIndex,
+ const void** const DescriptorAddress)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3) AUX_BOOT_SECTION;
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Lib/SCSI.c b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Lib/SCSI.c
new file mode 100644
index 000000000..ace118a48
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Lib/SCSI.c
@@ -0,0 +1,294 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * SCSI command processing routines, for SCSI commands issued by the host. Mass Storage
+ * devices use a thin "Bulk-Only Transport" protocol for issuing commands and status information,
+ * which wrap around standard SCSI device commands for controlling the actual storage medium.
+ */
+
+#define INCLUDE_FROM_SCSI_C
+#include "SCSI.h"
+
+/** Structure to hold the SCSI response data to a SCSI INQUIRY command. This gives information about the device's
+ * features and capabilities.
+ */
+static const SCSI_Inquiry_Response_t InquiryData =
+ {
+ .DeviceType = DEVICE_TYPE_BLOCK,
+ .PeripheralQualifier = 0,
+
+ .Removable = true,
+
+ .Version = 0,
+
+ .ResponseDataFormat = 2,
+ .NormACA = false,
+ .TrmTsk = false,
+ .AERC = false,
+
+ .AdditionalLength = 0x1F,
+
+ .SoftReset = false,
+ .CmdQue = false,
+ .Linked = false,
+ .Sync = false,
+ .WideBus16Bit = false,
+ .WideBus32Bit = false,
+ .RelAddr = false,
+
+ .VendorID = "LUFA",
+ .ProductID = "Bootloader",
+ .RevisionID = {'0','.','0','0'},
+ };
+
+/** Structure to hold the sense data for the last issued SCSI command, which is returned to the host after a SCSI REQUEST SENSE
+ * command is issued. This gives information on exactly why the last command failed to complete.
+ */
+static SCSI_Request_Sense_Response_t SenseData =
+ {
+ .ResponseCode = 0x70,
+ .AdditionalLength = 0x0A,
+ };
+
+
+/** Main routine to process the SCSI command located in the Command Block Wrapper read from the host. This dispatches
+ * to the appropriate SCSI command handling routine if the issued command is supported by the device, else it returns
+ * a command failure due to a ILLEGAL REQUEST.
+ *
+ * \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
+ *
+ * \return Boolean \c true if the command completed successfully, \c false otherwise
+ */
+bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
+{
+ bool CommandSuccess = false;
+
+ /* Run the appropriate SCSI command hander function based on the passed command */
+ switch (MSInterfaceInfo->State.CommandBlock.SCSICommandData[0])
+ {
+ case SCSI_CMD_INQUIRY:
+ CommandSuccess = SCSI_Command_Inquiry(MSInterfaceInfo);
+ break;
+ case SCSI_CMD_REQUEST_SENSE:
+ CommandSuccess = SCSI_Command_Request_Sense(MSInterfaceInfo);
+ break;
+ case SCSI_CMD_READ_CAPACITY_10:
+ CommandSuccess = SCSI_Command_Read_Capacity_10(MSInterfaceInfo);
+ break;
+ case SCSI_CMD_WRITE_10:
+ CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE);
+ break;
+ case SCSI_CMD_READ_10:
+ CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ);
+ break;
+ case SCSI_CMD_MODE_SENSE_6:
+ CommandSuccess = SCSI_Command_ModeSense_6(MSInterfaceInfo);
+ break;
+ case SCSI_CMD_START_STOP_UNIT:
+#if !defined(NO_APP_START_ON_EJECT)
+ /* If the user ejected the volume, signal bootloader exit at next opportunity. */
+ RunBootloader = ((MSInterfaceInfo->State.CommandBlock.SCSICommandData[4] & 0x03) != 0x02);
+#endif
+ case SCSI_CMD_SEND_DIAGNOSTIC:
+ case SCSI_CMD_TEST_UNIT_READY:
+ case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
+ case SCSI_CMD_VERIFY_10:
+ /* These commands should just succeed, no handling required */
+ CommandSuccess = true;
+ MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0;
+ break;
+ default:
+ /* Update the SENSE key to reflect the invalid command */
+ SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
+ SCSI_ASENSE_INVALID_COMMAND,
+ SCSI_ASENSEQ_NO_QUALIFIER);
+ break;
+ }
+
+ /* Check if command was successfully processed */
+ if (CommandSuccess)
+ {
+ SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD,
+ SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
+ SCSI_ASENSEQ_NO_QUALIFIER);
+
+ return true;
+ }
+
+ return false;
+}
+
+/** Command processing for an issued SCSI INQUIRY command. This command returns information about the device's features
+ * and capabilities to the host.
+ *
+ * \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
+ *
+ * \return Boolean \c true if the command completed successfully, \c false otherwise.
+ */
+static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
+{
+ uint16_t AllocationLength = SwapEndian_16(*(uint16_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[3]);
+ uint16_t BytesTransferred = MIN(AllocationLength, sizeof(InquiryData));
+
+ /* Only the standard INQUIRY data is supported, check if any optional INQUIRY bits set */
+ if ((MSInterfaceInfo->State.CommandBlock.SCSICommandData[1] & ((1 << 0) | (1 << 1))) ||
+ MSInterfaceInfo->State.CommandBlock.SCSICommandData[2])
+ {
+ /* Optional but unsupported bits set - update the SENSE key and fail the request */
+ SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
+ SCSI_ASENSE_INVALID_FIELD_IN_CDB,
+ SCSI_ASENSEQ_NO_QUALIFIER);
+
+ return false;
+ }
+
+ Endpoint_Write_Stream_LE(&InquiryData, BytesTransferred, NULL);
+
+ /* Pad out remaining bytes with 0x00 */
+ Endpoint_Null_Stream((AllocationLength - BytesTransferred), NULL);
+
+ /* Finalize the stream transfer to send the last packet */
+ Endpoint_ClearIN();
+
+ /* Succeed the command and update the bytes transferred counter */
+ MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred;
+
+ return true;
+}
+
+/** Command processing for an issued SCSI REQUEST SENSE command. This command returns information about the last issued command,
+ * including the error code and additional error information so that the host can determine why a command failed to complete.
+ *
+ * \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
+ *
+ * \return Boolean \c true if the command completed successfully, \c false otherwise.
+ */
+static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
+{
+ uint8_t AllocationLength = MSInterfaceInfo->State.CommandBlock.SCSICommandData[4];
+ uint8_t BytesTransferred = MIN(AllocationLength, sizeof(SenseData));
+
+ Endpoint_Write_Stream_LE(&SenseData, BytesTransferred, NULL);
+ Endpoint_Null_Stream((AllocationLength - BytesTransferred), NULL);
+ Endpoint_ClearIN();
+
+ /* Succeed the command and update the bytes transferred counter */
+ MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred;
+
+ return true;
+}
+
+/** Command processing for an issued SCSI READ CAPACITY (10) command. This command returns information about the device's capacity
+ * on the selected Logical Unit (drive), as a number of OS-sized blocks.
+ *
+ * \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
+ *
+ * \return Boolean \c true if the command completed successfully, \c false otherwise.
+ */
+static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
+{
+ Endpoint_Write_32_BE(LUN_MEDIA_BLOCKS - 1);
+ Endpoint_Write_32_BE(SECTOR_SIZE_BYTES);
+ Endpoint_ClearIN();
+
+ /* Succeed the command and update the bytes transferred counter */
+ MSInterfaceInfo->State.CommandBlock.DataTransferLength -= 8;
+
+ return true;
+}
+
+/** Command processing for an issued SCSI READ (10) or WRITE (10) command. This command reads in the block start address
+ * and total number of blocks to process, then calls the appropriate low-level Dataflash routine to handle the actual
+ * reading and writing of the data.
+ *
+ * \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
+ * \param[in] IsDataRead Indicates if the command is a READ (10) command or WRITE (10) command (DATA_READ or DATA_WRITE)
+ *
+ * \return Boolean \c true if the command completed successfully, \c false otherwise.
+ */
+static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
+ const bool IsDataRead)
+{
+ uint16_t BlockAddress;
+ uint16_t TotalBlocks;
+
+ /* Load in the 32-bit block address (SCSI uses big-endian, so have to reverse the byte order) */
+ BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]);
+
+ /* Load in the 16-bit total blocks (SCSI uses big-endian, so have to reverse the byte order) */
+ TotalBlocks = SwapEndian_16(*(uint16_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[7]);
+
+ /* Check if the block address is outside the maximum allowable value for the LUN */
+ if (BlockAddress >= LUN_MEDIA_BLOCKS)
+ {
+ /* Block address is invalid, update SENSE key and return command fail */
+ SCSI_SET_SENSE(SCSI_SENSE_KEY_ILLEGAL_REQUEST,
+ SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE,
+ SCSI_ASENSEQ_NO_QUALIFIER);
+
+ return false;
+ }
+
+ /* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */
+ for (uint16_t i = 0; i < TotalBlocks; i++)
+ {
+ if (IsDataRead == DATA_READ)
+ VirtualFAT_ReadBlock(BlockAddress + i);
+ else
+ VirtualFAT_WriteBlock(BlockAddress + i);
+ }
+
+ /* Update the bytes transferred counter and succeed the command */
+ MSInterfaceInfo->State.CommandBlock.DataTransferLength -= ((uint32_t)TotalBlocks * SECTOR_SIZE_BYTES);
+
+ return true;
+}
+
+/** Command processing for an issued SCSI MODE SENSE (6) command. This command returns various informational pages about
+ * the SCSI device, as well as the device's Write Protect status.
+ *
+ * \param[in] MSInterfaceInfo Pointer to the Mass Storage class interface structure that the command is associated with
+ *
+ * \return Boolean \c true if the command completed successfully, \c false otherwise.
+ */
+static bool SCSI_Command_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
+{
+ /* Send an empty header response indicating Write Protect flag is off */
+ Endpoint_Write_32_LE(0);
+ Endpoint_ClearIN();
+
+ /* Update the bytes transferred counter and succeed the command */
+ MSInterfaceInfo->State.CommandBlock.DataTransferLength -= 4;
+
+ return true;
+}
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Lib/SCSI.h b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Lib/SCSI.h
new file mode 100644
index 000000000..3529fde60
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Lib/SCSI.h
@@ -0,0 +1,84 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Header file for SCSI.c.
+ */
+
+#ifndef _SCSI_H_
+#define _SCSI_H_
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <avr/pgmspace.h>
+
+ #include <LUFA/Drivers/USB/USB.h>
+
+ #include "../BootloaderMassStorage.h"
+ #include "../Descriptors.h"
+ #include "VirtualFAT.h"
+
+ /* Macros: */
+ /** Macro to set the current SCSI sense data to the given key, additional sense code and additional sense qualifier. This
+ * is for convenience, as it allows for all three sense values (returned upon request to the host to give information about
+ * the last command failure) in a quick and easy manner.
+ *
+ * \param[in] Key New SCSI sense key to set the sense code to
+ * \param[in] Acode New SCSI additional sense key to set the additional sense code to
+ * \param[in] Aqual New SCSI additional sense key qualifier to set the additional sense qualifier code to
+ */
+ #define SCSI_SET_SENSE(Key, Acode, Aqual) do { SenseData.SenseKey = (Key); \
+ SenseData.AdditionalSenseCode = (Acode); \
+ SenseData.AdditionalSenseQualifier = (Aqual); } while (0)
+
+ /** Macro for the \ref SCSI_Command_ReadWrite_10() function, to indicate that data is to be read from the storage medium. */
+ #define DATA_READ true
+
+ /** Macro for the \ref SCSI_Command_ReadWrite_10() function, to indicate that data is to be written to the storage medium. */
+ #define DATA_WRITE false
+
+ /** Value for the DeviceType entry in the SCSI_Inquiry_Response_t enum, indicating a Block Media device. */
+ #define DEVICE_TYPE_BLOCK 0x00
+
+ /* Function Prototypes: */
+ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) AUX_BOOT_SECTION;
+
+ #if defined(INCLUDE_FROM_SCSI_C)
+ static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) AUX_BOOT_SECTION;
+ static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) AUX_BOOT_SECTION;
+ static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) AUX_BOOT_SECTION;
+ static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
+ const bool IsDataRead) AUX_BOOT_SECTION;
+ static bool SCSI_Command_ModeSense_6(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) AUX_BOOT_SECTION;
+ #endif
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Lib/VirtualFAT.c b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Lib/VirtualFAT.c
new file mode 100644
index 000000000..907b4e5ff
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Lib/VirtualFAT.c
@@ -0,0 +1,482 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Virtualized FAT12 filesystem implementation, to perform self-programming
+ * in response to read and write requests to the virtual filesystem by the
+ * host PC.
+ */
+
+#define INCLUDE_FROM_VIRTUAL_FAT_C
+#include "VirtualFAT.h"
+
+/** FAT filesystem boot sector block, must be the first sector on the physical
+ * disk so that the host can identify the presence of a FAT filesystem. This
+ * block is truncated; normally a large bootstrap section is located near the
+ * end of the block for booting purposes however as this is not meant to be a
+ * bootable disk it is omitted for space reasons.
+ *
+ * \note When returning the boot block to the host, the magic signature 0xAA55
+ * must be added to the very end of the block to identify it as a boot
+ * block.
+ */
+static const FATBootBlock_t BootBlock =
+ {
+ .Bootstrap = {0xEB, 0x3C, 0x90},
+ .Description = "mkdosfs",
+ .SectorSize = SECTOR_SIZE_BYTES,
+ .SectorsPerCluster = SECTOR_PER_CLUSTER,
+ .ReservedSectors = 1,
+ .FATCopies = 2,
+ .RootDirectoryEntries = (SECTOR_SIZE_BYTES / sizeof(FATDirectoryEntry_t)),
+ .TotalSectors16 = LUN_MEDIA_BLOCKS,
+ .MediaDescriptor = 0xF8,
+ .SectorsPerFAT = 1,
+ .SectorsPerTrack = (LUN_MEDIA_BLOCKS % 64),
+ .Heads = (LUN_MEDIA_BLOCKS / 64),
+ .HiddenSectors = 0,
+ .TotalSectors32 = 0,
+ .PhysicalDriveNum = 0,
+ .ExtendedBootRecordSig = 0x29,
+ .VolumeSerialNumber = 0x12345678,
+ .VolumeLabel = "LUFA BOOT ",
+ .FilesystemIdentifier = "FAT12 ",
+ };
+
+/** FAT 8.3 style directory entry, for the virtual FLASH contents file. */
+static FATDirectoryEntry_t FirmwareFileEntries[] =
+ {
+ /* Root volume label entry; disk label is contained in the Filename and
+ * Extension fields (concatenated) with a special attribute flag - other
+ * fields are ignored. Should be the same as the label in the boot block.
+ */
+ [DISK_FILE_ENTRY_VolumeID] =
+ {
+ .MSDOS_Directory =
+ {
+ .Name = "LUFA BOOT ",
+ .Attributes = FAT_FLAG_VOLUME_NAME,
+ .Reserved = {0},
+ .CreationTime = 0,
+ .CreationDate = 0,
+ .StartingCluster = 0,
+ .Reserved2 = 0,
+ }
+ },
+
+ /* VFAT Long File Name entry for the virtual firmware file; required to
+ * prevent corruption from systems that are unable to detect the device
+ * as being a legacy MSDOS style FAT12 volume. */
+ [DISK_FILE_ENTRY_FLASH_LFN] =
+ {
+ .VFAT_LongFileName =
+ {
+ .Ordinal = 1 | FAT_ORDINAL_LAST_ENTRY,
+ .Attribute = FAT_FLAG_LONG_FILE_NAME,
+ .Reserved1 = 0,
+ .Reserved2 = 0,
+
+ .Checksum = FAT_CHECKSUM('F','L','A','S','H',' ',' ',' ','B','I','N'),
+
+ .Unicode1 = 'F',
+ .Unicode2 = 'L',
+ .Unicode3 = 'A',
+ .Unicode4 = 'S',
+ .Unicode5 = 'H',
+ .Unicode6 = '.',
+ .Unicode7 = 'B',
+ .Unicode8 = 'I',
+ .Unicode9 = 'N',
+ .Unicode10 = 0,
+ .Unicode11 = 0,
+ .Unicode12 = 0,
+ .Unicode13 = 0,
+ }
+ },
+
+ /* MSDOS file entry for the virtual Firmware image. */
+ [DISK_FILE_ENTRY_FLASH_MSDOS] =
+ {
+ .MSDOS_File =
+ {
+ .Filename = "FLASH ",
+ .Extension = "BIN",
+ .Attributes = 0,
+ .Reserved = {0},
+ .CreationTime = FAT_TIME(1, 1, 0),
+ .CreationDate = FAT_DATE(14, 2, 1989),
+ .StartingCluster = 2,
+ .FileSizeBytes = FLASH_FILE_SIZE_BYTES,
+ }
+ },
+
+ [DISK_FILE_ENTRY_EEPROM_LFN] =
+ {
+ .VFAT_LongFileName =
+ {
+ .Ordinal = 1 | FAT_ORDINAL_LAST_ENTRY,
+ .Attribute = FAT_FLAG_LONG_FILE_NAME,
+ .Reserved1 = 0,
+ .Reserved2 = 0,
+
+ .Checksum = FAT_CHECKSUM('E','E','P','R','O','M',' ',' ','B','I','N'),
+
+ .Unicode1 = 'E',
+ .Unicode2 = 'E',
+ .Unicode3 = 'P',
+ .Unicode4 = 'R',
+ .Unicode5 = 'O',
+ .Unicode6 = 'M',
+ .Unicode7 = '.',
+ .Unicode8 = 'B',
+ .Unicode9 = 'I',
+ .Unicode10 = 'N',
+ .Unicode11 = 0,
+ .Unicode12 = 0,
+ .Unicode13 = 0,
+ }
+ },
+
+ [DISK_FILE_ENTRY_EEPROM_MSDOS] =
+ {
+ .MSDOS_File =
+ {
+ .Filename = "EEPROM ",
+ .Extension = "BIN",
+ .Attributes = 0,
+ .Reserved = {0},
+ .CreationTime = FAT_TIME(1, 1, 0),
+ .CreationDate = FAT_DATE(14, 2, 1989),
+ .StartingCluster = 2 + FILE_CLUSTERS(FLASH_FILE_SIZE_BYTES),
+ .FileSizeBytes = EEPROM_FILE_SIZE_BYTES,
+ }
+ },
+ };
+
+/** Starting cluster of the virtual FLASH.BIN file on disk, tracked so that the
+ * offset from the start of the data sector can be determined. On Windows
+ * systems files are usually replaced using the original file's disk clusters,
+ * while Linux appears to overwrite with an offset which must be compensated for.
+ */
+static const uint16_t* FLASHFileStartCluster = &FirmwareFileEntries[DISK_FILE_ENTRY_FLASH_MSDOS].MSDOS_File.StartingCluster;
+
+/** Starting cluster of the virtual EEPROM.BIN file on disk, tracked so that the
+ * offset from the start of the data sector can be determined. On Windows
+ * systems files are usually replaced using the original file's disk clusters,
+ * while Linux appears to overwrite with an offset which must be compensated for.
+ */
+static const uint16_t* EEPROMFileStartCluster = &FirmwareFileEntries[DISK_FILE_ENTRY_EEPROM_MSDOS].MSDOS_File.StartingCluster;
+
+/** Reads a byte of EEPROM out from the EEPROM memory space.
+ *
+ * \note This function is required as the avr-libc EEPROM functions do not cope
+ * with linker relaxations, and a jump longer than 4K of FLASH on the
+ * larger USB AVRs will break the linker. This function is marked as
+ * never inlinable and placed into the normal text segment so that the
+ * call to the EEPROM function will be short even if the AUX boot section
+ * is used.
+ *
+ * \param[in] Address Address of the EEPROM location to read from
+ *
+ * \return Read byte of EEPROM data.
+ */
+static uint8_t ReadEEPROMByte(const uint8_t* const Address)
+{
+ return eeprom_read_byte(Address);
+}
+
+/** Writes a byte of EEPROM out to the EEPROM memory space.
+ *
+ * \note This function is required as the avr-libc EEPROM functions do not cope
+ * with linker relaxations, and a jump longer than 4K of FLASH on the
+ * larger USB AVRs will break the linker. This function is marked as
+ * never inlinable and placed into the normal text segment so that the
+ * call to the EEPROM function will be short even if the AUX boot section
+ * is used.
+ *
+ * \param[in] Address Address of the EEPROM location to write to
+ * \param[in] Data New data to write to the EEPROM location
+ */
+static void WriteEEPROMByte(uint8_t* const Address,
+ const uint8_t Data)
+{
+ eeprom_update_byte(Address, Data);
+}
+
+/** Updates a FAT12 cluster entry in the FAT file table with the specified next
+ * chain index. If the cluster is the last in the file chain, the magic value
+ * \c 0xFFF should be used.
+ *
+ * \note FAT data cluster indexes are offset by 2, so that cluster 2 is the
+ * first file data cluster on the disk. See the FAT specification.
+ *
+ * \param[out] FATTable Pointer to the FAT12 allocation table
+ * \param[in] Index Index of the cluster entry to update
+ * \param[in] ChainEntry Next cluster index in the file chain
+ */
+static void UpdateFAT12ClusterEntry(uint8_t* const FATTable,
+ const uint16_t Index,
+ const uint16_t ChainEntry)
+{
+ /* Calculate the starting offset of the cluster entry in the FAT12 table */
+ uint8_t FATOffset = (Index + (Index >> 1));
+ bool UpperNibble = ((Index & 1) != 0);
+
+ /* Check if the start of the entry is at an upper nibble of the byte, fill
+ * out FAT12 entry as required */
+ if (UpperNibble)
+ {
+ FATTable[FATOffset] = (FATTable[FATOffset] & 0x0F) | ((ChainEntry & 0x0F) << 4);
+ FATTable[FATOffset + 1] = (ChainEntry >> 4);
+ }
+ else
+ {
+ FATTable[FATOffset] = ChainEntry;
+ FATTable[FATOffset + 1] = (FATTable[FATOffset] & 0xF0) | (ChainEntry >> 8);
+ }
+}
+
+/** Updates a FAT12 cluster chain in the FAT file table with a linear chain of
+ * the specified length.
+ *
+ * \note FAT data cluster indexes are offset by 2, so that cluster 2 is the
+ * first file data cluster on the disk. See the FAT specification.
+ *
+ * \param[out] FATTable Pointer to the FAT12 allocation table
+ * \param[in] Index Index of the start of the cluster chain to update
+ * \param[in] ChainLength Length of the chain to write, in clusters
+ */
+static void UpdateFAT12ClusterChain(uint8_t* const FATTable,
+ const uint16_t Index,
+ const uint8_t ChainLength)
+{
+ for (uint8_t i = 0; i < ChainLength; i++)
+ {
+ uint16_t CurrentCluster = Index + i;
+ uint16_t NextCluster = CurrentCluster + 1;
+
+ /* Mark last cluster as end of file */
+ if (i == (ChainLength - 1))
+ NextCluster = 0xFFF;
+
+ UpdateFAT12ClusterEntry(FATTable, CurrentCluster, NextCluster);
+ }
+}
+
+/** Reads or writes a block of data from/to the physical device FLASH using a
+ * block buffer stored in RAM, if the requested block is within the virtual
+ * firmware file's sector ranges in the emulated FAT file system.
+ *
+ * \param[in] BlockNumber Physical disk block to read from/write to
+ * \param[in,out] BlockBuffer Pointer to the start of the block buffer in RAM
+ * \param[in] Read If \c true, the requested block is read, if
+ * \c false, the requested block is written
+ */
+static void ReadWriteFLASHFileBlock(const uint16_t BlockNumber,
+ uint8_t* BlockBuffer,
+ const bool Read)
+{
+ uint16_t FileStartBlock = DISK_BLOCK_DataStartBlock + (*FLASHFileStartCluster - 2) * SECTOR_PER_CLUSTER;
+ uint16_t FileEndBlock = FileStartBlock + (FILE_SECTORS(FLASH_FILE_SIZE_BYTES) - 1);
+
+ /* Range check the write request - abort if requested block is not within the
+ * virtual firmware file sector range */
+ if (!((BlockNumber >= FileStartBlock) && (BlockNumber <= FileEndBlock)))
+ return;
+
+ #if (FLASHEND > 0xFFFF)
+ uint32_t FlashAddress = (uint32_t)(BlockNumber - FileStartBlock) * SECTOR_SIZE_BYTES;
+ #else
+ uint16_t FlashAddress = (uint16_t)(BlockNumber - FileStartBlock) * SECTOR_SIZE_BYTES;
+ #endif
+
+ if (Read)
+ {
+ /* Read out the mapped block of data from the device's FLASH */
+ for (uint16_t i = 0; i < SECTOR_SIZE_BYTES; i++)
+ {
+ #if (FLASHEND > 0xFFFF)
+ BlockBuffer[i] = pgm_read_byte_far(FlashAddress++);
+ #else
+ BlockBuffer[i] = pgm_read_byte(FlashAddress++);
+ #endif
+ }
+ }
+ else
+ {
+ /* Write out the mapped block of data to the device's FLASH */
+ for (uint16_t i = 0; i < SECTOR_SIZE_BYTES; i += 2)
+ {
+ if ((FlashAddress % SPM_PAGESIZE) == 0)
+ {
+ /* Erase the given FLASH page, ready to be programmed */
+ BootloaderAPI_ErasePage(FlashAddress);
+ }
+
+ /* Write the next data word to the FLASH page */
+ BootloaderAPI_FillWord(FlashAddress, (BlockBuffer[i + 1] << 8) | BlockBuffer[i]);
+ FlashAddress += 2;
+
+ if ((FlashAddress % SPM_PAGESIZE) == 0)
+ {
+ /* Write the filled FLASH page to memory */
+ BootloaderAPI_WritePage(FlashAddress - SPM_PAGESIZE);
+ }
+ }
+ }
+}
+
+/** Reads or writes a block of data from/to the physical device EEPROM using a
+ * block buffer stored in RAM, if the requested block is within the virtual
+ * firmware file's sector ranges in the emulated FAT file system.
+ *
+ * \param[in] BlockNumber Physical disk block to read from/write to
+ * \param[in,out] BlockBuffer Pointer to the start of the block buffer in RAM
+ * \param[in] Read If \c true, the requested block is read, if
+ * \c false, the requested block is written
+ */
+static void ReadWriteEEPROMFileBlock(const uint16_t BlockNumber,
+ uint8_t* BlockBuffer,
+ const bool Read)
+{
+ uint16_t FileStartBlock = DISK_BLOCK_DataStartBlock + (*EEPROMFileStartCluster - 2) * SECTOR_PER_CLUSTER;
+ uint16_t FileEndBlock = FileStartBlock + (FILE_SECTORS(EEPROM_FILE_SIZE_BYTES) - 1);
+
+ /* Range check the write request - abort if requested block is not within the
+ * virtual firmware file sector range */
+ if (!((BlockNumber >= FileStartBlock) && (BlockNumber <= FileEndBlock)))
+ return;
+
+ uint16_t EEPROMAddress = (uint16_t)(BlockNumber - FileStartBlock) * SECTOR_SIZE_BYTES;
+
+ if (Read)
+ {
+ /* Read out the mapped block of data from the device's EEPROM */
+ for (uint16_t i = 0; i < SECTOR_SIZE_BYTES; i++)
+ BlockBuffer[i] = ReadEEPROMByte((uint8_t*)EEPROMAddress++);
+ }
+ else
+ {
+ /* Write out the mapped block of data to the device's EEPROM */
+ for (uint16_t i = 0; i < SECTOR_SIZE_BYTES; i++)
+ WriteEEPROMByte((uint8_t*)EEPROMAddress++, BlockBuffer[i]);
+ }
+}
+
+/** Writes a block of data to the virtual FAT filesystem, from the USB Mass
+ * Storage interface.
+ *
+ * \param[in] BlockNumber Index of the block to write.
+ */
+void VirtualFAT_WriteBlock(const uint16_t BlockNumber)
+{
+ uint8_t BlockBuffer[SECTOR_SIZE_BYTES];
+
+ /* Buffer the entire block to be written from the host */
+ Endpoint_Read_Stream_LE(BlockBuffer, sizeof(BlockBuffer), NULL);
+ Endpoint_ClearOUT();
+
+ switch (BlockNumber)
+ {
+ case DISK_BLOCK_BootBlock:
+ case DISK_BLOCK_FATBlock1:
+ case DISK_BLOCK_FATBlock2:
+ /* Ignore writes to the boot and FAT blocks */
+
+ break;
+
+ case DISK_BLOCK_RootFilesBlock:
+ /* Copy over the updated directory entries */
+ memcpy(FirmwareFileEntries, BlockBuffer, sizeof(FirmwareFileEntries));
+
+ break;
+
+ default:
+ ReadWriteFLASHFileBlock(BlockNumber, BlockBuffer, false);
+ ReadWriteEEPROMFileBlock(BlockNumber, BlockBuffer, false);
+
+ break;
+ }
+}
+
+/** Reads a block of data from the virtual FAT filesystem, and sends it to the
+ * host via the USB Mass Storage interface.
+ *
+ * \param[in] BlockNumber Index of the block to read.
+ */
+void VirtualFAT_ReadBlock(const uint16_t BlockNumber)
+{
+ uint8_t BlockBuffer[SECTOR_SIZE_BYTES];
+ memset(BlockBuffer, 0x00, sizeof(BlockBuffer));
+
+ switch (BlockNumber)
+ {
+ case DISK_BLOCK_BootBlock:
+ memcpy(BlockBuffer, &BootBlock, sizeof(FATBootBlock_t));
+
+ /* Add the magic signature to the end of the block */
+ BlockBuffer[SECTOR_SIZE_BYTES - 2] = 0x55;
+ BlockBuffer[SECTOR_SIZE_BYTES - 1] = 0xAA;
+
+ break;
+
+ case DISK_BLOCK_FATBlock1:
+ case DISK_BLOCK_FATBlock2:
+ /* Cluster 0: Media type/Reserved */
+ UpdateFAT12ClusterEntry(BlockBuffer, 0, 0xF00 | BootBlock.MediaDescriptor);
+
+ /* Cluster 1: Reserved */
+ UpdateFAT12ClusterEntry(BlockBuffer, 1, 0xFFF);
+
+ /* Cluster 2 onwards: Cluster chain of FLASH.BIN */
+ UpdateFAT12ClusterChain(BlockBuffer, *FLASHFileStartCluster, FILE_CLUSTERS(FLASH_FILE_SIZE_BYTES));
+
+ /* Cluster 2+n onwards: Cluster chain of EEPROM.BIN */
+ UpdateFAT12ClusterChain(BlockBuffer, *EEPROMFileStartCluster, FILE_CLUSTERS(EEPROM_FILE_SIZE_BYTES));
+
+ break;
+
+ case DISK_BLOCK_RootFilesBlock:
+ memcpy(BlockBuffer, FirmwareFileEntries, sizeof(FirmwareFileEntries));
+
+ break;
+
+ default:
+ ReadWriteFLASHFileBlock(BlockNumber, BlockBuffer, true);
+ ReadWriteEEPROMFileBlock(BlockNumber, BlockBuffer, true);
+
+ break;
+ }
+
+ /* Write the entire read block Buffer to the host */
+ Endpoint_Write_Stream_LE(BlockBuffer, sizeof(BlockBuffer), NULL);
+ Endpoint_ClearIN();
+}
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Lib/VirtualFAT.h b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Lib/VirtualFAT.h
new file mode 100644
index 000000000..380132c53
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/Lib/VirtualFAT.h
@@ -0,0 +1,302 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#ifndef _VIRTUALFAT_H_
+#define _VIRTUALFAT_H_
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <avr/pgmspace.h>
+
+ #include <LUFA/Drivers/USB/USB.h>
+
+ #include "../BootloaderAPI.h"
+
+ /* Macros: */
+ /** Size of the virtual FLASH.BIN file in bytes. */
+ #define FLASH_FILE_SIZE_BYTES (FLASHEND - (FLASHEND - BOOT_START_ADDR) - AUX_BOOT_SECTION_SIZE)
+
+ /** Size of the virtual EEPROM.BIN file in bytes. */
+ #define EEPROM_FILE_SIZE_BYTES E2END
+
+ /** Number of sectors that comprise a single logical disk cluster. */
+ #define SECTOR_PER_CLUSTER 4
+
+ /** Size of a single logical sector on the disk. */
+ #define SECTOR_SIZE_BYTES 512
+
+ /** Size of a logical cluster on the disk, in bytes */
+ #define CLUSTER_SIZE_BYTES (SECTOR_PER_CLUSTER * SECTOR_SIZE_BYTES)
+
+ /** Number of sectors required to store a given size in bytes.
+ *
+ * \param[in] size Size of the data that needs to be stored
+ *
+ * \return Number of sectors required to store the given data on the disk.
+ */
+ #define FILE_SECTORS(size) ((size / SECTOR_SIZE_BYTES) + ((size % SECTOR_SIZE_BYTES) ? 1 : 0))
+
+ /** Number of clusters required to store a given size in bytes.
+ *
+ * \param[in] size Size of the data that needs to be stored
+ *
+ * \return Number of clusters required to store the given data on the disk.
+ */
+ #define FILE_CLUSTERS(size) ((size / CLUSTER_SIZE_BYTES) + ((size % CLUSTER_SIZE_BYTES) ? 1 : 0))
+
+ /** Total number of logical sectors/blocks on the disk. */
+ #define LUN_MEDIA_BLOCKS (FILE_SECTORS(FLASH_FILE_SIZE_BYTES) + FILE_SECTORS(EEPROM_FILE_SIZE_BYTES) + 32)
+
+ /** Converts a given time in HH:MM:SS format to a FAT filesystem time.
+ *
+ * \note The minimum seconds resolution of FAT is 2, thus odd seconds
+ * will be truncated to the previous integer multiple of 2 seconds.
+ *
+ * \param[in] hh Hours (0-23)
+ * \param[in] mm Minutes (0-59)
+ * \param[in] ss Seconds (0-59)
+ *
+ * \return Given time encoded as a FAT filesystem timestamp
+ */
+ #define FAT_TIME(hh, mm, ss) ((hh << 11) | (mm << 5) | (ss >> 1))
+
+ /** Converts a given date in DD/MM/YYYY format to a FAT filesystem date.
+ *
+ * \param[in] dd Days in the month (1-31)
+ * \param[in] mm Months in the year (1-12)
+ * \param[in] yyyy Year (1980 - 2107)
+ *
+ * \return Given date encoded as a FAT filesystem datestamp
+ */
+ #define FAT_DATE(dd, mm, yyyy) (((yyyy - 1980) << 9) | (mm << 5) | (dd << 0))
+
+ /** Bit-rotates a given 8-bit value once to the right.
+ *
+ * \param x Value to rotate right once
+ *
+ * \return Bit-rotated input value, rotated once to the right.
+ */
+ #define _ROT8(x) ((((x) & 0xFE) >> 1) | (((x) & 1) ? 0x80 : 0x00))
+
+ /** Computes the LFN entry checksum of a MSDOS 8.3 format file entry,
+ * to associate a LFN entry with its short file entry.
+ *
+ * \param n0 MSDOS Filename character 1
+ * \param n1 MSDOS Filename character 2
+ * \param n2 MSDOS Filename character 3
+ * \param n3 MSDOS Filename character 4
+ * \param n4 MSDOS Filename character 5
+ * \param n5 MSDOS Filename character 6
+ * \param n6 MSDOS Filename character 7
+ * \param n7 MSDOS Filename character 8
+ * \param e0 MSDOS Extension character 1
+ * \param e1 MSDOS Extension character 2
+ * \param e2 MSDOS Extension character 3
+ *
+ * \return LFN checksum of the given MSDOS 8.3 filename.
+ */
+ #define FAT_CHECKSUM(n0, n1, n2, n3, n4, n5, n6, n7, e0, e1, e2) \
+ (uint8_t)(_ROT8(_ROT8(_ROT8(_ROT8(_ROT8(_ROT8(_ROT8(_ROT8(_ROT8(_ROT8(n0)+n1)+n2)+n3)+n4)+n5)+n6)+n7)+e0)+e1)+e2)
+
+ /** \name FAT Filesystem Flags */
+ //@{
+ /** FAT attribute flag to indicate a read-only file. */
+ #define FAT_FLAG_READONLY (1 << 0)
+
+ /** FAT attribute flag to indicate a hidden file. */
+ #define FAT_FLAG_HIDDEN (1 << 1)
+
+ /** FAT attribute flag to indicate a system file. */
+ #define FAT_FLAG_SYSTEM (1 << 2)
+
+ /** FAT attribute flag to indicate a Volume name entry. */
+ #define FAT_FLAG_VOLUME_NAME (1 << 3)
+
+ /** FAT attribute flag to indicate a directory entry. */
+ #define FAT_FLAG_DIRECTORY (1 << 4)
+
+ /** FAT attribute flag to indicate a file ready for archiving. */
+ #define FAT_FLAG_ARCHIVE (1 << 5)
+
+ /** FAT pseudo-attribute flag to indicate a Long File Name entry. */
+ #define FAT_FLAG_LONG_FILE_NAME 0x0F
+
+ /** Ordinal flag marker for FAT Long File Name entries to mark the last entry. */
+ #define FAT_ORDINAL_LAST_ENTRY (1 << 6)
+ //@}
+
+ /* Enums: */
+ /** Enum for the Root FAT file entry indexes on the disk. This can be used
+ * to retrieve the current contents of a known directory entry.
+ */
+ enum
+ {
+ /** Volume ID directory entry, giving the name of the virtual disk. */
+ DISK_FILE_ENTRY_VolumeID = 0,
+ /** Long File Name FAT file entry of the virtual FLASH.BIN image file. */
+ DISK_FILE_ENTRY_FLASH_LFN = 1,
+ /** Legacy MSDOS FAT file entry of the virtual FLASH.BIN image file. */
+ DISK_FILE_ENTRY_FLASH_MSDOS = 2,
+ /** Long File Name FAT file entry of the virtual EEPROM.BIN image file. */
+ DISK_FILE_ENTRY_EEPROM_LFN = 3,
+ /** Legacy MSDOS FAT file entry of the virtual EEPROM.BIN image file. */
+ DISK_FILE_ENTRY_EEPROM_MSDOS = 4,
+ };
+
+ /** Enum for the physical disk blocks of the virtual disk. */
+ enum
+ {
+ /** Boot sector disk block. */
+ DISK_BLOCK_BootBlock = 0,
+ /** First copy of the FAT table block. */
+ DISK_BLOCK_FATBlock1 = 1,
+ /** Second copy of the FAT table block. */
+ DISK_BLOCK_FATBlock2 = 2,
+ /** Root file and directory entries block. */
+ DISK_BLOCK_RootFilesBlock = 3,
+ /** Start block of the disk data section. */
+ DISK_BLOCK_DataStartBlock = 4,
+ };
+
+ /* Type Definitions: */
+ /** FAT boot block structure definition, used to identify the core
+ * parameters of a FAT file system stored on a disk.
+ *
+ * \note This definition is truncated to save space; the magic signature
+ * \c 0xAA55 must be appended to the very end of the block for it
+ * to be detected by the host as a valid boot block.
+ */
+ typedef struct
+ {
+ uint8_t Bootstrap[3];
+ uint8_t Description[8];
+ uint16_t SectorSize;
+ uint8_t SectorsPerCluster;
+ uint16_t ReservedSectors;
+ uint8_t FATCopies;
+ uint16_t RootDirectoryEntries;
+ uint16_t TotalSectors16;
+ uint8_t MediaDescriptor;
+ uint16_t SectorsPerFAT;
+ uint16_t SectorsPerTrack;
+ uint16_t Heads;
+ uint32_t HiddenSectors;
+ uint32_t TotalSectors32;
+ uint16_t PhysicalDriveNum;
+ uint8_t ExtendedBootRecordSig;
+ uint32_t VolumeSerialNumber;
+ uint8_t VolumeLabel[11];
+ uint8_t FilesystemIdentifier[8];
+ /* uint8_t BootstrapProgram[448]; */
+ /* uint16_t MagicSignature; */
+ } FATBootBlock_t;
+
+ /** FAT directory entry structure, for the various kinds of File and
+ * directory descriptors on a FAT disk.
+ */
+ typedef union
+ {
+ /** VFAT Long File Name file entry. */
+ struct
+ {
+ uint8_t Ordinal;
+ uint16_t Unicode1;
+ uint16_t Unicode2;
+ uint16_t Unicode3;
+ uint16_t Unicode4;
+ uint16_t Unicode5;
+ uint8_t Attribute;
+ uint8_t Reserved1;
+ uint8_t Checksum;
+ uint16_t Unicode6;
+ uint16_t Unicode7;
+ uint16_t Unicode8;
+ uint16_t Unicode9;
+ uint16_t Unicode10;
+ uint16_t Unicode11;
+ uint16_t Reserved2;
+ uint16_t Unicode12;
+ uint16_t Unicode13;
+ } VFAT_LongFileName;
+
+ /** Legacy FAT MSDOS 8.3 file entry. */
+ struct
+ {
+ uint8_t Filename[8];
+ uint8_t Extension[3];
+ uint8_t Attributes;
+ uint8_t Reserved[10];
+ uint16_t CreationTime;
+ uint16_t CreationDate;
+ uint16_t StartingCluster;
+ uint32_t FileSizeBytes;
+ } MSDOS_File;
+
+ /** Legacy FAT MSDOS (sub-)directory entry. */
+ struct
+ {
+ uint8_t Name[11];
+ uint8_t Attributes;
+ uint8_t Reserved[10];
+ uint16_t CreationTime;
+ uint16_t CreationDate;
+ uint16_t StartingCluster;
+ uint32_t Reserved2;
+ } MSDOS_Directory;
+ } FATDirectoryEntry_t;
+
+ /* Function Prototypes: */
+ #if defined(INCLUDE_FROM_VIRTUAL_FAT_C)
+ static uint8_t ReadEEPROMByte(const uint8_t* const Address) ATTR_NO_INLINE;
+
+ static void WriteEEPROMByte(uint8_t* const Address,
+ const uint8_t Data) ATTR_NO_INLINE;
+
+ static void UpdateFAT12ClusterEntry(uint8_t* const FATTable,
+ const uint16_t Index,
+ const uint16_t ChainEntry) AUX_BOOT_SECTION;
+
+ static void UpdateFAT12ClusterChain(uint8_t* const FATTable,
+ const uint16_t StartIndex,
+ const uint8_t ChainLength) AUX_BOOT_SECTION;
+
+ static void ReadWriteFLASHFileBlock(const uint16_t BlockNumber,
+ uint8_t* BlockBuffer,
+ const bool Read) AUX_BOOT_SECTION;
+
+ static void ReadWriteEEPROMFileBlock(const uint16_t BlockNumber,
+ uint8_t* BlockBuffer,
+ const bool Read) AUX_BOOT_SECTION;
+ #endif
+
+ void VirtualFAT_WriteBlock(const uint16_t BlockNumber) AUX_BOOT_SECTION;
+ void VirtualFAT_ReadBlock(const uint16_t BlockNumber) AUX_BOOT_SECTION;
+
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/asf.xml b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/asf.xml
new file mode 100644
index 000000000..f1d550d1e
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/asf.xml
@@ -0,0 +1,156 @@
+<asf xmlversion="1.0">
+ <project caption="Mass Storage Bootloader - 128KB FLASH / 8KB Boot - AVR8 Architecture" id="lufa.bootloaders.mass_storage.avr8.128_8" force-caption="true" workspace-name="lufa_ms_128kb_8kb_">
+ <require idref="lufa.bootloaders.mass_storage"/>
+ <require idref="lufa.boards.dummy.avr8"/>
+ <generator value="as5_8"/>
+
+ <device-support value="at90usb1287"/>
+ <config name="lufa.drivers.board.name" value="none"/>
+
+ <config name="config.compiler.optimization.level" value="size"/>
+
+ <build type="define" name="F_CPU" value="16000000UL"/>
+ <build type="define" name="F_USB" value="16000000UL"/>
+
+ <build type="define" name="BOOT_START_ADDR" value="0x1E000"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.text=0x1E000"/>
+
+ <build type="define" name="AUX_BOOT_SECTION_SIZE" value="0"/>
+
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x1FFA0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x1FFE0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x1FFF8"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
+ </project>
+
+ <project caption="Mass Storage Bootloader - 64KB FLASH / 8KB Boot - AVR8 Architecture" id="lufa.bootloaders.mass_storage.avr8.64_8" force-caption="true" workspace-name="lufa_ms_64kb_8kb_">
+ <require idref="lufa.bootloaders.mass_storage"/>
+ <require idref="lufa.boards.dummy.avr8"/>
+ <generator value="as5_8"/>
+
+ <device-support value="at90usb647"/>
+ <config name="lufa.drivers.board.name" value="none"/>
+
+ <config name="config.compiler.optimization.level" value="size"/>
+
+ <build type="define" name="F_CPU" value="16000000UL"/>
+ <build type="define" name="F_USB" value="16000000UL"/>
+
+ <build type="define" name="BOOT_START_ADDR" value="0xE000"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.text=0xE000"/>
+
+ <build type="define" name="AUX_BOOT_SECTION_SIZE" value="0"/>
+
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0xFFA0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0xFFE0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0xFFF8"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
+ </project>
+
+ <project caption="Mass Storage Bootloader - 32KB FLASH / 4KB Boot (2KB AUX) - AVR8 Architecture" id="lufa.bootloaders.mass_storage.avr8.32_4" force-caption="true" workspace-name="lufa_ms_32kb_4kb_">
+ <require idref="lufa.bootloaders.mass_storage"/>
+ <require idref="lufa.boards.dummy.avr8"/>
+ <generator value="as5_8"/>
+
+ <device-support value="atmega32u4"/>
+ <config name="lufa.drivers.board.name" value="none"/>
+
+ <config name="config.compiler.optimization.level" value="size"/>
+
+ <build type="define" name="F_CPU" value="16000000UL"/>
+ <build type="define" name="F_USB" value="16000000UL"/>
+
+ <build type="define" name="BOOT_START_ADDR" value="0x7000"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.text=0x7000"/>
+
+ <build type="define" name="AUX_BOOT_SECTION_SIZE" value="2048"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.boot_aux=0x6810"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.boot_aux_trampoline=0x6800"/>
+ <build type="linker-config" subtype="flags" value="--undefined=Boot_AUX_Trampoline"/>
+
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x7FA0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x7FE0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x7FF8"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
+ </project>
+
+ <project caption="Mass Storage Bootloader - 16KB FLASH / 4KB Boot (2KB AUX) - AVR8 Architecture" id="lufa.bootloaders.mass_storage.avr8.16_4" force-caption="true" workspace-name="lufa_ms_16kb_4kb_">
+ <require idref="lufa.bootloaders.mass_storage"/>
+ <require idref="lufa.boards.dummy.avr8"/>
+ <generator value="as5_8"/>
+
+ <device-support value="atmega16u2"/>
+ <config name="lufa.drivers.board.name" value="none"/>
+
+ <config name="config.compiler.optimization.level" value="size"/>
+
+ <build type="define" name="F_CPU" value="16000000UL"/>
+ <build type="define" name="F_USB" value="16000000UL"/>
+
+ <build type="define" name="BOOT_START_ADDR" value="0x3000"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.text=0x3000"/>
+
+ <build type="define" name="AUX_BOOT_SECTION_SIZE" value="2048"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.boot_aux=0x2810"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.boot_aux_trampoline=0x2800"/>
+ <build type="linker-config" subtype="flags" value="--undefined=Boot_AUX_Trampoline"/>
+
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x3FA0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x3FE0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x3FF8"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
+ </project>
+
+ <module type="application" id="lufa.bootloaders.mass_storage" caption="Mass Storage Bootloader">
+ <info type="description" value="summary">
+ Mass Storage Class Bootloader, capable of reprogramming a device via binary BIN files copied to the virtual FAT12 file-system it creates when plugged into a host.
+ </info>
+
+ <info type="gui-flag" value="move-to-root"/>
+
+ <info type="keyword" value="Technology">
+ <keyword value="Bootloaders"/>
+ <keyword value="USB Device"/>
+ </info>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="include-path" value="."/>
+ <build type="c-source" value="BootloaderMassStorage.c"/>
+ <build type="header-file" value="BootloaderMassStorage.h"/>
+ <build type="c-source" value="Descriptors.c"/>
+ <build type="header-file" value="Descriptors.h"/>
+ <build type="c-source" value="BootloaderAPI.c"/>
+ <build type="header-file" value="BootloaderAPI.h"/>
+ <build type="asm-source" value="BootloaderAPITable.S"/>
+
+ <build type="module-config" subtype="path" value="Config"/>
+ <build type="header-file" value="Config/LUFAConfig.h"/>
+ <build type="header-file" value="Config/AppConfig.h"/>
+
+ <build type="include-path" value="Lib"/>
+ <build type="header-file" value="Lib/VirtualFAT.h"/>
+ <build type="c-source" value="Lib/VirtualFAT.c"/>
+ <build type="header-file" value="Lib/SCSI.h"/>
+ <build type="c-source" value="Lib/SCSI.c"/>
+
+ <build type="distribute" subtype="user-file" value="doxyfile"/>
+ <build type="distribute" subtype="user-file" value="BootloaderMassStorage.txt"/>
+
+ <require idref="lufa.common"/>
+ <require idref="lufa.platform"/>
+ <require idref="lufa.drivers.usb"/>
+ <require idref="lufa.drivers.board"/>
+ <require idref="lufa.drivers.board.leds"/>
+ </module>
+</asf>
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/doxyfile b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/doxyfile
new file mode 100644
index 000000000..9e816908e
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/doxyfile
@@ -0,0 +1,2365 @@
+# Doxyfile 1.8.8
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME = "LUFA Library - Mass Storage Class Bootloader"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
+# the documentation. The maximum height of the logo should not exceed 55 pixels
+# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
+# to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = ./Documentation/
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES = YES
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
+# new page for each member. If set to NO, the documentation of a member will be
+# part of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
+# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
+# Fortran. In the later case the parser tries to guess whether the code is fixed
+# or free formatted code, this is the default for Fortran type files), VHDL. For
+# instance to make doxygen treat .inc files as Fortran files (default is PHP),
+# and .f files as C (default is Fortran), use: inc=Fortran f=C.
+#
+# Note For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT = NO
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by by putting a % sign in front of the word
+# or globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE = YES
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO these classes will be included in the various overviews. This option has
+# no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
+# todo list. This list is created by putting \todo commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST = NO
+
+# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
+# test list. This list is created by putting \test commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST = NO
+
+# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST = NO
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES the list
+# will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET = YES
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO doxygen will only warn about wrong or incomplete parameter
+# documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces.
+# Note: If this tag is empty the current directory is searched.
+
+INPUT = ./
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank the
+# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
+# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
+# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
+# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
+# *.qsf, *.as and *.js.
+
+FILE_PATTERNS = *.h \
+ *.c \
+ *.txt
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE = Documentation/
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS = __* \
+ INCLUDE_FROM_*
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER ) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = NO
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS = NO
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the
+# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
+# cost of reduced performance. This can be particularly helpful with template
+# rich C++ code for which doxygen's built-in parser lacks the necessary type
+# information.
+# Note: The availability of this option depends on whether or not doxygen was
+# compiled with the --with-libclang option.
+# The default value is: NO.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_OPTIONS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefor more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra stylesheet files is of importance (e.g. the last
+# stylesheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the stylesheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP = NO
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS = YES
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated (
+# YES) or that it should be included in the master .chm file ( NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated (
+# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND = YES
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX = YES
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW = YES
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE = 1
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. To get the times font for
+# instance you can specify
+# EXTRA_PACKAGES=times
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empy string,
+# for the replacement values of the other commands the user is refered to
+# HTML_HEADER.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE = plain
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT = docbook
+
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
+# Definitions (see http://autogen.sf.net) file that captures the structure of
+# the code including all documentation. Note that this feature is still
+# experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
+# in the source code. If set to NO only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF = YES
+
+# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED = __DOXYGEN__ \
+ PROGMEM \
+ ATTR_NO_INIT
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
+# class index. If set to NO only the inherited external classes will be listed.
+# The default value is: NO.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
+# the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS = YES
+
+# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS = NO
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME =
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH = NO
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH = NO
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS = NO
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH = NO
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH = NO
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY = NO
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH = NO
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot.
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif and svg.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+PLANTUML_JAR_PATH =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES = 15
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH = 2
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT = YES
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP = YES
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/makefile b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/makefile
new file mode 100644
index 000000000..91bb4038e
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/MassStorage/makefile
@@ -0,0 +1,68 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2014.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+# --------------------------------------
+# LUFA Project Makefile.
+# --------------------------------------
+
+# Run "make help" for target help.
+
+MCU = at90usb1287
+ARCH = AVR8
+BOARD = USBKEY
+F_CPU = 8000000
+F_USB = $(F_CPU)
+OPTIMIZATION = s
+TARGET = BootloaderMassStorage
+SRC = $(TARGET).c Descriptors.c BootloaderAPI.c BootloaderAPITable.S Lib/SCSI.c Lib/VirtualFAT.c $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS)
+LUFA_PATH = ../../LUFA
+CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -IConfig/ -DBOOT_START_ADDR=$(BOOT_START_OFFSET)
+LD_FLAGS = -Wl,--section-start=.text=$(BOOT_START_OFFSET) $(BOOT_API_LD_FLAGS)
+
+# Flash size and bootloader section sizes of the target, in KB. These must
+# match the target's total FLASH size and the bootloader size set in the
+# device's fuses.
+FLASH_SIZE_KB = 128
+BOOT_SECTION_SIZE_KB = 8
+
+# Bootloader address calculation formulas
+# Do not modify these macros, but rather modify the dependent values above.
+CALC_ADDRESS_IN_HEX = $(shell printf "0x%X" $$(( $(1) )) )
+BOOT_START_OFFSET = $(call CALC_ADDRESS_IN_HEX, ($(FLASH_SIZE_KB) - $(BOOT_SECTION_SIZE_KB)) * 1024 )
+BOOT_SEC_OFFSET = $(call CALC_ADDRESS_IN_HEX, ($(FLASH_SIZE_KB) * 1024) - ($(strip $(1))) )
+
+# Bootloader linker section flags for relocating the API table sections to
+# known FLASH addresses - these should not normally be user-edited.
+BOOT_SECTION_LD_FLAG = -Wl,--section-start=$(strip $(1))=$(call BOOT_SEC_OFFSET, $(3)) -Wl,--undefined=$(strip $(2))
+BOOT_API_LD_FLAGS = $(call BOOT_SECTION_LD_FLAG, .apitable_trampolines, BootloaderAPI_Trampolines, 96)
+BOOT_API_LD_FLAGS += $(call BOOT_SECTION_LD_FLAG, .apitable_jumptable, BootloaderAPI_JumpTable, 32)
+BOOT_API_LD_FLAGS += $(call BOOT_SECTION_LD_FLAG, .apitable_signatures, BootloaderAPI_Signatures, 8)
+
+# Check if the bootloader needs an AUX section, located before the real bootloader section to store some of the
+# bootloader code. This is required for 32KB and smaller devices, where the actual bootloader is 6KB but the maximum
+# bootloader section size is 4KB. The actual usable application space will be reduced by 6KB for these devices.
+ifeq ($(BOOT_SECTION_SIZE_KB),8)
+ CC_FLAGS += -DAUX_BOOT_SECTION_SIZE=0
+else
+ AUX_BOOT_SECTION_SIZE_KB = (6 - $(BOOT_SECTION_SIZE_KB))
+
+ CC_FLAGS += -DAUX_BOOT_SECTION_SIZE='($(AUX_BOOT_SECTION_SIZE_KB) * 1024)'
+ LD_FLAGS += -Wl,--section-start=.boot_aux=$(call BOOT_SEC_OFFSET, (($(BOOT_SECTION_SIZE_KB) + $(AUX_BOOT_SECTION_SIZE_KB)) * 1024 - 16))
+ LD_FLAGS += $(call BOOT_SECTION_LD_FLAG, .boot_aux_trampoline, Boot_AUX_Trampoline, ($(BOOT_SECTION_SIZE_KB) + $(AUX_BOOT_SECTION_SIZE_KB)) * 1024)
+endif
+
+# Default target
+all:
+
+# Include LUFA build script makefiles
+include $(LUFA_PATH)/Build/lufa_core.mk
+include $(LUFA_PATH)/Build/lufa_sources.mk
+include $(LUFA_PATH)/Build/lufa_build.mk
+include $(LUFA_PATH)/Build/lufa_cppcheck.mk
+include $(LUFA_PATH)/Build/lufa_doxygen.mk
+include $(LUFA_PATH)/Build/lufa_avrdude.mk
+include $(LUFA_PATH)/Build/lufa_atprogram.mk
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/BootloaderAPI.c b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/BootloaderAPI.c
new file mode 100644
index 000000000..f7564e982
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/BootloaderAPI.c
@@ -0,0 +1,75 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Bootloader user application API functions.
+ */
+
+#include "BootloaderAPI.h"
+
+void BootloaderAPI_ErasePage(const uint32_t Address)
+{
+ boot_page_erase_safe(Address);
+ boot_spm_busy_wait();
+ boot_rww_enable();
+}
+
+void BootloaderAPI_WritePage(const uint32_t Address)
+{
+ boot_page_write_safe(Address);
+ boot_spm_busy_wait();
+ boot_rww_enable();
+}
+
+void BootloaderAPI_FillWord(const uint32_t Address, const uint16_t Word)
+{
+ boot_page_fill_safe(Address, Word);
+}
+
+uint8_t BootloaderAPI_ReadSignature(const uint16_t Address)
+{
+ return boot_signature_byte_get(Address);
+}
+
+uint8_t BootloaderAPI_ReadFuse(const uint16_t Address)
+{
+ return boot_lock_fuse_bits_get(Address);
+}
+
+uint8_t BootloaderAPI_ReadLock(void)
+{
+ return boot_lock_fuse_bits_get(GET_LOCK_BITS);
+}
+
+void BootloaderAPI_WriteLock(const uint8_t LockBits)
+{
+ boot_lock_bits_set_safe(LockBits);
+}
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/BootloaderAPI.h b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/BootloaderAPI.h
new file mode 100644
index 000000000..f44ab06c7
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/BootloaderAPI.h
@@ -0,0 +1,56 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Header file for BootloaderAPI.c.
+ */
+
+#ifndef _BOOTLOADER_API_H_
+#define _BOOTLOADER_API_H_
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <avr/boot.h>
+ #include <stdbool.h>
+
+ #include <LUFA/Common/Common.h>
+
+ /* Function Prototypes: */
+ void BootloaderAPI_ErasePage(const uint32_t Address);
+ void BootloaderAPI_WritePage(const uint32_t Address);
+ void BootloaderAPI_FillWord(const uint32_t Address, const uint16_t Word);
+ uint8_t BootloaderAPI_ReadSignature(const uint16_t Address);
+ uint8_t BootloaderAPI_ReadFuse(const uint16_t Address);
+ uint8_t BootloaderAPI_ReadLock(void);
+ void BootloaderAPI_WriteLock(const uint8_t LockBits);
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/BootloaderAPITable.S b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/BootloaderAPITable.S
new file mode 100644
index 000000000..ec499b74e
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/BootloaderAPITable.S
@@ -0,0 +1,91 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+; Trampolines to actual API implementations if the target address is outside the
+; range of a rjmp instruction (can happen with large bootloader sections)
+.section .apitable_trampolines, "ax"
+.global BootloaderAPI_Trampolines
+BootloaderAPI_Trampolines:
+
+ BootloaderAPI_ErasePage_Trampoline:
+ jmp BootloaderAPI_ErasePage
+ BootloaderAPI_WritePage_Trampoline:
+ jmp BootloaderAPI_WritePage
+ BootloaderAPI_FillWord_Trampoline:
+ jmp BootloaderAPI_FillWord
+ BootloaderAPI_ReadSignature_Trampoline:
+ jmp BootloaderAPI_ReadSignature
+ BootloaderAPI_ReadFuse_Trampoline:
+ jmp BootloaderAPI_ReadFuse
+ BootloaderAPI_ReadLock_Trampoline:
+ jmp BootloaderAPI_ReadLock
+ BootloaderAPI_WriteLock_Trampoline:
+ jmp BootloaderAPI_WriteLock
+ BootloaderAPI_UNUSED1:
+ ret
+ BootloaderAPI_UNUSED2:
+ ret
+ BootloaderAPI_UNUSED3:
+ ret
+ BootloaderAPI_UNUSED4:
+ ret
+ BootloaderAPI_UNUSED5:
+ ret
+
+
+
+; API function jump table
+.section .apitable_jumptable, "ax"
+.global BootloaderAPI_JumpTable
+BootloaderAPI_JumpTable:
+
+ rjmp BootloaderAPI_ErasePage_Trampoline
+ rjmp BootloaderAPI_WritePage_Trampoline
+ rjmp BootloaderAPI_FillWord_Trampoline
+ rjmp BootloaderAPI_ReadSignature_Trampoline
+ rjmp BootloaderAPI_ReadFuse_Trampoline
+ rjmp BootloaderAPI_ReadLock_Trampoline
+ rjmp BootloaderAPI_WriteLock_Trampoline
+ rjmp BootloaderAPI_UNUSED1 ; UNUSED ENTRY 1
+ rjmp BootloaderAPI_UNUSED2 ; UNUSED ENTRY 2
+ rjmp BootloaderAPI_UNUSED3 ; UNUSED ENTRY 3
+ rjmp BootloaderAPI_UNUSED4 ; UNUSED ENTRY 4
+ rjmp BootloaderAPI_UNUSED5 ; UNUSED ENTRY 5
+
+
+
+; Bootloader table signatures and information
+.section .apitable_signatures, "ax"
+.global BootloaderAPI_Signatures
+BootloaderAPI_Signatures:
+
+ .long BOOT_START_ADDR ; Start address of the bootloader
+ .word 0xDF20 ; Signature for the Printer class bootloader
+ .word 0xDCFB ; Signature for a LUFA class bootloader
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/BootloaderPrinter.c b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/BootloaderPrinter.c
new file mode 100644
index 000000000..a19cb0674
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/BootloaderPrinter.c
@@ -0,0 +1,431 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Main source file for the Printer class bootloader. This file contains the complete bootloader logic.
+ */
+
+#include "BootloaderPrinter.h"
+
+/** LUFA Printer Class driver interface configuration and state information. This structure is
+ * passed to all Printer Class driver functions, so that multiple instances of the same class
+ * within a device can be differentiated from one another.
+ */
+USB_ClassInfo_PRNT_Device_t TextOnly_Printer_Interface =
+ {
+ .Config =
+ {
+ .InterfaceNumber = INTERFACE_ID_Printer,
+ .DataINEndpoint =
+ {
+ .Address = PRINTER_IN_EPADDR,
+ .Size = PRINTER_IO_EPSIZE,
+ .Banks = 1,
+ },
+ .DataOUTEndpoint =
+ {
+ .Address = PRINTER_OUT_EPADDR,
+ .Size = PRINTER_IO_EPSIZE,
+ .Banks = 1,
+ },
+ .IEEE1284String =
+ "MFG:Generic;"
+ "MDL:Generic_/_Text_Only;"
+ "CMD:1284.4;"
+ "CLS:PRINTER",
+ },
+ };
+
+/** Intel HEX parser state machine state information, to track the contents of
+ * a HEX file streamed in as a sequence of arbitrary bytes.
+ */
+struct
+{
+ /** Current HEX parser state machine state. */
+ uint8_t ParserState;
+ /** Previously decoded numerical byte of data. */
+ uint8_t PrevData;
+ /** Currently decoded numerical byte of data. */
+ uint8_t Data;
+ /** Indicates if both bytes that correspond to a single decoded numerical
+ * byte of data (HEX encodes values in ASCII HEX, two characters per byte)
+ * have been read.
+ */
+ bool ReadMSB;
+ /** Intel HEX record type of the current Intel HEX record. */
+ uint8_t RecordType;
+ /** Numerical bytes of data remaining to be read in the current record. */
+ uint8_t DataRem;
+ /** Checksum of the current record received so far. */
+ uint8_t Checksum;
+ /** Starting address of the last addressed FLASH page. */
+ uint32_t PageStartAddress;
+ /** Current 32-bit byte extended base address in FLASH being targeted. */
+ uint32_t CurrBaseAddress;
+ /** Current 32-bit byte address in FLASH being targeted. */
+ uint32_t CurrAddress;
+} HEXParser;
+
+/** Indicates if there is data waiting to be written to a physical page of
+ * memory in FLASH.
+ */
+static bool PageDirty = false;
+
+/** Flag to indicate if the bootloader should be running, or should exit and allow the application code to run
+ * via a soft reset. When cleared, the bootloader will abort, the USB interface will shut down and the application
+ * started via a forced watchdog reset.
+ */
+static bool RunBootloader = true;
+
+/** Magic lock for forced application start. If the HWBE fuse is programmed and BOOTRST is unprogrammed, the bootloader
+ * will start if the /HWB line of the AVR is held low and the system is reset. However, if the /HWB line is still held
+ * low when the application attempts to start via a watchdog reset, the bootloader will re-start. If set to the value
+ * \ref MAGIC_BOOT_KEY the special init function \ref Application_Jump_Check() will force the application to start.
+ */
+uint16_t MagicBootKey ATTR_NO_INIT;
+
+
+/** Special startup routine to check if the bootloader was started via a watchdog reset, and if the magic application
+ * start key has been loaded into \ref MagicBootKey. If the bootloader started via the watchdog and the key is valid,
+ * this will force the user application to start via a software jump.
+ */
+void Application_Jump_Check(void)
+{
+ /* If the reset source was the bootloader and the key is correct, clear it and jump to the application */
+ if ((MCUSR & (1 << WDRF)) && (MagicBootKey == MAGIC_BOOT_KEY))
+ {
+ MagicBootKey = 0;
+
+ // cppcheck-suppress constStatement
+ ((void (*)(void))0x0000)();
+ }
+}
+
+/**
+ * Converts a given input byte of data from an ASCII encoded HEX value to an integer value.
+ *
+ * \note Input HEX bytes are expected to be in uppercase only.
+ *
+ * \param[in] Byte ASCII byte of data to convert
+ *
+ * \return Integer converted value of the input ASCII encoded HEX byte of data, or -1 if the
+ * input is not valid ASCII encoded HEX.
+ */
+static int8_t HexToDecimal(const char Byte)
+{
+ if ((Byte >= 'A') && (Byte <= 'F'))
+ return (10 + (Byte - 'A'));
+ else if ((Byte >= '0') && (Byte <= '9'))
+ return (Byte - '0');
+
+ return -1;
+}
+
+/**
+ * Flushes a partially written page of data to physical FLASH, if a page
+ * boundary has been crossed.
+ *
+ * \note If a page flush occurs the global HEX parser state is updated.
+ */
+static void FlushPageIfRequired(void)
+{
+ /* Abort if no data has been buffered for writing to the current page */
+ if (!PageDirty)
+ return;
+
+ /* Flush the FLASH page to physical memory if we are crossing a page boundary */
+ uint32_t NewPageStartAddress = (HEXParser.CurrAddress & ~(SPM_PAGESIZE - 1));
+ if (HEXParser.PageStartAddress != NewPageStartAddress)
+ {
+ boot_page_write(HEXParser.PageStartAddress);
+ boot_spm_busy_wait();
+
+ HEXParser.PageStartAddress = NewPageStartAddress;
+
+ PageDirty = false;
+ }
+}
+
+/**
+ * Parses an input Intel HEX formatted stream one character at a time, loading
+ * the data contents into the device's internal FLASH memory.
+ *
+ * \param[in] ReadCharacter Next input ASCII byte of data to parse
+ */
+static void ParseIntelHEXByte(const char ReadCharacter)
+{
+ /* Reset the line parser while waiting for a new line to start */
+ if ((HEXParser.ParserState == HEX_PARSE_STATE_WAIT_LINE) || (ReadCharacter == ':'))
+ {
+ HEXParser.Checksum = 0;
+ HEXParser.CurrAddress = HEXParser.CurrBaseAddress;
+ HEXParser.ReadMSB = false;
+
+ /* ASCII ':' indicates the start of a new HEX record */
+ if (ReadCharacter == ':')
+ HEXParser.ParserState = HEX_PARSE_STATE_BYTE_COUNT;
+
+ return;
+ }
+
+ /* Only allow ASCII HEX encoded digits, ignore all other characters */
+ int8_t ReadCharacterDec = HexToDecimal(ReadCharacter);
+ if (ReadCharacterDec < 0)
+ return;
+
+ /* Read and convert the next nibble of data from the current character */
+ HEXParser.Data = (HEXParser.Data << 4) | ReadCharacterDec;
+ HEXParser.ReadMSB = !HEXParser.ReadMSB;
+
+ /* Only process further when a full byte (two nibbles) have been read */
+ if (HEXParser.ReadMSB)
+ return;
+
+ /* Intel HEX checksum is for all fields except starting character and the
+ * checksum itself
+ */
+ if (HEXParser.ParserState != HEX_PARSE_STATE_CHECKSUM)
+ HEXParser.Checksum += HEXParser.Data;
+
+ switch (HEXParser.ParserState)
+ {
+ case HEX_PARSE_STATE_BYTE_COUNT:
+ HEXParser.DataRem = HEXParser.Data;
+ HEXParser.ParserState = HEX_PARSE_STATE_ADDRESS_HIGH;
+ break;
+
+ case HEX_PARSE_STATE_ADDRESS_HIGH:
+ HEXParser.CurrAddress += ((uint16_t)HEXParser.Data << 8);
+ HEXParser.ParserState = HEX_PARSE_STATE_ADDRESS_LOW;
+ break;
+
+ case HEX_PARSE_STATE_ADDRESS_LOW:
+ HEXParser.CurrAddress += HEXParser.Data;
+ HEXParser.ParserState = HEX_PARSE_STATE_RECORD_TYPE;
+ break;
+
+ case HEX_PARSE_STATE_RECORD_TYPE:
+ HEXParser.RecordType = HEXParser.Data;
+ HEXParser.ParserState = (HEXParser.DataRem ? HEX_PARSE_STATE_READ_DATA : HEX_PARSE_STATE_CHECKSUM);
+ break;
+
+ case HEX_PARSE_STATE_READ_DATA:
+ /* Track the number of read data bytes in the record */
+ HEXParser.DataRem--;
+
+ /* Protect the bootloader against being written to */
+ if (HEXParser.CurrAddress >= BOOT_START_ADDR)
+ {
+ HEXParser.ParserState = HEX_PARSE_STATE_WAIT_LINE;
+ PageDirty = false;
+ return;
+ }
+
+ /* Wait for a machine word (two bytes) of data to be read */
+ if (HEXParser.DataRem & 0x01)
+ {
+ HEXParser.PrevData = HEXParser.Data;
+ break;
+ }
+
+ /* Convert the last two received data bytes into a 16-bit word */
+ uint16_t NewDataWord = ((uint16_t)HEXParser.Data << 8) | HEXParser.PrevData;
+
+ switch (HEXParser.RecordType)
+ {
+ case HEX_RECORD_TYPE_Data:
+ /* If we are writing to a new page, we need to erase it first */
+ if (!(PageDirty))
+ {
+ boot_page_erase(HEXParser.PageStartAddress);
+ boot_spm_busy_wait();
+
+ PageDirty = true;
+ }
+
+ /* Fill the FLASH memory buffer with the new word of data */
+ boot_page_fill(HEXParser.CurrAddress, NewDataWord);
+ HEXParser.CurrAddress += 2;
+
+ /* Flush the FLASH page to physical memory if we are crossing a page boundary */
+ FlushPageIfRequired();
+ break;
+
+ case HEX_RECORD_TYPE_ExtendedSegmentAddress:
+ /* Extended address data - store the upper 12-bits of the new address */
+ HEXParser.CurrBaseAddress = ((uint32_t)NewDataWord << 4);
+ break;
+
+ case HEX_RECORD_TYPE_ExtendedLinearAddress:
+ /* Extended address data - store the upper 16-bits of the new address */
+ HEXParser.CurrBaseAddress = ((uint32_t)NewDataWord << 16);
+ break;
+ }
+
+ if (!HEXParser.DataRem)
+ HEXParser.ParserState = HEX_PARSE_STATE_CHECKSUM;
+ break;
+
+ case HEX_PARSE_STATE_CHECKSUM:
+ /* Verify checksum of the completed record */
+ if (HEXParser.Data != ((~HEXParser.Checksum + 1) & 0xFF))
+ break;
+
+ /* Flush the FLASH page to physical memory if we are crossing a page boundary */
+ FlushPageIfRequired();
+
+ /* If end of the HEX file reached, the bootloader should exit at next opportunity */
+ if (HEXParser.RecordType == HEX_RECORD_TYPE_EndOfFile)
+ RunBootloader = false;
+
+ break;
+
+ default:
+ HEXParser.ParserState = HEX_PARSE_STATE_WAIT_LINE;
+ break;
+ }
+}
+
+/** Main program entry point. This routine configures the hardware required by the application, then
+ * enters a loop to run the application tasks in sequence.
+ */
+int main(void)
+{
+ SetupHardware();
+
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
+ GlobalInterruptEnable();
+
+ while (RunBootloader)
+ {
+ uint8_t BytesReceived = PRNT_Device_BytesReceived(&TextOnly_Printer_Interface);
+
+ if (BytesReceived)
+ {
+ LEDs_SetAllLEDs(LEDMASK_USB_BUSY);
+
+ while (BytesReceived--)
+ {
+ int16_t ReceivedByte = PRNT_Device_ReceiveByte(&TextOnly_Printer_Interface);
+
+ /* Feed the next byte of data to the HEX parser */
+ ParseIntelHEXByte(ReceivedByte);
+ }
+
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);
+ }
+
+ PRNT_Device_USBTask(&TextOnly_Printer_Interface);
+ USB_USBTask();
+ }
+
+ /* Disconnect from the host - USB interface will be reset later along with the AVR */
+ USB_Detach();
+
+ /* Unlock the forced application start mode of the bootloader if it is restarted */
+ MagicBootKey = MAGIC_BOOT_KEY;
+
+ /* Enable the watchdog and force a timeout to reset the AVR */
+ wdt_enable(WDTO_250MS);
+
+ for (;;);
+}
+
+/** Configures the board hardware and chip peripherals for the demo's functionality. */
+static void SetupHardware(void)
+{
+ /* Disable watchdog if enabled by bootloader/fuses */
+ MCUSR &= ~(1 << WDRF);
+ wdt_disable();
+
+ /* Disable clock division */
+ clock_prescale_set(clock_div_1);
+
+ /* Relocate the interrupt vector table to the bootloader section */
+ MCUCR = (1 << IVCE);
+ MCUCR = (1 << IVSEL);
+
+ /* Hardware Initialization */
+ LEDs_Init();
+ USB_Init();
+
+ /* Bootloader active LED toggle timer initialization */
+ TIMSK1 = (1 << TOIE1);
+ TCCR1B = ((1 << CS11) | (1 << CS10));
+}
+
+/** ISR to periodically toggle the LEDs on the board to indicate that the bootloader is active. */
+ISR(TIMER1_OVF_vect, ISR_BLOCK)
+{
+ LEDs_ToggleLEDs(LEDS_LED1 | LEDS_LED2);
+}
+
+/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs. */
+void EVENT_USB_Device_Connect(void)
+{
+ /* Indicate USB enumerating */
+ LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
+}
+
+/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
+ * the status LEDs and stops the Printer management task.
+ */
+void EVENT_USB_Device_Disconnect(void)
+{
+ /* Indicate USB not ready */
+ LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
+}
+
+/** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration
+ * of the USB device after enumeration - the device endpoints are configured and the Mass Storage management task started.
+ */
+void EVENT_USB_Device_ConfigurationChanged(void)
+{
+ bool ConfigSuccess = true;
+
+ /* Setup Printer Data Endpoints */
+ ConfigSuccess &= PRNT_Device_ConfigureEndpoints(&TextOnly_Printer_Interface);
+
+ /* Reset the HEX parser upon successful connection to a host */
+ HEXParser.ParserState = HEX_PARSE_STATE_WAIT_LINE;
+
+ /* Indicate endpoint configuration success or failure */
+ LEDs_SetAllLEDs(ConfigSuccess ? LEDMASK_USB_READY : LEDMASK_USB_ERROR);
+}
+
+/** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent to
+ * the device from the USB host before passing along unhandled control requests to the library for processing
+ * internally.
+ */
+void EVENT_USB_Device_ControlRequest(void)
+{
+ PRNT_Device_ProcessControlRequest(&TextOnly_Printer_Interface);
+}
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/BootloaderPrinter.h b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/BootloaderPrinter.h
new file mode 100644
index 000000000..d5cec1914
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/BootloaderPrinter.h
@@ -0,0 +1,108 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Header file for BootloaderPrinter.c.
+ */
+
+#ifndef _BOOTLOADER_PRINTER_H_
+#define _BOOTLOADER_PRINTER_H_
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <avr/wdt.h>
+ #include <avr/power.h>
+ #include <avr/interrupt.h>
+
+ #include "Descriptors.h"
+
+ #include <LUFA/Drivers/Board/LEDs.h>
+ #include <LUFA/Drivers/USB/USB.h>
+ #include <LUFA/Platform/Platform.h>
+
+ /* Preprocessor Checks: */
+ #if !defined(__OPTIMIZE_SIZE__)
+ #error This bootloader requires that it be optimized for size, not speed, to fit into the target device. Change optimization settings and try again.
+ #endif
+
+ /* Macros: */
+ /** LED mask for the library LED driver, to indicate that the USB interface is not ready. */
+ #define LEDMASK_USB_NOTREADY LEDS_LED1
+
+ /** LED mask for the library LED driver, to indicate that the USB interface is enumerating. */
+ #define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3)
+
+ /** LED mask for the library LED driver, to indicate that the USB interface is ready. */
+ #define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4)
+
+ /** LED mask for the library LED driver, to indicate that an error has occurred in the USB interface. */
+ #define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3)
+
+ /** LED mask for the library LED driver, to indicate that the USB interface is busy. */
+ #define LEDMASK_USB_BUSY LEDS_LED2
+
+ /** Magic bootloader key to unlock forced application start mode. */
+ #define MAGIC_BOOT_KEY 0xDC42
+
+ /* Enums: */
+ /** Intel HEX parser state machine states. */
+ enum HEX_Parser_States_t
+ {
+ HEX_PARSE_STATE_WAIT_LINE, /**< Parser is waiting for a HEX Start of Line character. */
+ HEX_PARSE_STATE_BYTE_COUNT, /**< Parser is waiting for a record byte count. */
+ HEX_PARSE_STATE_ADDRESS_HIGH, /**< Parser is waiting for the MSB of a record address. */
+ HEX_PARSE_STATE_ADDRESS_LOW, /**< Parser is waiting for the LSB of a record address. */
+ HEX_PARSE_STATE_RECORD_TYPE, /**< Parser is waiting for the record type. */
+ HEX_PARSE_STATE_READ_DATA, /**< Parser is waiting for more data in the current record. */
+ HEX_PARSE_STATE_CHECKSUM, /**< Parser is waiting for the checksum of the current record. */
+ };
+
+ /** Intel HEX record types, used to indicate the type of record contained in a line of a HEX file. */
+ enum HEX_Record_Types_t
+ {
+ HEX_RECORD_TYPE_Data = 0, /**< Record contains loadable data. */
+ HEX_RECORD_TYPE_EndOfFile = 1, /**< End of file record. */
+ HEX_RECORD_TYPE_ExtendedSegmentAddress = 2, /**< Extended segment start record. */
+ HEX_RECORD_TYPE_StartSegmentAddress = 3, /**< Normal segment start record. */
+ HEX_RECORD_TYPE_ExtendedLinearAddress = 4, /**< Extended linear address start record. */
+ HEX_RECORD_TYPE_StartLinearAddress = 5, /**< Linear address start record. */
+ };
+
+ /* Function Prototypes: */
+ static void SetupHardware(void);
+
+ void EVENT_USB_Device_Connect(void);
+ void EVENT_USB_Device_Disconnect(void);
+ void EVENT_USB_Device_ConfigurationChanged(void);
+ void EVENT_USB_Device_ControlRequest(void);
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/BootloaderPrinter.txt b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/BootloaderPrinter.txt
new file mode 100644
index 000000000..cfa51d4cf
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/BootloaderPrinter.txt
@@ -0,0 +1,190 @@
+/** \file
+ *
+ * This file contains special DoxyGen information for the generation of the main page and other special
+ * documentation pages. It is not a project source file.
+ */
+
+/** \mainpage Printer Class USB AVR Bootloader
+ *
+ * \section Sec_Compat Demo Compatibility:
+ *
+ * The following list indicates what microcontrollers are compatible with this demo.
+ *
+ * \li Series 7 USB AVRs (AT90USBxxx7)
+ * \li Series 6 USB AVRs (AT90USBxxx6)
+ * \li Series 4 USB AVRs (ATMEGAxxU4)
+ * \li Series 2 USB AVRs (AT90USBxx2, ATMEGAxxU2)
+ *
+ * \section Sec_Info USB Information:
+ *
+ * The following table gives a rundown of the USB utilization of this demo.
+ *
+ * <table>
+ * <tr>
+ * <td><b>USB Mode:</b></td>
+ * <td>Device</td>
+ * </tr>
+ * <tr>
+ * <td><b>USB Class:</b></td>
+ * <td>Printer Class</td>
+ * </tr>
+ * <tr>
+ * <td><b>USB Subclass:</b></td>
+ * <td>Printer Subclass</td>
+ * </tr>
+ * <tr>
+ * <td><b>Relevant Standards:</b></td>
+ * <td>USBIF Printer Class Standard</td>
+ * </tr>
+ * <tr>
+ * <td><b>Supported USB Speeds:</b></td>
+ * <td>Full Speed Mode</td>
+ * </tr>
+ * </table>
+ *
+ * \section Sec_Description Project Description:
+ *
+ * This bootloader enumerates to the host as a Generic Text Only Printer device, capable of reading and parsing
+ * "printed" plain-text Intel HEX files to load firmware onto the AVR.
+ *
+ * Out of the box this bootloader builds for the AT90USB1287 with an 8KB bootloader section size, and will fit
+ * into 4KB of bootloader space. If you wish to alter this size and/or change the AVR model, you will need to
+ * edit the MCU, FLASH_SIZE_KB and BOOT_SECTION_SIZE_KB values in the accompanying makefile.
+ *
+ * When the bootloader is running, the board's LED(s) will flash at regular intervals to distinguish the
+ * bootloader from the normal user application.
+ *
+ * \section Sec_Running Running the Bootloader
+ *
+ * This bootloader is designed to be started via the HWB mechanism of the USB AVRs; ground the HWB pin (see device
+ * datasheet) then momentarily ground /RESET to start the bootloader. This assumes the HWBE fuse is set and the BOOTRST
+ * fuse is cleared.
+ *
+ * \section Sec_Installation Driver Installation
+ *
+ * This bootloader uses the Generic Text-Only printer drivers inbuilt into all modern operating systems, thus no
+ * additional drivers need to be supplied for correct operation.
+ *
+ * \section Sec_HostApp Host Controller Application
+ *
+ * This bootloader is compatible with Notepad under Windows, and the command line \c lpr utility under Linux.
+ *
+ * \subsection SSec_Notepad Notepad (Windows)
+ *
+ * While most text applications under Windows will be compatible with the bootloader, the inbuilt Notepad utility
+ * is recommended as it will introduce minimal formatting changes to the output stream. To program with Notepad,
+ * open the target HEX file and print it to the Generic Text Only printer device the bootloader creates.
+ *
+ * \subsection SSec_LPR LPR (Linux)
+ *
+ * While the CUPS framework under Linux will enumerate the bootloader as a Generic Text-Only printer, many
+ * applications will refuse to print to the device due to the lack of rich formatting options available. As a result,
+ * under Linux HEX files must be printed via the low level \c lpr utility instead.
+ *
+ * \code
+ * cat Mouse.hex | lpr
+ * \endcode
+ *
+ * \section Sec_API User Application API
+ *
+ * Several user application functions for FLASH and other special memory area manipulations are exposed by the bootloader,
+ * allowing the user application to call into the bootloader at runtime to read and write FLASH data.
+ *
+ * By default, the bootloader API jump table is located 32 bytes from the end of the device's FLASH memory, and follows the
+ * following layout:
+ *
+ * \code
+ * #define BOOTLOADER_API_TABLE_SIZE 32
+ * #define BOOTLOADER_API_TABLE_START ((FLASHEND + 1UL) - BOOTLOADER_API_TABLE_SIZE)
+ * #define BOOTLOADER_API_CALL(Index) (void*)((BOOTLOADER_API_TABLE_START + (Index * 2)) / 2)
+ *
+ * void (*BootloaderAPI_ErasePage)(uint32_t Address) = BOOTLOADER_API_CALL(0);
+ * void (*BootloaderAPI_WritePage)(uint32_t Address) = BOOTLOADER_API_CALL(1);
+ * void (*BootloaderAPI_FillWord)(uint32_t Address, uint16_t Word) = BOOTLOADER_API_CALL(2);
+ * uint8_t (*BootloaderAPI_ReadSignature)(uint16_t Address) = BOOTLOADER_API_CALL(3);
+ * uint8_t (*BootloaderAPI_ReadFuse)(uint16_t Address) = BOOTLOADER_API_CALL(4);
+ * uint8_t (*BootloaderAPI_ReadLock)(void) = BOOTLOADER_API_CALL(5);
+ * void (*BootloaderAPI_WriteLock)(uint8_t LockBits) = BOOTLOADER_API_CALL(6);
+ *
+ * #define BOOTLOADER_MAGIC_SIGNATURE_START (BOOTLOADER_API_TABLE_START + (BOOTLOADER_API_TABLE_SIZE - 2))
+ * #define BOOTLOADER_MAGIC_SIGNATURE 0xDCFB
+ *
+ * #define BOOTLOADER_CLASS_SIGNATURE_START (BOOTLOADER_API_TABLE_START + (BOOTLOADER_API_TABLE_SIZE - 4))
+ * #define BOOTLOADER_PRINTER_SIGNATURE 0xDF20
+ *
+ * #define BOOTLOADER_ADDRESS_START (BOOTLOADER_API_TABLE_START + (BOOTLOADER_API_TABLE_SIZE - 8))
+ * #define BOOTLOADER_ADDRESS_LENGTH 4
+ * \endcode
+ *
+ * From the application the API support of the bootloader can be detected by reading the FLASH memory bytes located at address
+ * \c BOOTLOADER_MAGIC_SIGNATURE_START and comparing them to the value \c BOOTLOADER_MAGIC_SIGNATURE. The class of bootloader
+ * can be determined by reading the FLASH memory bytes located at address \c BOOTLOADER_CLASS_SIGNATURE_START and comparing them
+ * to the value \c BOOTLOADER_PRINTER_SIGNATURE. The start address of the bootloader can be retrieved by reading the bytes of FLASH
+ * memory starting from address \c BOOTLOADER_ADDRESS_START.
+ *
+ * \subsection SSec_API_MemLayout Device Memory Map
+ * The following illustration indicates the final memory map of the device when loaded with the bootloader.
+ *
+ * \verbatim
+ * +----------------------------+ 0x0000
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | User Application |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * +----------------------------+ FLASHEND - BOOT_SECTION_SIZE
+ * | |
+ * | Bootloader Application |
+ * | (Not User App. Accessible) |
+ * | |
+ * +----------------------------+ FLASHEND - 96
+ * | API Table Trampolines |
+ * | (Not User App. Accessible) |
+ * +----------------------------+ FLASHEND - 32
+ * | Bootloader API Table |
+ * | (User App. Accessible) |
+ * +----------------------------+ FLASHEND - 8
+ * | Bootloader ID Constants |
+ * | (User App. Accessible) |
+ * +----------------------------+ FLASHEND
+ * \endverbatim
+ *
+ *
+ * \section Sec_KnownIssues Known Issues:
+ *
+ * \par On Linux machines, new firmware fails to be sent to the device via CUPS.
+ * Only a limited subset of normal printer functionality is exposed via the
+ * bootloader, causing CUPS to reject print requests from applications that
+ * are unable to handle true plain-text printing. For best results, the low
+ * level \c lpr command should be used to print new firmware to the bootloader.
+ *
+ * \par After loading an application, it is not run automatically on startup.
+ * Some USB AVR boards ship with the BOOTRST fuse set, causing the bootloader
+ * to run automatically when the device is reset. In most cases, the BOOTRST
+ * fuse should be disabled and the HWBE fuse used instead to run the bootloader
+ * when needed.
+ *
+ * \section Sec_Options Project Options
+ *
+ * The following defines can be found in this demo, which can control the demo behaviour when defined, or changed in value.
+ *
+ * <table>
+ * <tr>
+ * <td>
+ * None
+ * </td>
+ * </tr>
+ * </table>
+ */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/Config/LUFAConfig.h b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/Config/LUFAConfig.h
new file mode 100644
index 000000000..af2dd3060
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/Config/LUFAConfig.h
@@ -0,0 +1,93 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief LUFA Library Configuration Header File
+ *
+ * This header file is used to configure LUFA's compile time options,
+ * as an alternative to the compile time constants supplied through
+ * a makefile.
+ *
+ * For information on what each token does, refer to the LUFA
+ * manual section "Summary of Compile Tokens".
+ */
+
+#ifndef _LUFA_CONFIG_H_
+#define _LUFA_CONFIG_H_
+
+ #if (ARCH == ARCH_AVR8)
+
+ /* Non-USB Related Configuration Tokens: */
+// #define DISABLE_TERMINAL_CODES
+
+ /* USB Class Driver Related Tokens: */
+// #define HID_HOST_BOOT_PROTOCOL_ONLY
+// #define HID_STATETABLE_STACK_DEPTH {Insert Value Here}
+// #define HID_USAGE_STACK_DEPTH {Insert Value Here}
+// #define HID_MAX_COLLECTIONS {Insert Value Here}
+// #define HID_MAX_REPORTITEMS {Insert Value Here}
+// #define HID_MAX_REPORT_IDS {Insert Value Here}
+// #define NO_CLASS_DRIVER_AUTOFLUSH
+
+ /* General USB Driver Related Tokens: */
+ #define ORDERED_EP_CONFIG
+ #define USE_STATIC_OPTIONS (USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)
+ #define USB_DEVICE_ONLY
+// #define USB_HOST_ONLY
+// #define USB_STREAM_TIMEOUT_MS {Insert Value Here}
+// #define NO_LIMITED_CONTROLLER_CONNECT
+ #define NO_SOF_EVENTS
+
+ /* USB Device Mode Driver Related Tokens: */
+ #define USE_RAM_DESCRIPTORS
+// #define USE_FLASH_DESCRIPTORS
+// #define USE_EEPROM_DESCRIPTORS
+ #define NO_INTERNAL_SERIAL
+ #define FIXED_CONTROL_ENDPOINT_SIZE 8
+ #define DEVICE_STATE_AS_GPIOR 0
+ #define FIXED_NUM_CONFIGURATIONS 1
+// #define CONTROL_ONLY_DEVICE
+// #define INTERRUPT_CONTROL_ENDPOINT
+ #define NO_DEVICE_REMOTE_WAKEUP
+ #define NO_DEVICE_SELF_POWER
+
+ /* USB Host Mode Driver Related Tokens: */
+// #define HOST_STATE_AS_GPIOR {Insert Value Here}
+// #define USB_HOST_TIMEOUT_MS {Insert Value Here}
+// #define HOST_DEVICE_SETTLE_DELAY_MS {Insert Value Here}
+// #define NO_AUTO_VBUS_MANAGEMENT
+// #define INVERTED_VBUS_ENABLE_LINE
+
+ #else
+
+ #error Unsupported architecture for this LUFA configuration file.
+
+ #endif
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/Descriptors.c b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/Descriptors.c
new file mode 100644
index 000000000..187f7733d
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/Descriptors.c
@@ -0,0 +1,194 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * USB Device Descriptors, for library use when in USB device mode. Descriptors are special
+ * computer-readable structures which the host requests upon device enumeration, to determine
+ * the device's capabilities and functions.
+ */
+
+#include "Descriptors.h"
+
+
+/** Device descriptor structure. This descriptor, located in SRAM memory, describes the overall
+ * device characteristics, including the supported USB version, control endpoint size and the
+ * number of device configurations. The descriptor is read out by the USB host when the enumeration
+ * process begins.
+ */
+const USB_Descriptor_Device_t DeviceDescriptor =
+{
+ .Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
+
+ .USBSpecification = VERSION_BCD(1,1,0),
+ .Class = USB_CSCP_NoDeviceClass,
+ .SubClass = USB_CSCP_NoDeviceSubclass,
+ .Protocol = USB_CSCP_NoDeviceProtocol,
+
+ .Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
+
+ .VendorID = 0x03EB,
+ .ProductID = 0x206B,
+ .ReleaseNumber = VERSION_BCD(0,0,1),
+
+ .ManufacturerStrIndex = STRING_ID_Manufacturer,
+ .ProductStrIndex = STRING_ID_Product,
+ .SerialNumStrIndex = NO_DESCRIPTOR,
+
+ .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
+};
+
+/** Configuration descriptor structure. This descriptor, located in SRAM memory, describes the usage
+ * of the device in one of its supported configurations, including information about any device interfaces
+ * and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting
+ * a configuration so that the host may correctly communicate with the USB device.
+ */
+const USB_Descriptor_Configuration_t ConfigurationDescriptor =
+{
+ .Config =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration},
+
+ .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
+ .TotalInterfaces = 1,
+
+ .ConfigurationNumber = 1,
+ .ConfigurationStrIndex = NO_DESCRIPTOR,
+
+ .ConfigAttributes = USB_CONFIG_ATTR_RESERVED,
+
+ .MaxPowerConsumption = USB_CONFIG_POWER_MA(100)
+ },
+
+ .Printer_Interface =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
+
+ .InterfaceNumber = INTERFACE_ID_Printer,
+ .AlternateSetting = 0,
+
+ .TotalEndpoints = 2,
+
+ .Class = PRNT_CSCP_PrinterClass,
+ .SubClass = PRNT_CSCP_PrinterSubclass,
+ .Protocol = PRNT_CSCP_BidirectionalProtocol,
+
+ .InterfaceStrIndex = NO_DESCRIPTOR
+ },
+
+ .Printer_DataInEndpoint =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
+
+ .EndpointAddress = PRINTER_IN_EPADDR,
+ .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
+ .EndpointSize = PRINTER_IO_EPSIZE,
+ .PollingIntervalMS = 0x05
+ },
+
+ .Printer_DataOutEndpoint =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
+
+ .EndpointAddress = PRINTER_OUT_EPADDR,
+ .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
+ .EndpointSize = PRINTER_IO_EPSIZE,
+ .PollingIntervalMS = 0x05
+ }
+};
+
+/** Language descriptor structure. This descriptor, located in SRAM memory, is returned when the host requests
+ * the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which indicate
+ * via the language ID table available at USB.org what languages the device supports for its string descriptors.
+ */
+const USB_Descriptor_String_t LanguageString = USB_STRING_DESCRIPTOR_ARRAY(LANGUAGE_ID_ENG);
+
+/** Manufacturer descriptor string. This is a Unicode string containing the manufacturer's details in human readable
+ * form, and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
+ * Descriptor.
+ */
+const USB_Descriptor_String_t ManufacturerString = USB_STRING_DESCRIPTOR(L"Dean Camera");
+
+/** Product descriptor string. This is a Unicode string containing the product's details in human readable form,
+ * and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
+ * Descriptor.
+ */
+const USB_Descriptor_String_t ProductString = USB_STRING_DESCRIPTOR(L"LUFA Printer Bootloader");
+
+/** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
+ * documentation) by the application code so that the address and size of a requested descriptor can be given
+ * to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function
+ * is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the
+ * USB host.
+ */
+uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+ const uint8_t wIndex,
+ const void** const DescriptorAddress)
+{
+ const uint8_t DescriptorType = (wValue >> 8);
+ const uint8_t DescriptorNumber = (wValue & 0xFF);
+
+ const void* Address = NULL;
+ uint16_t Size = NO_DESCRIPTOR;
+
+ switch (DescriptorType)
+ {
+ case DTYPE_Device:
+ Address = &DeviceDescriptor;
+ Size = sizeof(USB_Descriptor_Device_t);
+ break;
+ case DTYPE_Configuration:
+ Address = &ConfigurationDescriptor;
+ Size = sizeof(USB_Descriptor_Configuration_t);
+ break;
+ case DTYPE_String:
+ switch (DescriptorNumber)
+ {
+ case STRING_ID_Language:
+ Address = &LanguageString;
+ Size = LanguageString.Header.Size;
+ break;
+ case STRING_ID_Manufacturer:
+ Address = &ManufacturerString;
+ Size = ManufacturerString.Header.Size;
+ break;
+ case STRING_ID_Product:
+ Address = &ProductString;
+ Size = ProductString.Header.Size;
+ break;
+ }
+
+ break;
+ }
+
+ *DescriptorAddress = Address;
+ return Size;
+}
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/Descriptors.h b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/Descriptors.h
new file mode 100644
index 000000000..144ca0660
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/Descriptors.h
@@ -0,0 +1,96 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Header file for Descriptors.c.
+ */
+
+#ifndef _DESCRIPTORS_H_
+#define _DESCRIPTORS_H_
+
+ /* Includes: */
+ #include <LUFA/Drivers/USB/USB.h>
+
+ #include <avr/pgmspace.h>
+
+ /* Macros: */
+ /** Endpoint address of the Printer device-to-host data IN endpoint. */
+ #define PRINTER_IN_EPADDR (ENDPOINT_DIR_IN | 3)
+
+ /** Endpoint address of the Printer host-to-device data OUT endpoint. */
+ #define PRINTER_OUT_EPADDR (ENDPOINT_DIR_OUT | 4)
+
+ /** Size in bytes of the Printer data endpoints. */
+ #define PRINTER_IO_EPSIZE 64
+
+ /* Type Defines: */
+ /** Type define for the device configuration descriptor structure. This must be defined in the
+ * application code, as the configuration descriptor contains several sub-descriptors which
+ * vary between devices, and which describe the device's usage to the host.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Configuration_Header_t Config;
+
+ // Printer Interface
+ USB_Descriptor_Interface_t Printer_Interface;
+ USB_Descriptor_Endpoint_t Printer_DataInEndpoint;
+ USB_Descriptor_Endpoint_t Printer_DataOutEndpoint;
+ } USB_Descriptor_Configuration_t;
+
+ /** Enum for the device interface descriptor IDs within the device. Each string descriptor
+ * should have a unique ID index associated with it, which can be used to refer to the
+ * interface from other descriptors.
+ */
+ enum InterfaceDescriptors_t
+ {
+ INTERFACE_ID_Printer = 0, /**< Printer interface descriptor ID */
+ };
+
+ /** Enum for the device string descriptor IDs within the device. Each string descriptor should
+ * have a unique ID index associated with it, which can be used to refer to the string from
+ * other descriptors.
+ */
+ enum StringDescriptors_t
+ {
+ STRING_ID_Language = 0, /**< Supported Languages string descriptor ID (must be zero) */
+ STRING_ID_Manufacturer = 1, /**< Manufacturer string ID */
+ STRING_ID_Product = 2, /**< Product string ID */
+ };
+
+ /* Function Prototypes: */
+ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+ const uint8_t wIndex,
+ const void** const DescriptorAddress)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/asf.xml b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/asf.xml
new file mode 100644
index 000000000..86a56911e
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/asf.xml
@@ -0,0 +1,159 @@
+<asf xmlversion="1.0">
+ <project caption="Printer Bootloader - 128KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.printer.avr8.128_4" force-caption="true" workspace-name="lufa_printer_128kb_4kb_">
+ <require idref="lufa.bootloaders.printer"/>
+ <require idref="lufa.boards.dummy.avr8"/>
+ <generator value="as5_8"/>
+
+ <device-support value="at90usb1287"/>
+ <config name="lufa.drivers.board.name" value="none"/>
+
+ <config name="config.compiler.optimization.level" value="size"/>
+
+ <build type="define" name="F_CPU" value="16000000UL"/>
+ <build type="define" name="F_USB" value="16000000UL"/>
+
+ <build type="define" name="BOOT_START_ADDR" value="0x1F000"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.text=0x1F000"/>
+
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x1FFA0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x1FFE0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x1FFF8"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
+ </project>
+
+ <project caption="Printer Bootloader - 64KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.printer.avr8.64_4" force-caption="true" workspace-name="lufa_printer_64kb_4kb_">
+ <require idref="lufa.bootloaders.printer"/>
+ <require idref="lufa.boards.dummy.avr8"/>
+ <generator value="as5_8"/>
+
+ <device-support value="at90usb647"/>
+ <config name="lufa.drivers.board.name" value="none"/>
+
+ <config name="config.compiler.optimization.level" value="size"/>
+
+ <build type="define" name="F_CPU" value="16000000UL"/>
+ <build type="define" name="F_USB" value="16000000UL"/>
+
+ <build type="define" name="BOOT_START_ADDR" value="0xF000"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.text=0xF000"/>
+
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0xFFA0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0xFFE0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0xFFF8"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
+ </project>
+
+ <project caption="Printer Bootloader - 32KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.printer.avr8.32_4" force-caption="true" workspace-name="lufa_printer_32kb_4kb_">
+ <require idref="lufa.bootloaders.printer"/>
+ <require idref="lufa.boards.dummy.avr8"/>
+ <generator value="as5_8"/>
+
+ <device-support value="atmega32u4"/>
+ <config name="lufa.drivers.board.name" value="none"/>
+
+ <config name="config.compiler.optimization.level" value="size"/>
+
+ <build type="define" name="F_CPU" value="16000000UL"/>
+ <build type="define" name="F_USB" value="16000000UL"/>
+
+ <build type="define" name="BOOT_START_ADDR" value="0x7000"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.text=0x7000"/>
+
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x7FA0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x7FE0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x7FF8"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
+ </project>
+
+ <project caption="Printer Bootloader - 16KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.printer.avr8.16_4" force-caption="true" workspace-name="lufa_printer_16kb_4kb_">
+ <require idref="lufa.bootloaders.printer"/>
+ <require idref="lufa.boards.dummy.avr8"/>
+ <generator value="as5_8"/>
+
+ <device-support value="atmega16u2"/>
+ <config name="lufa.drivers.board.name" value="none"/>
+
+ <config name="config.compiler.optimization.level" value="size"/>
+
+ <build type="define" name="F_CPU" value="16000000UL"/>
+ <build type="define" name="F_USB" value="16000000UL"/>
+
+ <build type="define" name="BOOT_START_ADDR" value="0x3000"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.text=0x3000"/>
+
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x3FA0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x3FE0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x3FF8"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
+ </project>
+
+ <project caption="Printer Bootloader - 8KB FLASH / 4KB Boot - AVR8 Architecture" id="lufa.bootloaders.printer.avr8.8_4" force-caption="true" workspace-name="lufa_printer_8kb_4kb_">
+ <require idref="lufa.bootloaders.printer"/>
+ <require idref="lufa.boards.dummy.avr8"/>
+ <generator value="as5_8"/>
+
+ <device-support value="atmega8u2"/>
+ <config name="lufa.drivers.board.name" value="none"/>
+
+ <config name="config.compiler.optimization.level" value="size"/>
+
+ <build type="define" name="F_CPU" value="16000000UL"/>
+ <build type="define" name="F_USB" value="16000000UL"/>
+
+ <build type="define" name="BOOT_START_ADDR" value="0x1000"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.text=0x1000"/>
+
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_trampolines=0x1FA0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Trampolines"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_jumptable=0x1FE0"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_JumpTable"/>
+ <build type="linker-config" subtype="flags" value="--section-start=.apitable_signatures=0x1FF8"/>
+ <build type="linker-config" subtype="flags" value="--undefined=BootloaderAPI_Signatures"/>
+ </project>
+
+ <module type="application" id="lufa.bootloaders.printer" caption="Printer Bootloader">
+ <info type="description" value="summary">
+ Printer Class Bootloader, capable of reprogramming a device by "printing" new HEX files to the virtual Plain-Text printer it creates when plugged into a host.
+ </info>
+
+ <info type="gui-flag" value="move-to-root"/>
+
+ <info type="keyword" value="Technology">
+ <keyword value="Bootloaders"/>
+ <keyword value="USB Device"/>
+ </info>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="include-path" value="."/>
+ <build type="c-source" value="BootloaderPrinter.c"/>
+ <build type="header-file" value="BootloaderPrinter.h"/>
+ <build type="c-source" value="Descriptors.c"/>
+ <build type="header-file" value="Descriptors.h"/>
+ <build type="c-source" value="BootloaderAPI.c"/>
+ <build type="header-file" value="BootloaderAPI.h"/>
+ <build type="asm-source" value="BootloaderAPITable.S"/>
+
+ <build type="module-config" subtype="path" value="Config"/>
+ <build type="header-file" value="Config/LUFAConfig.h"/>
+
+ <build type="distribute" subtype="user-file" value="doxyfile"/>
+ <build type="distribute" subtype="user-file" value="BootloaderPrinter.txt"/>
+
+ <require idref="lufa.common"/>
+ <require idref="lufa.platform"/>
+ <require idref="lufa.drivers.usb"/>
+ <require idref="lufa.drivers.board"/>
+ <require idref="lufa.drivers.board.leds"/>
+ </module>
+</asf>
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/doxyfile b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/doxyfile
new file mode 100644
index 000000000..a81be54f4
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/doxyfile
@@ -0,0 +1,2365 @@
+# Doxyfile 1.8.8
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME = "LUFA Library - Printer Class Bootloader"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
+# the documentation. The maximum height of the logo should not exceed 55 pixels
+# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
+# to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = ./Documentation/
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES = YES
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
+# new page for each member. If set to NO, the documentation of a member will be
+# part of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
+# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
+# Fortran. In the later case the parser tries to guess whether the code is fixed
+# or free formatted code, this is the default for Fortran type files), VHDL. For
+# instance to make doxygen treat .inc files as Fortran files (default is PHP),
+# and .f files as C (default is Fortran), use: inc=Fortran f=C.
+#
+# Note For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT = NO
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by by putting a % sign in front of the word
+# or globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE = YES
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO these classes will be included in the various overviews. This option has
+# no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
+# todo list. This list is created by putting \todo commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST = NO
+
+# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
+# test list. This list is created by putting \test commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST = NO
+
+# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST = NO
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES the list
+# will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET = YES
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO doxygen will only warn about wrong or incomplete parameter
+# documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces.
+# Note: If this tag is empty the current directory is searched.
+
+INPUT = ./
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank the
+# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
+# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
+# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
+# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
+# *.qsf, *.as and *.js.
+
+FILE_PATTERNS = *.h \
+ *.c \
+ *.txt
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE = Documentation/
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS = __* \
+ INCLUDE_FROM_*
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER ) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = NO
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS = NO
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the
+# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
+# cost of reduced performance. This can be particularly helpful with template
+# rich C++ code for which doxygen's built-in parser lacks the necessary type
+# information.
+# Note: The availability of this option depends on whether or not doxygen was
+# compiled with the --with-libclang option.
+# The default value is: NO.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_OPTIONS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefor more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra stylesheet files is of importance (e.g. the last
+# stylesheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the stylesheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP = NO
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS = YES
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated (
+# YES) or that it should be included in the master .chm file ( NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated (
+# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND = YES
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX = YES
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW = YES
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE = 1
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. To get the times font for
+# instance you can specify
+# EXTRA_PACKAGES=times
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empy string,
+# for the replacement values of the other commands the user is refered to
+# HTML_HEADER.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE = plain
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT = docbook
+
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
+# Definitions (see http://autogen.sf.net) file that captures the structure of
+# the code including all documentation. Note that this feature is still
+# experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
+# in the source code. If set to NO only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF = YES
+
+# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED = __DOXYGEN__ \
+ PROGMEM \
+ ATTR_NO_INIT
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
+# class index. If set to NO only the inherited external classes will be listed.
+# The default value is: NO.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
+# the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS = YES
+
+# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS = NO
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME =
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH = NO
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH = NO
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS = NO
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH = NO
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH = NO
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY = NO
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH = NO
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot.
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif and svg.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+PLANTUML_JAR_PATH =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES = 15
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH = 2
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT = YES
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP = YES
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/makefile b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/makefile
new file mode 100644
index 000000000..0716c3bbe
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/Printer/makefile
@@ -0,0 +1,55 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2014.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+# --------------------------------------
+# LUFA Project Makefile.
+# --------------------------------------
+
+# Run "make help" for target help.
+
+MCU = at90usb1287
+ARCH = AVR8
+BOARD = USBKEY
+F_CPU = 8000000
+F_USB = $(F_CPU)
+OPTIMIZATION = s
+TARGET = BootloaderPrinter
+SRC = $(TARGET).c Descriptors.c BootloaderAPI.c BootloaderAPITable.S $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS)
+LUFA_PATH = ../../LUFA
+CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -IConfig/ -DBOOT_START_ADDR=$(BOOT_START_OFFSET)
+LD_FLAGS = -Wl,--section-start=.text=$(BOOT_START_OFFSET) $(BOOT_API_LD_FLAGS)
+
+# Flash size and bootloader section sizes of the target, in KB. These must
+# match the target's total FLASH size and the bootloader size set in the
+# device's fuses.
+FLASH_SIZE_KB = 128
+BOOT_SECTION_SIZE_KB = 8
+
+# Bootloader address calculation formulas
+# Do not modify these macros, but rather modify the dependent values above.
+CALC_ADDRESS_IN_HEX = $(shell printf "0x%X" $$(( $(1) )) )
+BOOT_START_OFFSET = $(call CALC_ADDRESS_IN_HEX, ($(FLASH_SIZE_KB) - $(BOOT_SECTION_SIZE_KB)) * 1024 )
+BOOT_SEC_OFFSET = $(call CALC_ADDRESS_IN_HEX, ($(FLASH_SIZE_KB) * 1024) - ($(strip $(1))) )
+
+# Bootloader linker section flags for relocating the API table sections to
+# known FLASH addresses - these should not normally be user-edited.
+BOOT_SECTION_LD_FLAG = -Wl,--section-start=$(strip $(1))=$(call BOOT_SEC_OFFSET, $(3)) -Wl,--undefined=$(strip $(2))
+BOOT_API_LD_FLAGS = $(call BOOT_SECTION_LD_FLAG, .apitable_trampolines, BootloaderAPI_Trampolines, 96)
+BOOT_API_LD_FLAGS += $(call BOOT_SECTION_LD_FLAG, .apitable_jumptable, BootloaderAPI_JumpTable, 32)
+BOOT_API_LD_FLAGS += $(call BOOT_SECTION_LD_FLAG, .apitable_signatures, BootloaderAPI_Signatures, 8)
+
+# Default target
+all:
+
+# Include LUFA build script makefiles
+include $(LUFA_PATH)/Build/lufa_core.mk
+include $(LUFA_PATH)/Build/lufa_sources.mk
+include $(LUFA_PATH)/Build/lufa_build.mk
+include $(LUFA_PATH)/Build/lufa_cppcheck.mk
+include $(LUFA_PATH)/Build/lufa_doxygen.mk
+include $(LUFA_PATH)/Build/lufa_avrdude.mk
+include $(LUFA_PATH)/Build/lufa_atprogram.mk
diff --git a/tmk_core/protocol/lufa/LUFA-git/Bootloaders/makefile b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/makefile
new file mode 100644
index 000000000..885b17029
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Bootloaders/makefile
@@ -0,0 +1,46 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2014.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+
+# Makefile to build all the LUFA USB Bootloaders. Call with "make all" to
+# rebuild all bootloaders.
+
+# Bootloaders are pre-cleaned before each one is built, to ensure any
+# custom LUFA library build options are reflected in the compiled
+# code.
+
+PROJECT_DIRECTORIES := $(shell ls -d */)
+
+# This makefile is potentially infinitely recursive if something really bad
+# happens when determining the set of project directories - hard-abort if
+# more than 10 levels deep to avoid angry emails.
+ifeq ($(MAKELEVEL), 10)
+ $(error EMERGENCY ABORT: INFINITE RECURSION DETECTED)
+endif
+
+# Need to special-case building without a per-project object directory
+ifeq ($(OBJDIR),)
+ # If no target specified, force "clean all" and disallow parallel build
+ ifeq ($(MAKECMDGOALS),)
+ MAKECMDGOALS := clean all
+ .NOTPARALLEL:
+ endif
+
+ # If one of the targets is to build, force "clean" beforehand and disallow parallel build
+ ifneq ($(findstring all, $(MAKECMDGOALS)),)
+ MAKECMDGOALS := clean $(MAKECMDGOALS)
+ .NOTPARALLEL:
+ endif
+endif
+
+%: $(PROJECT_DIRECTORIES)
+ @echo . > /dev/null
+
+$(PROJECT_DIRECTORIES):
+ @$(MAKE) -C $@ $(MAKECMDGOALS)
+
+.PHONY: $(PROJECT_DIRECTORIES)
diff --git a/tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/Board/Board.h b/tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/Board/Board.h
new file mode 100644
index 000000000..2eb2c536a
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/Board/Board.h
@@ -0,0 +1,82 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief LUFA Custom Board Hardware Information Driver (Template)
+ *
+ * This is a stub driver header file, for implementing custom board
+ * layout hardware with compatible LUFA board specific drivers. If
+ * the library is configured to use the BOARD_USER board mode, this
+ * driver file should be completed and copied into the "/Board/" folder
+ * inside the application's folder.
+ *
+ * This stub is for the board-specific component of the LUFA Board Hardware
+ * information driver.
+ */
+
+#ifndef __BOARD_USER_H__
+#define __BOARD_USER_H__
+
+ /* Includes: */
+ // TODO: Add any required includes here
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has a hardware Buttons mounted if defined. */
+// #define BOARD_HAS_BUTTONS
+
+ /** Indicates the board has a hardware Dataflash mounted if defined. */
+// #define BOARD_HAS_DATAFLASH
+
+ /** Indicates the board has a hardware Joystick mounted if defined. */
+// #define BOARD_HAS_JOYSTICK
+
+ /** Indicates the board has a hardware LEDs mounted if defined. */
+// #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/Board/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/Board/Buttons.h
new file mode 100644
index 000000000..b14388527
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/Board/Buttons.h
@@ -0,0 +1,92 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief LUFA Custom Board Button Hardware Driver (Template)
+ *
+ * This is a stub driver header file, for implementing custom board
+ * layout hardware with compatible LUFA board specific drivers. If
+ * the library is configured to use the BOARD_USER board mode, this
+ * driver file should be completed and copied into the "/Board/" folder
+ * inside the application's folder.
+ *
+ * This stub is for the board-specific component of the LUFA Buttons driver,
+ * for the control of physical board-mounted GPIO pushbuttons.
+ */
+
+#ifndef __BUTTONS_USER_H__
+#define __BUTTONS_USER_H__
+
+ /* Includes: */
+ // TODO: Add any required includes here
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ #define BOARD_DUMMY_BUTTONS_IMPLEMENTATION
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Button mask for the first button on the board. */
+ #define BUTTONS_BUTTON1 (1 << 0)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+
+ }
+
+ static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Buttons_GetStatus(void)
+ {
+ return 0;
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/Board/Dataflash.h b/tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/Board/Dataflash.h
new file mode 100644
index 000000000..f32e398ea
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/Board/Dataflash.h
@@ -0,0 +1,197 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief LUFA Custom Board Dataflash Hardware Driver (Template)
+ *
+ * This is a stub driver header file, for implementing custom board
+ * layout hardware with compatible LUFA board specific drivers. If
+ * the library is configured to use the BOARD_USER board mode, this
+ * driver file should be completed and copied into the "/Board/" folder
+ * inside the application's folder.
+ *
+ * This stub is for the board-specific component of the LUFA Dataflash
+ * driver.
+*/
+
+#ifndef __DATAFLASH_USER_H__
+#define __DATAFLASH_USER_H__
+
+ /* Includes: */
+ // TODO: Add any required includes here
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_DATAFLASH_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Dataflash.h instead.
+ #endif
+
+ #define BOARD_DUMMY_DATAFLASH_IMPLEMENTATION
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define DATAFLASH_CHIPCS_MASK 0
+ #define DATAFLASH_CHIPCS_DDR 0
+ #define DATAFLASH_CHIPCS_PORT 0
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Constant indicating the total number of dataflash ICs mounted on the selected board. */
+ #define DATAFLASH_TOTALCHIPS 1
+
+ /** Mask for no dataflash chip selected. */
+ #define DATAFLASH_NO_CHIP 0
+
+ /** Mask for the first dataflash chip selected. */
+ #define DATAFLASH_CHIP1 0
+
+ /** Mask for the second dataflash chip selected. */
+ #define DATAFLASH_CHIP2 0
+
+ /** Internal main memory page size for the board's dataflash ICs. */
+ #define DATAFLASH_PAGE_SIZE 0
+
+ /** Total number of pages inside each of the board's dataflash ICs. */
+ #define DATAFLASH_PAGES 0
+
+ /* Inline Functions: */
+ /** Initializes the dataflash driver so that commands and data may be sent to an attached dataflash IC.
+ * The microcontroller's SPI driver MUST be initialized before any of the dataflash commands are used.
+ */
+ static inline void Dataflash_Init(void)
+ {
+
+ }
+
+ /** Sends a byte to the currently selected dataflash IC, and returns a byte from the dataflash.
+ *
+ * \param[in] Byte Byte of data to send to the dataflash
+ *
+ * \return Last response byte from the dataflash
+ */
+ static inline uint8_t Dataflash_TransferByte(const uint8_t Byte) ATTR_ALWAYS_INLINE;
+ static inline uint8_t Dataflash_TransferByte(const uint8_t Byte)
+ {
+ return 0;
+ }
+
+ /** Sends a byte to the currently selected dataflash IC, and ignores the next byte from the dataflash.
+ *
+ * \param[in] Byte Byte of data to send to the dataflash
+ */
+ static inline void Dataflash_SendByte(const uint8_t Byte) ATTR_ALWAYS_INLINE;
+ static inline void Dataflash_SendByte(const uint8_t Byte)
+ {
+
+ }
+
+ /** Sends a dummy byte to the currently selected dataflash IC, and returns the next byte from the dataflash.
+ *
+ * \return Last response byte from the dataflash
+ */
+ static inline uint8_t Dataflash_ReceiveByte(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Dataflash_ReceiveByte(void)
+ {
+ return 0;
+ }
+
+ /** Determines the currently selected dataflash chip.
+ *
+ * \return Mask of the currently selected Dataflash chip, either \ref DATAFLASH_NO_CHIP if no chip is selected
+ * or a DATAFLASH_CHIPn mask (where n is the chip number).
+ */
+ static inline uint8_t Dataflash_GetSelectedChip(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Dataflash_GetSelectedChip(void)
+ {
+ return 0;
+ }
+
+ /** Selects the given dataflash chip.
+ *
+ * \param[in] ChipMask Mask of the Dataflash IC to select, in the form of a \c DATAFLASH_CHIPn mask (where n is
+ * the chip number).
+ */
+ static inline void Dataflash_SelectChip(const uint8_t ChipMask) ATTR_ALWAYS_INLINE;
+ static inline void Dataflash_SelectChip(const uint8_t ChipMask)
+ {
+
+ }
+
+ /** Deselects the current dataflash chip, so that no dataflash is selected. */
+ static inline void Dataflash_DeselectChip(void) ATTR_ALWAYS_INLINE;
+ static inline void Dataflash_DeselectChip(void)
+ {
+
+ }
+
+ /** Selects a dataflash IC from the given page number, which should range from 0 to
+ * ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1). For boards containing only one
+ * dataflash IC, this will select DATAFLASH_CHIP1. If the given page number is outside
+ * the total number of pages contained in the boards dataflash ICs, all dataflash ICs
+ * are deselected.
+ *
+ * \param[in] PageAddress Address of the page to manipulate, ranging from
+ * 0 to ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1).
+ */
+ static inline void Dataflash_SelectChipFromPage(const uint16_t PageAddress)
+ {
+
+ }
+
+ /** Toggles the select line of the currently selected dataflash IC, so that it is ready to receive
+ * a new command.
+ */
+ static inline void Dataflash_ToggleSelectedChipCS(void)
+ {
+
+ }
+
+ /** Spin-loops while the currently selected dataflash is busy executing a command, such as a main
+ * memory page program or main memory to buffer transfer.
+ */
+ static inline void Dataflash_WaitWhileBusy(void)
+ {
+
+ }
+
+ /** Sends a set of page and buffer address bytes to the currently selected dataflash IC, for use with
+ * dataflash commands which require a complete 24-bit address.
+ *
+ * \param[in] PageAddress Page address within the selected dataflash IC
+ * \param[in] BufferByte Address within the dataflash's buffer
+ */
+ static inline void Dataflash_SendAddressBytes(uint16_t PageAddress, const uint16_t BufferByte)
+ {
+
+ }
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/Board/Joystick.h b/tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/Board/Joystick.h
new file mode 100644
index 000000000..4aa45ab67
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/Board/Joystick.h
@@ -0,0 +1,104 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief LUFA Custom Board Joystick Hardware Driver (Template)
+ *
+ * This is a stub driver header file, for implementing custom board
+ * layout hardware with compatible LUFA board specific drivers. If
+ * the library is configured to use the BOARD_USER board mode, this
+ * driver file should be completed and copied into the "/Board/" folder
+ * inside the application's folder.
+ *
+ * This stub is for the board-specific component of the LUFA Joystick
+ * driver, for a digital four-way (plus button) joystick.
+*/
+
+#ifndef __JOYSTICK_USER_H__
+#define __JOYSTICK_USER_H__
+
+ /* Includes: */
+ // TODO: Add any required includes here
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_JOYSTICK_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Joystick.h instead.
+ #endif
+
+ #define BOARD_DUMMY_JOYSTICK_IMPLEMENTATION
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Mask for the joystick being pushed in the left direction. */
+ #define JOY_LEFT 0
+
+ /** Mask for the joystick being pushed in the right direction. */
+ #define JOY_RIGHT 0
+
+ /** Mask for the joystick being pushed in the upward direction. */
+ #define JOY_UP 0
+
+ /** Mask for the joystick being pushed in the downward direction. */
+ #define JOY_DOWN 0
+
+ /** Mask for the joystick being pushed inward. */
+ #define JOY_PRESS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Joystick_Init(void)
+ {
+
+ }
+
+ static inline void Joystick_Disable(void)
+ {
+
+ }
+
+ static inline uint8_t Joystick_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Joystick_GetStatus(void)
+ {
+ return 0;
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/Board/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/Board/LEDs.h
new file mode 100644
index 000000000..a146e99c3
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/Board/LEDs.h
@@ -0,0 +1,132 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief LUFA Custom Board LED Hardware Driver (Template)
+ *
+ * This is a stub driver header file, for implementing custom board
+ * layout hardware with compatible LUFA board specific drivers. If
+ * the library is configured to use the BOARD_USER board mode, this
+ * driver file should be completed and copied into the "/Board/" folder
+ * inside the application's folder.
+ *
+ * This stub is for the board-specific component of the LUFA LEDs driver,
+ * for the LEDs (up to four) mounted on most development boards.
+*/
+
+#ifndef __LEDS_USER_H__
+#define __LEDS_USER_H__
+
+ /* Includes: */
+ // TODO: Add any required includes here
+
+/* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ #define BOARD_DUMMY_LEDS_IMPLEMENTATION
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 0)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1 << 1)
+
+ /** LED mask for the third LED on the board. */
+ #define LEDS_LED3 (1 << 2)
+
+ /** LED mask for the fourth LED on the board. */
+ #define LEDS_LED4 (1 << 3)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3 | LEDS_LED4)
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask, const uint8_t ActiveMask)
+ {
+
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return 0;
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/BoardDeviceMap.cfg b/tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/BoardDeviceMap.cfg
new file mode 100644
index 000000000..3fee2f1e3
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/BoardDeviceMap.cfg
@@ -0,0 +1,87 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2014.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+#
+# =============================================================================
+# Board configuration map script, processed with the "BoardDriverTest"
+# makefile. This script file maps the possible LUFA target BOARD makefile
+# values in user projects to a specific architecture and device. This mapping is
+# then used by the makefile to build all possible drivers for that board, to
+# detect any missing or erroneous functions. To add a new board mapping, use
+# the syntax:
+#
+# BOARD DEFINE = {ARCH} : {MCU} :
+#
+# And re-run the makefile. Note that each board may have only one target.
+# =============================================================================
+#
+#
+# ----------------- AVR8 Boards ------------------
+BOARD_ADAFRUITU4 = AVR8 : atmega32u4 :
+BOARD_ATAVRUSBRF01 = AVR8 : at90usb1287 :
+BOARD_BENITO = AVR8 : at90usb162 :
+BOARD_BIGMULTIO = AVR8 : atmega32u4 :
+BOARD_BLACKCAT = AVR8 : at90usb162 :
+BOARD_BUI = AVR8 : at90usb646 :
+BOARD_BUMBLEB = AVR8 : at90usb162 :
+BOARD_CULV3 = AVR8 : atmega32u4 :
+BOARD_DUCE = AVR8 : atmega32u2 :
+BOARD_EVK527 = AVR8 : atmega32u4 :
+BOARD_JMDBU2 = AVR8 : atmega32u2 :
+BOARD_LEONARDO = AVR8 : atmega32u4 :
+BOARD_MAXIMUS = AVR8 : at90usb162 :
+BOARD_MICROPENDOUS_32U2 = AVR8 : atmega32u2 :
+BOARD_MICROPENDOUS_A = AVR8 : at90usb1287 :
+BOARD_MICROPENDOUS_1 = AVR8 : at90usb162 :
+BOARD_MICROPENDOUS_2 = AVR8 : atmega32u4 :
+BOARD_MICROPENDOUS_3 = AVR8 : at90usb1287 :
+BOARD_MICROPENDOUS_4 = AVR8 : at90usb1287 :
+BOARD_MICROPENDOUS_DIP = AVR8 : at90usb1287 :
+BOARD_MICROPENDOUS_REV1 = AVR8 : at90usb1287 :
+BOARD_MICROPENDOUS_REV2 = AVR8 : at90usb1287 :
+BOARD_MICROSIN162 = AVR8 : atmega162 :
+BOARD_MINIMUS = AVR8 : atmega32u2 :
+BOARD_MULTIO = AVR8 : at90usb162 :
+BOARD_NONE = AVR8 : at90usb1287 :
+BOARD_OLIMEX162 = AVR8 : at90usb162 :
+BOARD_OLIMEX32U4 = AVR8 : atmega32u4 :
+BOARD_OLIMEXT32U4 = AVR8 : atmega32u4 :
+BOARD_OLIMEXISPMK2 = AVR8 : at90usb162 :
+BOARD_RZUSBSTICK = AVR8 : at90usb1287 :
+BOARD_SPARKFUN8U2 = AVR8 : atmega8u2 :
+BOARD_STK525 = AVR8 : at90usb647 :
+BOARD_STK526 = AVR8 : at90usb162 :
+BOARD_TEENSY = AVR8 : at90usb162 :
+BOARD_TEENSY2 = AVR8 : at90usb646 :
+BOARD_TUL = AVR8 : atmega32u4 :
+BOARD_UDIP = AVR8 : atmega32u2 :
+BOARD_UNO = AVR8 : atmega8u2 :
+BOARD_USB2AX = AVR8 : atmega32u2 :
+BOARD_USB2AX_V3 = AVR8 : atmega32u2 :
+BOARD_USB2AX_V31 = AVR8 : atmega32u2 :
+BOARD_USBFOO = AVR8 : atmega162 :
+BOARD_USBKEY = AVR8 : at90usb1287 :
+BOARD_USBTINYMKII = AVR8 : at90usb162 :
+BOARD_USER = AVR8 : at90usb1287 :
+BOARD_XPLAIN = AVR8 : at90usb1287 :
+BOARD_XPLAIN_REV1 = AVR8 : at90usb1287 :
+BOARD_STANGE_ISP = AVR8 : at90usb162 :
+BOARD_U2S = AVR8 : atmega32u2 :
+BOARD_YUN = AVR8 : atmega32u4 :
+BOARD_MICRO = AVR8 : atmega32u4 :
+#
+# ----------------- XMEGA Boards -----------------
+BOARD_A3BU_XPLAINED = XMEGA : atxmega256a3bu :
+BOARD_B1_XPLAINED = XMEGA : atxmega128b1 :
+BOARD_C3_XPLAINED = XMEGA : atxmega384c3 :
+#
+# ------------------ UC3 Boards ------------------
+BOARD_EVK1100 = UC3 : uc3a0512 :
+BOARD_EVK1101 = UC3 : uc3b0256 :
+BOARD_EVK1104 = UC3 : uc3a3256 :
+BOARD_UC3A3_XPLAINED = UC3 : uc3a3256 :
+#
diff --git a/tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/Test.c b/tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/Test.c
new file mode 100644
index 000000000..0105886b2
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/Test.c
@@ -0,0 +1,115 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include <LUFA/Common/Common.h>
+#include <LUFA/Drivers/Board/Board.h>
+#include <LUFA/Drivers/Board/Buttons.h>
+#include <LUFA/Drivers/Board/Dataflash.h>
+#include <LUFA/Drivers/Board/LEDs.h>
+#include <LUFA/Drivers/Board/Joystick.h>
+
+#if defined(BOARD_HAS_BUTTONS) == defined(BOARD_DUMMY_BUTTONS_IMPLEMENTATION)
+ #error Mismatch between BOARD_HAS_BUTTONS and implementation.
+#endif
+
+#if defined(BOARD_HAS_DATAFLASH) == defined(BOARD_DUMMY_DATAFLASH_IMPLEMENTATION)
+ #error Mismatch between BOARD_HAS_DATAFLASH and implementation.
+#endif
+
+#if defined(BOARD_HAS_LEDS) == defined(BOARD_DUMMY_LEDS_IMPLEMENTATION)
+ #error Mismatch between BOARD_HAS_LEDS and implementation.
+#endif
+
+#if defined(BOARD_HAS_JOYSTICK) == defined(BOARD_DUMMY_JOYSTICK_IMPLEMENTATION)
+ #error Mismatch between BOARD_HAS_JOYSTICK and implementation.
+#endif
+
+int main(void)
+{
+ uint_reg_t Dummy;
+
+ /* =============================
+ * Buttons Compile Check
+ * ============================= */
+ // cppcheck-suppress redundantAssignment
+ Dummy = BUTTONS_BUTTON1;
+ Buttons_Init();
+ // cppcheck-suppress redundantAssignment
+ Dummy = Buttons_GetStatus();
+ Buttons_Disable();
+
+ /* =============================
+ * Dataflash Compile Check
+ * ============================= */
+ // cppcheck-suppress redundantAssignment
+ Dummy = DATAFLASH_TOTALCHIPS + DATAFLASH_NO_CHIP + DATAFLASH_CHIP1 + DATAFLASH_PAGE_SIZE + DATAFLASH_PAGES;
+ Dataflash_Init();
+ Dataflash_TransferByte(0);
+ Dataflash_SendByte(0);
+ // cppcheck-suppress redundantAssignment
+ Dummy = Dataflash_ReceiveByte();
+ // cppcheck-suppress redundantAssignment
+ Dummy = Dataflash_GetSelectedChip();
+ Dataflash_SelectChip(DATAFLASH_CHIP1);
+ Dataflash_DeselectChip();
+ Dataflash_SelectChipFromPage(0);
+ Dataflash_ToggleSelectedChipCS();
+ Dataflash_WaitWhileBusy();
+ Dataflash_SendAddressBytes(0, 0);
+
+ /* =============================
+ * LEDs Compile Check
+ * ============================= */
+ // cppcheck-suppress redundantAssignment
+ Dummy = LEDS_LED1 + LEDS_LED2 + LEDS_LED3 + LEDS_LED4;
+ LEDs_Init();
+ LEDs_TurnOnLEDs(LEDS_ALL_LEDS);
+ LEDs_TurnOffLEDs(LEDS_ALL_LEDS);
+ LEDs_SetAllLEDs(LEDS_ALL_LEDS);
+ LEDs_ChangeLEDs(LEDS_ALL_LEDS, LEDS_NO_LEDS);
+ LEDs_ToggleLEDs(LEDS_ALL_LEDS);
+ // cppcheck-suppress redundantAssignment
+ Dummy = LEDs_GetLEDs();
+ LEDs_Disable();
+
+ /* =============================
+ * Joystick Compile Check
+ * ============================= */
+ // cppcheck-suppress redundantAssignment
+ Dummy = JOY_LEFT + JOY_RIGHT + JOY_UP + JOY_DOWN + JOY_PRESS;
+ Joystick_Init();
+ // cppcheck-suppress redundantAssignment
+ Dummy = Joystick_GetStatus();
+ Joystick_Disable();
+
+ (void)Dummy;
+}
+
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/makefile b/tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/makefile
new file mode 100644
index 000000000..cfd9da798
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/makefile
@@ -0,0 +1,68 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2014.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+
+# Makefile for the board driver build test. This
+# test attempts to build a dummy project with all
+# possible board targets using their respective
+# compiler.
+
+# Path to the LUFA library core
+LUFA_PATH := ../../LUFA/
+
+# Build test cannot be run with multiple parallel jobs
+.NOTPARALLEL:
+
+all: begin makeboardlist testboards clean end
+
+begin:
+ @echo Executing build test "BoardDriverTest".
+ @echo
+
+end:
+ @echo Build test "BoardDriverTest" complete.
+ @echo
+
+makeboardlist:
+ @grep "BOARD_" $(patsubst %/,%,$(LUFA_PATH))/Common/BoardTypes.h | cut -d'#' -f2 | cut -d' ' -f2 | grep "BOARD_" > BoardList.txt
+
+testboards:
+ @echo "buildtest:" > BuildMakefile
+
+ @while read line; \
+ do \
+ build_cfg=`grep "$$line " BoardDeviceMap.cfg | grep -v "#" | cut -d'=' -f2- | sed 's/ //g'`; \
+ \
+ build_board=$$line; \
+ build_arch=`echo $$build_cfg | cut -d':' -f1`; \
+ build_mcu=`echo $$build_cfg | cut -d':' -f2`; \
+ \
+ if ( test -z "$$build_cfg" ); then \
+ echo "No matching information set for board $$build_board"; \
+ else \
+ echo "Found board configuration for $$build_board - $$build_arch, $$build_mcu"; \
+ \
+ printf "\t@echo Building dummy project for $$build_board...\n" >> BuildMakefile; \
+ printf "\t$(MAKE) -f makefile.test clean elf MCU=%s ARCH=%s BOARD=%s\n\n" $$build_mcu $$build_arch $$build_board >> BuildMakefile; \
+ fi; \
+ done < BoardList.txt
+
+ $(MAKE) -f BuildMakefile buildtest
+
+clean:
+ rm -f BuildMakefile
+ rm -f BoardList.txt
+ $(MAKE) -f makefile.test clean BOARD=NONE ARCH=AVR8 MCU=at90usb1287
+ $(MAKE) -f makefile.test clean BOARD=NONE ARCH=XMEGA MCU=atxmega128a1u
+ $(MAKE) -f makefile.test clean BOARD=NONE ARCH=UC3 MCU=uc3a0256
+
+%:
+
+.PHONY: all begin end makeboardlist testboards clean
+
+# Include LUFA build script makefiles
+include $(LUFA_PATH)/Build/lufa_core.mk
diff --git a/tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/makefile.test b/tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/makefile.test
new file mode 100644
index 000000000..7391b514a
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/BuildTests/BoardDriverTest/makefile.test
@@ -0,0 +1,27 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2014.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+# --------------------------------------
+# LUFA Project Makefile.
+# --------------------------------------
+
+# Run "make help" for target help.
+
+MCU =
+ARCH =
+BOARD =
+F_CPU = $(F_USB)
+F_USB = 8000000
+OPTIMIZATION = 1
+TARGET = Test
+SRC = $(TARGET).c
+LUFA_PATH = ../../LUFA
+CC_FLAGS = -Werror
+DEBUG_LEVEL = 0
+
+# Include LUFA build script makefiles
+include $(LUFA_PATH)/Build/lufa_build.mk
diff --git a/tmk_core/protocol/lufa/LUFA-git/BuildTests/BootloaderTest/BootloaderDeviceMap.cfg b/tmk_core/protocol/lufa/LUFA-git/BuildTests/BootloaderTest/BootloaderDeviceMap.cfg
new file mode 100644
index 000000000..9e15c8cf4
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/BuildTests/BootloaderTest/BootloaderDeviceMap.cfg
@@ -0,0 +1,167 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2014.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+#
+# =============================================================================
+# Bootloader configuration map script, processed with the "BootloaderTest"
+# makefile. This script file defines the targets for each LUFA bootloader,
+# which are then built as part of the build test to ensure that there are no
+# failures on all standard configurations. To add a new build target for a
+# bootloader to this script, use the format:
+#
+# BOOTLOADER = {ARCH} : {MCU} : {BOARD} : {FLASH SIZE KB} : {BOOT SIZE KB} : {F_USB MHZ}
+#
+# And re-run the makefile.
+# =============================================================================
+#
+#
+# ------------ CDC Bootloader --------------------
+CDC = AVR8 : at90usb1287 : XPLAIN : 128 : 8 : 8 :
+CDC = AVR8 : at90usb1287 : NONE : 128 : 8 : 8 :
+CDC = AVR8 : at90usb1287 : NONE : 128 : 4 : 8 :
+CDC = AVR8 : at90usb647 : NONE : 64 : 4 : 8 :
+CDC = AVR8 : at90usb1286 : NONE : 128 : 8 : 8 :
+CDC = AVR8 : at90usb1286 : NONE : 128 : 4 : 8 :
+CDC = AVR8 : at90usb646 : NONE : 64 : 4 : 8 :
+CDC = AVR8 : atmega32u4 : NONE : 32 : 4 : 8 :
+CDC = AVR8 : atmega16u4 : NONE : 16 : 4 : 8 :
+CDC = AVR8 : atmega32u2 : NONE : 32 : 4 : 8 :
+CDC = AVR8 : atmega16u2 : NONE : 16 : 4 : 8 :
+CDC = AVR8 : atmega8u2 : NONE : 8 : 4 : 8 :
+CDC = AVR8 : at90usb162 : NONE : 16 : 4 : 8 :
+CDC = AVR8 : at90usb82 : NONE : 8 : 4 : 8 :
+CDC = AVR8 : at90usb1287 : NONE : 128 : 8 : 16 :
+CDC = AVR8 : at90usb1287 : NONE : 128 : 4 : 16 :
+CDC = AVR8 : at90usb647 : NONE : 64 : 4 : 16 :
+CDC = AVR8 : at90usb1286 : NONE : 128 : 8 : 16 :
+CDC = AVR8 : at90usb1286 : NONE : 128 : 4 : 16 :
+CDC = AVR8 : at90usb646 : NONE : 64 : 4 : 16 :
+CDC = AVR8 : atmega32u4 : NONE : 32 : 4 : 16 :
+CDC = AVR8 : atmega16u4 : NONE : 16 : 4 : 16 :
+CDC = AVR8 : atmega32u2 : NONE : 32 : 4 : 16 :
+CDC = AVR8 : atmega16u2 : NONE : 16 : 4 : 16 :
+CDC = AVR8 : atmega8u2 : NONE : 8 : 4 : 16 :
+CDC = AVR8 : at90usb162 : NONE : 16 : 4 : 16 :
+CDC = AVR8 : at90usb82 : NONE : 8 : 4 : 16 :
+#
+# ------------ DFU Bootloader --------------------
+DFU = AVR8 : at90usb1287 : XPLAIN : 128 : 8 : 8 :
+DFU = AVR8 : at90usb1287 : NONE : 128 : 8 : 8 :
+DFU = AVR8 : at90usb1287 : NONE : 128 : 4 : 8 :
+DFU = AVR8 : at90usb647 : NONE : 64 : 4 : 8 :
+DFU = AVR8 : at90usb1286 : NONE : 128 : 8 : 8 :
+DFU = AVR8 : at90usb1286 : NONE : 128 : 4 : 8 :
+DFU = AVR8 : at90usb646 : NONE : 64 : 4 : 8 :
+DFU = AVR8 : atmega32u4 : NONE : 32 : 4 : 8 :
+DFU = AVR8 : atmega16u4 : NONE : 16 : 4 : 8 :
+DFU = AVR8 : atmega32u2 : NONE : 32 : 4 : 8 :
+DFU = AVR8 : atmega16u2 : NONE : 16 : 4 : 8 :
+DFU = AVR8 : atmega8u2 : NONE : 8 : 4 : 8 :
+DFU = AVR8 : at90usb162 : NONE : 16 : 4 : 8 :
+DFU = AVR8 : at90usb82 : NONE : 8 : 4 : 8 :
+DFU = AVR8 : at90usb1287 : NONE : 128 : 8 : 16 :
+DFU = AVR8 : at90usb1287 : NONE : 128 : 4 : 16 :
+DFU = AVR8 : at90usb647 : NONE : 64 : 4 : 16 :
+DFU = AVR8 : at90usb1286 : NONE : 128 : 8 : 16 :
+DFU = AVR8 : at90usb1286 : NONE : 128 : 4 : 16 :
+DFU = AVR8 : at90usb646 : NONE : 64 : 4 : 16 :
+DFU = AVR8 : atmega32u4 : NONE : 32 : 4 : 16 :
+DFU = AVR8 : atmega16u4 : NONE : 16 : 4 : 16 :
+DFU = AVR8 : atmega32u2 : NONE : 32 : 4 : 16 :
+DFU = AVR8 : atmega16u2 : NONE : 16 : 4 : 16 :
+DFU = AVR8 : atmega8u2 : NONE : 8 : 4 : 16 :
+DFU = AVR8 : at90usb162 : NONE : 16 : 4 : 16 :
+DFU = AVR8 : at90usb82 : NONE : 8 : 4 : 16 :
+#
+# ------------ HID Bootloader --------------------
+HID = AVR8 : at90usb1287 : NONE : 128 : 8 : 8 :
+HID = AVR8 : at90usb1287 : NONE : 128 : 4 : 8 :
+HID = AVR8 : at90usb647 : NONE : 64 : 4 : 8 :
+HID = AVR8 : at90usb1286 : NONE : 128 : 8 : 8 :
+HID = AVR8 : at90usb1286 : NONE : 128 : 4 : 8 :
+HID = AVR8 : at90usb646 : NONE : 64 : 4 : 8 :
+HID = AVR8 : atmega32u4 : NONE : 32 : 4 : 8 :
+HID = AVR8 : atmega16u4 : NONE : 16 : 4 : 8 :
+HID = AVR8 : atmega32u2 : NONE : 32 : 2 : 8 :
+HID = AVR8 : atmega32u2 : NONE : 32 : 4 : 8 :
+HID = AVR8 : atmega16u2 : NONE : 16 : 2 : 8 :
+HID = AVR8 : atmega16u2 : NONE : 16 : 4 : 8 :
+HID = AVR8 : atmega8u2 : NONE : 8 : 2 : 8 :
+HID = AVR8 : atmega8u2 : NONE : 8 : 4 : 8 :
+HID = AVR8 : at90usb162 : NONE : 16 : 2 : 8 :
+HID = AVR8 : at90usb162 : NONE : 16 : 4 : 8 :
+HID = AVR8 : at90usb162 : NONE : 16 : 2 : 8 :
+HID = AVR8 : at90usb162 : NONE : 16 : 4 : 8 :
+HID = AVR8 : at90usb1287 : NONE : 128 : 8 : 8 :
+HID = AVR8 : at90usb1287 : NONE : 128 : 4 : 8 :
+HID = AVR8 : at90usb647 : NONE : 64 : 4 : 8 :
+HID = AVR8 : at90usb1286 : NONE : 128 : 8 : 16 :
+HID = AVR8 : at90usb1286 : NONE : 128 : 4 : 16 :
+HID = AVR8 : at90usb646 : NONE : 64 : 4 : 16 :
+HID = AVR8 : atmega32u4 : NONE : 32 : 4 : 16 :
+HID = AVR8 : atmega16u4 : NONE : 16 : 4 : 16 :
+HID = AVR8 : atmega32u2 : NONE : 32 : 2 : 16 :
+HID = AVR8 : atmega32u2 : NONE : 32 : 4 : 16 :
+HID = AVR8 : atmega16u2 : NONE : 16 : 2 : 16 :
+HID = AVR8 : atmega16u2 : NONE : 16 : 4 : 16 :
+HID = AVR8 : atmega8u2 : NONE : 8 : 2 : 16 :
+HID = AVR8 : atmega8u2 : NONE : 8 : 4 : 16 :
+HID = AVR8 : at90usb162 : NONE : 16 : 2 : 16 :
+HID = AVR8 : at90usb162 : NONE : 16 : 4 : 16 :
+HID = AVR8 : at90usb162 : NONE : 16 : 2 : 16 :
+HID = AVR8 : at90usb162 : NONE : 16 : 4 : 16 :
+#
+# ---------- Printer Bootloader ------------------
+Printer = AVR8 : at90usb1287 : NONE : 128 : 8 : 8 :
+Printer = AVR8 : at90usb1287 : NONE : 128 : 4 : 8 :
+Printer = AVR8 : at90usb647 : NONE : 64 : 4 : 8 :
+Printer = AVR8 : at90usb1286 : NONE : 128 : 8 : 8 :
+Printer = AVR8 : at90usb1286 : NONE : 128 : 4 : 8 :
+Printer = AVR8 : at90usb646 : NONE : 64 : 4 : 8 :
+Printer = AVR8 : atmega32u4 : NONE : 32 : 4 : 8 :
+Printer = AVR8 : atmega16u4 : NONE : 16 : 4 : 8 :
+Printer = AVR8 : atmega32u2 : NONE : 32 : 4 : 8 :
+Printer = AVR8 : atmega16u2 : NONE : 16 : 4 : 8 :
+Printer = AVR8 : atmega8u2 : NONE : 8 : 4 : 8 :
+Printer = AVR8 : at90usb162 : NONE : 16 : 4 : 8 :
+Printer = AVR8 : at90usb82 : NONE : 8 : 4 : 8 :
+Printer = AVR8 : at90usb1287 : NONE : 128 : 8 : 16 :
+Printer = AVR8 : at90usb1287 : NONE : 128 : 4 : 16 :
+Printer = AVR8 : at90usb647 : NONE : 64 : 4 : 16 :
+Printer = AVR8 : at90usb1286 : NONE : 128 : 8 : 16 :
+Printer = AVR8 : at90usb1286 : NONE : 128 : 4 : 16 :
+Printer = AVR8 : at90usb646 : NONE : 64 : 4 : 16 :
+Printer = AVR8 : atmega32u4 : NONE : 32 : 4 : 16 :
+Printer = AVR8 : atmega16u4 : NONE : 16 : 4 : 16 :
+Printer = AVR8 : atmega32u2 : NONE : 32 : 4 : 16 :
+Printer = AVR8 : atmega16u2 : NONE : 16 : 4 : 16 :
+Printer = AVR8 : atmega8u2 : NONE : 8 : 4 : 16 :
+Printer = AVR8 : at90usb162 : NONE : 16 : 4 : 16 :
+Printer = AVR8 : at90usb82 : NONE : 8 : 4 : 16 :
+#
+# ---------- Mass Storage Bootloader -----------------
+MassStorage = AVR8 : at90usb1287 : XPLAIN : 128 : 8 : 8 :
+MassStorage = AVR8 : at90usb1287 : NONE : 128 : 8 : 8 :
+MassStorage = AVR8 : at90usb1287 : NONE : 128 : 4 : 8 :
+MassStorage = AVR8 : at90usb647 : NONE : 64 : 4 : 8 :
+MassStorage = AVR8 : at90usb1286 : NONE : 128 : 8 : 8 :
+MassStorage = AVR8 : at90usb1286 : NONE : 128 : 4 : 8 :
+MassStorage = AVR8 : at90usb646 : NONE : 64 : 4 : 8 :
+MassStorage = AVR8 : atmega32u4 : LEONARDO : 32 : 4 : 16 :
+MassStorage = AVR8 : atmega32u4 : NONE : 32 : 4 : 8 :
+MassStorage = AVR8 : atmega16u4 : NONE : 16 : 4 : 8 :
+MassStorage = AVR8 : atmega32u2 : NONE : 32 : 4 : 8 :
+MassStorage = AVR8 : at90usb1287 : NONE : 128 : 8 : 16 :
+MassStorage = AVR8 : at90usb1287 : NONE : 128 : 4 : 16 :
+MassStorage = AVR8 : at90usb647 : NONE : 64 : 4 : 16 :
+MassStorage = AVR8 : at90usb1286 : NONE : 128 : 8 : 16 :
+MassStorage = AVR8 : at90usb1286 : NONE : 128 : 4 : 16 :
+MassStorage = AVR8 : at90usb646 : NONE : 64 : 4 : 16 :
+MassStorage = AVR8 : atmega32u4 : NONE : 32 : 4 : 16 :
+MassStorage = AVR8 : atmega16u4 : NONE : 16 : 4 : 16 :
+MassStorage = AVR8 : atmega32u2 : NONE : 32 : 4 : 16 :
+#
diff --git a/tmk_core/protocol/lufa/LUFA-git/BuildTests/BootloaderTest/makefile b/tmk_core/protocol/lufa/LUFA-git/BuildTests/BootloaderTest/makefile
new file mode 100644
index 000000000..52ebb9cdb
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/BuildTests/BootloaderTest/makefile
@@ -0,0 +1,64 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2014.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+
+# Makefile for the bootloader build test. This
+# test attempts to build all the bootloaders
+# with all supported device configurations.
+
+# Path to the LUFA library core
+LUFA_PATH := ../../LUFA/
+
+# Build test cannot be run with multiple parallel jobs
+.NOTPARALLEL:
+
+all: begin testbootloaders clean end
+
+begin:
+ @echo Executing build test "BootloaderTest".
+ @echo
+
+end:
+ @echo Build test "BootloaderTest" complete.
+ @echo
+
+testbootloaders:
+ @echo "buildtest:" > BuildMakefile
+
+ @while read line; \
+ do \
+ build_cfg=`echo $$line | grep -v "#" | sed 's/ //g'`; \
+ \
+ if ( test -n "$$build_cfg" ); then \
+ build_bootloader=`echo $$build_cfg | cut -d'=' -f1`; \
+ build_cfg=`echo $$build_cfg | cut -d'=' -f2-`; \
+ \
+ build_arch=`echo $$build_cfg | cut -d':' -f1`; \
+ build_mcu=`echo $$build_cfg | cut -d':' -f2`; \
+ build_board=`echo $$build_cfg | cut -d':' -f3`; \
+ build_flashsize=`echo $$build_cfg | cut -d':' -f4`; \
+ build_bootsize=`echo $$build_cfg | cut -d':' -f5`; \
+ build_fusb=`echo $$build_cfg | cut -d':' -f6`; \
+ \
+ printf "Found '%s' bootloader configuration (FLASH: %3s KB | BOOT: %3s KB | MCU: %12s / %4s | BOARD: %s | F_USB: %sMHz)\n" $$build_bootloader $$build_flashsize $$build_bootsize $$build_mcu $$build_arch $$build_board $$build_fusb; \
+ \
+ printf "\t@echo Building bootloader %s - %s - FLASH: %s KB, BOOT: %s KB, BOARD: %s, F_USB: %sMHz\n" $$build_bootloader $$build_mcu $$build_flashsize $$build_bootsize $$build_board $$build_fusb >> BuildMakefile; \
+ printf "\t$(MAKE) -C $(patsubst %/,%,$(LUFA_PATH))/../Bootloaders/%s/ clean elf ARCH=%s MCU=%s BOARD=%s FLASH_SIZE_KB=%s BOOT_SECTION_SIZE_KB=%s F_USB=%s000000 DEBUG_LEVEL=0\n\n" $$build_bootloader $$build_arch $$build_mcu $$build_board $$build_flashsize $$build_bootsize $$build_fusb >> BuildMakefile; \
+ fi; \
+ done < BootloaderDeviceMap.cfg
+
+ $(MAKE) -f BuildMakefile buildtest
+
+clean:
+ rm -f BuildMakefile
+
+%:
+
+.PHONY: all begin end testbootloaders clean
+
+# Include LUFA build script makefiles
+include $(LUFA_PATH)/Build/lufa_core.mk
diff --git a/tmk_core/protocol/lufa/LUFA-git/BuildTests/ModuleTest/Dummy.S b/tmk_core/protocol/lufa/LUFA-git/BuildTests/ModuleTest/Dummy.S
new file mode 100644
index 000000000..dcfe98186
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/BuildTests/ModuleTest/Dummy.S
@@ -0,0 +1,41 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+.section .text
+
+
+# Mandatory entry point for successful compilation and link
+.global main
+main:
+
+
+# Mandatory callback needed for base compile of the USB driver
+.global CALLBACK_USB_GetDescriptor
+CALLBACK_USB_GetDescriptor:
diff --git a/tmk_core/protocol/lufa/LUFA-git/BuildTests/ModuleTest/Modules.h b/tmk_core/protocol/lufa/LUFA-git/BuildTests/ModuleTest/Modules.h
new file mode 100644
index 000000000..cc16fd6b9
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/BuildTests/ModuleTest/Modules.h
@@ -0,0 +1,56 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include <LUFA/Common/Common.h>
+
+#include <LUFA/Platform/Platform.h>
+
+#include <LUFA/Drivers/USB/USB.h>
+#include <LUFA/Drivers/Misc/RingBuffer.h>
+#include <LUFA/Drivers/Misc/TerminalCodes.h>
+
+#if (ARCH == ARCH_AVR8)
+ #if defined(ADC)
+ #include <LUFA/Drivers/Peripheral/ADC.h>
+ #endif
+
+ #include <LUFA/Drivers/Peripheral/Serial.h>
+ #include <LUFA/Drivers/Peripheral/SerialSPI.h>
+ #include <LUFA/Drivers/Peripheral/SPI.h>
+
+ #if defined(TWCR)
+ #include <LUFA/Drivers/Peripheral/TWI.h>
+ #endif
+#elif (ARCH == ARCH_XMEGA)
+ #include <LUFA/Drivers/Peripheral/Serial.h>
+ #include <LUFA/Drivers/Peripheral/SerialSPI.h>
+ #include <LUFA/Drivers/Peripheral/SPI.h>
+ #include <LUFA/Drivers/Peripheral/TWI.h>
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/BuildTests/ModuleTest/Test_C.c b/tmk_core/protocol/lufa/LUFA-git/BuildTests/ModuleTest/Test_C.c
new file mode 100644
index 000000000..349ac6eec
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/BuildTests/ModuleTest/Test_C.c
@@ -0,0 +1,31 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "Modules.h"
diff --git a/tmk_core/protocol/lufa/LUFA-git/BuildTests/ModuleTest/Test_CPP.cpp b/tmk_core/protocol/lufa/LUFA-git/BuildTests/ModuleTest/Test_CPP.cpp
new file mode 100644
index 000000000..349ac6eec
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/BuildTests/ModuleTest/Test_CPP.cpp
@@ -0,0 +1,31 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "Modules.h"
diff --git a/tmk_core/protocol/lufa/LUFA-git/BuildTests/ModuleTest/makefile b/tmk_core/protocol/lufa/LUFA-git/BuildTests/ModuleTest/makefile
new file mode 100644
index 000000000..2cd33cf87
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/BuildTests/ModuleTest/makefile
@@ -0,0 +1,66 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2014.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+
+# Makefile for the module build test. This test
+# attempts to build as many modules as possible
+# under all supported architectures, and include
+# all module headers in a simple C and C++
+# application.
+
+# Path to the LUFA library core
+LUFA_PATH := ../../LUFA/
+
+# Build test cannot be run with multiple parallel jobs
+.NOTPARALLEL:
+
+# List of device families per architecture, one device per architecture sub-family
+AVR8_FAMILIES := at90usb1287 at90usb1286 atmega16u4 atmega16u2 at90usb162
+XMEGA_FAMILIES := atxmega128a1u atxmega128a3u atxmega256a3bu atxmega128a4u atxmega128b1 atxmega128b3 atxmega128c3 atxmega32c4
+UC3_FAMILIES := uc3a0256 uc3a1256 uc3a3256 uc3a4256 uc3b0256 uc3b1256
+
+# List of all device families, with a family postfix
+DEVICE_FAMILIES := $(AVR8_FAMILIES:%=%.avr8) $(XMEGA_FAMILIES:%=%.xmega) $(UC3_FAMILIES:%=%.uc3)
+
+
+all: begin $(DEVICE_FAMILIES) clean end
+
+arch_avr8: begin $(AVR8_FAMILIES:%=%.avr8) end
+arch_xmega: begin $(XMEGA_FAMILIES:%=%.xmega) end
+arch_uc3: begin $(UC3_FAMILIES:%=%.uc3) end
+
+begin:
+ @echo Executing build test "ModuleTest".
+ @echo
+
+end:
+ @echo Build test "ModuleTest" complete.
+ @echo
+
+%.avr8:
+ @echo Building ModuleTest for ARCH=AVR8 MCU=$(@:%.avr8=%)...
+ $(MAKE) -f makefile.test clean elf ARCH=AVR8 MCU=$(@:%.avr8=%)
+
+%.xmega:
+ @echo Building ModuleTest for ARCH=XMEGA MCU=$(@:%.xmega=%)...
+ $(MAKE) -f makefile.test clean elf ARCH=XMEGA MCU=$(@:%.xmega=%)
+
+%.uc3:
+ @echo Building ModuleTest for ARCH=UC3 MCU=$(@:%.uc3=%)...
+ $(MAKE) -f makefile.test clean elf ARCH=UC3 MCU=$(@:%.uc3=%)
+
+clean:
+ $(MAKE) -f makefile.test clean ARCH=AVR8 MCU=$(firstword $(AVR8_FAMILIES))
+ $(MAKE) -f makefile.test clean ARCH=XMEGA MCU=$(firstword $(XMEGA_FAMILIES))
+ $(MAKE) -f makefile.test clean ARCH=UC3 MCU=$(firstword $(UC3_FAMILIES))
+
+%:
+
+.PHONY: all arch_avr8 arch_xmega arch_uc3 begin end
+
+# Include LUFA build script makefiles
+include $(LUFA_PATH)/Build/lufa_core.mk
diff --git a/tmk_core/protocol/lufa/LUFA-git/BuildTests/ModuleTest/makefile.test b/tmk_core/protocol/lufa/LUFA-git/BuildTests/ModuleTest/makefile.test
new file mode 100644
index 000000000..1307d5e37
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/BuildTests/ModuleTest/makefile.test
@@ -0,0 +1,88 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2014.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+# --------------------------------------
+# LUFA Project Makefile.
+# --------------------------------------
+
+# Run "make help" for target help.
+
+MCU =
+ARCH =
+BOARD = NONE
+F_CPU = $(F_USB)
+OPTIMIZATION = 1
+TARGET = Test
+SRC = $(TARGET)_C.c $(TARGET)_CPP.cpp Dummy.S $(LUFA_SRC_USB)
+LUFA_PATH = ../../LUFA
+DEBUG_LEVEL = 0
+
+ifeq ($(ARCH), AVR8)
+ F_USB = 8000000
+else ifeq ($(ARCH), XMEGA)
+ F_USB = 48000000
+else ifeq ($(ARCH), UC3)
+ F_USB = 48000000
+endif
+
+# Generic C/C++ compiler flags
+CC_FLAGS = -Wextra
+CC_FLAGS += -Werror
+CC_FLAGS += -Wformat=2
+CC_FLAGS += -Winit-self
+CC_FLAGS += -Wswitch-enum
+CC_FLAGS += -Wunused
+CC_FLAGS += -Wundef
+CC_FLAGS += -Wpointer-arith
+CC_FLAGS += -Wcast-align
+CC_FLAGS += -Wwrite-strings
+CC_FLAGS += -Wlogical-op
+CC_FLAGS += -Wmissing-declarations
+CC_FLAGS += -Wmissing-field-initializers
+CC_FLAGS += -Wmissing-format-attribute
+CC_FLAGS += -Woverlength-strings
+CC_FLAGS += -Wswitch-default
+CC_FLAGS += -Wfloat-equal
+CC_FLAGS += -Waggregate-return
+CC_FLAGS += -Wmissing-include-dirs
+
+# Disable warnings not supported by the version of GCC used for UC3 targets (FIXME)
+ifneq ($(ARCH), UC3)
+ CC_FLAGS += -Wdouble-promotion
+endif
+
+# Only enable redundant declaration warnings for AVR8 target (FIXME)
+ifeq ($(ARCH), AVR8)
+ CC_FLAGS += -Wredundant-decls
+endif
+
+# C compiler only flags
+C_FLAGS += -Wmissing-parameter-type
+C_FLAGS += -Wmissing-prototypes
+C_FLAGS += -Wnested-externs
+C_FLAGS += -Wbad-function-cast
+C_FLAGS += -Wstrict-prototypes
+C_FLAGS += -Wold-style-definition
+
+# Disable warnings not supported by the version of GCC used for UC3 targets (FIXME)
+ifneq ($(ARCH), UC3)
+ C_FLAGS += -Wunsuffixed-float-constants
+ C_FLAGS += -Wjump-misses-init
+endif
+
+# Only check C++ compatibility on the build files, to ensure headers are C++ compatible
+Test_C.c Test_CPP.c: CC_FLAGS += -Wc++-compat
+
+# Potential additional warnings to enable in the future (FIXME)
+#CC_FLAGS += -Wcast-qual
+#CC_FLAGS += -Wconversion
+#CC_FLAGS += -Wsign-conversion
+#CC_FLAGS += -pedantic
+
+# Include LUFA build script makefiles
+include $(LUFA_PATH)/Build/lufa_sources.mk
+include $(LUFA_PATH)/Build/lufa_build.mk
diff --git a/tmk_core/protocol/lufa/LUFA-git/BuildTests/SingleUSBModeTest/Dummy.S b/tmk_core/protocol/lufa/LUFA-git/BuildTests/SingleUSBModeTest/Dummy.S
new file mode 100644
index 000000000..b5655add5
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/BuildTests/SingleUSBModeTest/Dummy.S
@@ -0,0 +1,42 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+.section .text
+
+
+# Mandatory entry point for successful compilation and link
+.global main
+main:
+ # Force code generation of the base USB stack
+ call USB_Init
+
+# Mandatory callback needed for base compile of the USB driver
+.global CALLBACK_USB_GetDescriptor
+CALLBACK_USB_GetDescriptor:
diff --git a/tmk_core/protocol/lufa/LUFA-git/BuildTests/SingleUSBModeTest/Test.c b/tmk_core/protocol/lufa/LUFA-git/BuildTests/SingleUSBModeTest/Test.c
new file mode 100644
index 000000000..7a83794df
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/BuildTests/SingleUSBModeTest/Test.c
@@ -0,0 +1,32 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include <LUFA/Common/Common.h>
+#include <LUFA/Drivers/USB/USB.h>
diff --git a/tmk_core/protocol/lufa/LUFA-git/BuildTests/SingleUSBModeTest/makefile b/tmk_core/protocol/lufa/LUFA-git/BuildTests/SingleUSBModeTest/makefile
new file mode 100644
index 000000000..cd88754db
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/BuildTests/SingleUSBModeTest/makefile
@@ -0,0 +1,56 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2014.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+
+# Makefile for the single USB mode build test.
+# This test attempts to build the USB module
+# under fixed device and fixed host modes under
+# all supported architectures
+
+# Path to the LUFA library core
+LUFA_PATH := ../../LUFA/
+
+# Build test cannot be run with multiple parallel jobs
+.NOTPARALLEL:
+
+all: begin compile clean end
+
+begin:
+ @echo Executing build test "SingleUSBModeTest".
+ @echo
+
+end:
+ @echo Build test "SingleUSBModeTest" complete.
+ @echo
+
+compile:
+ @echo Building SingleUSBModeTest for ARCH=AVR8 in device only mode...
+ $(MAKE) -f makefile.test clean elf ARCH=AVR8 MCU=at90usb1287 CC_FLAGS='-D USB_DEVICE_ONLY'
+
+ @echo Building SingleUSBModeTest for ARCH=AVR8 in host only mode...
+ $(MAKE) -f makefile.test clean elf ARCH=AVR8 MCU=at90usb1287 CC_FLAGS='-D USB_HOST_ONLY'
+
+ @echo Building SingleUSBModeTest for ARCH=XMEGA in device only mode...
+ $(MAKE) -f makefile.test clean elf ARCH=XMEGA MCU=atxmega128a1u CC_FLAGS='-D USB_DEVICE_ONLY'
+
+ @echo Building SingleUSBModeTest for ARCH=UC3 in device only mode...
+ $(MAKE) -f makefile.test clean elf ARCH=UC3 MCU=uc3a0256 CC_FLAGS='-D USB_DEVICE_ONLY'
+
+ @echo Building SingleUSBModeTest for ARCH=UC3 in host only mode...
+ $(MAKE) -f makefile.test clean elf ARCH=UC3 MCU=uc3a0256 CC_FLAGS='-D USB_HOST_ONLY'
+
+clean:
+ $(MAKE) -f makefile.test clean ARCH=AVR8 MCU=at90usb1287
+ $(MAKE) -f makefile.test clean ARCH=XMEGA MCU=atxmega128a1u
+ $(MAKE) -f makefile.test clean ARCH=UC3 MCU=uc3a0256
+
+%:
+
+.PHONY: begin end compile clean
+
+# Include LUFA build script makefiles
+include $(LUFA_PATH)/Build/lufa_core.mk
diff --git a/tmk_core/protocol/lufa/LUFA-git/BuildTests/SingleUSBModeTest/makefile.test b/tmk_core/protocol/lufa/LUFA-git/BuildTests/SingleUSBModeTest/makefile.test
new file mode 100644
index 000000000..242e530ea
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/BuildTests/SingleUSBModeTest/makefile.test
@@ -0,0 +1,69 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2014.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+# --------------------------------------
+# LUFA Project Makefile.
+# --------------------------------------
+
+# Run "make help" for target help.
+
+MCU =
+ARCH =
+BOARD = NONE
+F_CPU = $(F_USB)
+DEBUG_LEVEL = 0
+
+ifeq ($(ARCH), AVR8)
+ F_USB = 8000000
+else ifeq ($(ARCH), XMEGA)
+ F_USB = 48000000
+else ifeq ($(ARCH), UC3)
+ F_USB = 48000000
+endif
+
+OPTIMIZATION = 1
+TARGET = Test
+SRC = Test.c Dummy.S $(LUFA_SRC_USB)
+LUFA_PATH = ../../LUFA
+
+# Generic C/C++ compiler flags
+CC_FLAGS = -Wextra
+CC_FLAGS += -Werror
+CC_FLAGS += -Wformat=2
+CC_FLAGS += -Winit-self
+CC_FLAGS += -Wswitch-enum
+CC_FLAGS += -Wunused
+CC_FLAGS += -Wundef
+CC_FLAGS += -Wpointer-arith
+CC_FLAGS += -Wcast-align
+CC_FLAGS += -Wwrite-strings
+CC_FLAGS += -Wlogical-op
+CC_FLAGS += -Wmissing-declarations
+CC_FLAGS += -Wmissing-field-initializers
+CC_FLAGS += -Wmissing-format-attribute
+CC_FLAGS += -Woverlength-strings
+
+# Only enable rendundant declaration warnings for AVR8 target (FIXME)
+ifeq ($(ARCH), AVR8)
+ CC_FLAGS += -Wredundant-decls
+endif
+
+# C compiler only flags
+C_FLAGS += -Wmissing-parameter-type
+C_FLAGS += -Wnested-externs
+
+# Potential additional warnings to enable in the future (FIXME)
+#CC_FLAGS += -Wswitch-default
+#CC_FLAGS += -Wc++-compat
+#CC_FLAGS += -Wcast-qual
+#CC_FLAGS += -Wconversion
+#CC_FLAGS += -Wjump-misses-init
+#CC_FLAGS += -pedantic
+
+# Include LUFA build script makefiles
+include $(LUFA_PATH)/Build/lufa_sources.mk
+include $(LUFA_PATH)/Build/lufa_build.mk
diff --git a/tmk_core/protocol/lufa/LUFA-git/BuildTests/StaticAnalysisTest/makefile b/tmk_core/protocol/lufa/LUFA-git/BuildTests/StaticAnalysisTest/makefile
new file mode 100644
index 000000000..f5dc1c007
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/BuildTests/StaticAnalysisTest/makefile
@@ -0,0 +1,47 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2014.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+
+# Static anlysis of the entire LUFA source tree, using the free cross-platform "cppcheck" tool.
+
+# Path to the LUFA library core
+LUFA_PATH := ../../LUFA/
+
+CPPCHECK_EXCLUDES := FATFs/ \
+ PetiteFATFs/ \
+ uip/
+
+CPPCHECK_INCLUDES := $(patsubst %/,%,$(LUFA_PATH))/CodeTemplates/ \
+ $(patsubst %/,%,$(LUFA_PATH))/../Projects/AVRISP-MKII/
+
+CPPCHECK_FLAGS := -U TEMPLATE_FUNC_NAME -U __GNUC__ -U __DOXYGEN__
+
+CPPCHECK_SUPPRESS := variableScope missingInclude unusedFunction
+
+SRC := $(patsubst %/,%,$(LUFA_PATH))/..
+
+# Build test cannot be run with multiple parallel jobs
+.NOTPARALLEL:
+
+all: begin cppcheck end
+
+begin:
+ @echo Executing build test "StaticAnalysisTest".
+ @echo
+
+end:
+ @echo Build test "StaticAnalysisTest" complete.
+ @echo
+
+%:
+
+
+.PHONY: all begin end
+
+# Include LUFA build script makefiles
+include $(LUFA_PATH)/Build/lufa_core.mk
+include $(LUFA_PATH)/Build/lufa_cppcheck.mk
diff --git a/tmk_core/protocol/lufa/LUFA-git/BuildTests/makefile b/tmk_core/protocol/lufa/LUFA-git/BuildTests/makefile
new file mode 100644
index 000000000..1f09b3fec
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/BuildTests/makefile
@@ -0,0 +1,24 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2014.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+
+# Makefile to build all the LUFA Build Tests. Build Tests are
+# used to verify the correctness of the LUFA library, and are
+# not intended to be modified or compiled by non-developers.
+
+all:
+
+%:
+ @echo Executing \"make $@\" on all LUFA build tests.
+ @echo
+ $(MAKE) -C BoardDriverTest $@
+ $(MAKE) -C BootloaderTest $@
+ $(MAKE) -C ModuleTest $@
+ $(MAKE) -C SingleUSBModeTest $@
+ $(MAKE) -C StaticAnalysisTest $@
+ @echo
+ @echo LUFA build test \"make $@\" operation complete.
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/HID_EEPROM_Loader/HID_EEPROM_Loader.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/HID_EEPROM_Loader/HID_EEPROM_Loader.c
new file mode 100644
index 000000000..7ee46b4db
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/HID_EEPROM_Loader/HID_EEPROM_Loader.c
@@ -0,0 +1,61 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Special application to extract an EEPROM image stored in FLASH memory, and
+ * copy it to the device EEPROM. This application is designed to be used with
+ * the HID build system module of LUFA to program the EEPROM of a target device
+ * that uses the HID bootloader protocol, which does not have native EEPROM
+ * programming support.
+ */
+
+#include <avr/io.h>
+#include <avr/eeprom.h>
+#include <avr/pgmspace.h>
+
+/* References to the binary EEPROM data linked in the AVR's FLASH memory space */
+extern const char _binary_InputEEData_bin_start[];
+extern const char _binary_InputEEData_bin_end[];
+extern const char _binary_InputEEData_bin_size[];
+
+/* Friendly names for the embedded binary data stored in FLASH memory space */
+#define InputEEData _binary_InputEEData_bin_start
+#define InputEEData_size ((int)_binary_InputEEData_bin_size)
+
+int main(void)
+{
+ /* Copy out the embedded EEPROM data from FLASH to EEPROM memory space */
+ for (uint16_t i = 0; i < InputEEData_size; i++)
+ eeprom_update_byte((uint8_t*)i, pgm_read_byte(&InputEEData[i]));
+
+ /* Infinite loop once complete */
+ for (;;);
+}
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/HID_EEPROM_Loader/makefile b/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/HID_EEPROM_Loader/makefile
new file mode 100644
index 000000000..9fd188c93
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/HID_EEPROM_Loader/makefile
@@ -0,0 +1,42 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2014.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+# --------------------------------------
+# LUFA Project Makefile.
+# --------------------------------------
+
+# Run "make help" for target help.
+
+MCU = at90usb1287
+ARCH = AVR8
+F_CPU = 1000000
+F_USB = $(F_CPU)
+OPTIMIZATION = s
+TARGET = HID_EEPROM_Loader
+SRC = $(TARGET).c
+LUFA_PATH = ../../../LUFA
+CC_FLAGS =
+LD_FLAGS =
+OBJECT_FILES = InputEEData.o
+
+# Default target
+all:
+
+# Determine the AVR sub-architecture of the build main application object file
+FIND_AVR_SUBARCH = avr$(shell avr-objdump -f $(TARGET).o | grep architecture | cut -d':' -f3 | cut -d',' -f1)
+
+# Create a linkable object file with the input binary EEPROM data stored in the FLASH section
+InputEEData.o: InputEEData.bin $(TARGET).o $(MAKEFILE_LIST)
+ @echo $(MSG_OBJCPY_CMD) Converting \"$<\" to a object file \"$@\"
+ avr-objcopy -I binary -O elf32-avr -B $(call FIND_AVR_SUBARCH) --rename-section .data=.progmem.data,contents,alloc,readonly,data $< $@
+
+# Include LUFA build script makefiles
+include $(LUFA_PATH)/Build/lufa_core.mk
+include $(LUFA_PATH)/Build/lufa_build.mk
+include $(LUFA_PATH)/Build/lufa_cppcheck.mk
+include $(LUFA_PATH)/Build/lufa_doxygen.mk
+include $(LUFA_PATH)/Build/lufa_hid.mk
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_atprogram.mk b/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_atprogram.mk
new file mode 100644
index 000000000..943383418
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_atprogram.mk
@@ -0,0 +1,103 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2014.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+
+LUFA_BUILD_MODULES += ATPROGRAM
+LUFA_BUILD_TARGETS += atprogram atprogram-ee
+LUFA_BUILD_MANDATORY_VARS += MCU TARGET
+LUFA_BUILD_OPTIONAL_VARS += ATPROGRAM_PROGRAMMER ATPROGRAM_INTERFACE ATPROGRAM_PORT
+LUFA_BUILD_PROVIDED_VARS +=
+LUFA_BUILD_PROVIDED_MACROS +=
+
+# -----------------------------------------------------------------------------
+# LUFA ATPROGRAM Programmer Buildsystem Makefile Module.
+# -----------------------------------------------------------------------------
+# DESCRIPTION:
+# Provides a set of targets to re-program a device using the Atmel atprogram
+# utility in AVR Studio 5.x and Atmel Studio 6.0 onwards.
+# -----------------------------------------------------------------------------
+# TARGETS:
+#
+# atprogram - Program target FLASH with application using
+# atprogram
+# atprogram-ee - Program target EEPROM with application data
+# using atprogram
+#
+# MANDATORY PARAMETERS:
+#
+# MCU - Microcontroller device model name
+# TARGET - Application name
+#
+# OPTIONAL PARAMETERS:
+#
+# ATPROGRAM_PROGRAMMER - Name of programming hardware to use
+# ATPROGRAM_INTERFACE - Name of programming interface to use
+# ATPROGRAM_PORT - Name of communication port to use
+#
+# PROVIDED VARIABLES:
+#
+# (None)
+#
+# PROVIDED MACROS:
+#
+# (None)
+#
+# -----------------------------------------------------------------------------
+
+SHELL = /bin/sh
+
+ERROR_IF_UNSET ?= $(if $(filter undefined, $(origin $(strip $(1)))), $(error Makefile $(strip $(1)) value not set))
+ERROR_IF_EMPTY ?= $(if $(strip $($(strip $(1)))), , $(error Makefile $(strip $(1)) option cannot be blank))
+ERROR_IF_NONBOOL ?= $(if $(filter Y N, $($(strip $(1)))), , $(error Makefile $(strip $(1)) option must be Y or N))
+
+# Default values of optionally user-supplied variables
+ATPROGRAM_PROGRAMMER ?= jtagice3
+ATPROGRAM_INTERFACE ?= jtag
+ATPROGRAM_PORT ?=
+
+# Sanity check user supplied values
+$(foreach MANDATORY_VAR, $(LUFA_BUILD_MANDATORY_VARS), $(call ERROR_IF_UNSET, $(MANDATORY_VAR)))
+$(call ERROR_IF_EMPTY, MCU)
+$(call ERROR_IF_EMPTY, TARGET)
+$(call ERROR_IF_EMPTY, ATPROGRAM_PROGRAMMER)
+$(call ERROR_IF_EMPTY, ATPROGRAM_INTERFACE)
+
+# Output Messages
+MSG_ATPROGRAM_CMD := ' [ATPRGRM] :'
+
+# Construct base atprogram command flags
+BASE_ATPROGRAM_FLAGS := --tool $(ATPROGRAM_PROGRAMMER) --interface $(ATPROGRAM_INTERFACE) --device $(MCU)
+ifneq ($(ATPROGRAM_PORT),)
+ BASE_ATPROGRAM_FLAGS += --port $(ATPROGRAM_PORT)
+endif
+
+# Construct the flags to use for the various memory spaces
+ifeq ($(ARCH), AVR8)
+ ATPROGRAM_FLASH_FLAGS := --chiperase --flash
+ ATPROGRAM_EEPROM_FLAGS := --eeprom
+else ifeq ($(ARCH), XMEGA)
+ ATPROGRAM_FLASH_FLAGS := --erase --flash
+ ATPROGRAM_EEPROM_FLAGS := --eeprom
+else ifeq ($(ARCH), UC3)
+ ATPROGRAM_FLASH_FLAGS := --erase
+ ATPROGRAM_EEPROM_FLAGS := --eeprom
+else
+ $(error Unsupported architecture "$(ARCH)")
+endif
+
+# Programs in the target FLASH memory using ATPROGRAM
+atprogram: $(TARGET).elf $(MAKEFILE_LIST)
+ @echo $(MSG_ATPROGRAM_CMD) Programming device \"$(MCU)\" FLASH using \"$(ATPROGRAM_PROGRAMMER)\"
+ atprogram $(BASE_ATPROGRAM_FLAGS) program $(ATPROGRAM_FLASH_FLAGS) --file $<
+
+# Programs in the target EEPROM memory using ATPROGRAM
+atprogram-ee: $(TARGET).elf $(MAKEFILE_LIST)
+ @echo $(MSG_ATPROGRAM_CMD) Programming device \"$(MCU)\" EEPROM using \"$(ATPROGRAM_PROGRAMMER)\"
+ atprogram $(BASE_ATPROGRAM_FLAGS) program $(ATPROGRAM_EEPROM_FLAGS) --file $<
+
+# Phony build targets for this module
+.PHONY: atprogram atprogram-ee
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_avrdude.mk b/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_avrdude.mk
new file mode 100644
index 000000000..4eff4181c
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_avrdude.mk
@@ -0,0 +1,86 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2014.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+
+LUFA_BUILD_MODULES += AVRDUDE
+LUFA_BUILD_TARGETS += avrdude avrdude-ee
+LUFA_BUILD_MANDATORY_VARS += MCU TARGET
+LUFA_BUILD_OPTIONAL_VARS += AVRDUDE_PROGRAMMER AVRDUDE_PORT AVRDUDE_FLAGS
+LUFA_BUILD_PROVIDED_VARS +=
+LUFA_BUILD_PROVIDED_MACROS +=
+
+# -----------------------------------------------------------------------------
+# LUFA AVRDUDE Programmer Buildsystem Makefile Module.
+# -----------------------------------------------------------------------------
+# DESCRIPTION:
+# Provides a set of targets to re-program a device using the open source
+# avr-dude utility.
+# -----------------------------------------------------------------------------
+# TARGETS:
+#
+# avrdude - Program target FLASH with application using
+# avrdude
+# avrdude-ee - Program target EEPROM with application data
+# using avrdude
+#
+# MANDATORY PARAMETERS:
+#
+# MCU - Microcontroller device model name
+# TARGET - Application name
+#
+# OPTIONAL PARAMETERS:
+#
+# AVRDUDE_PROGRAMMER - Name of programming hardware to use
+# AVRDUDE_PORT - Name of communication port to use
+# AVRDUDE_FLAGS - Flags to pass to avr-dude
+#
+# PROVIDED VARIABLES:
+#
+# (None)
+#
+# PROVIDED MACROS:
+#
+# (None)
+#
+# -----------------------------------------------------------------------------
+
+SHELL = /bin/sh
+
+ERROR_IF_UNSET ?= $(if $(filter undefined, $(origin $(strip $(1)))), $(error Makefile $(strip $(1)) value not set))
+ERROR_IF_EMPTY ?= $(if $(strip $($(strip $(1)))), , $(error Makefile $(strip $(1)) option cannot be blank))
+ERROR_IF_NONBOOL ?= $(if $(filter Y N, $($(strip $(1)))), , $(error Makefile $(strip $(1)) option must be Y or N))
+
+# Default values of optionally user-supplied variables
+AVRDUDE_PROGRAMMER ?= jtagicemkii
+AVRDUDE_PORT ?= usb
+AVRDUDE_FLAGS ?=
+
+# Sanity check user supplied values
+$(foreach MANDATORY_VAR, $(LUFA_BUILD_MANDATORY_VARS), $(call ERROR_IF_UNSET, $(MANDATORY_VAR)))
+$(call ERROR_IF_EMPTY, MCU)
+$(call ERROR_IF_EMPTY, TARGET)
+$(call ERROR_IF_EMPTY, AVRDUDE_PROGRAMMER)
+$(call ERROR_IF_EMPTY, AVRDUDE_PORT)
+
+# Output Messages
+MSG_AVRDUDE_CMD := ' [AVRDUDE] :'
+
+# Construct base avrdude command flags
+BASE_AVRDUDE_FLAGS := -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
+
+# Programs in the target FLASH memory using AVRDUDE
+avrdude: $(TARGET).hex $(MAKEFILE_LIST)
+ @echo $(MSG_AVRDUDE_CMD) Programming device \"$(MCU)\" FLASH using \"$(AVRDUDE_PROGRAMMER)\" on port \"$(AVRDUDE_PORT)\"
+ avrdude $(BASE_AVRDUDE_FLAGS) -U flash:w:$< $(AVRDUDE_FLAGS)
+
+# Programs in the target EEPROM memory using AVRDUDE
+avrdude-ee: $(TARGET).eep $(MAKEFILE_LIST)
+ @echo $(MSG_AVRDUDE_CMD) Programming device \"$(MCU)\" EEPROM using \"$(AVRDUDE_PROGRAMMER)\" on port \"$(AVRDUDE_PORT)\"
+ avrdude $(BASE_AVRDUDE_FLAGS) -U eeprom:w:$< $(AVRDUDE_FLAGS)
+
+# Phony build targets for this module
+.PHONY: avrdude avrdude-ee
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_build.mk b/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_build.mk
new file mode 100644
index 000000000..b9b144aee
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_build.mk
@@ -0,0 +1,351 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2014.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+
+LUFA_BUILD_MODULES += BUILD
+LUFA_BUILD_TARGETS += size symbol-sizes all lib elf bin hex lss clean mostlyclean
+LUFA_BUILD_MANDATORY_VARS += TARGET ARCH MCU SRC F_USB LUFA_PATH
+LUFA_BUILD_OPTIONAL_VARS += BOARD OPTIMIZATION C_STANDARD CPP_STANDARD F_CPU C_FLAGS CPP_FLAGS ASM_FLAGS CC_FLAGS LD_FLAGS OBJDIR OBJECT_FILES DEBUG_TYPE DEBUG_LEVEL LINKER_RELAXATIONS COMPILER_PATH
+LUFA_BUILD_PROVIDED_VARS +=
+LUFA_BUILD_PROVIDED_MACROS +=
+
+# -----------------------------------------------------------------------------
+# LUFA GCC Compiler Buildsystem Makefile Module.
+# -----------------------------------------------------------------------------
+# DESCRIPTION:
+# Provides a set of targets to build a C, C++ and/or Assembly application
+# via the AVR-GCC compiler.
+# -----------------------------------------------------------------------------
+# TARGETS:
+#
+# size - List built application size
+# symbol-sizes - Print application symbols from the binary ELF
+# file as a list sorted by size in bytes
+# all - Build application and list size
+# lib - Build and archive source files into a library
+# elf - Build application ELF debug object file
+# bin - Build application BIN binary object file
+# hex - Build application HEX object file
+# lss - Build application LSS assembly listing file
+# clean - Remove all project intermediary and binary
+# output files
+# mostlyclean - Remove intermediary output files, but
+# preserve binaries
+# <filename>.s - Compile C/C++ source file into an assembly file
+# for manual code inspection
+#
+# MANDATORY PARAMETERS:
+#
+# TARGET - Application name
+# ARCH - Device architecture name
+# MCU - Microcontroller device model name
+# SRC - List of input source files (*.c, *.cpp, *.S)
+# F_USB - Speed of the input clock of the USB controller
+# in Hz
+# LUFA_PATH - Path to the LUFA library core
+#
+# OPTIONAL PARAMETERS:
+#
+# BOARD - LUFA board hardware
+# OPTIMIZATION - Optimization level
+# C_STANDARD - C Language Standard to use
+# CPP_STANDARD - C++ Language Standard to use
+# F_CPU - Speed of the CPU, in Hz
+# C_FLAGS - Flags to pass to the C compiler only
+# CPP_FLAGS - Flags to pass to the C++ compiler only
+# ASM_FLAGS - Flags to pass to the assembler only
+# CC_FLAGS - Common flags to pass to the C/C++ compiler and
+# assembler
+# LD_FLAGS - Flags to pass to the linker
+# LINKER_RELAXATIONS - Enable or disable linker relaxations to
+# decrease binary size (note: can cause link
+# failures on systems with an unpatched binutils)
+# OBJDIR - Directory for the output object and dependency
+# files; if equal to ".", the output files will
+# be generated in the same folder as the sources
+# OBJECT_FILES - Extra object files to link in to the binaries
+# DEBUG_FORMAT - Format of the debugging information to
+# generate in the compiled object files
+# DEBUG_LEVEL - Level the debugging information to generate in
+# the compiled object files
+# COMPILER_PATH - Location of the GCC toolchain to use
+#
+# PROVIDED VARIABLES:
+#
+# (None)
+#
+# PROVIDED MACROS:
+#
+# (None)
+#
+# -----------------------------------------------------------------------------
+
+SHELL = /bin/sh
+
+ERROR_IF_UNSET ?= $(if $(filter undefined, $(origin $(strip $(1)))), $(error Makefile $(strip $(1)) value not set))
+ERROR_IF_EMPTY ?= $(if $(strip $($(strip $(1)))), , $(error Makefile $(strip $(1)) option cannot be blank))
+ERROR_IF_NONBOOL ?= $(if $(filter Y N, $($(strip $(1)))), , $(error Makefile $(strip $(1)) option must be Y or N))
+
+# Default values of optionally user-supplied variables
+COMPILER_PATH ?=
+BOARD ?= NONE
+OPTIMIZATION ?= s
+F_CPU ?=
+C_STANDARD ?= gnu99
+CPP_STANDARD ?= gnu++98
+C_FLAGS ?=
+CPP_FLAGS ?=
+ASM_FLAGS ?=
+CC_FLAGS ?=
+OBJDIR ?= .
+OBJECT_FILES ?=
+DEBUG_FORMAT ?= dwarf-2
+DEBUG_LEVEL ?= 2
+LINKER_RELAXATIONS ?= Y
+
+# Sanity check user supplied values
+$(foreach MANDATORY_VAR, $(LUFA_BUILD_MANDATORY_VARS), $(call ERROR_IF_UNSET, $(MANDATORY_VAR)))
+$(call ERROR_IF_EMPTY, MCU)
+$(call ERROR_IF_EMPTY, TARGET)
+$(call ERROR_IF_EMPTY, ARCH)
+$(call ERROR_IF_EMPTY, F_USB)
+$(call ERROR_IF_EMPTY, LUFA_PATH)
+$(call ERROR_IF_EMPTY, BOARD)
+$(call ERROR_IF_EMPTY, OPTIMIZATION)
+$(call ERROR_IF_EMPTY, C_STANDARD)
+$(call ERROR_IF_EMPTY, CPP_STANDARD)
+$(call ERROR_IF_EMPTY, OBJDIR)
+$(call ERROR_IF_EMPTY, DEBUG_FORMAT)
+$(call ERROR_IF_EMPTY, DEBUG_LEVEL)
+$(call ERROR_IF_NONBOOL, LINKER_RELAXATIONS)
+
+# Determine the utility prefix to use for the selected architecture
+ifeq ($(ARCH), AVR8)
+ CROSS := $(COMPILER_PATH)avr
+else ifeq ($(ARCH), XMEGA)
+ CROSS := $(COMPILER_PATH)avr
+ $(warning The XMEGA device support is currently EXPERIMENTAL (incomplete and/or non-functional), and is included for preview purposes only.)
+else ifeq ($(ARCH), UC3)
+ CROSS := $(COMPILER_PATH)avr32
+ $(warning The UC3 device support is currently EXPERIMENTAL (incomplete and/or non-functional), and is included for preview purposes only.)
+else
+ $(error Unsupported architecture "$(ARCH)")
+endif
+
+# Output Messages
+MSG_INFO_MESSAGE := ' [INFO] :'
+MSG_COMPILE_CMD := ' [GCC] :'
+MSG_ASSEMBLE_CMD := ' [GAS] :'
+MSG_NM_CMD := ' [NM] :'
+MSG_REMOVE_CMD := ' [RM] :'
+MSG_LINK_CMD := ' [LNK] :'
+MSG_ARCHIVE_CMD := ' [AR] :'
+MSG_SIZE_CMD := ' [SIZE] :'
+MSG_OBJCPY_CMD := ' [OBJCPY] :'
+MSG_OBJDMP_CMD := ' [OBJDMP] :'
+
+# Convert input source file list to differentiate them by type
+C_SOURCE := $(filter %.c, $(SRC))
+CPP_SOURCE := $(filter %.cpp, $(SRC))
+ASM_SOURCE := $(filter %.S, $(SRC))
+
+# Create a list of unknown source file types, if any are found throw an error
+UNKNOWN_SOURCE := $(filter-out $(C_SOURCE) $(CPP_SOURCE) $(ASM_SOURCE), $(SRC))
+ifneq ($(UNKNOWN_SOURCE),)
+ $(error Unknown input source file formats: $(UNKNOWN_SOURCE))
+endif
+
+# Convert input source filenames into a list of required output object files
+OBJECT_FILES += $(addsuffix .o, $(basename $(SRC)))
+
+# Check if an output object file directory was specified instead of the input file location
+ifneq ($(OBJDIR),.)
+ # Prefix all the object filenames with the output object file directory path
+ OBJECT_FILES := $(addprefix $(patsubst %/,%,$(OBJDIR))/, $(notdir $(OBJECT_FILES)))
+
+ # Check if any object file (without path) appears more than once in the object file list
+ ifneq ($(words $(sort $(OBJECT_FILES))), $(words $(OBJECT_FILES)))
+ $(error Cannot build with OBJDIR parameter set - one or more object file name is not unique)
+ endif
+
+ # Create the output object file directory if it does not exist and add it to the virtual path list
+ $(shell mkdir $(OBJDIR) 2> /dev/null)
+ VPATH += $(dir $(SRC))
+endif
+
+# Create a list of dependency files from the list of object files
+DEPENDENCY_FILES := $(OBJECT_FILES:%.o=%.d)
+
+# Create a list of common flags to pass to the compiler/linker/assembler
+BASE_CC_FLAGS := -pipe -g$(DEBUG_FORMAT) -g$(DEBUG_LEVEL)
+ifeq ($(ARCH), AVR8)
+ BASE_CC_FLAGS += -mmcu=$(MCU) -fshort-enums -fno-inline-small-functions -fpack-struct
+else ifeq ($(ARCH), XMEGA)
+ BASE_CC_FLAGS += -mmcu=$(MCU) -fshort-enums -fno-inline-small-functions -fpack-struct
+else ifeq ($(ARCH), UC3)
+ BASE_CC_FLAGS += -mpart=$(MCU:at32%=%) -masm-addr-pseudos
+endif
+BASE_CC_FLAGS += -Wall -fno-strict-aliasing -funsigned-char -funsigned-bitfields -ffunction-sections
+BASE_CC_FLAGS += -I. -I$(patsubst %/,%,$(LUFA_PATH))/..
+BASE_CC_FLAGS += -DARCH=ARCH_$(ARCH) -DBOARD=BOARD_$(BOARD) -DF_USB=$(F_USB)UL
+ifneq ($(F_CPU),)
+ BASE_CC_FLAGS += -DF_CPU=$(F_CPU)UL
+endif
+ifeq ($(LINKER_RELAXATIONS), Y)
+BASE_CC_FLAGS += -mrelax
+endif
+
+# This flag is required for bootloaders as GCC will emit invalid jump table
+# assembly code for devices with large amounts of flash; the jump table target
+# is extracted from FLASH without using the correct ELPM instruction, resulting
+# in a pseudo-random jump target.
+BASE_CC_FLAGS += -fno-jump-tables
+
+# Additional language specific compiler flags
+BASE_C_FLAGS := -x c -O$(OPTIMIZATION) -std=$(C_STANDARD) -Wstrict-prototypes
+BASE_CPP_FLAGS := -x c++ -O$(OPTIMIZATION) -std=$(CPP_STANDARD)
+BASE_ASM_FLAGS := -x assembler-with-cpp
+
+# Create a list of flags to pass to the linker
+BASE_LD_FLAGS := -lm -Wl,-Map=$(TARGET).map,--cref -Wl,--gc-sections
+ifeq ($(LINKER_RELAXATIONS), Y)
+ BASE_LD_FLAGS += -Wl,--relax
+endif
+ifeq ($(ARCH), AVR8)
+ BASE_LD_FLAGS += -mmcu=$(MCU)
+else ifeq ($(ARCH), XMEGA)
+ BASE_LD_FLAGS += -mmcu=$(MCU)
+else ifeq ($(ARCH), UC3)
+ BASE_LD_FLAGS += -mpart=$(MCU:at32%=%) --rodata-writable --direct-data
+endif
+
+# Determine flags to pass to the size utility based on its reported features (only invoke if size target required)
+# and on an architecture where this non-standard patch is available
+ifneq ($(ARCH), UC3)
+size: SIZE_MCU_FLAG := $(shell $(CROSS)-size --help | grep -- --mcu > /dev/null && echo --mcu=$(MCU) )
+size: SIZE_FORMAT_FLAG := $(shell $(CROSS)-size --help | grep -- --format=.*avr > /dev/null && echo --format=avr )
+endif
+
+# Pre-build informational target, to give compiler and project name information when building
+build_begin:
+ @echo $(MSG_INFO_MESSAGE) Begin compilation of project \"$(TARGET)\"...
+ @echo ""
+ @$(CROSS)-gcc --version
+
+# Post-build informational target, to project name information when building has completed
+build_end:
+ @echo $(MSG_INFO_MESSAGE) Finished building project \"$(TARGET)\".
+
+# Prints size information of a compiled application (FLASH, RAM and EEPROM usages)
+size: $(TARGET).elf
+ @echo $(MSG_SIZE_CMD) Determining size of \"$<\"
+ @echo ""
+ $(CROSS)-size $(SIZE_MCU_FLAG) $(SIZE_FORMAT_FLAG) $<
+
+# Prints size information on the symbols within a compiled application in decimal bytes
+symbol-sizes: $(TARGET).elf
+ @echo $(MSG_NM_CMD) Extracting \"$<\" symbols with decimal byte sizes
+ $(CROSS)-nm --size-sort --demangle --radix=d $<
+
+# Cleans intermediary build files, leaving only the compiled application files
+mostlyclean:
+ @echo $(MSG_REMOVE_CMD) Removing object files of \"$(TARGET)\"
+ rm -f $(OBJECT_FILES)
+ @echo $(MSG_REMOVE_CMD) Removing dependency files of \"$(TARGET)\"
+ rm -f $(DEPENDENCY_FILES)
+
+# Cleans all build files, leaving only the original source code
+clean: mostlyclean
+ @echo $(MSG_REMOVE_CMD) Removing output files of \"$(TARGET)\"
+ rm -f $(TARGET).elf $(TARGET).hex $(TARGET).bin $(TARGET).eep $(TARGET).map $(TARGET).lss $(TARGET).sym lib$(TARGET).a
+
+# Performs a complete build of the user application and prints size information afterwards
+all: build_begin elf hex bin lss sym size build_end
+
+# Helper targets, to build a specific type of output file without having to know the project target name
+lib: lib$(TARGET).a
+elf: $(TARGET).elf
+hex: $(TARGET).hex $(TARGET).eep
+bin: $(TARGET).bin
+lss: $(TARGET).lss
+sym: $(TARGET).sym
+
+# Default target to *create* the user application's specified source files; if this rule is executed by
+# make, the input source file doesn't exist and an error needs to be presented to the user
+$(SRC):
+ $(error Source file does not exist: $@)
+
+# Compiles an input C source file and generates an assembly listing for it
+%.s: %.c $(MAKEFILE_LIST)
+ @echo $(MSG_COMPILE_CMD) Generating assembly from C file \"$(notdir $<)\"
+ $(CROSS)-gcc -S $(BASE_CC_FLAGS) $(BASE_C_FLAGS) $(CC_FLAGS) $(C_FLAGS) $< -o $@
+
+# Compiles an input C++ source file and generates an assembly listing for it
+%.s: %.cpp $(MAKEFILE_LIST)
+ @echo $(MSG_COMPILE_CMD) Generating assembly from C++ file \"$(notdir $<)\"
+ $(CROSS)-gcc -S $(BASE_CC_FLAGS) $(BASE_CPP_FLAGS) $(CC_FLAGS) $(CPP_FLAGS) $< -o $@
+
+# Compiles an input C source file and generates a linkable object file for it
+$(OBJDIR)/%.o: %.c $(MAKEFILE_LIST)
+ @echo $(MSG_COMPILE_CMD) Compiling C file \"$(notdir $<)\"
+ $(CROSS)-gcc -c $(BASE_CC_FLAGS) $(BASE_C_FLAGS) $(CC_FLAGS) $(C_FLAGS) -MMD -MP -MF $(@:%.o=%.d) $< -o $@
+
+# Compiles an input C++ source file and generates a linkable object file for it
+$(OBJDIR)/%.o: %.cpp $(MAKEFILE_LIST)
+ @echo $(MSG_COMPILE_CMD) Compiling C++ file \"$(notdir $<)\"
+ $(CROSS)-gcc -c $(BASE_CC_FLAGS) $(BASE_CPP_FLAGS) $(CC_FLAGS) $(CPP_FLAGS) -MMD -MP -MF $(@:%.o=%.d) $< -o $@
+
+# Assembles an input ASM source file and generates a linkable object file for it
+$(OBJDIR)/%.o: %.S $(MAKEFILE_LIST)
+ @echo $(MSG_ASSEMBLE_CMD) Assembling \"$(notdir $<)\"
+ $(CROSS)-gcc -c $(BASE_CC_FLAGS) $(BASE_ASM_FLAGS) $(CC_FLAGS) $(ASM_FLAGS) -MMD -MP -MF $(@:%.o=%.d) $< -o $@
+
+# Generates a library archive file from the user application, which can be linked into other applications
+.PRECIOUS : $(OBJECT_FILES)
+.SECONDARY : %.a
+%.a: $(OBJECT_FILES)
+ @echo $(MSG_ARCHIVE_CMD) Archiving object files into \"$@\"
+ $(CROSS)-ar rcs $@ $(OBJECT_FILES)
+
+# Generates an ELF debug file from the user application, which can be further processed for FLASH and EEPROM data
+# files, or used for programming and debugging directly
+.PRECIOUS : $(OBJECT_FILES)
+.SECONDARY : %.elf
+%.elf: $(OBJECT_FILES)
+ @echo $(MSG_LINK_CMD) Linking object files into \"$@\"
+ $(CROSS)-gcc $^ -o $@ $(BASE_LD_FLAGS) $(LD_FLAGS)
+
+# Extracts out the loadable FLASH memory data from the project ELF file, and creates an Intel HEX format file of it
+%.hex: %.elf
+ @echo $(MSG_OBJCPY_CMD) Extracting HEX file data from \"$<\"
+ $(CROSS)-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature $< $@
+
+# Extracts out the loadable FLASH memory data from the project ELF file, and creates an Binary format file of it
+%.bin: %.elf
+ @echo $(MSG_OBJCPY_CMD) Extracting BIN file data from \"$<\"
+ $(CROSS)-objcopy -O binary -R .eeprom -R .fuse -R .lock -R .signature $< $@
+
+# Extracts out the loadable EEPROM memory data from the project ELF file, and creates an Intel HEX format file of it
+%.eep: %.elf
+ @echo $(MSG_OBJCPY_CMD) Extracting EEP file data from \"$<\"
+ $(CROSS)-objcopy -O ihex -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings $< $@ || exit 0
+
+# Creates an assembly listing file from an input project ELF file, containing interleaved assembly and source data
+%.lss: %.elf
+ @echo $(MSG_OBJDMP_CMD) Extracting LSS file data from \"$<\"
+ $(CROSS)-objdump -h -d -S -z $< > $@
+
+# Creates a symbol file listing the loadable and discarded symbols from an input project ELF file
+%.sym: %.elf
+ @echo $(MSG_NM_CMD) Extracting SYM file data from \"$<\"
+ $(CROSS)-nm -n $< > $@
+
+# Include build dependency files
+-include $(DEPENDENCY_FILES)
+
+# Phony build targets for this module
+.PHONY: build_begin build_end size symbol-sizes lib elf hex lss clean mostlyclean
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_core.mk b/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_core.mk
new file mode 100644
index 000000000..7d974664b
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_core.mk
@@ -0,0 +1,175 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2014.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+
+LUFA_BUILD_MODULES += CORE
+LUFA_BUILD_TARGETS += help list_targets list_modules list_mandatory list_optional list_provided list_macros
+LUFA_BUILD_MANDATORY_VARS +=
+LUFA_BUILD_OPTIONAL_VARS +=
+LUFA_BUILD_PROVIDED_VARS +=
+LUFA_BUILD_PROVIDED_MACROS +=
+
+# -----------------------------------------------------------------------------
+# LUFA Core Build System Makefile Module.
+# -----------------------------------------------------------------------------
+# DESCRIPTION:
+# Provides a set of core build targets for the LUFA build system
+# -----------------------------------------------------------------------------
+# TARGETS:
+#
+# help - Build system help
+# list_targets - List all build targets
+# list_modules - List all build modules
+# list_mandatory - List all mandatory make variables required by
+# the included build modules of the application
+# list_optional - List all optional make variables required by
+# the included build modules of the application
+# list_provided - List all provided make variables from the
+# included build modules of the application
+# list_macros - List all provided make macros from the
+# included build modules of the application
+#
+# MANDATORY PARAMETERS:
+#
+# (None)
+#
+# OPTIONAL PARAMETERS:
+#
+# (None)
+#
+# PROVIDED VARIABLES:
+#
+# (None)
+#
+# PROVIDED MACROS:
+#
+# (None)
+#
+# -----------------------------------------------------------------------------
+
+SHELL = /bin/sh
+
+# Converts a given input to a printable output using "(None)" if no items are in the list
+CONVERT_TO_PRINTABLE = $(if $(strip $(1)), $(1), (None))
+
+
+# Build sorted and filtered lists of the included build module data
+SORTED_LUFA_BUILD_MODULES = $(sort $(LUFA_BUILD_MODULES))
+SORTED_LUFA_BUILD_TARGETS = $(sort $(LUFA_BUILD_TARGETS))
+SORTED_LUFA_MANDATORY_VARS = $(sort $(LUFA_BUILD_MANDATORY_VARS))
+SORTED_LUFA_OPTIONAL_VARS = $(filter-out $(SORTED_LUFA_MANDATORY_VARS), $(sort $(LUFA_BUILD_OPTIONAL_VARS)))
+SORTED_LUFA_PROVIDED_VARS = $(sort $(LUFA_BUILD_PROVIDED_VARS))
+SORTED_LUFA_PROVIDED_MACROS = $(sort $(LUFA_BUILD_PROVIDED_MACROS))
+
+# Create printable versions of the sorted build module data (use "(None)" when no data is available)
+PRINTABLE_LUFA_BUILD_MODULES = $(call CONVERT_TO_PRINTABLE, $(SORTED_LUFA_BUILD_MODULES))
+PRINTABLE_LUFA_BUILD_TARGETS = $(call CONVERT_TO_PRINTABLE, $(SORTED_LUFA_BUILD_TARGETS))
+PRINTABLE_LUFA_MANDATORY_VARS = $(call CONVERT_TO_PRINTABLE, $(SORTED_LUFA_MANDATORY_VARS))
+PRINTABLE_LUFA_OPTIONAL_VARS = $(call CONVERT_TO_PRINTABLE, $(SORTED_LUFA_OPTIONAL_VARS))
+PRINTABLE_LUFA_PROVIDED_VARS = $(call CONVERT_TO_PRINTABLE, $(SORTED_LUFA_PROVIDED_VARS))
+PRINTABLE_LUFA_PROVIDED_MACROS = $(call CONVERT_TO_PRINTABLE, $(SORTED_LUFA_PROVIDED_MACROS))
+
+help:
+ @echo "==================================================================="
+ @echo " LUFA Build System 2.0 "
+ @echo " (C) Dean Camera, 2014 { dean @ fourwalledcubicle . com } "
+ @echo "==================================================================="
+ @echo "DESCRIPTION: "
+ @echo " This build system is a set of makefile modules for (GNU) Make, to "
+ @echo " provide a simple system for building LUFA powered applications. "
+ @echo " Each makefile module can be included from within a user makefile, "
+ @echo " to expose the build rules documented in the comments at the top of"
+ @echo " each build module. "
+ @echo " "
+ @echo "USAGE: "
+ @echo " To execute a rule, define all variables indicated in the desired "
+ @echo " module as a required parameter before including the build module "
+ @echo " in your project makefile. Parameters marked as optional will "
+ @echo " assume a default value in the modules if not user-assigned. "
+ @echo " "
+ @echo " By default the target output shows both a friendly summary, as "
+ @echo " well as the actual invoked command. To suppress the output of the "
+ @echo " invoked commands and show only the friendly command output, run "
+ @echo " make with the \"-s\" switch added before the target(s). "
+ @echo " "
+ @echo "SEE ALSO: "
+ @echo " For more information, see the 'Build System' chapter of the LUFA "
+ @echo " project documentation. "
+ @echo "==================================================================="
+ @echo " "
+ @echo " Currently used build system modules in this application: "
+ @echo " "
+ @printf " %b" "$(PRINTABLE_LUFA_BUILD_MODULES:%= - %\n)"
+ @echo " "
+ @echo " "
+ @echo " Currently available build targets in this application: "
+ @echo " "
+ @printf " %b" "$(PRINTABLE_LUFA_BUILD_TARGETS:%= - %\n)"
+ @echo " "
+ @echo " "
+ @echo " Mandatory variables required by the selected build Modules: "
+ @echo " "
+ @printf " %b" "$(PRINTABLE_LUFA_MANDATORY_VARS:%= - %\n)"
+ @echo " "
+ @echo " "
+ @echo " Optional variables required by the selected build Modules: "
+ @echo " "
+ @printf " %b" "$(PRINTABLE_LUFA_OPTIONAL_VARS:%= - %\n)"
+ @echo " "
+ @echo " "
+ @echo " Variables provided by the selected build Modules: "
+ @echo " "
+ @printf " %b" "$(PRINTABLE_LUFA_PROVIDED_VARS:%= - %\n)"
+ @echo " "
+ @echo " "
+ @echo " Macros provided by the selected build Modules: "
+ @echo " "
+ @printf " %b" "$(PRINTABLE_LUFA_PROVIDED_MACROS:%= - %\n)"
+ @echo " "
+ @echo "==================================================================="
+ @echo " The LUFA BuildSystem 2.0 - Powered By Positive Thinking (tm) "
+ @echo "==================================================================="
+
+# Lists build modules included by the project makefile, in alphabetical order
+list_modules:
+ @echo Currently Used Build System Modules:
+ @printf " %b" "$(PRINTABLE_LUFA_BUILD_MODULES:%= - %\n)"
+
+# Lists build targets included by the project makefile, in alphabetical order
+list_targets:
+ @echo Currently Available Build Targets:
+ @printf " %b" "$(PRINTABLE_LUFA_BUILD_TARGETS:%= - %\n)"
+
+# Lists mandatory variables that must be set by the project makefile, in alphabetical order
+list_mandatory:
+ @echo Mandatory Variables for Included Modules:
+ @printf " %b" "$(PRINTABLE_LUFA_MANDATORY_VARS:%= - %\n)"
+
+# Lists optional variables that must be set by the project makefile, in alphabetical order
+list_optional:
+ @echo Optional Variables for Included Modules:
+ @printf " %b" "$(PRINTABLE_LUFA_OPTIONAL_VARS:%= - %\n)"
+
+# Lists variables provided by the included build modules, in alphabetical order
+list_provided:
+ @echo Variables Provided by the Included Modules:
+ @printf " %b" "$(PRINTABLE_LUFA_PROVIDED_VARS:%= - %\n)"
+
+# Lists macros provided by the included build modules, in alphabetical order
+list_macros:
+ @echo Macros Provided by the Included Modules:
+ @printf " %b" "$(PRINTABLE_LUFA_PROVIDED_MACROS:%= - %\n)"
+
+# Disable default in-built make rules (those that are needed are explicitly
+# defined, and doing so has performance benefits when recursively building)
+ifeq ($(filter -r,$(MAKEFLAGS)),)
+ MAKEFLAGS += -r
+endif
+.SUFFIXES:
+
+# Phony build targets for this module
+.PHONY: help list_modules list_targets list_mandatory list_optional list_provided list_macros
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_cppcheck.mk b/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_cppcheck.mk
new file mode 100644
index 000000000..0b9b61164
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_cppcheck.mk
@@ -0,0 +1,107 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2014.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+
+LUFA_BUILD_MODULES += CPPCHECK
+LUFA_BUILD_TARGETS += cppcheck cppcheck-config
+LUFA_BUILD_MANDATORY_VARS += SRC
+LUFA_BUILD_OPTIONAL_VARS += CPPCHECK_INCLUDES CPPCHECK_EXCLUDES CPPCHECK_MSG_TEMPLATE CPPCHECK_ENABLE \
+ CPPCHECK_SUPPRESS CPPCHECK_FAIL_ON_WARNING CPPCHECK_QUIET CPPCHECK_FLAGS
+LUFA_BUILD_PROVIDED_VARS +=
+LUFA_BUILD_PROVIDED_MACROS +=
+
+# -----------------------------------------------------------------------------
+# LUFA CPPCheck Buildsystem Makefile Module.
+# -----------------------------------------------------------------------------
+# DESCRIPTION:
+# Provides a set of targets to scan a project with the free "cppcheck" static
+# analysis tool, to check for code errors at runtime
+# (see http://cppcheck.sourceforge.net).
+# -----------------------------------------------------------------------------
+# TARGETS:
+#
+# cppcheck - Scan the project with CPPCheck
+# cppcheck-config - Use CPPCheck to look for missing include files
+#
+# MANDATORY PARAMETERS:
+#
+# SRC - List of source files to statically analyze
+#
+# OPTIONAL PARAMETERS:
+#
+# CPPCHECK_INCLUDES - Extra include paths to search for missing
+# header files
+# CPPCHECK_EXCLUDES - Source file paths to exclude checking (can be
+# a path fragment if desired)
+# CPPCHECK_MSG_TEMPLATE - Template for cppcheck error and warning output
+# CPPCHECK_ENABLE - General cppcheck category checks to enable
+# CPPCHECK_SUPPRESS - Specific cppcheck warnings to disable by ID
+# CPPCHECK_FAIL_ON_WARNING - Set to Y to fail the build on cppcheck
+# warnings, N to continue even if warnings occur
+# CPPCHECK_QUIET - Enable cppcheck verbose or quiet output mode
+# CPPCHECK_FLAGS - Additional flags to pass to cppcheck
+#
+# PROVIDED VARIABLES:
+#
+# (None)
+#
+# PROVIDED MACROS:
+#
+# (None)
+#
+# -----------------------------------------------------------------------------
+
+SHELL = /bin/sh
+
+ERROR_IF_UNSET ?= $(if $(filter undefined, $(origin $(strip $(1)))), $(error Makefile $(strip $(1)) value not set))
+ERROR_IF_EMPTY ?= $(if $(strip $($(strip $(1)))), , $(error Makefile $(strip $(1)) option cannot be blank))
+ERROR_IF_NONBOOL ?= $(if $(filter Y N, $($(strip $(1)))), , $(error Makefile $(strip $(1)) option must be Y or N))
+
+# Default values of optionally user-supplied variables
+CPPCHECK_INCLUDES ?=
+CPPCHECK_EXCLUDES ?=
+CPPCHECK_MSG_TEMPLATE ?= {file}:{line}: {severity} ({id}): {message}
+CPPCHECK_ENABLE ?= all
+CPPCHECK_SUPPRESS ?= variableScope missingInclude
+CPPCHECK_FAIL_ON_WARNING ?= Y
+CPPCHECK_QUIET ?= Y
+CPPCHECK_FLAGS ?=
+
+# Sanity check user supplied values
+$(foreach MANDATORY_VAR, $(LUFA_BUILD_MANDATORY_VARS), $(call ERROR_IF_UNSET, $(MANDATORY_VAR)))
+$(call ERROR_IF_EMPTY, SRC)
+$(call ERROR_IF_EMPTY, CPPCHECK_MSG_TEMPLATE)
+$(call ERROR_IF_EMPTY, CPPCHECK_ENABLE)
+$(call ERROR_IF_NONBOOL, CPPCHECK_FAIL_ON_WARNING)
+$(call ERROR_IF_NONBOOL, CPPCHECK_QUIET)
+
+# Build a default argument list for cppcheck
+BASE_CPPCHECK_FLAGS := --template="$(CPPCHECK_MSG_TEMPLATE)" $(CPPCHECK_INCLUDES:%=-I%) $(CPPCHECK_EXCLUDES:%=-i%) --inline-suppr --force --std=c99
+
+# Sanity check parameters and construct additional command line arguments to cppcheck
+ifeq ($(CPPCHECK_FAIL_ON_WARNING), Y)
+ BASE_CPPCHECK_FLAGS += --error-exitcode=1
+endif
+ifeq ($(CPPCHECK_QUIET), Y)
+ BASE_CPPCHECK_FLAGS += --quiet
+endif
+
+# Output Messages
+MSG_CPPCHECK_CMD := ' [CPPCHECK]:'
+
+# Checks the CPPCheck configuration as used in the user project, to determine if any paths are missing or invalid
+cppcheck-config: $(MAKEFILE_LIST)
+ @echo $(MSG_CPPCHECK_CMD) Checking cppcheck configuration check on source files
+ cppcheck $(BASE_CPPCHECK_FLAGS) --check-config $(CPPCHECK_FLAGS) $(SRC)
+
+# Runs a static analysis using CPPCheck to determine if there are any issues
+cppcheck: $(MAKEFILE_LIST)
+ @echo $(MSG_CPPCHECK_CMD) Performing static analysis on source files
+ cppcheck $(BASE_CPPCHECK_FLAGS) --enable=$(CPPCHECK_ENABLE) $(CPPCHECK_SUPPRESS:%=--suppress=%) $(CPPCHECK_FLAGS) $(SRC)
+
+# Phony build targets for this module
+.PHONY: cppcheck-config cppcheck
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_dfu.mk b/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_dfu.mk
new file mode 100644
index 000000000..956adc8ba
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_dfu.mk
@@ -0,0 +1,95 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2014.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+
+LUFA_BUILD_MODULES += DFU
+LUFA_BUILD_TARGETS += flip flip-ee dfu dfu-ee
+LUFA_BUILD_MANDATORY_VARS += MCU TARGET
+LUFA_BUILD_OPTIONAL_VARS +=
+LUFA_BUILD_PROVIDED_VARS +=
+LUFA_BUILD_PROVIDED_MACROS +=
+
+# -----------------------------------------------------------------------------
+# LUFA DFU Bootloader Buildsystem Makefile Module.
+# -----------------------------------------------------------------------------
+# DESCRIPTION:
+# Provides a set of targets to re-program a device currently running a DFU
+# class bootloader with a project's FLASH and EEPROM files.
+# -----------------------------------------------------------------------------
+# TARGETS:
+#
+# flip - Program FLASH into target via Atmel FLIP
+# flip-ee - Program EEPROM into target via Atmel FLIP
+# dfu - Program FLASH into target via dfu-programmer
+# dfu-ee - Program EEPROM into target via dfu-programmer
+#
+# MANDATORY PARAMETERS:
+#
+# MCU - Microcontroller device model name
+# TARGET - Application name
+#
+# OPTIONAL PARAMETERS:
+#
+# (None)
+#
+# PROVIDED VARIABLES:
+#
+# (None)
+#
+# PROVIDED MACROS:
+#
+# (None)
+#
+# -----------------------------------------------------------------------------
+
+SHELL = /bin/sh
+
+ERROR_IF_UNSET ?= $(if $(filter undefined, $(origin $(strip $(1)))), $(error Makefile $(strip $(1)) value not set))
+ERROR_IF_EMPTY ?= $(if $(strip $($(strip $(1)))), , $(error Makefile $(strip $(1)) option cannot be blank))
+ERROR_IF_NONBOOL ?= $(if $(filter Y N, $($(strip $(1)))), , $(error Makefile $(strip $(1)) option must be Y or N))
+
+# Sanity-check values of mandatory user-supplied variables
+$(foreach MANDATORY_VAR, $(LUFA_BUILD_MANDATORY_VARS), $(call ERROR_IF_UNSET, $(MANDATORY_VAR)))
+$(call ERROR_IF_EMPTY, MCU)
+$(call ERROR_IF_EMPTY, TARGET)
+
+# Output Messages
+MSG_COPY_CMD := ' [CP] :'
+MSG_REMOVE_CMD := ' [RM] :'
+MSG_DFU_CMD := ' [DFU] :'
+
+# Programs in the target FLASH memory using BATCHISP, the command line tool used by FLIP
+flip: $(TARGET).hex $(MAKEFILE_LIST)
+ @echo $(MSG_DFU_CMD) Programming FLASH with batchisp using \"$<\"
+ batchisp -hardware usb -device $(MCU) -operation erase f loadbuffer $< program
+ batchisp -hardware usb -device $(MCU) -operation start reset 0
+
+# Programs in the target EEPROM memory using BATCHISP, the command line tool used by FLIP
+flip-ee: $(TARGET).eep $(MAKEFILE_LIST)
+ @echo $(MSG_COPY_CMD) Copying EEP file to temporary file \"$<.hex\"
+ cp $< $<.hex
+ @echo $(MSG_DFU_CMD) Programming EEPROM with batchisp using \"$<.hex\"
+ batchisp -hardware usb -device $(MCU) -operation memory EEPROM loadbuffer $<.hex program
+ batchisp -hardware usb -device $(MCU) -operation start reset 0
+ @echo $(MSG_REMOVE_CMD) Removing temporary file \"$<.hex\"
+ rm $<.hex
+
+# Programs in the target FLASH memory using DFU-PROGRAMMER
+dfu: $(TARGET).hex $(MAKEFILE_LIST)
+ @echo $(MSG_DFU_CMD) Programming FLASH with dfu-programmer using \"$<\"
+ dfu-programmer $(MCU) erase
+ dfu-programmer $(MCU) flash $<
+ dfu-programmer $(MCU) reset
+
+# Programs in the target EEPROM memory using DFU-PROGRAMMER
+dfu-ee: $(TARGET).eep $(MAKEFILE_LIST)
+ @echo $(MSG_DFU_CMD) Programming EEPROM with dfu-programmer using \"$<\"
+ dfu-programmer $(MCU) eeprom-flash $<
+ dfu-programmer $(MCU) reset
+
+# Phony build targets for this module
+.PHONY: flip flip-ee dfu dfu-ee
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_doxygen.mk b/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_doxygen.mk
new file mode 100644
index 000000000..babf28798
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_doxygen.mk
@@ -0,0 +1,100 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2014.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+
+LUFA_BUILD_MODULES += DOXYGEN
+LUFA_BUILD_TARGETS += doxygen doxygen_upgrade doxygen_create
+LUFA_BUILD_MANDATORY_VARS += LUFA_PATH
+LUFA_BUILD_OPTIONAL_VARS += DOXYGEN_CONF DOXYGEN_FAIL_ON_WARNING DOXYGEN_OVERRIDE_PARAMS
+LUFA_BUILD_PROVIDED_VARS +=
+LUFA_BUILD_PROVIDED_MACROS +=
+
+# -----------------------------------------------------------------------------
+# LUFA Doxygen Buildsystem Makefile Module.
+# -----------------------------------------------------------------------------
+# DESCRIPTION:
+# Provides a set of targets to automatically build Doxygen documentation for
+# a project (see www.doxygen.org).
+# -----------------------------------------------------------------------------
+# TARGETS:
+#
+# doxygen - Build Doxygen Documentation
+# doxygen_create - Create a new Doxygen configuration file using
+# the latest template
+# doxygen_upgrade - Upgrade an existing Doxygen configuration file
+# to the latest template
+#
+# MANDATORY PARAMETERS:
+#
+# LUFA_PATH - Path to the LUFA library core
+#
+# OPTIONAL PARAMETERS:
+#
+# DOXYGEN_CONF - Doxygen configuration filename
+# DOXYGEN_FAIL_ON_WARNING - Set to Y to fail the build on Doxygen warnings,
+# N to continue even if warnings occur
+# DOXYGEN_OVERRIDE_PARAMS - Parameters to override in the doxygen
+# configuration file
+# PROVIDED VARIABLES:
+#
+# (None)
+#
+# PROVIDED MACROS:
+#
+# (None)
+#
+# -----------------------------------------------------------------------------
+
+SHELL = /bin/sh
+
+ERROR_IF_UNSET ?= $(if $(filter undefined, $(origin $(strip $(1)))), $(error Makefile $(strip $(1)) value not set))
+ERROR_IF_EMPTY ?= $(if $(strip $($(strip $(1)))), , $(error Makefile $(strip $(1)) option cannot be blank))
+ERROR_IF_NONBOOL ?= $(if $(filter Y N, $($(strip $(1)))), , $(error Makefile $(strip $(1)) option must be Y or N))
+
+# Default values of optionally user-supplied variables
+DOXYGEN_CONF ?= doxyfile
+DOXYGEN_FAIL_ON_WARNING ?= Y
+DOXYGEN_OVERRIDE_PARAMS ?= QUIET=YES HTML_EXTRA_STYLESHEET=$(patsubst %/,%,$(LUFA_PATH))/DoxygenPages/Style/Style.css
+
+# Sanity check user supplied values
+$(foreach MANDATORY_VAR, $(LUFA_BUILD_MANDATORY_VARS), $(call ERROR_IF_UNSET, $(MANDATORY_VAR)))
+$(call ERROR_IF_EMPTY, DOXYGEN_CONF)
+$(call ERROR_IF_EMPTY, LUFA_PATH)
+$(call ERROR_IF_NONBOOL, DOXYGEN_FAIL_ON_WARNING)
+
+# Output Messages
+MSG_DOXYGEN_CMD := ' [DOXYGEN] :'
+
+# Determine Doxygen invocation command
+BASE_DOXYGEN_CMD := ( cat $(DOXYGEN_CONF) $(DOXYGEN_OVERRIDE_PARAMS:%=; echo "%") ) | doxygen -
+ifeq ($(DOXYGEN_FAIL_ON_WARNING), Y)
+ DOXYGEN_CMD := if ( $(BASE_DOXYGEN_CMD) 2>&1 | grep -v "warning: ignoring unsupported tag" ;); then exit 1; fi;
+else
+ DOXYGEN_CMD := $(BASE_DOXYGEN_CMD)
+endif
+
+# Error if the specified Doxygen configuration file does not exist
+$(DOXYGEN_CONF):
+ $(error Doxygen configuration file $@ does not exist)
+
+# Builds the project documentation using the specified configuration file and the DOXYGEN tool
+doxygen: $(DOXYGEN_CONF) $(MAKEFILE_LIST)
+ @echo $(MSG_DOXYGEN_CMD) Configuration file \"$(DOXYGEN_CONF)\" with parameters \"$(DOXYGEN_OVERRIDE_PARAMS)\"
+ $(DOXYGEN_CMD)
+
+# Upgrades an existing Doxygen configuration file to the latest Doxygen template, preserving settings
+doxygen_upgrade: $(DOXYGEN_CONF) $(MAKEFILE_LIST)
+ @echo $(MSG_DOXYGEN_CMD) Upgrading configuration file \"$(DOXYGEN_CONF)\" with latest template
+ doxygen -u $(DOXYGEN_CONF) > /dev/null
+
+# Creates a new Doxygen configuration file with the set file name
+doxygen_create: $(MAKEFILE_LIST)
+ @echo $(MSG_DOXYGEN_CMD) Creating new configuration file \"$(DOXYGEN_CONF)\" with latest template
+ doxygen -g $(DOXYGEN_CONF) > /dev/null
+
+# Phony build targets for this module
+.PHONY: doxygen doxygen_upgrade doxygen_create
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_hid.mk b/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_hid.mk
new file mode 100644
index 000000000..e79b7bf4d
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_hid.mk
@@ -0,0 +1,96 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2014.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+
+LUFA_BUILD_MODULES += HID
+LUFA_BUILD_TARGETS += hid hid-ee teensy teensy-ee
+LUFA_BUILD_MANDATORY_VARS += MCU TARGET
+LUFA_BUILD_OPTIONAL_VARS +=
+LUFA_BUILD_PROVIDED_VARS +=
+LUFA_BUILD_PROVIDED_MACROS +=
+
+# -----------------------------------------------------------------------------
+# LUFA HID Bootloader Buildsystem Makefile Module.
+# -----------------------------------------------------------------------------
+# DESCRIPTION:
+# Provides a set of targets to re-program a device currently running a HID
+# class bootloader with a project's FLASH files.
+# -----------------------------------------------------------------------------
+# TARGETS:
+#
+# hid - Program FLASH into target via
+# hid_bootloader_cli
+# hid-ee - Program EEPROM into target via a temporary
+# AVR application and hid_bootloader_cli
+# teensy - Program FLASH into target via
+# teensy_loader_cli
+# teensy-ee - Program EEPROM into target via a temporary
+# AVR application and teensy_loader_cli
+#
+# MANDATORY PARAMETERS:
+#
+# MCU - Microcontroller device model name
+# TARGET - Application name
+#
+# OPTIONAL PARAMETERS:
+#
+# (None)
+#
+# PROVIDED VARIABLES:
+#
+# (None)
+#
+# PROVIDED MACROS:
+#
+# (None)
+#
+# -----------------------------------------------------------------------------
+
+SHELL = /bin/sh
+
+LUFA_MODULE_PATH := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST))))
+
+ERROR_IF_UNSET ?= $(if $(filter undefined, $(origin $(strip $(1)))), $(error Makefile $(strip $(1)) value not set))
+ERROR_IF_EMPTY ?= $(if $(strip $($(strip $(1)))), , $(error Makefile $(strip $(1)) option cannot be blank))
+ERROR_IF_NONBOOL ?= $(if $(filter Y N, $($(strip $(1)))), , $(error Makefile $(strip $(1)) option must be Y or N))
+
+# Sanity-check values of mandatory user-supplied variables
+$(foreach MANDATORY_VAR, $(LUFA_BUILD_MANDATORY_VARS), $(call ERROR_IF_UNSET, $(MANDATORY_VAR)))
+$(call ERROR_IF_EMPTY, MCU)
+$(call ERROR_IF_EMPTY, TARGET)
+
+# Output Messages
+MSG_HID_BOOTLOADER_CMD := ' [HID] :'
+MSG_OBJCPY_CMD := ' [OBJCPY] :'
+MSG_MAKE_CMD := ' [MAKE] :'
+
+# Programs in the target FLASH memory using the HID_BOOTLOADER_CLI tool
+hid: $(TARGET).hex $(MAKEFILE_LIST)
+ @echo $(MSG_HID_BOOTLOADER_CMD) Programming FLASH with hid_bootloader_cli using \"$<\"
+ hid_bootloader_cli -mmcu=$(MCU) -v $<
+
+# Programs in the target EEPROM memory using the HID_BOOTLOADER_CLI tool (note: clears target FLASH memory)
+hid-ee: $(TARGET).eep $(MAKEFILE_LIST)
+ @echo $(MSG_OBJCPY_CMD) Converting \"$<\" to a binary file \"InputEEData.bin\"
+ avr-objcopy -I ihex -O binary $< $(LUFA_MODULE_PATH)/HID_EEPROM_Loader/InputEEData.bin
+ @echo $(MSG_MAKE_CMD) Making EEPROM loader application for \"$<\"
+ $(MAKE) -C $(LUFA_MODULE_PATH)/HID_EEPROM_Loader/ MCU=$(MCU) clean hid
+
+# Programs in the target FLASH memory using the TEENSY_BOOTLOADER_CLI tool
+teensy: $(TARGET).hex $(MAKEFILE_LIST)
+ @echo $(MSG_HID_BOOTLOADER_CMD) Programming FLASH with teensy_loader_cli using \"$<\"
+ teensy_loader_cli -mmcu=$(MCU) -v $<
+
+# Programs in the target EEPROM memory using the TEENSY_BOOTLOADER_CLI tool (note: clears target FLASH memory)
+teensy-ee: $(TARGET).hex $(MAKEFILE_LIST)
+ @echo $(MSG_OBJCPY_CMD) Converting \"$<\" to a binary file \"InputEEData.bin\"
+ avr-objcopy -I ihex -O binary $< $(LUFA_MODULE_PATH)/HID_EEPROM_Loader/InputEEData.bin
+ @echo $(MSG_MAKE_CMD) Making EEPROM loader application for \"$<\"
+ $(MAKE) -s -C $(LUFA_MODULE_PATH)/HID_EEPROM_Loader/ MCU=$(MCU) clean teensy
+
+# Phony build targets for this module
+.PHONY: hid hid-ee teensy teensy-ee
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_sources.mk b/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_sources.mk
new file mode 100644
index 000000000..cc3492ecc
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Build/lufa_sources.mk
@@ -0,0 +1,144 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2014.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+
+LUFA_BUILD_MODULES += SOURCES
+LUFA_BUILD_TARGETS +=
+LUFA_BUILD_MANDATORY_VARS += LUFA_PATH ARCH
+LUFA_BUILD_OPTIONAL_VARS +=
+LUFA_BUILD_PROVIDED_VARS += LUFA_SRC_USB_DEVICE LUFA_SRC_USB_HOST \
+ LUFA_SRC_USB LUFA_SRC_USBCLASS_DEVICE \
+ LUFA_SRC_USBCLASS_HOST LUFA_SRC_USBCLASS \
+ LUFA_SRC_TEMPERATURE LUFA_SRC_SERIAL \
+ LUFA_SRC_TWI LUFA_SRC_PLATFORM
+LUFA_BUILD_PROVIDED_MACROS +=
+
+# -----------------------------------------------------------------------------
+# LUFA Sources Buildsystem Makefile Module.
+# -----------------------------------------------------------------------------
+# DESCRIPTION:
+# Provides a set of makefile variables for the various LUFA module sources.
+# Once included, the sources required to use a given LUFA module will become
+# available using the makefile variable names listed in the LUFA project
+# documentation.
+# -----------------------------------------------------------------------------
+# TARGETS:
+#
+# (None)
+#
+# MANDATORY PARAMETERS:
+#
+# LUFA_PATH - Path to the LUFA library core
+# ARCH - Device architecture name
+#
+# OPTIONAL PARAMETERS:
+#
+# (None)
+#
+# PROVIDED VARIABLES:
+#
+# LUFA_SRC_USB_DEVICE - List of LUFA USB driver source files required
+# for USB Device mode only
+# LUFA_SRC_USB_HOST - List of LUFA USB driver source files required
+# for USB Host mode only
+# LUFA_SRC_USB - List of LUFA USB driver source files for all
+# USB modes
+# LUFA_SRC_USBCLASS_DEVICE - List of LUFA USB Class driver source files for
+# USB Device mode only
+# LUFA_SRC_USBCLASS_HOST - List of LUFA USB Class driver source files for
+# USB Host mode only
+# LUFA_SRC_USBCLASS - List of LUFA USB Class driver source files for
+# all USB modes
+# LUFA_SRC_TEMPERATURE - List of LUFA temperature sensor driver source
+# files
+# LUFA_SRC_SERIAL - List of LUFA Serial U(S)ART driver source files
+# LUFA_SRC_TWI - List of LUFA TWI driver source files
+# LUFA_SRC_PLATFORM - List of LUFA architecture specific platform
+# management source files
+#
+# PROVIDED MACROS:
+#
+# (None)
+#
+# -----------------------------------------------------------------------------
+
+SHELL = /bin/sh
+
+ERROR_IF_UNSET ?= $(if $(filter undefined, $(origin $(strip $(1)))), $(error Makefile $(strip $(1)) value not set))
+ERROR_IF_EMPTY ?= $(if $(strip $($(strip $(1)))), , $(error Makefile $(strip $(1)) option cannot be blank))
+ERROR_IF_NONBOOL ?= $(if $(filter Y N, $($(strip $(1)))), , $(error Makefile $(strip $(1)) option must be Y or N))
+
+# Sanity check user supplied values
+$(foreach MANDATORY_VAR, $(LUFA_BUILD_MANDATORY_VARS), $(call ERROR_IF_UNSET, $(MANDATORY_VAR)))
+$(call ERROR_IF_EMPTY, LUFA_PATH)
+$(call ERROR_IF_EMPTY, ARCH)
+
+# Allow LUFA_ROOT_PATH to be overridden elsewhere to support legacy LUFA makefiles
+LUFA_ROOT_PATH ?= $(patsubst %/,%,$(LUFA_PATH))
+
+# Construct LUFA module source variables
+LUFA_SRC_USB_COMMON := $(LUFA_ROOT_PATH)/Drivers/USB/Core/$(ARCH)/USBController_$(ARCH).c \
+ $(LUFA_ROOT_PATH)/Drivers/USB/Core/$(ARCH)/USBInterrupt_$(ARCH).c \
+ $(LUFA_ROOT_PATH)/Drivers/USB/Core/ConfigDescriptors.c \
+ $(LUFA_ROOT_PATH)/Drivers/USB/Core/Events.c \
+ $(LUFA_ROOT_PATH)/Drivers/USB/Core/USBTask.c \
+ $(LUFA_ROOT_PATH)/Drivers/USB/Class/Common/HIDParser.c \
+
+LUFA_SRC_USB_HOST := $(LUFA_ROOT_PATH)/Drivers/USB/Core/$(ARCH)/Host_$(ARCH).c \
+ $(LUFA_ROOT_PATH)/Drivers/USB/Core/$(ARCH)/Pipe_$(ARCH).c \
+ $(LUFA_ROOT_PATH)/Drivers/USB/Core/$(ARCH)/PipeStream_$(ARCH).c \
+ $(LUFA_ROOT_PATH)/Drivers/USB/Core/HostStandardReq.c \
+ $(LUFA_SRC_USB_COMMON)
+
+LUFA_SRC_USB_DEVICE := $(LUFA_ROOT_PATH)/Drivers/USB/Core/$(ARCH)/Device_$(ARCH).c \
+ $(LUFA_ROOT_PATH)/Drivers/USB/Core/$(ARCH)/Endpoint_$(ARCH).c \
+ $(LUFA_ROOT_PATH)/Drivers/USB/Core/$(ARCH)/EndpointStream_$(ARCH).c \
+ $(LUFA_ROOT_PATH)/Drivers/USB/Core/DeviceStandardReq.c \
+ $(LUFA_SRC_USB_COMMON)
+
+LUFA_SRC_USBCLASS_DEVICE := $(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/AudioClassDevice.c \
+ $(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/CDCClassDevice.c \
+ $(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/HIDClassDevice.c \
+ $(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/MassStorageClassDevice.c \
+ $(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/MIDIClassDevice.c \
+ $(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/PrinterClassDevice.c \
+ $(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/RNDISClassDevice.c \
+
+LUFA_SRC_USBCLASS_HOST := $(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/AndroidAccessoryClassHost.c \
+ $(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/AudioClassHost.c \
+ $(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/CDCClassHost.c \
+ $(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/HIDClassHost.c \
+ $(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/MassStorageClassHost.c \
+ $(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/MIDIClassHost.c \
+ $(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/PrinterClassHost.c \
+ $(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/RNDISClassHost.c \
+ $(LUFA_ROOT_PATH)/Drivers/USB/Class/Host/StillImageClassHost.c
+
+LUFA_SRC_USB := $(sort $(LUFA_SRC_USB_COMMON) $(LUFA_SRC_USB_HOST) $(LUFA_SRC_USB_DEVICE))
+
+LUFA_SRC_USBCLASS := $(LUFA_SRC_USBCLASS_DEVICE) $(LUFA_SRC_USBCLASS_HOST)
+
+LUFA_SRC_TEMPERATURE := $(LUFA_ROOT_PATH)/Drivers/Board/Temperature.c
+
+LUFA_SRC_SERIAL := $(LUFA_ROOT_PATH)/Drivers/Peripheral/$(ARCH)/Serial_$(ARCH).c
+
+LUFA_SRC_TWI := $(LUFA_ROOT_PATH)/Drivers/Peripheral/$(ARCH)/TWI_$(ARCH).c
+
+ifeq ($(ARCH), UC3)
+ LUFA_SRC_PLATFORM := $(LUFA_ROOT_PATH)/Platform/UC3/Exception.S \
+ $(LUFA_ROOT_PATH)/Platform/UC3/InterruptManagement.c
+else
+ LUFA_SRC_PLATFORM :=
+endif
+
+# Build a list of all available module sources
+LUFA_SRC_ALL_FILES := $(LUFA_SRC_USB) \
+ $(LUFA_SRC_USBCLASS) \
+ $(LUFA_SRC_TEMPERATURE) \
+ $(LUFA_SRC_SERIAL) \
+ $(LUFA_SRC_TWI) \
+ $(LUFA_SRC_PLATFORM)
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DeviceTemplate/Descriptors.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DeviceTemplate/Descriptors.c
new file mode 100644
index 000000000..71cebe891
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DeviceTemplate/Descriptors.c
@@ -0,0 +1,180 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * USB Device Descriptors, for library use when in USB device mode. Descriptors are special
+ * computer-readable structures which the host requests upon device enumeration, to determine
+ * the device's capabilities and functions.
+ */
+
+#include "Descriptors.h"
+
+/** Device descriptor structure. This descriptor describes the overall device
+ * characteristics, including the supported USB version, control endpoint size
+ * and the number of device configurations. The descriptor is read out by the
+ * USB host when the enumeration process begins.
+ */
+const USB_Descriptor_Device_t DeviceDescriptor =
+{
+ .Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
+
+ .USBSpecification = VERSION_BCD(2,0,0),
+ .Class = USB_CSCP_NoDeviceClass,
+ .SubClass = USB_CSCP_NoDeviceSubclass,
+ .Protocol = USB_CSCP_NoDeviceProtocol,
+
+ .Endpoint0Size = 64,
+
+ .VendorID = 0x0000,
+ .ProductID = 0x0000,
+ .ReleaseNumber = VERSION_BCD(0,0,2),
+
+ .ManufacturerStrIndex = 0x01,
+ .ProductStrIndex = 0x02,
+ .SerialNumStrIndex = NO_DESCRIPTOR,
+
+ .NumberOfConfigurations = 1
+};
+
+/** Configuration descriptor structure. This descriptor, located in FLASH memory, describes the usage
+ * of the device in one of its supported configurations, including information about any device interfaces
+ * and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting
+ * a configuration so that the host may correctly communicate with the USB device.
+ */
+const USB_Descriptor_Configuration_t ConfigurationDescriptor =
+{
+ .Config =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration},
+
+ .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
+ .TotalInterfaces = 0,
+
+ .ConfigurationNumber = 1,
+ .ConfigurationStrIndex = NO_DESCRIPTOR,
+
+ .ConfigAttributes = (USB_CONFIG_ATTR_RESERVED | USB_CONFIG_ATTR_SELFPOWERED),
+
+ .MaxPowerConsumption = USB_CONFIG_POWER_MA(100)
+ },
+};
+
+/** Language descriptor structure. This descriptor, located in FLASH memory, is returned when the host requests
+ * the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which indicate
+ * via the language ID table available at USB.org what languages the device supports for its string descriptors.
+ */
+const USB_Descriptor_String_t LanguageString =
+{
+ .Header = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String},
+
+ .UnicodeString = {LANGUAGE_ID_ENG}
+};
+
+/** Manufacturer descriptor string. This is a Unicode string containing the manufacturer's details in human readable
+ * form, and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
+ * Descriptor.
+ */
+const USB_Descriptor_String_t ManufacturerString =
+{
+ .Header = {.Size = USB_STRING_LEN(14), .Type = DTYPE_String},
+
+ .UnicodeString = L"Your Name Here"
+};
+
+/** Product descriptor string. This is a Unicode string containing the product's details in human readable form,
+ * and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
+ * Descriptor.
+ */
+const USB_Descriptor_String_t ProductString =
+{
+ .Header = {.Size = USB_STRING_LEN(15), .Type = DTYPE_String},
+
+ .UnicodeString = L"LUFA USB Device"
+};
+
+/** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
+ * documentation) by the application code so that the address and size of a requested descriptor can be given
+ * to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function
+ * is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the
+ * USB host.
+ */
+uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+ const uint8_t wIndex,
+ const void** const DescriptorAddress
+ #if defined(HAS_MULTIPLE_DESCRIPTOR_ADDRESS_SPACES)
+ , uint8_t* const DescriptorMemorySpace
+ #endif
+ )
+{
+ const uint8_t DescriptorType = (wValue >> 8);
+ const uint8_t DescriptorNumber = (wValue & 0xFF);
+
+ const void* Address = NULL;
+ uint16_t Size = NO_DESCRIPTOR;
+
+ switch (DescriptorType)
+ {
+ case DTYPE_Device:
+ Address = &DeviceDescriptor;
+ Size = sizeof(USB_Descriptor_Device_t);
+ break;
+ case DTYPE_Configuration:
+ Address = &ConfigurationDescriptor;
+ Size = sizeof(USB_Descriptor_Configuration_t);
+ break;
+ case DTYPE_String:
+ switch (DescriptorNumber)
+ {
+ case 0x00:
+ Address = &LanguageString;
+ Size = pgm_read_byte(&LanguageString.Header.Size);
+ break;
+ case 0x01:
+ Address = &ManufacturerString;
+ Size = pgm_read_byte(&ManufacturerString.Header.Size);
+ break;
+ case 0x02:
+ Address = &ProductString;
+ Size = pgm_read_byte(&ProductString.Header.Size);
+ break;
+ }
+
+ break;
+ }
+
+ #if defined(HAS_MULTIPLE_DESCRIPTOR_ADDRESS_SPACES)
+ *DescriptorMemorySpace = MEMSPACE_RAM;
+ #endif
+
+ *DescriptorAddress = Address;
+ return Size;
+}
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DeviceTemplate/Descriptors.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DeviceTemplate/Descriptors.h
new file mode 100644
index 000000000..6d8145d0c
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DeviceTemplate/Descriptors.h
@@ -0,0 +1,59 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Header file for Descriptors.c.
+ */
+
+#ifndef _DESCRIPTORS_H_
+#define _DESCRIPTORS_H_
+
+ /* Includes: */
+ #include <LUFA/Drivers/USB/USB.h>
+
+ /* Macros: */
+ #if (defined(ARCH_HAS_MULTI_ADDRESS_SPACE) && \
+ !(defined(USE_FLASH_DESCRIPTORS) || defined(USE_EEPROM_DESCRIPTORS) || defined(USE_RAM_DESCRIPTORS)))
+ #define HAS_MULTIPLE_DESCRIPTOR_ADDRESS_SPACES
+ #endif
+
+ /* Type Defines: */
+ /** Type define for the device configuration descriptor structure. This must be defined in the
+ * application code, as the configuration descriptor contains several sub-descriptors which
+ * vary between devices, and which describe the device's usage to the host.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Configuration_Header_t Config;
+ } USB_Descriptor_Configuration_t;
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DeviceTemplate/DeviceApplication.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DeviceTemplate/DeviceApplication.c
new file mode 100644
index 000000000..ddaa9d089
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DeviceTemplate/DeviceApplication.c
@@ -0,0 +1,106 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Main source file for the USB device application. This file contains the
+ * main tasks of the application and is responsible for the initial
+ * application hardware configuration.
+ */
+
+#include "DeviceApplication.h"
+
+/** Main program entry point. This routine contains the overall program flow, including initial
+ * setup of all components and the main program loop.
+ */
+int main(void)
+{
+ SetupHardware();
+
+ GlobalInterruptEnable();
+
+ for (;;)
+ {
+ USB_USBTask();
+ }
+}
+
+/** Configures the board hardware and chip peripherals for the demo's functionality. */
+void SetupHardware(void)
+{
+ #if (ARCH == ARCH_AVR8)
+ /* Disable watchdog if enabled by bootloader/fuses */
+ MCUSR &= ~(1 << WDRF);
+ wdt_disable();
+
+ /* Disable clock division */
+ clock_prescale_set(clock_div_1);
+
+ /* Hardware Initialization */
+ USB_Init(USB_MODE_Device, USB_DEVICE_OPT_FULLSPEED | USB_OPT_AUTO_PLL);
+ #elif (ARCH == ARCH_XMEGA)
+ /* Start the PLL to multiply the 2MHz RC oscillator to 32MHz and switch the CPU core to run from it */
+ XMEGACLK_StartPLL(CLOCK_SRC_INT_RC2MHZ, 2000000, F_CPU);
+ XMEGACLK_SetCPUClockSource(CLOCK_SRC_PLL);
+
+ /* Start the 32MHz internal RC oscillator and start the DFLL to increase it to 48MHz using the USB SOF as a reference */
+ XMEGACLK_StartInternalOscillator(CLOCK_SRC_INT_RC32MHZ);
+ XMEGACLK_StartDFLL(CLOCK_SRC_INT_RC32MHZ, DFLL_REF_INT_USBSOF, F_USB);
+
+ PMIC.CTRL = PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm;
+
+ /* Hardware Initialization */
+ USB_Init(USB_OPT_RC32MCLKSRC | USB_OPT_BUSEVENT_PRIHIGH);
+ #endif
+}
+
+/** Event handler for the library USB Connection event. */
+void EVENT_USB_Device_Connect(void)
+{
+
+}
+
+/** Event handler for the library USB Disconnection event. */
+void EVENT_USB_Device_Disconnect(void)
+{
+
+}
+
+/** Event handler for the library USB Configuration Changed event. */
+void EVENT_USB_Device_ConfigurationChanged(void)
+{
+
+}
+
+/** Event handler for the library USB Control Request reception event. */
+void EVENT_USB_Device_ControlRequest(void)
+{
+
+}
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DeviceTemplate/DeviceApplication.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DeviceTemplate/DeviceApplication.h
new file mode 100644
index 000000000..325176c53
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DeviceTemplate/DeviceApplication.h
@@ -0,0 +1,53 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Header file for DeviceApplication.c.
+ */
+
+#ifndef _USB_DEVICE_APPLICATION_H_
+#define _USB_DEVICE_APPLICATION_H_
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <avr/wdt.h>
+ #include <avr/power.h>
+
+ #include <LUFA/Platform/Platform.h>
+ #include <LUFA/Drivers/USB/USB.h>
+
+ #include "Descriptors.h"
+
+ /* Function Prototypes: */
+ void SetupHardware(void);
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DeviceTemplate/asf.xml b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DeviceTemplate/asf.xml
new file mode 100644
index 000000000..fd65db283
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DeviceTemplate/asf.xml
@@ -0,0 +1,55 @@
+<asf xmlversion="1.0">
+ <project caption="USB Device Template" id="lufa.templates.device.project.avr8">
+ <require idref="lufa.templates.device"/>
+ <require idref="lufa.boards.dummy.avr8"/>
+ <generator value="as5_8_template"/>
+
+ <device-support value="at90usb1287"/>
+ <config name="lufa.drivers.board.name" value="usbkey"/>
+
+ <build type="define" name="F_CPU" value="8000000UL"/>
+ <build type="define" name="F_USB" value="8000000UL"/>
+ </project>
+
+ <project caption="USB Device Template" id="lufa.templates.device.project.xmega">
+ <require idref="lufa.templates.device"/>
+ <require idref="lufa.boards.dummy.xmega"/>
+ <generator value="as5_8_template"/>
+
+ <device-support value="atxmega256a3bu"/>
+ <config name="lufa.drivers.board.name" value="a3bu_xplained"/>
+
+ <build type="define" name="F_CPU" value="32000000UL"/>
+ <build type="define" name="F_USB" value="48000000UL"/>
+ </project>
+
+ <module type="application" id="lufa.templates.device" caption="USB Device Template">
+ <info type="description" value="summary">
+ Template for a LUFA USB device mode application.
+ </info>
+
+ <info type="gui-flag" value="move-to-root"/>
+
+ <info type="keyword" value="Technology">
+ <keyword value="USB Device"/>
+ <keyword value="Template Projects"/>
+ </info>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="c-source" value="DeviceApplication.c"/>
+ <build type="c-source" value="Descriptors.c"/>
+ <build type="header-file" value="DeviceApplication.h"/>
+ <build type="header-file" value="Descriptors.h"/>
+
+ <build type="module-config" subtype="path" value=".."/>
+ <build type="header-file" value="../LUFAConfig.h"/>
+
+ <require idref="lufa.common"/>
+ <require idref="lufa.platform"/>
+ <require idref="lufa.drivers.usb"/>
+ <require idref="lufa.drivers.board"/>
+ </module>
+</asf>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DriverStubs/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DriverStubs/Board.h
new file mode 100644
index 000000000..5a1e58364
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DriverStubs/Board.h
@@ -0,0 +1,82 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief LUFA Custom Board Hardware Information Driver (Template)
+ *
+ * This is a stub driver header file, for implementing custom board
+ * layout hardware with compatible LUFA board specific drivers. If
+ * the library is configured to use the BOARD_USER board mode, this
+ * driver file should be completed and copied into the "/Board/" folder
+ * inside the application's folder.
+ *
+ * This stub is for the board-specific component of the LUFA Board Hardware
+ * information driver.
+ */
+
+#ifndef __BOARD_USER_H__
+#define __BOARD_USER_H__
+
+ /* Includes: */
+ // TODO: Add any required includes here
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware Buttons mounted if defined. */
+// #define BOARD_HAS_BUTTONS
+
+ /** Indicates the board has a hardware Dataflash mounted if defined. */
+// #define BOARD_HAS_DATAFLASH
+
+ /** Indicates the board has a hardware Joystick mounted if defined. */
+// #define BOARD_HAS_JOYSTICK
+
+ /** Indicates the board has hardware LEDs mounted if defined. */
+// #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DriverStubs/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DriverStubs/Buttons.h
new file mode 100644
index 000000000..b3c2f2b42
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DriverStubs/Buttons.h
@@ -0,0 +1,90 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief LUFA Custom Board Button Hardware Driver (Template)
+ *
+ * This is a stub driver header file, for implementing custom board
+ * layout hardware with compatible LUFA board specific drivers. If
+ * the library is configured to use the BOARD_USER board mode, this
+ * driver file should be completed and copied into the "/Board/" folder
+ * inside the application's folder.
+ *
+ * This stub is for the board-specific component of the LUFA Buttons driver,
+ * for the control of physical board-mounted GPIO pushbuttons.
+ */
+
+#ifndef __BUTTONS_USER_H__
+#define __BUTTONS_USER_H__
+
+ /* Includes: */
+ // TODO: Add any required includes here
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Button mask for the first button on the board. */
+ #define BUTTONS_BUTTON1 // TODO: Add mask for first board button here
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+ // TODO: Initialize the appropriate port pins as an inputs here, with pull-ups
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+ // TODO: Clear the appropriate port pins as high impedance inputs here
+ }
+
+ static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Buttons_GetStatus(void)
+ {
+ // TODO: Return current button status here, debounced if required
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DriverStubs/Dataflash.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DriverStubs/Dataflash.h
new file mode 100644
index 000000000..83acb2f12
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DriverStubs/Dataflash.h
@@ -0,0 +1,223 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief LUFA Custom Board Dataflash Hardware Driver (Template)
+ *
+ * This is a stub driver header file, for implementing custom board
+ * layout hardware with compatible LUFA board specific drivers. If
+ * the library is configured to use the BOARD_USER board mode, this
+ * driver file should be completed and copied into the "/Board/" folder
+ * inside the application's folder.
+ *
+ * This stub is for the board-specific component of the LUFA Dataflash
+ * driver.
+*/
+
+#ifndef __DATAFLASH_USER_H__
+#define __DATAFLASH_USER_H__
+
+ /* Includes: */
+ // TODO: Add any required includes here
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_DATAFLASH_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Dataflash.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define DATAFLASH_CHIPCS_MASK // TODO: Replace this with a mask of all the /CS pins of all Dataflashes
+ #define DATAFLASH_CHIPCS_DDR // TODO: Replace with the DDR register name for the board's Dataflash ICs
+ #define DATAFLASH_CHIPCS_PORT // TODO: Replace with the PORT register name for the board's Dataflash ICs
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Constant indicating the total number of dataflash ICs mounted on the selected board. */
+ #define DATAFLASH_TOTALCHIPS 1 // TODO: Replace with the number of Dataflashes on the board, max 2
+
+ /** Mask for no dataflash chip selected. */
+ #define DATAFLASH_NO_CHIP 0
+
+ /** Mask for the first dataflash chip selected. */
+ #define DATAFLASH_CHIP1 // TODO: Replace with mask with the pin attached to the first Dataflash /CS set
+
+ /** Mask for the second dataflash chip selected. */
+ #define DATAFLASH_CHIP2 // TODO: Replace with mask with the pin attached to the second Dataflash /CS set
+
+ /** Internal main memory page size for the board's dataflash ICs. */
+ #define DATAFLASH_PAGE_SIZE // TODO: Replace with the page size for the Dataflash ICs
+
+ /** Total number of pages inside each of the board's dataflash ICs. */
+ #define DATAFLASH_PAGES // TODO: Replace with the total number of pages inside one of the Dataflash ICs
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ /** Initializes the dataflash driver so that commands and data may be sent to an attached dataflash IC.
+ * The microcontroller's SPI driver MUST be initialized before any of the dataflash commands are used.
+ */
+ static inline void Dataflash_Init(void)
+ {
+ DATAFLASH_CHIPCS_DDR |= DATAFLASH_CHIPCS_MASK;
+ DATAFLASH_CHIPCS_PORT |= DATAFLASH_CHIPCS_MASK;
+ }
+
+ /** Sends a byte to the currently selected dataflash IC, and returns a byte from the dataflash.
+ *
+ * \param[in] Byte Byte of data to send to the dataflash
+ *
+ * \return Last response byte from the dataflash
+ */
+ static inline uint8_t Dataflash_TransferByte(const uint8_t Byte) ATTR_ALWAYS_INLINE;
+ static inline uint8_t Dataflash_TransferByte(const uint8_t Byte)
+ {
+ // TODO
+ }
+
+ /** Sends a byte to the currently selected dataflash IC, and ignores the next byte from the dataflash.
+ *
+ * \param[in] Byte Byte of data to send to the dataflash
+ */
+ static inline void Dataflash_SendByte(const uint8_t Byte) ATTR_ALWAYS_INLINE;
+ static inline void Dataflash_SendByte(const uint8_t Byte)
+ {
+ // TODO
+ }
+
+ /** Sends a dummy byte to the currently selected dataflash IC, and returns the next byte from the dataflash.
+ *
+ * \return Last response byte from the dataflash
+ */
+ static inline uint8_t Dataflash_ReceiveByte(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Dataflash_ReceiveByte(void)
+ {
+ // TODO
+ }
+
+ /** Determines the currently selected dataflash chip.
+ *
+ * \return Mask of the currently selected Dataflash chip, either \ref DATAFLASH_NO_CHIP if no chip is selected
+ * or a DATAFLASH_CHIPn mask (where n is the chip number).
+ */
+ static inline uint8_t Dataflash_GetSelectedChip(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Dataflash_GetSelectedChip(void)
+ {
+ return (~DATAFLASH_CHIPCS_PORT & DATAFLASH_CHIPCS_MASK);
+ }
+
+ /** Selects the given dataflash chip.
+ *
+ * \param[in] ChipMask Mask of the Dataflash IC to select, in the form of a \c DATAFLASH_CHIPn mask (where n is
+ * the chip number).
+ */
+ static inline void Dataflash_SelectChip(const uint8_t ChipMask) ATTR_ALWAYS_INLINE;
+ static inline void Dataflash_SelectChip(const uint8_t ChipMask)
+ {
+ DATAFLASH_CHIPCS_PORT = ((DATAFLASH_CHIPCS_PORT | DATAFLASH_CHIPCS_MASK) & ~ChipMask);
+ }
+
+ /** Deselects the current dataflash chip, so that no dataflash is selected. */
+ static inline void Dataflash_DeselectChip(void) ATTR_ALWAYS_INLINE;
+ static inline void Dataflash_DeselectChip(void)
+ {
+ Dataflash_SelectChip(DATAFLASH_NO_CHIP);
+ }
+
+ /** Selects a dataflash IC from the given page number, which should range from 0 to
+ * ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1). For boards containing only one
+ * dataflash IC, this will select DATAFLASH_CHIP1. If the given page number is outside
+ * the total number of pages contained in the boards dataflash ICs, all dataflash ICs
+ * are deselected.
+ *
+ * \param[in] PageAddress Address of the page to manipulate, ranging from
+ * 0 to ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1).
+ */
+ static inline void Dataflash_SelectChipFromPage(const uint16_t PageAddress)
+ {
+ Dataflash_DeselectChip();
+
+ if (PageAddress >= (DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS))
+ return;
+
+ #if (DATAFLASH_TOTALCHIPS == 2)
+ if (PageAddress & 0x01)
+ Dataflash_SelectChip(DATAFLASH_CHIP2);
+ else
+ Dataflash_SelectChip(DATAFLASH_CHIP1);
+ #else
+ Dataflash_SelectChip(DATAFLASH_CHIP1);
+ #endif
+ }
+
+ /** Toggles the select line of the currently selected dataflash IC, so that it is ready to receive
+ * a new command.
+ */
+ static inline void Dataflash_ToggleSelectedChipCS(void)
+ {
+ uint8_t SelectedChipMask = Dataflash_GetSelectedChip();
+
+ Dataflash_DeselectChip();
+ Dataflash_SelectChip(SelectedChipMask);
+ }
+
+ /** Spin-loops while the currently selected dataflash is busy executing a command, such as a main
+ * memory page program or main memory to buffer transfer.
+ */
+ static inline void Dataflash_WaitWhileBusy(void)
+ {
+ Dataflash_ToggleSelectedChipCS();
+ Dataflash_SendByte(DF_CMD_GETSTATUS);
+ while (!(Dataflash_ReceiveByte() & DF_STATUS_READY));
+ Dataflash_ToggleSelectedChipCS();
+ }
+
+ /** Sends a set of page and buffer address bytes to the currently selected dataflash IC, for use with
+ * dataflash commands which require a complete 24-bit address.
+ *
+ * \param[in] PageAddress Page address within the selected dataflash IC
+ * \param[in] BufferByte Address within the dataflash's buffer
+ */
+ static inline void Dataflash_SendAddressBytes(uint16_t PageAddress,
+ const uint16_t BufferByte)
+ {
+ #if (DATAFLASH_TOTALCHIPS == 2)
+ PageAddress >>= 1;
+ #endif
+
+ Dataflash_SendByte(PageAddress >> 5);
+ Dataflash_SendByte((PageAddress << 3) | (BufferByte >> 8));
+ Dataflash_SendByte(BufferByte);
+ }
+ #endif
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DriverStubs/Joystick.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DriverStubs/Joystick.h
new file mode 100644
index 000000000..07542ab72
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DriverStubs/Joystick.h
@@ -0,0 +1,102 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief LUFA Custom Board Joystick Hardware Driver (Template)
+ *
+ * This is a stub driver header file, for implementing custom board
+ * layout hardware with compatible LUFA board specific drivers. If
+ * the library is configured to use the BOARD_USER board mode, this
+ * driver file should be completed and copied into the "/Board/" folder
+ * inside the application's folder.
+ *
+ * This stub is for the board-specific component of the LUFA Joystick
+ * driver, for a digital four-way (plus button) joystick.
+*/
+
+#ifndef __JOYSTICK_USER_H__
+#define __JOYSTICK_USER_H__
+
+ /* Includes: */
+ // TODO: Add any required includes here
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_JOYSTICK_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Joystick.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Mask for the joystick being pushed in the left direction. */
+ #define JOY_LEFT // TODO: Add mask to indicate joystick left position here
+
+ /** Mask for the joystick being pushed in the right direction. */
+ #define JOY_RIGHT // TODO: Add mask to indicate joystick right position here
+
+ /** Mask for the joystick being pushed in the upward direction. */
+ #define JOY_UP // TODO: Add mask to indicate joystick up position here
+
+ /** Mask for the joystick being pushed in the downward direction. */
+ #define JOY_DOWN // TODO: Add mask to indicate joystick down position here
+
+ /** Mask for the joystick being pushed inward. */
+ #define JOY_PRESS // TODO: Add mask to indicate joystick pressed position here
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Joystick_Init(void)
+ {
+ // TODO: Initialize joystick port pins as inputs with pull-ups
+ }
+
+ static inline void Joystick_Disable(void)
+ {
+ // TODO: Clear the joystick pins as high impedance inputs here
+ }
+
+ static inline uint8_t Joystick_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Joystick_GetStatus(void)
+ {
+ // TODO: Return current joystick position data which can be obtained by masking against the JOY_* macros
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DriverStubs/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DriverStubs/LEDs.h
new file mode 100644
index 000000000..437397279
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/DriverStubs/LEDs.h
@@ -0,0 +1,130 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief LUFA Custom Board LED Hardware Driver (Template)
+ *
+ * This is a stub driver header file, for implementing custom board
+ * layout hardware with compatible LUFA board specific drivers. If
+ * the library is configured to use the BOARD_USER board mode, this
+ * driver file should be completed and copied into the "/Board/" folder
+ * inside the application's folder.
+ *
+ * This stub is for the board-specific component of the LUFA LEDs driver,
+ * for the LEDs (up to four) mounted on most development boards.
+*/
+
+#ifndef __LEDS_USER_H__
+#define __LEDS_USER_H__
+
+ /* Includes: */
+ // TODO: Add any required includes here
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 // TODO: Add mask for first board LED here
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 // TODO: Add mask for second board LED here
+
+ /** LED mask for the third LED on the board. */
+ #define LEDS_LED3 // TODO: Add mask for third board LED here
+
+ /** LED mask for the fourth LED on the board. */
+ #define LEDS_LED4 // TODO: Add mask for fourth board LED here
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3 | LEDS_LED4)
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ // TODO: Add code to initialize LED port pins as outputs here
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ // TODO: Clear the LED port pins as high impedance inputs here
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ // TODO: Add code to turn on LEDs given in the LEDMask mask here, leave others as-is
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ // TODO: Add code to turn off LEDs given in the LEDMask mask here, leave others as-is
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ // TODO: Add code to turn on only LEDs given in the LEDMask mask here, all others off
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask, const uint8_t ActiveMask)
+ {
+ // TODO: Add code to set the Leds in the given LEDMask to the status given in ActiveMask here
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ // TODO: Add code to toggle the Leds in the given LEDMask, ignoring all others
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ // TODO: Add code to return the current LEDs status' here which can be masked against LED_LED* macros
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/HostTemplate/HostApplication.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/HostTemplate/HostApplication.c
new file mode 100644
index 000000000..1ac03788d
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/HostTemplate/HostApplication.c
@@ -0,0 +1,133 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Main source file for the USB host application. This file contains the
+ * main tasks of the application and is responsible for the initial
+ * application hardware configuration.
+ */
+
+#include "HostApplication.h"
+
+/** Main program entry point. This routine configures the hardware required by the application, then
+ * enters a loop to run the application tasks in sequence.
+ */
+int main(void)
+{
+ SetupHardware();
+
+ GlobalInterruptEnable();
+
+ for (;;)
+ {
+ USB_USBTask();
+ }
+}
+
+/** Configures the board hardware and chip peripherals for the demo's functionality. */
+void SetupHardware(void)
+{
+ /* Disable watchdog if enabled by bootloader/fuses */
+ MCUSR &= ~(1 << WDRF);
+ wdt_disable();
+
+ /* Disable clock division */
+ clock_prescale_set(clock_div_1);
+
+ /* Hardware Initialization */
+ USB_Init(USB_MODE_Host, USB_DEVICE_OPT_FULLSPEED | USB_OPT_AUTO_PLL);
+}
+
+/** Event handler for the USB_DeviceAttached event. This indicates that a device has been attached to the host, and
+ * starts the library USB task to begin the enumeration and USB management process.
+ */
+void EVENT_USB_Host_DeviceAttached(void)
+{
+
+}
+
+/** Event handler for the USB_DeviceUnattached event. This indicates that a device has been removed from the host, and
+ * stops the library USB task management process.
+ */
+void EVENT_USB_Host_DeviceUnattached(void)
+{
+
+}
+
+/** Event handler for the USB_DeviceEnumerationComplete event. This indicates that a device has been successfully
+ * enumerated by the host and is now ready to be used by the application.
+ */
+void EVENT_USB_Host_DeviceEnumerationComplete(void)
+{
+ uint16_t ConfigDescriptorSize;
+ uint8_t ConfigDescriptorData[512];
+
+ if (USB_Host_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, ConfigDescriptorData,
+ sizeof(ConfigDescriptorData)) != HOST_GETCONFIG_Successful)
+ {
+ return;
+ }
+
+ if (USB_Host_SetDeviceConfiguration(1) != HOST_SENDCONTROL_Successful)
+ {
+ return;
+ }
+}
+
+/** Event handler for the USB_HostError event. This indicates that a hardware error occurred while in host mode. */
+void EVENT_USB_Host_HostError(const uint8_t ErrorCode)
+{
+ USB_Disable();
+ for(;;);
+}
+
+/** Event handler for the USB_DeviceEnumerationFailed event. This indicates that a problem occurred while
+ * enumerating an attached USB device.
+ */
+void EVENT_USB_Host_DeviceEnumerationFailed(const uint8_t ErrorCode,
+ const uint8_t SubErrorCode)
+{
+
+}
+
+/* Required callback for retrieving descriptors from a LUFA device - unless the USB_HOST_ONLY configuration
+ * option is set, this is still required even in an application that uses host mode only.
+ */
+uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+ const uint8_t wIndex,
+ const void** const DescriptorAddress
+#if defined(HAS_MULTIPLE_DESCRIPTOR_ADDRESS_SPACES)
+ , uint8_t* const DescriptorMemorySpace
+#endif
+)
+{
+ return 0;
+}
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/HostTemplate/HostApplication.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/HostTemplate/HostApplication.h
new file mode 100644
index 000000000..16dbb535a
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/HostTemplate/HostApplication.h
@@ -0,0 +1,56 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Header file for HostApplication.c.
+ */
+
+#ifndef _USB_HOST_APPLICATION_H_
+#define _USB_HOST_APPLICATION_H_
+
+ /* Includes: */
+ #include <avr/io.h>
+ #include <avr/wdt.h>
+ #include <avr/power.h>
+
+ #include <LUFA/Drivers/USB/USB.h>
+
+ /* Macros: */
+ #if (defined(ARCH_HAS_MULTI_ADDRESS_SPACE) && \
+ !(defined(USE_FLASH_DESCRIPTORS) || defined(USE_EEPROM_DESCRIPTORS) || defined(USE_RAM_DESCRIPTORS)))
+ #define HAS_MULTIPLE_DESCRIPTOR_ADDRESS_SPACES
+ #endif
+
+ /* Function Prototypes: */
+ void SetupHardware(void);
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/HostTemplate/asf.xml b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/HostTemplate/asf.xml
new file mode 100644
index 000000000..c1996ec71
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/HostTemplate/asf.xml
@@ -0,0 +1,41 @@
+<asf xmlversion="1.0">
+ <project caption="USB Host Template" id="lufa.templates.host.project">
+ <require idref="lufa.templates.host"/>
+ <require idref="lufa.boards.dummy.avr8"/>
+ <generator value="as5_8_template"/>
+
+ <device-support value="at90usb1287"/>
+ <config name="lufa.drivers.board.name" value="usbkey"/>
+
+ <build type="define" name="F_CPU" value="8000000UL"/>
+ <build type="define" name="F_USB" value="8000000UL"/>
+ </project>
+
+ <module type="application" id="lufa.templates.host" caption="USB Host Template">
+ <info type="description" value="summary">
+ Template for a LUFA USB host mode application.
+ </info>
+
+ <info type="gui-flag" value="move-to-root"/>
+
+ <info type="keyword" value="Technology">
+ <keyword value="USB Host"/>
+ <keyword value="Template Projects"/>
+ </info>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="c-source" value="HostApplication.c"/>
+ <build type="header-file" value="HostApplication.h"/>
+
+ <build type="module-config" subtype="path" value=".."/>
+ <build type="header-file" value="../LUFAConfig.h"/>
+
+ <require idref="lufa.common"/>
+ <require idref="lufa.platform"/>
+ <require idref="lufa.drivers.usb"/>
+ <require idref="lufa.drivers.board"/>
+ </module>
+</asf>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/LUFAConfig.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/LUFAConfig.h
new file mode 100644
index 000000000..ab7fc7520
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/LUFAConfig.h
@@ -0,0 +1,167 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief LUFA Library Configuration Header File (Template)
+ *
+ * This is a header file which can be used to configure LUFA's
+ * compile time options, as an alternative to the compile time
+ * constants supplied through a makefile. To use this configuration
+ * header, copy this into your project's root directory and supply
+ * the \c USE_LUFA_CONFIG_HEADER token to the compiler so that it is
+ * defined in all compiled source files.
+ *
+ * For information on what each token does, refer to the LUFA
+ * manual section "Summary of Compile Tokens".
+ */
+
+#ifndef __LUFA_CONFIG_H__
+#define __LUFA_CONFIG_H__
+
+ #if (ARCH == ARCH_AVR8)
+
+ /* Non-USB Related Configuration Tokens: */
+// #define DISABLE_TERMINAL_CODES
+
+ /* USB Class Driver Related Tokens: */
+// #define HID_HOST_BOOT_PROTOCOL_ONLY
+// #define HID_STATETABLE_STACK_DEPTH {Insert Value Here}
+// #define HID_USAGE_STACK_DEPTH {Insert Value Here}
+// #define HID_MAX_COLLECTIONS {Insert Value Here}
+// #define HID_MAX_REPORTITEMS {Insert Value Here}
+// #define HID_MAX_REPORT_IDS {Insert Value Here}
+// #define NO_CLASS_DRIVER_AUTOFLUSH
+
+ /* General USB Driver Related Tokens: */
+// #define ORDERED_EP_CONFIG
+// #define USE_STATIC_OPTIONS {Insert Value Here}
+// #define USB_DEVICE_ONLY
+// #define USB_HOST_ONLY
+// #define USB_STREAM_TIMEOUT_MS {Insert Value Here}
+// #define NO_LIMITED_CONTROLLER_CONNECT
+// #define NO_SOF_EVENTS
+
+ /* USB Device Mode Driver Related Tokens: */
+// #define USE_RAM_DESCRIPTORS
+// #define USE_FLASH_DESCRIPTORS
+// #define USE_EEPROM_DESCRIPTORS
+// #define NO_INTERNAL_SERIAL
+// #define FIXED_CONTROL_ENDPOINT_SIZE {Insert Value Here}
+// #define DEVICE_STATE_AS_GPIOR {Insert Value Here}
+// #define FIXED_NUM_CONFIGURATIONS {Insert Value Here}
+// #define CONTROL_ONLY_DEVICE
+// #define INTERRUPT_CONTROL_ENDPOINT
+// #define NO_DEVICE_REMOTE_WAKEUP
+// #define NO_DEVICE_SELF_POWER
+
+ /* USB Host Mode Driver Related Tokens: */
+// #define HOST_STATE_AS_GPIOR {Insert Value Here}
+// #define USB_HOST_TIMEOUT_MS {Insert Value Here}
+// #define HOST_DEVICE_SETTLE_DELAY_MS {Insert Value Here}
+// #define NO_AUTO_VBUS_MANAGEMENT
+// #define INVERTED_VBUS_ENABLE_LINE
+
+ #elif (ARCH == ARCH_XMEGA)
+
+ /* Non-USB Related Configuration Tokens: */
+// #define DISABLE_TERMINAL_CODES
+
+ /* USB Class Driver Related Tokens: */
+// #define HID_HOST_BOOT_PROTOCOL_ONLY
+// #define HID_STATETABLE_STACK_DEPTH {Insert Value Here}
+// #define HID_USAGE_STACK_DEPTH {Insert Value Here}
+// #define HID_MAX_COLLECTIONS {Insert Value Here}
+// #define HID_MAX_REPORTITEMS {Insert Value Here}
+// #define HID_MAX_REPORT_IDS {Insert Value Here}
+// #define NO_CLASS_DRIVER_AUTOFLUSH
+
+ /* General USB Driver Related Tokens: */
+// #define USE_STATIC_OPTIONS {Insert Value Here}
+// #define USB_STREAM_TIMEOUT_MS {Insert Value Here}
+// #define NO_LIMITED_CONTROLLER_CONNECT
+// #define NO_SOF_EVENTS
+
+ /* USB Device Mode Driver Related Tokens: */
+// #define USE_RAM_DESCRIPTORS
+// #define USE_FLASH_DESCRIPTORS
+// #define USE_EEPROM_DESCRIPTORS
+// #define NO_INTERNAL_SERIAL
+// #define FIXED_CONTROL_ENDPOINT_SIZE {Insert Value Here}
+// #define DEVICE_STATE_AS_GPIOR {Insert Value Here}
+// #define FIXED_NUM_CONFIGURATIONS {Insert Value Here}
+// #define CONTROL_ONLY_DEVICE
+// #define MAX_ENDPOINT_INDEX {Insert Value Here}
+// #define NO_DEVICE_REMOTE_WAKEUP
+// #define NO_DEVICE_SELF_POWER
+
+ #elif (ARCH == ARCH_UC3)
+
+ /* Non-USB Related Configuration Tokens: */
+// #define DISABLE_TERMINAL_CODES
+
+ /* USB Class Driver Related Tokens: */
+// #define HID_HOST_BOOT_PROTOCOL_ONLY
+// #define HID_STATETABLE_STACK_DEPTH {Insert Value Here}
+// #define HID_USAGE_STACK_DEPTH {Insert Value Here}
+// #define HID_MAX_COLLECTIONS {Insert Value Here}
+// #define HID_MAX_REPORTITEMS {Insert Value Here}
+// #define HID_MAX_REPORT_IDS {Insert Value Here}
+// #define NO_CLASS_DRIVER_AUTOFLUSH
+
+ /* General USB Driver Related Tokens: */
+// #define ORDERED_EP_CONFIG
+// #define USE_STATIC_OPTIONS {Insert Value Here}
+// #define USB_DEVICE_ONLY
+// #define USB_HOST_ONLY
+// #define USB_STREAM_TIMEOUT_MS {Insert Value Here}
+// #define NO_SOF_EVENTS
+
+ /* USB Device Mode Driver Related Tokens: */
+// #define NO_INTERNAL_SERIAL
+// #define FIXED_CONTROL_ENDPOINT_SIZE {Insert Value Here}
+// #define FIXED_NUM_CONFIGURATIONS {Insert Value Here}
+// #define CONTROL_ONLY_DEVICE
+// #define INTERRUPT_CONTROL_ENDPOINT
+// #define NO_DEVICE_REMOTE_WAKEUP
+// #define NO_DEVICE_SELF_POWER
+
+ /* USB Host Mode Driver Related Tokens: */
+// #define USB_HOST_TIMEOUT_MS {Insert Value Here}
+// #define HOST_DEVICE_SETTLE_DELAY_MS {Insert Value Here}
+// #define NO_AUTO_VBUS_MANAGEMENT
+// #define INVERTED_VBUS_ENABLE_LINE
+
+ #else
+
+ #error Unsupported architecture for this LUFA configuration file.
+
+ #endif
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/WindowsINF/LUFA CDC-ACM.inf b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/WindowsINF/LUFA CDC-ACM.inf
new file mode 100644
index 000000000..212b5bbcb
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/WindowsINF/LUFA CDC-ACM.inf
@@ -0,0 +1,64 @@
+; Windows LUFA CDC ACM Setup File
+; Copyright (c) 2000 Microsoft Corporation
+
+[DefaultInstall]
+CopyINF="LUFA CDC-ACM.inf"
+
+[Version]
+Signature="$Windows NT$"
+Class=Ports
+ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318}
+Provider=%MFGNAME%
+DriverVer=7/1/2012,10.0.0.0
+
+[Manufacturer]
+%MFGNAME%=DeviceList, NTx86, NTamd64, NTia64
+
+[SourceDisksNames]
+
+[SourceDisksFiles]
+
+[DestinationDirs]
+DefaultDestDir=12
+
+[DriverInstall]
+Include=mdmcpq.inf
+CopyFiles=FakeModemCopyFileSection
+AddReg=DriverInstall.AddReg
+
+[DriverInstall.Services]
+Include=mdmcpq.inf
+AddService=usbser, 0x00000002, LowerFilter_Service_Inst
+
+[DriverInstall.AddReg]
+HKR,,EnumPropPages32,,"msports.dll,SerialPortPropPageProvider"
+
+;------------------------------------------------------------------------------
+; Vendor and Product ID Definitions
+;------------------------------------------------------------------------------
+; When developing your USB device, the VID and PID used in the PC side
+; application program and the firmware on the microcontroller must match.
+; Modify the below line to use your VID and PID. Use the format as shown below.
+; Note: One INF file can be used for multiple devices with different VID and PIDs.
+; For each supported device, append ",USB\VID_xxxx&PID_yyyy" to the end of the line.
+;------------------------------------------------------------------------------
+[DeviceList]
+%DESCRIPTION%=DriverInstall, USB\VID_03EB&PID_2044
+
+[DeviceList.NTx86]
+%DESCRIPTION%=DriverInstall, USB\VID_03EB&PID_2044
+
+[DeviceList.NTamd64]
+%DESCRIPTION%=DriverInstall, USB\VID_03EB&PID_2044
+
+[DeviceList.NTia64]
+%DESCRIPTION%=DriverInstall, USB\VID_03EB&PID_2044
+
+;------------------------------------------------------------------------------
+; String Definitions
+;------------------------------------------------------------------------------
+;Modify these strings to customize your device
+;------------------------------------------------------------------------------
+[Strings]
+MFGNAME="http://www.lufa-lib.org"
+DESCRIPTION="LUFA CDC-ACM Virtual Serial Port"
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/WindowsINF/LUFA RNDIS.inf b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/WindowsINF/LUFA RNDIS.inf
new file mode 100644
index 000000000..73ca50e68
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/WindowsINF/LUFA RNDIS.inf
@@ -0,0 +1,59 @@
+; Windows LUFA RNDIS Setup File
+; Copyright (c) 2000 Microsoft Corporation
+
+[DefaultInstall]
+CopyINF="LUFA RNDIS.inf"
+
+[Version]
+Signature="$Windows NT$"
+Class=Net
+ClassGuid={4d36e972-e325-11ce-bfc1-08002be10318}
+Provider=%MFGNAME%
+DriverVer=7/1/2012,10.0.0.0
+
+[Manufacturer]
+%MFGNAME%=DeviceList, NTx86, NTamd64, NTia64
+
+[ControlFlags]
+ExcludeFromSelect=*
+
+[DriverInstall]
+Characteristics=0x84 ; NCF_PHYSICAL + NCF_HAS_UI
+BusType=15
+include=netrndis.inf
+needs=Usb_Rndis.ndi
+AddReg=Rndis_AddReg_Vista
+
+[DriverInstall.Services]
+include=netrndis.inf
+needs=Usb_Rndis.ndi.Services
+
+;------------------------------------------------------------------------------
+; Vendor and Product ID Definitions
+;------------------------------------------------------------------------------
+; When developing your USB device, the VID and PID used in the PC side
+; application program and the firmware on the microcontroller must match.
+; Modify the below line to use your VID and PID. Use the format as shown below.
+; Note: One INF file can be used for multiple devices with different VID and PIDs.
+; For each supported device, append ",USB\VID_xxxx&PID_yyyy" to the end of the line.
+;------------------------------------------------------------------------------
+[DeviceList]
+%DESCRIPTION%=DriverInstall, USB\VID_03EB&PID_204C
+
+[DeviceList.NTx86]
+%DESCRIPTION%=DriverInstall, USB\VID_03EB&PID_204C
+
+[DeviceList.NTamd64]
+%DESCRIPTION%=DriverInstall, USB\VID_03EB&PID_204C
+
+[DeviceList.NTia64]
+%DESCRIPTION%=DriverInstall, USB\VID_03EB&PID_204C
+
+;------------------------------------------------------------------------------
+; String Definitions
+;------------------------------------------------------------------------------
+;Modify these strings to customize your device
+;------------------------------------------------------------------------------
+[Strings]
+MFGNAME="http://www.lufa-lib.org"
+DESCRIPTION="LUFA RNDIS USB Ethernet Adapter"
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/makefile_template b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/makefile_template
new file mode 100644
index 000000000..efb6aa76f
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/CodeTemplates/makefile_template
@@ -0,0 +1,38 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2014.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+# --------------------------------------
+# LUFA Project Makefile.
+# --------------------------------------
+
+# Run "make help" for target help.
+
+MCU = at90usb1287
+ARCH = AVR8
+BOARD = USBKEY
+F_CPU = 8000000
+F_USB = $(F_CPU)
+OPTIMIZATION = s
+TARGET = Target
+SRC = $(TARGET).c $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS) $(LUFA_SRC_PLATFORM)
+LUFA_PATH = ../../LUFA
+CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -IConfig
+LD_FLAGS =
+
+# Default target
+all:
+
+# Include LUFA build script makefiles
+include $(LUFA_PATH)/Build/lufa_core.mk
+include $(LUFA_PATH)/Build/lufa_sources.mk
+include $(LUFA_PATH)/Build/lufa_build.mk
+include $(LUFA_PATH)/Build/lufa_cppcheck.mk
+include $(LUFA_PATH)/Build/lufa_doxygen.mk
+include $(LUFA_PATH)/Build/lufa_dfu.mk
+include $(LUFA_PATH)/Build/lufa_hid.mk
+include $(LUFA_PATH)/Build/lufa_avrdude.mk
+include $(LUFA_PATH)/Build/lufa_atprogram.mk
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Common/ArchitectureSpecific.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Common/ArchitectureSpecific.h
new file mode 100644
index 000000000..292e27b37
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Common/ArchitectureSpecific.h
@@ -0,0 +1,185 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Architecture specific definitions relating to specific processor architectures.
+ *
+ * \copydetails Group_ArchitectureSpecific
+ *
+ * \note Do not include this file directly, rather include the Common.h header file instead to gain this file's
+ * functionality.
+ */
+
+/** \ingroup Group_Common
+ * \defgroup Group_ArchitectureSpecific Architecture Specific Definitions
+ * \brief Architecture specific definitions relating to specific processor architectures.
+ *
+ * Architecture specific macros, functions and other definitions, which relate to specific architectures. This
+ * definitions may or may not be available in some form on other architectures, and thus should be protected by
+ * preprocessor checks in portable code to prevent compile errors.
+ *
+ * @{
+ */
+
+#ifndef __LUFA_ARCHSPEC_H__
+#define __LUFA_ARCHSPEC_H__
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_COMMON_H)
+ #error Do not include this file directly. Include LUFA/Common/Common.h instead to gain this functionality.
+ #endif
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ #if (ARCH == ARCH_AVR8) || (ARCH == ARCH_XMEGA) || defined(__DOXYGEN__)
+ #if (ARCH == ARCH_AVR8) || defined(__DOXYGEN__)
+ /** Re-enables the AVR's JTAG bus in software, until a system reset. This will re-enable JTAG debugging
+ * interface after is has been disabled in software via \ref JTAG_DISABLE().
+ *
+ * \note This macro is not available for all architectures.
+ */
+ #define JTAG_ENABLE() do { \
+ __asm__ __volatile__ ( \
+ "in __tmp_reg__,__SREG__" "\n\t" \
+ "cli" "\n\t" \
+ "out %1, %0" "\n\t" \
+ "out __SREG__, __tmp_reg__" "\n\t" \
+ "out %1, %0" "\n\t" \
+ : \
+ : "r" (MCUCR & ~(1 << JTD)), \
+ "M" (_SFR_IO_ADDR(MCUCR)) \
+ : "r0"); \
+ } while (0)
+
+ /** Disables the AVR's JTAG bus in software, until a system reset. This will override the current JTAG
+ * status as set by the JTAGEN fuse, disabling JTAG debugging and reverting the JTAG pins back to GPIO
+ * mode.
+ *
+ * \note This macro is not available for all architectures.
+ */
+ #define JTAG_DISABLE() do { \
+ __asm__ __volatile__ ( \
+ "in __tmp_reg__,__SREG__" "\n\t" \
+ "cli" "\n\t" \
+ "out %1, %0" "\n\t" \
+ "out __SREG__, __tmp_reg__" "\n\t" \
+ "out %1, %0" "\n\t" \
+ : \
+ : "r" (MCUCR | (1 << JTD)), \
+ "M" (_SFR_IO_ADDR(MCUCR)) \
+ : "r0"); \
+ } while (0)
+ #endif
+
+ /** Defines a volatile \c NOP statement which cannot be optimized out by the compiler, and thus can always
+ * be set as a breakpoint in the resulting code. Useful for debugging purposes, where the optimizer
+ * removes/reorders code to the point where break points cannot reliably be set.
+ *
+ * \note This macro is not available for all architectures.
+ */
+ #define JTAG_DEBUG_POINT() __asm__ __volatile__ ("nop" ::)
+
+ /** Defines an explicit JTAG break point in the resulting binary via the assembly \c BREAK statement. When
+ * a JTAG is used, this causes the program execution to halt when reached until manually resumed.
+ *
+ * \note This macro is not available for all architectures.
+ */
+ #define JTAG_DEBUG_BREAK() __asm__ __volatile__ ("break" ::)
+
+ /** Macro for testing condition "x" and breaking via \ref JTAG_DEBUG_BREAK() if the condition is false.
+ *
+ * \note This macro is not available for all architectures.
+ *
+ * \param[in] Condition Condition that will be evaluated.
+ */
+ #define JTAG_ASSERT(Condition) do { \
+ if (!(Condition)) \
+ JTAG_DEBUG_BREAK(); \
+ } while (0)
+
+ /** Macro for testing condition \c "x" and writing debug data to the stdout stream if \c false. The stdout stream
+ * must be pre-initialized before this macro is run and linked to an output device, such as the microcontroller's
+ * USART peripheral.
+ *
+ * The output takes the form "{FILENAME}: Function {FUNCTION NAME}, Line {LINE NUMBER}: Assertion {Condition} failed."
+ *
+ * \note This macro is not available for all architectures.
+ *
+ * \param[in] Condition Condition that will be evaluated,
+ */
+ #define STDOUT_ASSERT(Condition) do { \
+ if (!(Condition)) \
+ printf_P(PSTR("%s: Function \"%s\", Line %d: " \
+ "Assertion \"%s\" failed.\r\n"), \
+ __FILE__, __func__, __LINE__, #Condition); \
+ } while (0)
+
+ #if !defined(pgm_read_ptr) || defined(__DOXYGEN__)
+ /** Reads a pointer out of PROGMEM space on the AVR8 architecture. This is a wrapper for the avr-libc
+ * \c pgm_read_word() macro with a \c void* cast, so that its value can be assigned directly to a
+ * pointer variable or used in pointer arithmetic without further casting in C.
+ *
+ * \note This macro is not available for all architectures.
+ *
+ * \param[in] Address Address of the pointer to read.
+ *
+ * \return Pointer retrieved from PROGMEM space.
+ */
+ #define pgm_read_ptr(Address) (void*)pgm_read_word(Address)
+ #endif
+ #elif (ARCH == ARCH_UC3)
+ #define JTAG_DEBUG_POINT() __asm__ __volatile__ ("nop" ::)
+ #define JTAG_DEBUG_BREAK() __asm__ __volatile__ ("breakpoint" ::)
+ #define JTAG_ASSERT(Condition) do { \
+ if (!(Condition)) \
+ JTAG_DEBUG_BREAK(); \
+ } while (0)
+ #define STDOUT_ASSERT(Condition) do { \
+ if (!(Condition)) \
+ printf("%s: Function \"%s\", Line %d: " \
+ "Assertion \"%s\" failed.\r\n", \
+ __FILE__, __func__, __LINE__, #Condition); \
+ } while (0)
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Common/Architectures.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Common/Architectures.h
new file mode 100644
index 000000000..265b41244
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Common/Architectures.h
@@ -0,0 +1,84 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Supported library architecture defines.
+ *
+ * \copydetails Group_Architectures
+ *
+ * \note Do not include this file directly, rather include the Common.h header file instead to gain this file's
+ * functionality.
+ */
+
+/** \ingroup Group_Common
+ * \defgroup Group_Architectures Hardware Architectures
+ * \brief Supported library architecture defines.
+ *
+ * Architecture macros for selecting the desired target microcontroller architecture. One of these values should be
+ * defined as the value of \c ARCH in the user project makefile via the \c -D compiler switch to GCC, to select the
+ * target architecture.
+ *
+ * The selected architecture should remain consistent with the makefile \c ARCH value, which is used to select the
+ * underlying driver source files for each architecture.
+ *
+ * @{
+ */
+
+#ifndef __LUFA_ARCHITECTURES_H__
+#define __LUFA_ARCHITECTURES_H__
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_COMMON_H)
+ #error Do not include this file directly. Include LUFA/Common/Common.h instead to gain this functionality.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Selects the Atmel 8-bit AVR (AT90USB* and ATMEGA*U* chips) architecture. */
+ #define ARCH_AVR8 0
+
+ /** Selects the Atmel 32-bit UC3 AVR (AT32UC3* chips) architecture. */
+ #define ARCH_UC3 1
+
+ /** Selects the Atmel XMEGA AVR (ATXMEGA* chips) architecture. */
+ #define ARCH_XMEGA 2
+
+ #if !defined(__DOXYGEN__)
+ #define ARCH_ ARCH_AVR8
+
+ #if !defined(ARCH)
+ #define ARCH ARCH_AVR8
+ #endif
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Common/Attributes.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Common/Attributes.h
new file mode 100644
index 000000000..dc5c6be4c
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Common/Attributes.h
@@ -0,0 +1,150 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Special function/variable attribute macros.
+ *
+ * \copydetails Group_FuncVarAttributes
+ *
+ * \note Do not include this file directly, rather include the Common.h header file instead to gain this file's
+ * functionality.
+ */
+
+/** \ingroup Group_Common
+ * \defgroup Group_FuncVarAttributes Function/Variable Attributes
+ * \brief Special function/variable attribute macros.
+ *
+ * This module contains macros for applying specific attributes to functions and variables to control various
+ * optimizer and code generation features of the compiler. Attributes may be placed in the function prototype
+ * or variable declaration in any order, and multiple attributes can be specified for a single item via a space
+ * separated list.
+ *
+ * On incompatible versions of GCC or on other compilers, these macros evaluate to nothing unless they are
+ * critical to the code's function and thus must throw a compile error when used.
+ *
+ * @{
+ */
+
+#ifndef __LUFA_ATTR_H__
+#define __LUFA_ATTR_H__
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_COMMON_H)
+ #error Do not include this file directly. Include LUFA/Common/Common.h instead to gain this functionality.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ #if (__GNUC__ >= 3) || defined(__DOXYGEN__)
+ /** Indicates to the compiler that the function can not ever return, so that any stack restoring or
+ * return code may be omitted by the compiler in the resulting binary.
+ */
+ #define ATTR_NO_RETURN __attribute__ ((noreturn))
+
+ /** Indicates that the function returns a value which should not be ignored by the user code. When
+ * applied, any ignored return value from calling the function will produce a compiler warning.
+ */
+ #define ATTR_WARN_UNUSED_RESULT __attribute__ ((warn_unused_result))
+
+ /** Indicates that the specified parameters of the function are pointers which should never be \c NULL.
+ * When applied as a 1-based comma separated list the compiler will emit a warning if the specified
+ * parameters are known at compiler time to be \c NULL at the point of calling the function.
+ */
+ #define ATTR_NON_NULL_PTR_ARG(...) __attribute__ ((nonnull (__VA_ARGS__)))
+
+ /** Removes any preamble or postamble from the function. When used, the function will not have any
+ * register or stack saving code. This should be used with caution, and when used the programmer
+ * is responsible for maintaining stack and register integrity.
+ */
+ #define ATTR_NAKED __attribute__ ((naked))
+
+ /** Prevents the compiler from considering a specified function for in-lining. When applied, the given
+ * function will not be in-lined under any circumstances.
+ */
+ #define ATTR_NO_INLINE __attribute__ ((noinline))
+
+ /** Forces the compiler to inline the specified function. When applied, the given function will be
+ * in-lined under all circumstances.
+ */
+ #define ATTR_ALWAYS_INLINE __attribute__ ((always_inline))
+
+ /** Indicates that the specified function is pure, in that it has no side-effects other than global
+ * or parameter variable access.
+ */
+ #define ATTR_PURE __attribute__ ((pure))
+
+ /** Indicates that the specified function is constant, in that it has no side effects other than
+ * parameter access.
+ */
+ #define ATTR_CONST __attribute__ ((const))
+
+ /** Marks a given function as deprecated, which produces a warning if the function is called. */
+ #define ATTR_DEPRECATED __attribute__ ((deprecated))
+
+ /** Marks a function as a weak reference, which can be overridden by other functions with an
+ * identical name (in which case the weak reference is discarded at link time).
+ */
+ #define ATTR_WEAK __attribute__ ((weak))
+ #endif
+
+ /** Forces the compiler to not automatically zero the given global variable on startup, so that the
+ * current RAM contents is retained. Under most conditions this value will be random due to the
+ * behavior of volatile memory once power is removed, but may be used in some specific circumstances,
+ * like the passing of values back after a system watchdog reset.
+ */
+ #define ATTR_NO_INIT __attribute__ ((section (".noinit")))
+
+ /** Places the function in one of the initialization sections, which execute before the main function
+ * of the application. Refer to the avr-libc manual for more information on the initialization sections.
+ *
+ * \param[in] SectionIndex Initialization section number where the function should be placed.
+ */
+ #define ATTR_INIT_SECTION(SectionIndex) __attribute__ ((used, naked, section (".init" #SectionIndex )))
+
+ /** Marks a function as an alias for another function.
+ *
+ * \param[in] Func Name of the function which the given function name should alias.
+ */
+ #define ATTR_ALIAS(Func) __attribute__ ((alias( #Func )))
+
+ /** Marks a variable or struct element for packing into the smallest space available, omitting any
+ * alignment bytes usually added between fields to optimize field accesses.
+ */
+ #define ATTR_PACKED __attribute__ ((packed))
+
+ /** Indicates the minimum alignment in bytes for a variable or struct element.
+ *
+ * \param[in] Bytes Minimum number of bytes the item should be aligned to.
+ */
+ #define ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes)))
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Common/BoardTypes.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Common/BoardTypes.h
new file mode 100644
index 000000000..06ff4ddb4
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Common/BoardTypes.h
@@ -0,0 +1,254 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Supported pre-made board hardware defines.
+ *
+ * \copydetails Group_BoardTypes
+ *
+ * \note Do not include this file directly, rather include the Common.h header file instead to gain this file's
+ * functionality.
+ */
+
+/** \ingroup Group_Common
+ * \defgroup Group_BoardTypes Board Types
+ * \brief Supported pre-made board hardware defines.
+ *
+ * Board macros for indicating the chosen physical board hardware to the library. These macros should be used when
+ * defining the \c BOARD token to the chosen hardware via the \c -D switch in the project makefile. If a custom
+ * board is used, the \ref BOARD_NONE or \ref BOARD_USER values should be selected.
+ *
+ * @{
+ */
+
+#ifndef __LUFA_BOARDTYPES_H__
+#define __LUFA_BOARDTYPES_H__
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_COMMON_H)
+ #error Do not include this file directly. Include LUFA/Common/Common.h instead to gain this functionality.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Selects the user-defined board drivers, which should be placed in the user project's folder
+ * under a directory named \c /Board/. Each board driver should be named identically to the LUFA
+ * master board driver (i.e., driver in the \c LUFA/Drivers/Board directory) so that the library
+ * can correctly identify it.
+ */
+ #define BOARD_USER 0
+
+ /** Disables board drivers when operation will not be adversely affected (e.g. LEDs) - use of board drivers
+ * such as the Joystick driver, where the removal would adversely affect the code's operation is still disallowed. */
+ #define BOARD_NONE 1
+
+ /** Selects the USBKEY specific board drivers, including Temperature, Button, Dataflash, Joystick and LED drivers. */
+ #define BOARD_USBKEY 2
+
+ /** Selects the STK525 specific board drivers, including Temperature, Button, Dataflash, Joystick and LED drivers. */
+ #define BOARD_STK525 3
+
+ /** Selects the STK526 specific board drivers, including Temperature, Button, Dataflash, Joystick and LED drivers. */
+ #define BOARD_STK526 4
+
+ /** Selects the RZUSBSTICK specific board drivers, including the driver for the boards LEDs. */
+ #define BOARD_RZUSBSTICK 5
+
+ /** Selects the ATAVRUSBRF01 specific board drivers, including the driver for the board LEDs. */
+ #define BOARD_ATAVRUSBRF01 6
+
+ /** Selects the BUMBLEB specific board drivers, using the officially recommended peripheral layout. */
+ #define BOARD_BUMBLEB 7
+
+ /** Selects the XPLAIN (Revision 2 or newer) specific board drivers, including LED and Dataflash drivers. */
+ #define BOARD_XPLAIN 8
+
+ /** Selects the XPLAIN (Revision 1) specific board drivers, including LED and Dataflash drivers. */
+ #define BOARD_XPLAIN_REV1 9
+
+ /** Selects the EVK527 specific board drivers, including Temperature, Button, Dataflash, Joystick and LED drivers. */
+ #define BOARD_EVK527 10
+
+ /** Selects the Teensy version 1.x specific board drivers, including the driver for the board LEDs. */
+ #define BOARD_TEENSY 11
+
+ /** Selects the USBTINY MKII specific board drivers, including the Button and LEDs drivers. */
+ #define BOARD_USBTINYMKII 12
+
+ /** Selects the Benito specific board drivers, including the Button and LEDs drivers. */
+ #define BOARD_BENITO 13
+
+ /** Selects the JM-DB-U2 specific board drivers, including the Button and LEDs drivers. */
+ #define BOARD_JMDBU2 14
+
+ /** Selects the Olimex AVR-USB-162 specific board drivers, including the Button and LEDs drivers. */
+ #define BOARD_OLIMEX162 15
+
+ /** Selects the UDIP specific board drivers, including the Button and LEDs drivers. */
+ #define BOARD_UDIP 16
+
+ /** Selects the BUI specific board drivers, including the driver for the board LEDs. */
+ #define BOARD_BUI 17
+
+ /** Selects the Arduino Uno specific board drivers, including the driver for the board LEDs. */
+ #define BOARD_UNO 18
+
+ /** Selects the Busware CUL V3 specific board drivers, including the Button and LEDs drivers. */
+ #define BOARD_CULV3 19
+
+ /** Selects the Blackcat USB JTAG specific board drivers, including the driver for the board LEDs. */
+ #define BOARD_BLACKCAT 20
+
+ /** Selects the Maximus specific board drivers, including the driver for the board LEDs. */
+ #define BOARD_MAXIMUS 21
+
+ /** Selects the Minimus specific board drivers, including the Button and LEDs drivers. */
+ #define BOARD_MINIMUS 22
+
+ /** Selects the Adafruit U4 specific board drivers, including the Button driver. */
+ #define BOARD_ADAFRUITU4 23
+
+ /** Selects the Microsin AVR-USB162 specific board drivers, including the Button and LEDs drivers. */
+ #define BOARD_MICROSIN162 24
+
+ /** Selects the Kernel Concepts USBFOO specific board drivers, including the Button and LEDs drivers. */
+ #define BOARD_USBFOO 25
+
+ /** Selects the Sparkfun ATMEGA8U2 specific board drivers, including the driver for the board LEDs. */
+ #define BOARD_SPARKFUN8U2 26
+
+ /** Selects the Atmel EVK1101 specific board drivers, including the Button, Joystick and LED drivers. */
+ #define BOARD_EVK1101 27
+
+ /** Selects the Busware TUL specific board drivers, including the Button and LED drivers. */
+ #define BOARD_TUL 28
+
+ /** Selects the Atmel EVK1100 specific board drivers, including the Button, Joystick and LED drivers. */
+ #define BOARD_EVK1100 29
+
+ /** Selects the Atmel EVK1104 specific board drivers, including the Button and LED drivers. */
+ #define BOARD_EVK1104 30
+
+ /** Selects the Atmel XMEGA A3BU Xplained specific board drivers, including Dataflash, Button and LED drivers. */
+ #define BOARD_A3BU_XPLAINED 31
+
+ /** Selects the Teensy version 2.x specific board drivers, including the driver for the board LEDs. */
+ #define BOARD_TEENSY2 32
+
+ /** Selects the USB2AX version 1 and 2 specific board drivers, including the Button and LEDs drivers. */
+ #define BOARD_USB2AX 33
+
+ /** Selects the USB2AX version 3 specific board drivers, including the Button and LEDs drivers. */
+ #define BOARD_USB2AX_V3 34
+
+ /** Selects the Micropendous 32U2 specific board drivers, including the Button and LED drivers. */
+ #define BOARD_MICROPENDOUS_32U2 35
+
+ /** Selects the Micropendous A specific board drivers, including the driver for the board Button. */
+ #define BOARD_MICROPENDOUS_A 36
+
+ /** Selects the Micropendous 1 specific board drivers, including the driver for the board Button. */
+ #define BOARD_MICROPENDOUS_1 37
+
+ /** Selects the Micropendous 2 specific board drivers, including the driver for the board Button. */
+ #define BOARD_MICROPENDOUS_2 38
+
+ /** Selects the Micropendous 3 specific board drivers, including the driver for the board Button. */
+ #define BOARD_MICROPENDOUS_3 39
+
+ /** Selects the Micropendous 4 specific board drivers, including the driver for the board Button. */
+ #define BOARD_MICROPENDOUS_4 40
+
+ /** Selects the Micropendous DIP specific board drivers, including the driver for the board Button. */
+ #define BOARD_MICROPENDOUS_DIP 41
+
+ /** Selects the Micropendous (Arduino-like) revision 1 specific board drivers, including the Button and LED drivers. */
+ #define BOARD_MICROPENDOUS_REV1 42
+
+ /** Selects the Micropendous (Arduino-like) revision 2 specific board drivers, including the Button and LED drivers. */
+ #define BOARD_MICROPENDOUS_REV2 43
+
+ /** Selects the XMEGA B1 Xplained specific board drivers, including the Button and LED drivers. */
+ #define BOARD_B1_XPLAINED 44
+
+ /** Selects the Bitwizard Multio specific board drivers, including the driver for the board LEDs. */
+ #define BOARD_MULTIO 45
+
+ /** Selects the Bitwizard Big-Multio specific board drivers, including the driver for the board LEDs. */
+ #define BOARD_BIGMULTIO 46
+
+ /** Selects the DorkbotPDX Duce specific board drivers, including the driver for the board LEDs. */
+ #define BOARD_DUCE 47
+
+ /** Selects the Olimex AVR-USB-32U4 specific board drivers, including the Button and LED drivers. */
+ #define BOARD_OLIMEX32U4 48
+
+ /** Selects the Olimex AVR-USB-T32U4 specific board drivers, including the Button and LED drivers. */
+ #define BOARD_OLIMEXT32U4 49
+
+ /** Selects the Olimex AVR-ISP-MK2 specific board drivers, including the Button and LED drivers. */
+ #define BOARD_OLIMEXISPMK2 50
+
+ /** Selects the Arduino Leonardo specific board drivers, including the driver for the board LEDs. */
+ #define BOARD_LEONARDO 51
+
+ /** Selects the UC3-A3 Xplained specific board drivers, including the Button and LED drivers. */
+ #define BOARD_UC3A3_XPLAINED 52
+
+ /** Selects the USB2AX version 3.1 specific board drivers, including the Button and LEDs drivers. */
+ #define BOARD_USB2AX_V31 53
+
+ /** Selects the Stange-ISP specific board drivers, including the Button and LEDs drivers. */
+ #define BOARD_STANGE_ISP 54
+
+ /** Selects the XMEGA C3 XPLAINED specific board drivers, including the Button and LEDs drivers. */
+ #define BOARD_C3_XPLAINED 55
+
+ /** Selects the U2S specific board drivers, including the Button and LEDs drivers. */
+ #define BOARD_U2S 56
+
+ /** Selects the Arduino YUN specific board drivers, including the driver for the board LEDs. */
+ #define BOARD_YUN 57
+
+ /** Selects the Arduino Micro specific board drivers, including the driver for the board LEDs. */
+ #define BOARD_MICRO 58
+
+ #if !defined(__DOXYGEN__)
+ #define BOARD_ BOARD_NONE
+
+ #if !defined(BOARD)
+ #define BOARD BOARD_NONE
+ #endif
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Common/Common.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Common/Common.h
new file mode 100644
index 000000000..3e12e4f33
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Common/Common.h
@@ -0,0 +1,393 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \dir
+ * \brief Common library header files.
+ *
+ * This folder contains header files which are common to all parts of the LUFA library. They may be used freely in
+ * user applications.
+ */
+
+/** \file
+ * \brief Common library convenience headers, macros and functions.
+ *
+ * \copydetails Group_Common
+ */
+
+/** \defgroup Group_Common Common Utility Headers - LUFA/Drivers/Common/Common.h
+ * \brief Common library convenience headers, macros and functions.
+ *
+ * Common utility headers containing macros, functions, enums and types which are common to all
+ * aspects of the library.
+ *
+ * @{
+ */
+
+/** \defgroup Group_GlobalInt Global Interrupt Macros
+ * \brief Convenience macros for the management of interrupts globally within the device.
+ *
+ * Macros and functions to create and control global interrupts within the device.
+ */
+
+#ifndef __LUFA_COMMON_H__
+#define __LUFA_COMMON_H__
+
+ /* Macros: */
+ #define __INCLUDE_FROM_COMMON_H
+
+ /* Includes: */
+ #include <stdint.h>
+ #include <stdbool.h>
+ #include <string.h>
+ #include <stddef.h>
+
+ #include "Architectures.h"
+ #include "BoardTypes.h"
+ #include "ArchitectureSpecific.h"
+ #include "CompilerSpecific.h"
+ #include "Attributes.h"
+
+ #if defined(USE_LUFA_CONFIG_HEADER)
+ #include "LUFAConfig.h"
+ #endif
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Architecture specific utility includes: */
+ #if defined(__DOXYGEN__)
+ /** Type define for an unsigned integer the same width as the selected architecture's machine register.
+ * This is distinct from the non-specific standard int data type, whose width is machine dependant but
+ * which may not reflect the actual machine register width on some targets (e.g. AVR8).
+ */
+ typedef MACHINE_REG_t uint_reg_t;
+ #elif (ARCH == ARCH_AVR8)
+ #include <avr/io.h>
+ #include <avr/interrupt.h>
+ #include <avr/pgmspace.h>
+ #include <avr/eeprom.h>
+ #include <avr/boot.h>
+ #include <math.h>
+ #include <util/delay.h>
+
+ typedef uint8_t uint_reg_t;
+
+ #define ARCH_HAS_EEPROM_ADDRESS_SPACE
+ #define ARCH_HAS_FLASH_ADDRESS_SPACE
+ #define ARCH_HAS_MULTI_ADDRESS_SPACE
+ #define ARCH_LITTLE_ENDIAN
+
+ #include "Endianness.h"
+ #elif (ARCH == ARCH_UC3)
+ #include <avr32/io.h>
+ #include <math.h>
+
+ // === TODO: Find abstracted way to handle these ===
+ #define PROGMEM
+ #define pgm_read_byte(x) *x
+ #define memcmp_P(...) memcmp(__VA_ARGS__)
+ #define memcpy_P(...) memcpy(__VA_ARGS__)
+ // =================================================
+
+ typedef uint32_t uint_reg_t;
+
+ #define ARCH_BIG_ENDIAN
+
+ #include "Endianness.h"
+ #elif (ARCH == ARCH_XMEGA)
+ #include <avr/io.h>
+ #include <avr/interrupt.h>
+ #include <avr/pgmspace.h>
+ #include <avr/eeprom.h>
+ #include <math.h>
+ #include <util/delay.h>
+
+ typedef uint8_t uint_reg_t;
+
+ #define ARCH_HAS_EEPROM_ADDRESS_SPACE
+ #define ARCH_HAS_FLASH_ADDRESS_SPACE
+ #define ARCH_HAS_MULTI_ADDRESS_SPACE
+ #define ARCH_LITTLE_ENDIAN
+
+ #include "Endianness.h"
+ #else
+ #error Unknown device architecture specified.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ #if !defined(__DOXYGEN__)
+ // Obsolete, retained for compatibility with user code
+ #define MACROS do
+ #define MACROE while (0)
+ #endif
+
+ /** Convenience macro to determine the larger of two values.
+ *
+ * \attention This macro should only be used with operands that do not have side effects from being evaluated
+ * multiple times.
+ *
+ * \param[in] x First value to compare
+ * \param[in] y First value to compare
+ *
+ * \return The larger of the two input parameters
+ */
+ #if !defined(MAX) || defined(__DOXYGEN__)
+ #define MAX(x, y) (((x) > (y)) ? (x) : (y))
+ #endif
+
+ /** Convenience macro to determine the smaller of two values.
+ *
+ * \attention This macro should only be used with operands that do not have side effects from being evaluated
+ * multiple times.
+ *
+ * \param[in] x First value to compare.
+ * \param[in] y First value to compare.
+ *
+ * \return The smaller of the two input parameters
+ */
+ #if !defined(MIN) || defined(__DOXYGEN__)
+ #define MIN(x, y) (((x) < (y)) ? (x) : (y))
+ #endif
+
+ #if !defined(STRINGIFY) || defined(__DOXYGEN__)
+ /** Converts the given input into a string, via the C Preprocessor. This macro puts literal quotation
+ * marks around the input, converting the source into a string literal.
+ *
+ * \param[in] x Input to convert into a string literal.
+ *
+ * \return String version of the input.
+ */
+ #define STRINGIFY(x) #x
+
+ /** Converts the given input into a string after macro expansion, via the C Preprocessor. This macro puts
+ * literal quotation marks around the expanded input, converting the source into a string literal.
+ *
+ * \param[in] x Input to expand and convert into a string literal.
+ *
+ * \return String version of the expanded input.
+ */
+ #define STRINGIFY_EXPANDED(x) STRINGIFY(x)
+ #endif
+
+ #if !defined(CONCAT) || defined(__DOXYGEN__)
+ /** Concatenates the given input into a single token, via the C Preprocessor.
+ *
+ * \param[in] x First item to concatenate.
+ * \param[in] y Second item to concatenate.
+ *
+ * \return Concatenated version of the input.
+ */
+ #define CONCAT(x, y) x ## y
+
+ /** CConcatenates the given input into a single token after macro expansion, via the C Preprocessor.
+ *
+ * \param[in] x First item to concatenate.
+ * \param[in] y Second item to concatenate.
+ *
+ * \return Concatenated version of the expanded input.
+ */
+ #define CONCAT_EXPANDED(x, y) CONCAT(x, y)
+ #endif
+
+ #if !defined(ISR) || defined(__DOXYGEN__)
+ /** Macro for the definition of interrupt service routines, so that the compiler can insert the required
+ * prologue and epilogue code to properly manage the interrupt routine without affecting the main thread's
+ * state with unintentional side-effects.
+ *
+ * Interrupt handlers written using this macro may still need to be registered with the microcontroller's
+ * Interrupt Controller (if present) before they will properly handle incoming interrupt events.
+ *
+ * \note This macro is only supplied on some architectures, where the standard library does not include a valid
+ * definition. If an existing definition exists, the alternative definition here will be ignored.
+ *
+ * \ingroup Group_GlobalInt
+ *
+ * \param[in] Name Unique name of the interrupt service routine.
+ */
+ #define ISR(Name, ...) void Name (void) __attribute__((__interrupt__)) __VA_ARGS__; void Name (void)
+ #endif
+
+ /* Inline Functions: */
+ /** Function to reverse the individual bits in a byte - i.e. bit 7 is moved to bit 0, bit 6 to bit 1,
+ * etc.
+ *
+ * \param[in] Byte Byte of data whose bits are to be reversed.
+ *
+ * \return Input data with the individual bits reversed (mirrored).
+ */
+ static inline uint8_t BitReverse(uint8_t Byte) ATTR_WARN_UNUSED_RESULT ATTR_CONST;
+ static inline uint8_t BitReverse(uint8_t Byte)
+ {
+ Byte = (((Byte & 0xF0) >> 4) | ((Byte & 0x0F) << 4));
+ Byte = (((Byte & 0xCC) >> 2) | ((Byte & 0x33) << 2));
+ Byte = (((Byte & 0xAA) >> 1) | ((Byte & 0x55) << 1));
+
+ return Byte;
+ }
+
+ /** Function to perform a blocking delay for a specified number of milliseconds. The actual delay will be
+ * at a minimum the specified number of milliseconds, however due to loop overhead and internal calculations
+ * may be slightly higher.
+ *
+ * \param[in] Milliseconds Number of milliseconds to delay
+ */
+ static inline void Delay_MS(uint16_t Milliseconds) ATTR_ALWAYS_INLINE;
+ static inline void Delay_MS(uint16_t Milliseconds)
+ {
+ #if (ARCH == ARCH_AVR8)
+ if (GCC_IS_COMPILE_CONST(Milliseconds))
+ {
+ _delay_ms(Milliseconds);
+ }
+ else
+ {
+ while (Milliseconds--)
+ _delay_ms(1);
+ }
+ #elif (ARCH == ARCH_UC3)
+ while (Milliseconds--)
+ {
+ __builtin_mtsr(AVR32_COUNT, 0);
+ while ((uint32_t)__builtin_mfsr(AVR32_COUNT) < (F_CPU / 1000));
+ }
+ #elif (ARCH == ARCH_XMEGA)
+ if (GCC_IS_COMPILE_CONST(Milliseconds))
+ {
+ _delay_ms(Milliseconds);
+ }
+ else
+ {
+ while (Milliseconds--)
+ _delay_ms(1);
+ }
+ #endif
+ }
+
+ /** Retrieves a mask which contains the current state of the global interrupts for the device. This
+ * value can be stored before altering the global interrupt enable state, before restoring the
+ * flag(s) back to their previous values after a critical section using \ref SetGlobalInterruptMask().
+ *
+ * \ingroup Group_GlobalInt
+ *
+ * \return Mask containing the current Global Interrupt Enable Mask bit(s).
+ */
+ static inline uint_reg_t GetGlobalInterruptMask(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline uint_reg_t GetGlobalInterruptMask(void)
+ {
+ GCC_MEMORY_BARRIER();
+
+ #if (ARCH == ARCH_AVR8)
+ return SREG;
+ #elif (ARCH == ARCH_UC3)
+ return __builtin_mfsr(AVR32_SR);
+ #elif (ARCH == ARCH_XMEGA)
+ return SREG;
+ #endif
+ }
+
+ /** Sets the global interrupt enable state of the microcontroller to the mask passed into the function.
+ * This can be combined with \ref GetGlobalInterruptMask() to save and restore the Global Interrupt Enable
+ * Mask bit(s) of the device after a critical section has completed.
+ *
+ * \ingroup Group_GlobalInt
+ *
+ * \param[in] GlobalIntState Global Interrupt Enable Mask value to use
+ */
+ static inline void SetGlobalInterruptMask(const uint_reg_t GlobalIntState) ATTR_ALWAYS_INLINE;
+ static inline void SetGlobalInterruptMask(const uint_reg_t GlobalIntState)
+ {
+ GCC_MEMORY_BARRIER();
+
+ #if (ARCH == ARCH_AVR8)
+ SREG = GlobalIntState;
+ #elif (ARCH == ARCH_UC3)
+ if (GlobalIntState & AVR32_SR_GM)
+ __builtin_ssrf(AVR32_SR_GM_OFFSET);
+ else
+ __builtin_csrf(AVR32_SR_GM_OFFSET);
+ #elif (ARCH == ARCH_XMEGA)
+ SREG = GlobalIntState;
+ #endif
+
+ GCC_MEMORY_BARRIER();
+ }
+
+ /** Enables global interrupt handling for the device, allowing interrupts to be handled.
+ *
+ * \ingroup Group_GlobalInt
+ */
+ static inline void GlobalInterruptEnable(void) ATTR_ALWAYS_INLINE;
+ static inline void GlobalInterruptEnable(void)
+ {
+ GCC_MEMORY_BARRIER();
+
+ #if (ARCH == ARCH_AVR8)
+ sei();
+ #elif (ARCH == ARCH_UC3)
+ __builtin_csrf(AVR32_SR_GM_OFFSET);
+ #elif (ARCH == ARCH_XMEGA)
+ sei();
+ #endif
+
+ GCC_MEMORY_BARRIER();
+ }
+
+ /** Disabled global interrupt handling for the device, preventing interrupts from being handled.
+ *
+ * \ingroup Group_GlobalInt
+ */
+ static inline void GlobalInterruptDisable(void) ATTR_ALWAYS_INLINE;
+ static inline void GlobalInterruptDisable(void)
+ {
+ GCC_MEMORY_BARRIER();
+
+ #if (ARCH == ARCH_AVR8)
+ cli();
+ #elif (ARCH == ARCH_UC3)
+ __builtin_ssrf(AVR32_SR_GM_OFFSET);
+ #elif (ARCH == ARCH_XMEGA)
+ cli();
+ #endif
+
+ GCC_MEMORY_BARRIER();
+ }
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Common/CompilerSpecific.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Common/CompilerSpecific.h
new file mode 100644
index 000000000..9979fffbb
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Common/CompilerSpecific.h
@@ -0,0 +1,97 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Compiler specific definitions for code optimization and correctness.
+ *
+ * \copydetails Group_CompilerSpecific
+ *
+ * \note Do not include this file directly, rather include the Common.h header file instead to gain this file's
+ * functionality.
+ */
+
+/** \ingroup Group_Common
+ * \defgroup Group_CompilerSpecific Compiler Specific Definitions
+ * \brief Compiler specific definitions for code optimization and correctness.
+ *
+ * Compiler specific definitions to expose certain compiler features which may increase the level of code optimization
+ * for a specific compiler, or correct certain issues that may be present such as memory barriers for use in conjunction
+ * with atomic variable access.
+ *
+ * Where possible, on alternative compilers, these macros will either have no effect, or default to returning a sane value
+ * so that they can be used in existing code without the need for extra compiler checks in the user application code.
+ *
+ * @{
+ */
+
+#ifndef __LUFA_COMPILERSPEC_H__
+#define __LUFA_COMPILERSPEC_H__
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_COMMON_H)
+ #error Do not include this file directly. Include LUFA/Common/Common.h instead to gain this functionality.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ #if defined(__GNUC__) || defined(__DOXYGEN__)
+ /** Forces GCC to use pointer indirection (via the device's pointer register pairs) when accessing the given
+ * struct pointer. In some cases GCC will emit non-optimal assembly code when accessing a structure through
+ * a pointer, resulting in a larger binary. When this macro is used on a (non \c const) structure pointer before
+ * use, it will force GCC to use pointer indirection on the elements rather than direct store and load
+ * instructions.
+ *
+ * \param[in, out] StructPtr Pointer to a structure which is to be forced into indirect access mode.
+ */
+ #define GCC_FORCE_POINTER_ACCESS(StructPtr) __asm__ __volatile__("" : "=b" (StructPtr) : "0" (StructPtr))
+
+ /** Forces GCC to create a memory barrier, ensuring that memory accesses are not reordered past the barrier point.
+ * This can be used before ordering-critical operations, to ensure that the compiler does not re-order the resulting
+ * assembly output in an unexpected manner on sections of code that are ordering-specific.
+ */
+ #define GCC_MEMORY_BARRIER() __asm__ __volatile__("" ::: "memory");
+
+ /** Determines if the specified value can be determined at compile-time to be a constant value when compiling under GCC.
+ *
+ * \param[in] x Value to check compile-time constantness of.
+ *
+ * \return Boolean \c true if the given value is known to be a compile time constant, \c false otherwise.
+ */
+ #define GCC_IS_COMPILE_CONST(x) __builtin_constant_p(x)
+ #else
+ #define GCC_FORCE_POINTER_ACCESS(StructPtr)
+ #define GCC_MEMORY_BARRIER()
+ #define GCC_IS_COMPILE_CONST(x) 0
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Common/Endianness.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Common/Endianness.h
new file mode 100644
index 000000000..2eb3ad094
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Common/Endianness.h
@@ -0,0 +1,493 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Endianness and Byte Ordering macros and functions.
+ *
+ * \copydetails Group_Endianness
+ */
+
+/** \ingroup Group_Endianness
+ * \defgroup Group_ByteSwapping Byte Reordering
+ * \brief Macros and functions for forced byte reordering.
+ */
+
+/** \ingroup Group_Endianness
+ * \defgroup Group_EndianConversion Endianness Conversion
+ * \brief Macros and functions for automatic endianness conversion.
+ */
+
+/** \ingroup Group_Common
+ * \defgroup Group_Endianness Endianness and Byte Ordering
+ * \brief Convenience macros and functions relating to byte (re-)ordering
+ *
+ * Common library convenience macros and functions relating to byte (re-)ordering.
+ *
+ * @{
+ */
+
+#ifndef __LUFA_ENDIANNESS_H__
+#define __LUFA_ENDIANNESS_H__
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_COMMON_H)
+ #error Do not include this file directly. Include LUFA/Common/Common.h instead to gain this functionality.
+ #endif
+
+ #if !(defined(ARCH_BIG_ENDIAN) || defined(ARCH_LITTLE_ENDIAN))
+ #error ARCH_BIG_ENDIAN or ARCH_LITTLE_ENDIAN not set for the specified architecture.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Swaps the byte ordering of a 16-bit value at compile-time. Do not use this macro for swapping byte orderings
+ * of dynamic values computed at runtime, use \ref SwapEndian_16() instead. The result of this macro can be used
+ * inside struct or other variable initializers outside of a function, something that is not possible with the
+ * inline function variant.
+ *
+ * \hideinitializer
+ *
+ * \ingroup Group_ByteSwapping
+ *
+ * \param[in] x 16-bit value whose byte ordering is to be swapped.
+ *
+ * \return Input value with the byte ordering reversed.
+ */
+ #define SWAPENDIAN_16(x) (uint16_t)((((x) & 0xFF00) >> 8) | (((x) & 0x00FF) << 8))
+
+ /** Swaps the byte ordering of a 32-bit value at compile-time. Do not use this macro for swapping byte orderings
+ * of dynamic values computed at runtime- use \ref SwapEndian_32() instead. The result of this macro can be used
+ * inside struct or other variable initializers outside of a function, something that is not possible with the
+ * inline function variant.
+ *
+ * \hideinitializer
+ *
+ * \ingroup Group_ByteSwapping
+ *
+ * \param[in] x 32-bit value whose byte ordering is to be swapped.
+ *
+ * \return Input value with the byte ordering reversed.
+ */
+ #define SWAPENDIAN_32(x) (uint32_t)((((x) & 0xFF000000UL) >> 24UL) | (((x) & 0x00FF0000UL) >> 8UL) | \
+ (((x) & 0x0000FF00UL) << 8UL) | (((x) & 0x000000FFUL) << 24UL))
+
+ #if defined(ARCH_BIG_ENDIAN) && !defined(le16_to_cpu)
+ #define le16_to_cpu(x) SwapEndian_16(x)
+ #define le32_to_cpu(x) SwapEndian_32(x)
+ #define be16_to_cpu(x) (x)
+ #define be32_to_cpu(x) (x)
+ #define cpu_to_le16(x) SwapEndian_16(x)
+ #define cpu_to_le32(x) SwapEndian_32(x)
+ #define cpu_to_be16(x) (x)
+ #define cpu_to_be32(x) (x)
+ #define LE16_TO_CPU(x) SWAPENDIAN_16(x)
+ #define LE32_TO_CPU(x) SWAPENDIAN_32(x)
+ #define BE16_TO_CPU(x) (x)
+ #define BE32_TO_CPU(x) (x)
+ #define CPU_TO_LE16(x) SWAPENDIAN_16(x)
+ #define CPU_TO_LE32(x) SWAPENDIAN_32(x)
+ #define CPU_TO_BE16(x) (x)
+ #define CPU_TO_BE32(x) (x)
+ #elif !defined(le16_to_cpu)
+ /** \name Run-time endianness conversion */
+ //@{
+
+ /** Performs a conversion between a Little Endian encoded 16-bit piece of data and the
+ * Endianness of the currently selected CPU architecture.
+ *
+ * On little endian architectures, this macro does nothing.
+ *
+ * \note This macro is designed for run-time conversion of data - for compile-time endianness
+ * conversion, use \ref LE16_TO_CPU instead.
+ *
+ * \ingroup Group_EndianConversion
+ *
+ * \param[in] x Data to perform the endianness conversion on.
+ *
+ * \return Endian corrected version of the input value.
+ */
+ #define le16_to_cpu(x) (x)
+
+ /** Performs a conversion between a Little Endian encoded 32-bit piece of data and the
+ * Endianness of the currently selected CPU architecture.
+ *
+ * On little endian architectures, this macro does nothing.
+ *
+ * \note This macro is designed for run-time conversion of data - for compile-time endianness
+ * conversion, use \ref LE32_TO_CPU instead.
+ *
+ * \ingroup Group_EndianConversion
+ *
+ * \param[in] x Data to perform the endianness conversion on.
+ *
+ * \return Endian corrected version of the input value.
+ */
+ #define le32_to_cpu(x) (x)
+
+ /** Performs a conversion between a Big Endian encoded 16-bit piece of data and the
+ * Endianness of the currently selected CPU architecture.
+ *
+ * On big endian architectures, this macro does nothing.
+ *
+ * \note This macro is designed for run-time conversion of data - for compile-time endianness
+ * conversion, use \ref BE16_TO_CPU instead.
+ *
+ * \ingroup Group_EndianConversion
+ *
+ * \param[in] x Data to perform the endianness conversion on.
+ *
+ * \return Endian corrected version of the input value.
+ */
+ #define be16_to_cpu(x) SwapEndian_16(x)
+
+ /** Performs a conversion between a Big Endian encoded 32-bit piece of data and the
+ * Endianness of the currently selected CPU architecture.
+ *
+ * On big endian architectures, this macro does nothing.
+ *
+ * \note This macro is designed for run-time conversion of data - for compile-time endianness
+ * conversion, use \ref BE32_TO_CPU instead.
+ *
+ * \ingroup Group_EndianConversion
+ *
+ * \param[in] x Data to perform the endianness conversion on.
+ *
+ * \return Endian corrected version of the input value.
+ */
+ #define be32_to_cpu(x) SwapEndian_32(x)
+
+ /** Performs a conversion on a natively encoded 16-bit piece of data to ensure that it
+ * is in Little Endian format regardless of the currently selected CPU architecture.
+ *
+ * On little endian architectures, this macro does nothing.
+ *
+ * \note This macro is designed for run-time conversion of data - for compile-time endianness
+ * conversion, use \ref CPU_TO_LE16 instead.
+ *
+ * \ingroup Group_EndianConversion
+ *
+ * \param[in] x Data to perform the endianness conversion on.
+ *
+ * \return Endian corrected version of the input value.
+ */
+ #define cpu_to_le16(x) (x)
+
+ /** Performs a conversion on a natively encoded 32-bit piece of data to ensure that it
+ * is in Little Endian format regardless of the currently selected CPU architecture.
+ *
+ * On little endian architectures, this macro does nothing.
+ *
+ * \note This macro is designed for run-time conversion of data - for compile-time endianness
+ * conversion, use \ref CPU_TO_LE32 instead.
+ *
+ * \ingroup Group_EndianConversion
+ *
+ * \param[in] x Data to perform the endianness conversion on.
+ *
+ * \return Endian corrected version of the input value.
+ */
+ #define cpu_to_le32(x) (x)
+
+ /** Performs a conversion on a natively encoded 16-bit piece of data to ensure that it
+ * is in Big Endian format regardless of the currently selected CPU architecture.
+ *
+ * On big endian architectures, this macro does nothing.
+ *
+ * \note This macro is designed for run-time conversion of data - for compile-time endianness
+ * conversion, use \ref CPU_TO_BE16 instead.
+ *
+ * \ingroup Group_EndianConversion
+ *
+ * \param[in] x Data to perform the endianness conversion on.
+ *
+ * \return Endian corrected version of the input value.
+ */
+ #define cpu_to_be16(x) SwapEndian_16(x)
+
+ /** Performs a conversion on a natively encoded 32-bit piece of data to ensure that it
+ * is in Big Endian format regardless of the currently selected CPU architecture.
+ *
+ * On big endian architectures, this macro does nothing.
+ *
+ * \note This macro is designed for run-time conversion of data - for compile-time endianness
+ * conversion, use \ref CPU_TO_BE32 instead.
+ *
+ * \ingroup Group_EndianConversion
+ *
+ * \param[in] x Data to perform the endianness conversion on.
+ *
+ * \return Endian corrected version of the input value.
+ */
+ #define cpu_to_be32(x) SwapEndian_32(x)
+
+ //@}
+
+ /** \name Compile-time endianness conversion */
+ //@{
+
+ /** Performs a conversion between a Little Endian encoded 16-bit piece of data and the
+ * Endianness of the currently selected CPU architecture.
+ *
+ * On little endian architectures, this macro does nothing.
+ *
+ * \note This macro is designed for compile-time conversion of data - for run time endianness
+ * conversion, use \ref le16_to_cpu instead.
+ *
+ * \ingroup Group_EndianConversion
+ *
+ * \param[in] x Data to perform the endianness conversion on.
+ *
+ * \return Endian corrected version of the input value.
+ */
+ #define LE16_TO_CPU(x) (x)
+
+ /** Performs a conversion between a Little Endian encoded 32-bit piece of data and the
+ * Endianness of the currently selected CPU architecture.
+ *
+ * On little endian architectures, this macro does nothing.
+ *
+ * \note This macro is designed for compile-time conversion of data - for run time endianness
+ * conversion, use \ref le32_to_cpu instead.
+ *
+ * \ingroup Group_EndianConversion
+ *
+ * \param[in] x Data to perform the endianness conversion on.
+ *
+ * \return Endian corrected version of the input value.
+ */
+ #define LE32_TO_CPU(x) (x)
+
+ /** Performs a conversion between a Big Endian encoded 16-bit piece of data and the
+ * Endianness of the currently selected CPU architecture.
+ *
+ * On big endian architectures, this macro does nothing.
+ *
+ * \note This macro is designed for compile-time conversion of data - for run-time endianness
+ * conversion, use \ref be16_to_cpu instead.
+ *
+ * \ingroup Group_EndianConversion
+ *
+ * \param[in] x Data to perform the endianness conversion on.
+ *
+ * \return Endian corrected version of the input value.
+ */
+ #define BE16_TO_CPU(x) SWAPENDIAN_16(x)
+
+ /** Performs a conversion between a Big Endian encoded 32-bit piece of data and the
+ * Endianness of the currently selected CPU architecture.
+ *
+ * On big endian architectures, this macro does nothing.
+ *
+ * \note This macro is designed for compile-time conversion of data - for run-time endianness
+ * conversion, use \ref be32_to_cpu instead.
+ *
+ * \ingroup Group_EndianConversion
+ *
+ * \param[in] x Data to perform the endianness conversion on.
+ *
+ * \return Endian corrected version of the input value.
+ */
+ #define BE32_TO_CPU(x) SWAPENDIAN_32(x)
+
+ /** Performs a conversion on a natively encoded 16-bit piece of data to ensure that it
+ * is in Little Endian format regardless of the currently selected CPU architecture.
+ *
+ * On little endian architectures, this macro does nothing.
+ *
+ * \note This macro is designed for compile-time conversion of data - for run-time endianness
+ * conversion, use \ref cpu_to_le16 instead.
+ *
+ * \ingroup Group_EndianConversion
+ *
+ * \param[in] x Data to perform the endianness conversion on.
+ *
+ * \return Endian corrected version of the input value.
+ */
+ #define CPU_TO_LE16(x) (x)
+
+ /** Performs a conversion on a natively encoded 32-bit piece of data to ensure that it
+ * is in Little Endian format regardless of the currently selected CPU architecture.
+ *
+ * On little endian architectures, this macro does nothing.
+ *
+ * \note This macro is designed for compile-time conversion of data - for run-time endianness
+ * conversion, use \ref cpu_to_le32 instead.
+ *
+ * \ingroup Group_EndianConversion
+ *
+ * \param[in] x Data to perform the endianness conversion on.
+ *
+ * \return Endian corrected version of the input value.
+ */
+ #define CPU_TO_LE32(x) (x)
+
+ /** Performs a conversion on a natively encoded 16-bit piece of data to ensure that it
+ * is in Big Endian format regardless of the currently selected CPU architecture.
+ *
+ * On big endian architectures, this macro does nothing.
+ *
+ * \note This macro is designed for compile-time conversion of data - for run-time endianness
+ * conversion, use \ref cpu_to_be16 instead.
+ *
+ * \ingroup Group_EndianConversion
+ *
+ * \param[in] x Data to perform the endianness conversion on.
+ *
+ * \return Endian corrected version of the input value.
+ */
+ #define CPU_TO_BE16(x) SWAPENDIAN_16(x)
+
+ /** Performs a conversion on a natively encoded 32-bit piece of data to ensure that it
+ * is in Big Endian format regardless of the currently selected CPU architecture.
+ *
+ * On big endian architectures, this macro does nothing.
+ *
+ * \note This macro is designed for compile-time conversion of data - for run-time endianness
+ * conversion, use \ref cpu_to_be32 instead.
+ *
+ * \ingroup Group_EndianConversion
+ *
+ * \param[in] x Data to perform the endianness conversion on.
+ *
+ * \return Endian corrected version of the input value.
+ */
+ #define CPU_TO_BE32(x) SWAPENDIAN_32(x)
+
+ //! @}
+ #endif
+
+ /* Inline Functions: */
+ /** Function to reverse the byte ordering of the individual bytes in a 16 bit value.
+ *
+ * \ingroup Group_ByteSwapping
+ *
+ * \param[in] Word Word of data whose bytes are to be swapped.
+ *
+ * \return Input data with the individual bytes reversed.
+ */
+ static inline uint16_t SwapEndian_16(const uint16_t Word) ATTR_WARN_UNUSED_RESULT ATTR_CONST;
+ static inline uint16_t SwapEndian_16(const uint16_t Word)
+ {
+ if (GCC_IS_COMPILE_CONST(Word))
+ return SWAPENDIAN_16(Word);
+
+ uint8_t Temp;
+
+ union
+ {
+ uint16_t Word;
+ uint8_t Bytes[2];
+ } Data;
+
+ Data.Word = Word;
+
+ Temp = Data.Bytes[0];
+ Data.Bytes[0] = Data.Bytes[1];
+ Data.Bytes[1] = Temp;
+
+ return Data.Word;
+ }
+
+ /** Function to reverse the byte ordering of the individual bytes in a 32 bit value.
+ *
+ * \ingroup Group_ByteSwapping
+ *
+ * \param[in] DWord Double word of data whose bytes are to be swapped.
+ *
+ * \return Input data with the individual bytes reversed.
+ */
+ static inline uint32_t SwapEndian_32(const uint32_t DWord) ATTR_WARN_UNUSED_RESULT ATTR_CONST;
+ static inline uint32_t SwapEndian_32(const uint32_t DWord)
+ {
+ if (GCC_IS_COMPILE_CONST(DWord))
+ return SWAPENDIAN_32(DWord);
+
+ uint8_t Temp;
+
+ union
+ {
+ uint32_t DWord;
+ uint8_t Bytes[4];
+ } Data;
+
+ Data.DWord = DWord;
+
+ Temp = Data.Bytes[0];
+ Data.Bytes[0] = Data.Bytes[3];
+ Data.Bytes[3] = Temp;
+
+ Temp = Data.Bytes[1];
+ Data.Bytes[1] = Data.Bytes[2];
+ Data.Bytes[2] = Temp;
+
+ return Data.DWord;
+ }
+
+ /** Function to reverse the byte ordering of the individual bytes in a n byte value.
+ *
+ * \ingroup Group_ByteSwapping
+ *
+ * \param[in,out] Data Pointer to a number containing an even number of bytes to be reversed.
+ * \param[in] Length Length of the data in bytes.
+ *
+ * \return Input data with the individual bytes reversed.
+ */
+ static inline void SwapEndian_n(void* const Data,
+ uint8_t Length) ATTR_NON_NULL_PTR_ARG(1);
+ static inline void SwapEndian_n(void* const Data,
+ uint8_t Length)
+ {
+ uint8_t* CurrDataPos = (uint8_t*)Data;
+
+ while (Length > 1)
+ {
+ uint8_t Temp = *CurrDataPos;
+ *CurrDataPos = *(CurrDataPos + Length - 1);
+ *(CurrDataPos + Length - 1) = Temp;
+
+ CurrDataPos++;
+ Length -= 2;
+ }
+ }
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/BuildSystem.txt b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/BuildSystem.txt
new file mode 100644
index 000000000..7ddfa1be3
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/BuildSystem.txt
@@ -0,0 +1,975 @@
+/** \file
+ *
+ * This file contains special DoxyGen information for the generation of the main page and other special
+ * documentation pages. It is not a project source file.
+ */
+
+/** \page Page_BuildSystem The LUFA Build System
+ *
+ * \section Sec_BuildSystem_Overview Overview of the LUFA Build System
+ * The LUFA build system is an attempt at making a set of re-usable, modular build make files which
+ * can be referenced in a LUFA powered project, to minimize the amount of code required in an
+ * application makefile. The system is written in GNU Make, and each module is independent of
+ * one-another.
+ *
+ * For details on the prerequisites needed for Linux and Windows machines to be able to use the LUFA
+ * build system, see \ref Sec_CompilingApps_Prerequisites.
+ *
+ * To use a LUFA build system module, simply add an include to your project makefile. All user projects
+ * should at a minimum include \ref Page_BuildModule_CORE for base functionality:
+ * \code
+ * include $(LUFA_PATH)/Build/lufa_core.mk
+ * \endcode
+ *
+ * Once included in your project makefile, the associated build module targets will be added to your
+ * project's build makefile targets automatically. To call a build target, run <tt>make {TARGET_NAME}</tt>
+ * from the command line, substituting in the appropriate target name.
+ *
+ * \see \ref Sec_ConfiguringApps_AppMakefileParams for a copy of the sample LUFA project makefile.
+ *
+ * Each build module may have one or more mandatory parameters (GNU Make variables) which <i>must</i>
+ * be supplied in the project makefile for the module to work, and one or more optional parameters which
+ * may be defined and which will assume a sensible default if not.
+ *
+ * \section SSec_BuildSystem_Modules Available Modules
+ *
+ * The following modules are included in this LUFA release:
+ *
+ * \li \subpage Page_BuildModule_ATPROGRAM - Device Programming
+ * \li \subpage Page_BuildModule_AVRDUDE - Device Programming
+ * \li \subpage Page_BuildModule_BUILD - Compiling/Assembling/Linking
+ * \li \subpage Page_BuildModule_CORE - Core Build System Functions
+ * \li \subpage Page_BuildModule_CPPCHECK - Static Code Analysis
+ * \li \subpage Page_BuildModule_DFU - Device Programming
+ * \li \subpage Page_BuildModule_DOXYGEN - Automated Source Code Documentation
+ * \li \subpage Page_BuildModule_HID - Device Programming
+ * \li \subpage Page_BuildModule_SOURCES - LUFA Module Source Code Variables
+ *
+ * If you have problems building using the LUFA build system, see \subpage Page_BuildTroubleshooting for resolution steps.
+ */
+
+ /** \page Page_BuildModule_BUILD The BUILD build module
+ *
+ * The BUILD LUFA build system module, providing targets for the compilation,
+ * assembling and linking of an application from source code into binary files
+ * suitable for programming into a target device, using the GCC compiler.
+ *
+ * To use this module in your application makefile, add the following code:
+ * \code
+ * include $(LUFA_PATH)/Build/lufa_build.mk
+ * \endcode
+ *
+ * \section SSec_BuildModule_BUILD_Requirements Requirements
+ * This module requires the the architecture appropriate binaries of the GCC compiler are available in your
+ * system's <b>PATH</b> variable. The GCC compiler and associated toolchain is distributed in Atmel AVR Studio
+ * 5.x and Atmel Studio 6.x installation directories, as well as in many third party distribution packages.
+ *
+ * \section SSec_BuildModule_BUILD_Targets Targets
+ *
+ * <table>
+ * <tr>
+ * <td><tt>size</tt></td>
+ * <td>Display size of the compiled application FLASH and SRAM segments.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>symbol-sizes</tt></td>
+ * <td>Display a size-sorted list of symbols from the compiled application, in decimal bytes.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>lib</tt></td>
+ * <td>Build and archive all source files into a library A binary file.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>all</tt></td>
+ * <td>Build and link the application into ELF debug and HEX binary files.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>elf</tt></td>
+ * <td>Build and link the application into an ELF debug file.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>bin</tt></td>
+ * <td>Build and link the application and produce a BIN binary file.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>hex</tt></td>
+ * <td>Build and link the application and produce HEX and EEP binary files.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>lss</tt></td>
+ * <td>Build and link the application and produce a LSS source code/assembly code mixed listing file.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>clean</tt></td>
+ * <td>Remove all intermediary files and binary output files.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>mostlyclean</tt></td>
+ * <td>Remove all intermediary files but preserve any binary output files.</td>
+ * </tr>
+ * <tr>
+ * <td><tt><i>&lt;filename&gt;</i>.s</tt></td>
+ * <td>Create an assembly listing of a given input C/C++ source file.</td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_BUILD_MandatoryParams Mandatory Parameters
+ *
+ * <table>
+ * <tr>
+ * <td><tt>TARGET</tt></td>
+ * <td>Name of the application output file prefix (e.g. <tt>TestApplication</tt>).</td>
+ * </tr>
+ * <tr>
+ * <td><tt>ARCH</tt></td>
+ * <td>Architecture of the target processor (see \ref Page_DeviceSupport).</td>
+ * </tr>
+ * <tr>
+ * <td><tt>MCU</tt></td>
+ * <td>Name of the Atmel processor model (e.g. <tt>at90usb1287</tt>).</td>
+ * </tr>
+ * <tr>
+ * <td><tt>SRC</tt></td>
+ * <td>List of relative or absolute paths to the application C (.c), C++ (.cpp) and Assembly (.S) source files.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>F_USB</tt></td>
+ * <td>Speed in Hz of the input clock frequency to the target's USB controller.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>LUFA_PATH</tt></td>
+ * <td>Path to the LUFA library core, either relative or absolute (e.g. <tt>../LUFA-000000/LUFA/</tt>).</td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_BUILD_OptionalParams Optional Parameters
+ *
+ * <table>
+ * <tr>
+ * <td><tt>BOARD</tt></td>
+ * <td>LUFA board hardware drivers to use (see \ref Page_DeviceSupport).</td>
+ * </tr>
+ * <tr>
+ * <td><tt>OPTIMIZATION</tt></td>
+ * <td>Optimization level to use when compiling source files (see GCC manual).</td>
+ * </tr>
+ * <tr>
+ * <td><tt>C_STANDARD</tt></td>
+ * <td>Version of the C standard to apply when compiling C++ source files (see GCC manual).</td>
+ * </tr>
+ * <tr>
+ * <td><tt>CPP_STANDARD</tt></td>
+ * <td>Version of the C++ standard to apply when compiling C++ source files (see GCC manual).</td>
+ * </tr>
+ * <tr>
+ * <td><tt>DEBUG_FORMAT</tt></td>
+ * <td>Format of the debug information to embed in the generated object files (see GCC manual).</td>
+ * </tr>
+ * <tr>
+ * <td><tt>DEBUG_LEVEL</tt></td>
+ * <td>Level of the debugging information to embed in the generated object files (see GCC manual).</td>
+ * </tr>
+ * <tr>
+ * <td><tt>F_CPU</tt></td>
+ * <td>Speed of the processor CPU clock, in Hz.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>C_FLAGS</tt></td>
+ * <td>Flags to pass to the C compiler only, after the automatically generated flags.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>CPP_FLAGS</tt></td>
+ * <td>Flags to pass to the C++ compiler only, after the automatically generated flags.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>ASM_FLAGS</tt></td>
+ * <td>Flags to pass to the assembler only, after the automatically generated flags.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>CC_FLAGS</tt></td>
+ * <td>Common flags to pass to the C/C++ compiler and assembler, after the automatically generated flags.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>COMPILER_PATH</tt></td>
+ * <td>Directory where the C/C++ toolchain is located, if not available in the system <tt>PATH</tt>.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>LD_FLAGS</tt></td>
+ * <td>Flags to pass to the linker, after the automatically generated flags.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>LINKER_RELAXATIONS</tt></td>
+ * <td>Enables or disables linker relaxations when linking the application binary. This can reduce the total size
+ * of the application by replacing full \c CALL instructions with smaller \c RCALL instructions where possible.
+ * \note On some unpatched versions of binutils, this can cause link failures in some circumstances. If you
+ * receive a link error <tt>relocation truncated to fit: R_AVR_13_PCREL</tt>, disable this setting.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>OBJDIR</tt></td>
+ * <td>Directory to place the generated object and dependency files. If set to "." the same folder as the source file will be used.
+ * \note When this option is enabled, all source filenames <b>must</b> be unique.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>OBJECT_FILES</tt></td>
+ * <td>List of additional object files that should be linked into the resulting binary.</td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_BUILD_ProvidedVariables Module Provided Variables
+ *
+ * <table>
+ * <tr>
+ * <td><i>None</i></td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_BUILD_ProvidedMacros Module Provided Macros
+ *
+ * <table>
+ * <tr>
+ * <td><i>None</i></td>
+ * </tr>
+ * </table>
+ */
+
+/** \page Page_BuildModule_CORE The CORE build module
+ *
+ * The core LUFA build system module, providing common build system help and information targets.
+ *
+ * To use this module in your application makefile, add the following code:
+ * \code
+ * include $(LUFA_PATH)/Build/lufa_core.mk
+ * \endcode
+ *
+ * \section SSec_BuildModule_CORE_Requirements Requirements
+ * This module has no requirements outside a standard *nix shell like environment; the <tt>sh</tt>
+ * shell, GNU <tt>make</tt> and *nix CoreUtils (<tt>echo</tt>, <tt>printf</tt>, etc.).
+ *
+ * \section SSec_BuildModule_CORE_Targets Targets
+ *
+ * <table>
+ * <tr>
+ * <td><tt>help</tt></td>
+ * <td>Display build system help and configuration information.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>list_targets</tt></td>
+ * <td>List all available build targets from the build system.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>list_modules</tt></td>
+ * <td>List all available build modules from the build system.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>list_mandatory</tt></td>
+ * <td>List all mandatory parameters required by the included modules.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>list_optional</tt></td>
+ * <td>List all optional parameters required by the included modules.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>list_provided</tt></td>
+ * <td>List all variables provided by the included modules.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>list_macros</tt></td>
+ * <td>List all macros provided by the included modules.</td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_CORE_MandatoryParams Mandatory Parameters
+ *
+ * <table>
+ * <tr>
+ * <td><i>None</i></td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_CORE_OptionalParams Optional Parameters
+ *
+ * <table>
+ * <tr>
+ * <td><i>None</i></td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_CORE_ProvidedVariables Module Provided Variables
+ *
+ * <table>
+ * <tr>
+ * <td><i>None</i></td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_CORE_ProvidedMacros Module Provided Macros
+ *
+ * <table>
+ * <tr>
+ * <td><i>None</i></td>
+ * </tr>
+ * </table>
+ */
+
+/** \page Page_BuildModule_ATPROGRAM The ATPROGRAM build module
+ *
+ * The ATPROGRAM programming utility LUFA build system module, providing targets to reprogram an
+ * Atmel processor FLASH and EEPROM memories with a project's compiled binary output files.
+ *
+ * To use this module in your application makefile, add the following code:
+ * \code
+ * include $(LUFA_PATH)/Build/lufa_atprogram.mk
+ * \endcode
+ *
+ * \section SSec_BuildModule_ATPROGRAM_Requirements Requirements
+ * This module requires the <tt>atprogram.exe</tt> utility to be available in your system's <b>PATH</b>
+ * variable. The <tt>atprogram.exe</tt> utility is distributed in Atmel AVR Studio 5.x and Atmel Studio 6.x
+ * inside the application install folder's "\atbackend" subdirectory.
+ *
+ * \section SSec_BuildModule_ATPROGRAM_Targets Targets
+ *
+ * <table>
+ * <tr>
+ * <td><tt>atprogram</tt></td>
+ * <td>Program the device FLASH memory with the application's executable data.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>atprogram-ee</tt></td>
+ * <td>Program the device EEPROM memory with the application's EEPROM data.</td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_ATPROGRAM_MandatoryParams Mandatory Parameters
+ *
+ * <table>
+ * <tr>
+ * <td><tt>MCU</tt></td>
+ * <td>Name of the Atmel processor model (e.g. <tt>at90usb1287</tt>).</td>
+ * </tr>
+ * <tr>
+ * <td><tt>TARGET</tt></td>
+ * <td>Name of the application output file prefix (e.g. <tt>TestApplication</tt>).</td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_ATPROGRAM_OptionalParams Optional Parameters
+ *
+ * <table>
+ * <tr>
+ * <td><tt>ATPROGRAM_PROGRAMMER</tt></td>
+ * <td>Name of the Atmel programmer or debugger tool to communicate with (e.g. <tt>jtagice3</tt>).</td>
+ * </tr>
+ * <tr>
+ * <td><tt>ATPROGRAM_INTERFACE</tt></td>
+ * <td>Name of the programming interface to use when programming the target (e.g. <tt>spi</tt>).</td>
+ * </tr>
+ * <tr>
+ * <td><tt>ATPROGRAM_PORT</tt></td>
+ * <td>Name of the communication port to use when when programming with a serially connected tool (e.g. <tt>COM2</tt>).</td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_ATPROGRAM_ProvidedVariables Module Provided Variables
+ *
+ * <table>
+ * <tr>
+ * <td><i>None</i></td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_ATPROGRAM_ProvidedMacros Module Provided Macros
+ *
+ * <table>
+ * <tr>
+ * <td><i>None</i></td>
+ * </tr>
+ * </table>
+ */
+
+/** \page Page_BuildModule_AVRDUDE The AVRDUDE build module
+ *
+ * The AVRDUDE programming utility LUFA build system module, providing targets to reprogram an
+ * Atmel processor FLASH and EEPROM memories with a project's compiled binary output files.
+ *
+ * To use this module in your application makefile, add the following code:
+ * \code
+ * include $(LUFA_PATH)/Build/lufa_avrdude.mk
+ * \endcode
+ *
+ * \section SSec_BuildModule_AVRDUDE_Requirements Requirements
+ * This module requires the <tt>avrdude</tt> utility to be available in your system's <b>PATH</b>
+ * variable. The <tt>avrdude</tt> utility is distributed in the old WinAVR project releases for
+ * Windows (<a>http://winavr.sourceforge.net</a>) or can be installed on *nix systems via the project's
+ * source code (<a>https://savannah.nongnu.org/projects/avrdude</a>) or through the package manager.
+ *
+ * \section SSec_BuildModule_AVRDUDE_Targets Targets
+ *
+ * <table>
+ * <tr>
+ * <td><tt>avrdude</tt></td>
+ * <td>Program the device FLASH memory with the application's executable data.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>avrdude-ee</tt></td>
+ * <td>Program the device EEPROM memory with the application's EEPROM data.</td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_AVRDUDE_MandatoryParams Mandatory Parameters
+ *
+ * <table>
+ * <tr>
+ * <td><tt>MCU</tt></td>
+ * <td>Name of the Atmel processor model (e.g. <tt>at90usb1287</tt>).</td>
+ * </tr>
+ * <tr>
+ * <td><tt>TARGET</tt></td>
+ * <td>Name of the application output file prefix (e.g. <tt>TestApplication</tt>).</td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_AVRDUDE_OptionalParams Optional Parameters
+ *
+ * <table>
+ * <tr>
+ * <td><tt>AVRDUDE_PROGRAMMER</tt></td>
+ * <td>Name of the programmer or debugger tool to communicate with (e.g. <tt>jtagicemkii</tt>).</td>
+ * </tr>
+ * <tr>
+ * <td><tt>AVRDUDE_PORT</tt></td>
+ * <td>Name of the communication port to use when when programming with the connected tool (e.g. <tt>COM2</tt>, <tt>/dev/ttyUSB0</tt> or <tt>usb</tt>).</td>
+ * </tr>
+ * <tr>
+ * <td><tt>AVRDUDE_FLAGS</tt></td>
+ * <td>Additional flags to pass to avrdude when programming, applied after the automatically generated flags.</td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_AVRDUDE_ProvidedVariables Module Provided Variables
+ *
+ * <table>
+ * <tr>
+ * <td><i>None</i></td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_AVRDUDE_ProvidedMacros Module Provided Macros
+ *
+ * <table>
+ * <tr>
+ * <td><i>None</i></td>
+ * </tr>
+ * </table>
+ */
+
+ /** \page Page_BuildModule_CPPCHECK The CPPCHECK build module
+ *
+ * The CPPCHECK programming utility LUFA build system module, providing targets to statically
+ * analyze C and C++ source code for errors and performance/style issues.
+ *
+ * To use this module in your application makefile, add the following code:
+ * \code
+ * include $(LUFA_PATH)/Build/lufa_cppcheck.mk
+ * \endcode
+ *
+ * \section SSec_BuildModule_CPPCHECK_Requirements Requirements
+ * This module requires the <tt>cppcheck</tt> utility to be available in your system's <b>PATH</b>
+ * variable. The <tt>cppcheck</tt> utility is distributed through the project's home page
+ * (<a>http://cppcheck.sourceforge.net</a>) for Windows, and can be installed on *nix systems via
+ * the project's source code or through the package manager.
+ *
+ * \section SSec_BuildModule_CPPCHECK_Targets Targets
+ *
+ * <table>
+ * <tr>
+ * <td><tt>cppcheck</tt></td>
+ * <td>Statically analyze the project source code for issues.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>cppcheck-config</tt></td>
+ * <td>Check the <tt>cppcheck</tt> configuration - scan source code and warn about missing header files and other issues.</td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_CPPCHECK_MandatoryParams Mandatory Parameters
+ *
+ * <table>
+ * <tr>
+ * <td><tt>SRC</tt></td>
+ * <td>List of source files to statically analyze.</td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_CPPCHECK_OptionalParams Optional Parameters
+ *
+ * <table>
+ * <tr>
+ * <td><tt>CPPCHECK_INCLUDES</tt></td>
+ * <td>Path of extra directories to check when attemting to resolve C/C++ header file includes.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>CPPCHECK_EXCLUDES</tt></td>
+ * <td>Paths or path fragments to exclude when analyzing.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>CPPCHECK_MSG_TEMPLATE</tt></td>
+ * <td>Output message template to use when printing errors, warnings and information (see <tt>cppcheck</tt> documentation).</td>
+ * </tr>
+ * <tr>
+ * <td><tt>CPPCHECK_ENABLE</tt></td>
+ * <td>Analysis rule categories to enable (see <tt>cppcheck</tt> documentation).</td>
+ * </tr>
+ * <tr>
+ * <td><tt>CPPCHECK_SUPPRESS</tt></td>
+ * <td>Specific analysis rules to suppress (see <tt>cppcheck</tt> documentation).</td>
+ * </tr>
+ * <tr>
+ * <td><tt>CPPCHECK_FAIL_ON_WARNING</tt></td>
+ * <td>Set to <b>Y</b> to fail the analysis job with an error exit code if warnings are found, <b>N</b> to continue without failing.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>CPPCHECK_QUIET</tt></td>
+ * <td>Set to <b>Y</b> to suppress all output except warnings and errors, <b>N</b> to show verbose output information.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>CPPCHECK_FLAGS</tt></td>
+ * <td>Extra flags to pass to <tt>cppcheck</tt>, after the automatically generated flags.</td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_CPPCHECK_ProvidedVariables Module Provided Variables
+ *
+ * <table>
+ * <tr>
+ * <td><i>None</i></td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_CPPCHECK_ProvidedMacros Module Provided Macros
+ *
+ * <table>
+ * <tr>
+ * <td><i>None</i></td>
+ * </tr>
+ * </table>
+ */
+
+ /** \page Page_BuildModule_DFU The DFU build module
+ *
+ * The DFU programming utility LUFA build system module, providing targets to reprogram an
+ * Atmel processor FLASH and EEPROM memories with a project's compiled binary output files.
+ * This module requires a DFU class bootloader to be running in the target, compatible with
+ * the DFU bootloader protocol as published by Atmel.
+ *
+ * To use this module in your application makefile, add the following code:
+ * \code
+ * include $(LUFA_PATH)/Build/lufa_dfu.mk
+ * \endcode
+ *
+ * \section SSec_BuildModule_DFU_Requirements Requirements
+ * This module requires either the <tt>batchisp</tt> utility from Atmel's FLIP utility, or the open
+ * source <tt>dfu-programmer</tt> utility (<a>http://dfu-programmer.sourceforge.net/</a>) to be
+ * available in your system's <b>PATH</b> variable. On *nix systems the <tt>dfu-programmer</tt> utility
+ * can be installed via the project's source code or through the package manager.
+ *
+ * \section SSec_BuildModule_DFU_Targets Targets
+ *
+ * <table>
+ * <tr>
+ * <td><tt>dfu</tt></td>
+ * <td>Program the device FLASH memory with the application's executable data using <tt>dfu-programmer</tt>.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>dfu-ee</tt></td>
+ * <td>Program the device EEPROM memory with the application's EEPROM data using <tt>dfu-programmer</tt>.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>flip</tt></td>
+ * <td>Program the device FLASH memory with the application's executable data using <tt>batchisp</tt>.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>flip-ee</tt></td>
+ * <td>Program the device EEPROM memory with the application's EEPROM data using <tt>batchisp</tt>.</td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_DFU_MandatoryParams Mandatory Parameters
+ *
+ * <table>
+ * <tr>
+ * <td><tt>MCU</tt></td>
+ * <td>Name of the Atmel processor model (e.g. <tt>at90usb1287</tt>).</td>
+ * </tr>
+ * <tr>
+ * <td><tt>TARGET</tt></td>
+ * <td>Name of the application output file prefix (e.g. <tt>TestApplication</tt>).</td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_DFU_OptionalParams Optional Parameters
+ *
+ * <table>
+ * <tr>
+ * <td><i>None</i></td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_DFU_ProvidedVariables Module Provided Variables
+ *
+ * <table>
+ * <tr>
+ * <td><i>None</i></td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_DFU_ProvidedMacros Module Provided Macros
+ *
+ * <table>
+ * <tr>
+ * <td><i>None</i></td>
+ * </tr>
+ * </table>
+ */
+
+ /** \page Page_BuildModule_DOXYGEN The DOXYGEN build module
+ *
+ * The DOXYGEN code documentation utility LUFA build system module, providing targets to generate
+ * project HTML and other format documentation from a set of source files that include special
+ * Doxygen comments.
+ *
+ * To use this module in your application makefile, add the following code:
+ * \code
+ * include $(LUFA_PATH)/Build/lufa_doxygen.mk
+ * \endcode
+ *
+ * \section SSec_BuildModule_DOXYGEN_Requirements Requirements
+ * This module requires the <tt>doxygen</tt> utility from the Doxygen website
+ * (<a>http://www.doxygen.org/</a>) to be available in your system's <b>PATH</b> variable. On *nix
+ * systems the <tt>doxygen</tt> utility can be installed via the project's source code or through
+ * the package manager.
+ *
+ * \section SSec_BuildModule_DOXYGEN_Targets Targets
+ *
+ * <table>
+ * <tr>
+ * <td><tt>doxygen</tt></td>
+ * <td>Generate project documentation.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>doxygen_create</tt></td>
+ * <td>Create a new Doxygen configuration file using the latest template.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>doxygen_upgrade</tt></td>
+ * <td>Upgrade an existing Doxygen configuration file to the latest template</td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_DOXYGEN_MandatoryParams Mandatory Parameters
+ *
+ * <table>
+ * <tr>
+ * <td><tt>LUFA_PATH</tt></td>
+ * <td>Path to the LUFA library core, either relative or absolute (e.g. <tt>../LUFA-000000/LUFA/</tt>).</td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_DOXYGEN_OptionalParams Optional Parameters
+ *
+ * <table>
+ * <tr>
+ * <td><tt>DOXYGEN_CONF</tt></td>
+ * <td>Name and path of the base Doxygen configuration file for the project.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>DOXYGEN_FAIL_ON_WARNING</tt></td>
+ * <td>Set to <b>Y</b> to fail the generation with an error exit code if warnings are found other than unsupported configuration parameters, <b>N</b> to continue without failing.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>DOXYGEN_OVERRIDE_PARAMS</tt></td>
+ * <td>Extra Doxygen configuration parameters to apply, overriding the corresponding config entry in the project's configuration file (e.g. <tt>QUIET=YES</tt>).</td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_DOXYGEN_ProvidedVariables Module Provided Variables
+ *
+ * <table>
+ * <tr>
+ * <td><i>None</i></td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_DOXYGEN_ProvidedMacros Module Provided Macros
+ *
+ * <table>
+ * <tr>
+ * <td><i>None</i></td>
+ * </tr>
+ * </table>
+ */
+
+ /** \page Page_BuildModule_HID The HID build module
+ *
+ * The HID programming utility LUFA build system module, providing targets to reprogram an
+ * Atmel processor's FLASH memory with a project's compiled binary output file. This module
+ * requires a HID class bootloader to be running in the target, using a protocol compatible
+ * with the PJRC "HalfKay" protocol (<a>http://www.pjrc.com/teensy/halfkay_protocol.html</a>).
+ *
+ * To use this module in your application makefile, add the following code:
+ * \code
+ * include $(LUFA_PATH)/Build/lufa_hid.mk
+ * \endcode
+ *
+ * \section SSec_BuildModule_HID_Requirements Requirements
+ * This module requires either the <tt>hid_bootloader_cli</tt> utility from the included LUFA HID
+ * class bootloader API subdirectory, or the <tt>teensy_loader_cli</tt> utility from PJRC
+ * (<a>http://www.pjrc.com/teensy/loader_cli.html</a>) to be available in your system's <b>PATH</b>
+ * variable.
+ *
+ * \section SSec_BuildModule_HID_Targets Targets
+ *
+ * <table>
+ * <tr>
+ * <td><tt>hid</tt></td>
+ * <td>Program the device FLASH memory with the application's executable data using <tt>hid_bootloader_cli</tt>.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>hid-ee</tt></td>
+ * <td>Program the device EEPROM memory with the application's EEPROM data using <tt>hid_bootloader_cli</tt> and
+ * a temporary AVR application programmed into the target's FLASH.
+ * \note This will erase the currently loaded application in the target.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>teensy</tt></td>
+ * <td>Program the device FLASH memory with the application's executable data using <tt>teensy_loader_cli</tt>.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>teensy-ee</tt></td>
+ * <td>Program the device EEPROM memory with the application's EEPROM data using <tt>teensy_loader_cli</tt> and
+ * a temporary AVR application programmed into the target's FLASH.
+ * \note This will erase the currently loaded application in the target.</td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_HID_MandatoryParams Mandatory Parameters
+ *
+ * <table>
+ * <tr>
+ * <td><tt>MCU</tt></td>
+ * <td>Name of the Atmel processor model (e.g. <tt>at90usb1287</tt>).</td>
+ * </tr>
+ * <tr>
+ * <td><tt>TARGET</tt></td>
+ * <td>Name of the application output file prefix (e.g. <tt>TestApplication</tt>).</td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_HID_OptionalParams Optional Parameters
+ *
+ * <table>
+ * <tr>
+ * <td><i>None</i></td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_HID_ProvidedVariables Module Provided Variables
+ *
+ * <table>
+ * <tr>
+ * <td><i>None</i></td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_HID_ProvidedMacros Module Provided Macros
+ *
+ * <table>
+ * <tr>
+ * <td><i>None</i></td>
+ * </tr>
+ * </table>
+ */
+
+ /** \page Page_BuildModule_SOURCES The SOURCES build module
+ *
+ * The SOURCES LUFA build system module, providing variables listing the various LUFA source files
+ * required to be build by a project for a given LUFA module. This module gives a way to reference
+ * LUFA source files symbolically, so that changes to the library structure do not break the library
+ * makefile.
+ *
+ * To use this module in your application makefile, add the following code:
+ * \code
+ * include $(LUFA_PATH)/Build/lufa_sources.mk
+ * \endcode
+ *
+ * \section SSec_BuildModule_SOURCES_Requirements Requirements
+ * None.
+ *
+ * \section SSec_BuildModule_SOURCES_Targets Targets
+ *
+ * <table>
+ * <tr>
+ * <td><i>None</i></td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_SOURCES_MandatoryParams Mandatory Parameters
+ *
+ * <table>
+ * <tr>
+ * <td><tt>LUFA_PATH</tt></td>
+ * <td>Path to the LUFA library core, either relative or absolute (e.g. <tt>../LUFA-000000/LUFA/</tt>).</td>
+ * </tr>
+ * <tr>
+ * <td><tt>ARCH</tt></td>
+ * <td>Architecture of the target processor (see \ref Page_DeviceSupport).</td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_SOURCES_OptionalParams Optional Parameters
+ *
+ * <table>
+ * <tr>
+ * <td><i>None</i></td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_SOURCES_ProvidedVariables Module Provided Variables
+ *
+ * <table>
+ * <tr>
+ * <td><tt>LUFA_SRC_USB</tt></td>
+ * <td>List of LUFA USB driver source files.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>LUFA_SRC_USBCLASS</tt></td>
+ * <td>List of LUFA USB Class driver source files.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>LUFA_SRC_TEMPERATURE</tt></td>
+ * <td>List of LUFA temperature sensor driver source files.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>LUFA_SRC_SERIAL</tt></td>
+ * <td>List of LUFA Serial U(S)ART driver source files.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>LUFA_SRC_TWI</tt></td>
+ * <td>List of LUFA TWI driver source files.</td>
+ * </tr>
+ * <tr>
+ * <td><tt>LUFA_SRC_PLATFORM</tt></td>
+ * <td>List of LUFA architecture specific platform management source files.</td>
+ * </tr>
+ * </table>
+ *
+ * \section SSec_BuildModule_SOURCES_ProvidedMacros Module Provided Macros
+ *
+ * <table>
+ * <tr>
+ * <td><i>None</i></td>
+ * </tr>
+ * </table>
+ */
+
+/** \page Page_BuildTroubleshooting Troubleshooting Information
+ *
+ * LUFA uses a lot of advanced features of the AVR-GCC compiler, linker, and surrounding binaries. This can sometimes lead to problems compiling applications if one of these
+ * features is buggy in the version of the tools used in a build environment. Missing utilities and incorrectly set makefile configuration options can also result in different
+ * errors being produced when compilation or other operations are attempted. The table below lists a set of commonly encountered errors and their resolutions.
+ *
+ * <table>
+ * <tr>
+ * <th>Problem</th>
+ * <th>Resolution</th>
+ * </tr>
+ * <tr>
+ * <td>Error &quot;<b><tt>relocation truncated to fit: R_AVR_13_PCREL against symbol <i>{X}</i></tt></b>&quot; shown when compiling.</td>
+ * <td>Try compiling with the setting <tt>LINKER_RELAXATIONS=N</tt> in your LUFA Build System 2.0 makefile, or remove the line <tt>-Wl,--relax</tt>
+ * from other makefiles. Alternatively, make sure you have the latest version of the Atmel Toolchain installed for your system.</td>
+ * </tr>
+ * <tr>
+ * <td>Error &quot;<b><tt>error: ld terminated with signal 11 [Segmentation fault]</tt></b>&quot; shown when compiling.</td>
+ * <td>Try compiling with the setting <tt>DEBUG_LEVEL=2</tt> in your LUFA Build System 2.0 makefile, or make sure you are using <tt>binutils</tt> version 2.22 or later.</td>
+ * </tr>
+ * <tr>
+ * <td>Error &quot;<b><tt>EMERGENCY ABORT: INFINITE RECURSION DETECTED</tt></b>&quot; shown when compiling.</td>
+ * <td>Make sure you are using an up to date version of GNU Make when compiling. This error is a safety system added to the mid-level makefiles, to prevent an issue with
+ * GNU make or other variants of Make causing an infinitely recursive build.</td>
+ * </tr>
+ * <tr>
+ * <td>Error &quot;<b><tt>Unsupported architecture &quot;<i>{X}</i>&quot;</tt></b>&quot; shown when compiling.</td>
+ * <td>Ensure your makefile's <tt>ARCH</tt> setting is set to one of the architecture names (case-sensitive) supported by the version of LUFA you are compiling against.</td>
+ * </tr>
+ * <tr>
+ * <td>Error &quot;<b><tt>Makefile <i>{X}</i> value not set</tt></b>&quot; shown when compiling.</td>
+ * <td>The specified Makefile value was not configured in your project's makefile or on the command line, and the nominated setting is required by one or more LUFA
+ * build system modules. Define the value in your project makefile and try again.</td>
+ * </tr>
+ * <tr>
+ * <td>Error &quot;<b><tt>Makefile <i>{X}</i> option cannot be blank</tt></b>&quot; shown when compiling.</td>
+ * <td>The specified Makefile value was configured in your project's makefile or on the command line, but was set to an empty value. For the nominated configuration
+ * option, an empty value is not allowed. Define the nominated setting to a correct non-blank value and try again.</td>
+ * </tr>
+ * <tr>
+ * <td>Error &quot;<b><tt>Makefile <i>{X}</i> option must be Y or N</tt></b>&quot; shown when compiling.</td>
+ * <td>The specified Makefile value was configured in your project's makefile or on the command line, but was set to a value other than a Y (for "Yes") or "N" (for "No").
+ * This configuration option is required to be one of the aforementioned boolean values, and other values are invalid. Set this option to either Y or N and try again.</td>
+ * </tr>
+ * <tr>
+ * <td>Error &quot;<b><tt>Unknown input source file formats: <i>{X}</i></tt></b>&quot; shown when compiling.</td>
+ * <td>The nominated source files, specified in your project's makefile in the <tt>SRC</tt> configuration option, has an extension that the LUFA build system does not
+ * recognise. The file extensions are case sensitive, and must be one of the supported formats (<tt>*.c</tt>, <tt>*.cpp</tt> or <tt>*.S</tt>).</td>
+ * </tr>
+ * <tr>
+ * <td>Error &quot;<b><tt>Cannot build with OBJDIR parameter set - one or more object file name is not unique</tt></b>&quot; shown when compiling.</td>
+ * <td>When a project is built with a non-empty <tt>OBJDIR</tt> object directory name set, all input source files must have unique names, excluding extension and path.
+ * This means that input files that are named identically and differ only by their path or extension are invalid when this mode is used.</td>
+ * </tr>
+ * <tr>
+ * <td>Error &quot;<b><tt>Source file does not exist: <i>{X}</i></tt></b>&quot; shown when compiling.</td>
+ * <td>The nominated input source file, specified in the user project's <tt>SRC</tt> parameter, could not be found. Ensure the source file exists and the absolute or
+ * relative path given in the user project makefile is correct and try again.</td>
+ * </tr>
+ * <tr>
+ * <td>Error &quot;<b><tt>Doxygen configuration file <i>{X}</i> does not exist</tt></b>&quot; shown when upgrading a Doxygen configuration file.</td>
+ * <td>The nominated Doxygen configuration file, specified in the user project's <tt>DOXYGEN_CONF</tt> parameter, could not be found. Ensure the configuration file exists
+ * and the absolute or relative path given in the user project makefile is correct and try again, or run the appropriate makefile target to generate a new configuration
+ * file.</td>
+ * </tr>
+ * <tr>
+ * <td>Error &quot;<b><tt>avr-gcc: error: unrecognized option '<i>{X}</i>'</tt></b>&quot; shown when compiling.</td>
+ * <td>An unrecognised option was supplied to the compiler, usually in the <tt>C_FLAGS</tt>, <tt>CPP_FLAGS</tt>, <tt>ASM_FLAGS</tt> or <tt>CC_FLAGS</tt> configuration
+ * options. The nominated compiler switch may be invalid, or unsupported by the version of AVR-GCC on the host system. Remove the unrecognised flag if invalid, or
+ * upgrade to the latest AVR-GCC. If the option is a valid linker option, use the prefix "-Wl," to ensure it is passed to the linker correctly.</td>
+ * </tr>
+ * <tr>
+ * <td>Error &quot;<b><tt>makefile:{X}: {Y}.mk: No such file or directory</tt></b>&quot; shown when make is invoked.</td>
+ * <td>The path to the nominated makefile module was incorrect. This usually indicates that the makefile <tt>LUFA_PATH</tt> option is not set to a valid relative or
+ * absolute path to the LUFA library core.</td>
+ * </tr>
+ * <tr>
+ * <td>Error &quot;<b><tt>fatal error: LUFAConfig.h: No such file or directory</tt></b>&quot; shown when compiling.</td>
+ * <td>The <tt>USE_LUFA_CONFIG_HEADER</tt> compile time option was set in the user project makefile, but the user supplied <tt>LUFAConfig.h</tt> header could not be
+ * found. Ensure that the directory that contains this configuration file is correctly passed to the compiler via the -I switch in the makefile <tt>CC_FLAGS</tt>
+ * parameter.</td>
+ * </tr>
+ * <tr>
+ * <td>Error &quot;<b><tt>ld.exe: section .apitable_trampolines loaded at <i>{X}</i> overlaps section .text</tt></b>&quot; shown when compiling a bootloader.</td>
+ * <td>The bootloader is compiling too large for the given <tt>FLASH_SIZE_KB</tt> and <tt>BOOT_SECTION_SIZE_KB</tt> parameters set in the bootloader makefile. This
+ * usually indicates that these values are incorrect for the specified device the bootloader is targeting. If these values are correct, a newer version of the
+ * compiler may need to be used to ensure that the bootloader is built within the section size constraints of the target device.</td>
+ * </tr>
+ * <tr>
+ * <td>Error &quot;<b><tt>unknown MCU '<i>{X}</i>' specified</tt></b>&quot; shown when compiling.</td>
+ * <td>The specified microcontroller device model name set in the user application's makefile as the <tt>MCU</tt> parameter is incorrect, or unsupported by the
+ * version of the compiler being used. Make sure the model name is correct, or upgrade to the latest Atmel Toolchain to obtain newer device support.</td>
+ * </tr>
+ * <tr>
+ * <td>Error &quot;<b><tt>undefined reference to `<i>{X}</i>'</tt></b>&quot; shown when compiling.</td>
+ * <td>This is usually caused by a missing source file in the user application's <tt>SRC</tt> configuration parameter. If the indicated symbol is one from the LUFA
+ * library, you may be missing a LUFA source makefile module (see \ref Page_BuildModule_SOURCES).</td>
+ * </tr>
+ * </table>
+ *
+ * For troubleshooting other errors you encounter, please see \ref Sec_ProjectHelp.
+ */
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/BuildingLinkableLibraries.txt b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/BuildingLinkableLibraries.txt
new file mode 100644
index 000000000..cbbae4b8e
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/BuildingLinkableLibraries.txt
@@ -0,0 +1,23 @@
+/** \file
+ *
+ * This file contains special DoxyGen information for the generation of the main page and other special
+ * documentation pages. It is not a project source file.
+ */
+
+/** \page Page_BuildLibrary Building as a Linkable Library
+ *
+ * The LUFA library can be built as a proper linkable library (with the extension .a) under AVR-GCC, so that
+ * the library does not need to be recompiled with each revision of a user project. Instructions for creating
+ * a library from a given source tree can be found in the AVR-GCC user manual included in the WinAVR install
+ * /Docs/ directory.
+ *
+ * However, building the library is <b>not recommended</b>, as the static (compile-time) options will be
+ * unable to be changed without a recompilation of the LUFA code. Therefore, if the library is to be built
+ * from the LUFA source, it should be made to be application-specific and compiled with the static options
+ * that are required for each project (which should be recorded along with the library).
+ *
+ * Normal library use has the library components compiled in at the same point as the application code, as
+ * demonstrated in the library demos and applications. This is the preferred method, as the library is recompiled
+ * each time to ensure that all static options for a particular application are applied.
+ */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/ChangeLog.txt b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/ChangeLog.txt
new file mode 100644
index 000000000..482c8868e
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/ChangeLog.txt
@@ -0,0 +1,1597 @@
+/** \file
+ *
+ * This file contains special DoxyGen information for the generation of the main page and other special
+ * documentation pages. It is not a project source file.
+ */
+
+ /** \page Page_ChangeLog Project Changelog
+ *
+ * \section Sec_ChangeLog140928 Version 140928
+ * <b>New:</b>
+ * - Core:
+ * - Updated the BUILD build system module to add a new COMPILER_PATH optional variable
+ * - Added Serial_IsSendReady() and Serial_IsSendComplete() functions to the Serial hardware peripheral driver
+ * - Added support for the Arduino Yun board (ATMEGA32U4 co-processor)
+ * - Added support for the Arduino Micro board (thanks to Zoltán Szőke)
+ * - Library Applications:
+ * - Added new Dual MIDI class driver device demo
+ *
+ * <b>Changed:</b>
+ * - Core:
+ * - The RNDIS device class driver now takes a user-supplied buffer and buffer length for the internal RNDIS
+ * message management (thanks to Peter Mc Shane)
+ *
+ * <b>Fixed:</b>
+ * - Core:
+ * - Fixed device class driver pipe configuration routines returning success with a partially constructed instance
+ * when a pipe configuration failed (thanks to Helge Suess)
+ * - Fixed incorrect XMEGA DFLL reference frequency (thanks to Martin Aakerberg)
+ * - Fixed possible infinite loop in the control endpoint stream write function (thanks to Clayton Knight)
+ * - Fixed missing HID report ID prefix on HID class driver GetReport request responses (thanks to Bert van Hall)
+ * - Fixed incorrect XMEGA USB controller clock division factory for non-Full Speed operation (thanks to Bert van Hall)
+ * - Fixed the LUFA build system to prevent incorrect code from being generated in newer toolchains when building for larger
+ * FLASH memory devices (thanks to demultiplexer)
+ * - Fixed missing parenthesis in the MIDI_EVENT() macro which could cause incorrect results (thanks to hexwab)
+ * - Fixed mixed capitalization of TWI in the XMEGA TWI driver causing compilation failures (thanks to Jacob Schloss)
+ * - Fixed broken AVR8 USART-SPI peripheral driver (thanks to Phil Zakielarz)
+ * - Library Applications:
+ * - Fixed spurious 0xFE USART byte sent in the USBtoSerial project when the baud rate is changed (thanks to Carl Kjeldsen)
+ * - Fixed blocking USART reads causing low throughput on slow baud rates in the USBtoSerial project (thanks to Nevada Smith)
+ * - Fixed USART reception overrun corrupting the internal buffers in the USBtoSerial project (thanks to Nevada Smith)
+ * - Fixed broken LowLevel Audio Out demo sampling frequency configuration (thanks to Torsten Duwe)
+ *
+ * \section Sec_ChangeLog140302 Version 140302
+ * <b>New:</b>
+ * - Library Applications:
+ * - Added new Bulk Vendor low level device demo
+ * - Added new libUSB host Python and NodeJS application examples for the Class driver GenericHID demo (thanks to Laszlo Monda)
+ * - Added new AVR8 USB option to keep 3.3V regulator enabled (thanks to Michael Hanselmann)
+ * - Added new USB_STRING_DESCRIPTOR() and USB_STRING_DESCRIPTOR_ARRAY() convenience macros (thanks to Laszlo Monda)
+ *
+ * <b>Changed:</b>
+ * - Library Applications:
+ * - Refactored out USB interface IDs in the demo applications into enums (thanks to Laszlo Monda)
+ * - AVRISP-MKII Clone Project PDI/TPI frequency increased from 250KHz to 2MHz as it is now stable
+ * - Increased TPI/PDI handshake delay to 100us from 1us to support targets with high amounts of capacitance on their
+ * /RESET lines (thanks to Paul Duke)
+ * - Changed the VERSION_BCD() macro to accept the major/minor/revision values as separate parameters
+ *
+ * <b>Fixed:</b>
+ * - Core:
+ * - Fixed MIDI device class driver MIDI_Device_ReceiveEventPacket() for the XMEGA architecture
+ * - Library Applications:
+ * - Fixed incorrect signature bytes returned in the DFU bootloader
+ *
+ * \section Sec_ChangeLog130901 Version 130901
+ * <b>New:</b>
+ * - Core:
+ * - Added additional MIDI command definitions to the MIDI class driver (thanks to Daniel Dreibrodt)
+ * - Added new CONCAT() and CONCAT_EXPANDED() convenience macros
+ * - Added new Printer Device Class driver
+ * - Added support for the XMEGA C3 Xplained board
+ * - Added support for the U2S board (thanks to megal0maniac)
+ * - Added TWI Master driver for the XMEGA architecture (thanks to Michael Janssen)
+ * - Library Applications:
+ * - Added new Printer class bootloader
+ * - Added new Mass Storage class bootloader
+ * - Added XMEGA support for class driver device demos (where applicable)
+ * - Added Python host application example for the Generic HID class driver device demo
+ * - Added Python alternative host application for the HID class bootloader
+ *
+ * <b>Changed:</b>
+ * - Core:
+ * - Updated the BUILD build system module to produce binary BIN files in addition to Intel HEX files
+ * - Updated the Android Accessory Class to accept version 2 protocol devices (with version 1 functionality)
+ * - All board drivers now implement dummy functions and constants when BOARD is set to NONE
+ * - Added missing LEDs to the XMEGA A3BU Xplained board LED driver (thanks to Michael Janssen)
+ * - Changed board Dataflash drivers to automatically configure the appropriate SPI interface for the selected board
+ * - Library Applications:
+ * - Re-added Set Control Line State request handling to the CDC class bootloader to prevent issues with the .NET serial
+ * class (thanks to Erik Lins)
+ * - TemperatureDataLogger project dummy RTC mode now tracks real time (thanks to David Lazarus)
+ *
+ * <b>Fixed:</b>
+ * - Core:
+ * - Fixed Low Speed USB devices broken when using the library HID Class driver (thanks to Michael)
+ * - Fixed possible register corruption in USB Host mode on AVR8 devices when ORDERED_EP_CONFIG is used (thanks to Martin Aakerberg)
+ * - Fixed Pipe_GetBoundEndpointAddress() returning invalid endpoint directions on AVR8 architecture devices (thanks to decerri)
+ * under some circumstances
+ * - Fixed incorrect USB device state set when a suspended LUFA device is woken while addressed but not configured (thanks to Balaji Krishnan)
+ * - Fixed broken USART SPI driver for the AVR8 architecture due to incorrect initialization
+ * - Fixed re-enumeration issue of XMEGA architecture targets (thanks to Jaroslav Jedlinsky)
+ * - Fixed error receiving PIMA events via the Still Image Host class driver
+ * - Library Applications:
+ * - Added handler for SCSI_CMD_START_STOP_UNIT in demos using the Mass Storage class, to prevent ejection errors on *nix systems due to an
+ * unknown SCSI command
+ * - Fixed incorrect HID report descriptor generated for 16-bit axis ranges by the HID_DESCRIPTOR_MOUSE() and HID_DESCRIPTOR_JOYSTICK()
+ * macros (thanks to Armory)
+ * - Fixed incorrect HID report descriptor generated for button multiples of 8 by the HID_DESCRIPTOR_MOUSE() and HID_DESCRIPTOR_JOYSTICK()
+ * macros
+ * - Fixed race condition in the DFU class bootloader causing failed device reprogramming in some circumstances (thanks to Luis Mendes)
+ * - Fixed incorrect time/date configuration data order in the TempDataLogger host application (thanks to David Lazarus)
+ *
+ * \section Sec_ChangeLog130303 Version 130303
+ * <b>New:</b>
+ * - Core:
+ * - Added support for the Arduino Leonardo board
+ * - Added support for the Atmel UC3-A3 Xplained board
+ * - Added support for the Xevelabs USB2AX revision 3.1 board
+ * - Added support for the Dimex Stange-ISP board (thanks to Gerhard Wesser)
+ * - Added new \c doxygen_upgrade and \c doxygen_create targets to the DOXYGEN build system module
+ * - Added new Board Hardware Information board driver
+ * - Library Applications:
+ * - Added a different device serial number when the AVRISP-MKII Clone project is in libUSB compatibility mode, so that
+ * both the libUSB and Jungo drivers can be installed at the same time without having to use a filter driver
+ *
+ * <b>Changed:</b>
+ * - Core:
+ * - Added workaround for broken VBUS detection on AVR8 devices when a bootloader starts the application
+ * via a software jump without first turning off the OTG pad (thanks to Simon Inns)
+ * - Library Applications:
+ * - Increased throughput in the USBtoSerial project now that data transmission is non-blocking (thanks to Joseph Lacerte)
+ * - Updated bootloader makefiles to remove dependency on the \c bc command line calculator tool
+ * - Updated AVRISP-MKII Clone Programmer project so that the SCK clock period is saved in EEPROM (thanks to Gerhard Wesser)
+ * - Changed all *_SendByte() function prototypes to accept a void pointer for the input buffer (thanks to Simon Kuppers)
+ *
+ * <b>Fixed:</b>
+ * - Core:
+ * - Fixed incorrectly issuing STALL response to unsupported control request SETUP packets, rather than in the data/status stage
+ * - Fixed inverted LEDs_GetLEDs() function implementation for the Benito, Minimus and Arduino UNO boards
+ * - Fixed missing Windows 32-bit compatibility sections in the LUFA INF driver files (thanks to Christan Beharrell)
+ * - Fixed logic hole breaking USB operations on a USB controller with only one supported USB mode and no USB_DEVICE_ONLY or USB_HOST_ONLY
+ * configuration token set
+ * - Fixed possible rounding in the VERSION_BCD() macros for some 0.01 step increments (thanks to Oliver Zander)
+ * - Fixed incorrect Dataflash functionality in the USBKEY board if the driver is modified for a single Dataflash chip (thanks to Jonathan Oakley)
+ * - Fixed incorrect definitions of \c HID_KEYBOARD_LED_KANA, \c HID_KEYBOARD_SC_KEYPAD_EQUAL_SIGN and \c HID_KEYBOARD_SC_KEYPAD_EQUAL_SIGN_AS400
+ * and added a missing definition for \c HID_KEYBOARD_SC_APPLICATION (thanks to David Monro)
+ * - Fixed maximum allowed keyboard key code usage of \c 0x65 rather than \c 0xFF for the \c HID_DESCRIPTOR_KEYBOARD() macro (thanks to David Monro)
+ * - Fixed hardware race condition that could cause failed device enumerations for AVR8 and UC3 architectures (thanks to Mike Beyhs)
+ * - Fixed incorrect Minimus board LED definitions (thanks to Joonas Lahtinen)
+ * - Fixed incorrect ordering of the linker options in the build system causing link failures in some cases
+ * - Fixed bug in the TWI peripheral driver for the AVR8 devices causing incorrect failure codes to be returned in some cases (thanks to Peter K)
+ * - Fixed swapped LED3 and LED4 masks for the Olimex-32U4 development board LED driver
+ * - Fixed potential NULL pointer dereference in the HID Host mode Class Driver (thanks to Pavel Kuzmin)
+ * - Library Applications:
+ * - Fixed broken RESET_TOGGLES_LIBUSB_COMPAT compile time option in the AVRISP-MKII project
+ * - Fixed incompatibility in the CDC class bootloader on some systems (thanks to Sylvain Munaut)
+ * - Fixed lengthy timeouts in the USBtoSerial project if no application on the host is consuming data (thanks to Nicolas Saugnier)
+ * - Fixed lengthy automatic data flushing in the CDC and MIDI device class drivers
+ * - Fixed incorrect LED masks for received data display in the Device GenericHID demos (thanks to Denys Berkovskyy)
+ * - Fixed incorrect output in the HIDReportViewer project when no device is connected (thanks to Pavel Kuzmin)
+ *
+ * \section Sec_ChangeLog120730 Version 120730
+ * <b>New:</b>
+ * - Core:
+ * - Added new, revamped modular build system with new makefile templates
+ * - Added support for the BitWizard Multio and Big-Multio boards
+ * - Added support for the DorkbotPDX Duce board
+ * - Added support for the Olimex AVR-USB-32U4 board
+ * - Added support for the Olimex AVR-USB-T32U4 board
+ * - Added support for the Olimex AVR-ISP-MK2 board
+ * - Added new Endpoint_ConfigureEndpointTable() function
+ * - Added new Pipe_ConfigurePipeTable() function
+ * - Added build test to verify correct compilation of all board drivers using all driver APIs
+ * - Added build test to verify correct compilation of all bootloaders using all supported devices
+ * - Added build test to verify that there are no detectable errors in the codebase via static analysis
+ * - Added new JTAG_ENABLE() macro for the AVR8 architecture
+ * - Library Applications:
+ * - Modified the CDC Host demos to set a default CDC Line Encoding on enumerated devices
+ * - Added Dataflash operational checks and aborts to all projects using the Dataflash to ensure it is working correctly before use
+ * - Added new SerialToLCD user project contributed by Simon Foster
+ * - Added new RESET_TOGGLES_LIBUSB_COMPAT compile time option to the AVRISP-MKII clone programmer project (thanks to Robert Spitzenpfeil)
+ *
+ * <b>Changed:</b>
+ * - Core:
+ * - Android Accessory Host property strings changed from a struct of pointer to an array to prevent unaligned access on greater than 8-bit architectures
+ * - Audio Device Class driver changed to also require the index of the Audio Control interface within the device, for SET/GET/CUR/MIN/MAX/RES property adjustments
+ * - Removed variable axis support from the HID_DESCRIPTOR_JOYSTICK() macro due to OS incompatibilities, replaced with fixed 3-axis joystick report structure
+ * - Removed the old pseudo-scheduler from the library as it was unused and deprecated since the 090810 release
+ * - Endpoint indexes are now specified as full endpoint addresses within the device in device mode, rather than a logical index
+ * - The Endpoint_ConfigureEndpoint() function no longer takes an endpoint direction as a parameter, as this is now deduced from the specified full endpoint
+ * address and type
+ * - The Endpoint_ConfigureEndpoint() function no longer takes a number of banks as a special mask; the number of banks is now specified as an integer parameter
+ * - Endpoints are now configured via instances of a new struct USB_Endpoint_Table_t in all device mode class drivers, rather than a list of endpoint parameters
+ * - Pipe indexes are now specified as full pipe addresses within the host in host mode, rather than a logical index
+ * - The Pipe_ConfigurePipe() function no longer takes an pipe token as a parameter, as this is now deduced from the specified full pipe address and type
+ * - The Pipe_ConfigurePipe() function no longer takes a number of banks as a special mask; the number of banks is now specified as an integer parameter
+ * - Pipes are now configured via instances of a new struct USB_Pipe_Table_t in all host mode class drivers, rather than a list of pipe parameters
+ * - Added support for various assert and debugging macros for the UC3 devices
+ * - Changed MIDI event structure MIDI_EventPacket_t to use a single field for the combined virtual cable index and command ID, to prevent bitfield packing issues
+ * on some architectures (thanks to Darren Gibbs)
+ * - Changed board LED driver implementations of LEDs_ToggleLEDs() for the AVR8 architecture to use the fast PIN register toggle alternative function for speed
+ * - Library Applications:
+ * - Raised the guard bits in the AVRISP-MKII clone project when in PDI and TPI to 32, to prevent communication errors on low quality connections to a target
+ * - Added additional bootloader API data to expose the bootloader start address and class to the DFU and CDC class bootloaders
+ * - Reverted AVRISP-MKII clone project watchdog based command timeout patch in favour of a hardware timer, to allow for use in devices with WDTRST fuse programmed
+ * - The library bootloaders will now correctly start the user application after a watchdog-based application start, even if the /HWB line is held low externally
+ * during the reset phase
+ * - Increased endpoint polling interval for all demos and projects to 5ms, as 1ms was causing some enumeration issues on some machines (thanks to Riku Salminen)
+ *
+ * <b>Fixed:</b>
+ * - Core:
+ * - Fixed possible enumeration error if the user application selects a pipe other than the default Control pipe between the Powered and Default states of
+ * the host state machine
+ * - Fixed incorrect call to the user callback CALLBACK_Audio_Device_GetSetInterfaceProperty() in the Audio Class device driver (thanks to Tiit Ratsep)
+ * - Fixed compile error for the UC3 architecture when INTERRUPT_CONTROL_ENDPOINT is specified (thanks to Andrus Aaslaid)
+ * - Fixed compile error if LEDs_Disable() is called and BOARD=NONE is set (thanks to Sam Lin)
+ * - Fixed inverted LED logic in the OLIMEX162 board LED driver
+ * - Fixed incorrect response to GET STATUS requests in device mode if NO_DEVICE_SELF_POWER or NO_DEVICE_REMOTE_WAKEUP tokens are defined (thanks to Georg Glock)
+ * - Fixed inverted LED logic in the USB2AX board LED driver
+ * - Fixed possible deadlock in the CDC device driver if the USB connection is dropped while the CDC_REQ_SetLineEncoding control request is being processed by
+ * the stack (thanks to Jonathan Hudgins)
+ * - Fixed broken MIDI host driver MIDI_Host_ReceiveEventPacket() function due to not unfreezing the MIDI data IN pipe before use (thanks to Michael Brown)
+ * - Fixed swapped Little Endian/Big Endian endpoint and pipe write code for the UC3 devices (thanks to Andrew Chu)
+ * - Fixed the JTAG_DISABLE() macro clearing all other bits in MCUSR when called
+ * - Fixed incorrect Micropendous board LED driver LEDs_SetAllLEDs() and LEDs_ChangeLEDs() function implementations (thanks to MitchJS)
+ * - Fixed endianess issues in the RNDIS host class driver for UC3 devices (thanks to Andrew Chu)
+ * - Library Applications:
+ * - Fixed error in the AVRISP-MKII programmer when ISP mode is used at 64KHz (thanks to Ben R. Porter)
+ * - Fixed AVRISP-MKII programmer project failing to compile for the U4 chips when VTARGET_ADC_CHANNEL is defined to an invalid channel and NO_VTARGET_DETECT is
+ * defined (thanks to Steven Morehouse)
+ * - Fixed AVRISP-MKII programmer project reset line polarity inverted when the generated EEP file is loaded into the USB AVR's EEPROM and avr-dude is used
+ * - Fixed CDC and DFU bootloaders failing to compile when the bootloader section size is 8KB or more (thanks to Georg Glock)
+ * - Fixed CDC and DFU bootloaders API function offsets incorrect on some devices (thanks to Rod DeMay)
+ * - Fixed incorrect DFU version number reported to the host in the DFU bootloader descriptors (thanks to Georg Glock)
+ * - Fixed incorrect version hundredths value encoding in VERSION_BCD() macro (thanks to Georg Glock)
+ * - Fixed invalid configuration descriptor in the low level KeyboardMouse device demo (thanks to Jun Wako)
+ * - Fixed CDC and DFU bootloaders API page erase and write function failures (thanks to Martin Lambert)
+ *
+ * \section Sec_ChangeLog120219 Version 120219
+ * <b>New:</b>
+ * - Core:
+ * - Added support for the XMEGA A3BU Xplained board
+ * - Added support for the new B series XMEGA devices
+ * - Added support for version 2 of the Teensy boards (thanks to Christoph Redecker)
+ * - Added support for the USB2AX boards, hardware revision 1-3
+ * - Added new Android Accessory Host class driver
+ * - Added new USB_Host_GetDescriptor(), USB_Host_GetDeviceConfiguration() and USB_Host_GetInterfaceAltSetting() functions
+ * - Added new CALLBACK_Audio_Device_GetSetInterfaceProperty() callback to the Audio Device Class driver
+ * - Added new LEDs_Disable(), Buttons_Disable() and Joystick_Disable() functions to the board hardware drivers
+ * - Added support for the Micropendous family of boards (Arduino-like revisions 1 and 2, DIP, 32U2, A, 1, 2, 3 and 4)
+ * - Added INVERTED_VBUS_ENABLE_LINE and NO_AUTO_VBUS_MANAGEMENT compile time options (thanks to Opendous Inc.)
+ * - Added support for the Atmel XMEGA B1 Xplained board
+ * - Added Serial USART peripheral driver for the XMEGA architecture
+ * - Added Master Mode SPI USART peripheral driver for the XMEGA and AVR8 architectures
+ * - Added build test to verify correct compilation of as many modules as possible under as many architectures as possible under the C and C++ languages
+ * - Added build test to verify correct compilation of the USB driver when forced into single USB mode under as many architectures as possible
+ * - Library Applications:
+ * - Added User Application APIs to the CDC and DFU class bootloaders
+ * - Added INVERTED_ISP_MISO compile time option to the AVRISP-MKII clone project (thanks to Chuck Rohs)
+ * - Added new Android Accessory Host demo (thanks to Opendous Inc.)
+ *
+ * <b>Changed:</b>
+ * - Core:
+ * - When automatic PLL management mode is enabled on the U4 series AVR8 chips, the PLL is now configured for 48MHz and not
+ * a divided 96MHz, to lower power consumption and to keep the system within the datasheet specs for 3.3V operation (thanks to Scott Vitale)
+ * - Added Class, ClassDevice, ClassHost and ClassCommon to the internal class driver source filenames to prevent ambiguities
+ * - Altered the Mass Storage Host class driver so that SCSI data STALLs from the attached device can be recovered from automatically without
+ * having to reset the Mass Storage interface
+ * - USB_CONFIG_ATTR_BUSPOWERED constant renamed to USB_CONFIG_ATTR_RESERVED, as this was misnamed (thanks to NXP Semiconductors)
+ * - Reordered board name definition indexes so that a misspelled BOARD compile option will default to BOARD_USER rather than BOARD_USBKEY
+ * - Altered the HID class driver to only try to construct at maximum one packet per USB frame, to reduce CPU usage
+ * - All USB Class Driver configuration struct values are now non-const, to allow for run-time modifications if required before configuring an instance
+ * - Library Applications:
+ * - Altered the Mass Storage Host LowLevel demo so that SCSI data STALLs from the attached device can be recovered from automatically without
+ * having to reset the Mass Storage interface
+ * - Updated the AVRISP-MKII Clone programmer project to be compatible with the latest version of AVR Studio (version 5.1)
+ * - Changed the AVRISP-MKII Clone programmer project to report a fixed 3.3V VTARGET voltage on USB AVRs lacking an ADC instead of 5V to prevent
+ * warnings in AVR Studio 5.1 when programming XMEGA devices
+ * - Allow serial strings to be generated on the older AVR8 devices which do not explicitly state they contain unique values in the datasheet,
+ * as this appears to be implemented in hardware
+ *
+ * <b>Fixed:</b>
+ * - Core:
+ * - Fixed ring buffer size limited to 255 elements, instead of the intended 65535 elements.
+ * - Fixed CDC class drivers not saving and sending all 16-bits of the control line states (thanks to Matthew Swabey)
+ * - Fixed race conditions in the CDC, HID and Mass Storage class drivers when processing some control requests
+ * - Fixed misspelled HID_KEYBOARD_MODIFIER_* macros in the HID class driver (thanks to Laszlo Monda)
+ * - Fixed broken AVR32 endpoint/pipe communications when ORDERED_EP_CONFIG compile time option is not enabled (thanks to Matthias Jahr)
+ * - Fixed broken compilation for the AVR32 devices if the NO_SOF_EVENTS compile time option was not enabled (thanks to Matthias Jahr)
+ * - Fixed compiler warning on GCC with \c -wundef compile flag is used (thanks to Georg Glock)
+ * - Fixed incorrect implementation of LEDs_ToggleLEDs() for the Adafruit-U4 board (thanks to Caroline Saliman)
+ * - Fixed broken compilation of LUFA under C++ compilers when the Serial peripheral module header file is included in a C++ source file
+ * - Fixed missing semicolon in the UC3 architecture host pipe functions
+ * - Fixed failed compilation for the XMEGA architecture if USB_DEVICE_ONLY us not specified
+ * - Fixed UC3 architecture ignoring the pipe size when Pipe_ConfigurePipe() is called
+ * - Library Applications:
+ * - Added reliability patches to the AVRISP-MKII Clone project's PDI/TPI protocols (thanks to Justin Mattair)
+ * - Fixed AVRISP-MKII Clone compile warning on AVR8 U4 targets even when NO_VTARGET_DETECT is enabled
+ * - Fixed AVRISP-MKII Clone failing to start application firmware once a TPI programming session is exited
+ * - Fixed DFU class bootloader not resetting the LED pins as high impedance inputs when a software jump to the user applications is requested
+ * - Fixed AVRISP-MKII Clone timing out on long programming commands such as programming the EEPROM on an ATMEGA8 (thanks to Martin Kelling)
+ * - Fixed invalid PID value used in the TempDataLogger project host application (thanks to Anupam Pathak)
+ *
+ * \section Sec_ChangeLog111009 Version 111009
+ * <b>New:</b>
+ * - Core:
+ * - Added USE_LUFA_CONFIG_HEADER compile time option to include a LUFAConfig.h header in the user director for LUFA configuration
+ * tokens as an alternative to tokens defined in the project makefile
+ * - Added new USB_Host_SetInterfaceAltSetting() convenience function for the selection of an interface's alternative setting
+ * - Added Audio class control request definitions
+ * - Added new CALLBACK_Audio_Device_GetSetEndpointProperty() callback to the Audio Device Class driver to allow for endpoint control manipulations
+ * such as data sample rates
+ * - Added support for the Audio class GET STATUS request in the Audio Device Class driver so that it is correctly ACKed when sent by the host
+ * - Added new EVENT_Audio_Device_StreamStartStop() event to the Audio Device Class driver to detect stream start/stop events
+ * - Added board driver support for the Busware TUL board
+ * - Added board hardware driver support for the EVK1100 board
+ * - Added board hardware driver support for the EVK1104 board
+ * - Added new Host mode Audio Class driver
+ * - Added new SPI_GetCurrentMode() function to the SPI peripheral driver
+ * - Added RingBuffer_GetFreeCount() function to the Ring Buffer driver
+ * - Added new HID_Host_SetIdlePeriod() function to the HID Host Class driver
+ * - Added new USB_Host_ConfigurationNumber global variable to indicate the selected configuration in an attached device
+ * - Added new USB_Host_GetDeviceStatus() function to the host standard request function set
+ * - Added AVR USB XMEGA architecture port (currently incomplete/experimental)
+ * - Added new STRINGIFY() and STRINGIFY_EXPANDED() convenience macros
+ * - Added new JTAG_DISABLE() macro for the AVR8 architecture
+ * - Added Device Qualifier standard descriptor structure definitions USB_StdDescriptor_DeviceQualifier_t and USB_Descriptor_DeviceQualifier_t
+ * - Library Applications:
+ * - Added RNDIS device mode to the Webserver project
+ * - Added new incomplete AndroidAccessoryHost Host LowLevel demo
+ * - Added new HIDReportViewer project
+ * - Added new MediaControl project
+ * - Added new AudioInputHost Host ClassDriver demo
+ * - Added new AudioOutputHost Host ClassDriver demo
+ * - Added new AudioInputHost Host LowLevel demo
+ * - Added new AudioOutputHost Host LowLevel demo
+ * - Added new "checksource" target to all library project makefiles
+ * - Added new VTARGET_USE_INTERNAL_REF configuration option to the AVRISP-MKII clone project (thanks to Volker Bosch)
+ *
+ * <b>Changed:</b>
+ * - Core:
+ * - Altered the definition of the USB_Audio_Descriptor_Format_t descriptor so that the user is now responsible for supplying
+ * the supported audio sampling rates, to allow for multiple audio interfaces with different numbers of supported rates and/or
+ * continuous sample rates
+ * - Pipe_BoundEndpointNumber() has been renamed to Pipe_GetBoundEndpointAddress(), and now returns the correct endpoint direction
+ * as part of the endpoint address
+ * - Renamed global state variables that are specific to a certain USB mode to clearly indicate which mode the variable relates to,
+ * by changing the USB_* prefix to USB_Device_* or USB_Host_*
+ * - Removed the HOST_STATE_WaitForDeviceRemoval and HOST_STATE_Suspended host state machine states, as these are no longer required
+ * - Altered the USB_Host_SetDeviceConfiguration() function to update the global Host state machine state and the new
+ * USB_Host_ConfigurationNumber global as required
+ * - Added endian correcting code to the library USB class drivers for multiple architecture support
+ * - Removed the ENDPOINT_DESCRIPTOR_DIR_* macros, replaced by ENDPOINT_DIR_* instead
+ * - Renamed the JTAG_DEBUG_ASSERT() macro to JTAG_ASSERT()
+ * - Added variable number of axis to HID_DESCRIPTOR_JOYSTICK() for multi-axis joysticks above just X and Y
+ * - Renamed USB_Host_ClearPipeStall() to USB_Host_ClearEndpointStall() as the function works on an endpoint address within the attached device,
+ * and not a Pipe within the host
+ * - The MS_Host_ResetMSInterface() now performs a full Mass Storage reset sequence to prevent data corruption in the event of a device
+ * lock up or timeout (thanks to David Lyons)
+ * - Added endian-correction to the CDC driver's Line Encoding control request handlers.
+ * - Library Applications:
+ * - Modified the Low Level and Class Driver AudioInput and AudioOutput demos to support multiple audio sample rates
+ * - Updated all host mode demos and projects to use the EVENT_USB_Host_DeviceEnumerationComplete() event callback for device configuration
+ * instead of manual host state machine manipulations in the main application task
+ * - Changed the reports in the GenericHID device demos to control the board LEDs, to reduce user confusion over the callback routines
+ * - Added reliability patches to the AVRISP-MKII Clone project's ISP and PDI/TPI protocols (thanks to Justin Mattair)
+ *
+ * <b>Fixed:</b>
+ * - Core:
+ * - Large number of documentation and code comment corrections (thanks to Andrey from Microsin.ru)
+ * - Fixed possibility of the AVR's SPI interface being pulled out of master mode if the /SS pin is a input and pulled low (thanks
+ * to Andrey from Microsin.ru)
+ * - Fixed compile error when FIXED_CONTROL_ENDPOINT_SIZE compile time option was disabled, and a USE_*_DESCRIPTORS compile time
+ * option was not enabled on the AVR8s
+ * - Fixed lack of C++ compatibility in some internal header files causing compile errors when using LUFA in C++ projects
+ * - Fixed error in the pipe unordered allocation algorithm for the AVR8 devices breaking compatibility with some devices
+ * - Fixed USB_USBTask not being called internally in stream transfers between packets when Partial Stream Transfers are used
+ * - Fixed swapped TWI_ADDRESS_READ and TWI_ADDRESS_WRITE values
+ * - Fixed TWI_ReadPacket() not releasing the TWI bus on read completion
+ * - Fixed optimization error in the HID Parser item value USB_SetHIDReportItemInfo() and USB_GetHIDReportItemInfo() routines if the report item was
+ * \c NULL (which should be allowable according to the API)
+ * - Fixed HID Parser CALLBACK_HIDParser_FilterHIDReportItem() callback function not being passed a cacheable report item pointer
+ * - Fixed HID Parser's largest report size bit count not including the size of the last parsed report item
+ * - Fixed HID host driver's largest HID report size count corrupt when the number of report bits exceeds 255
+ * - Library Applications:
+ * - Fixed incorrect signature in the CDC and DFU class bootloaders for the ATMEGA8U2
+ * - Fixed KeyboardHost and KeyboardHostWithParser demos displaying incorrect values when numerical keys were pressed
+ * - Fixed compile errors in the incomplete BluetoothHost demo application (thanks to Timo Lindfors)
+ * - Fixed incorrect Dataflash buffer use in the DataflashManager_WriteBlocks_RAM() function of several demos/projects (thanks to Jeremy Willden)
+ * - Fixed incorrect logging interval (always 500ms longer than requested) in the TempDataLogger project
+ * - Fixed incorrect buffer size check in the USBtoSerial project (thanks to Yuri A Nikiforov)
+ * - Fixed port state table corruption in the TCP layer of the RNDIS Ethernet device demos
+ *
+ * \section Sec_ChangeLog110528 Version 110528
+ * <b>New:</b>
+ * - Core:
+ * - Added new ORDERED_EP_CONFIG compile time option to restrict endpoint/pipe configuration to ascending order
+ * in exchange for a smaller compiled program binary size
+ * - Added a new general RingBuff.h miscellaneous ring buffer library driver header
+ * - Added new GCC_FORCE_POINTER_ACCESS() macro to correct GCC's mishandling of struct pointer accesses
+ * - Added new GCC_MEMORY_BARRIER() macro to prevent instruction reordering across boundaries
+ * - Added basic driver example use code to the library documentation
+ * - Added new Endpoint_Null_Stream() and Pipe_Null_Stream() functions
+ * - Added new ADC_GET_CHANNEL_MASK() convenience macro
+ * - Added new HID report item macros (with HID_RI_ prefix) to allow for easy creation and editing of HID report descriptors
+ * - Added new HID_DESCRIPTOR_MOUSE(), HID_DESCRIPTOR_KEYBOARD(), HID_DESCRIPTOR_JOYSTICK() and HID_DESCRIPTOR_VENDOR() macros
+ * for easy automatic creation of basic USB HID device reports
+ * - Added new MAX() and MIN() convenience macros
+ * - Added new Serial_SendData() function to the Serial driver
+ * - Added board driver support for the Sparkfun ATMEGA8U2 breakout board
+ * - Added TWI baud rate prescaler and bit length parameters to the TWI_Init() function (thanks to Thomas Herlinghaus)
+ * - Internal restructuring for eventual multiple architecture ports
+ * - Added AVR32 UC3 architecture port (currently incomplete/experimental)
+ * - Added new architecture independent functions to enable, disable, save and restore the Global Interrupt Enable flags
+ * - Added new RNDIS Device Class Driver packet send and receive functions
+ * - Library Applications:
+ * - Added ability to write protect Mass Storage disk write operations from the host OS
+ * - Added new MIDIToneGenerator project
+ * - Added new KeyboardMouseMultiReport Device ClassDriver demo
+ * - Added new VirtualSerialMassStorage Device ClassDriver demo
+ * - Added HID class bootloader, compatible with a modified version of the command line Teensy loader from PJRC.com
+ * - Added LED flashing to the CDC and DFU class bootloaders to indicate when they are running
+ *
+ * <b>Changed:</b>
+ * - Core:
+ * - Unordered Endpoint/Pipe configuration is now allowed once again by default via the previous reconfig workaround
+ * - Refactored Host mode Class Driver *_Host_ConfigurePipes() routines to be more space efficient when compiled
+ * - Added new *_ENUMERROR_PipeConfigurationFailed error codes for the *_Host_ConfigurePipes() routines
+ * - The USARTStream global is now public and documented in the SerialStream module, allowing for the serial USART
+ * stream to be accessed via its handle rather than via the implicit stdout and stdin streams
+ * - The FAST_STREAM_TRANSFERS compile time option has been removed due to lack of use and low cost/benefit ratio
+ * - Altered all endpoint/pipe stream transfers so that the new BytesProcessed parameter now points to a location
+ * where the number of bytes in the transfer that have been completed can be stored (or NULL if entire transaction
+ * should be performed in one chunk)
+ * - The NO_STREAM_CALLBACKS compile time option has now been removed due to the new partial stream transfer feature
+ * - Changed over all project and demo HID report descriptors to use the new HID report item macros
+ * - Moved the HIDParser.c source file to the LUFA/Drivers/USB/Class/Common/ directory from the LUFA/Drivers/USB/Class/Host/
+ * - Added support to the HID parser for extended USAGE items that contain the usage page as well as the usage index
+ * - Removed the SerialStream driver, rolled functionality into the regular Serial peripheral driver via the new
+ * Serial_CreateStream() and Serial_CreateBlockingStream() functions
+ * - Renamed the low level Serial byte send/receive functions, to be consistent with the CDC class driver byte functions
+ * - Altered the behaviour of the serial byte reception function so that is is non-blocking, and now returns a negative
+ * value if no character is received (to remain consistent with the CDC class driver byte reception routines)
+ * - Renamed the PRNT_Host_SendString(), CDC_Host_SendString() and CDC_Device_SendString() functions to *_SendData(), and
+ * added new versions of the *_SendString() routines that expect a null terminated string instead
+ * - Renamed all driver termination *_ShutDown() functions to the more logical name *_Disable()
+ * - Reduced latency for executing the Start-Of-Frame events (if enabled in the user application)
+ * - Removed Pipe_ClearErrorFlags(), pipe error flags are now automatically cleared when Pipe_ClearError() is called
+ * - Endpoint_ResetFIFO() renamed to Endpoint_ResetEndpoint(), to be consistent with the Pipe_ResetPipe() function name
+ * - Implemented on-demand PLL clock generation for the U4, U6 and U7 series USB AVRs when automatic PLL mode is specified
+ * - F_CLOCK changed to F_USB to be more descriptive, and applicable on future architecture ports
+ * - Renamed all low level Endpoint_Read_*, Endpoint_Write_* and Endpoint_Discard_* functions to use the number of bits instead of
+ * a symbolic size (Byte, Word, DWord) so that the function names are applicable and correct across all architectures
+ * - Renamed all low level Pipe_Read_*, Pipe_Write_* and Pipe_Discard_* functions to use the number of bits instead of
+ * a symbolic size (Byte, Word, DWord) so that the function names are applicable and correct across all architectures
+ * - Separated out board drivers by architecture in the library internals for better organisation
+ * - Library Applications:
+ * - Changed the XPLAINBridge software UART to use the regular timer CTC mode instead of the alternative CTC mode
+ * via the Input Capture register, to reduce user confusion
+ * - Combined page and word ISP programming mode code in the AVRISP-MKII clone project to reduce compiled size and
+ * increase maintainability of the code
+ * - Changed over library projects to use the new general ring buffer library driver module
+ * - Added new high level TWI packet read/write commands, altered behaviour of the TWI_StartTransmission() function
+ * - Changed TempDataLogger project's DS1307 driver to simplify the function interface and prevent a possible race condition
+ * - Changed AVRISP-MKII project to use the Watchdog interrupt for command timeouts, to reduce CPU usage and free timer 0
+ * for other uses
+ * - Updated the software USART code in the XPLAIN Bridge application so that the incoming bits are sampled at their mid-point
+ * instead of starting point, to give maximum reliability (thanks to Anton Staaf)
+ *
+ * <b>Fixed:</b>
+ * - Core:
+ * - Fixed broken USBFOO board drivers due to missing BOARD_USBFOO define
+ * - Fixed HID host class driver incorrectly binding to HID devices that do not have an OUT endpoint
+ * - Fixed incorrect definition of the HID_KEYBOARD_SC_D constant in the HID class driver (thanks to Opendous Inc.)
+ * - Fixed incorrect definition of the HID_KEYBOARD_SC_RIGHT_ARROW constant in the HID class driver (thanks to Joby Taffey)
+ * - Fixed incorrect endpoint initialisation order in the several device demos (thanks to Rick Drolet)
+ * - Fixed inverted Minimus board LEDs
+ * - Fixed incorrect byte ordering in the Audio_Device_WriteSample24 function (thanks to WZab)
+ * - Fixed several functions in the Host mode Still Image Class driver returning an error code from the incorrect
+ * error code enum (thanks to Daniel Seibert)
+ * - Fixed ReportID not being removed from the feature/out report data array in the HID class driver when Report IDs are used
+ * - Fixed incorrect BUTTONS_BUTTON1 definition for the Minimus board
+ * - Fixed Still Image Host class driver exiting the descriptor search routine prematurely if the data pipes (but not event pipe)
+ * is found
+ * - Fixed missing call to Pipe_SetInfiniteINRequests() in the Pipe_ConfigurePipe() routine
+ * - Fixed Remote Wakeup broken on the AVRs due to the mechanism only operating when the SUSPI bit is set (thanks to Holger Steinhaus)
+ * - Fixed possible invalid program execution when in host mode if corrupt descriptor lengths are supplied by the attached device
+ * - Library Applications:
+ * - Fixed Benito project discarding incoming data from the USB virtual serial port when the USART is busy
+ * - Fixed broken DFU bootloader, added XPLAIN support for bootloader start when XCK jumpered to ground
+ * - Fixed broken HID_REQ_GetReport request handler in the Low Level GenericHID demo
+ * - Fixed possible lost data in the XPLAINBridge, USBtoSerial and Benito projects when the host exceeds the packet
+ * timeout period on received packets as set by USB_STREAM_TIMEOUT_MS (thanks to Justin Rajewski)
+ * - Fixed possible programming problem in the AVRISP-MKII clone project when programming specific patterns into a target
+ * memory space that is only byte (not page) addressable
+ * - Fixed errors in the incomplete Test and Measurement device demo preventing proper operation (thanks to Pavel Plotnikov)
+ * - Fixed programming errors in the AVRISP-MKII project when the programming packet is a round multiple of the endpoint bank
+ * size under avrdude (thanks to Steffan Woltjer)
+ *
+ *
+ * \section Sec_ChangeLog101122 Version 101122
+ * <b>New:</b>
+ * - Core:
+ * - Added new SCSI_ASENSE_NOT_READY_TO_READY_CHANGE constant to the Mass Storage class driver, to indicate when a previously
+ * not ready removable medium has now become ready for the host's use (thanks to Martin Degelsegger)
+ * - Moved the Pipe and Endpoint stream related code to two new USB library core source files EndpointStream.c and PipeStream.c
+ * - Added new USB_Device_GetFrameNumber() and USB_Host_GetFrameNumber() functions to retrieve the current USB frame number
+ * - Added new USB_Host_EnableSOFEvents(), USB_Host_DisableSOFEvents() and EVENT_USB_Host_StartOfFrame() for the user application
+ * handling of USB Start of Frame events while in USB Host mode
+ * - Added new PRNT_Host_BytesReceived(), PRNT_Host_ReceiveByte(), PRNT_Host_SendByte() and PRNT_Host_Flush() functions to the
+ * Print Host Class driver
+ * - Added class specific descriptor alternative struct type defines with standard USB-IF element naming
+ * - Added new project makefile template to the library and moved board driver stub files into in a new "CodeTemplates" directory
+ * - Added board hardware driver support for the Adafruit U4 breakout board
+ * - Added board hardware driver support for the Arduino Uno development board
+ * - Added board hardware driver support for the Blackcat USB JTAG board (thanks to the PSGroove team)
+ * - Added board hardware driver support for the Busware BUI development board
+ * - Added board hardware driver support for the Busware CUL V3 868MHZ radio board (thanks to Dirk Tostmann)
+ * - Added board hardware driver support for the Kernel Concepts USBFOO development board
+ * - Added board hardware driver support for the Linnix UDIP development board
+ * - Added board hardware driver support for the Olimex AVR-USB-162 development board (thanks to Steve Fawcett)
+ * - Added board hardware driver support for the Maximus board (thanks to the PSGroove team)
+ * - Added board hardware driver support for the Microsin AVR-USB162 breakout board
+ * - Added board hardware driver support for the Minimus board (thanks to the PSGroove team)
+ * - Added new NO_CLASS_DRIVER_AUTOFLUSH compile time option to disable automatic flushing of interfaces when the USB management
+ * tasks for each driver is called
+ * - Added standard keyboard HID report scan-code defines (thanks to Laszlo Monda)
+ * - Added new Pipe_GetBusyBanks(), Endpoint_GetBusyBanks() and Endpoint_AbortPendingIN() functions
+ * - Library Applications:
+ * - Added default test tone generation mode to the Device mode AudioInput demos
+ * - Added new NO_BLOCK_SUPPORT, NO_EEPROM_BYTE_SUPPORT, NO_FLASH_BYTE_SUPPORT and NO_LOCK_BYTE_WRITE_SUPPORT compile time options to the
+ * CDC class bootloader
+ * - Added new XCK_RESCUE_CLOCK_ENABLE compile time option to the AVRISP-MKII clone programmer project (thanks to Tom Light)
+ *
+ * <b>Changed:</b>
+ * - Core:
+ * - Removed complicated logic for the Endpoint_ConfigureEndpoint() function to use inlined or function called versions
+ * depending of if the given bank size is a compile time constant, as the compiler does a better job of optimizing
+ * with basic code
+ * - Changed the signature of the CALLBACK_USB_GetDescriptor() callback function so that the descriptor pointer is const, to remove
+ * the need for extra casting inside the callback (thanks to Jonathan Kollasch)
+ * - Reduced HOST_DEVICE_SETTLE_DELAY_MS to 1000ms down from 1500ms to improve device compatibility while in USB Host mode
+ * - Removed the EVENT_USB_InitFailure() event, not specifying a USB mode correctly now defaults to UID selection mode
+ * - Renamed and moved class driver common constant definitions to make the naming scheme more uniform
+ * - Moved the USB mode specifier constants into a new enum, so that they are semantically related to one another
+ * - Renamed ENDPOINT_DOUBLEBANK_SUPPORTED() to ENDPOINT_BANKS_SUPPORTED() and changed it to return the maximum number of supported banks for
+ * the given endpoint
+ * - Better algorithm to extract and convert the internal device serial number into a string descriptor (if present)
+ * - All USB class drivers are now automatically included when LUFA/Drivers/USB.h is included, and no longer need to be separately included
+ * - The MIDI class drivers now automatically flushes the MIDI interface when the MIDI class driver's USBTask() function is called
+ * - Renamed the EVENT_USB_Device_UnhandledControlRequest() event to EVENT_USB_Device_ControlRequest() as it is now fired before the library
+ * request handlers, not afterwards
+ * - Library Applications:
+ * - Changed over all device demos to use a clearer algorithm for the configuring of the application's endpoints
+ * - Added missing DataflashManager_CheckDataflashOperation() function to the MassStorageKeyboard demo, removed redundant
+ * SCSI_Codes.h file as these values are part of the MassStorage Class Driver
+ * - Added compile time error to the AVRISP-MKII project when built for the U4 chips, as the default VTARGET detection ADC channel
+ * does not exist on these chips (thanks to Marco)
+ * - Changed all Device mode LowLevel demos and Device Class drivers so that the control request is acknowledged and any data
+ * transferred as quickly as possible without any processing in between sections, so that long callbacks or event handlers will
+ * not break communications with the host by exceeding the maximum control request stage timeout period
+ * - Changed over all demos, drivers and internal functions to use the current frame number over the Start of Frame flag where possible
+ * to free up the Start of Frame flag for interrupt use in the user application
+ * - All project makefiles now correctly clean intermediate build files from assembly and C++ sources (thanks to Daniel Czigany)
+ * - Changed default value for the reset polarity parameter in the AVRISP-MKII project so that it defaults to active low drive
+ * - Changed configuration descriptor parser for all host mode projects and class drivers to ensure better compatibility with devices
+ * - All LowLevel demos changed to use the constants and types defined in the USB class drivers
+ * - Changed AudioInput and AudioOutput demos to reload the next sample via an interrupt rather than polling the sample timer
+ * - Rescue clock of the AVRISP-MKII moved to the AVR's OCR1A pin, so that the clock can be generated at all times
+ * - Changed ClassDriver MIDI demos to process all incoming events in a loop until the bank becomes empty rather than one at a time
+ * - Changed LowLevel MIDI demos to only clear the incoming event bank once it has become empty to support packed event packets
+ *
+ * <b>Fixed:</b>
+ * - Core:
+ * - Fixed USB_GetHIDReportItemInfo() function modifying the given report item's data when the report item does not exist
+ * within the supplied report of a multiple report HID device
+ * - Fixed critical pipe/endpoint memory allocation issue where the bank memory address space could be silently overlapped
+ * in the USB controller if the endpoints or pipes were allocated in anything other than ascending order (thanks to Martin Degelsegger)
+ * - Added LEDs_ToggleLEDs() function to several board LED drivers which were missing it (thanks to Andrei Krainev)
+ * - Fixed SET FEATURE and CLEAR FEATURE control requests directed at an unconfigured endpoint causing request timeouts
+ * - Fixed USB_Host_ClearPipeStall() incorrectly determining the endpoint direction from the currently selected pipe
+ * - Fixed JTAG_DEBUG_POINT() and JTAG_DEBUG_BREAK() macros not compiling under pure C99 standards mode
+ * - Fixed endpoint selection within the CALLBACK_HID_Device_CreateHIDReport() callback function causing broken GET REPORT requests
+ * - Fixed incorrect command name for EEPROM memory programming in the makefile dfu-ee target
+ * - Fixed incorrect LEDs_ChangeLEDs() function in the Benito board LED driver
+ * - Fixed incorrect USB_DeviceState value when unconfiguring the device without an address set
+ * - Fixed SPI driver not explicitly setting /SS and MISO pins as inputs when SPI_Init() is called
+ * - Fixed random enumeration failure while in device mode due to interrupts causing the Set Address request to exceed maximum timings
+ * - Fixed MIDI_Host_Flush() not aborting early when the specified MIDI host interface was not configured
+ * - Fixed MIDI class driver send routines silently discarding packets if the endpoint or pipe is busy (thanks to Robin Green)
+ * - Library Applications:
+ * - Fixed MassStorage based demos and projects resetting the SCSI sense values before the command is executed, leading to
+ * missed SCSI sense values when the host retrieves the sense key (thanks to Martin Degelsegger)
+ * - Fixed USBtoSerial and Benito project SetLineEncoding calls failing if the USART is busy, due to the RX ISR delaying the control
+ * request handler
+ * - Fixed LowLevel PrinterHost demo not sending control requests to the attached printer with the correct printer interface wIndex value
+ * - Fixed incorrect signature reported in the CDC class bootloader for the ATMEGA32U2
+ * - Fixed BootloaderCDC project failing on some operating systems due to removed Line Encoding options (thanks to Alexey Belyaev)
+ * - Fixed broken FLASH/EEPROM programming in the AVRISP-MKII clone project when writing in non-paged mode and the polling byte cannot be used
+ * - Fixed ISR definition conflict in the XPLAIN bridge between the software UART and the AVRISP-MKII ISP modules
+ * - Fixed USBtoSerial and XPLAINBridge demos discarding data from the PC if the send buffer becomes full
+ * - Fixed broken input in the MagStripe reader project due to an incorrect HID report descriptor
+ * - Fixed incorrect PollingIntervalMS values in the demo/project/bootloader endpoint descriptors (thanks to MCS Electronics)
+ * - Fixed AVRISP-MKII clone project not starting the target's program automatically after exiting TPI programming mode
+ *
+ *
+ * \section Sec_ChangeLog100807 Version 100807
+ * <b>New:</b>
+ * - Added new ADC_DisableChannel() function (thanks to Mich Davis)
+ * - Added new VTARGET_REF_VOLTS and VTARGET_SCALE_FACTOR compile time defines to the AVRISP-MKII programmer project to set
+ * the VTARGET reference voltage and scale factor
+ * - Added new pgm_read_ptr() macro to Common.h for reading of pointers out of flash memory space
+ * - Added new SWAPENDIAN_16() and SWAPENDIAN_32() macros to Common.h for statically initialized variables at compile time
+ * - Added new Drivers/USB/LowLevel/Device.c file to house Device mode specific functions that are more complicated than simple macros
+ * - Added new AVRStudio 4 project files for all library demos, projects and bootloaders
+ * - Added ability to set the serial baud rate via the user's terminal in the XPLAINBridge project
+ * - Added new LUFA module variables for the different source modules in the core library makefile to simplify project makefiles
+ * - Added start of a new Test and Measurement class demo (thanks to Peter Lawrence)
+ * - Added new SPI_ORDER_* data order masks to the SPI peripheral driver
+ * - Added support to the AVRISP-MKII project for ISP speeds slower than 125KHz via a new software SPI driver
+ * - Added support for the new button/LED on the latest model USBTINY-MKII
+ *
+ * <b>Changed:</b>
+ * - The RingBuff library code has been replaced in the XPLAINBridge, Benito and USBtoSerial projects with an ultra lightweight
+ * ring buffer to help improve the reliability of the projects
+ * - The EEPROM stream read/write functions now use eeprom_update_byte() instead of eeprom_write_byte(), so that only
+ * changed bytes are written to EEPROM to preserve its lifespan
+ * - Changed over the AVRISP-MKII and TemperatureDataLogger projects to use eeprom_update_byte() when writing non-volatile
+ * parameters to EEPROM to preserve its lifespan
+ * - Removed unused line encoding data and control requests from the CDC Bootloader code, to save space
+ * - Renamed SERIAL_STREAM_ASSERT() macro to STDOUT_ASSERT()
+ * - The USB_Device_IsRemoteWakeupSent() and USB_Device_IsUSBSuspended() macros have been deleted, as they are now obsolete
+ * - Rewrote the implementation of the SwapEndian_16() and SwapEndian_32() functions so that they compile down in most instances to
+ * minimal loads and stores rather than complicated shifts
+ * - The software UART in the XPLAINBridge has been largely altered to try to improve upon its performance and reliability
+ * - The USBtoSerial and Benito projects now flushes received data via a flush timer, so that several bytes can be transmitted at once
+ * - Removed the automated checking of event names in the demo, project and bootloader makefiles due to inconsistencies between the
+ * behaviour of the command line tools used to perform the check on each platform
+ * - Internal USB driver source files renamed and moved to ease future possible architecture ports
+ * - All internal pseudo-function macros have been converted to true inline functions for type-safety and readability
+ * - Changed LED indicator masks for the AVRISP-MKII project, so that there are defined roles for each LED
+ * - Altered the CDC Device and Host Class drivers' receive byte routines, so that no data is indicated by the function returning a
+ * negative value (thanks to Andreas Paulin)
+ * - Added auto flushing of OUT data to the CDC Host Class driver's USBTask function to automatically flush the send pipe buffer
+ *
+ * <b>Fixed:</b>
+ * - Fixed AVRISP project sending a LOAD EXTENDED ADDRESS command to 128KB AVRs after programming or reading from
+ * the last page of FLASH (thanks to Gerard Sexton)
+ * - Fixed AVRISP project not sending a full erase-and-write EEPROM command to XMEGA targets when writing to the EEPROM
+ * instead of the split write-only command (thanks to Tim Margush)
+ * - Fixed RNDISEthernet demos crashing when calculating checksums for Ethernet/TCP packets of more than ~500 bytes due to
+ * an overflow in the checksum calculation loop (thanks to Kevin Malec)
+ * - Fixed XPLAINBridge project not correctly reading the XMEGA's supply voltage when reporting back to the host
+ * - Fixed incorrect signature for the ATMEGA32U2 in the DFU bootloader (thanks to Axel Rohde)
+ * - Fixed internal device serial not being accessible on the ATMEGAXXU2 AVRs (thanks to Axel Rohde)
+ * - Fixed void pointer arithmetic in ConfigDescriptor.h breaking C++ compatibility (thanks to Michael Hennebry)
+ * - Fixed broken PDI EEPROM Section Erase functionality in the AVRISP-MKII project
+ * - Fixed USB_Device_SendRemoteWakeup() not working when the USB clock was frozen during USB bus suspend (thanks to Brian Dickman)
+ * - Fixed occasional lockup of the AVRISP project due to the timeout extension code incorrectly extending the timeout in
+ * PDI and TPI programming modes infinitely
+ * - Fixed HID device class driver still using PrevReportINBuffer for GetReport control requests even when it has been
+ * set to NULL by the user application (thanks to Axel Rohde)
+ * - Fixed MIDI_Device_SendEventPacket() not correctly waiting for the endpoint to become ready (thanks to Robin Green)
+ * - Fixed Benito and USBtoSerial projects not turning off the USART before reconfiguring it, which could cause incorrect
+ * operation to occur (thanks to Bob Paddock)
+ * - Fixed Serial peripheral driver not turning off the USART before reconfiguring it, which would cause incorrect operation
+ * to occur (thanks to Bob Paddock)
+ * - Fixed software application start command broken in the DFU class bootloader when dfu-programmer is used due to application
+ * start address corruption
+ *
+ *
+ * \section Sec_ChangeLog100513 Version 100513
+ * <b>New:</b>
+ * - Added incomplete MIDIToneGenerator project
+ * - Added new Relay Controller Board project (thanks to OBinou)
+ * - Added board hardware driver support for the Teensy, USBTINY MKII, Benito and JM-DB-U2 lines of third party USB AVR boards
+ * - Added new ATTR_NO_INIT variable attribute for global variables that should not be automatically cleared on startup
+ * - Added new ENDPOINT_*_BusSuspended error code to the Endpoint function, so that the stream functions early-abort if the bus
+ * is suspended before or during a transfer
+ * - Added new EVENT_CDC_Device_BreakSent() event and CDC_Host_SendBreak() function to the Device and Host CDC Class drivers
+ * - Added ReportType parameter to the HID device class driver CALLBACK_HID_Device_ProcessHIDReport() function so that FEATURE
+ * reports from the host to the device can be correctly processed
+ * - Added ReportType parameter to the HID host class driver HID_Host_SendReportByID() function so that FEATURE reports can be
+ * issued to the attached device
+ *
+ * <b>Changed:</b>
+ * - AVRISP programmer project now has a more robust timeout system
+ * - Added a timeout value to the TWI_StartTransmission() function, within which the addressed device must respond
+ * - Webserver project now uses the board LEDs to indicate the current IP configuration state
+ * - Added ENABLE_TELNET_SERVER compile time option to the Webserver project to disable the TELNET server if desired
+ * - Increased throughput of the USBtoSerial demo on systems that send multiple bytes per packet (thanks to Opendous Inc.)
+ * - Double bank CDC endpoints in the XPLAIN Bridge project, re-enable JTAG once the mode selection pin has been sampled.
+ * - Standardized the naming scheme given to configuration descriptor sub-elements in the Device mode demos, bootloaders
+ * and projects
+ * - All Class Driver Host mode demos now correctly set the board LEDs to READY once the enumeration process has completed
+ * - Added LIBUSB_FILTERDRV_COMPAT compile time option to the AVRISP programmer project to make the code compatible with Windows
+ * builds of avrdude at the expense of AVRStudio compatibility
+ * - Removed two-step endpoint/pipe bank clear and switch sequence for smaller, faster endpoint/pipe code
+ * - The USB_Init() function no longer calls sei() - the user is now responsible for enabling interrupts when they are ready
+ * for them to be enabled (thanks to Andrei Krainev)
+ * - The Audio_Device_IsSampleReceived() and Audio_Device_IsReadyForNextSample() functions are now inline, to reduce overhead
+ * - Removed the cast to uint16_t on the set baud rate in the USBtoSerial project, so that the higher >1M baud rates can be
+ * selected (thanks to Steffan Woltjer)
+ * - Removed software PDI and TPI emulation from the AVRISP-MKII clone project as it was very buggy and slow - PDI and TPI must
+ * now be implemented via separate programming headers
+ * - The CDC class bootloader now uses a watchdog reset rather than a soft-reset when exited to ensure that all hardware is
+ * properly reset to their defaults
+ * - Device mode class driver callbacks are now fired before the control request status stage is sent to prevent the host from
+ * timing out if another request is immediately fired and the device has a lengthy callback routine
+ * - The TeensyHID bootloader has been removed, per request from Paul at PJRC
+ * - The LIBUSB_FILTERDRV_COMPAT compile time option in the XPLAINBridge and AVRISP-MKII projects has been renamed
+ * LIBUSB_DRIVER_COMPAT, as it applies to all software on all platforms using the libUSB driver
+ *
+ * <b>Fixed:</b>
+ * - Fixed possible device lockup when INTERRUPT_CONTROL_ENDPOINT is enabled and the control endpoint is not properly
+ * selected when the ISR completes
+ * - Fixed AVRISP-MKII clone project not correctly issuing LOAD EXTENDED ADDRESS commands when the extended address
+ * boundary is crossed during programming or read back (thanks to Gerard Sexton)
+ * - Fixed warnings when building the AVRISP-MKII clone project with the ENABLE_XPROG_PROTOCOL compile time option disabled
+ * - Fixed software PDI/TPI programming mode in the AVRISP project not correctly toggling just the clock pin
+ * - Fixed TWI_StartTransmission() corrupting the contents of the GPIOR0 register
+ * - Fixed TWI driver not aborting when faced with no response after attempting to address a device on the bus
+ * - Fixed ADC routines not correctly returning the last result when multiple channels were read
+ * - Fixed ADC routines failing to read the extended channels (Channels 8 to 13, Internal Temperature Sensor) on the
+ * U4 series USB AVR parts
+ * - Fixed LowLevel MassStorage demo broken on the U2 series USB AVRs due to unsupported double-banked endpoint modes used
+ * - Fixed compilation error in the AudioInput demos when MICROPHONE_BIASED_TO_HALF_RAIL is defined (thanks to C. Scott Ananian)
+ * - Fixed incorrect definition of HID_ALIGN_DATA() causing incorrect HID report item data alignment
+ * - Fixed Still Image Host class driver not resetting the transaction ID when a new session is opened, fixed driver not sending
+ * a valid session ID to the device
+ * - Removed invalid dfu and flip related targets from the bootloaders - bootloaders can only be replaced with an external programmer
+ * - Fixed Set/Clear Feature requests directed to a non-configured endpoint not returning a stall to the host
+ * - Fixed HID Device Class Driver not allocating a temporary buffer when the host requests a report via the control endpoint and the
+ * user has set the PrevReportINBuffer driver configuration element to NULL (thanks to Lars Noschinski)
+ * - Fixed device state not being reset to DEVICE_STATE_Default if the host sets a 0x00 device address
+ * - Fixed device not stalling configuration requests before the device's address has been set
+ * - Fixed possibility of internal signature retrieval being corrupted if an interrupt occurs during a signature byte
+ * read (thanks to Andrei Krainev)
+ * - Fixed device state not being reset back to the default state if the host sets the address to 0
+ * - Fixed Set Configuration requests not being stalled until the host has set the device's address
+ * - Fixed Host mode HID class driver not sending the correct report type when HID_Host_SendReportByID() was called and the
+ * HID_HOST_BOOT_PROTOCOL_ONLY compile time option is set
+ * - Fixed INTERRUPT_CONTROL_ENDPOINT compile time option preventing other interrupts from occurring while the control endpoint
+ * request is being processed, causing possible lockups if a USB interrupt occurs during a transfer
+ * - Remove incorrect Abstract Call Management class specific descriptor from the CDC demos, bootloaders and projects
+ *
+ *
+ * \section Sec_ChangeLog100219 Version 100219
+ *
+ * <b>New:</b>
+ * - Added TPI programming support for 6-pin ATTINY devices to the AVRISP programmer project (thanks to Tom Light)
+ * - Added command timeout counter to the AVRISP project so that the device no longer freezes when incorrectly connected
+ * to a target
+ * - Added new TemperatureDataLogger application, a USB data logger which writes to the device's dataflash and appears to
+ * the host as a standard Mass Storage device when inserted
+ * - Added MIDI event packing support to the MIDI Device and Host mode Class drivers, allowing for multiple MIDI events to
+ * sent or received in packed form in a single USB packet
+ * - Added new MIDI send buffer flush routines to the MIDI Device and Host mode Class drivers, to flush packed events
+ * - Added master mode hardware TWI driver for easy TWI peripheral control
+ * - Added ADC MUX masks for the standard ADC input channels on all AVR models with an ADC, altered demos to use these masks
+ * as on some models, the channel number is not identical to its single-ended ADC MUX mask
+ * - New Webserver project, a RNDIS host USB webserver using the open source uIP TCP/IP network stack and FatFS library
+ * - New BOARD value option BOARD_NONE (equivalent to not specifying BOARD) which will remove all board hardware drivers which
+ * do not adversely affect the code operation (currently only the LEDs driver)
+ * - Added keyboard modifier masks (HID_KEYBOARD_MODIFER_*) and LED report masks (KEYBOARD_LED_*) to the HID class driver and
+ * Keyboard demos
+ * - Added .5MHz recovery clock to the AVRISP programmer project when in ISP programming mode to correct mis-set fuses
+ *
+ * <b>Changed:</b>
+ * - Slowed down software USART carried PDI programming in the AVRISP project to prevent transmission errors
+ * - Renamed the AVRISP project folder to AVRISP-MKII to reduce confusion
+ * - Renamed the RESET_LINE_* makefile tokens in the AVRISP MKII Project to AUX_LINE_*, as they are not always used for target
+ * reset
+ * - Changed over the MassStorageKeyboard Class driver device demo to use Start of Frame events rather than a timer to keep track
+ * of elapsed milliseconds
+ * - Inlined currently unused (but standardized) maintenance functions in the Device and Host Class drivers to save space
+ * - The XPLAINBridge project now selects between a USB to Serial bridge and a PDI programmer on startup, reading the JTAG port's
+ * TDI pin to determine which mode to use
+ * - Removed the stream example code from the Low Level VirtualSerial demos, as they were buggy and only served to add clutter
+ *
+ * <b>Fixed:</b>
+ * - Fixed AVRISP project not able to enter programming mode when ISP protocol is used
+ * - Fixed AVRISP PDI race condition where the guard time between direction changes could be interpreted as a start bit
+ * - Fixed ADC_IsReadingComplete() returning an inverted result
+ * - Fixed blocking CDC streams not aborting when the host is disconnected
+ * - Fixed XPLAIN board Dataflash driver broken due to incorrect preprocessor commands
+ * - Fixed inverted XPLAIN LED driver output (LED turned on when it was supposed to be turned off, and vice-versa)
+ * - Fixed Class Driver struct interface numbers in the KeyboardMouse and VirtualSerialMouse demos (thanks to Renaud Cerrato)
+ * - Fixed invalid USB controller PLL prescaler values for the ATMEGAxxU2 controllers
+ * - Fixed lack of support for the ATMEGA32U2 in the DFU and CDC class bootloaders
+ * - Fixed Benito project not resetting the target AVR automatically when programming has completed
+ * - Fixed DFU bootloader programming not discarding the correct number of filler bytes from the host when non-aligned programming
+ * ranges are specified (thanks to Thomas Bleeker)
+ * - Fixed CDC and RNDIS host demos and class drivers - bidirectional endpoints should use two separate pipes, not one half-duplex pipe
+ * - Fixed Pipe_IsEndpointBound() not taking the endpoint's direction into account
+ * - Fixed EEPROM and FLASH ISP programming in the AVRISP project
+ * - Fixed incorrect values of USB_CONFIG_ATTR_SELFPOWERED and USB_CONFIG_ATTR_REMOTEWAKEUP tokens (thanks to Claus Christensen)
+ * - Fixed SerialStream driver blocking while waiting for characters to be received instead of returning EOF
+ * - Fixed SerialStream driver not setting stdin to the created serial stream (thanks to Mike Alexander)
+ * - Fixed USB_GetHIDReportSize() returning the number of bits in the specified report instead of bytes
+ * - Fixed AVRISP project not extending the command delay after each successful page/word/byte program
+ * - Fixed accuracy of the SERIAL_UBBRVAL() and SERIAL_2X_UBBRVAL() macros for higher baud rates (thanks to Renaud Cerrato)
+ *
+ *
+ * \section Sec_ChangeLog091223 Version 091223
+ *
+ * <b>New:</b>
+ * - Added activity LED indicators to the AVRISP project to indicate when the device is busy processing a command
+ * - The USB target family and allowable USB mode tokens are now public and documented (USB_CAN_BE_*, USB_SERIES_*_AVR)
+ * - Added new XPLAIN USB to Serial Bridge project (thanks to John Steggall for initial proof-of-concept, David Prentice
+ * and Peter Danneger for revised software USART code)
+ * - Added new RNDIS Ethernet Host LowLevel demo
+ * - Added new RNDIS Ethernet Host Class Driver
+ * - Added new RNDIS Ethernet Host ClassDriver demo
+ * - Added CDC_Host_Flush() function to the CDC Host Class driver to flush sent data to the attached device
+ * - Added PDI programming support for XMEGA devices to the AVRISP programmer project (thanks to Justin Mattair)
+ * - Added support for the XPLAIN board Dataflash, with new XPLAIN_REV1 board target for the different Dataflash used
+ * on the first revision boards compared to the one mounted on later revisions
+ * - Added new HID_ALIGN_DATA() macro to return the pre-retrieved value of a HID report item, left-aligned to a given datatype
+ * - Added new PreviousValue to the HID Report Parser report item structure, for easy monitoring of previous report item values
+ * - Added new EVK527 board target
+ * - Added new USB_Host_GetDeviceStringDescriptor() convenience function
+ * - Added new LEDNotification project to the library, to give a visual LED notification on new events from the host
+ * - Added new NO_DEVICE_REMOTE_WAKEUP and NO_DEVICE_SELF_POWER compile time options
+ *
+ * <b>Changed:</b>
+ * - Removed code in the Keyboard demos to send zeroed reports between two reports with differing numbers of key codes
+ * as this relied on non-standard OS driver behaviour to repeat key groups
+ * - The SCSI_Request_Sense_Response_t and SCSI_Inquiry_Response_t type defines are now part of the Mass Storage Class
+ * driver common defines, rather than being defined in the Host mode Class driver section only
+ * - The USB_MODE_HOST token is now defined even when host mode is not available
+ * - The CALLBACK_HID_Device_CreateHIDReport() HID Device Class driver callback now has a new ReportType parameter to
+ * indicate the report type to generate
+ * - All Class Drivers now return false or the "DeviceDisconnected" error code of their respective error enums when a function
+ * is called when no host/device is connected where possible
+ * - The HOST_SENDCONTROL_DeviceDisconnect enum value has been renamed to HOST_SENDCONTROL_DeviceDisconnected to be in line
+ * with the rest of the library error codes
+ * - Make MIDI device demos also turn off the on board LEDs if MIDI Note On messages are sent with a velocity of zero,
+ * which some devices use instead of Note Off messages (thanks to Robin Green)
+ * - The CDC demos are now named "VirtualSerial" instead to indicate the demos' function rather than its implemented USB class,
+ * to reduce confusion and to be in line with the rest of the LUFA demos
+ * - The SImage_Host_SendBlockHeader() and SImage_Host_ReceiveBlockHeader() Still Image Host Class driver functions are now public
+ *
+ * <b>Fixed:</b>
+ * - Added missing CDC_Host_CreateBlockingStream() function code to the CDC Host Class driver
+ * - Fixed incorrect values for REPORT_ITEM_TYPE_* enum values causing corrupt data in the HID Host Parser
+ * - Fixed misnamed SI_Host_USBTask() and SI_Host_ConfigurePipes() functions
+ * - Fixed broken USB_GetNextDescriptor() function causing the descriptor to jump ahead double the expected amount
+ * - Fixed Pipe_IsEndpointBound() not masking the given Endpoint Address against PIPE_EPNUM_MASK
+ * - Fixed host state machine not enabling Auto VBUS mode when HOST_DEVICE_SETTLE_DELAY_MS is set to zero
+ * - Fixed misnamed Pipe_SetPipeToken() macro for setting a pipe's direction
+ * - Fixed CDCHost failing on devices with bidirectional endpoints
+ * - Fixed USB driver failing to define the PLL prescaler mask for the ATMEGA8U2 and ATMEGA16U2
+ * - Fixed HID Parser not distributing the Usage Min and Usage Max values across an array of report items
+ * - Fixed Mass Storage Host Class driver and Low Level demo not clearing the error condition if an attached device returns a
+ * STALL to a GET MAX LUN request (thanks to Martin Luxen)
+ * - Fixed TeensyHID bootloader not properly shutting down the USB interface to trigger a disconnection on the host before resetting
+ * - Fixed MassStorageHost Class driver demo not having USB_STREAM_TIMEOUT_MS compile time option set properly to prevent slow
+ * devices from timing out the data pipes
+ * - Fixed the definition of the Endpoint_BytesInEndpoint() macro for the U4 series AVR parts
+ * - Fixed MIDI host Class driver MIDI_Host_SendEventPacket() routine not properly checking for Pipe ready before writing
+ * - Fixed use of deprecated struct initializers, removed library unused parameter warnings when compiled with -Wextra enabled
+ * - Fixed Still Image Host Class driver truncating the PIMA response code (thanks to Daniel Seibert)
+ * - Fixed USB_CurrentMode not being reset to USB_MODE_NONE when the USB interface is shut down and both Host and Device modes can be
+ * used (thanks to Daniel Levy)
+ * - Fixed TeensyHID bootloader not enumerating to the host correctly (thanks to Clint Fisher)
+ * - Fixed AVRISP project timeouts not checking for the correct timeout period (thanks to Carl Ott)
+ * - Fixed STK525 Dataflash driver using incorrect bit-shifting for Dataflash addresses (thanks to Tim Mitchell)
+ *
+ *
+ * \section Sec_ChangeLog091122 Version 091122
+ *
+ * <b>New:</b>
+ * - Added new Dual Role Keyboard/Mouse demo
+ * - Added new HID_HOST_BOOT_PROTOCOL_ONLY compile time token to reduce the size of the HID Host Class driver when
+ * Report protocol is not needed
+ * - Added new MIDI LowLevel and ClassDriver Host demo, add new MIDI Host Class driver
+ * - Added new CDC/Mouse ClassDriver device demo
+ * - Added new Joystick Host ClassDriver and LowLevel demos
+ * - Added new Printer Host mode Class driver
+ * - Added new Printer Host mode ClassDriver demo
+ * - Added optional support for double banked endpoints and pipes in the Device and Host mode Class drivers
+ * - Added new stream creation function to the CDC Class drivers, to easily make standard I/O streams from CDC Class driver instances
+ *
+ * <b>Changed:</b>
+ * - Removed mostly useless "TestApp" demo, as it was mainly useful only for checking for syntax errors in the library
+ * - MIDI device demos now receive MIDI events from the host and display note ON messages via the board LEDs
+ * - Cleanups to the Device mode Mass Storage demo application SCSI routines
+ * - Changed Audio Class driver sample read/write functions to be inline, to reduce the number of cycles needed to transfer
+ * samples to and from the device (allowing more time for sample processing and output)
+ * - Audio class Device mode demos now work at both 16MHz and 8MHz, rather than just at 8MHz
+ * - The previous USBtoSerial demo has been moved into the projects directory, as it was just a modified CDC demo
+ * - The Endpoint/Pipe functions now use the const qualifier on the input buffer
+ * - Changed the CALLBACK_HIDParser_FilterHIDReportItem() callback to pass a HID_ReportItem_t rather than just the current
+ * item's attributes, to expose more information on the item (including it's type, collection path, etc.)
+ * - Changed MouseHostWithParser demos to check that the report items have a Mouse usage collection as a parent at some point,
+ * to prevent Joysticks from enumerating with the demo
+ * - Corrected the name of the misnamed USB_GetDeviceConfigDescriptor() function to USB_Host_GetDeviceConfigDescriptor().
+ * - Keyboard LowLevel/ClassDriver demos now support multiple simultaneous key presses (up to 6) per report
+ *
+ * <b>Fixed:</b>
+ * - Fixed PrinterHost demo returning invalid Device ID data when the attached device does not have a
+ * device ID (thanks to Andrei Krainev)
+ * - Changed LUFA_VERSION_INTEGER define to use BCD values, to make comparisons easier
+ * - Fixed issue in the HID Host class driver's HID_Host_SendReportByID() routine using the incorrect mode (control/pipe)
+ * to send report to the attached device
+ * - Fixed ClassDriver AudioOutput device demo not selecting an audio output mode
+ * - Fixed incorrect SampleFrequencyType value in the AudioInput and AudioOutput ClassDriver demos' descriptors
+ * - Fixed incorrect event name rule in demo/project/bootloader makefiles
+ * - Fixed HID device class driver not reselecting the correct endpoint once the user callback routines have been called
+ * - Corrected HID descriptor in the Joystick Device demos - buttons should be placed outside the pointer collection
+ * - Fixed HID report parser collection paths invalid due to misplaced semicolon in the free path item search loop
+ * - Fixed HID host Class driver report send/receive report broken when issued through the control pipe
+ * - Fixed HOST_STATE_AS_GPIOR compile time option being ignored when in host mode (thanks to David Lyons)
+ * - Fixed LowLevel Keyboard demo not saving the issues report only after it has been sent to the host
+ * - Fixed Endpoint_Write_Control_Stream_* functions not sending a terminating IN when given data Length is zero
+ *
+ *
+ * \section Sec_ChangeLog090924 Version 090924
+ *
+ * <b>New:</b>
+ * - Added new host mode class drivers and matching demos to the library for rapid application development
+ * - Added flag to the HID report parser to indicate if a device has multiple reports
+ * - Added new EVENT_USB_Device_StartOfFrame() event, controlled by the new USB_Device_EnableSOFEvents() and
+ * USB_Device_DisableSOFEvents() macros to give bus-synchronized millisecond interrupts when in USB device mode
+ * - Added new Endpoint_SetEndpointDirection() macro for bidirectional endpoints
+ * - Added new AVRISP project, a LUFA powered clone of the Atmel AVRISP-MKII programmer
+ * - Added ShutDown() functions for all hardware peripheral drivers, so that peripherals can be turned off after use
+ * - Added new CDC_Device_Flush() command to the device mode CDC Class driver to flush Device->Host data
+ * - Added extra masks to the SPI driver, changed SPI_Init() so that the clock polarity and sample modes can be set
+ * - Added new callback to the HID report parser, so that the user application can filter only the items it is interested
+ * in to be stored into the HIDReportInfo structure to save RAM
+ * - Added support for the officially recommended external peripheral layout for the BUMBLEB board (thanks to Dave Fletcher)
+ * - Added new Pipe_IsFrozen() macro to determine if the currently selected pipe is frozen
+ * - Added new USB_GetHIDReportSize() function to the HID report parser to retrieve the size of a given report by its ID
+ * - Added new combined Mass Storage and Keyboard demo (thanks to Matthias Hullin)
+ *
+ * <b>Changed:</b>
+ * - SetIdle requests to the HID device driver with a 0 idle period (send changes only) now only affect the requested
+ * HID interface within the device, not all HID interfaces
+ * - Added explicit attribute masks to the device mode demos' descriptors
+ * - Added return values to the CDC and MIDI class driver transmit functions
+ * - Optimized Endpoint_Read_Word_* and Pipe_Read_Word_* macros to reduce compiled size
+ * - Added non-null function parameter pointer restrictions to USB Class drivers to improve user code reliability
+ * - Added new "Common" section to the class drivers, to hold all mode-independent definitions for clarity
+ * - Moved SCSI command/sense constants into the Mass Storage Class driver, instead of the user-code
+ * - Altered the SCSI commands in the LowLevel Mass Storage Host to save on FLASH space by reducing function calls
+ * - Changed the parameters and behaviour of the USB_GetDeviceConfigDescriptor() function so that it now performs size checks
+ * and data validations internally, to simplify user code
+ * - Changed HIDParser to only zero out important values in the Parsed HID Report Item Information structure to save cycles
+ * - The HID report parser now always processed FEATURE items - HID_ENABLE_FEATURE_PROCESSING token now has no effect
+ * - The HID report parser now always ignores constant-data items, HID_INCLUDE_CONSTANT_DATA_ITEMS token now has no effect
+ * - The Benito Programmer project now has its own unique VID/PID pair allocated from the Atmel donated LUFA VID/PID pool
+ * - Add in new invalid event hook check targets to project makefiles to produce compilation errors when invalid event names
+ * are used in a project
+ * - The HID Report Parser now gives information on the total length of each report within a HID interface
+ * - The USE_NONSTANDARD_DESCRIPTOR_NAMES compile time token has been removed - there are now separate USB_Descriptor_* and
+ * USB_StdDescriptor_* structures for both the LUFA and standardized element naming conventions so both may be used
+ *
+ * <b>Fixed:</b>
+ * - Fixed possible lockup in the CDC device class driver, when the host sends data that is a multiple of the
+ * endpoint's bank
+ * - Fixed swapped parameters in the HID state memory copy call while processing a HID PUSH item in the HID report parser
+ * - Fixed memory corruption HID report parser when too many COLLECTION or PUSH items were processed
+ * - Fixed HID report parser not resetting the FEATURE item count when a REPORT ID item is encountered
+ * - Fixed USBtoSerial demos not reading in UDR1 when the USART receives data but the USB interface is not enumerated,
+ * causing continuous USART receive interrupts
+ * - Fixed misspelled event name in the Class driver USBtoSerial demo, preventing correct operation
+ * - Fixed invalid data being returned when a GetStatus request is issued in Device mode with an unhandled data recipient
+ * - Added hardware USART receive interrupt and software buffering to the Benito project to ensure received data is not
+ * missed or corrupted
+ * - Fixed Device mode HID Class driver always sending IN packets, even when nothing to report
+ * - Fixed Device mode HID Class driver not explicitly initializing the ReportSize parameter to zero before calling callback
+ * routine, so that ignored callbacks don't cause incorrect data to be sent
+ * - Fixed StillImageHost not correctly freezing and unfreezing data pipes while waiting for a response block header
+ * - Fixed error in the PrinterHost demo preventing the full page data from being sent to the attached device (thanks to John Andrews)
+ * - Fixed CDC based demos and projects' INF driver files under 64 bit versions of Windows (thanks to Ronny Hanson, Thomas Bleeker)
+ * - Re-add in missing flip, flip-ee, dfu and dfu-ee targets to project makefiles (thanks to Opendous Inc.)
+ * - Fix allowable F_CPU values comment in project makefiles to more accurately reflect the allowable values on the USB AVRs
+ * - Fixed DFU and CDC class bootloaders on the series 2 USB AVRs, corrected invalid signatures, added support for the new
+ * ATMEGAxx2 series 2 variant AVRs to the DFU bootloader
+ * - Fixed Low Level USBtoSerial demo not storing received characters (thanks to Michael Cooper)
+ * - Fixed MIDI Device Class driver not sending/receiving MIDI packets of the correct size (thanks to Thomas Bleeker)
+ *
+ *
+ * \section Sec_ChangeLog090810 Version 090810
+ *
+ * <b>New:</b>
+ * - Added new device class drivers and matching demos to the library for rapid application development
+ * - Added new PrinterHost demo (thanks to John Andrews)
+ * - Added USB Missile Launcher project, submitted by Dave Fletcher
+ * - Added new Benito Arduino Programmer project
+ * - Added incomplete device and host mode demos for later enhancement
+ * - Updated MassStorage device block write routines to use ping-pong Dataflash buffering to increase throughput by around 30%
+ * - Error status LEDs shown when device endpoint configuration fails to complete in all demos and projects
+ * - Added new USB_Host_SetDeviceConfiguration() convenience function for easy configuration selection of devices while in USB
+ * host mode
+ * - Added new USB_Host_ClearPipeStall() convenience function to clear a stall condition on an attached device's endpoint
+ * - Added new USB_Host_GetDeviceDescriptor() convenience function to retrieve the attached device's Device descriptor
+ * - Added new Endpoint_ClearStatusStage() convenience function to assist with the status stages of control transfers
+ * - Added new USE_INTERNAL_SERIAL define for using the unique serial numbers in some AVR models as the USB device's serial number,
+ * added NO_INTERNAL_SERIAL compile time option to turn off new serial number reading code
+ * - Added new DATAFLASH_CHIP_MASK() macro to the Dataflash driver, which returns the Dataflash select mask for the given chip index
+ * - Added new HOST_STATE_WaitForDeviceRemoval host state machine state for non-blocking disabling of device communications until the
+ * device has been removed (for use when an error occurs or communications with the device have completed)
+ * - Added new FAST_STREAM_TRANSFERS compile time option for faster stream transfers via multiple bytes copied per stream loop
+ * - Added stdio stream demo code to the CDC device demos, to show how to create standard streams out of the virtual serial ports
+ * - Added new EEPROM and FLASH buffer versions of the Endpoint and Pipe stream functions
+ * - Added new USE_FLASH_DESCRIPTORS and FIXED_NUM_CONFIGURATIONS compile time options
+ * - Added support for the new ATMEGA32U2, ATMEGA16U2 and ATMEGA8U2 AVR models
+ * - Added new USB_DeviceState variable to keep track of the current Device mode USB state
+ * - Added new LEDs_ToggleLEDs() function to the LEDs driver
+ * - Added new Pipe_BoundEndpointNumber() and Pipe_IsEndpointBound() functions
+ * - Added new DEVICE_STATE_AS_GPIOR and HOST_STATE_AS_GPIOR compile time options
+ * - Added 404 Not Found errors to the webserver in the RNDIS demos to indicate invalid URLs
+ *
+ * <b>Changed:</b>
+ * - Deprecated pseudo-scheduler and removed dynamic memory allocator from the library (first no longer needed and second unused)
+ * - The device-mode CALLBACK_USB_GetDescriptor() function now has an extra parameter so that the memory space in which the requested
+ * descriptor is located can be specified. This means that descriptors can now be located in multiple memory spaces within a device.
+ * - Removed vague USB_IsConnected global - test USB_DeviceState or USB_HostState explicitly to gain previous functionality
+ * - Removed USB_IsSuspended global - test USB_DeviceState against DEVICE_STATE_Suspended instead
+ * - Extended USB_GetDeviceConfigDescriptor() routine to require the configuration number within the device to fetch
+ * - Dataflash_WaitWhileBusy() now always ensures that the dataflash is ready for the next command immediately after returning,
+ * no need to call Dataflash_ToggleSelectedChipCS() afterwards
+ * - Low level API MIDI device demo no longer blocks if a note change event is sent while the endpoint is not ready
+ * - Pipe_GetErrorFlags() now returns additional error flags for overflow and underflow errors
+ * - Pipe stream functions now automatically set the correct pipe token, so that bidirectional pipes can be used
+ * - Pipe_ConfigurePipe() now automatically defaults IN pipes to accepting infinite IN requests, this can still be changed by calling
+ * the existing Pipe_SetFiniteINRequests() function
+ * - Changed F_USB entries in project makefiles to alias to F_CPU by default, as this is the most common case
+ * - Host mode demos now use sane terminal escape codes, so that text is always readable and events/program output is visually distinguished
+ * from one another using foreground colours
+ * - Internal per-device preprocessing conditions changed to per-device series rather than per-controller group for finer-grain
+ * internal control
+ * - Interrupts are no longer disabled during the processing of Control Requests on the default endpoint while in device mode
+ * - AudioOutput demos now always output to board LEDs, regardless of output mode (removed AUDIO_OUT_LEDS project option)
+ * - Removed SINGLE_DEVICE_CONFIGURATION compile time option in favor of the new FIXED_NUM_CONFIGURATIONS option so that the exact number
+ * of device configurations can be defined statically
+ * - Removed VBUS events, as they are already exposed to the user application via the regular device connection and disconnection events
+ * - Renamed and altered existing events to properly separate out Host and Device mode events
+ * - All demos switched over from GNU99 standards mode to C99 standards mode, to reduce the dependencies on GCC-only language extensions
+ *
+ * <b>Fixed:</b>
+ * - Changed bootloaders to use FLASHEND rather than the existence of RAMPZ to determine if far FLASH pointers are needed to fix
+ * bootloaders on some of the USB AVR devices where avr-libc erroneously defines RAMPZ
+ * - Fixes to MassStorageHost for better device compatibility (increase command timeout, change MassStore_WaitForDataReceived()
+ * to only unfreeze and check one data pipe at a time) to prevent incorrect device enumerations and freezes while transferring data
+ * - Make Pipe_ConfigurePipe() mask the given endpoint number against PIPE_EPNUM_MASK to ensure the endpoint IN direction bit is
+ * cleared to prevent endpoint type corruption
+ * - Fixed issue opening CDC-ACM ports on hosts when the CDC device tries to send data before the host has set the line encoding
+ * - Fixed USB_OPT_MANUAL_PLL option being ignored during device disconnects on some models (thanks to Brian Dickman)
+ * - Fixed documentation mentioning Pipe_GetCurrentToken() function when correct function name is Pipe_GetPipeToken()
+ * - Fixed ADC driver for the ATMEGA32U4 and ATMEGA16U4 (thanks to Opendous Inc.)
+ * - Fixed CDCHost demo unfreezing the pipes at the point of configuration, rather than use
+ * - Fixed MassStorage demo not clearing the reset flag when a Mass Storage Reset is issued while not processing a command
+ * - Fixed USB_Host_SendControlRequest() not re-suspending the USB bus when initial device ready-wait fails
+ * - Fixed USB Pad regulator not being disabled on some AVR models when the USB_OPT_REG_DISABLED option is used
+ * - Fixed Host mode to Device mode UID change not causing a USB Disconnect event when a device was connected
+ * - Fixed Mouse/Keyboard demos not performing the correct arithmetic on the Idle period at the right times (thanks to Brian Dickman)
+ * - Fixed GenericHID failing HID class tests due to incorrect Logical Minimum and Logical Maximum values (thanks to Soren Greiner)
+ * - Fixed incorrect PIPE_EPNUM_MASK mask causing pipe failures on devices with endpoint addresses of 8 and above (thanks to John Andrews)
+ * - Fixed report data alignment issues in the MouseHostWithParser demo when X and Y movement data size is not a multiple of 8 bits
+ * - Fixed HID Report Descriptor Parser not correctly resetting internal states when a REPORT ID element is encountered
+ * - Fixed incorrect BUTTONS_BUTTON1 for the STK526 target
+ * - Fixed RNDIS demos freezing when more than one connection was attempted simultaneously, causing memory corruption
+ * - Fixed USBtoSerial demo receiving noise from the USART due to pull-up not being enabled
+ *
+ *
+ * \section Sec_ChangeLog090605 Version 090605
+ *
+ * - Fixed bug in RNDISEthernet and DualCDC demos not using the correct USB_ControlRequest structure for control request data
+ * - Fixed documentation showing incorrect USB mode support on the supported AVRs list
+ * - Fixed RNDISEthernet not working under Linux due to Linux requiring an "optional" RNDIS request which was unhandled
+ * - Fixed Mouse and Keyboard device demos not acting in accordance with the HID specification for idle periods (thanks to Brian Dickman)
+ * - Removed support for endpoint/pipe non-control interrupts; these did not act in the way users expected, and had many subtle issues
+ * - Fixed Device Mode not handling Set Feature and Clear Feature Chapter 9 requests that are addressed to the device (thanks to Brian Dickman)
+ * - Moved control endpoint interrupt handling into the library itself, enable via the new INTERRUPT_CONTROL_ENDPOINT token
+ * - Fixed CDCHost not clearing configured pipes and resetting configured pipes mask when a partially enumerated invalid CDC
+ * interface is skipped
+ * - Clarified the size of library tokens which accept integer values in the Compile Time Tokens page, values now use the smallest datatype
+ * inside the library that is able to hold their defined value to save space
+ * - Removed DESCRIPTOR_ADDRESS() macro as it was largely superfluous and only served to obfuscate code
+ * - Rewritten event system to remove all macros, to make user code clearer
+ * - Fixed incorrect ENDPOINT_EPNUM_MASK mask preventing endpoints above EP3 from being selected (thanks to Jonathan Oakley)
+ * - Removed STREAM_CALLBACK() macro - callbacks now use regular function definitions to clarify user code
+ * - Removed DESCRIPTOR_COMPARATOR() macro - comparators should now use regular function definitions to clarify user code
+ * - USB_IsConnected is now cleared before the USB_Disconnect() event is fired in response to VBUS being removed
+ * - Fixed incorrect PID value being used in the USBtoSerial project (thanks to Phill)
+ * - Deleted StdDescriptors.c, renamed USB_GetDescriptor() to CALLBACK_USB_GetDescriptor, moved ConfigDescriptor.c/.h from the
+ * LUFA/Drivers/USB/Class/ directory to LUFA/Drivers/USB/HighLevel/ in preparation for the new USB class APIs
+ * - Moved out each demos' functionality library files (e.g. Ring Buffer library) to /Lib directories for a better directory structure
+ * - Removed Tx interrupt from the USBtoSerial demo; now sends characters via polling to ensure more time for the Rx interrupt
+ * - Fixed possible enumeration errors from spin-loops which may fail to exit if the USB connection is severed before the exit condition
+ * becomes true
+ *
+ *
+ * \section Sec_ChangeLog090510 Version 090510
+ *
+ * - Added new GenericHIDHost demo
+ * - Corrections to the KeyboardHost and MouseHost demos' pipe handling to freeze and unfreeze the data pipes at the point of use
+ * - KeyboardHost, MouseHost and GenericHIDHost demos now save and restore the currently selected pipe inside the pipe ISR
+ * - Changed GenericHID device demo to use the LUFA scheduler, added INTERRUPT_DATA_ENDPOINT and INTERRUPT_CONTROL_ENDPOINT compile
+ * time options
+ * - All comments in the library, bootloaders, demos and projects have now been spell-checked and spelling mistakes/typos corrected
+ * - Added new PIMA_DATA_SIZE() define to the Still Image Host demo
+ * - Add call to MassStore_WaitForDataReceived() in MassStore_GetReturnedStatus() to ensure that the CSW has been received in the
+ * extended MSC timeout period before continuing, to prevent long processing delays from causing the MassStore_GetReturnedStatus()
+ * to early-abort (thanks to Dmitry Maksimov)
+ * - Move StdRequestType.h, StreamCallbacks.h, USBMode.h from the LowLevel USB driver directory to the HighLevel USB driver directory,
+ * where they are more suited
+ * - Removed all binary constants and replaced with decimal or hexadecimal constants so that unpatched GCC compilers can still build the
+ * code without having to be itself patched and recompiled first
+ * - Added preprocessor checks and documentation to the bootloaders giving information about missing SIGNATURE_x defines due to
+ * outdated avr-libc versions.
+ * - Added support to the CDCHost demo for devices with multiple CDC interfaces which are not the correct ACM type preceding the desired
+ * ACM CDC interface
+ * - Fixed GenericHID demo not starting USB and HID management tasks when not using interrupt driven modes (thanks to Carl Kjeldsen)
+ * - Fixed RNDISEthenet demo checking the incorrect message field for packet size constraints (thanks to Jonathan Oakley)
+ * - Fixed WriteNextReport code in the GenericHIDHost demo using incorrect parameter types and not selecting the correct endpoint
+ * - Adjusted sample CTC timer calculations in the AudioOutput and AudioInput demos to match the CTC calculations in the AVR datasheet,
+ * and to fix instances where rounding caused the endpoint to underflow (thanks to Robin Theunis)
+ * - The USB_Host_SendControlRequest() function no longer automatically selects the Control pipe (pipe 0), so that other control type
+ * pipes can be used with the function
+ * - The USB Host management task now saves and restores the currently selected pipe before and after the task completes
+ * - Fixed GenericHIDHost demo report write routine incorrect for control type requests (thanks to Andrei Krainev)
+ * - Removed Endpoint_ClearCurrentBank() and Pipe_ClearCurrentBank() in favor of new Endpoint_ClearIN(), Endpoint_ClearOUT(),
+ * Pipe_ClearIN() and Pipe_ClearOUT() macros (done to allow for the detection of packets of zero length)
+ * - Renamed *_ReadWriteAllowed() macros to *_IsReadWriteAllowed() to remain consistent with the rest of the LUFA API
+ * - Endpoint_IsSetupReceived() macro has been renamed to Endpoint_IsSETUPReceived(), Endpoint_ClearSetupReceived() macro has been
+ * renamed to Endpoint_ClearSETUP(), the Pipe_IsSetupSent() macro has been renamed to Pipe_IsSETUPSent() and the
+ * Pipe_ClearSetupSent() macro is no longer applicable and should be removed - changes made to compliment the new endpoint and pipe
+ * bank management API
+ * - Updated all demos, bootloaders and projects to use the new endpoint and pipe management APIs (thanks to Roman Thiel from Curetis AG)
+ * - Updated library Doxygen documentation, added groups, changed documentation macro functions to real functions for clarity
+ * - Removed old endpoint and pipe aliased read/write/discard routines which did not have an explicit endian specifier for clarity
+ * - Removed the ButtLoadTag.h header file, as no one used for its intended purpose anyway
+ * - Renamed the main Drivers/AT90USBXXX directory to Drivers/Peripheral, renamed the Serial_Stream driver to SerialStream
+ * - Fixed CDC and USBtoSerial demos freezing where buffers were full while still transmitting or receiving (thanks to Peter Hand)
+ * - Removed "Host_" section of the function names in ConfigDescriptor.h, as most of the routines can now be used in device mode on the
+ * device descriptor
+ * - Renamed functions in the HID parser to have a "USB_" prefix and the acronym "HID" in the name
+ * - Fixed incorrect HID interface class and subclass values in the Mouse and KeyboardMouse demos (thanks to Brian Dickman)
+ * - Capitalized the "Descriptor_Search" and "Descriptor_Search_Comp" prefixes of the values in the DSearch_Return_ErrorCodes_t and
+ * DSearch_Comp_Return_ErrorCodes_t enums
+ * - Removed "ERROR" from the enum names in the endpoint and pipe stream error code enums
+ * - Renamed the USB_PowerOnErrorCodes_t enum to USB_InitErrorCodes_t, renamed the POWERON_ERROR_NoUSBModeSpecified enum value to
+ * USB_INITERROR_NoUSBModeSpecified
+ * - Renamed USB_PowerOnFail event to USB_InitFailure
+ * - Renamed OTG.h header functions to be more consistent with the rest of the library API
+ * - Changed over all deprecated GCC structure tag initializers to the standardized C99 format (thanks to Mike Alexander)
+ * - USB_HostRequest renamed to USB_ControlRequest, entire control request header is now read into USB_ControlRequest in Device mode
+ * rather than having the library pass only partially read header data to the application
+ * - The USB_UnhandledControlPacket event has had its parameters removed, in favor of accessing the new USB_ControlRequest structure
+ * - The Endpoint control stream functions now correctly send a ZLP to the host when less data than requested is sent
+ * - Fixed USB_RemoteWakeupEnabled flag never being set (the REMOTE WAKEUP Set Feature request was not being handled)
+ * - Renamed the FEATURELESS_CONTROL_ONLY_DEVICE compile-time token to CONTROL_ONLY_DEVICE
+ * - Endpoint configuration is now refined to give better output when all configurations have static inputs - removed the now useless
+ * STATIC_ENDPOINT_CONFIGURATION compile time token
+ * - Fixed SPI driver init function not clearing SPI2X bit when not needed
+ * - Fixed PREVENT ALLOW MEDIUM REMOVAL command issuing in the MassStorageHost demo using incorrect parameters (thanks to Mike Alex)
+ * - Fixed MassStorageHost demo broken due to an incorrect if statement test in MassStore_GetReturnedStatus()
+ * - Fixed reversed signature byte ordering in the CDC bootloader (thanks to Johannes Raschke)
+ * - Changed PIPE_CONTROLPIPE_DEFAULT_SIZE from 8 to 64 to try to prevent problems with faulty devices which do not respect the given
+ * wLength value when reading in the device descriptor
+ * - Fixed missing semicolon in the ATAVRUSBRF01 LED board driver code (thanks to Morten Lund)
+ * - Changed LED board driver code to define dummy LED masks for the first four board LEDs, so that user code can be compiled for boards
+ * with less than four LEDs without code modifications (thanks to Morten Lund)
+ * - Changed HWB board driver to Buttons driver, to allow for the support of future boards with more than one mounted GPIO button
+ * - Serial driver now correctly calculates the baud register value when in double speed mode
+ * - Init function of the Serial driver is now static inline to product smaller code for the common-case of static init values
+ *
+ *
+ * \section Sec_ChangeLog090401 Version 090401
+ *
+ * - Fixed MagStripe project configuration descriptor containing an unused (blank) endpoint descriptor
+ * - Incorporated makefile changes by Denver Gingerich to retain compatibility with stock (non-WinAVR) AVR-GCC installations
+ * - Fixed makefile EEPROM programming targets programming FLASH data in addition to EEPROM data
+ * - LUFA devices now enumerate correctly with LUFA hosts
+ * - Fixed Configuration Descriptor search routine freezing when a comparator returned a failure
+ * - Removed HID report item serial dump in the MouseHostWithParser and KeyboardHostWithParser - useful only for debugging, and
+ * slowed down the enumeration of HID devices too much
+ * - Increased the number of bits per track which can be read in the MagStripe project to 8192 when compiled for the AT90USBXXX6/7
+ * - Fixed KeyboardMouse demo discarding the wIndex value in the REQ_GetReport request
+ * - USBtoSerial demo now discards all Rx data when not connected to a USB host, rather than buffering characters for transmission
+ * next time the device is attached to a host.
+ * - Added new F_USB compile time constant to the library and makefiles, to give the raw input clock (used to feed the PLL before any
+ * clock prescaling is performed) frequency, so that the PLL prescale mask can be determined
+ * - Changed stream wait timeout counter to be 16-bit, so that very long timeout periods can be set for correct communications with
+ * badly designed hosts or devices which greatly exceed the USB specification limits
+ * - Mass Storage Host demo now uses a USB_STREAM_TIMEOUT_MS of two seconds to maintain compatibility with poorly designed devices
+ * - Function attribute ATTR_ALWAYSINLINE renamed to ATTR_ALWAYS_INLINE to match other function attribute macro naming conventions
+ * - Added ATTR_ALWAYS_INLINE attribute to several key inlined library components, to ensure they are inlined in all circumstances
+ * - Removed SetSystemClockPrescaler() macro, the clock_prescale_set() avr-libc macro has been corrected in recent avr-libc versions
+ * - Fixed incorrect/missing control status stage transfers on demos, bootloaders and applications (thanks to Nate Lawson)
+ * - The NO_CLEARSET_FEATURE_REQUEST compile time token has been renamed to FEATURELESS_CONTROL_ONLY_DEVICE, and its function expanded
+ * to also remove parts of the Get Status chapter 9 request to further reduce code usage
+ * - Makefile updated to include output giving the currently selected BOARD parameter value
+ * - Board Dataflash driver now allows for dataflash ICs which use different shifts for setting the current page/byte address (thanks
+ * to Kenneth Clubb)
+ * - Added DataflashManager_WriteBlocks_RAM() and DataflashManager_ReadBlocks_RAM() functions to the MassStorage demo, to allow for easy
+ * interfacing with a FAT library for dataflash file level access
+ * - Corrected CDC class bootloader to fix a few bugs, changed address counter to store x2 addresses for convenience
+ * - Fixed typos in the SPI driver SPI_SPEED_FCPU_DIV_64 and SPI_SPEED_FCPU_DIV_128 masks (thanks to Markus Zocholl)
+ * - Keyboard and Mouse device demos (normal, data interrupt and fully interrupt driven) combined into unified keyboard and mouse demos
+ * - Keyboard and Mouse host demos (normal and data interrupt driven) combined into unified keyboard and mouse demos
+ * - Removed AVRISP_Programmer project due to code quality concerns
+ * - Fixed CDC demo not sending an empty packet after each transfer to prevent the host from buffering incoming data
+ * - Fixed documentation typos and preprocessor checks relating to misspellings of the USE_RAM_DESCRIPTORS token (thanks to Ian Gregg)
+ * - Fixed USBTask.h not conditionally including HostChapter9.h only when USB_CAN_BE_HOST is defined (thanks to Ian Gregg)
+ * - Fixed incorrect ADC driver init register manipulation (thanks to Tobias)
+ * - Added new GenericHID device demo application
+ * - Fixed Still Image Host SImage_SendData() function not clearing the pipe bank after sending data
+ *
+ *
+ * \section Sec_ChangeLog090209 Version 090209
+ *
+ * - PWM timer mode in AudioOut demo changed to Fast PWM for speed
+ * - Updated Magstripe project to work with the latest hardware revision
+ * - Fixed library not responding to the BCERRI flag correctly in host mode, leading to device lockups
+ * - Fixed library handling Get Descriptor requests when not addressed as standard requests to the device or interface (thanks to
+ * Nate Lawson)
+ * - Fixed serious data corruption issue in MassStorage demo dataflash write routine
+ * - Added new NO_CLEARSET_FEATURE_REQUEST compile time token
+ * - USB task now restores previous global interrupt state after execution, rather than forcing global interrupts to be enabled
+ * - Fixed USB_DeviceEnumerationComplete event firing after each configuration change, rather than once after the initial configuration
+ * - Added ENDPOINT_DOUBLEBANK_SUPPORTED() macros to Endpoint.h, altered ENDPOINT_MAX_SIZE() to allow user to specify endpoint
+ * - ENDPOINT_MAX_ENDPOINTS changed to ENDPOINT_TOTAL_ENDPOINTS, PIPE_MAX_PIPES changed to PIPE_TOTAL_PIPES
+ * - Endpoint and Pipe non-control stream functions now ensure endpoint or pipe is ready before reading or writing
+ * - Changed Teensy bootloader to use a watchdog reset when exiting rather than a software jump
+ * - Fixed integer promotion error in MassStorage and MassStorageHost demos, corrupting read/write transfers
+ * - SPI_SendByte is now SPI_TransferByte, added new SPI_SendByte and SPI_ReceiveByte functions for fast one-way transfer
+ * - MassStorage demo changed to use new fast one-way SPI transfers to increase throughput
+ * - MassStorage handling of Mass Storage Reset class request improved
+ * - Altered MassStorage demo dataflash block read code for speed
+ * - Added USB_IsSuspended global flag
+ * - Simplified internal Dual Mode (OTG) USB library code to reduce code size
+ * - Extended stream timeout period to 100ms from 50ms
+ * - Mass Storage Host demo commands now all return an error code from the Pipe_Stream_RW_ErrorCodes_t enum
+ * - Added SubErrorCode parameter to the USB_DeviceEnumerationFailed event
+ * - VBUS drop interrupt now disabled during the manual-to-auto VBUS delivery handoff
+ * - Simplified low level backend so that device/host mode initialization uses the same code paths
+ * - Added workaround for faulty Mass Storage devices which do not implement the required GET_MAX_LUN request
+ * - Removed buggy Telnet application from the RNDIS demo
+ * - Moved Mass Storage class requests in the Mass Storage Host demo to wrapper functions in MassStoreCommands.c
+ * - Fixed incorrect SCSI command size value in the Request Sense command in MassStoreCommands.c
+ * - Added SetProtocol request to HID class non-parser Mouse and Keyboard demos to force devices to use the correct Boot Protocol
+ * - Added new "dfu" and "flip" programming targets to project makefiles
+ * - HID_PARSE_Sucessful enum member typo corrected to HID_PARSE_Successful
+ * - Changed COLLECTION item structures in the HID descriptor parser to include the collection's Usage Page value
+ * - Serial driver now sets Tx line as output, enables pull-up on Rx line
+ * - Fixed smaller USB AVRs raising multiple connection and disconnection events when NO_LIMITED_CONTROLLER_CONNECT is disabled
+ * - Added HOST_DEVICE_SETTLE_DELAY_MS to give the host delay after a device is connected before it is enumerated
+ * - Fixed KeyboardHostWithParser demo linking against the wrong global variables
+ * - Completed doxygen documentation of remaining library bootloaders, demos and projects
+ * - Fixed incorrect bootloader start address in the TeensyHID bootloader
+ * - Added HWB button whole-disk ASCII dump functionality to MassStoreHost demo
+ * - Replaced printf_P(PSTR("%c"), {Variable}) calls with putchar(<Variable>) for speed and size savings
+ * - Serial driver now accepts baud rates over 16-bits in size, added double speed flag option
+ * - Fixed incorrect callback abort return value in Pipe.c
+ * - Added new flip-ee and dfu-ee makefile targets (courtesy of Opendous Inc.)
+ * - Removed reboot-on-disconnect code from the TeensyHID bootloader, caused problems on some systems
+ * - Fixed AudioOutput and AudioInput demos looping on the endpoint data, rather than processing a sample at a time and returning
+ * each time the task runs to allow for other tasks to execute
+ * - Added support for the Atmel ATAVRUSBRF01 board
+ * - Added AVRISP Programmer Project, courtesy of Opendous Inc.
+ * - Fixed CDC Host demo not searching through both CDC interfaces for endpoints
+ * - Fixed incorrect Product String descriptor length in the DFU class bootloader
+ *
+ *
+ * \section Sec_ChangeLog081224 Version 081224
+ *
+ * - MyUSB name changed to LUFA, the Lightweight USB Framework for AVRs
+ * - Fixed Mass Storage Host demo's MassStore_SendCommand() delay in the incorrect place
+ * - Fixed USBtoSerial demo not calling ReconfigureUSART() after a change in the line encoding
+ * - Fixed infinite loop in host mode Host-to-Device control transfers with data stages
+ * - HID report parser now supports devices with multiple reports in one interface via Report IDs
+ * - Fixed RZUSBSTICK board LED driver header incorrect macro definition order causing compile errors
+ * - Calling USB_Init() when the USB interface is already configured now forces a complete interface reset
+ * and re-enumeration - fixes MyUSB DFU bootloader not switching to app code correctly when soft reset used
+ * - Fixed "No newline at end of file" warning when stream callbacks are enabled
+ * - DFU bootloader now uses fixed signature bytes per device, rather than reading them out dynamically for size
+ * - Added new FIXED_CONTROL_ENDPOINT_SIZE and USE_SINGLE_DEVICE_CONFIGURATION switches to statically define certain values to
+ * reduce compiled binary size
+ * - Added new NO_LIMITED_CONTROLLER_CONNECT switch to prevent the library from trying to determine bus connection
+ * state from the suspension and wake up events on the smaller USB AVRs
+ * - Added summary of all library compile time tokens to the documentation
+ * - Added overview of the LUFA scheduler to the documentation
+ * - Removed MANUAL_PLL_CONTROL compile time token, replaced with a mask for the USB_Init() Options parameter
+ * - CDC bootloader now uses the correct non-far or far versions of the pgm_* functions depending on if RAMPZ is defined
+ * - Doxygen documentation now contains documentation on all the projects, bootloaders and most demos included with the library
+ * - CDC bootloader now runs user application when USB disconnected rather than waiting for a hard reset
+ * - MouseHostWithParser and KeyboardHostWithParser now support multiple-report devices
+ * - RNDIS demo can now close connections correctly using the new TCP_APP_CLOSECONNECTION() macro - used in Webserver
+ * - Fixed the DFU bootloader, no longer freezes up when certain files are programmed into an AVR, made reading/writing faster
+ * - Fixed mouse/joystick up/down movements reversed - HID mouse X/Y coordinates use a left-handed coordinate system, not a normal
+ * right-handed system
+ * - Added stub code to the CDC and USBtoSerial demos showing how to read and set the RS-232 handshake lines - not currently used in
+ * the demos, but the example code and supporting defines are now in place
+ * - Interrupts are now disabled when processing a control request in device mode, to avoid exceeding the strict control request
+ * timing requirements.
+ * - All demos now use a central StatusUpdate() function rather than direct calls to the board LED functions, so that the demos can
+ * easily be altered to show different LED combinations (or do something else entirely) as the demo's status changes
+ * - Removed LED commands from the CDC bootloader, unused by most AVR910 programming software
+ * - Fixed RNDIS demo ICMP ping requests echoing back incorrect data
+ * - Added DHCP server code to RNDIS demo, allowing for hands-free auto configuration on any PC
+ * - Fixed DFU bootloader PID value for the ATMEGA16U4 AVR
+ * - Endpoint and Pipe configuration functions now return an error code indicating success or failure
+ * - USB Reset in device mode now resets and disables all device endpoints
+ * - Added intermediate states to the host mode state machine, reducing the USB task blocking time to no more than 1ms explicitly per
+ * invocation when in host mode
+ * - Added support for the ATMEGA32U6 microcontroller
+ * - Added STATIC_ENDPOINT_CONFIGURATION compile time option, enabled in the bootloaders to minimize space usage
+ * - Removed redundant code from the USB device GetStatus() chapter 9 processing routine
+ * - Added new TeensyHID bootloader, compatible with the Teensy HID protocol (http://www.pjrc.com/teensy/)
+ * - Versions are now numbered by release dates, rather than arbitrary major/minor revision numbers
+ * - USB_RemoteWakeupEnabled is now correctly set and cleared by SetFeature and ClearFeature requests from the host
+ * - Changed prototype of GetDescriptor, so that it now returns the descriptor size (or zero if the descriptor doesn't exist)
+ * rather than passing the size back to the caller through a parameter and returning a boolean
+ *
+ *
+ * \section Sec_ChangeLog153 Version 1.5.3 (081002)
+ *
+ * - Fixed CDC bootloader using pgmspace macros for some descriptors inappropriately
+ * - Updated all Mouse and Keyboard device demos to include boot protocol support (now works in BIOS)
+ * - Renamed bootloader directories to remove spaces, which were causing build problems on several OSes
+ * - Removed serial number strings from all but the MassStore demo where it is required - users were not
+ * modifying the code to either omit the descriptor or use a unique serial per device causing problems
+ * when multiple units of the same device were plugged in at the same time
+ * - AudioOutput and AudioInput demos now correctly silence endpoints when not enabled by the host
+ * - Added KeyboardMouse demo (Keyboard and Mouse functionality combined into a single demo)
+ * - Added DriverStubs directory to house board level driver templates, to make MyUSB compatible custom board
+ * driver creation easier
+ * - Extended MassStorage demo to support multiple LUNs, 2 by default
+ * - Fixed incorrect device address mask, preventing the device from enumerating with addresses larger than 63
+ * - Fixed incorrect data direction mask in the GetStatus standard request, preventing it from being handled
+ * - Fixed incorrect GetStatus standard request for endpoints, now returns the endpoint STALL status correctly
+ * - Added in new USB_RemoteWakeupEnabled and USB_CurrentlySelfPowered flags rather than using fixed values
+ * - Added DualCDC demo to demonstrate the use of Interface Association Descriptors
+ * - Added pipe NAK detection and clearing API
+ * - Added pipe status change (NAK, STALL, etc.) interrupt API
+ * - Fixed MassStorageHost demo so that it no longer freezes randomly when issuing several commands in a row
+ * - Host demos configuration descriptor routines now return a unique error code when the returned data does
+ * not have a valid configuration descriptor header
+ * - Added Endpoint_WaitUntilReady() and Pipe_WaitUntilReady() functions
+ * - Stream functions now have software timeouts, timeout period can be set by the USB_STREAM_TIMEOUT_MS token
+ * - All demos now pass the USB.org automated Chapter 9 device compliance tests
+ * - All HID demos now pass the USB.org automated HID compliance tests
+ * - Polling interval of the interrupt endpoint in the CDC based demos changed to 0xFF to fix problems on Linux systems
+ * - Changed stream functions to accept a new callback function, with NO_STREAM_CALLBACKS used to disable all callbacks
+ * - Mass Storage demo Dataflash management routines changed to use the endpoint stream functions
+ * - Added AVRStudio project files for each demo in addition to the existing Programmer's Notepad master project file
+ * - Re-added call to ReconfigureUSART() in USBtoSerial SetLineCoding request, so that baud rate changes
+ * are reflected in the hardware (change was previously lost)
+ *
+ *
+ * \section Sec_ChangeLog152 Version 1.5.2 (080731)
+ *
+ * - Fixed SwapEndian_32() function in Common.h so that it now works correctly (wrong parameter types)
+ * - Updated RNDIS demo - notification endpoint is no longer blocking so that it works with faulty Linux RNDIS
+ * implementations (where the notification endpoint is ignored in favor of polling the control endpoint)
+ * - Fixed incorrect Vendor Description string return size in RNDIS demo for the OID_GEN_VENDOR_DESCRIPTION OID token
+ * - Added very basic TCP/IP stack and HTTP/TELNET servers to RNDIS demo
+ * - Fixed DFU bootloader exit causing programming software to complain about failed writes
+ * - Fixed DFU bootloader EEPROM programming mode wiping first flash page
+ * - Fixed Clear/Set Feature device standard request processing code (fixing MassStorage demo in the process)
+ * - Added support for the ATMEGA16U4 AVR microcontroller
+ * - Library license changed from LGPLv3 to MIT license
+ *
+ *
+ * \section Sec_ChangeLog151 Version 1.5.1 (080707)
+ *
+ * - Changed host demos to enable the host function task on the firing of the USB_DeviceEnumerationComplete event
+ * rather than the USB_DeviceAttached event
+ * - HID Usage Stack now forcefully cleared after an IN/OUT/FEATURE item has been completely processed to remove
+ * any referenced but not created usages
+ * - Changed USB_INT_DisableAllInterrupts() and USB_INT_ClearAllInterrupts(), USB_Host_GetNextDescriptorOfType(),
+ * USB_Host_GetNextDescriptorOfTypeBefore(), USB_Host_GetNextDescriptorOfTypeAfter() to normal functions (from inline)
+ * - Fixed USBtoSerial demo not sending data, only receiving
+ * - Fixed main makefile to make all by default, fixed MagStripe directory case to prevent case-sensitive path problems
+ * - ConfigDescriptor functions made normal, instead of static inline
+ * - Pipe/Endpoint *_Ignore_* functions changed to *_Discard_*, old names still present as aliases
+ * - Fixed ENDPOINT_MAX_SIZE define to be correct on limited USB controller AVRs
+ * - Changed endpoint and pipe size translation routines to use previous IF/ELSE IF cascade code, new algorithmic
+ * approach was buggy and caused problems
+ * - Bootloaders now compile with -fno-inline-small-functions option to reduce code size
+ * - Audio demos now use correct endpoint sizes for full and limited controller USB AVRs, double banking in all cases
+ * to be in line with the specification (isochronous endpoints MUST be double banked)
+ * - Added Interface Association descriptor to StdDescriptors.h, based on the relevant USB2.0 ECN
+ * - Fixed MIDI demo, corrected Audio Streaming descriptor to follow the MIDI-specific AS structure
+ * - Fixed HID class demo descriptors so that the HID interface's protocol is 0x00 (required for non-boot protocol HID
+ * devices) to prevent problems on hosts expecting the boot protocol functions to be supported
+ * - Added read/write control stream functions to Endpoint.h
+ * - Fixed AudioOut demo not setting port pins to inputs on USB disconnect properly
+ * - Added RNDISEthernet demo application
+ *
+ *
+ * \section Sec_ChangeLog150 Version 1.5.0 (080610)
+ *
+ * - Fixed MIDI demo, now correctly waits for the endpoint to be ready between multiple note messages
+ * - Added CDC Host demo application
+ * - Added KeyboardFullInt demo application
+ * - Endpoint and Pipe creation routines now mask endpoint/pipe size with the size mask, to remove transaction
+ * size bits not required for the routines (improves compatibility with devices)
+ * - Fixed AudioInput demo - now correctly sends sampled audio to the host PC
+ * - Fixed AudioOutput demo once more -- apparently Windows requires endpoint packets to be >=192 bytes
+ * - Shrunk round-robin scheduler code slightly via the use of struct pointers rather than array indexes
+ * - Fixed off-by-one error when determining if the Usage Stack is full inside the HID Report parser
+ * - Renamed Magstripe.h to MagstripeHW.h and moved driver out of the library and into the MagStripe demo folder
+ * - Added preprocessor checks to enable C linkage on the library components when used with a C++ compiler
+ * - Added Still Image Host demo application
+ * - The USB device task now restores the previously selected endpoint, allowing control requests to be transparently
+ * handled via interrupts while other endpoints are serviced through polling
+ * - Fixed device signature being sent in reverse order in the CDC bootloader
+ * - Host demos now have a separate ConfigDescriptor.c/.h file for configuration descriptor processing
+ * - HostWithParser demos now have a separate HIDReport.c/.h file for HID report processing and dumping
+ * - Removed non-mandatory commands from MassStorage demo to save space, fixed SENSE ResponseCode value
+ * - CDC demos now send empty packets after sending a full one to prevent buffering issues on the host
+ * - Updated demo descriptors to use VID/PID values donated by Atmel
+ * - Added DoxyGen documentation to the source files
+ * - Fixed Serial_IsCharReceived() definition, was previously reversed
+ * - Removed separate USB_Descriptor_Language_t descriptor, USB_Descriptor_String_t is used instead
+ * - Removed unused Device Qualifier descriptor structure
+ * - Renamed the USB_CreateEndpoints event to the more appropriate USB_ConfigurationChanged
+ * - Fixed MassStorageHost demo reading in the block data in reverse
+ * - Removed outdated typedefs in StdRequestType.h, superseded by the macro masks
+ * - Corrected OTG.h is now included when the AVR supports both Host and Device modes, for creating OTG products
+ * - USB_DeviceEnumerationComplete event is now also fired when in device mode and the host has finished its enumeration
+ * - Interrupt driven demos now properly restore previously selected endpoint when ISR is complete
+ * - The value of USB_HOST_TIMEOUT_MS can now be overridden in the user project makefile to a custom fixed timeout value
+ * - Renamed USB_Host_SOFGeneration_* macros to more friendly USB_Host_SuspendBus(), USB_Host_ResumeBus()
+ * and USB_Host_IsBusSuspended()
+ * - Renamed *_*_Is* macros to *_Is* to make all flag checking macros consistent, Pipe_SetInterruptFreq() is now
+ * Pipe_SetInterruptPeriod() to use the correct terminology
+ * - UnicodeString member of USB_Descriptor_String_t struct changed to an ordinary int array type, so that the GCC
+ * Unicode strings (prefixed with an L before the opening quotation mark) can be used instead of explicit arrays
+ * of ASCII characters
+ * - Fixed Endpoint/Pipes being configured incorrectly if the maximum endpoint/pipe size for the selected USB AVR
+ * model was given as the bank size
+ * - HID device demos now use a true raw array for the HID report descriptor rather than a struct wrapped array
+ * - Added VERSION_BCD() macro, fixed reported HID and USB version numbers in demo descriptors
+ * - Cleaned up GetDescriptor device chapter 9 handler function
+ * - Added GET_REPORT class specific request to HID demos to make them complaint to the HID class
+ * - Cleaned up setting of USB_IsInitialized and USB_IsConnected values to only when needed
+ * - Removed Atomic.c and ISRMacro.h; the library was already only compatible with recent avr-lib-c for other reasons
+ * - All demos and library functions now use USB standardized names for the USB data (bRequest, wLength, etc.)
+ * - Added USE_NONSTANDARD_DESCRIPTOR_NAMES token to switch back to the non-standard descriptor element names
+ *
+ *
+ * \section Sec_ChangeLog141 Version 1.4.1 (090519)
+ *
+ * - Enhanced KeyboardWithParser demo, now prints out pressed alphanumeric characters like the standard demo
+ * - Fixed MassStorage demo, read/writes using non mode-10 commands now work correctly
+ * - Corrected version number in Version.h
+ *
+ *
+ * \section Sec_ChangeLog140 Version 1.4.0 (090505)
+ *
+ * - Added HID Report Parser API to the library
+ * - Added Mouse and Keyboard host demo applications, using the new HID report parser engine
+ * - Added MouseFullInt demo, which demonstrates a fully interrupt (including control requests) mouse device
+ * - Fixed incorrect length value in the audio control descriptor of the AudioOutput and AudioInput demos
+ * - Added MIDI device demo application to the library
+ * - Fixed problem preventing USB devices from being resumed from a suspended state
+ * - Added new CDC class bootloader to the library, based on the AVR109 bootloader protocol
+ * - Added header to each demo application indicating the mode, class, subclass, standards used and supported speed
+ * - Functions expecting endpoint/pipe numbers are no longer automatically masked against ENDPOINT_EPNUM_MASK or
+ * PIPE_PIPENUM_MASK - this should be manually added to code which requires it
+ * - Fixed DFU class bootloader - corrected frequency of flash page writes, greatly reducing programming time
+ * - Renamed AVR_HOST_GetDeviceConfigDescriptor() to USB_Host_GetDeviceConfigDescriptor() and AVR_HOST_GetNextDescriptor()
+ * to USB_Host_GetNextDescriptor()
+ * - Added new USB_Host_GetNextDescriptorOfTypeBefore() and USB_Host_GetNextDescriptorOfTypeAfter() routines
+ * - Moved configuration descriptor routines to MyUSB/Drivers/USB/Class/, new accompanying ConfigDescriptors.c file
+ * - Added new configuration descriptor comparator API for more powerful descriptor parsing, updated host demos to use the
+ * new comparator API
+ * - Fixed MassStorageHost demo capacity printout, and changed data read/write mode from little-endian to the correct
+ * big-endian for SCSI devices
+ * - Fixed macro/function naming consistency; USB_HOST is now USB_Host, USB_DEV is now USB_Device
+ * - Added better error reporting to host demos
+ * - Added 10 microsecond delay after addressing devices in host mode, to prevent control stalls
+ *
+ *
+ * \section Sec_ChangeLog132 Version 1.3.2 (080401)
+ *
+ * - Added call to ReconfigureUSART() in USBtoSerial SetLineCoding request, so that baud rate changes
+ * are reflected in the hardware
+ * - Fixed CDC and USBtoSerial demos - Stream commands do not work for control endpoints, and the
+ * GetLineCoding request had an incorrect RequestType mask preventing it from being processed
+ * - Improved reliability of the USBtoSerial demo, adding a busy wait while the buffer is full
+ * - Device control endpoint size is now determined from the device's descriptors rather than being fixed
+ * - Separated out SPI code into new SPI driver in AT90USBXXX driver directory
+ * - Bootloader now returns correct PID for the selected USB AVR model, not just the AT90USB128X PID
+ * - Added support for the RZUSBSTICK board
+ * - Bicolour driver removed in favor of generic LEDs driver
+ * - Added support for the ATMEGA32U4 AVR
+ * - Added MANUAL_PLL_CONTROL compile time option to prevent the USB library from manipulating the PLL
+ *
+ *
+ * \section Sec_ChangeLog131 Version 1.3.1 (080319)
+ *
+ * - Fixed USB to Serial demo - class value in the descriptors was incorrect
+ * - Control endpoint size changed from 64 bytes to 8 bytes to save on USB FIFO RAM and to allow low
+ * speed mode devices to enumerate properly
+ * - USB to Serial demo data endpoints changed to dual-banked 16 byte to allow the demo to work
+ * on USB AVRs with limited USB FIFO RAM
+ * - Changed demo endpoint numbers to use endpoints 3 and 4 for double banking, to allow limited
+ * USB device controller AVRs (AT90USB162, AT90USB82) to function correctly
+ * - Updated Audio Out demo to use timer 1 for AVRs lacking a timer 3 for the PWM output
+ * - Fixed incorrect USB_DEV_OPT_HIGHSPEED entry in the Mass Storage device demo makefile
+ * - Optimized Mass Storage demo for a little extra transfer speed
+ * - Added LED indicators to the Keyboard demo for Caps Lock, Num Lock and Scroll Lock
+ * - Added Endpoint_Read_Stream, Endpoint_Write_Stream, Pipe_Read_Stream and Pipe_Write_Stream functions
+ * (including Big and Little Endian variants)
+ * - Made Dataflash functions inline for speed, removed now empty Dataflash.c driver file
+ * - Added new SetSystemClockPrescaler() macro (thanks to Joerg Wunsch)
+ * - Fixed Endpoint_ClearStall() to function correctly on full USB controller AVRs (AT90USBXXX6/7)
+ * - Endpoint_Setup_In_Clear() and Endpoint_Setup_Out_Clear() no longer set FIFOCON, in line with the
+ * directives in the datasheet
+ * - Fixed PLL prescaler defines for all AVR models and frequencies
+ * - Fixed ENDPOINT_INT_IN and ENDPOINT_INT_OUT definitions
+ * - Added interrupt driven keyboard and mouse device demos
+ * - Combined USB_Device_ClearFeature and USB_Device_SetFeature requests into a single routine for code
+ * size savings
+ * - Added missing Pipe_GetCurrentPipe() macro to Pipe.h
+ *
+ *
+ * \section Sec_ChangeLog130 Version 1.3.0 (080307)
+ *
+ * - Unnecessary control endpoint config removed from device mode
+ * - Fixed device standard request interpreter accidentally processing some class-specific requests
+ * - Added USE_RAM_DESCRIPTORS and USE_EEPROM_DESCRIPTORS compile time options to instruct the library
+ * to use descriptors stored in RAM or EEPROM rather than flash memory
+ * - All demos now disable watchdog on startup, in case it has been enabled by fuses or the bootloader
+ * - USB_DEV_OPT_LOWSPEED option now works correctly
+ * - Added ability to set the USB options statically for a binary size reduction via the USE_STATIC_OPTIONS
+ * compile time define
+ * - USB_Init no longer takes a Mode parameter if compiled for a USB device with no host mode option, or
+ * if forced to a particular mode via the USB_HOST_ONLY or USB_DEVICE_ONLY compile time options
+ * - USB_Init no longer takes an Options parameter if options statically configured by USE_STATIC_OPTIONS
+ * - Endpoint_Ignore_* and Pipe_Ignore_* made smaller by making the dummy variable non-volatile so that the
+ * compiler can throw away the result more efficiently
+ * - Added in an optional GroupID value to each scheduler entry, so that groups of tasks can once again be
+ * controlled by the new Scheduler_SetGroupTaskMode() routine
+ * - Added support for AT90USB162 and AT90USB82 AVR models
+ * - Added support for the STK525 and STK526 boards
+ * - Added support for custom board drivers to be supplied by selecting the board type as BOARD_USER, and
+ * placing board drivers in {Application Directory}/Board/
+ * - PLL is now stopped and USB clock is frozen when detached from host in device mode, to save power
+ * - Joystick defines are now in sync with the schematics - orientation will be rotated for the USBKEY
+ * - Fixed USB_DEV_IsUSBSuspended() - now checks the correct register
+ * - Fixed data transfers to devices when in host mode
+ * - Renamed USB_DEV_OPT_HIGHSPEED to USB_DEV_OPT_FULLSPEED and USB_HOST_IsDeviceHighSpeed() to
+ * USB_HOST_IsDeviceFullSpeed() to be in line with the official USB speed names (to avoid confusion with
+ * the real high speed mode, which is unavailable on the USB AVRs)
+ *
+ *
+ * \section Sec_ChangeLog120 Version 1.2.0 (080204)
+ *
+ * - Added USB_DeviceEnumerationComplete event for host mode
+ * - Added new Scheduler_Init routine to prepare the scheduler, so that tasks can be started and
+ * stopped before the scheduler has been started (via Scheduler_Start)
+ * - Connection events in both Device and Host mode are now interrupt-driven, allowing the USB management
+ * task to be stopped when the USB is not connected to a host or device
+ * - All demos updated to stop the USB task when not in use via the appropriate USB events
+ * - Mass Storage Host demo application updated to function correctly with all USB flash disks
+ * - Mass Storage Host demo application now prints out the capacity and number of LUNs in the attached
+ * device, and prints the first block as hexadecimal numbers rather than ASCII characters
+ * - Endpoint and Pipe clearing routines now clear the Endpoint/Pipe interrupt and status flags
+ * - Shifted error handling code in the host enum state machine to a single block, to reduce code complexity
+ * - Added in DESCRIPTOR_TYPE, DESCRIPTOR_SIZE and DESCRIPTOR_CAST macros to make config descriptor processing
+ * clearer in USB hosts and DESCRIPTOR_ADDRESS for convenience in USB devices
+ * - Added in alloca macro to common.h, in case the user is using an old version of avr-lib-c missing the macro
+ *
+ *
+ * \section Sec_ChangeLog110 Version 1.1.0 (080125)
+ *
+ * - Fixed DCONNI interrupt being enabled accidentally after a USB reset
+ * - Fixed DDISCI interrupt not being disabled when a device is not connected
+ * - Added workaround for powerless pull-up devices causing false disconnect interrupts
+ * - Added USB_DeviceEnumerationFailed event for Host mode
+ * - AVR_HOST_GetDeviceConfigDescriptor routine no longer modifies ConfigSizePtr if a valid buffer
+ * pointer is passed
+ * - Added ALLOCABLE_BYTES to DynAlloc, and added code to make the size of key storage variables
+ * dependent on size of memory parameters passed in via the user project's makefile
+ * - Fixed incorrect device reset routine being called in USBTask
+ * - Devices which do not connect within the standard 300mS are now supported
+ * - Removed incorrect ATTR_PURE from Scheduler_SetTaskMode(), which was preventing tasks from being
+ * started/stopped, as well as USB_InitTaskPointer(), which was breaking dual device/host USB projects
+ * - Changed scheduler to use the task name rather than IDs for setting the task mode, eliminating the
+ * need to have a task ID list
+ * - ID transition interrupt now raises the appropriate device/host disconnect event if device attached
+ * - Fixed double VBUS change (and VBUS -) event when detaching in device mode
+ * - Added ability to disable ANSI terminal codes by the defining of DISABLE_TERMINAL_CODES in makefile
+ * - Removed return from ConfigurePipe and ConfigureEndpoint functions - use Pipe_IsConfigured() and
+ * Endpoint_IsConfigured() after calling the config functions to determine success
+ */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/CompileTimeTokens.txt b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/CompileTimeTokens.txt
new file mode 100644
index 000000000..ab075cff7
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/CompileTimeTokens.txt
@@ -0,0 +1,223 @@
+/** \file
+ *
+ * This file contains special DoxyGen information for the generation of the main page and other special
+ * documentation pages. It is not a project source file.
+ */
+
+/** \page Page_TokenSummary Summary of Compile Tokens
+ *
+ * The following lists all the possible tokens which can be defined in a project makefile, and passed to the
+ * compiler via the -D switch, to alter the LUFA library code. These tokens may alter the library behaviour,
+ * or remove features unused by a given application in order to save flash space.
+ *
+ * \note If the \c USE_LUFA_CONFIG_HEADER token is defined, the library will include a header file named \c LUFAConfig.h located
+ * in the user directory where the below compile time tokens may be defined. This allows for an alternative to makefile
+ * defined tokens for configuring the library.
+ *
+ * \section Sec_TokenSummary_NonUSBTokens Non USB Related Tokens
+ * This section describes compile tokens which affect non-USB sections of the LUFA library.
+ *
+ * \li <b>DISABLE_TERMINAL_CODES</b> - (\ref Group_Terminal) - <i>All Architectures</i> \n
+ * If an application contains ANSI terminal control codes listed in TerminalCodes.h, it might be desired to remove them
+ * at compile time for use with a terminal which is non-ANSI control code aware, without modifying the source code. If
+ * this token is defined, all ANSI control codes in the application code from the TerminalCodes.h header are removed from
+ * the source code at compile time.
+ *
+ *
+ * \section Sec_TokenSummary_USBClassTokens USB Class Driver Related Tokens
+ * This section describes compile tokens which affect USB class-specific drivers in the LUFA library.
+ *
+ * \li <b>HID_HOST_BOOT_PROTOCOL_ONLY</b> - (\ref Group_USBClassHIDHost) - <i>All Architectures</i> \n
+ * By default, the USB HID Host class driver is designed to work with HID devices using either the Boot or Report HID
+ * communication protocols. On devices where the Report protocol is not used (i.e. in applications where only basic
+ * Mouse or Keyboard operation is desired, using boot compatible devices), the code responsible for the Report protocol
+ * mode can be removed to save space in the compiled application by defining this token. When defined, it is still necessary
+ * to explicitly put the attached device into Boot protocol mode via a call to \ref HID_Host_SetBootProtocol().
+ *
+ * \li <b>HID_STATETABLE_STACK_DEPTH</b>=<i>x</i> - (\ref Group_HIDParser) - <i>All Architectures</i> \n
+ * HID reports may contain PUSH and POP elements, to store and retrieve the current HID state table onto a stack. This
+ * allows for reports to save the state table before modifying it slightly for a data item, and then restore the previous
+ * state table in a compact manner. This token may be defined to a non-zero 8-bit value to give the maximum depth of the state
+ * table stack. If not defined, this defaults to the value indicated in the HID.h file documentation.
+ *
+ * \li <b>HID_USAGE_STACK_DEPTH</b>=<i>x</i> - (\ref Group_HIDParser) - <i>All Architectures</i> \n
+ * HID reports generally contain many USAGE elements, which are assigned to INPUT, OUTPUT and FEATURE items in succession
+ * when multiple items are defined at once (via REPORT COUNT elements). This allows for several items to be defined with
+ * different usages in a compact manner. This token may be defined to a non-zero 8-bit value to set the maximum depth of the
+ * usage stack, indicating the maximum number of USAGE items which can be stored temporarily until the next INPUT, OUTPUT
+ * and FEATURE item. If not defined, this defaults to the value indicated in the HID.h file documentation.
+ *
+ * \li <b>HID_MAX_COLLECTIONS</b>=<i>x</i> - (\ref Group_HIDParser) - <i>All Architectures</i> \n
+ * HID reports generally contain several COLLECTION elements, used to group related data items together. Collection information
+ * is stored separately in the processed usage structure (and referred to by the data elements in the structure) to save space.
+ * This token may be defined to a non-zero 8-bit value to set the maximum number of COLLECTION items which can be processed by the
+ * parser into the resultant processed report structure. If not defined, this defaults to the value indicated in the HID.h file
+ * documentation.
+ *
+ * \li <b>HID_MAX_REPORTITEMS</b>=<i>x</i> - (\ref Group_HIDParser) - <i>All Architectures</i> \n
+ * All HID reports contain one or more INPUT, OUTPUT and/or FEATURE items describing the data which can be sent to and from the HID
+ * device. Each item has associated usages, bit offsets in the item reports and other associated data indicating the manner in which
+ * the report data should be interpreted by the host. This token may be defined to a non-zero 8-bit value to set the maximum number of
+ * data elements which can be stored in the processed HID report structure, including INPUT, OUTPUT and (if enabled) FEATURE items.
+ * If a item has a multiple count (i.e. a REPORT COUNT of more than 1), each item in the report count is placed separately in the
+ * processed HID report table. If not defined, this defaults to the value indicated in the HID.h file documentation.
+ *
+ * \li <b>HID_MAX_REPORT_IDS</b>=<i>x</i> - (\ref Group_HIDParser) - <i>All Architectures</i> \n
+ * HID reports may contain several report IDs, to logically distinguish grouped device data from one another - for example, a combination
+ * keyboard and mouse might use report IDs to separate the keyboard reports from the mouse reports. In order to determine the size of each
+ * report, and thus know how many bytes must be read or written, the size of each report (IN, OUT and FEATURE) must be calculated and
+ * stored. This token may be defined to a non-zero 8-bit value to set the maximum number of report IDs in a device which can be processed
+ * and their sizes calculated/stored into the resultant processed report structure. If not defined, this defaults to the value indicated in
+ * the HID.h file documentation.
+ *
+ * \li <b>NO_CLASS_DRIVER_AUTOFLUSH</b> - (\ref Group_USBClassDrivers) - <i>All Architectures</i> \n
+ * Many of the device and host mode class drivers automatically flush any data waiting to be written to an interface, when the corresponding
+ * USB management task is executed. This is usually desirable to ensure that any queued data is sent as soon as possible once and new data is
+ * constructed in the main program loop. However, if flushing is to be controlled manually by the user application via the *_Flush() commands,
+ * the compile time token may be defined in the application's makefile to disable automatic flushing during calls to the class driver USB
+ * management tasks.
+ *
+ *
+ * \section Sec_TokenSummary_USBTokens General USB Driver Related Tokens
+ * This section describes compile tokens which affect USB driver stack as a whole in the LUFA library.
+ *
+ * \li <b>ORDERED_EP_CONFIG</b> - (\ref Group_EndpointManagement , \ref Group_PipeManagement) - <i>AVR8, UC3</i> \n
+ * The USB AVRs do not allow for Endpoints and Pipes to be configured out of order; they <i>must</i> be configured in an ascending order to
+ * prevent data corruption issues. However, by default LUFA employs a workaround to allow for unordered Endpoint/Pipe initialization. This compile
+ * time token may be used to restrict the initialization order to ascending indexes only in exchange for a smaller compiled binary size. Use
+ * caution when applied to applications using the library USB Class drivers; the user application must ensure that all endpoints and pipes are
+ * allocated sequentially.
+ *
+ * \li <b>USE_STATIC_OPTIONS</b>=<i>x</i> - (\ref Group_USBManagement) - <i>All Architectures</i> \n
+ * By default, the USB_Init() function accepts dynamic options at runtime to alter the library behaviour, including whether the USB pad
+ * voltage regulator is enabled, and the device speed when in device mode. By defining this token to a mask comprised of the USB options
+ * mask defines usually passed as the Options parameter to USB_Init(), the resulting compiled binary can be decreased in size by removing
+ * the dynamic options code, and replacing it with the statically set options. When defined, the USB_Init() function no longer accepts an
+ * Options parameter.
+ *
+ * \li <b>USB_DEVICE_ONLY</b> - (\ref Group_USBManagement) - <i>All Architectures</i> \n
+ * For the USB AVR models supporting both device and host USB modes, the USB_Init() function contains a Mode parameter which specifies the
+ * mode the library should be initialized to. If only device mode is required, the code for USB host mode can be removed from the binary to
+ * save space. When defined, the USB_Init() function no longer accepts a Mode parameter. This define is irrelevant on smaller USB AVRs which
+ * do not support host mode.
+ *
+ * \li <b>USB_HOST_ONLY</b> - (\ref Group_USBManagement) - <i>All Architectures</i> \n
+ * Same as USB_DEVICE_ONLY, except the library is fixed to USB host mode rather than USB device mode. Not available on some USB AVR models.
+ *
+ * \li <b>USB_STREAM_TIMEOUT_MS</b>=<i>x</i> - (\ref Group_USBManagement) - <i>All Architectures</i> \n
+ * When endpoint and/or pipe stream functions are used, by default there is a timeout between each transfer which the connected device or host
+ * must satisfy, or the stream function aborts the remaining data transfer. This token may be defined to a non-zero 16-bit value to set the timeout
+ * period for stream transfers, specified in milliseconds. If not defined, the default value specified in LowLevel.h is used instead.
+ *
+ * \li <b>NO_LIMITED_CONTROLLER_CONNECT</b> - (\ref Group_Events) - <i>AVR8 Only</i> \n
+ * On the smaller USB AVRs, the USB controller lacks VBUS events to determine the physical connection state of the USB bus to a host. In lieu of
+ * VBUS events, the library attempts to determine the connection state via the bus suspension and wake up events instead. This however may be
+ * slightly inaccurate due to the possibility of the host suspending the bus while the device is still connected. If accurate connection status is
+ * required, the VBUS line of the USB connector should be routed to an AVR pin to detect its level, so that the USB_DeviceState global
+ * can be accurately set and the \ref EVENT_USB_Device_Connect() and \ref EVENT_USB_Device_Disconnect() events manually raised by the RAISE_EVENT macro.
+ * When defined, this token disables the library's auto-detection of the connection state by the aforementioned suspension and wake up events.
+ *
+ * \li <b>NO_SOF_EVENTS</b> - (\ref Group_Events) - <i>All Architectures</i> \n
+ * By default, there exists a LUFA application event for the start of each USB frame while the USB bus is not suspended in either host or device mode.
+ * This event can be selectively enabled or disabled by calling the appropriate device or host mode function. When this compile time token is defined,
+ * the ability to receive USB Start of Frame events via the \ref EVENT_USB_Device_StartOfFrame() or \ref EVENT_USB_Host_StartOfFrame() events is removed,
+ * reducing the compiled program's binary size.
+ *
+ *
+ * \section Sec_TokenSummary_USBDeviceTokens USB Device Mode Driver Related Tokens
+ * This section describes compile tokens which affect USB driver stack of the LUFA library when used in Device mode.
+ *
+ * \li <b>USE_RAM_DESCRIPTORS</b> - (\ref Group_StdDescriptors) - <i>AVR8 Only</i> \n
+ * Define this token to indicate to the USB driver that all device descriptors are stored in RAM, rather than being located in any one
+ * of the AVR's memory spaces. RAM descriptors may be desirable in applications where the descriptors need to be modified at runtime.
+ *
+ * \li <b>USE_FLASH_DESCRIPTORS</b> - (\ref Group_StdDescriptors) - <i>AVR8 Only</i> \n
+ * Similar to USE_RAM_DESCRIPTORS, but all descriptors are stored in the AVR's FLASH memory rather than RAM.
+ *
+ * \li <b>USE_EEPROM_DESCRIPTORS</b> - (\ref Group_StdDescriptors) - <i>AVR8 Only</i> \n
+ * Similar to USE_RAM_DESCRIPTORS, but all descriptors are stored in the AVR's EEPROM memory rather than RAM.
+ *
+ * \li <b>NO_INTERNAL_SERIAL</b> - (\ref Group_StdDescriptors) - <i>All Architectures</i> \n
+ * Some AVR models contain a unique serial number which can be used as the device serial number, while in device mode. This allows
+ * the host to uniquely identify the device regardless of if it is moved between USB ports on the same computer, allowing allocated
+ * resources (such as drivers, COM Port number allocations) to be preserved. This is not needed in many apps, and so the code that
+ * performs this task can be disabled by defining this option and passing it to the compiler via the -D switch.
+ *
+ * \li <b>FIXED_CONTROL_ENDPOINT_SIZE</b>=<i>x</i> - (\ref Group_EndpointManagement) - <i>All Architectures</i> \n
+ * By default, the library determines the size of the control endpoint (when in device mode) by reading the device descriptor.
+ * Normally this reduces the amount of configuration required for the library, allows the value to change dynamically (if
+ * descriptors are stored in EEPROM or RAM rather than flash memory) and reduces code maintenance. However, this token can be
+ * defined to a non-zero value instead to give the size in bytes of the control endpoint, to reduce the size of the compiled
+ * binary.
+ *
+ * \li <b>DEVICE_STATE_AS_GPIOR</b> - (\ref Group_Device) - <i>AVR8 Only</i> \n
+ * One of the most frequently used global variables in the stack is the USB_DeviceState global, which indicates the current state of
+ * the Device State Machine. To reduce the amount of code and time required to access and modify this global in an application, this token
+ * may be defined to a value between 0 and 2 to fix the state variable into one of the three general purpose IO registers inside the AVR
+ * reserved for application use. When defined, the corresponding GPIOR register should not be used within the user application except
+ * implicitly via the library APIs.
+ *
+ * \li <b>FIXED_NUM_CONFIGURATIONS</b>=<i>x</i> - (\ref Group_Device) - <i>All Architectures</i> \n
+ * By default, the library determines the number of configurations a USB device supports by reading the device descriptor. This reduces
+ * the amount of configuration required to set up the library, and allows the value to change dynamically (if descriptors are stored in
+ * EEPROM or RAM rather than flash memory) and reduces code maintenance. However, this value may be fixed via this token in the project
+ * makefile to reduce the compiled size of the binary at the expense of flexibility.
+ *
+ * \li <b>CONTROL_ONLY_DEVICE</b> - (\ref Group_Device) - <i>All Architectures</i> \n
+ * In some limited USB device applications, there are no device endpoints other than the control endpoint; i.e. all device communication
+ * is through control endpoint requests. Defining this token will remove several features related to the selection and control of device
+ * endpoints internally, saving space. Generally, this is usually only useful in (some) bootloaders and is best avoided.
+ *
+ * \li <b>MAX_ENDPOINT_INDEX</b> - (\ref Group_Device) - <i>XMEGA Only</i> \n
+ * Defining this value to the highest index (not address - this excludes the direction flag) endpoint within the device will restrict the
+ * number of FIFOs created internally for the endpoint buffers, reducing the total RAM usage.
+ *
+ * \li <b>INTERRUPT_CONTROL_ENDPOINT</b> - (\ref Group_USBManagement) - <i>All Architectures</i> \n
+ * Some applications prefer to not call the USB_USBTask() management task regularly while in device mode, as it can complicate code significantly.
+ * Instead, when device mode is used this token can be passed to the library via the -D switch to allow the library to manage the USB control
+ * endpoint entirely via USB controller interrupts asynchronously to the user application. When defined, USB_USBTask() does not need to be called
+ * when in USB device mode.
+ *
+ * \li <b>NO_DEVICE_REMOTE_WAKEUP</b> - (\ref Group_Device) - <i>All Architectures</i> \n
+ * Many devices do not require the use of the Remote Wakeup features of USB, used to wake up the USB host when suspended. On these devices,
+ * the code required to manage device Remote Wakeup can be disabled by defining this token and passing it to the library via the -D switch.
+ *
+ * \li <b>NO_DEVICE_SELF_POWER</b> - (\ref Group_Device) - <i>All Architectures</i> \n
+ * USB devices may be bus powered, self powered, or a combination of both. When a device can be both bus powered and self powered, the host may
+ * query the device to determine the current power source, via \ref USB_Device_CurrentlySelfPowered. For solely bus powered devices, this global
+ * and the code required to manage it may be disabled by passing this token to the library via the -D switch.
+ *
+ *
+ * \section Sec_TokenSummary_USBHostTokens USB Host Mode Driver Related Tokens
+ *
+ * This section describes compile tokens which affect USB driver stack of the LUFA library when used in Host mode.
+ *
+ * \li <b>HOST_STATE_AS_GPIOR</b> - (\ref Group_Host) - <i>AVR8 Only</i> \n
+ * One of the most frequently used global variables in the stack is the USB_HostState global, which indicates the current state of
+ * the Host State Machine. To reduce the amount of code and time required to access and modify this global in an application, this token
+ * may be defined to a value between 0 and 2 to fix the state variable into one of the three general purpose IO registers inside the AVR
+ * reserved for application use. When defined, the corresponding GPIOR register should not be used within the user application except
+ * implicitly via the library APIs.
+ *
+ * \li <b>USB_HOST_TIMEOUT_MS</b>=<i>x</i> - (\ref Group_Host) - <i>All Architectures</i> \n
+ * When a control transfer is initiated in host mode to an attached device, a timeout is used to abort the transfer if the attached
+ * device fails to respond within the timeout period. This token may be defined to a non-zero 16-bit value to set the timeout period for
+ * control transfers, specified in milliseconds. If not defined, the default value specified in Host.h is used instead.
+ *
+ * \li <b>HOST_DEVICE_SETTLE_DELAY_MS</b>=<i>x</i> - (\ref Group_Host) - <i>All Architectures</i> \n
+ * Some devices require a delay of up to 5 seconds after they are connected to VBUS before the enumeration process can be started, or
+ * they will fail to enumerate correctly. By placing a delay before the enumeration process, it can be ensured that the bus has settled
+ * back to a known idle state before communications occur with the device. This token may be defined to a 16-bit value to set the device
+ * settle period, specified in milliseconds. If not defined, the default value specified in Host.h is used instead.
+ *
+ * \li <b>INVERTED_VBUS_ENABLE_LINE</b> - (\ref Group_Host) - <i>All Architectures</i> \n
+ * If enabled, this will indicate that the USB target VBUS line polarity is inverted; i.e. it should be pulled low to enable VBUS to the
+ * target, and pulled high to stop the target VBUS generation.
+ * \n
+ * \attention On AVR8 architecture devices, this compile time option requires \c NO_AUTO_VBUS_MANAGEMENT to be set.
+ *
+ * \li <b>NO_AUTO_VBUS_MANAGEMENT</b> - (\ref Group_Host) - <i>All Architectures</i> \n
+ * Disables the automatic management of VBUS to the target, i.e. automatic shut down in the even of an overcurrent situation. When enabled, VBUS
+ * is enabled while the USB controller is initialized in USB Host mode.
+ */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/CompilingApps.txt b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/CompilingApps.txt
new file mode 100644
index 000000000..08f81d2ba
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/CompilingApps.txt
@@ -0,0 +1,46 @@
+/** \file
+ *
+ * This file contains special DoxyGen information for the generation of the main page and other special
+ * documentation pages. It is not a project source file.
+ */
+
+/** \page Page_CompilingApps Compiling the Demos, Bootloaders and Projects
+ *
+ * The following details how to compile the included LUFA demos, applications and bootloaders using AVR-GCC.
+ *
+ * \section Sec_CompilingApps_Prerequisites Prerequisites
+ * Before you can compile any of the LUFA library code or demos, you will need a recent distribution of avr-libc (1.6.2+)
+ * and the AVR-GCC (4.2+) compiler. A standard "coreutils" package for your system is also required for command line
+ * compilation of LUFA based applications.
+ *
+ * \subsection SSec_CompilingApps_PreqWindows Windows Prerequisites
+ * On Windows, you will need a copy of the latest Atmel Toolchain (<a>http://www.atmel.com/tools/ATMELAVRTOOLCHAINFORWINDOWS.aspx</a>),
+ * either downloaded and installed as a standalone package, or installed as part of Atmel Studio. You will need to ensure
+ * that the "bin" directory of the toolchain is available in your system's <b>PATH</b> environment variable.
+ *
+ * In addition, you will need to install a ported version of the ZSH or BASH *nix shells, and a standard set of *nix
+ * utilities such as <i>cut</i>, <i>find</i> and <i>sed</i>. These can be found in the "basic" system package of the
+ * of the MinGW installer (<a>http://www.mingw.org</a>). Once installed, add the "msys\1.0\bin" of the MinGW installation
+ * folder is added to your system's <b>PATH</b> environment variable.
+ *
+ * \subsection SSec_CompilingApps_PreqLinux Linux Prerequisites
+ * On Linux systems you will need to install the latest Linux distribution of the standalone Atmel Toolchain from the
+ * Atmel website (<a>http://www.atmel.com/tools/ATMELAVRTOOLCHAINFORLINUX.aspx</a>), or use the latest avr-libc and avr-gcc packages
+ * for your chosen distribution's package manager. For full device support, the Atmel standalone Toolchain package is recommended.
+ *
+ * \section Sec_CompilingApps_Compiling Compiling a LUFA Application
+ * Compiling the LUFA demos, applications and/or bootloaders is very simple. LUFA comes with makefile scripts for
+ * each individual demo, bootloader and project folder, as well as scripts in the Demos/, Bootloaders/, Projects/
+ * and the LUFA root directory. Compilation of projects can be started from any of the above directories, with a build
+ * started from an upper directory in the directory structure executing build of all child directories under it. This
+ * means that while a build inside a particular demo directory will build only that particular demo, a build started from
+ * the /Demos/ directory will build all LUFA demo projects sequentially.
+ *
+ * To build a project from the source via the command line, the command <b>"make all"</b> should be executed from the command
+ * line in the directory of interest. To remove compiled files (including the binary output, all intermediately files and all
+ * diagnostic output files), execute <b>"make clean"</b>. Once a "make all" has been run and no errors were encountered, the
+ * resulting binary will be located in the generated ".HEX" file. If your project makes use of pre-initialized EEPROM
+ * variables, the generated ".EEP" file will contain the project's EEPROM data.
+ *
+ * \see \ref Page_BuildSystem for information on the LUFA build system.
+ */
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/ConfiguringApps.txt b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/ConfiguringApps.txt
new file mode 100644
index 000000000..15b660e92
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/ConfiguringApps.txt
@@ -0,0 +1,157 @@
+/** \file
+ *
+ * This file contains special DoxyGen information for the generation of the main page and other special
+ * documentation pages. It is not a project source file.
+ */
+
+/** \page Page_ConfiguringApps Configuring the Demos, Bootloaders and Projects
+ *
+ * If the target microcontroller model, architecture, clock speed, board or other settings are different from the current
+ * settings, they must be changed and the project recompiled from the source code before being programmed into the microcontroller.
+ * Most project configuration options are located in the <tt>makefile</tt> build script inside each LUFA application's folder,
+ * however some demo or application-specific configuration settings are located in one or more of the source files of the project.
+ * See each project's individual documentation for application-specific configuration values.
+ *
+ * Each project "makefile" contains all the script and configuration data required to compile each project. When opened with
+ * any regular basic text editor such as Notepad or WordPad (ensure that the save format is a pure ASCII text format) the
+ * build configuration settings may be altered.
+ *
+ * \see \ref Page_BuildSystem for information on the LUFA build system.
+ *
+ * \section Sec_ConfiguringApps_AppMakefileParams The Default Application Makefile Template
+ *
+ * Below is a copy of the default LUFA application makefile, which can be used as a template for each application.
+ *
+ * \verbinclude makefile_template
+ *
+ * Inside each makefile, a number of configuration variables are listed with the syntax "<VARIABLE NAME> = <VALUE>". For
+ * each application, the important standard variables which should be altered are:
+ *
+ * - <b>MCU</b>, the target processor model
+ * - <b>ARCH</b>, the target microcontroller architecture
+ * - <b>BOARD</b>, the target board hardware
+ * - <b>F_CPU</b>, the target CPU master clock frequency, after any prescaling
+ * - <b>F_USB</b>, the target raw input clock to the USB module of the processor
+ * - <b>OPTIMIZATION</b>, the level of optimization to compile with
+ * - <b>TARGET</b>, the name of the target output binary and other files
+ * - <b>SRC</b>, the list of source files to compile/assemble/link
+ * - <b>LUFA_PATH</b>, the path to the LUFA library core source code
+ * - <b>CC_FLAGS</b>, the common command line flags to pass to the C/C++ compiler, assembler and linker
+ * - <b>LD_FLAGS</b>, the command line flags to pass to the linker
+ *
+ * These values should be changed to reflect the build hardware.
+ *
+ * \subsection SSec_ConfiguringApps_MCU The MCU Parameter
+ * This parameter indicates the target microcontroller model for the compiled application. This should be set to the model of the target
+ * microcontroller (such as the AT90USB1287, or the ATMEGA32U4), in all lower-case (e.g. "at90usb1287"). Note that not all demos support all the
+ * microcontroller models and architectures, as they may make use of peripherals or modes only present in some devices.
+ *
+ * For supported processor models, see \ref Page_DeviceSupport.
+ *
+ * \subsection SSec_ConfiguringApps_ARCH The ARCH Parameter
+ * This parameter indicates the target microcontroller architecture the library is to be compiled for. Different microcontroller
+ * architectures require different source files to be compiled into the final binary, and so this option must be set to the correct
+ * architecture for the selected platform.
+ *
+ * For supported processor architectures, see \ref Page_DeviceSupport.
+ *
+ * \subsection SSec_ConfiguringApps_BOARD The BOARD Parameter
+ * This parameter indicates the target board hardware for the compiled application. Some LUFA library drivers are board-specific,
+ * such as the LED driver, and the library needs to know the layout of the target board. If you are using one of the board models listed
+ * on the main library page, change this parameter to the board name in all UPPER-case.
+ *
+ * If you are not using any board-specific drivers in the LUFA library, or you are using a custom board layout, change this to read
+ * "USER" (no quotes) instead of a standard board name. If the USER board type is selected and the application makes use of one or more
+ * board-specific hardware drivers inside the LUFA library, then the appropriate stub drives files should be copied from the \c /CodeTemplates/DriverStubs/
+ * directory into a /Board/ folder inside the application directory, and the stub driver completed with the appropriate code to drive the
+ * custom board's hardware.
+ *
+ * For boards with built in hardware driver support within the LUFA library, see \ref Page_DeviceSupport.
+ *
+ * \subsection SSec_ConfiguringApps_F_CPU The F_CPU Parameter
+ * This parameter indicates the target microcontroller's main CPU clock frequency, in Hz. This is used by many libraries (and applications) for
+ * timing related purposes, and should reflect the actual CPU speed after any prescaling or adjustments are performed.
+ *
+ * \subsection SSec_ConfiguringApps_F_USB The F_USB Parameter
+ * This parameter indicates the raw input clock frequency to the USB module within the microcontroller in Hz. This may be very different on some platforms
+ * to the main CPU clock or other peripheral/bus clocks.
+ *
+ * \note On AVR8 platforms, this must be equal to \c 8000000 or \c 16000000.
+ *
+ * \note On XMEGA platforms, this must be equal to a multiple of 6000000 from \c 6000000 to \c 48000000.
+ *
+ * \note On UC3 platforms, this must be equal to a multiple of 12000000 from \c 12000000 to \c 48000000.
+ *
+ * \subsection SSec_ConfiguringApps_OPTIMIZATION The OPTIMIZATION Parameter
+ * This parameter indicates the level of optimization to use when compiling the application. This will allow you to compile with an optimization level
+ * supported by GCC, from <tt>0</tt> (no optimization) to <tt>3</tt> (fastest runtime optimization) or <tt>s</tt> (smallest size).
+ *
+ * \subsection SSec_ConfiguringApps_TARGET The TARGET Parameter
+ * This parameter indicates the application target name, which is used as the base filename for the build binary and debugging files. This will be the
+ * name of the output files once linked together into the final application, ready to load into the target.
+ *
+ * \subsection SSec_ConfiguringApps_SRC The SRC Parameter
+ * This parameter indicates the source files used to compile the application, as a list of C (<tt>*.c</tt>), C++ (<tt>*.cpp</tt>) and Assembly (<tt>*.S</tt>) files. Note that
+ * all assembly files must end in a <b>capital</b> .S extension, as lowercase .s files are reserved for GCC intermediate files.
+ *
+ * \subsection SSec_ConfiguringApps_LUFA_PATH The LUFA_PATH Parameter
+ * As each LUFA program requires the LUFA library source code to compile correctly, the application must know where the LUFA library is located. This
+ * value specifies the path to the LUFA library core. This path may be relative or absolute, however note than even under Windows based systems the
+ * forward-slash (/) path separator must be used.
+ *
+ * \subsection SSec_ConfiguringApps_CC_FLAGS The CC_FLAGS Parameter
+ * This parameter lists the compiler flags passed to the C/C++ compiler, the assembler and the linker. These are used as-is directly to GCC and thus
+ * must match GCC's command line options as given in the GCC manual. This variable may be used to define tokens directly on the command line, enable or
+ * disable warnings, adjust the target-specific tuning parameters or other options.
+ *
+ * \subsection SSec_ConfiguringApps_LD_FLAGS The LD_FLAGS Parameter
+ * This parameter lists the linker flags passed exclusively to the linker. These are used as-is directly to GCC and thus must match GCC's command line
+ * linker options as given in the GCC manual. This variable may be used to create or relocate custom data sections, or enable linker specific behaviors.
+ *
+ *
+ * \section Sec_ExampleAppConfig Example Application Makefile Configurations
+ * Below is an example makefile for an AVR8 based AT90USB1287 running at 8MHz, to compile a program called "MyApplication":
+ * \verbatim
+ MCU = at90usb1287
+ ARCH = AVR8
+ BOARD = NONE
+ F_CPU = 8000000
+ F_USB = $(F_CPU)
+ OPTIMIZATION = s
+ TARGET = MyApplication
+ SRC = MyApplication.c Descriptors.c $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS)
+ LUFA_PATH = ../../../../LUFA
+ CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -IConfig/
+ LD_FLAGS =
+ \endverbatim
+ *
+ * Below is an example makefile for an XMEGA based ATXMEGA128A1U running at 32MHz, to compile a program called "MyApplication":
+ * \verbatim
+ MCU = atxmega128a1u
+ ARCH = XMEGA
+ BOARD = NONE
+ F_CPU = 32000000
+ F_USB = 48000000
+ OPTIMIZATION = s
+ TARGET = MyApplication
+ SRC = MyApplication.c Descriptors.c $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS)
+ LUFA_PATH = ../../../../LUFA
+ CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -IConfig/
+ LD_FLAGS =
+ \endverbatim
+ *
+ * Below is an example makefile for a UC3 based AT32UC3A0512 running at 50MHz, to compile a program called "MyApplication":
+ * \verbatim
+ MCU = uc3a0512
+ ARCH = UC3
+ BOARD = NONE
+ F_CPU = 50000000
+ F_USB = 48000000
+ OPTIMIZATION = s
+ TARGET = MyApplication
+ SRC = MyApplication.c Descriptors.c $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS)
+ LUFA_PATH = ../../../../LUFA
+ CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -IConfig/
+ LD_FLAGS =
+ \endverbatim
+ */
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/DevelopingWithLUFA.txt b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/DevelopingWithLUFA.txt
new file mode 100644
index 000000000..9a02f95b9
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/DevelopingWithLUFA.txt
@@ -0,0 +1,24 @@
+/** \file
+ *
+ * This file contains special DoxyGen information for the generation of the main page and other special
+ * documentation pages. It is not a project source file.
+ */
+
+/**
+ * \page Page_DevelopingWithLUFA Developing With LUFA
+ *
+ * This section of the manual contains information on LUFA development, such as Getting Started information,
+ * information on compile-time tuning of the library and other developer-related sections.
+ *
+ * <b>Subsections:</b>
+ * \li \subpage Page_BuildSystem - The LUFA Buildsystem
+ * \li \subpage Page_TokenSummary - Summary of Compile Time Tokens
+ * \li \subpage Page_Migration - Migrating from an Older LUFA Version
+ * \li \subpage Page_VIDPID - Allocated USB VID and PID Values
+ * \li \subpage Page_OSDrivers - Operating System Driver Information
+ * \li \subpage Page_BuildLibrary - Building as a Linkable Library
+ * \li \subpage Page_ExportingLibrary - Exporting LUFA for IDE Use
+ * \li \subpage Page_WritingBoardDrivers - How to Write Custom Board Drivers
+ * \li \subpage Page_SoftwareBootloaderStart - How to jump to the bootloader in software
+ */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/DeviceSupport.txt b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/DeviceSupport.txt
new file mode 100644
index 000000000..2a4b9c335
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/DeviceSupport.txt
@@ -0,0 +1,422 @@
+/** \file
+ *
+ * This file contains special DoxyGen information for the generation of the main page and other special
+ * documentation pages. It is not a project source file.
+ */
+
+/**
+ * \page Page_DeviceSupport Device and Hardware Support
+ *
+ * <b>Atmel Microcontrollers:</b>
+ * \li \subpage Page_AVR8Support - Atmel AVR8 Support
+ * \li \subpage Page_UC3Support - Atmel AVR32 UC3 Support
+ * \li \subpage Page_XMEGASupport - Atmel XMEGA Support
+ */
+
+/**
+ * \page Page_AVR8Support Atmel 8-Bit AVR (AVR8) Support
+ *
+ * \section Sec_AVR8Support_Devices Supported Microcontroller Models
+ *
+ * Currently supported AVR8 models:
+ *
+ * <table>
+ * <tr>
+ * <th width="150px">Part</th>
+ * <th width="150px">USB Device Mode</th>
+ * <th width="150px">USB Host Mode</th>
+ * </tr>
+ * <tr>
+ * <td>AT90USB82</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#EE0000">No</td>
+ * </tr>
+ * <tr>
+ * <td>ATMEGA8U2</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#EE0000">No</td>
+ * </tr>
+ * <tr>
+ * <td>AT90USB162</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#EE0000">No</td>
+ * </tr>
+ * <tr>
+ * <td>ATMEGA16U2</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#EE0000">No</td>
+ * </tr>
+ * <tr>
+ * <td>ATMEGA16U4</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#EE0000">No</td>
+ * </tr>
+ * <tr>
+ * <td>ATMEGA32U2</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#EE0000">No</td>
+ * </tr>
+ * <tr>
+ * <td>ATMEGA32U4</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#EE0000">No</td>
+ * </tr>
+ * <tr>
+ * <td>AT90USB646</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#EE0000">No</td>
+ * </tr>
+ * <tr>
+ * <td>AT90USB647</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>AT90USB1286</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#EE0000">No</td>
+ * </tr>
+ * <tr>
+ * <td>AT90USB1287</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * </table>
+ *
+ * \section Sec_AVR8Support_Boards Supported Atmel Boards
+ * Currently supported Atmel AVR8 boards (see \ref Group_BoardTypes):
+ * - AT90USBKEY
+ * - ATAVRUSBRF01
+ * - EVK527
+ * - RZUSBSTICK
+ * - STK525
+ * - STK526
+ * - XPLAIN (Original green board, <i>not</i> the newer blue XPLAINED family boards)
+ *
+ * \section Sec_AVR8Support_ThirdParty Supported Third Party Boards
+ * Currently supported third-party boards (see \ref Group_BoardTypes for makefile \c BOARD constant names):
+ * - Adafruit U4 Breakout Board
+ * - Arduino Leonardo
+ * - Arduino Micro
+ * - Arduino Uno
+ * - Arduino Yun
+ * - Bitwizard Multio and Big-Multio
+ * - Busware BUI
+ * - Busware CUL V3
+ * - Busware TUL
+ * - DorkbotPDX Duce
+ * - Fletchtronics Bumble-B (using manufacturer recommended peripheral layout)
+ * - Kernel Concepts USBFOO
+ * - Linnix UDIP
+ * - MattairTech JM-DB-U2
+ * - Maximus USB
+ * - Micropendous Boards (Micropendous-32U2, Micropendous-1, Micropendous-2)
+ * - Microsin AVR-USB162
+ * - Minimus USB
+ * - Olimex AVR-USB-162, AVR-USB-32U4 and AVR-USB-T32U4 Boards
+ * - Olimex AVR-ISP-MK2
+ * - Paranoid Studio's US2AX (V1, V2 and V3 hardware revisions)
+ * - PJRC Teensy (1.x and 2.x versions)
+ * - Rikus' U2S
+ * - Sparkfun U2 Breakout Board
+ * - Stange ISP Programmer Board
+ * - TCNISO Blackcat USB JTAG
+ * - Tempusdictum Benito
+ * - Tom's USBTINY-MKII (all revisions and versions)
+ * - Custom User Boards (with Board Drivers if desired, see \ref Page_WritingBoardDrivers)
+ */
+
+/**
+ * \page Page_UC3Support Atmel 32-Bit UC3 AVR (UC3)
+ *
+ * \warning The AVR32 UC3 device support is currently <b>experimental</b>, and is included for preview purposes only.
+ *
+ * \section Sec_UC3Support_Devices Supported Microcontroller Models
+ *
+ * Currently supported UC3 models:
+ *
+ * <table>
+ * <tr>
+ * <th width="150px">Part</th>
+ * <th width="150px">USB Device Mode</th>
+ * <th width="150px">USB Host Mode</th>
+ * </tr>
+ * <tr>
+ * <td>AT32UC3A364</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>AT32UC3A364S</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>AT32UC3A464</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>AT32UC3A464S</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>AT32UC3B064</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>AT32UC3B164</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>AT32UC3A0128</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>AT32UC3A1128</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>AT32UC3A3128</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>AT32UC3A3128S</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>AT32UC3A4128</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>AT32UC3A4128S</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>AT32UC3B0128</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>AT32UC3B1128</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>AT32UC3A0256</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>AT32UC3A1256</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>AT32UC3A3256</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>AT32UC3A3256S</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>AT32UC3A4256</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>AT32UC3A4256S</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>AT32UC3B0256</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>AT32UC3B1256</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>AT32UC3A0512</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>AT32UC3A1512</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>AT32UC3B0512</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>AT32UC3B1512</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * </table>
+ *
+ * \section Sec_UC3Support_Boards Supported Atmel Boards
+ *
+ * Currently supported Atmel UC3 boards (see \ref Group_BoardTypes):
+ * - EVK1100
+ * - EVK1101
+ * - EVK1104
+ * - UC3-A3 Xplained
+ *
+ * \section Sec_UC3Support_ThirdParty Supported Third Party Boards
+ *
+ * Currently supported third-party boards (see \ref Group_BoardTypes for makefile \c BOARD constant names):
+ * - Custom User Boards (with Board Drivers if desired, see \ref Page_WritingBoardDrivers)
+ */
+
+/**
+ * \page Page_XMEGASupport Atmel USB XMEGA AVR (XMEGA)
+ *
+ * \warning The XMEGA device support is currently <b>experimental</b> (incomplete and/or non-functional), and is included for preview purposes only.
+ *
+ * \section Sec_XMEGASupport_Devices Supported Microcontroller Models
+ *
+ * Currently supported XMEGA models:
+ *
+ * <table>
+ * <tr>
+ * <th width="150px">Part</th>
+ * <th width="150px">USB Device Mode</th>
+ * <th width="150px">USB Host Mode</th>
+ * </tr>
+ * <tr>
+ * <td>ATXMEGA16A4U</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#EE0000">No</td>
+ * </tr>
+ * <tr>
+ * <td>ATXMEGA32A4U</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#EE0000">No</td>
+ * </tr>
+ * <tr>
+ * <td>ATXMEGA64A4U</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#EE0000">No</td>
+ * </tr>
+ * <tr>
+ * <td>ATXMEGA128A4U</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#EE0000">No</td>
+ * </tr>
+ * <tr>
+ * <td>ATXMEGA64A3U</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#EE0000">No</td>
+ * </tr>
+ * <tr>
+ * <td>ATXMEGA128A3U</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#EE0000">No</td>
+ * </tr>
+ * <tr>
+ * <td>ATXMEGA192A3U</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#EE0000">No</td>
+ * </tr>
+ * <tr>
+ * <td>ATXMEGA256A3U</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#EE0000">No</td>
+ * </tr>
+ * <tr>
+ * <td>ATXMEGA256A3BU</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#EE0000">No</td>
+ * </tr>
+ * <tr>
+ * <td>ATXMEGA128A1U</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#EE0000">No</td>
+ * </tr>
+ * <tr>
+ * <td>ATXMEGA64B3</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#EE0000">No</td>
+ * </tr>
+ * <tr>
+ * <td>ATXMEGA128B3</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#EE0000">No</td>
+ * </tr>
+ * <tr>
+ * <td>ATXMEGA64B1</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#EE0000">No</td>
+ * </tr>
+ * <tr>
+ * <td>ATXMEGA128B1</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#EE0000">No</td>
+ * </tr>
+ * <tr>
+ * <td>ATXMEGA64C3</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#EE0000">No</td>
+ * </tr>
+ * <tr>
+ * <td>ATXMEGA128C3</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#EE0000">No</td>
+ * </tr>
+ * <tr>
+ * <td>ATXMEGA192C3</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#EE0000">No</td>
+ * </tr>
+ * <tr>
+ * <td>ATXMEGA256C3</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#EE0000">No</td>
+ * </tr>
+ * <tr>
+ * <td>ATXMEGA384C3</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#EE0000">No</td>
+ * </tr>
+ * <tr>
+ * <td>ATXMEGA16C4</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#EE0000">No</td>
+ * </tr>
+ * <tr>
+ * <td>ATXMEGA32C4</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#EE0000">No</td>
+ * </tr>
+ * </table>
+ *
+ * \section Sec_XMEGASupport_Boards Supported Atmel Boards
+ * Currently supported Atmel XMEGA boards (see \ref Group_BoardTypes):
+ * - XMEGA A3BU Xplained
+ * - XMEGA B1 Xplained
+ * - XMEGA C3 Xplained
+ *
+ * \section Sec_XMEGASupport_ThirdParty Supported Third Party Boards
+ * Currently supported third-party boards (see \ref Group_BoardTypes for makefile \c BOARD constant names):
+ * - Custom User Boards (with Board Drivers if desired, see \ref Page_WritingBoardDrivers)
+ */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/DirectorySummaries.txt b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/DirectorySummaries.txt
new file mode 100644
index 000000000..87b863c28
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/DirectorySummaries.txt
@@ -0,0 +1,80 @@
+/** \file
+ *
+ * This file contains special DoxyGen information for the generation of the main page and other special
+ * documentation pages. It is not a project source file.
+ */
+
+/** \dir Platform
+ * \brief Platform specific drivers.
+ *
+ * This folder contains platform specific drivers and defines for various supported architectures. These may or may
+ * not be used in a LUFA application, and are provided for convenience purposes.
+ *
+ * \dir Drivers
+ * \brief Library hardware and software drivers.
+ *
+ * This folder contains all the library hardware and software drivers for each supported board, architecture and
+ * microcontroller model.
+ *
+ * \dir Drivers/Misc
+ * \brief Miscellaneous driver files.
+ *
+ * This folder contains drivers for aspects other than the USB interface, board hardware or microcontroller peripherals.
+ *
+ * \dir Drivers/Peripheral
+ * \brief Microcontroller peripheral driver files.
+ *
+ * This folder contains drivers for various low level microcontroller peripherals, usually located on the microcontroller
+ * die within the same physical chip.
+ *
+ * \dir Drivers/USB
+ * \brief USB controller peripheral driver files.
+ *
+ * This folder contains the complete LUFA USB stack and controller files, including the core driver and stack, as well
+ * as the USB class driver implementations.
+ *
+ * \dir Drivers/USB/Core
+ * \brief Core USB driver files.
+ *
+ * This folder contains the core USB stack and controller driver files, to correctly implement USB functionality on the
+ * target architecture and microcontroller model. This
+ *
+ * \dir Drivers/USB/Class
+ * \brief USB Class helper driver files.
+ *
+ * This folder contains drivers for implementing functionality of standardized USB classes. These are not used directly by the library,
+ * but provide a standard and library-maintained way of implementing functionality from some of the defined USB classes without extensive
+ * development effort. Is is recommended that these drivers be used where possible to reduce maintenance of user applications.
+ *
+ * \dir Drivers/USB/Class/Device
+ * \brief USB Device Class helper driver files.
+ *
+ * Device mode drivers for the standard USB classes.
+ *
+ * \dir Drivers/USB/Class/Host
+ * \brief USB Host Class helper driver files.
+ *
+ * Host mode drivers for the standard USB classes.
+ *
+ * \dir Drivers/Board
+ * \brief Board hardware driver files.
+ *
+ * This folder contains drivers for interfacing with the physical hardware on supported commercial boards, primarily from
+ * the Atmel corporation. Header files in this folder should be included in user applications requiring the functionality of
+ * hardware placed on supported boards.
+ *
+ * \dir CodeTemplates
+ * \brief Code templates for use in LUFA powered applications.
+ *
+ * This contains code templates for board drivers, sample LUFA project makefiles and other similar templates that can be copied into
+ * a LUFA powered application and modified to speed up development.
+ *
+ * \dir CodeTemplates/DriverStubs
+ * \brief Driver stub header files for custom boards, to allow the LUFA board drivers to operate.
+ *
+ * This contains stub files for the LUFA board drivers. If the LUFA board drivers are used with board hardware other than those
+ * directly supported by the library, the BOARD parameter of the application's makefile can be set to "USER", and these stub files
+ * copied to the "/Board/" directory of the application's folder. When fleshed out with working driver code for the custom board,
+ * the corresponding LUFA board APIs will work correctly with the non-standard board hardware.
+ */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Donating.txt b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Donating.txt
new file mode 100644
index 000000000..4a4b6aa72
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Donating.txt
@@ -0,0 +1,26 @@
+/** \file
+ *
+ * This file contains special DoxyGen information for the generation of the main page and other special
+ * documentation pages. It is not a project source file.
+ */
+
+/**
+ * \page Page_Donating Donating to Support This Project
+ *
+ * \image html Images/Author.jpg "Dean Camera, LUFA Developer"
+ *
+ * I am a 24 year old Atmel Applications Engineer, living in Trondheim, Norway and working on LUFA in my spare time.
+ * The development and support of this library requires much effort from myself, as I am the sole developer, maintainer
+ * and supporter. Please consider donating a small amount to support this and my future Open Source projects - All
+ * donations are <i>greatly</i> appreciated.
+ *
+ * Note that commercial entities can remove the attribution portion of the LUFA license by a one-time fee - see
+ * \ref Page_LicenseInfo for more details (<b>Note: Please do NOT pay this in advance through the donation link below -
+ * contact author for payment details.</b>).
+ *
+ * \htmlonly
+ * \image html "http://www.pledgie.com/campaigns/6927.png"
+ * \endhtmlonly
+ * <a href="http://www.lufa-lib.org/donate">Donate to this project via PayPal</a> - Thanks in Advance!
+ */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/ExportingLibrary.txt b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/ExportingLibrary.txt
new file mode 100644
index 000000000..095184862
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/ExportingLibrary.txt
@@ -0,0 +1,112 @@
+/** \file
+ *
+ * This file contains special DoxyGen information for the generation of the main page and other special
+ * documentation pages. It is not a project source file.
+ */
+
+/** \page Page_ExportingLibrary Exporting the Library for IDE Use
+ *
+ * While LUFA was designed to allow for easy compilation in a makefile driven environment,
+ * it is possible to export the library into a form suitable for drop-in use inside of an
+ * IDE.
+ *
+ * \note <b>LUFA is also available as a native Atmel Studio 6.1 extension</b>, which integrates LUFA into
+ * Atmel Studio including all demos and projects. If you are running Atmel Studio 6.1 or later, the
+ * below instructions are not required; download and install the native LUFA extension from the
+ * <a href="http://gallery.atmel.com">Atmel Gallery</a> instead.
+ *
+ * \section Sec_LibraryExport Exporting the Library
+ * An export of the library is at its most basic, a direct copy of the main "LUFA" source folder from the
+ * root download folder; this contains the library core which can be re-used within external projects.
+ * However, as many IDEs attempt to automatically compile all included source files, it is necessary to
+ * exclude some directories and files from the library core export to allow for easier integration into
+ * an IDE project.
+ *
+ * \subsection SSec_ManualExport Manual Export
+ * To manually export the library core, copy over the main LUFA library folder from the LUFA root directory,
+ * renaming as desired. Within the library core folder, the following directories should be removed or
+ * excluded from your IDE import:
+ * - Documentation/
+ * - DoxygenPages/
+ * - CodeTemplates/
+ * - StudioIntegration/
+ *
+ * If required, files from the CodeTemplates/ subdirectory may be copied to your IDE project as needed.
+ *
+ * The resulting copy of the library may then be imported into your chosen IDE according to the instructions
+ * shown in \ref Sec_LibraryImport.
+ *
+ * \subsection SSec_AutomaticExport Automatic Export
+ * If desired, the steps indicated in \ref SSec_ManualExport may be automatically performed, by running the
+ * command <b><code>make export_tar</code></b> from the command line. This will generate two .tar files in the
+ * current directory, named <code>LUFA_YYMMDD.tar</code> and <code>LUFA_YYMMDD_Code_Templates.tar</code> (where
+ * "YYMMDD" is the version of the library being exported). The first archive contains the exported LUFA core
+ * with the non-required files removed, while the second contains an archived copy of the code template files
+ * for the current LUFA version.
+ *
+ * The resulting archived copy of the library may then be extracted to your chosen IDE project source directory
+ * and imported according to the instructions shown in \ref Sec_LibraryImport.
+ *
+ * \section Sec_LibraryImport Importing the Library
+ * An exported copy of the library may be imported wholesale into an IDE project, if the instructions detailed
+ * in \ref Sec_LibraryExport are followed.
+ *
+ * Specific instructions for importing an exported version of LUFA into various IDEs are listed below.
+ *
+ * \subsection SSec_AS56_Import Importing into AVRStudio 5.x/Atmel Studio 6.0
+ * To import LUFA into a new or existing project, the following steps must be followed.
+ *
+ * \subsubsection SSSec_AS56_Import_Step1 Copy over the exported library
+ * Copy over the exported library archive created via the steps listed in \ref Sec_LibraryExport to your AS5/AS6
+ * project directory.
+ *
+ * \image html Images/AS5_AS6_Import/AS5_AS6_Import_Step1.png
+ *
+ * \subsubsection SSSec_AS56_Import_Step2 Extract exported library
+ * Extract out the contents of the archive to a new folder. This may be any name you wish, however keep in mind
+ * that this name will need to be referenced within your user application under most circumstances. It is
+ * suggested that this folder be named "LUFA", or "LUFA" followed by the version string for easy reference.
+ *
+ * \image html Images/AS5_AS6_Import/AS5_AS6_Import_Step2.png
+ *
+ * \subsubsection SSSec_AS56_Import_Step3 Add the library files
+ * Open your AVRStudio 5/Atmel Studio 6 project. From the "Solution Explorer" pane, click the "Show All Files"
+ * button on the toolbar to display ghosted icons of files and folders located in the project source directory
+ * that are not currently added to the project.
+ *
+ * \image html Images/AS5_AS6_Import/AS5_AS6_Import_Step3.png
+ *
+ * Right-click the ghosted version of the extracted LUFA export folder in the Solution Explorer pane, and
+ * choose the "Add to Project" option from the context menu. This will add the entire LUFA source tree to the
+ * current project.
+ *
+ * \subsubsection SSSec_AS56_Import_Step4 Open Project Toolchain Properties
+ * In the Solution Explorer pane, click the project node, and press the "Properties" button in the toolbar to
+ * open the Project Properties window. This window allows you to configure the various project global compiler,
+ * assembler and linker options.
+ *
+ * \image html Images/AS5_AS6_Import/AS5_AS6_Import_Step4.png
+ *
+ * Click the "Toolchain" tab on the left side of the Project Properties window.
+ *
+ * \subsubsection SSSec_AS56_Import_Step5 Configure Project Toolchain Properties
+ *
+ * In the GNU C Compiler section, open the "Symbols" page. Click the "Add Item" button to the top-right of the
+ * "Defined Symbols" section to add new symbols.
+ *
+ * At a minimum, you will need to define the following symbols (for more information on these symbols, see
+ * \ref Page_ConfiguringApps):
+ * - ARCH
+ * - F_CPU
+ * - F_USB
+ * - BOARD
+ * \image html Images/AS5_AS6_Import/AS5_AS6_Import_Step5_1.png
+ *
+ * Next, open the GNU C Compiler section's "Optimization" page. Ensure that the option to prepare functions for
+ * garbage collection is enabled.
+ * \image html Images/AS5_AS6_Import/AS5_AS6_Import_Step5_2.png
+ *
+ * Finally, in the GNU C Linker section, open the "Optimization" page. Ensure that the option to garbage collect
+ * unused sections is selected.
+ * \image html Images/AS5_AS6_Import/AS5_AS6_Import_Step5_3.png
+ */
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/FutureChanges.txt b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/FutureChanges.txt
new file mode 100644
index 000000000..af1186374
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/FutureChanges.txt
@@ -0,0 +1,47 @@
+/** \file
+ *
+ * This file contains special DoxyGen information for the generation of the main page and other special
+ * documentation pages. It is not a project source file.
+ */
+
+ /** \page Page_FutureChanges Future Changes
+ *
+ * Below is a list of future changes which are proposed for the LUFA library, but not yet started/complete.
+ * This gives an unordered list of future changes which may be available in future releases of the library.
+ * If you have an item to add to this list, please contact the library author via email, the LUFA mailing list,
+ * or post your suggestion as an enhancement request to the project bug tracker.
+ *
+ * <b>Targeted for Future Releases:</b>
+ * - Code Features
+ * -# Add hub support when in Host mode for multiple devices
+ * -# Investigate virtual hubs when in device mode instead of composite devices
+ * -# Re-add interrupt Pipe/Endpoint support
+ * -# Update stream APIs to use DMA transfers on supported architectures
+ * -# Pull out third party libraries into a separate folder and reference them as required
+ * -# Add a LUFA_YIELD macro for integration into a third-party RTOS
+ * -# Abstract out Mass Storage byte send/receive to prevent low level API use in projects
+ * -# Fix HID report parser usage support for array types
+ * -# Make HOST_DEVICE_SETTLE_DELAY_MS a global variable that can be changed
+ * -# Add MANDATORY_EVENT_FUNCTIONS compile time option
+ * -# Add watchdog support to the library and apps/bootloaders
+ * -# Limit the maximum size of control transfers
+ * - Testing/Verification
+ * -# Re-run USBIF test suite on all classes to formally verify operation
+ * -# Implement automated functional testing of all demos
+ * - Documentation/Support
+ * -# Add detailed overviews of how each demo works
+ * -# Add board overviews
+ * -# Write LUFA tutorials
+ * - Demos/Projects
+ * -# Add class driver support for Test and Measurement class
+ * -# Add class driver support for EEM class
+ * -# Add class driver support for ECM class
+ * -# Add class driver generic HID report host demo
+ * -# Implement flow control for USB to Serial project
+ * - Ports
+ * -# Port all demos to multiple architectures
+ * -# Finish USB XMEGA port
+ * -# Add AVR32 UC3C, UC3D and UC3L support
+ * -# Other (commercial) C compilers
+ */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/GettingStarted.txt b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/GettingStarted.txt
new file mode 100644
index 000000000..9ceec1e04
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/GettingStarted.txt
@@ -0,0 +1,37 @@
+/** \file
+ *
+ * This file contains special DoxyGen information for the generation of the main page and other special
+ * documentation pages. It is not a project source file.
+ */
+
+/** \page Page_GettingStarted Getting Started
+ *
+ * Getting started with LUFA is easy; read the content below to get on your way to your first LUFA powered application.
+ *
+ * \section Sec_DemosOverview The LUFA Demo Applications
+ *
+ * Out of the box, LUFA contains a large number of pre-made class demos for you to test, experiment with and
+ * ultimately build upon for your own projects. All the demos (where possible) come pre-configured to build and
+ * run correctly on the AT90USB1287 AVR microcontroller, mounted on the Atmel USBKEY board and running at an 8MHz
+ * master clock. This is due to two reasons; one, it is the hardware the author possesses, and two, it is the most
+ * popular Atmel USB demonstration board to date. To learn how to reconfigure, recompile and program the included
+ * LUFA applications using different settings, see the subsections below.
+ *
+ * \section Sec_ClassOrLowLevel Class Driver and Low Level Demos
+ *
+ * Most of the included demos in the /Demos/ folder come in both ClassDriver and LowLevel varieties. If you are new
+ * to LUFA, it is highly recommended that you look at the ClassDriver versions first, which use the pre-made USB
+ * Class Drivers (\ref Group_USBClassDrivers) to simplify the use of the standard USB classes in user applications.
+ * These demos give a basic but easy to use interface to the USB class used in the demo application, such as HID or
+ * CDC.
+ *
+ * Those needing absolute control over the class implementation can look at the LowLevel demos, which implement the
+ * required USB class directly in the demo application using the lowest level LUFA APIs.
+ *
+ *
+ * <b>Subsections:</b>
+ * \li \subpage Page_ConfiguringApps - How to Configure the Included Demos, Projects and Bootloaders
+ * \li \subpage Page_CompilingApps - How to Compile the Included Demos, Projects and Bootloaders
+ * \li \subpage Page_ProgrammingApps - How to Program an AVR with the Included Demos, Projects and Bootloaders
+ */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Groups.txt b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Groups.txt
new file mode 100644
index 000000000..2dfa4209d
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Groups.txt
@@ -0,0 +1,38 @@
+/** \file
+ *
+ * This file contains special DoxyGen information for the generation of the main page and other special
+ * documentation pages. It is not a project source file.
+ */
+
+/** \defgroup Group_BoardDrivers Board Drivers
+ *
+ * \brief Functions, macros, variables, enums and types related to the control of physical board hardware.
+ */
+
+/** \defgroup Group_PeripheralDrivers On-chip Peripheral Drivers
+ *
+ * \brief Functions, macros, variables, enums and types related to the control of AVR subsystems.
+ */
+
+/** \defgroup Group_MiscDrivers Miscellaneous Drivers
+ *
+ * \brief Miscellaneous driver Functions, macros, variables, enums and types.
+ */
+
+/** \defgroup Group_PlatformDrivers_AVR8 AVR8
+ * \ingroup Group_PlatformDrivers
+ *
+ * \brief Drivers relating to the AVR8 architecture platform, such as clock setup and interrupt management.
+ */
+
+/** \defgroup Group_PlatformDrivers_XMEGA XMEGA
+ * \ingroup Group_PlatformDrivers
+ *
+ * \brief Drivers relating to the XMEGA architecture platform, such as clock setup and interrupt management.
+ */
+
+/** \defgroup Group_PlatformDrivers_UC3 UC3
+ * \ingroup Group_PlatformDrivers
+ *
+ * \brief Drivers relating to the UC3 architecture platform, such as clock setup and interrupt management.
+ */
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step1.png b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step1.png
new file mode 100644
index 000000000..4f0c26f37
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step1.png
Binary files differ
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step2.png b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step2.png
new file mode 100644
index 000000000..6e309ae41
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step2.png
Binary files differ
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step3.png b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step3.png
new file mode 100644
index 000000000..8192c9ae8
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step3.png
Binary files differ
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step4.png b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step4.png
new file mode 100644
index 000000000..2bb8f5fc8
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step4.png
Binary files differ
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step5_1.png b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step5_1.png
new file mode 100644
index 000000000..f3a49ba9c
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step5_1.png
Binary files differ
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step5_2.png b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step5_2.png
new file mode 100644
index 000000000..078f4ec8d
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step5_2.png
Binary files differ
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step5_3.png b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step5_3.png
new file mode 100644
index 000000000..8a8571bd8
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step5_3.png
Binary files differ
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/Author.jpg b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/Author.jpg
new file mode 100644
index 000000000..e8f5541a0
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/Author.jpg
Binary files differ
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/LUFA.png b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/LUFA.png
new file mode 100644
index 000000000..54fa1a664
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/LUFA.png
Binary files differ
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/LUFA_thumb.png b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/LUFA_thumb.png
new file mode 100644
index 000000000..efa538677
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Images/LUFA_thumb.png
Binary files differ
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/KnownIssues.txt b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/KnownIssues.txt
new file mode 100644
index 000000000..7018fec4d
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/KnownIssues.txt
@@ -0,0 +1,170 @@
+/** \file
+ *
+ * This file contains special DoxyGen information for the generation of the main page and other special
+ * documentation pages. It is not a project source file.
+ */
+
+ /** \page Page_KnownIssues Known Issues
+ * The following are known issues present in each official LUFA release. This list should contain all known
+ * issues in the library. Most of these issues should be corrected in the future release - see
+ * \ref Page_FutureChanges for a list of planned changes in future releases.
+ *
+ * \section Sec_KnownIssues140928 Version 140928
+ * - AVR8 Architecture
+ * - No known issues.
+ * - UC3 Architecture
+ * \warning The UC3 device support is currently <b>experimental</b> (incomplete and/or non-functional), and is included for preview purposes only. \n
+ *
+ * - No demos, bootloaders or projects have been ported for the UC3 devices in the current release,
+ * although the architecture is supported in the LUFA core library.
+ * - DMA transfers to and from the USB controller are not yet implemented for this release.
+ * - The UC3C, UC3D and UC3L sub-families of UC3 are not currently supported by the library due to their
+ * altered USB controller design.
+ * - The various \c *_CreateStream() functions for creating standard \c <stdio.h> compatible virtual file
+ * streams are not available on the UC3 architecture, due to a lack of suitable library support.
+ * - XMEGA Architecture
+ * \warning The XMEGA device support is currently <b>experimental</b> (incomplete and/or non-functional), and is included for preview purposes only.
+ *
+ * - Endpoints of more than 64 bytes are not currently supported in this release.
+ * - Isochronous endpoints are not currently supported in this release. As a result, the audio class
+ * cannot be used on XMEGA devices.
+ * - Multiple-bank endpoints are not currently supported in this release.
+ * - Early silicon revisions of the ATXMEGA128A1U are incompatible with LUFA, due to their various errata
+ * relating to the USB controller.
+ * - Architecture Independent
+ * - The LUFA library is not watchdog aware, and thus timeouts are possible if short periods are used
+ * and a lengthy USB operation is initiated.
+ * - No LUFA provided driver INF files for Windows are signed, and thus may fail to install on systems where driver signing is enforced (e.g. Windows 8).
+ * - Build System
+ * - No known issues.
+ * - Atmel Studio Integration
+ * - Not all devices are listed in the "Supported Parts" screen when selecting a device. To select an alternative device, change the "Show Device" drop-down to "All Parts".
+ * - When switching boards after changing the device selection, a second conflicting \c BOARD symbol definition can be created that prevents successful compilation. To fix, open the project properties window (<i>Project->Project {name} Properties...</i> menu item), click the "Toolchain" tab, click "Symbols" under the "AVR/GNU C Compiler" section and remove the incorrect definition.
+ *
+ * \section Sec_KnownIssues140302 Version 140302
+ * - AVR8 Architecture
+ * - No known issues.
+ * - UC3 Architecture
+ * \warning The UC3 device support is currently <b>experimental</b> (incomplete and/or non-functional), and is included for preview purposes only. \n
+ *
+ * - No demos, bootloaders or projects have been ported for the UC3 devices in the current release,
+ * although the architecture is supported in the LUFA core library.
+ * - DMA transfers to and from the USB controller are not yet implemented for this release.
+ * - The UC3C, UC3D and UC3L sub-families of UC3 are not currently supported by the library due to their
+ * altered USB controller design.
+ * - The various \c *_CreateStream() functions for creating standard \c <stdio.h> compatible virtual file
+ * streams are not available on the UC3 architecture, due to a lack of suitable library support.
+ * - XMEGA Architecture
+ * \warning The XMEGA device support is currently <b>experimental</b> (incomplete and/or non-functional), and is included for preview purposes only.
+ *
+ * - Endpoints of more than 64 bytes are not currently supported in this release.
+ * - Isochronous endpoints are not currently supported in this release. As a result, the audio class
+ * cannot be used on XMEGA devices.
+ * - Multiple-bank endpoints are not currently supported in this release.
+ * - Early silicon revisions of the ATXMEGA128A1U are incompatible with LUFA, due to their various errata
+ * relating to the USB controller.
+ * - Architecture Independent
+ * - The LUFA library is not watchdog aware, and thus timeouts are possible if short periods are used
+ * and a lengthy USB operation is initiated.
+ * - No LUFA provided driver INF files for Windows are signed, and thus may fail to install on systems where driver signing is enforced (e.g. Windows 8).
+ * - Build System
+ * - No known issues.
+ * - Atmel Studio Integration
+ * - Not all devices are listed in the "Supported Parts" screen when selecting a device. To select an alternative device, change the "Show Device" drop-down to "All Parts".
+ * - When switching boards after changing the device selection, a second conflicting BOARD symbol definition can be created that prevents successful compilation. To fix, open the project properties window (<i>Project->Project {name} Properties...</i> menu item), click the Toolchain tab, click "Symbols" under the "AVR/GNU C Compiler" section and remove the incorrect definition.
+ *
+ * \section Sec_KnownIssues130901 Version 130901
+ * - AVR8 Architecture
+ * - No known issues.
+ * - UC3 Architecture
+ * \warning The UC3 device support is currently <b>experimental</b> (incomplete and/or non-functional), and is included for preview purposes only. \n
+ *
+ * - No demos, bootloaders or projects have been ported for the UC3 devices in the current release,
+ * although the architecture is supported in the LUFA core library.
+ * - DMA transfers to and from the USB controller are not yet implemented for this release.
+ * - The UC3C, UC3D and UC3L sub-families of UC3 are not currently supported by the library due to their
+ * altered USB controller design.
+ * - The various \c *_CreateStream() functions for creating standard \c <stdio.h> compatible virtual file
+ * streams are not available on the UC3 architecture, due to a lack of suitable library support.
+ * - XMEGA Architecture
+ * \warning The XMEGA device support is currently <b>experimental</b> (incomplete and/or non-functional), and is included for preview purposes only.
+ *
+ * - Endpoints of more than 64 bytes are not currently supported in this release.
+ * - Isochronous endpoints are not currently supported in this release. As a result, the audio class
+ * cannot be used on XMEGA devices.
+ * - Multiple-bank endpoints are not currently supported in this release.
+ * - Early silicon revisions of the ATXMEGA128A1U are incompatible with LUFA, due to their various errata
+ * relating to the USB controller.
+ * - Architecture Independent
+ * - The LUFA library is not watchdog aware, and thus timeouts are possible if short periods are used
+ * and a lengthy USB operation is initiated.
+ * - No LUFA provided driver INF files for Windows are signed, and thus may fail to install on systems where driver signing is enforced (e.g. Windows 8).
+ * - Build System
+ * - No known issues.
+ * - Atmel Studio Integration
+ * - Not all devices are listed in the "Supported Parts" screen when selecting a device. To select an alternative device, change the "Show Device" drop-down to "All Parts".
+ * - When switching boards after changing the device selection, a second conflicting BOARD symbol definition can be created that prevents successful compilation. To fix, open the project properties window (<i>Project->Project {name} Properties...</i> menu item), click the Toolchain tab, click "Symbols" under the "AVR/GNU C Compiler" section and remove the incorrect definition.
+ *
+ * \section Sec_KnownIssues130303 Version 130303
+ * - AVR8 Architecture
+ * - No known issues.
+ * - UC3 Architecture
+ * \warning The UC3 device support is currently <b>experimental</b> (incomplete and/or non-functional), and is included for preview purposes only. \n
+ *
+ * - No demos, bootloaders or projects have been ported for the UC3 devices in the current release,
+ * although the architecture is supported in the LUFA core library.
+ * - DMA transfers to and from the USB controller are not yet implemented for this release.
+ * - The UC3C, UC3D and UC3L sub-families of UC3 are not currently supported by the library due to their
+ * altered USB controller design.
+ * - The various \c CreateStream() functions for creating standard \c <stdio.h> compatible virtual file
+ * streams are not available on the UC3 architecture, due to a lack of suitable library support.
+ * - XMEGA Architecture
+ * \warning The XMEGA device support is currently <b>experimental</b> (incomplete and/or non-functional), and is included for preview purposes only.
+ *
+ * - No demos, bootloaders or projects have been ported for the XMEGA devices in the current release,
+ * although the architecture is supported in the LUFA core library.
+ * - Endpoints of more than 64 bytes are not currently supported in this release.
+ * - Isochronous endpoints are not currently supported in this release. As a result, the audio class
+ * cannot be used on XMEGA devices.
+ * - Multiple-bank endpoints are not currently supported in this release.
+ * - Early revisions of the ATXMEGA128A1U are incompatible with LUFA, due to their various errata
+ * relating to the USB controller.
+ * - Architecture Independent
+ * - The LUFA library is not watchdog aware, and thus timeouts are possible if short periods are used
+ * and a lengthy USB operation is initiated.
+ * - No LUFA provided driver INF files for Windows are signed, and thus may fail to install on systems where driver signing is enforced (e.g. Windows 8).
+ * - Build System
+ * - No known issues.
+ *
+ * \section Sec_KnownIssues120730 Version 120730
+ * - AVR8 Architecture
+ * - No known issues.
+ * - UC3 Architecture
+ * \warning The UC3 device support is currently <b>experimental</b> (incomplete and/or non-functional), and is included for preview purposes only. \n
+ *
+ * - No demos, bootloaders or projects have been ported for the UC3 devices in the current release,
+ * although the architecture is supported in the LUFA core library.
+ * - DMA transfers to and from the USB controller are not yet implemented for this release.
+ * - The UC3C, UC3D and UC3L sub-families of UC3 are not currently supported by the library due to their
+ * altered USB controller design.
+ * - The various \c CreateStream() functions for creating standard \c <stdio.h> compatible virtual file
+ * streams are not available on the UC3 architecture, due to a lack of suitable library support.
+ * - XMEGA Architecture
+ * \warning The XMEGA device support is currently <b>experimental</b> (incomplete and/or non-functional), and is included for preview purposes only.
+ *
+ * - No demos, bootloaders or projects have been ported for the XMEGA devices in the current release,
+ * although the architecture is supported in the LUFA core library.
+ * - Endpoints of more than 64 bytes are not currently supported in this release.
+ * - Isochronous endpoints are not currently supported in this release. As a result, the audio class
+ * cannot be used on XMEGA devices.
+ * - Multiple-bank endpoints are not currently supported in this release.
+ * - Early revisions of the ATXMEGA128A1U are incompatible with LUFA, due to their various errata
+ * relating to the USB controller.
+ * - Architecture Independent
+ * - The LUFA library is not watchdog aware, and thus timeouts are possible if short periods are used
+ * and a lengthy USB operation is initiated.
+ * - No LUFA provided driver INF files for Windows are signed, and thus may fail to install on systems where driver signing is enforced (e.g. Windows 8).
+ * - Build System
+ * - No known issues.
+ */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/LUFAPoweredProjects.txt b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/LUFAPoweredProjects.txt
new file mode 100644
index 000000000..b1816d061
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/LUFAPoweredProjects.txt
@@ -0,0 +1,224 @@
+/** \file
+ *
+ * This file contains special DoxyGen information for the generation of the main page and other special
+ * documentation pages. It is not a project source file.
+ */
+
+/** \page Page_LUFAPoweredProjects User Projects Powered by LUFA
+ *
+ * LUFA is currently in use all around the world, in many applications both commercial and non-commercial. Below is a
+ * list of known public LUFA powered projects, which all use the LUFA library in some way. Feel free to visit each project's
+ * home page for more information on each project.
+ *
+ * If you have a project that you would like to add to this list, please contact me via the details on the main page of this
+ * documentation.
+ *
+ * \section Sec_BoardsUsingLUFA AVR-USB Development Boards Using LUFA
+ *
+ * The following is a list of known AVR USB development boards, which recommend using LUFA for the USB stack. Some of these
+ * are open design, and all are available for purchase as completed development boards suitable for project development.
+ *
+ * \li AVR-USB-162, a USBKEY-like development board for the AT90USB162: http://olimex.com/dev/avr-usb-162.html
+ * \li Benito #7, a no-frills USB board: http://www.dorkbotpdx.org/wiki/benito
+ * \li Duce, the successor to the Benito #7: http://dorkbotpdx.org/wiki/duce
+ * \li JM-DB-U2, an ATMEGA32U2 development board: http://u2.mattair.net/index.html
+ * \li Micropendous, an open design/source set of AVR USB development boards: http://micropendous.org/
+ * \li Microsin AVR-USB162 breakout board, a DIY AT90USB162 development board: http://microsin.ru/content/view/685/44/
+ * \li Minimus USB, a board specially designed for PSGroove: http://www.minimususb.com/
+ * \li Nanduino, a do-it-yourself AT90USB162 board: http://www.makestuff.eu/wordpress/?page_id=569
+ * \li Sparkfun ATMEGA8U2 breakout board: http://www.sparkfun.com/products/10277
+ * \li Teensy and Teensy++, two other AVR USB development boards: http://www.pjrc.com/teensy/index.html
+ * \li U2DIL/U4DIL, a set of DIP layout USB AVR boards: http://www.reworld.eu/re/en/products/u2dil/
+ * \li USB2AX, a tiny USB to serial converter board: http://paranoidstudio.assembla.com/wiki/show/paranoidstudio/USB2AX
+ * \li USBFOO 2, AT90USB162 based development board: http://shop.kernelconcepts.de/product_info.php?products_id=102
+ *
+ * \section Sec_LUFAProjects Projects Using LUFA (Hobbyist)
+ *
+ * The following are known hobbyist projects using LUFA. Most are open source, and show off interesting ways that the LUFA library
+ * can be incorporated into many different applications.
+ *
+ * \li Accelerometer Game Joystick: http://www.crictor.co.il/he/episodes/joystick/
+ * \li Adjacent Reality Motion Tracker: http://www.adjacentreality.org/
+ * \li AD9833 based USB Function Generator: http://tuomasnylund.fi/drupal6/content/ad9833-based-usb-function-generator
+ * \li AERY development platform for the AVR32 devices: http://www.aery32.com/
+ * \li AM Radio transmitter: http://amcinnes.info/2012/uc_am_xmit/
+ * \li Arcade Controller: http://fletchtronics.net/arcade-controller-made-petunia
+ * \li Arcade Joystick: http://jamie.lentin.co.uk/embedded/arcade-joystick/
+ * \li AttoBasic AVR BASIC interpreter: http://cappels.org/dproj/AttoBasic_Home/AttoBasic_Home.html
+ * \li AVR USB Modem, a 3G Wireless Modem host: http://code.google.com/p/avrusbmodem/
+ * \li Bicycle POV: http://www.code.google.com/p/bicycleledpov/
+ * \li Bluetooth Explorerbot: http://code.google.com/p/bluetooth-explorerbot/
+ * \li Bus Ninja, an AVR clone of the popular BusPirate project: http://blog.hodgepig.org/busninja/
+ * \li CAMTRIG, a remote Camera Trigger device: http://code.astraw.com/projects/motmot/camtrig
+ * \li ChameleonMini, a smart card emulator: https://github.com/skuep/ChameleonMini
+ * \li CD Driver Emulator Dongle for ISO Files: http://cdemu.blogspot.com/
+ * \li ChipWhisperer, a signal capture device: https://www.assembla.com/spaces/chipwhisperer/wiki/ChipWhisperer_Rev2_Capture_Hardware
+ * \li ClockTamer, a configurable clock generator: http://code.google.com/p/clock-tamer/
+ * \li Collection of alternative Arduino Uno firmwares: http://hunt.net.nz/users/darran/
+ * \li Computer controlled LED matrix (Russian): http://we.easyelectronics.ru/AVR/nebolshoy-primer-s-lufa-hidapi.html
+ * \li CULFW, a 868MHz RF packet encoder/decoder: http://www.koeniglich.de/culfw/culfw.html
+ * \li Dashkey, a custom PC keyboard controller: http://geekhack.org/showwiki.php?title=Island:19096
+ * \li DIY PS3 controller emulator: https://code.google.com/p/diyps3controller/
+ * \li EMuSer, a USB-RS422 adapter for E-Mu samplers: http://www.emxp.net/EMuSer.htm
+ * \li EQ Track, a telescope mount controller: http://sourceforge.net/projects/eqtrack/
+ * \li Estick JTAG, an ARM JTAG debugger: http://code.google.com/p/estick-jtag/
+ * \li "Fingerlicking Wingdinger" (WARNING: Bad language if no Javascript), a MIDI controller: http://noisybox.net/electronics/wingdinger/
+ * \li Flyatar, a real-time fly tracking system: https://github.com/peterpolidoro/Flyatar
+ * \li FootJoy, a 22 button, 6-axis josystick with keyboard and mouse modes: https://bitbucket.org/sirbrialliance/foot-joy/
+ * \li Gamecube controller to USB adapter: https://www.facebook.com/media/set/?set=a.10150202447076304.310536.688776303&l=df53851c50
+ * \li Garmin GPS USB to NMEA standard serial sentence translator: http://github.com/nall/garmin-transmogrifier/tree/master
+ * \li Geiger Counter with USB interface: http://www.hforsten.com/i-made-a-geiger-counter.html
+ * \li Generic HID Device Creator: http://generichid.sourceforge.net/
+ * \li Generic HID Open Source Framework: http://www.waitingforfriday.com/index.php/USB_Generic_HID_Open_Source_Framework_for_Atmel_AVR_and_Windows
+ * \li Ghetto Drum, a MIDI drum controller: http://noisybox.net/art/gdrum/
+ * \li GPS enabled lap timer for vehicles: http://www.assembla.com/code/ironlung/subversion/nodes/trunk/LapTimer
+ * \li GSynth, an 8-bit sound synthesizer: https://github.com/gcielniak/GSynth
+ * \li Gumbi, a Python library and USB GPIO controller: https://code.google.com/p/gumbi/
+ * \li Hardware Volume Control: https://github.com/davidk/hw-volume-control
+ * \li Hiduino, a USB-MIDI replacement firmware for the Arduino Uno: http://code.google.com/p/hiduino/
+ * \li IBM capacitive keybord replacement controller: http://downloads.cornall.co/ibm-capsense-usb-web/ibm-capsense-usb.html
+ * \li Ikea RGB LED USB modification: http://slashhome.se/p/projects/id/ikea_dioder_usb/#project
+ * \li IR electricity meter monitor: http://sourceforge.net/projects/irmetermon/
+ * \li IR Remote to Keyboard decoder: http://netzhansa.blogspot.com/2010/04/our-living-room-hi-fi-setup-needs-mp3.html
+ * \li Jukebox panic button: http://thinkl33t.co.uk/the-panic-button
+ * \li Kinesis replacement firmware: https://github.com/chrisandreae/kinesis-firmware
+ * \li LED Panel controller: http://projects.peterpolidoro.net/caltech/panelscontroller/panelscontroller.htm
+ * \li Linux Secure Storage Dongle: http://github.com/TomMD/teensy
+ * \li LUFA powered DDR dance mat (French): http://logicien-parfait.fr/dokuwiki/doku.php?id=projet:ddr_repair
+ * \li Macintosh SIMM ROM Programmer: https://code.google.com/p/mac-rom-simm-programmer/
+ * \li MakeTV Episode Dispenser: http://www.youtube.com/watch?v=BkWUi18hl3g
+ * \li Mec64,a Commodore 64 keyboard: http://deskthority.net/workshop-f7/mec64-keyboard-t4522.html
+ * \li MidiMonster, a USB-to-MIDI gateway board: http://www.dorkbotpdx.org/wiki/midimonster
+ * \li MIDI Theremin: http://baldwisdom.com/usb-midi-controller-theremin-style-on-arduino-uno/
+ * \li MIDI interface hack of a toy Guitar: http://blog.x37v.info/2011/06/26/toy-guitar-hacked-midi-conroller
+ * \li MiniBloq, a graphical Ardunio programming environment : http://minibloq.org/
+ * \li MiXley, a port of the Teacup 3D printer firmware for the USB AVRs: http://codaset.com/michielh/mixley
+ * \li Mobo 4.3, a USB controlled all band (160-10m) HF SDR transceiver: http://sites.google.com/site/lofturj/mobo4_3
+ * \li Moco, a native Arduino Uno MIDI replacement firmware: http://web.mac.com/kuwatay/morecat_lab./MocoLUFA.html
+ * \li Monash ECSE Smart Packet Radio Testbed: http://www.ecse.monash.edu.au/twiki/bin/view/WSRNLab/SmartPacketRadio
+ * \li Motherboard BIOS flasher: http://www.coreboot.org/InSystemFlasher
+ * \li Multi-button Joystick (French): http://logicien-parfait.fr/dokuwiki/doku.php?id=projet:joystick
+ * \li Music Playing Alarm Clock (Tutorial): http://www.instructables.com/id/Music-Playing-Alarm-Clock/
+ * \li Nehebkau, Laptop Controlled Keyboard and Mouse: http://www.frank-zhao.com/cache/nehebkau.php
+ * \li NeroJTAG, a JTAG dongle: https://github.com/makestuff/neroJtag
+ * \li NES Controller USB modification: https://github.com/nfd/nes_adapter
+ * \li Nikon wireless camera remote control (Norwegian): http://hekta.org/~hpe1119/
+ * \li Nintendo Four-Score, USB NES 4-player controller adapter: http://www.waitingforfriday.com/index.php/Nintendo_Four_Score_USB
+ * \li Numpad keyboard: http://tuomasnylund.fi/drupal6/content/usb-cherry-mx-numpad
+ * \li Opendous-JTAG, an open source ARM JTAG debugger: http://code.google.com/p/opendous-jtag/
+ * \li Openkubus, an open source hardware-based authentication dongle: http://code.google.com/p/openkubus/
+ * \li Orbee, a USB connected RGB Orb for notifications: http://www.franksworkshop.com.au/Electronics/Orbee/Orbee.htm
+ * \li Password keyring: http://owlsan.blogspot.no/2014/06/keyring-project-version-10.html
+ * \li Picade alternative firmware, a retro Arcade controller/cabinet: https://github.com/rktrlng/picade_lufa
+ * \li PPM signal generator over USB: https://github.com/G33KatWork/USBPPM
+ * \li Programmable keyboard controller: http://41j.com/blog/2011/10/a-programmable-keyboard-controller/
+ * \li Programmable XBOX controller: http://richard-burke.dyndns.org/wordpress/pan-galactic-gargantuan-gargle-brain-aka-xbox-360-usb-controller/
+ * \li Project Surface, a touch interface controller for Windows 8: https://code.google.com/p/project-surface/
+ * \li PSGroove, a Playstation 3 Homebrew dongle: http://github.com/psgroove
+ * \li PS/2 to USB adapter: https://github.com/makestuff/p2ukbd
+ * \li RaspiFace, an Arduino platform bridge for the Raspberry Pi: http://www.raspiface.com/
+ * \li Reflow oven controller: http://danstrother.com/2011/01/15/reflow-oven-controller/
+ * \li RFPirate, a RF experimentation platform: https://github.com/ebuller/RF-Pirate
+ * \li RF Power Meter, based on the AD8307 log amp: https://sites.google.com/site/lofturj/ad8307-power-meter
+ * \li RF Transceiver using the MRF49XA: http://alternet.us.com/?page_id=1494
+ * \li SD Card reader: http://elasticsheep.com/2010/04/teensy2-usb-mass-storage-with-an-sd-card/
+ * \li SDR1, a Software Defined Radio firmware: https://code.google.com/p/sdr-mk1/
+ * \li SEGA Megadrive/Genesis Development Cartridge: http://www.makestuff.eu/wordpress/?page_id=398
+ * \li Serial Line bus analyser: http://www.pjrc.com/teensy/projects/SerialAnalyzer.html
+ * \li Simple USB LED Controller (SULC): https://github.com/scottbez1/sulc
+ * \li SNES custom FLASH ROM: http://electrifiedfoolingmachine.co/?page_id=633
+ * \li Smartcard Detective: https://code.google.com/p/smartcarddetective/
+ * \li SmartportVHD Apple II Mass Storage adapter: http://pcedric3.free.fr/SmartportVHD/
+ * \li Single LED Matrix Display: http://guysoft.wordpress.com/2009/10/08/bumble-b/
+ * \li Simple USB LED Controller: https://github.com/scottbez1/sulc
+ * \li Stripe Snoop, a Magnetic Card reader: http://www.ossguy.com/ss_usb/
+ * \li Stylophone, with USB MIDI connectivity: http://www.waitingforfriday.com/index.php/Stylophone_Studio_5
+ * \li Teensy SD Card .WAV file player: http://elasticsheep.com/2010/04/teensy2-usb-wav-player-part-1/
+ * \li Touch It (Fabulously), presumably art: http://touch.it.fa.bulo.us/ly/
+ * \li Touchscreen Input Device: http://capnstech.blogspot.com/2010/07/touchscreen-update.html
+ * \li UDFS, a BBC Micro USB disk filing system: https://github.com/makestuff/udfs
+ * \li Universal USB AVR Module: http://usbavr.bplaced.net/
+ * \li USB2AX, a USB to Dynamixel network adapter: http://paranoidstudio.assembla.com/wiki/show/paranoidstudio/USB2AX
+ * \li USBPass, a USB password keeper: http://sroz.net/projects/usbpass/
+ * \li USB Business Card: http://www.limpkin.fr/index.php?post/2012/09/15/My-new-business-card
+ * \li USB Function Generator: http://tuomasnylund.fi/drupal6/content/ad9833-based-usb-function-generator
+ * \li USB Infrared Receiver/Transmitter: http://vaton4.web2001.cz/
+ * \li USB Interface for Playstation Portable Devices: http://forums.ps2dev.org/viewtopic.php?t=11001
+ * \li USB MIDI to DMX controller: http://github.com/hanshuebner/miDiMX
+ * \li USB Mood Light: https://github.com/hsbp/usb_moodlight
+ * \li USB powered Geiger Counter: http://uhrheber.wordpress.com/2011/04/28/a-usb-powered-geiger-counter-for-the-z2-and-other-computers/
+ * \li Userial, a USB to Serial converter with SPI, I2C and other protocols: http://www.tty1.net/userial/
+ * \li Wii Classic Controller to USB converter: https://github.com/crazyiop/wii-classic-2-usb
+ * \li Wireless MIDI Guitar system: http://www.ise.pw.edu.pl/~wzab/wireless_guitar_system/
+ * \li XBOX 360 Startup Sound Changer: http://www.homebrew-connection.org/change-your-xbox-360-startup-sounds-yourself/
+ * \li Xnormidi, a C MIDI library: http://x37v.info/projects/xnormidi
+ * \li XUM1541, a Commodore 64 floppy drive to USB adapter: http://www.root.org/~nate/c64/xum1541/
+ * \li Zeus, a touch screen computer for music manipulation: http://www.benbengler.com/developments_zeus.html
+ *
+ * \section Sec_LUFACommercialProjects Projects Using LUFA (Commercial)
+ *
+ * The following is a list of known commercial products using LUFA. Some of these are open source, although many are "black-box"
+ * solutions with no source code given. Those companies which have purchased a Commercial License to LUFA (see \ref Page_LicenseInfo)
+ * are not listed here unless specifically requested.
+ *
+ * \li Alphasphere, a MIDI input sphere device for music creation: http://www.alphasphere.com/
+ * \li Arduino Uno and Leonardo, official Arduino boards: http://www.arduino.cc
+ * \li ARPS Locator: http://la3t.hamradio.no/lab//?id=tracker_en
+ * \li AsTeRICS assistive technologies project, HID actuator: http://www.asterics.eu
+ * \li BitFury, a Bitcoin ASIC miner: https://github.com/aauer1/LUFA-BitFury/tree/master/Projects/BitfuryBTC
+ * \li Ceberus, a MadCatz Xbox 360 arcade stick modifier: http://www.phreakmods.com/products/cerberus
+ * \li CFFA3000, a CompactFlash interface for the Apple II: http://www.dreher.net/CFforAppleII
+ * \li Digital Survey Instruments Magnetometer and Pointer: http://www.digitalsurveyinstruments.com/
+ * \li FinchRobot, a robot designed for educational use: http://www.finchrobot.com/
+ * \li Flysight, a GPS logger for wingsuit pilots: http://flysight.ca/
+ * \li Goldilocks, an Arduino compatible clone: http://feilipu.me/2014/03/08/goldilocks-1284p-arduino-uno-clone/
+ * \li HummingBird Kit, a robotics learning platform: http://www.hummingbirdkit.com/
+ * \li LP1, an AVRISP-MKII Clone AVR Programmer: http://embeddedglow.com/items/LP1/LP1.php
+ * \li Penguino, an Arduino Board With On-Board LUFA Powered Debugger/Programmer: http://wiki.icy.com.au/PenguinoAVR
+ * \li PhatIO, a filesystem based I/O interface: http://www.phatio.com/
+ * \li PIR-1, an IR control interface for consumer electronics: http://www.promixis.com/pir-1.php
+ * \li PIR-4, a USB Connected 4 port IR transmitter: http://promixis.com/pir-4.php
+ * \li PortPilot, a USB device charger with power meter: http://portpilot.net/
+ * \li KeyGlove, an alternative input system: http://www.keyglove.net/
+ * \li Many of Busware's Products: http://www.busware.de/
+ * \li MIDIFighter, a USB-MIDI controller: http://www.midifighter.com/
+ * \li MIDI USB Arduino Shield: http://openpipe.cc/products/midi-usb-shield/
+ * \li Norduino, a wireless Arduino: http://norduino.robomotic.com/norduino-is-now-usb-hid/
+ * \li Olimex AVR-ISP-MK2, an AVRISP-MKII Clone AVR Programmer: https://www.olimex.com/dev/avr-isp-mk2.html
+ * \li Retrode, a USB Games Console Cartridge Reader: http://www.retrode.org
+ * \li RFI21.1EU UHF RFID reader: http://www.metra.cz/rfid/uhf-rfid-ctecky/rfi21-1eu-uhf-rfid-ctecka.htm
+ * \li SmartCardDetective, a Smart Card analysis tool: http://www.smartcarddetective.com/
+ * \li TimelapsePlus, a digital camera time lapse tool: https://github.com/timelapseplus/TimelapsePlus-Firmware
+ * \li USBTINY-MKII, an AVRISP-MKII Clone AVR Programmer: http://tom-itx.no-ip.biz:81/~webpage/boards/USBTiny_Mkii/USBTiny_Mkii_index.php
+ * \li UDS18B20 USB Temperature sensor: http://toughlog.org/uds18b20/
+ * \li VMeter, a USB MIDI touch strip controller: http://www.vmeter.net/
+ * \li XMEGA Development Board, using LUFA as an On-Board Programmer: http://xmega.mattair.net/
+ * \li Zeptoprog, a multifunction AVR programmer: http://www.mattairtech.com/index.php/featured/zeptoprog.html
+ *
+ * \section Sec_LUFAPublications Publications Mentioning LUFA
+ * The following are published magazines which have either mentioned or featured the LUFA library.
+ *
+ * \li Elektor Magazine, "My First AVR-USB" by Antoine Authier (feature), January 2010 Issue
+ * \li Elektor Magazine, "USB is Cool/Sucks" by Jerry Jacobs and Chris Vossen (minor mention), January 2010 Issue
+ * \li Elektor Magazine, "20 x Open Source" by Jens Nickel, March 2010 Issue
+ * \li Circuit Cellar Magazine, "Advanced USB Design Debugging" by Collin O'Flynn, August 2010 Issue
+ * \li "Some Assembly Required: Assembly Language Programming with the AVR Microcontroller" by Timothy S. Margush
+ * \li Elektor Magazine, "Taming the Beast (2)" by Clemens Valens/Raymond Vermeulen, January 2014 Issue
+ *
+ * \section Sec_LUFANotableMentions Other Notable Mentions of LUFA
+ * The following are non-print but notable mentions of the LUFA library.
+ *
+ * \li Adafruit "Ask an Engineer", 7th November 2010
+ * \li Arduino 2010 Keynote speech
+ * \li The Amp Hour podcast blog #11
+ * \li Blackhat 2011 conference, "Exploiting USB Devices with Arduino"
+ *
+ * \section Sec_PortsAndForks Non-Official LUFA Ports and Forks
+ * The following are unofficial forks of the LUFA codebase, which implement different features such as support for
+ * additional architectures.
+ *
+ * \li NXP's official LPCOpen "LPCUSBLib" LUFA fork, for LPC devices: http://www.lpcware.com/
+ * \li Kevin Mehall's LUFA port to the NXP LPC13xx: https://github.com/kevinmehall/LUFA-LPC13xx
+ * \li Mark Ding's port for the Silicon Labs SiM3U1xx: https://www.github.com/MarkDing/USB_CDC
+ * \li Mark Ding's port for the Silicon Labs EFM32 Giant Gecko: https://github.com/MarkDing/lufa-efm32
+ */
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/LibraryResources.txt b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/LibraryResources.txt
new file mode 100644
index 000000000..f69d4344c
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/LibraryResources.txt
@@ -0,0 +1,33 @@
+/** \file
+ *
+ * This file contains special DoxyGen information for the generation of the main page and other special
+ * documentation pages. It is not a project source file.
+ */
+
+/**
+ * \page Page_Resources Library Resources
+ *
+ * \section Sec_UnofficialResources Unofficial Resources
+ * Unofficial Russian LUFA documentation translation: http://microsin.ru/Download.cnt/doc/LUFA/ \n
+ * Tutorial for LUFA USB Control Transfers: http://www.avrbeginners.net/new/tutorials/usb-control-transfers-with-lufa/
+ *
+ * \section Sec_ProjectPages LUFA Related Webpages
+ * Project Homepage: http://www.lufa-lib.org \n
+ * Commercial Licenses: http://www.lufa-lib.org/license \n
+ * Author's Website: http://www.fourwalledcubicle.com \n
+ * Development Blog: http://www.fourwalledcubicle.com/blog \n
+ *
+ * \section Sec_ProjectHelp Assistance With LUFA
+ * Support Mailing List: http://www.lufa-lib.org/support \n
+ * Author's Email: dean [at] fourwalledcubicle [dot] com \n
+ *
+ * \section Sec_InDevelopment Latest In-Development Source Code
+ * Issue Tracker: http://www.lufa-lib.org/tracker \n
+ * Public GIT Repository: http://www.lufa-lib.org/git \n
+ * Latest Repository Source Archive: http://www.lufa-lib.org/latest-archive \n
+ * Commit RSS Feed: http://www.lufa-lib.org/rss \n
+ *
+ * \section Sec_USBResources USB Resources
+ * USB-IF Website: http://www.usb.org \n
+ */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/LicenseInfo.txt b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/LicenseInfo.txt
new file mode 100644
index 000000000..86ed124bb
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/LicenseInfo.txt
@@ -0,0 +1,43 @@
+/** \file
+ *
+ * This file contains special DoxyGen information for the generation of the main page and other special
+ * documentation pages. It is not a project source file.
+ */
+
+/**
+ * \page Page_LicenseInfo Source Code License
+ *
+ * The LUFA library is currently released under the MIT license, included below.
+ *
+ * \section Sec_LicenseForHumans License Summary for Human Beings
+ * Everyone is free to use LUFA without payment - even in commercial applications
+ * where the product source code is not publicly disclosed. However, use of the
+ * library must be in accordance with the library license conditions.
+ *
+ * If you wish to use LUFA without payment, you <b>must</b> include a copy of the
+ * full license text below with your product or project - on your website, and in
+ * an accompanying manual or other materials for the product. As long as the entire
+ * license text is made available and obvious to the users of your product, you
+ * are free to incorporate the LUFA library into your product without special
+ * additional licensing.
+ *
+ * \section Sec_CommercialLicenses Commercial Licensing
+ * In some instances the small requirement for public disclosure of LUFA within a
+ * product is unwanted; in these instances a commercial license is offered up as an
+ * alternative to the standard LUFA license.
+ *
+ * Commercial entities can opt out of the public disclosure clause in this license
+ * for a one-time US$1500 payment. This provides a non-exclusive modified MIT
+ * licensed which allows for the free use of the LUFA library, bootloaders and
+ * (where the sole copyright is attributed to Dean Camera) demos without public
+ * disclosure within an organization, in addition to three free hours of consultation
+ * with the library author, and priority support.
+ *
+ * Please visit the Commercial License link on \ref Page_Resources for more information on
+ * ordering a commercial license for your company.
+ *
+ * \section Sec_LicenseText LUFA License Text
+ *
+ * \verbinclude License.txt
+ */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/MainPage.txt b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/MainPage.txt
new file mode 100644
index 000000000..e737c39b5
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/MainPage.txt
@@ -0,0 +1,52 @@
+/** \file
+ *
+ * This file contains special DoxyGen information for the generation of the main page and other special
+ * documentation pages. It is not a project source file.
+ */
+
+/**
+ * \mainpage
+ *
+ * \image html Images/LUFA.png
+ * <div align="center"><small><i>Logo design by <a href="http://www.studiomonsoon.com">Studio Monsoon Photography</a></i></small></div>
+ * \n
+ * <div align="center"><a href="http://www.lufa-lib.org">http://www.lufa-lib.org</a></div>
+ * \n
+ *
+ * <b>LUFA is donationware. For author and donation information, see \ref Page_Donating.</b>
+ *
+ * LUFA is an open-source USB library for the USB-enabled AVR microcontrollers, released under the MIT license (see \ref Page_LicenseInfo).
+ * It supports a large number of USB AVR models and boards (see \ref Page_DeviceSupport). It is designed to provide an easy to use,
+ * feature rich framework for the development of USB peripherals and hosts.
+ *
+ * LUFA focuses on the microcontroller side of USB development only; it includes no PC host USB driver development facilities - other projects
+ * such as the Windows Driver Development Kit, Windows USB Device Mode Framework and libusb may be of interest for developing custom OS drivers.
+ * While custom USB devices can be made with LUFA using such tools, the included demos all use the inbuilt OS drivers for each USB class for
+ * simplicity.
+ *
+ * The library is currently in a stable release, suitable for download and incorporation into user projects for
+ * both host and device modes. For information about the project progression, see the blog link at \ref Page_Resources.
+ *
+ * LUFA is written specifically for the free AVR-GCC compiler, and uses several GCC-only extensions to make the
+ * library API more streamlined and robust. You can download AVR-GCC for free in a convenient windows package,
+ * from the the WinAVR website (see \ref Page_Resources).
+ *
+ * The only required AVR peripherals for LUFA is the USB controller itself and interrupts - LUFA does not require the use of the
+ * microcontroller's timers or other hardware, leaving more hardware to the application developer.
+ *
+ * Accompanying LUFA in the download package is a set of example demo applications, plus several Bootloaders of different classes
+ * and open source LUFA powered projects.
+ *
+ * <b>Subsections:</b>
+ * \li \subpage Page_LicenseInfo - Project source license and commercial use information
+ * \li \subpage Page_Donating - Donating to support this project
+ * \li \subpage Page_DeviceSupport - Current Device and Hardware Support
+ * \li \subpage Page_ChangeLog - Project Changelog
+ * \li \subpage Page_KnownIssues - Known Issues
+ * \li \subpage Page_FutureChanges - Planned Changes to the Library
+ * \li \subpage Page_GettingStarted - Getting started with LUFA
+ * \li \subpage Page_DevelopingWithLUFA - Developing with LUFA
+ * \li \subpage Page_LUFAPoweredProjects - Other Projects Using LUFA
+ * \li \subpage Page_Resources - LUFA and USB Related Resources
+ */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/MigrationInformation.txt b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/MigrationInformation.txt
new file mode 100644
index 000000000..bc47d1475
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/MigrationInformation.txt
@@ -0,0 +1,708 @@
+/** \file
+ *
+ * This file contains special DoxyGen information for the generation of the main page and other special
+ * documentation pages. It is not a project source file.
+ */
+
+/** \page Page_Migration Migrating from Older Versions
+ *
+ * Below is migration information for updating existing projects based on previous versions of the LUFA library
+ * to the next version released. It does not indicate all new additions to the library in each version change, only
+ * areas relevant to making older projects compatible with the API changes of each new release.
+ *
+ * \section Sec_Migration140928 Migrating from 140302 to 140928
+ * <b>Device Mode</b>
+ * - The device mode RNDIS class driver now requires a user-supplied buffer and buffer length to operate, rather
+ * than allocating this buffer internally.
+ *
+ * \section Sec_Migration140302 Migrating from 130901 to 140302
+ * <b>USB Core</b>
+ * - The \c VERSION_BCD() macro has changed from accepting one floating point parameter to taking three distinct major/minor/revision integer parameters, as
+ * some edge cases caused incorrect parsing of the input float into the final integer BCD encoded value.
+ *
+ * <b>Non-USB Library Components</b>
+ * - The \c ATTR_NEVER_INLINE macro, erroneously introduced in a previous release has been removed, as it duplicates the existing \c ATTR_NO_INLINE macro.
+ *
+ * <b>Build System</b>
+ * - The default configuration file for Doxygen is now "doxyfile" rather than "Doxygen.conf", to conform to the Doxygen project's own default file name.
+ * Set \c DOXYGEN_CONF to override the new default file name.
+ *
+ * \section Sec_Migration130901 Migrating from 130303 to 130901
+ * <b>Non-USB Library Components</b>
+ * - The Board Dataflash \c Dataflash_Init() function now automatically configures the appropriate communication interface.
+ *
+ * \section Sec_Migration130303 Migrating from 120730 to 130303
+ * <b>Device Mode</b>
+ * - The \ref HID_KEYBOARD_LED_KANA macro was previously misspelled as \c HID_KEYBOARD_LED_KATANA, and had an incorrect value. User applications requiring this
+ * constant should use the new name, and remove any workarounds for the previously incorrect macro definition.
+ * - The \c HID_KEYBOARD_SC_EQUAL_SIGN macro has been renamed to \ref HID_KEYBOARD_SC_KEYPAD_EQUAL_SIGN, and the previous definition of
+ * \c HID_KEYBOARD_SC_KEYPAD_EQUAL_SIGN has been renamed \ref HID_KEYBOARD_SC_KEYPAD_EQUAL_SIGN_AS400 to conform to the definitions in the HID specification.
+ *
+ * <b>Host Mode</b>
+ * - The \ref HID_KEYBOARD_LED_KANA macro was previously misspelled as \c HID_KEYBOARD_LED_KATANA, and had an incorrect value. User applications requiring this
+ * constant should use the new name, and remove any workarounds for the previously incorrect macro definition.
+ * - The \c HID_KEYBOARD_SC_EQUAL_SIGN macro has been renamed to \ref HID_KEYBOARD_SC_KEYPAD_EQUAL_SIGN, and the previous definition of
+ * \c HID_KEYBOARD_SC_KEYPAD_EQUAL_SIGN has been renamed \ref HID_KEYBOARD_SC_KEYPAD_EQUAL_SIGN_AS400 to conform to the definitions in the HID specification.
+ *
+ * \section Sec_Migration120730 Migrating from 120219 to 120730
+ * <b>Device Mode</b>
+ * - The device mode Audio Class driver now requires an additional configuration parameter, the Audio Control interface index. Existing applications should
+ * be adjusted to specify the additional configuration parameter.
+ * - The HID_DESCRIPTOR_JOYSTICK() macro no longer takes a variable number of axis as a parameter, due to OS incompatibilities; this macro now uses a fixed
+ * 3 axis of data. User applications should update their calls to this macro and their report structures to suit a fixed 3-axis joystick report. If a user
+ * application requires more than 3 axis' of data, a custom report descriptor will need to be constructed by hand.
+ * - The \ref Endpoint_ConfigureEndpoint() function no longer takes in masks for the banks and direction; the number of banks is now an integer argument, and
+ * the direction is obtained from the full endpoint address within the device. Applications calling Endpoint_ConfigureEndpoint() should update their API
+ * call to use a full endpoint address (including ENDPOINT_DIR_IN or ENDPOINT_DIR_OUT direction in the MSB of the endpoint address) and an integer number
+ * of banks.
+ * - All endpoint functions now operate on full endpoint addresses within the device, rather than a directionless endpoint index. Applications should update
+ * their API calls to use full endpoint addresses when required within the device.
+ * - All device mode class drivers have been updated to use a new unified endpoint description structure for all endpoints; existing applications will need
+ * to update their class driver struct instantiation to match the new scheme (see \ref USB_Endpoint_Table_t).
+ * - The \c ENDPOINT_BANKS_SUPPORTED() and \c ENDPOINT_MAX_ENDPOINT_SIZE() macros have been removed, as these do not function correctly with the new addressing
+ * scheme for the endpoint APIs. Please refer to the target device's datasheet for the maximum bank size of each endpoint.
+ * - The MIDI class driver \ref MIDI_EventPacket_t event packet no longer contains separate \c CableIndex and \c Command entries; these have been combined
+ * into a single \c Event element which can be constructed using the new macro \ref MIDI_EVENT(). Existing applications should use the new macro and structure
+ * element name.
+ *
+ * <b>Host Mode</b>
+ * - The Android Accessory Host class driver property strings are now a array of \c char* rather than a struct of named pointers. Existing applications
+ * should use C99 Designated Initializers with the property string indexes located in \ref AOA_Strings_t instead.
+ * - The \ref Pipe_ConfigurePipe() function no longer takes in masks for the banks and token; the number of banks is now an integer argument, and the token
+ * is now inferred from the full pipe address within the device, and the pipe type. Applications calling Pipe_ConfigurePipe() should update their API
+ * call to use a full pipe address (including PIPE_DIR_IN or PIPE_DIR_OUT direction in the MSB of the pipe address) and an integer number of banks.
+ * - All pipe functions now operate on full pipe addresses within the device, rather than a directionless pipe index. Applications should update their API
+ * calls to use full pipe addresses when required within the device.
+ * - All host mode class drivers have been updated to use a new unified pipe description structure for all pipes; existing applications will need to update
+ * their class driver struct instantiation to match the new scheme (see \ref USB_Pipe_Table_t).
+ * - The MIDI class driver \ref MIDI_EventPacket_t event packet no longer contains seperate \c CableIndex and \c Command entries; these have been combined
+ * into a single \c Event element which can be constructed using the new macro \ref MIDI_EVENT(). Existing applications should use the new macro and structure
+ * element name.
+ * - The library "LUFA/Drivers/USB/Core/ConfigDescriptor.c" source file has been renamed "LUFA/Drivers/USB/Core/ConfigDescriptors.c" as this was clashing with
+ * files in some low level host mode demo applications, preventing parallel project builds. If you are referencing the project source files directly instead
+ * of using the makefile module names, you will need to adjust your project makefile.
+ *
+ * \section Sec_Migration120219 Migrating from 111009 to 120219
+ * <b>USB Core</b>
+ * - The HID_KEYBOARD_MODIFER_* macros in the HID class driver have been corrected to HID_KEYBOARD_MODIFIER_* (note the spelling of "modifier").
+ * Existing applications should switch over to the correctly spelled macro names.
+ * - The names of the USB Device and USB Host class driver files have changed; a new "ClassDevice" and "ClassHost" postfix has been added to the
+ * respective class driver files. Projects referencing the class driver source files by filename rather than the LUFA_SRC_USBCLASS makefile
+ * variable should append these postfixes to the source file names. Projects including the USB class driver dispatch headers directly should either
+ * switch to including the main USB driver header instead, or use the updated header filenames.
+ * - The USB_CONFIG_ATTR_BUSPOWERED constant has been renamed to USB_CONFIG_ATTR_RESERVED, as this was misnamed. All devices must set this bit in
+ * the Configuration descriptor's attributes field. As all devices are assumed to be bus-powered unless stated otherwise with the
+ * USB_CONFIG_ATTR_SELFPOWERED flag a replacement constant for bus powered devices is not provided.
+ *
+ * <b>Device Mode</b>
+ * - The device mode Audio class driver now requires a new user application callback, \ref CALLBACK_Audio_Device_GetSetInterfaceProperty().
+ * Existing applications must implement this new callback, however if no audio entities are defined in the audio device's descriptors,
+ * this function may be hard-coded to always return false for previous behaviour to be retained.
+ *
+ * \section Sec_Migration111009 Migrating from 110528 to 111009
+ * <b>Non-USB Library Components</b>
+ * - The \c JTAG_DEBUG_ASSERT() macro has been renamed \ref JTAG_ASSERT() to be consistent with \ref STDOUT_ASSERT().
+ *
+ * <b>USB Core</b>
+ * - By default, unordered Endpoint and Pipe configuration is now allowed once again, via the previous workaround of
+ * reconfiguring all Endpoints/Pipes in order each time a new Endpoint/Pipe is created. To minimize the compiled program
+ * size, the new \c ORDERED_EP_CONFIG compile time option may be defined in the project makefile to restrict the ordering
+ * in exchange for a smaller compiled binary size.
+ * - The previous \c F_CLOCK symbol, required in the project makefile, has been renamed to \c F_USB. This is due to the previous name
+ * being far too generic for use in future architecture ports, where multiple clock domains are used.
+ *
+ * <b>Device Mode</b>
+ * - The Endpoint stream functions now all require a \c BytesProcessed parameter instead of the previous callback parameter.
+ * This should be set to \c NULL to retain previous behaviour of the functions, or point to a location where the number of bytes
+ * processed in the current transaction can be stored. If the \c BytesProcessed parameter is non \c NULL, each time the endpoint
+ * bank becomes full and the packet is sent, the routine will exit with the new \ref ENDPOINT_RWSTREAM_IncompleteTransfer
+ * error code to allow the user application to determine when to send the next chunk of data.
+ * - The \ref CDC_Device_SendString() function now expects a null terminated string instead of an explicit length. Existing code
+ * should use the new \ref CDC_Device_SendData() function, or remove the length parameter from the function call.
+ * - The \c Endpoint_ResetFIFO() function has been renamed to \ref Endpoint_ResetEndpoint(), to make the API function names more
+ * consistent. Existing applications using the old function name should simply replace it with a call to the new function name.
+ * - The \c Endpoint_*_Byte() functions have been renamed Endpoint_*_8() to ensure they are correct across all architectures. Existing
+ * code using these functions should replace the previous function names with the new function names.
+ * - The \c Endpoint_*_Word() functions have been renamed Endpoint_*_16() to ensure they are correct across all architectures. Existing
+ * code using these functions should replace the previous function names with the new function names.
+ * - The \c Endpoint_*_DWord() functions have been renamed Endpoint_*_32() to ensure they are correct across all architectures. Existing
+ * code using these functions should replace the previous function names with the new function names.
+ * - The Device mode RNDIS class driver no longer stores the incoming and outgoing packets in the class driver instance; the user is
+ * now expected to manually define a storage location for the packet data. Packets must now be sent and received manually via a call
+ * to \ref RNDIS_Device_ReadPacket() and/or \ref RNDIS_Device_SendPacket().
+ * - The definition of the Audio class \ref USB_Audio_Descriptor_Format_t has been altered, to remove the fixed singular
+ * audio sample rate in the descriptor definition, and to rename the \c SampleFrequencyType to the more appropriate
+ * \c TotalDiscreteSampleRates. Existing applications will need to add an array of \ref USB_Audio_SampleFreq_t elements
+ * immediately following any \ref USB_Audio_Descriptor_Format_t descriptors, and insert the appropriate sampling rates
+ * supported by the device, as well as rename the descriptor elements to match the updated element names.
+ * - The device mode Audio class driver now requires a new user application callback, \ref CALLBACK_Audio_Device_GetSetEndpointProperty().
+ * Existing applications must implement this new callback, however if multiple sample rates or pitch control is not used,
+ * this function may be hard-coded to always return false for previous behaviour to be retained.
+ * - The \c USB_ConfigurationNumber, \c USB_RemoteWakeupEnabled and \c USB_CurrentlySelfPowered globals have been renamed to
+ * \ref USB_Device_ConfigurationNumber, \ref USB_Device_RemoteWakeupEnabled and \ref USB_Device_CurrentlySelfPowered to clearly indicate
+ * the USB mode they relate to. Existing applications using these variables should rename all references to the previous names.
+ * - The \c ENDPOINT_DESCRIPTOR_DIR_IN and \c ENDPOINT_DESCRIPTOR_DIR_OUT macros have now been replaced by \ref ENDPOINT_DIR_IN and
+ * \ref ENDPOINT_DIR_OUT to improve code clarity.
+ * - The \ref HID_DESCRIPTOR_JOYSTICK() macro now takes an additional (first) parameter indicating the number of axis in the joystick.
+ *
+ * <b>Host Mode</b>
+ * - The Pipe stream functions now all require a \c BytesProcessed parameter instead of the previous callback parameter.
+ * This should be set to \c NULL to retain previous behaviour of the functions, or point to a location where the number of bytes
+ * processed in the current transaction can be stored. If the BytesProcessed parameter is non \c NULL, each time the pipe
+ * bank becomes full and the packet is sent, the routine will exit with the new \ref PIPE_RWSTREAM_IncompleteTransfer
+ * error code to allow the user application to determine when to send the next chunk of data.
+ * - The \ref PRNT_Host_SendString() and \ref CDC_Host_SendString() functions now expect a null terminated string instead of an explicit
+ * length. Existing code should use the new \ref PRNT_Host_SendData() and \ref CDC_Host_SendData() functions, or remove the
+ * length parameter from the function call.
+ * - The \c Pipe_ClearErrorFlags() function has been removed, as the pipe error flags are now automatically cleared when the
+ * \ref Pipe_ClearError() function is called.
+ * - The \c Pipe_*_Byte() functions have been renamed Pipe_*_8() to ensure they are correct across all architectures. Existing code using
+ * these functions should replace the previous function names with the new function names.
+ * - The \c Pipe_*_Word() functions have been renamed Pipe_*_16() to ensure they are correct across all architectures. Existing code using
+ * these functions should replace the previous function names with the new function names.
+ * - The \c Pipe_*_DWord() functions have been renamed Pipe_*_32() to ensure they are correct across all architectures. Existing code using
+ * these functions should replace the previous function names with the new function names.
+ * - The \c USB_Host_ClearPipeStall() function has been renamed to USB_Host_ClearEndpointStall(), as it operates on a full endpoint address
+ * within the attached device and not a pipe within the host. Existing code using the old function name should update the function calls and
+ * check for correct usage.
+ *
+ * \section Sec_Migration101122 Migrating from 100807 to 101122
+ * <b>USB Core</b>
+ * - A new USB driver source file, \c Drivers/USB/HighLevel/EndpointStream.c now exists. This source file should be added
+ * to all project makefiles using the USB driver of LUFA, or the makefile should be updated to use the new module source
+ * variables.
+ * - A new USB driver source file, \c Drivers/USB/HighLevel/PipeStream.c now exists. This source file should be added to all
+ * project makefiles using the USB driver of LUFA, or the makefile should be updated to use the new module source variables.
+ * - The \c EVENT_USB_InitFailure() event has been removed, as the \ref USB_Init() function will no longer fail; if not USB mode is
+ * specified, the controller will default to UID selection mode.
+ * - The USB mode specifier constants have been moved into a new enum and renamed. Existing projects should use the equivalent
+ * value in the new \ref USB_Modes_t enum.
+ * - All class driver headers are now included as part of the standard \c LUFA/Drivers/USB/USB.h master dispatch header, and should
+ * no longer be included separately. Class driver module source files must still be added as a separate module in the project's
+ * makefile if used.
+ *
+ * <b>Device Mode</b>
+ * - Endpoints MUST be allocated in ascending order to ensure that bank corruption does not occur. Ensure that your user application
+ * allocated endpoints in ascending order - or if your application uses the USB device mode class drivers, ensure that each instance's
+ * endpoint indexes are not overlapped with other interface's endpoints.
+ * - The signature for the \ref CALLBACK_USB_GetDescriptor() callback has changed, the \c void** \c const \c DescriptorAddress parameter is
+ * now \c const \c void** \c const \c DescriptorAddress. Existing applications should update their callback signatures to match this, and
+ * eliminate any casting of descriptor pointers to a non \c const pointer.
+ * - The names of the class specific descriptor type defines in the USB Class drivers have changed - refer to the driver documentation
+ * for each class driver for the new class specific descriptor type names.
+ * - The \c ENDPOINT_DOUBLEBANK_SUPPORTED() macro is has been renamed \c ENDPOINT_BANKS_SUPPORTED() and now returns the total number of
+ * banks supported by the given endpoint. Existing code should switch to the new naming scheme, and test that the return value of the
+ * macro is equal to or greater than 2 to regain the previous functionality.
+ * - The \c EVENT_USB_Device_UnhandledControlRequest() event is now named \ref EVENT_USB_Device_ControlRequest() and fires before (not after)
+ * the internal library event handlers. Existing code should rename the event handlers in the user application to match the new event
+ * name, and should ensure that the new execution order does not affect the application's operation.
+ *
+ * <b>Host Mode</b>
+ * - Pipes MUST be allocated in ascending order to ensure that bank corruption does not occur. Ensure that your user application
+ * allocated pipes in ascending order - or if your application uses the USB host mode class drivers, ensure that each instance's
+ * pipe indexes are not overlapped with other interface's pipes.
+ * - The \c PRNT_Host_SendData() function has been renamed to \ref PRNT_Host_SendString(). Existing applications should simply
+ * replace all references to the obsolete function name with the new function name.
+ * - The names of the class specific descriptor type defines in the USB Class drivers have changed - refer to the driver documentation
+ * for each class driver for the new class specific descriptor type names.
+ * - The Still Image Host class' function prefix has been changed from \c SImage_ to \c SI_, to remain consistent with the rest of the
+ * driver's enums, type defines and constants.
+ *
+ * \section Sec_Migration100807 Migrating from 100513 to 100807
+ *
+ * <b>Non-USB Library Components</b>
+ * - The Dataflash board driver stub file has changed, as dataflash functions previously located in the internal
+ * Dataflash driver of the library have now been moved to the individual board files. Existing drivers can
+ * copy-paste the new functions from the board Dataflash stub driver.
+ *
+ * <b>USB Core</b>
+ * - A new USB driver source file, \c Drivers/USB/LowLevel/Device.c now exists. This source file should be added to all project
+ * makefiles using the USB driver of LUFA, or the makefile should be updated to use the new module source variables.
+ * - The \c Drivers/USB/LowLevel/DevChapter9.c source file has moved to \c Drivers/USB/HighLevel/DeviceStandardReq.c - this should
+ * be updated in all project makefiles, or the makefile should be updated to use the new module source variables.
+ * - The \c Drivers/USB/LowLevel/HostChapter9.h source file has moved to \c Drivers/USB/HighLevel/HostStandardReq.c - this should
+ * be updated in all project makefiles, or the makefile should be updated to use the new module source variables.
+ * - The \c Drivers/USB/LowLevel/LowLevel.c source file has moved to \c Drivers/LowLevel/USBController.c - this should be updated
+ * in all project makefiles, or the makefile should be updated to use the new module source variables.
+ *
+ * <b>Device Mode</b>
+ * - The \c USB_Device_IsRemoteWakeupSent() macro has been removed, as the remote wakeup request is now fully handled by the
+ * enhanced \ref USB_Device_SendRemoteWakeup() function. Existing code may now discard any checks to \c USB_Device_IsRemoteWakeupSent().
+ * - The \c USB_Device_IsUSBSuspended() macro has been removed, as it is obsolete. Existing code should compare \ref USB_DeviceState
+ * to see if it the device is in the \ref DEVICE_STATE_Suspended state instead.
+ * - The \ref CDC_Device_ReceiveByte() function has changed, and now returns a signed 16-bit integer, with -1 indicating no data was
+ * received. This allows for more efficient coding, as a call to \ref CDC_Device_BytesReceived() is no longer needed if the exact
+ * number of queued bytes received is not needed.
+ *
+ * <b>Host Mode</b>
+ * - The \ref CDC_Host_ReceiveByte() function has changed, and now returns a signed 16-bit integer, with -1 indicating no data was
+ * received. This allows for more efficient coding, as a call to \ref CDC_Host_BytesReceived() is no longer needed if the exact
+ * number of queued bytes received is not needed.
+ * - The \ref CDC_Host_USBTask() now calls \ref CDC_Host_Flush() automatically, flushing any queued data to the attached device. Manual
+ * flushing of the interface is no longer needed if the flushes should be in sync with calls to \ref CDC_Host_USBTask().
+ *
+ * \section Sec_Migration100513 Migrating from 100219 to 100513
+ *
+ * <b>Non-USB Library Components</b>
+ * - The \ref TWI_StartTransmission() function now takes in a timeout period, expressed in milliseconds, within which the addressed
+ * device must respond or the function will abort.
+ *
+ * <b>Device Mode</b>
+ * - The \ref USB_Init() function no longer calls \c sei() to enable global interrupts, as the user application may need
+ * to perform other initialization before it is ready to handle global interrupts. The user application is now responsible
+ * for enabling global interrupts before or shortly after calling \ref USB_Init() to ensure that the enumeration process
+ * functions correctly.
+ * - The \c USBInterrupt.c USB driver source file has been relocated from \c LUFA/Drivers/USB/HighLevel/ to \c LUFA/Drivers/USB/LowLevel.
+ * Projects must update their makefile SRC values accordingly.
+ * - The HID Device Class driver's function signature for the \ref CALLBACK_HID_Device_ProcessHIDReport() function has been changed, to
+ * allow for a new \c ReportType parameter. This new parameter must be added in all user applications using the Device mode HID Class
+ * Driver, but may be ignored unless Host-to-Device FEATURE HID reports are used.
+ *
+ * <b>Host Mode</b>
+ * - The \ref USB_Init() function no longer calls \c sei() to enable global interrupts, as the user application may need
+ * to perform other initialization before it is ready to handle global interrupts. The user application is now responsible
+ * for enabling global interrupts before or shortly after calling \ref USB_Init() to ensure that the enumeration process
+ * functions correctly.
+ * - The \c USBInterrupt.c USB driver source file has been relocated from \c LUFA/Drivers/USB/HighLevel/ to \c LUFA/Drivers/USB/LowLevel.
+ * Projects must update their makefile \c SRC values accordingly.
+ * - The HID Host Class driver's function signature for the \ref HID_Host_SendReportByID() function has been changed, to allow for a new
+ * ReportType parameter. Existing calls to this function should substitute \c REPORT_ITEM_TYPE_Out as this parameter's value.
+ *
+ * \section Sec_Migration100219 Migrating from 091223 to 100219
+ *
+ * <b>Non-USB Library Components</b>
+ * - Due to some ADC channels not being identical to their ADC MUX selection masks for single-ended conversions on some AVR models,
+ * the ADC driver now has explicit masks for each of the standard ADC channels (see \ref Group_ADC). These masks should be used
+ * when calling the ADC functions to ensure proper operation across all AVR models. Note that the \ref ADC_SetupChannel() function
+ * is an exception, and should always be called with a channel number rather than a channel mask.
+ *
+ * <b>Host Mode</b>
+ * - The MIDI Host Class driver send and receive routines now operate on packed events, where multiple MIDI events may be
+ * packed into a single USB packet. This means that the sending of MIDI events will now be delayed until the MIDI send
+ * pipe bank is full. To override this new behaviour and revert to the previous behaviour, the user application may manually
+ * flush the queued event(s) to the device by calling \ref MIDI_Host_Flush().
+ * - The \ref Pipe_IsEndpointBound() function now takes the endpoint's direction into account, by checking if the MSB of the endpoint's address
+ * is set to denote IN endpoints. If the previous functionality where the direction is to be discounted is required, mask the endpoint
+ * address against the \ref PIPE_EPNUM_MASK token before calling \ref Pipe_IsEndpointBound().
+ *
+ * <b>Device Mode</b>
+ * - The MIDI Device Class driver send and receive routines now operate on packed events, where multiple MIDI events may be
+ * packed into a single USB packet. This means that the sending of MIDI events will now be delayed until the MIDI send
+ * endpoint bank is full. To override this new behaviour and revert to the previous behaviour, the user application may manually
+ * flush the queued event(s) to the host by calling \ref MIDI_Device_Flush().
+ *
+ * \section Sec_Migration091223 Migrating from 091122 to 091223
+ *
+ * <b>Host Mode</b>
+ * - The Still Image Host Class driver \ref SI_Host_USBTask() and \ref SI_Host_ConfigurePipes() functions were misnamed, and are
+ * now named \c SImage_Host_USBTask() and \c SImage_Host_ConfigurePipes() respectively.
+ * - The \c HOST_SENDCONTROL_DeviceDisconnect enum value has been renamed to \ref HOST_SENDCONTROL_DeviceDisconnected to be in
+ * line with the rest of the library error codes.
+ * - The HID Parser item usages no longer contain separate minimum and maximum values, as this was a violation of the HID
+ * specification. Instead, the values are distributed evenly across each item as its usage value, to ensure that all items
+ * can be distinguished from one-another.
+ *
+ * <b>Device Mode</b>
+ * - The \ref CALLBACK_HID_Device_CreateHIDReport() HID Device Class driver callback now has a new \c ReportType parameter to
+ * indicate the report type to generate. Existing applications may simply add and ignore this additional parameter.
+ *
+ * \section Sec_Migration091122 Migrating from 090924 to 091122
+ *
+ * <b>Host Mode</b>
+ * - The \c HID_PARSE_UsageStackOverflow HID parser error constant is now named \ref HID_PARSE_UsageListOverflow
+ * - The \ref CALLBACK_HIDParser_FilterHIDReportItem() HID Parser callback now passes a complete \ref HID_ReportItem_t to the
+ * user application, instead of just its attributes.
+ * - The \c USB_GetDeviceConfigDescriptor() function was incorrectly named and is now called \ref USB_Host_GetDeviceConfigDescriptor().
+ *
+ * \section Sec_Migration090924 Migrating from 090810 to 090924
+ *
+ * <b>Non-USB Library Components</b>
+ * - The \c ADC_Off() function has been renamed to \c ADC_ShutDown() to be consistent with the rest of the library.
+ * - The \ref SPI_Init() routine's parameters have changed, so that the clock polarity and data sampling modes can be set. See
+ * the \ref SPI_Init() function documentation for more details
+ * - The \ref Dataflash_Init() routine no longer initializes the SPI bus - the SPI bus should be initialized manually via a
+ * call to \ref SPI_Init() before using the Dataflash driver
+ *
+ * <b>Host Mode</b>
+ * - The \c USB_GetDeviceConfigDescriptor() function's parameters and behaviour has changed; the user is required to
+ * preallocate the largest allowable buffer, and pass the size of the buffer to the function. This allows for a single
+ * call to the function to retrieve, size check and validate the Configuration Descriptor rather than having the user
+ * application perform these intermediary steps.
+ * - The HID report parser now requires a mandatory callback in the user code, to filter only the items the application
+ * is interested in into the processed HID report item structure to save RAM. See \ref CALLBACK_HIDParser_FilterHIDReportItem().
+ * - The HID report parser now always parses FEATURE and always ignores constant-data items - the \c HID_ENABLE_FEATURE_PROCESSING
+ * and \c HID_INCLUDE_CONSTANT_DATA_ITEMS compile time tokens now have no effect.
+ * - The \c USE_NONSTANDARD_DESCRIPTOR_NAMES compile time token has been removed - there are now separate \c USB_Descriptor_*
+ * and \c USB_StdDescriptor_* structures for both the LUFA and standardized element naming conventions so that both may be used in
+ * the one project. For existing projects using the standardized names, change all code to use the \c USB_StdDescriptor_* variants.
+ *
+ * <b>Device Mode</b>
+ * - The \c USE_NONSTANDARD_DESCRIPTOR_NAMES compile time token has been removed - there are now separate \c USB_Descriptor_*
+ * and \c USB_StdDescriptor_* structures for both the LUFA and standardized element naming conventions so that both may be used in
+ * the one project. For existing projects using the standardized names, change all code to use the \c USB_StdDescriptor_* variants.
+ *
+ * \section Sec_Migration090810 Migrating from 090605 to 090810
+ *
+ * <b>All</b>
+ * - The "Simple Scheduler" has been <i>deprecated</i>, as it was little more than an abstracted loop and caused much confusion.
+ * User applications using the scheduler should switch to regular loops instead. The scheduler code will be removed in a future
+ * release.
+ * - The "Dynamic Memory Block Allocator" has been removed, as it was unused in (and unrelated to) the LUFA library and never
+ * used in user applications.
+ *
+ * <b>Non-USB Library Components</b>
+ * - The \c ATTR_NOINLINE function attribute macro has been renamed to \ref ATTR_NO_INLINE to be in line with the rest of the function attribute
+ * macro names.
+ *
+ * <b>Library Demos</b>
+ * - Most demos now have a corresponding Class Driver implementation, which uses the new internal library class drivers for the standard
+ * USB classes. This allows for more rapid device and host development, and so should be used in preference to the low level APIs where
+ * possible so that fixes to the class drivers propagate to all applications which use them automatically with each new LUFA release.
+ *
+ * <b>Host Mode</b>
+ * - The \c HIDParser.c module has moved from \c LUFA/Drivers/USB/Class/ to \c LUFA/Drivers/USB/Class/Host/.
+ * - The \c USB_GetDeviceConfigDescriptor() function now requires the desired configuration index within the device as its first
+ * parameter, to add support for multi-configuration devices. Existing code should use a configuration index of 1 to indicate the
+ * first configuration descriptor within the device.
+ * - The non-standard "Ready" host state has been removed. Existing \ref HOST_STATE_Configured code should be moved to the end of
+ * the existing \ref HOST_STATE_Addressed state, and the existing HOST_STATE_Ready state code should be moved to the \ref HOST_STATE_Configured
+ * state.
+ * - The \c USB_IsConnected global has been removed, as it is too vague for general use. Test \ref USB_HostState explicitly to ensure the host is
+ * in the desired state instead.
+ * - The USB event names have been changed and their firing conditions changed to properly separate out Host mode events from Device mode
+ * events. See the \ref Group_Events page for details on the new event names and firing conditions.
+ *
+ * <b>Device Mode</b>
+ * - The \ref CALLBACK_USB_GetDescriptor() function now takes an extra parameter to specify the descriptor's memory space so that
+ * descriptors in mixed memory spaces can be used. The previous functionality can be returned by defining the \c USE_FLASH_DESCRIPTORS
+ * token in the project makefile to fix all descriptors into FLASH space and remove the extra function parameter.
+ * - The \c USB_IsSuspended global has been removed - test \ref USB_DeviceState against \ref DEVICE_STATE_Suspended instead.
+ * - The \c USB_IsConnected global has been removed, as it is too vague for general use. Test \ref USB_DeviceState explicitly to ensure the device
+ * is in the desired state instead.
+ * - The VBUS events have been removed, as they are already exposed to the user via the \c USB_Connect and \c USB_Disconnect events.
+ * - The USB event names have been changed and their firing conditions changed to properly separate out Host mode events from Device mode
+ * events. See the \ref Group_Events page for details on the new event names and firing conditions.
+ *
+ * \section Sec_Migration090605 Migrating from 090510 to 090605
+ *
+ * <b>Device Mode</b>
+ * - Support for non-control data endpoint interrupts has been dropped due to many issues in the implementation. All existing
+ * projects using interrupts on non-control endpoints should switch to polling. For control interrupts, the library can
+ * manage the control endpoint via interrupts automatically by compiling with the \c INTERRUPT_CONTROL_ENDPOINT token defined.
+ * - The \c DESCRIPTOR_ADDRESS() macro has been removed. User applications should use normal casts to obtain a descriptor's memory
+ * address.
+ * - The library events system has been rewritten, so that all macros have been removed to allow for clearer user code. See
+ * \ref Group_Events for new API details.
+ * - The \c STREAM_CALLBACK() macro has been removed. User applications should replace all instances of the macro with regular
+ * function signatures of a function accepting no arguments and returning a \c uint8_t value.
+ * - The \c Event_DeviceError() event no longer exists, as its sole caller (unlinked \c USB_GetDescriptor() function) now produces a
+ * compilation error rather than a runtime error. The \c StdDescriptors.c file no longer exists as a result, and should be removed
+ * from project makefiles.
+ * - The \c USB_GetDescriptor() function has been renamed to \ref CALLBACK_USB_GetDescriptor() to be in line with the new \c CALLBACK_
+ * function prefixes for functions which <i>must</i> be implemented in the user application.
+ *
+ * <b>Host Mode</b>
+ * - Support for non-control data pipe interrupts has been dropped due to many issues in the implementation. All existing
+ * projects using interrupts on non-control pipes should switch to polling.
+ * - The library events system has been rewritten, so that all macros have been removed to allow for clearer user code. See
+ * \ref Group_Events for new API details.
+ * - The \c STREAM_CALLBACK() macro has been removed. User applications should replace all instances of the macro with regular
+ * function signatures of a function accepting no arguments and returning a \c uint8_t value.
+ * - The \c DESCRIPTOR_COMPARATOR() macro has been removed. User applications should replace all instances of the macro with
+ * regular function signatures of a function accepting a void pointer to the descriptor to test, and returning a \c uint8_t value.
+ *
+ * \section Sec_Migration090510 Migrating from 090401 to 090510
+ *
+ * <b>All</b>
+ * - The \c ButtLoadTag.h header has been removed, as it was never used for its intended purpose. Projects should either remove all
+ * \c BUTTLOADTAG() elements, or download and extract \c ButtLoadTag.h header from the ButtLoad project.
+ * - The \c Drivers/AT90USBXXX/ directory has been renamed to \c Drivers/Peripheral/.
+ * - The \c Serial_Stream driver has been renamed to \c SerialStream to remain consistent with the rest of the library naming scheme.
+ * - The HWB driver has changed to the \c Buttons driver. See the board Buttons driver documentation for the new API.
+ *
+ * <b>Dual Role Mode</b>
+ * - The \c USB_PowerOnFail event has been renamed to \c USB_InitFailure.
+ * - The functions in \c OTG.h have been renamed to remain more consistent with the library API. See the functions in \c OTG.h for more
+ * details.
+ *
+ * <b>Device Mode</b>
+ * - The \c Endpoint_ClearCurrentBank() macro has been removed, and is now replaced with the \ref Endpoint_ClearIN(), \ref Endpoint_ClearOUT()
+ * macros. See \c Endpoint.h documentation for more details on the new endpoint management macros.
+ * - The \c Endpoint_ReadWriteAllowed() macro has been renamed to \ref Endpoint_IsReadWriteAllowed() to be more consistent with the rest of
+ * the API naming scheme.
+ * - The \c Endpoint_IsSetupINReady() and \c Endpoint_IsSetupOUTReceived() macros have been renamed to \ref Endpoint_IsINReady() and
+ * \ref Endpoint_IsOUTReceived() respectively.
+ * - The \c Endpoint_IsSetupReceived() macro has been renamed to \ref Endpoint_IsSETUPReceived().
+ * - The \c Endpoint_ClearSetupReceived() macro has been renamed to \ref Endpoint_ClearSETUP().
+ * - All endpoint read/write/discard aliases which did not have an explicitly endianness specifier (such as \c Endpoint_Read_Word()) have
+ * been removed for clarity. Existing projects should use the \c _LE suffix on such calls to use the explicit Little Endian versions.
+ * - The \c USB_UnhandledControlPacket event no longer has any parameters. User code should no longer attempt to read in the remainder of
+ * the Control Request header as all Control Request header data is now preloaded by the library and made available in the
+ * USB_ControlRequest structure.
+ * - The \c FEATURELESS_CONTROL_ONLY_DEVICE token has been renamed to \c CONTROL_ONLY_DEVICE.
+ * - The \c STATIC_ENDPOINT_CONFIGURATION is no longer applicable as the library will apply this optimization when appropriate automatically.
+ * - The values of the \ref Endpoint_Stream_RW_ErrorCodes_t and \ref Endpoint_ControlStream_RW_ErrorCodes_t enums have had the \c ERROR_ portion
+ * of their names removed.
+ *
+ * <b>Host Mode</b>
+ * - The \ref USB_Host_SendControlRequest() function no longer automatically selects the Control pipe (pipe 0) to allow it to be used on
+ * other control type pipes. Care should be taken to ensure that the Control pipe is always selected before the function is called
+ * in existing projects where the Control pipe is to be operated on.
+ * - The USB Host management task now saves and restores the currently selected pipe before and after the task runs. Projects no longer
+ * need to manage this manually when calling the USB management task.
+ * - The \c Pipe_ClearCurrentBank() macro has been removed, and is now replaced with the Pipe_ClearIN(), Pipe_ClearOUT() macros. See
+ * Pipe.h documentation for more details on the new pipe management macros.
+ * - The \c Pipe_ReadWriteAllowed() macro has been renamed to \ref Pipe_IsReadWriteAllowed() to be more consistent with the rest of the API
+ * naming scheme.
+ * - The \c Pipe_IsSetupINReceived() and \c Pipe_IsOutReady() macros have been renamed to \ref Pipe_IsINReceived() and \ref Pipe_IsOUTReady()
+ * respectively.
+ * - The new \ref Pipe_ClearSETUP() macro should be used to send SETUP transactions, rather than the previous \c Pipe_ClearSetupOUT() macro.
+ * - The \c Pipe_IsSetupSent() macro has been renamed to \ref Pipe_IsSETUPSent().
+ * - The \c Pipe_ClearSetupSent() macro is no longer applicable and should be removed.
+ * - All pipe read/write/discard aliases which did not have an explicitly endianness specifier (such as \c Pipe_Read_Word()) have
+ * been removed for clarity. Existing projects should use the \c _LE suffix on such calls to use the explicit Little Endian versions.
+ * - The \c Host_IsResetBusDone() macro has been renamed to \c Host_IsBusResetComplete().
+ * - The \c Pipe_Ignore_Word() and \c Pipe_Ignore_DWord() functions have been renamed to \c Pipe_Discard_Word() and \c Pipe_Discard_DWord()
+ * to remain consistent with the rest of the pipe API.
+ * - It is no longer needed to manually include the headers from \c LUFA/Drivers/USB/Class, as they are now included along with the rest
+ * of the USB headers when \c LUFA/Drivers/USB/USB.h is included.
+ * - Functions in the \c ConfigDescriptor.h header file no longer have \c Host_ as part of their names.
+ * - The \c ProcessHIDReport() has been renamed to \ref USB_ProcessHIDReport(), \c GetReportItemInfo() has been renamed to \ref USB_GetHIDReportItemInfo()
+ * and \c SetReportItemInfo() has been renamed to \ref USB_GetHIDReportItemInfo().
+ * - The values of the \ref DSearch_Return_ErrorCodes_t and \ref DSearch_Comp_Return_ErrorCodes_t enums have had their respective \c Descriptor_Search
+ * and \c Descriptor_Search_Comp prefixes changed to all caps.
+ * - The \c USB_HostRequest global has been renamed to \ref USB_ControlRequest, and is used in Device mode also. The \c USB_Host_Request_Header_t
+ * structure type has been renamed to \ref USB_Request_Header_t.
+ * - The values of the \ref Pipe_Stream_RW_ErrorCodes_t enum have had the \c ERROR_ portion of their names removed.
+ *
+ * \section Sec_Migration090401 Migrating from 090209 to 090401
+ *
+ * <b>All</b>
+ * - LUFA projects must now give the raw input clock frequency (before any prescaling) as a compile time constant \c F_USB,
+ * defined in the project makefile and passed to the compiler via the -D switch.
+ * - The makefile EEPROM programming targets for FLIP and dfu-programmer no longer program in the FLASH data in addition to the
+ * EEPROM data into the device. If both are to be programmed, both the EEPROM and FLASH programming targets must be called.
+ * - As the avr-libc macro has been corrected in recent avr-libc distributions, the \c SetSystemClockPrescaler() macro has been removed.
+ * Include \c <avr/power.h> and call \c clock_prescale_set(clock_div_1); instead on recent avr-libc distributions.
+ *
+ * <b>Library Demos</b>
+ * - The USBtoSerial demo now discards all data when not connected to a host, rather than buffering it for later transmission.
+ *
+ * <b>Non-USB Library Components</b>
+ * - The \c ATTR_ALWAYSINLINE function attribute macro has been renamed to \ref ATTR_ALWAYS_INLINE.
+ * - Custom board Dataflash drivers now require the implementation of \ref Dataflash_SelectChipFromPage() and \ref Dataflash_SendAddressBytes().
+ *
+ * <b>Device Mode</b>
+ * - The \c NO_CLEARSET_FEATURE_REQUEST compile time token has been renamed to \c FEATURELESS_CONTROL_ONLY_DEVICE, and its function expanded
+ * to also remove parts of the Get Status chapter 9 request to further reduce code usage. On all applications currently using the
+ * \c NO_CLEARSET_FEATURE_REQUEST compile time token, it can be replaced with the \c FEATURELESS_CONTROL_ONLY_DEVICE token with no further
+ * modifications required.
+ *
+ * \section Sec_Migration090209 Migrating from 081217 to 090209
+ *
+ * <b>Device Mode</b>
+ * - The \c ENDPOINT_MAX_ENDPOINTS constant has been renamed to the more appropriate name of \c ENDPOINT_TOTAL_ENDPOINTS.
+ * - The \c USB_STREAM_TIMEOUT_MS stream timeout default period has been extended to 100ms. This can be overridden in the user
+ * makefile if desired to restore the previous 50ms timeout.
+ *
+ * <b>Host Mode</b>
+ * - The \c PIPE_MAX_ENDPOINTS constant has been renamed to the more appropriate name of \c PIPE_TOTAL_ENDPOINTS.
+ * - The \c USB_STREAM_TIMEOUT_MS stream timeout default period has been extended to 100ms. This can be overridden in the user
+ * makefile if desired to restore the previous 50ms timeout.
+ * - The \c USB_DeviceEnumerationFailed event now contains a second \c SubErrorCode parameter, giving the error code of the function
+ * which failed.
+ * - The \c HID_PARSE_Sucessful enum member constant name has been corrected to \ref HID_PARSE_Successful.
+ *
+ * <b>Non-USB Library Components</b>
+ * - The previous \c SPI_SendByte() functionality is now located in \ref SPI_TransferByte(). \ref SPI_SendByte() now discards the return byte
+ * for speed, to compliment the new \ref SPI_ReceiveByte() function. If bidirectional SPI transfers are required, calls to \ref SPI_SendByte()
+ * should be changed to \ref SPI_TransferByte().
+ * - The serial driver now sets the Tx line as an output explicitly, and enables the pull-up of the Rx line.
+ * - The \ref Serial_Init() and \c SerialStream_Init() functions now take a second \c DoubleSpeed parameter, which indicates if the USART
+ * should be initialized in double speed mode - useful in some circumstances for attaining baud rates not usually possible at the given AVR
+ * clock speed.
+ *
+ * \section Sec_Migration171208 Migrating from V1.5.3 to 081217
+ *
+ * <b>All</b>
+ * - The MyUSB project name has been changed to LUFA (Lightweight Framework for USB AVRs). All references to MyUSB, including macro names,
+ * have been changed to LUFA.
+ *
+ * <b>Library Demos</b>
+ * - The ReconfigureUSART() routine in the USBtoSerial demo was not being called after new line encoding
+ * parameters were set by the host. Projects built on the USBtoSerial code should update to the latest version.
+ * - The HID Parser now supports multiple report (on a single endpoint) HID devices. The MouseHostWithParser and
+ * KeyboardHostWithPaser demos use the updated API functions to function correctly on such devices. Projects
+ * built on either "WithParser" demo should update to the latest code.
+ * - The RNDIS demo TCP stack has been modified so that connections can be properly closed. It is still not
+ * recommended that the MyUSB RNDIS demo TCP/IP stack be used for anything other than demonstration purposes,
+ * as it is neither a full nor a standards compliant implementation.
+ *
+ * <b>Non-USB Library Components</b>
+ * - The Serial_IsCharReceived() macro has been changed to the correct spelling of Serial_IsCharReceived() in Serial.h.
+ *
+ * <b>Device Mode</b>
+ * - The MANUAL_PLL_CONTROL compile time token has been removed, and replaced with a USB_OPT_MANUAL_PLL mask
+ * to be used in the Options parameter of the USB_Init() function.
+ * - Calling USB_Init() now forces a complete USB interface reset and enumeration, even if the USB interface is
+ * currently initialized.
+ * - Interrupts are now disabled when processing control requests, to avoid problems with interrupts causing the library
+ * or user request processing code to exceed the strict USB timing requirements on control transfers.
+ * - The USB Reset event now resets and disables all device endpoints. If user code depends on endpoints remaining configured
+ * after a Reset event, it should be altered to explicitly re-initialize all user endpoints.
+ * - The prototype for the GetDescriptor function has been changed, as the return value was redundant. The function now
+ * returns the size of the descriptor, rather than passing it back via a parameter, or returns NO_DESCRIPTOR if the specified
+ * descriptor does not exist.
+ * - The NO_DESCRIPTOR_STRING macro has been renamed NO_DESCRIPTOR, and is now also used as a possible return value for the
+ * GetDescriptor function.
+ *
+ * <b>Host Mode</b>
+ * - The MANUAL_PLL_CONTROL compile time token has been removed, and replaced with a USB_OPT_MANUAL_PLL mask
+ * to be used in the Options parameter of the USB_Init() function.
+ * - The HID report parser now supports multiple Report IDs. The HID report parser GetReportItemInfo() and
+ * SetReportItemInfo() routines now return a boolean, set if the requested report item was located in the
+ * current report. If sending a report to a multi-report device, the first byte of the report is automatically
+ * set to the report ID of the given report item.
+ * - Calling USB_Init() now forces a complete USB interface reset and enumeration, even if the USB interface is
+ * currently initialized.
+ *
+ * \section Sec_Migration152 Migrating from V1.5.2 to V1.5.3
+ *
+ * <b>Library Demos</b>
+ * - Previously, all demos contained a serial number string descriptor, filled with all zeros. A serial number
+ * string is required in Mass Storage devices, or devices which are to retain settings when moved between
+ * ports on a machine. As people were not changing the serial number value, this was causing conflicts and so
+ * the serial number descriptor has been removed from all but the Mass Storage demo, which requires it.
+ * - The AudioOut and AudioIn demos did not previously silence their endpoints when the host has deactivated
+ * them. Projects built upon either demo should upgrade to the latest code.
+ * - The FEATURE_ENDPOINT macro has been renamed FEATURE_ENDPOINT_HALT, and is now correctly documented.
+ * - The MassStoreHost demo contained errors which caused it to lock up randomly on certain devices. Projects built
+ * on the MassStoreDemo code should update to the latest version.
+ * - The Interrupt type endpoint in the CDC based demos previously had a polling interval of 0x02, which caused
+ * problems on some Linux systems. This has been changed to 0xFF, projects built on the CDC demos should upgrade
+ * to the latest code.
+ * - The HID keyboard and mouse demos were not previously boot mode compatible. To enable boot mode support, projects
+ * built on the keyboard or mouse demos (or derivatives) should upgrade to the latest code.
+ * - The Mass Storage demo was not previously standards compliant. Projects built on the Mass Storage demo should
+ * upgrade to the latest code.
+ * - The USART was not being reconfigured after the host sent new encoding settings in the USBtoSerial demo. This was
+ * previously discovered and fixed, but the change was lost. Projects built on the USBtoSerial demo should update
+ * to the latest code.
+ *
+ * <b>Device Mode</b>
+ * - The endpoint non-control stream functions now have a default timeout of 50ms between packets in the stream.
+ * If this timeout is exceeded, the function returns the new ENDPOINT_RWSTREAM_ERROR_Timeout error value. The
+ * timeout value can be overridden by defining the USB_STREAM_TIMEOUT_MS in the project makefile to the desired
+ * timeout duration in ms.
+ * - Rather than returning fixed values, the flags indicating if the device has Remote Wakeup currently enabled
+ * and/or is self-powered are now accessed and set through the new USB_RemoteWakeupEnabled and
+ * USB_CurrentlySelfPowered macros. See the DevChapter9.h documentation for more details.
+ * - All endpoint stream functions now require an extra Callback function parameter. Existing code may be updated
+ * to either supply NO_STREAM_CALLBACK as the extra parameter, or disable stream callbacks altogether by passing
+ * the token NO_STREAM_CALLBACKS to the compiler using the -D switch.
+ *
+ * <b>Host Mode</b>
+ * - The pipe non-control stream functions now have a default timeout of 50ms between packets in the stream.
+ * If this timeout is exceeded, the function returns the new PIPE_RWSTREAM_ERROR_Timeout error value. The
+ * timeout value can be overridden by defining the USB_STREAM_TIMEOUT_MS in the project makefile to the desired
+ * timeout duration in ms.
+ * - CollectionPath_t has been renamed to HID_CollectionPath_t to be more in line with the other HID parser structures.
+ * - All pipe stream functions now require an extra Callback function parameter. Existing code may be updated
+ * to either supply NO_STREAM_CALLBACK as the extra parameter, or disable stream callbacks altogether by passing
+ * the token NO_STREAM_CALLBACKS to the compiler using the -D switch.
+ *
+ * \section Sec_Migration151 Migrating from V1.5.1 to V1.5.2
+ *
+ * <b>Library Demos</b>
+ * - The RNDIS demo application has been updated so that it is functional on Linux under earlier implementations
+ * of the RNDIS specification, which had non-standard behaviour. Projects built upon the demo should upgrade
+ * to the latest code.
+ * - The DFU class bootloader has had several bugs corrected in this release. It is recommended that where
+ * possible any existing devices upgrade to the latest bootloader code.
+ *
+ * \section Sec_Migration150 Migrating from V1.5.0 to V1.5.1
+ *
+ * <b>Library Demos</b>
+ * - The USBtoSerial demo was broken in the 1.5.0 release, due to incorrect register polling in place of the
+ * global "Transmitting" flag. The change has been reverted in this release. Projects built upon the demo
+ * should upgrade to the latest code.
+ * - The HID class demos did not implement the mandatory GetReport HID class request. Projects built upon the HID
+ * demos should upgrade to the latest code.
+ * - The HID class demos incorrectly reported themselves as boot-protocol enabled HID devices in their descriptors.
+ * Projects built upon the HID demos should upgrade to the latest code.
+ * - The MIDI device demo had incorrect AudioStreaming interface descriptors. Projects built upon the MIDI demo
+ * should upgrade to the latest code.
+ * - The AudioOut demo did not correctly tristate the speaker pins when USB was disconnected, wasting power.
+ * Projects built upon the AudioOut demo should upgrade to the latest code.
+ *
+ * \section Sec_Migration141 Migrating from V1.4.1 to V1.5.0
+ *
+ * <b>Library Demos</b>
+ * - Previous versions of the library demos had incorrectly encoded BCD version numbers in the descriptors. To
+ * avoid such mistakes in the future, the VERSION_BCD macro has been added to StdDescriptors.h. Existing
+ * projects should at least manually correct the BCD version numbers, or preferably update the descriptors to
+ * encode the version number in BCD format using the new macro.
+ * - The mandatory GetReport class-specific request was accidentally omitted from previous versions of the demos
+ * based on the Human Interface Device (HID) class. This has been corrected, and any user projects based on the
+ * HID demos should also be updated accordingly.
+ * - The CDC demos now correctly send an empty packet directly after a full packet, to end the transmission.
+ * Failure to do this on projects which always or frequently send full packets will cause buffering issues on
+ * the host OS. All CDC user projects are advised to update their transmission routines in the same manner as
+ * the library CDC demos.
+ * - The previous interrupt-driven Endpoint/Pipe demos did not properly save and restore the currently selected
+ * Endpoint/Pipe when the ISR fired. This has been corrected - user projects based on the interrupt driven
+ * demos should also update to properly save and restore the selected Endpoint/Pipe.
+ *
+ * <b>Non-USB Library Components</b>
+ * - The Atomic.h and ISRMacro.h header files in MyUSB/Common have been removed, as the library is now only
+ * compatible with avr-libc library versions newer than the time before the functionality of the deleted
+ * headers was available.
+ *
+ * <b>Device Mode</b>
+ * - The GetDescriptor function (see StdDescriptors.h) now has a new prototype, with altered parameter names and
+ * functions. Existing projects will need to update the GetDescriptor implementation to reflect the new API.
+ * The previously split Type and Index parameters are now passed as the original wValue parameter to the
+ * function, to make way for the USB specification wIndex parameter which is <i>not</i> the same as the
+ * previous Index parameter.
+ * - The USB_UnhandledControlPacket event (see Events.h) now has new parameter names, to be in line with the
+ * official USB specification. Existing code will need to be altered to use the new parameter names.
+ * - The USB_CreateEndpoints event (see Events.h) has been renamed to USB_ConfigurationChanged, which is more
+ * appropriate. It fires in an identical manner to the previously named event, thus the only change to be made
+ * is the event name itself in the user project.
+ * - The USB_Descriptor_Language_t structure no longer exists in StdDescriptors.h, as this was a
+ * pseudo-descriptor modeled on the string descriptor. It is replaced by the true USB_Descriptor_String_t type
+ * descriptor as indicated in the USB specification, thus all device code must be updated accordingly.
+ * - The names of several Endpoint macros have been changed to be more consistent with the rest of the library,
+ * with no implementation changes. This means that existing code can be altered to use the new macro names
+ * with no other considerations required. See Endpoint.h for the new macro names.
+ * - The previous version of the MassStorage demo had an incorrect value in the SCSI_Request_Sense_Response_t
+ * structure named SenseData in SCSI.c which caused some problems with some hosts. User projects based on this
+ * demo should correct the structure value to maintain compatibility across multiple OS platforms.
+ * - By default, the descriptor structures use the official USB specification names for the elements. Previous
+ * versions of the library used non-standard (but more verbose) names, which are still usable in the current
+ * and future releases when the correct compile time option is enabled. See the StdDescriptors.h file
+ * documentation for more details.
+ *
+ * <b>Host Mode</b>
+ * - The USB_Host_Request_Header_t structure in HostChapter9.h (used for issuing control requests) has had its
+ * members renamed to the official USB specification names for requests. Existing code will need to be updated
+ * to use the new names.
+ * - The names of several Pipe macros have been changed to be more consistent with the rest of the library,
+ * with no implementation changes. This means that existing code can be altered to use the new macro names
+ * with no other considerations required. See Pipe.h for the new macro names.
+ * - By default, the descriptor structures use the official USB specification names for the elements. Previous
+ * versions of the library used non-standard (but more verbose) names, which are still usable in the current
+ * and future releases when the correct compile time option is enabled. See the StdDescriptors.h file
+ * documentation for more details.
+ * - The names of the macros in Host.h for controlling the SOF generation have been renamed, see the Host.h
+ * module documentation for the new macro names.
+ *
+ * <b>Dual Role Mode</b>
+ * - The OTG.h header file has been corrected so that the macros now perform their stated functions. Any existing
+ * projects using custom headers to fix the broken OTG header should now be altered to once again use the OTG
+ * header inside the library.
+ * - The USB_DeviceEnumerationComplete event (see Events.h) now also fires in Device mode, when the host has
+ * finished enumerating the device. Projects relying on the event only firing in Host mode should be updated
+ * so that the event action only occurs when the USB_Mode global is set to USB_MODE_HOST.
+ */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/OSDrivers.txt b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/OSDrivers.txt
new file mode 100644
index 000000000..4823c5b08
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/OSDrivers.txt
@@ -0,0 +1,111 @@
+/** \file
+ *
+ * This file contains special DoxyGen information for the generation of the main page and other special
+ * documentation pages. It is not a project source file.
+ */
+
+/** \page Page_OSDrivers Operating System Drivers
+ *
+ * Most of the USB classes supported by LUFA are also supported natively in
+ * most operating systems, without extra drivers being required. However, in
+ * some cases, a driver file is required in order for the device to enumerate
+ * and function correctly.
+ *
+ * \section Sec_OSClassSupport Operating System USB Class Support
+ * The table below lists the supported LUFA USB classes, and their associated
+ * <i>native</i> support on modern operating systems.
+ *
+ * <table>
+ * <tr>
+ * <th width="200px">USB Class</th>
+ * <th width="150px">Android</th>
+ * <th width="150px">Windows</th>
+ * <th width="150px">Linux</th>
+ * <th width="150px">OS X</th>
+ * </tr>
+ * <tr>
+ * <td>Android Open Accessory</td>
+ * <td>2.3.4+</td>
+ * <td>N/A</td>
+ * <td>N/A</td>
+ * <td>N/A</td>
+ * </tr>
+ * <tr>
+ * <td>Audio 1.0</td>
+ * <td>N/A</td>
+ * <td>XP+</td>
+ * <td>2.6.?+</td>
+ * <td>10.?+</td>
+ * </tr>
+ * <tr>
+ * <td>CDC-ACM</td>
+ * <td>N/A</td>
+ * <td>XP+</td>
+ * <td>2.6.?+</td>
+ * <td>10.?+</td>
+ * </tr>
+ * <tr>
+ * <td>HID</td>
+ * <td>3.?+</td>
+ * <td>XP+</td>
+ * <td>2.6.?+</td>
+ * <td>10.?+</td>
+ * </tr>
+ * <tr>
+ * <td>MIDI</td>
+ * <td>N/A</td>
+ * <td>XP+</td>
+ * <td>2.6.?+</td>
+ * <td>10.?+</td>
+ * </tr>
+ * <tr>
+ * <td>Mass Storage</td>
+ * <td>N/A</td>
+ * <td>XP+</td>
+ * <td>2.6.?+</td>
+ * <td>10.?+</td>
+ * </tr>
+ * <tr>
+ * <td>Printer</td>
+ * <td>N/A</td>
+ * <td>XP+</td>
+ * <td>2.6.?+</td>
+ * <td>10.?+</td>
+ * </tr>
+ * <tr>
+ * <td>RNDIS</td>
+ * <td>N/A</td>
+ * <td>XP+</td>
+ * <td>2.6.?+</td>
+ * <td>N/A</td>
+ * </tr>
+ * <tr>
+ * <td>Still Image</td>
+ * <td>N/A</td>
+ * <td>XP+</td>
+ * <td>2.6.?+</td>
+ * <td>10.?+</td>
+ * </tr>
+ * </table>
+ *
+ * \section Sec_WinINFTemplates Windows INF Drivers
+ * Windows uses INF driver files to associate a USB device of a specific class,
+ * VID/PID ID pair, Windows Compatibility ID or other characteristic to a kernel
+ * driver. In most cases these files are build into the operating system, and
+ * no special user action or driver files are required for a device using a
+ * standard USB class to enumerate. However, for some classes, a specific INF
+ * driver must be created and given to the operating system for the device to
+ * enumerate.
+ *
+ * Those USB classes requiring a custom INF driver file in Windows are listed
+ * below, along with a basic INF template for each class.
+ *
+ * \subsection SSec_WinINF_CDC Windows CDC INF Template
+ * This template is required for all CDC-ACM devices on Windows XP or newer.
+ * \verbinclude "WindowsINF/LUFA CDC-ACM.inf"
+ *
+ * \subsection SSec_WinINF_RNDIS Windows RNDIS INF Template
+ * This template is required for all RNDIS devices on Windows XP or newer.
+ * \verbinclude "WindowsINF/LUFA RNDIS.inf"
+ */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/ProgrammingApps.txt b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/ProgrammingApps.txt
new file mode 100644
index 000000000..4759ac87a
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/ProgrammingApps.txt
@@ -0,0 +1,30 @@
+/** \file
+ *
+ * This file contains special DoxyGen information for the generation of the main page and other special
+ * documentation pages. It is not a project source file.
+ */
+
+/** \page Page_ProgrammingApps Programming an Application into a USB AVR
+ *
+ * Once you have built an application, you will need a way to program in the resulting ".HEX" file (and, if your
+ * application uses EEPROM variables with initial values, also a ".EEP" file) into your USB AVR. Normally, the
+ * reprogramming of an AVR device must be performed using a special piece of programming hardware, through one of the
+ * supported AVR programming protocols - ISP, HVSP, HVPP, JTAG, dW or PDI. This can be done through a custom programmer,
+ * a third party programmer, or an official Atmel AVR tool - for more information, see the <a>atmel.com</a> website.
+ *
+ * Alternatively, you can use the bootloader. From the Atmel factory, each USB AVR comes preloaded with the Atmel
+ * DFU (Device Firmware Update) class bootloader, a small piece of AVR firmware which allows the remainder of the
+ * AVR to be programmed through a non-standard interface such as the serial USART port, SPI, or (in this case) USB.
+ * Bootloaders have the advantage of not requiring any special hardware for programming, and cannot usually be erased
+ * or broken without an external programming device. They have disadvantages however; they cannot change the fuses of
+ * the AVR (special configuration settings that control the operation of the chip itself) and a small portion of the
+ * AVR's FLASH program memory must be reserved to contain the bootloader firmware, and thus cannot be used by the
+ * loaded application.
+ *
+ * If you wish to use the DFU bootloader to program in your application, refer to your DFU programmer's documentation.
+ * Atmel provides a free utility called FLIP which is USB AVR compatible, and an open source (Linux compatible)
+ * alternative exists called "dfu-programmer".
+ *
+ * \see \ref Page_BuildModule_DFU for information on the LUFA build system DFU module, for automatic DFU bootloader
+ * programming makefile targets.
+ */
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/SoftwareBootloaderJump.txt b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/SoftwareBootloaderJump.txt
new file mode 100644
index 000000000..0b69612b6
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/SoftwareBootloaderJump.txt
@@ -0,0 +1,71 @@
+/** \file
+ *
+ * This file contains special DoxyGen information for the generation of the main page and other special
+ * documentation pages. It is not a project source file.
+ */
+
+/**
+ * \page Page_SoftwareBootloaderStart Entering the Bootloader via Software
+ *
+ * A common requirement of many applications is the ability to jump to the programmed bootloader of a chip
+ * on demand, via the code's firmware (i.e. not as a result of any physical user interaction with the
+ * hardware). This might be required because the device does not have any physical user input, or simply
+ * just to streamline the device upgrade process on the host PC.
+ *
+ * The following C code snippets may be used to enter the bootloader upon request by the user application.
+ * By using the watchdog to physically reset the controller, it is ensured that all system hardware is
+ * completely reset to their defaults before the bootloader is run. This is important; since bootloaders
+ * are written to occupy a very limited space, they usually make assumptions about the register states based
+ * on the default values after a hard-reset of the chip.
+ *
+ * \section Sec_SoftareBootAVR8 AVR8 Architecture
+ * The following software bootloader jump code is written for the AVR8 architecture.
+ *
+ * \code
+ * #include <avr/wdt.h>
+ * #include <avr/io.h>
+ * #include <util/delay.h>
+ *
+ * #include <LUFA/Common/Common.h>
+ * #include <LUFA/Drivers/USB/USB.h>
+ *
+ * uint32_t Boot_Key ATTR_NO_INIT;
+ *
+ * #define MAGIC_BOOT_KEY 0xDC42ACCA
+ * #define BOOTLOADER_START_ADDRESS ((FLASH_SIZE_BYTES - BOOTLOADER_SEC_SIZE_BYTES) >> 1)
+ *
+ * void Bootloader_Jump_Check(void) ATTR_INIT_SECTION(3);
+ * void Bootloader_Jump_Check(void)
+ * {
+ * // If the reset source was the bootloader and the key is correct, clear it and jump to the bootloader
+ * if ((MCUSR & (1 << WDRF)) && (Boot_Key == MAGIC_BOOT_KEY))
+ * {
+ * Boot_Key = 0;
+ * ((void (*)(void))BOOTLOADER_START_ADDRESS)();
+ * }
+ * }
+ *
+ * void Jump_To_Bootloader(void)
+ * {
+ * // If USB is used, detach from the bus and reset it
+ * USB_Disable();
+ *
+ * // Disable all interrupts
+ * cli();
+ *
+ * // Wait two seconds for the USB detachment to register on the host
+ * Delay_MS(2000);
+ *
+ * // Set the bootloader key to the magic value and force a reset
+ * Boot_Key = MAGIC_BOOT_KEY;
+ * wdt_enable(WDTO_250MS);
+ * for (;;);
+ * }
+ * \endcode
+ *
+ * Note that the bootloader magic key can be any arbitrary value. The <em>FLASH_SIZE_BYTES</em> and
+ * <em>BOOTLOADER_SEC_SIZE_BYTES</em> tokens should be replaced with the total flash size of the AVR
+ * in bytes, and the allocated size of the bootloader section for the target AVR.
+ *
+ */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Style/Footer.htm b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Style/Footer.htm
new file mode 100644
index 000000000..a72c5bdd2
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Style/Footer.htm
@@ -0,0 +1,35 @@
+<!--BEGIN GENERATE_TREEVIEW-->
+ <div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
+ <ul>
+ <li class="footer" style="float:left !important;">
+ $generatedby
+ <a href="http://www.doxygen.org/index.html">
+ <img class="footer" src="$relpath$doxygen.png" alt="doxygen"/>
+ </a>
+ $doxygenversion
+ </li>
+
+ <li class="footer">
+ <a href="http://www.lufa-lib.org" title="LUFA Project Page">LUFA Project Page</a> | <a href="http://www.lufa-lib.org/support" title="LUFA Support List">Support Mailing List</a> | <a href="http://www.lufa-lib.org/donate" title="Donate to Support LUFA">Donate</a> | <a href="http://www.fourwalledcubicle.com" title="Four Walled Cubicle Website">Four Walled Cubicle</a> - LUFA, the Lightweight USB Framework for AVRs
+ </li>
+ </ul>
+ </div>
+<!--END GENERATE_TREEVIEW-->
+<!--BEGIN !GENERATE_TREEVIEW-->
+ <hr class="footer"/>
+ <div class="footer">
+ <span style="float: left;">
+ $generatedby
+ <a href="http://www.doxygen.org/index.html">
+ <img class="footer" src="$relpath$doxygen.png" alt="doxygen"/>
+ </a>
+ $doxygenversion
+ </span>
+
+ <span style="margin-right: 20px; float: right;">
+ <a href="http://www.lufa-lib.org" title="LUFA Project Page">LUFA Project Page</a> | <a href="http://www.lufa-lib.org/support" title="LUFA Support List">Support Mailing List</a> | <a href="http://www.lufa-lib.org/donate" title="Donate to Support LUFA">Donate</a> | <a href="http://www.fourwalledcubicle.com" title="Four Walled Cubicle Website">Four Walled Cubicle</a> - LUFA, the Lightweight USB Framework for AVRs
+ </span>
+ </div>
+<!--END !GENERATE_TREEVIEW-->
+ </body>
+</html> \ No newline at end of file
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Style/Style.css b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Style/Style.css
new file mode 100644
index 000000000..933215546
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/Style/Style.css
@@ -0,0 +1,93 @@
+/* ============================= */
+/* Page Header Formattings */
+/* ============================= */
+#titlearea {
+ background-color:#E1E7F4;
+ background-image:url('nav_f.png');
+ background-repeat:repeat-x;
+ color:#20335A;
+ font-weight:bold;
+ text-shadow:0 1px 1px rgba(255, 255, 255, 0.9);
+}
+
+#projectlogo {
+ padding-left: 10px;
+}
+
+/* ============================= */
+/* General Text Formattings */
+/* ============================= */
+body,table,div,p,dl {
+ font-family:Lucida Grande, Verdana, Geneva, Arial, sans-serif;
+ font-size:13px;
+ line-height:1.3;
+}
+
+div.header, div.contents p {
+ padding-left:12px;
+}
+
+/* ============================= */
+/* API Documentation Formattings */
+/* ============================= */
+div.contents table.memberdecls, .paramname {
+ font-family:Consolas, Monaco, courier, sans-serif;
+ font-size:105%;
+ padding-right:20px;
+}
+
+/* ============================= */
+/* HTML Heading Formattings */
+/* ============================= */
+h1, h2, h3, h4 {
+ font-family:Lucida Grande, Verdana, Geneva, Arial, sans-serif;
+}
+
+h1 {
+ font-size:25px;
+ margin-bottom:10px;
+}
+
+h2 {
+ color:#42657B;
+ font-size:17px;
+}
+
+h3 {
+ font-size:15px;
+}
+
+h4 {
+ font-size:13px;
+}
+
+/* ============================= */
+/* Code Snippet Formattings */
+/* ============================= */
+span.keyword {
+ color:#008000;
+}
+
+span.keywordtype {
+ color:#604020;
+}
+
+span.keywordflow {
+ color:#e08000;
+}
+
+span.comment {
+ color:#008000;
+}
+
+span.preprocessor {
+ color:#806020;
+}
+
+span.stringliteral {
+ color:#002080;
+}
+
+span.charliteral {
+ color:#008080;
+}
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/VIDAndPIDValues.txt b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/VIDAndPIDValues.txt
new file mode 100644
index 000000000..8b1722044
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/VIDAndPIDValues.txt
@@ -0,0 +1,199 @@
+/** \file
+ *
+ * This file contains special DoxyGen information for the generation of the main page and other special
+ * documentation pages. It is not a project source file.
+ */
+
+/** \page Page_VIDPID VID and PID values
+ *
+ * \section Sec_VIDPID_Allocations VID and PID Allocations
+ * The LUFA library uses VID/PID combinations generously donated by Atmel. The following VID/PID combinations
+ * are used within the LUFA demos, and thus may be re-used by derivations of each demo. Free PID values may be
+ * used by future LUFA demo projects.
+ *
+ * <b>These VID/PID values should not be used in commercial designs under any circumstances.</b> Private projects
+ * may use the following values freely, but must accept any collisions due to other LUFA derived private projects
+ * sharing identical values. It is suggested that private projects using interfaces compatible with existing
+ * demos share the same VID/PID value.
+ *
+ * <table>
+ * <tr>
+ * <th>VID</th>
+ * <th>PID</th>
+ * <th>Usage</th>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>0x2040</td>
+ * <td>Test VID/PID (See \ref Sec_Test_VIDPID)</td>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>0x2041</td>
+ * <td>Mouse Demo Application</td>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>0x2042</td>
+ * <td>Keyboard Demo Application</td>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>0x2043</td>
+ * <td>Joystick Demo Application</td>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>0x2044</td>
+ * <td>CDC Demo Application</td>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>0x2045</td>
+ * <td>Mass Storage Demo Application</td>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>0x2046</td>
+ * <td>Audio Output Demo Application</td>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>0x2047</td>
+ * <td>Audio Input Demo Application</td>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>0x2048</td>
+ * <td>MIDI Demo Application</td>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>0x2049</td>
+ * <td>MagStripe Project</td>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>0x204A</td>
+ * <td>CDC Class Bootloader</td>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>0x204B</td>
+ * <td>USB to Serial Demo Application</td>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>0x204C</td>
+ * <td>RNDIS Demo Application</td>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>0x204D</td>
+ * <td>Combined Keyboard and Mouse Demo Application</td>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>0x204E</td>
+ * <td>Dual CDC Demo Application</td>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>
+ * 0x204F
+ * </td>
+ * <td>Generic HID Demo Application</td>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>0x2060</td>
+ * <td>Benito Programmer Project</td>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>0x2061</td>
+ * <td>Combined Mass Storage and Keyboard Demo</td>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>0x2062</td>
+ * <td>Combined CDC and Mouse Demo</td>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>0x2063</td>
+ * <td>Mass Storage/HID Interface Datalogger Project</td>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>0x2064</td>
+ * <td>Interfaceless Control-Only LUFA Devices</td>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>0x2065</td>
+ * <td>Test and Measurement Demo</td>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>
+ * 0x2066
+ * </td>
+ * <td>Multiple Report Keyboard/Mouse HID Demo</td>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>0x2067</td>
+ * <td>HID Class Bootloader</td>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>0x2068</td>
+ * <td>Virtual Serial/Mass Storage Demo</td>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>
+ * 0x2069
+ * </td>
+ * <td>Webserver Project</td>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>0x206A</td>
+ * <td>Media Control Project</td>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>0x206B</td>
+ * <td>Printer Class Bootloader</td>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>0x206C</td>
+ * <td>Bulk Vendor Demo Application</td>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>0x206D</td>
+ * <td>Dual MIDI Demo Application</td>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>0x206E</td>
+ * <td><i>Currently Unallocated</i></td>
+ * </tr>
+ * <tr>
+ * <td>0x03EB</td>
+ * <td>0x206F</td>
+ * <td><i>Currently Unallocated</i></td>
+ * </tr>
+ * </table>
+ *
+ * \section Sec_Test_VIDPID The Test VID/PID Combination
+ * For use in testing of LUFA powered devices during development only, by non-commercial entities.
+ * All devices must accept collisions on this VID/PID range (from other in-development LUFA devices)
+ * to be resolved by using a unique release number in the Device Descriptor. No devices using this
+ * VID/PID combination may be released to the general public.
+ */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/WritingBoardDrivers.txt b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/WritingBoardDrivers.txt
new file mode 100644
index 000000000..b2ff07e66
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/DoxygenPages/WritingBoardDrivers.txt
@@ -0,0 +1,47 @@
+/** \file
+ *
+ * This file contains special DoxyGen information for the generation of the main page and other special
+ * documentation pages. It is not a project source file.
+ */
+
+/** \page Page_WritingBoardDrivers Writing LUFA Board Drivers
+ *
+ * LUFA ships with several basic pre-made board drivers, to control hardware present on the supported board
+ * hardware - such as Dataflash ICs, LEDs, Joysticks, or other hardware peripherals. When compiling an application
+ * which makes use of one or more board drivers located in <i>LUFA/Drivers/Board</i>, you must also indicate which
+ * board hardware you are using in your project makefile. This is done by defining the <tt>BOARD</tt> macro using
+ * the <tt>-D</tt> switch passed to the compiler, with a constant of <tt>BOARD_{Name}</tt>. For example,
+ * <tt>-DBOARD=BOARD_USBKEY</tt> instructs the compiler to use the USBKEY board hardware drivers.
+ *
+ * If your application does not use <i>any</i> board level drivers, you can omit the definition of the <tt>BOARD</tt>
+ * macro. However, some users may wish to write their own custom board hardware drivers which are to remain compatible
+ * with the LUFA hardware API. To do this, the <tt>BOARD</tt> macro should be defined to the value <tt>BOARD_USER</tt>.
+ * This indicates that the board level drivers should be located in a folder named "Board" located inside the
+ * application's folder.
+ *
+ * When used, the driver stub files located in the <tt>LUFA/CodeTemplates/DriverStubs</tt> folder should be copied to
+ * the user application's <tt>Board/</tt> directory, and filled out to include the values and code needed to control
+ * the custom board hardware. Once done, the existing LUFA board level APIs (accessed in the regular
+ * <tt>LUFA/Drivers/Board/</tt> folder) will redirect to the user board drivers, maintaining code compatibility and
+ * allowing for a different board to be selected through the project makefile with no code changes.
+ *
+ * \section Sec_BoardTemplates Board Driver Templates
+ *
+ * The templates for each board driver are reproduced below.
+ *
+ * \subsection SSec_BoardTemplates_Board Template for USER <Board/Board.h>
+ * \include "DriverStubs/Board.h"
+ *
+ * \subsection SSec_BoardTemplates_Buttons Template for USER <Board/Buttons.h>
+ * \include "DriverStubs/Buttons.h"
+ *
+ * \subsection SSec_BoardTemplates_Dataflash Template for USER <Board/Dataflash.h>
+ * \include "DriverStubs/Dataflash.h"
+ *
+ * \subsection SSec_BoardTemplates_Joystick Template for USER <Board/Joystick.h>
+ * \include "DriverStubs/Joystick.h"
+ *
+ * \subsection SSec_BoardTemplates_LEDs Template for USER <Board/LEDs.h>
+ * \include "DriverStubs/LEDs.h"
+ */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/ADAFRUITU4/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/ADAFRUITU4/Board.h
new file mode 100644
index 000000000..48016e0bf
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/ADAFRUITU4/Board.h
@@ -0,0 +1,78 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Adafruit U4 Breakout board.
+ * \copydetails Group_BoardInfo_ADAFRUITU4
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_ADAFRUITU4 ADAFRUITU4
+ * \brief Board specific information header for the Adafruit U4 Breakout board.
+ *
+ * Board specific information header for the Adafruit U4 Breakout board (http://ladyada.net/products/atmega32u4breakout).
+ *
+ * @{
+ */
+
+#ifndef __BOARD_ADAFRUITU4_H__
+#define __BOARD_ADAFRUITU4_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/ADAFRUITU4/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/ADAFRUITU4/LEDs.h
new file mode 100644
index 000000000..9f312207b
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/ADAFRUITU4/LEDs.h
@@ -0,0 +1,135 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Adafruit U4 Breakout board.
+ * \copydetails Group_LEDs_ADAFRUITU4
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_ADAFRUITU4 ADAFRUITU4
+ * \brief Board specific LED driver header for the Adafruit U4 Breakout board.
+ *
+ * Board specific LED driver header for the Adafruit U4 Breakout board (http://ladyada.net/products/atmega32u4breakout).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Green</td><td>General Indicator</td><td>High</td><td>PORTE.6</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_ADAFRUITU4_H__
+#define __LEDS_ADAFRUITU4_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 6)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS LEDS_LED1
+
+ /** LED mask for the none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRE |= LEDS_ALL_LEDS;
+ PORTE &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRE &= ~LEDS_ALL_LEDS;
+ PORTE &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTE |= LEDMask;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTE &= ~LEDMask;
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTE = ((PORTE & ~LEDS_ALL_LEDS) | LEDMask);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTE = ((PORTE & ~LEDMask) | ActiveMask);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PINE = LEDMask;
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return (PORTE & LEDS_ALL_LEDS);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/Board.h
new file mode 100644
index 000000000..07000ecdd
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/Board.h
@@ -0,0 +1,82 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Atmel ATAVRUSBRF01.
+ * \copydetails Group_BoardInfo_ATAVRUSBRF01
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_ATAVRUSBRF01 ATAVRUSBRF01
+ * \brief Board specific information header for the Atmel ATAVRUSBRF01.
+ *
+ * Board specific information header for the Atmel ATAVRUSBRF01.
+ *
+ * @{
+ */
+
+#ifndef __BOARD_ATAVRUSBRF01_H__
+#define __BOARD_ATAVRUSBRF01_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../Buttons.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware Buttons mounted. */
+ #define BOARD_HAS_BUTTONS
+
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/Buttons.h
new file mode 100644
index 000000000..8b815dbcb
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/Buttons.h
@@ -0,0 +1,103 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Buttons driver header for the Atmel ATAVRUSBRF01.
+ * \copydetails Group_Buttons_ATAVRUSBRF01
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Buttons driver
+ * dispatch header located in LUFA/Drivers/Board/Buttons.h.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_ATAVRUSBRF01 ATAVRUSBRF01
+ * \brief Board specific Buttons driver header for the Atmel ATAVRUSBRF01.
+ *
+ * Board specific Buttons driver header for the Atmel ATAVRUSBRF01.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>BUTTONS_BUTTON1</td><td>HWB Button</td><td>Low</td><td>PORTD.7</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __BUTTONS_ATAVRUSBRF01_H__
+#define __BUTTONS_ATAVRUSBRF01_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Button mask for the first button on the board. */
+ #define BUTTONS_BUTTON1 (1 << 7)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+ DDRD &= ~BUTTONS_BUTTON1;
+ PORTD |= BUTTONS_BUTTON1;
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+ DDRD &= ~BUTTONS_BUTTON1;
+ PORTD &= ~BUTTONS_BUTTON1;
+ }
+
+ static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Buttons_GetStatus(void)
+ {
+ return ((PIND & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/LEDs.h
new file mode 100644
index 000000000..76e89fd0d
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/LEDs.h
@@ -0,0 +1,139 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Atmel ATAVRUSBRF01.
+ * \copydetails Group_LEDs_ATAVRUSBRF01
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_ATAVRUSBRF01 ATAVRUSBRF01
+ * \brief Board specific LED driver header for the Atmel ATAVRUSBRF01.
+ *
+ * Board specific LED driver header for the Atmel ATAVRUSBRF01.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Green</td><td>RX LED</td><td>High</td><td>PORTD.0</td></tr>
+ * <tr><td>LEDS_LED2</td><td>Red</td><td>TX LED</td><td>High</td><td>PORTD.1</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_ATAVRUSBRF01_H__
+#define __LEDS_ATAVRUSBRF01_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 0)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1 << 1)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2)
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRD |= LEDS_ALL_LEDS;
+ PORTD &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRD &= ~LEDS_ALL_LEDS;
+ PORTD &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTD |= (LEDMask & LEDS_ALL_LEDS);
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTD &= ~(LEDMask & LEDS_ALL_LEDS);
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTD = (PORTD & ~LEDS_ALL_LEDS) | (LEDMask & LEDS_ALL_LEDS);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTD = ((PORTD & ~LEDMask) | ActiveMask);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PIND = LEDMask;
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return (PORTD & LEDS_ALL_LEDS);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BENITO/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BENITO/Board.h
new file mode 100644
index 000000000..5584e1ea7
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BENITO/Board.h
@@ -0,0 +1,82 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Tempusdictum Benito.
+ * \copydetails Group_BoardInfo_BENITO
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_BENITO BENITO
+ * \brief Board specific information header for the Tempusdictum Benito.
+ *
+ * Board specific information header for the Tempusdictum Benito (http://dorkbotpdx.org/wiki/benito).
+ *
+ * @{
+ */
+
+#ifndef __BOARD_BENITO_H__
+#define __BOARD_BENITO_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../Buttons.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware Buttons mounted. */
+ #define BOARD_HAS_BUTTONS
+
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BENITO/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BENITO/Buttons.h
new file mode 100644
index 000000000..96d14a3ae
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BENITO/Buttons.h
@@ -0,0 +1,103 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Buttons driver header for the Tempusdictum Benito.
+ * \copydetails Group_Buttons_BENITO
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Buttons driver
+ * dispatch header located in LUFA/Drivers/Board/Buttons.h.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_BENITO BENITO
+ * \brief Board specific Buttons driver header for the Tempusdictum Benito.
+ *
+ * Board specific Buttons driver header for the Tempusdictum Benito (http://dorkbotpdx.org/wiki/benito).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>BUTTONS_BUTTON1</td><td>HWB Button</td><td>Low</td><td>PORTD.7</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __BUTTONS_BENITO_H__
+#define __BUTTONS_BENITO_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Button mask for the first button on the board. */
+ #define BUTTONS_BUTTON1 (1 << 7)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+ DDRD &= ~BUTTONS_BUTTON1;
+ PORTD |= BUTTONS_BUTTON1;
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+ DDRD &= ~BUTTONS_BUTTON1;
+ PORTD &= ~BUTTONS_BUTTON1;
+ }
+
+ static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Buttons_GetStatus(void)
+ {
+ return ((PIND & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BENITO/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BENITO/LEDs.h
new file mode 100644
index 000000000..49df44191
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BENITO/LEDs.h
@@ -0,0 +1,139 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Tempusdictum Benito.
+ * \copydetails Group_LEDs_BENITO
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_BENITO BENITO
+ * \brief Board specific LED driver header for the Tempusdictum Benito.
+ *
+ * Board specific LED driver header for the Tempusdictum Benito (http://dorkbotpdx.org/wiki/benito).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Green</td><td>TX LED</td><td>Low</td><td>PORTC.7</td></tr>
+ * <tr><td>LEDS_LED2</td><td>Red</td><td>RX LED</td><td>Low</td><td>PORTC.6</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_BENITO_H__
+#define __LEDS_BENITO_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 7)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1 << 6)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2)
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRC |= LEDS_ALL_LEDS;
+ PORTC |= LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRC &= ~LEDS_ALL_LEDS;
+ PORTC &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTC &= ~LEDMask;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTC |= LEDMask;
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTC = ((PORTC | LEDS_ALL_LEDS) & ~LEDMask);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTC = ((PORTC | LEDMask) & ~ActiveMask);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PINC = LEDMask;
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return (~PORTC & LEDS_ALL_LEDS);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BIGMULTIO/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BIGMULTIO/Board.h
new file mode 100644
index 000000000..9d4e30130
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BIGMULTIO/Board.h
@@ -0,0 +1,78 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Bitwizard Big-Multio.
+ * \copydetails Group_BoardInfo_BIGMULTIO
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_BIGMULTIO BIGMULTIO
+ * \brief Board specific information header for the Bitwizard Big-Multio.
+ *
+ * Board specific information header for the Bitwizard Big-Multio (http://www.bitwizard.nl/wiki/index.php/Usbbigmultio).
+ *
+ * @{
+ */
+
+#ifndef __BOARD_BIGMULTIO_H__
+#define __BOARD_BIGMULTIO_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BIGMULTIO/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BIGMULTIO/LEDs.h
new file mode 100644
index 000000000..93d5bec97
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BIGMULTIO/LEDs.h
@@ -0,0 +1,161 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Bitwizard Big-Multio.
+ * \copydetails Group_LEDs_BIGMULTIO
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_BIGMULTIO BIGMULTIO
+ * \brief Board specific LED driver header for the Bitwizard Big-Multio.
+ *
+ * Board specific LED driver header for the Bitwizard Big-Multio (http://www.bitwizard.nl/wiki/index.php/Usbbigmultio).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Unknown</td><td>LED0</td><td>High</td><td>PORTF.6</td></tr>
+ * <tr><td>LEDS_LED2</td><td>Unknown</td><td>LED1</td><td>High</td><td>PORTF.7</td></tr>
+ * <tr><td>LEDS_LED3</td><td>Unknown</td><td>LED2</td><td>High</td><td>PORTE.2</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_BIGMULTIO_H__
+#define __LEDS_BIGMULTIO_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define LEDS_PORTF_LEDS (LEDS_LED1 | LEDS_LED2)
+ #define LEDS_PORTE_LEDS LEDS_LED3
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 6)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1 << 7)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED3 (1 << 2)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3)
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRF |= LEDS_PORTF_LEDS;
+ DDRE |= LEDS_PORTE_LEDS;
+
+ PORTF &= ~LEDS_PORTF_LEDS;
+ PORTE &= ~LEDS_PORTE_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRF &= ~LEDS_PORTF_LEDS;
+ DDRE &= ~LEDS_PORTE_LEDS;
+
+ PORTF &= ~LEDS_PORTF_LEDS;
+ PORTE &= ~LEDS_PORTE_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTF |= (LEDMask & LEDS_PORTF_LEDS);
+ PORTE |= (LEDMask & LEDS_PORTE_LEDS);
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTF &= ~(LEDMask & LEDS_PORTF_LEDS);
+ PORTE &= ~(LEDMask & LEDS_PORTE_LEDS);
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTF = (PORTF & ~LEDS_PORTF_LEDS) | (LEDMask & LEDS_PORTF_LEDS);
+ PORTE = (PORTE & ~LEDS_PORTE_LEDS) | (LEDMask & LEDS_PORTE_LEDS);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTF = (PORTF & ~(LEDMask & LEDS_PORTF_LEDS)) | (ActiveMask & LEDS_PORTF_LEDS);
+ PORTE = (PORTE & ~(LEDMask & LEDS_PORTE_LEDS)) | (ActiveMask & LEDS_PORTE_LEDS);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PINF = (LEDMask & LEDS_PORTF_LEDS);
+ PINE = (LEDMask & LEDS_PORTE_LEDS);
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return ((PORTF & LEDS_PORTF_LEDS) | (PORTE & LEDS_PORTE_LEDS));
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BLACKCAT/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BLACKCAT/Board.h
new file mode 100644
index 000000000..6eec7bf7d
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BLACKCAT/Board.h
@@ -0,0 +1,78 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the BLACKCAT USB JTAG.
+ * \copydetails Group_BoardInfo_BLACKCAT
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_BLACKCAT BLACKCAT
+ * \brief Board specific information header for the BLACKCAT USB JTAG.
+ *
+ * Board specific information header for the TCNISO Blackcat USB JTAG (http://www.embeddedcomputers.net/products/BlackcatUSB).
+ *
+ * @{
+ */
+
+#ifndef __BOARD_BLACKCAT_H__
+#define __BOARD_BLACKCAT_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BLACKCAT/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BLACKCAT/LEDs.h
new file mode 100644
index 000000000..4a72039ae
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BLACKCAT/LEDs.h
@@ -0,0 +1,139 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the BLACKCAT USB JTAG.
+ * \copydetails Group_LEDs_BLACKCAT
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_BLACKCAT BLACKCAT
+ * \brief Board specific LED driver header for the BLACKCAT USB JTAG.
+ *
+ * Board specific LED driver header for the TCNISO Blackcat USB JTAG (http://www.embeddedcomputers.net/products/BlackcatUSB).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Unknown</td><td>LED0</td><td>High</td><td>PORTD.6</td></tr>
+ * <tr><td>LEDS_LED2</td><td>Unknown</td><td>LED1</td><td>High</td><td>PORTD.3</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_BLACKCAT_H__
+#define __LEDS_BLACKCAT_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 6)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1 << 3)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2)
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRD |= LEDS_ALL_LEDS;
+ PORTD &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRD &= ~LEDS_ALL_LEDS;
+ PORTD &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTD |= LEDMask;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTD &= ~LEDMask;
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTD = ((PORTD & ~LEDS_ALL_LEDS) | LEDMask);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTD = ((PORTD & ~LEDMask) | ActiveMask);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PIND = LEDMask;
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return (PORTD & LEDS_ALL_LEDS);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BUI/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BUI/Board.h
new file mode 100644
index 000000000..067e870d8
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BUI/Board.h
@@ -0,0 +1,78 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Busware BUI.
+ * \copydetails Group_BoardInfo_BUI
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_BUI BUI
+ * \brief Board specific information header for the Busware BUI.
+ *
+ * Board specific information header for the Busware BUI (http://www.busware.de/tiki-index.php?page=BUI).
+ *
+ * @{
+ */
+
+#ifndef __BOARD_BUI_H__
+#define __BOARD_BUI_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BUI/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BUI/LEDs.h
new file mode 100644
index 000000000..e06edb5fc
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BUI/LEDs.h
@@ -0,0 +1,143 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Busware BUI.
+ * \copydetails Group_LEDs_BUI
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_BUI BUI
+ * \brief Board specific LED driver header for the Busware BUI.
+ *
+ * Board specific LED driver header for the Busware BUI (http://www.busware.de/tiki-index.php?page=BUI).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Red</td><td>RGB LED</td><td>High</td><td>PORTC.2</td></tr>
+ * <tr><td>LEDS_LED2</td><td>Green</td><td>RGB LED</td><td>High</td><td>PORTC.3</td></tr>
+ * <tr><td>LEDS_LED3</td><td>Blue</td><td>RGB LED</td><td>High</td><td>PORTC.4</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_BUI_H__
+#define __LEDS_BUI_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+/* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 2)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1 << 3)
+
+ /** LED mask for the third LED on the board. */
+ #define LEDS_LED3 (1 << 4)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3)
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRC |= LEDS_ALL_LEDS;
+ PORTC &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRC &= ~LEDS_ALL_LEDS;
+ PORTC &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTC |= LEDMask;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTC &= ~LEDMask;
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTC = (PORTC & ~LEDS_ALL_LEDS) | LEDMask;
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTC = (PORTC & ~LEDMask) | ActiveMask;
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PINC = LEDMask;
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return (PORTC & LEDS_ALL_LEDS);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BUMBLEB/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BUMBLEB/Board.h
new file mode 100644
index 000000000..906f0b5e0
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BUMBLEB/Board.h
@@ -0,0 +1,86 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Fletchtronics BUMBLEB.
+ * \copydetails Group_BoardInfo_BUMBLEB
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_BUMBLEB BUMBLEB
+ * \brief Board specific information header for the Fletchtronics BUMBLEB.
+ *
+ * Board specific information header for the Fletchtronics BUMBLEB (http://fletchtronics.net/bumble-b).
+ *
+ * @{
+ */
+
+#ifndef __BOARD_BUMBLEB_H__
+#define __BOARD_BUMBLEB_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../Buttons.h"
+ #include "../../Joystick.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware Buttons mounted. */
+ #define BOARD_HAS_BUTTONS
+
+ /** Indicates the board has a hardware Joystick mounted. */
+ #define BOARD_HAS_JOYSTICK
+
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BUMBLEB/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BUMBLEB/Buttons.h
new file mode 100644
index 000000000..049542591
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BUMBLEB/Buttons.h
@@ -0,0 +1,105 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Buttons driver header for the Fletchtronics BUMBLEB.
+ * \copydetails Group_Buttons_BUMBLEB
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Buttons driver
+ * dispatch header located in LUFA/Drivers/Board/Buttons.h.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_BUMBLEB BUMBLEB
+ * \brief Board specific Buttons driver header for the Fletchtronics BUMBLEB.
+ *
+ * Board specific buttons driver header for the Fletchtronics BUMBLEB (http://fletchtronics.net/bumble-b). The BUMBLEB
+ * third-party board does not include any on-board peripherals, but does have an officially recommended external peripheral
+ * layout for buttons, LEDs and a Joystick.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>BUTTONS_BUTTON1</td><td>HWB Button</td><td>Low</td><td>PORTD.7</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __BUTTONS_BUMBLEB_H__
+#define __BUTTONS_BUMBLEB_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Button mask for the first button on the board. */
+ #define BUTTONS_BUTTON1 (1 << 7)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+ DDRD &= ~BUTTONS_BUTTON1;
+ PORTD |= BUTTONS_BUTTON1;
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+ DDRD &= ~BUTTONS_BUTTON1;
+ PORTD &= ~BUTTONS_BUTTON1;
+ }
+
+ static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Buttons_GetStatus(void)
+ {
+ return ((PIND & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BUMBLEB/Joystick.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BUMBLEB/Joystick.h
new file mode 100644
index 000000000..82d085e89
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BUMBLEB/Joystick.h
@@ -0,0 +1,123 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific joystick driver header for the Fletchtronics BUMBLEB.
+ * \copydetails Group_Joystick_BUMBLEB
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the joystick driver
+ * dispatch header located in LUFA/Drivers/Board/Joystick.h.
+ */
+
+/** \ingroup Group_Joystick
+ * \defgroup Group_Joystick_BUMBLEB BUMBLEB
+ * \brief Board specific joystick driver header for the Fletchtronics BUMBLEB.
+ *
+ * Board specific joystick driver header for the Fletchtronics BUMBLEB (http://fletchtronics.net/bumble-b). The BUMBLEB
+ * third-party board does not include any on-board peripherals, but does have an officially recommended external peripheral
+ * layout for buttons, LEDs and a Joystick.
+ *
+ * <table>
+ * <tr><th>Left Port Pin</th><th>Up Port Pin</th><th>Right Port Pin</th><th>Down Port Pin</th><th>Press Port Pin</th></tr>
+ * <tr><td>PORTD.2</td><td>PORTD.3</td><td>PORTD.0</td><td>PORTD.1</td><td>PORTD.4</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __JOYSTICK_BUMBLEB_H__
+#define __JOYSTICK_BUMBLEB_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_JOYSTICK_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Joystick.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define JOY_MASK ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4))
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Mask for the joystick being pushed in the left direction. */
+ #define JOY_LEFT (1 << 2)
+
+ /** Mask for the joystick being pushed in the upward direction. */
+ #define JOY_UP (1 << 3)
+
+ /** Mask for the joystick being pushed in the right direction. */
+ #define JOY_RIGHT (1 << 0)
+
+ /** Mask for the joystick being pushed in the downward direction. */
+ #define JOY_DOWN (1 << 1)
+
+ /** Mask for the joystick being pushed inward. */
+ #define JOY_PRESS (1 << 4)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Joystick_Init(void)
+ {
+ DDRD &= ~JOY_MASK;
+ PORTD |= JOY_MASK;
+ }
+
+ static inline void Joystick_Disable(void)
+ {
+ DDRD &= ~JOY_MASK;
+ PORTD &= ~JOY_MASK;
+ }
+
+ static inline uint8_t Joystick_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Joystick_GetStatus(void)
+ {
+ return (uint8_t)(~PIND & JOY_MASK);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BUMBLEB/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BUMBLEB/LEDs.h
new file mode 100644
index 000000000..5cd7b483c
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/BUMBLEB/LEDs.h
@@ -0,0 +1,149 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Fletchtronics BUMBLEB.
+ * \copydetails Group_LEDs_BUMBLEB
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_BUMBLEB BUMBLEB
+ * \brief Board specific LED driver header for the Fletchtronics BUMBLEB.
+ *
+ * Board specific LED driver header for the Fletchtronics BUMBLEB (http://fletchtronics.net/bumble-b). The BUMBLEB
+ * third-party board does not include any on-board peripherals, but does have an officially recommended external
+ * peripheral layout for buttons, LEDs and a Joystick.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>N/A</td><td>User Supplied</td><td>High</td><td>PORTB.4</td></tr>
+ * <tr><td>LEDS_LED2</td><td>N/A</td><td>User Supplied</td><td>High</td><td>PORTB.5</td></tr>
+ * <tr><td>LEDS_LED3</td><td>N/A</td><td>User Supplied</td><td>High</td><td>PORTB.6</td></tr>
+ * <tr><td>LEDS_LED4</td><td>N/A</td><td>User Supplied</td><td>High</td><td>PORTB.7</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_BUMBLEB_H__
+#define __LEDS_BUMBLEB_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 4)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1 << 5)
+
+ /** LED mask for the third LED on the board. */
+ #define LEDS_LED3 (1 << 6)
+
+ /** LED mask for the fourth LED on the board. */
+ #define LEDS_LED4 (1 << 7)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3 | LEDS_LED4)
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRB |= LEDS_ALL_LEDS;
+ PORTB &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRB &= ~LEDS_ALL_LEDS;
+ PORTB &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LedMask)
+ {
+ PORTB |= LedMask;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LedMask)
+ {
+ PORTB &= ~LedMask;
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LedMask)
+ {
+ PORTB = ((PORTB & ~LEDS_ALL_LEDS) | LedMask);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LedMask,
+ const uint8_t ActiveMask)
+ {
+ PORTB = ((PORTB & ~LedMask) | ActiveMask);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PINB = LEDMask;
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return (PORTB & LEDS_ALL_LEDS);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/CULV3/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/CULV3/Board.h
new file mode 100644
index 000000000..777902d27
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/CULV3/Board.h
@@ -0,0 +1,82 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Busware CUL V3.
+ * \copydetails Group_BoardInfo_CULV3
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_CULV3 CULV3
+ * \brief Board specific information header for the Busware CUL V3.
+ *
+ * Board specific information header for the Busware CUL V3 (http://busware.de/tiki-index.php?page=CUL).
+ *
+ * @{
+ */
+
+#ifndef __BOARD_CULV3_H__
+#define __BOARD_CULV3_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../Buttons.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware Buttons mounted. */
+ #define BOARD_HAS_BUTTONS
+
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/CULV3/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/CULV3/Buttons.h
new file mode 100644
index 000000000..6a26a9980
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/CULV3/Buttons.h
@@ -0,0 +1,103 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Busware CULV3.
+ * \copydetails Group_LEDs_CULV3
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Buttons driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_CULV3 CULV3
+ * \brief Board specific Buttons driver header for the Busware CULV3.
+ *
+ * Board specific Buttons driver header for the Busware CUL V3 (http://busware.de/tiki-index.php?page=CUL).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>BUTTONS_BUTTON1</td><td>HWB Button</td><td>Low</td><td>PORTE.2</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __BUTTONS_CULV3_H__
+#define __BUTTONS_CULV3_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Button mask for the first button on the board. */
+ #define BUTTONS_BUTTON1 (1 << 2)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+ DDRE &= ~BUTTONS_BUTTON1;
+ PORTE |= BUTTONS_BUTTON1;
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+ DDRE &= ~BUTTONS_BUTTON1;
+ PORTE &= ~BUTTONS_BUTTON1;
+ }
+
+ static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Buttons_GetStatus(void)
+ {
+ return ((PINE & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/CULV3/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/CULV3/LEDs.h
new file mode 100644
index 000000000..3d2b8fda0
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/CULV3/LEDs.h
@@ -0,0 +1,135 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Busware CUL V3.
+ * \copydetails Group_LEDs_CULV3
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_CULV3 CULV3
+ * \brief Board specific LED driver header for the Busware CUL V3.
+ *
+ * Board specific LED driver header for the Busware CUL V3 (http://busware.de/tiki-index.php?page=CUL).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Yellow</td><td>General Indicator</td><td>High</td><td>PORTE.6</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_CULV3_H__
+#define __LEDS_CULV3_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 6)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS LEDS_LED1
+
+ /** LED mask for the none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRE |= LEDS_ALL_LEDS;
+ PORTE &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRE &= ~LEDS_ALL_LEDS;
+ PORTE &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTE |= LEDMask;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTE &= ~LEDMask;
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTE = ((PORTE & ~LEDS_ALL_LEDS) | LEDMask);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTE = ((PORTE & ~LEDMask) | ActiveMask);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PINE = LEDMask;
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return (PORTE & LEDS_ALL_LEDS);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/DUCE/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/DUCE/Board.h
new file mode 100644
index 000000000..44cf6918b
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/DUCE/Board.h
@@ -0,0 +1,78 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the DorkbotPDX Duce.
+ * \copydetails Group_BoardInfo_DUCE
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_DUCE DUCE
+ * \brief Board specific information header for the DorkbotPDX Duce.
+ *
+ * Board specific information header for the DorkbotPDX Duce (http://dorkbotpdx.org/wiki/duce).
+ *
+ * @{
+ */
+
+#ifndef __BOARD_DUCE_H__
+#define __BOARD_DUCE_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/DUCE/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/DUCE/LEDs.h
new file mode 100644
index 000000000..83cadedff
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/DUCE/LEDs.h
@@ -0,0 +1,147 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the DorkbotPDX Duce.
+ * \copydetails Group_LEDs_DUCE
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_DUCE DUCE
+ * \brief Board specific LED driver header for the DorkbotPDX Duce.
+ *
+ * Board specific LED driver header for the DorkbotPDX Duce (http://dorkbotpdx.org/wiki/duce).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Red</td><td>Bicolor Indicator 1</td><td>High</td><td>PORTC.4</td></tr>
+ * <tr><td>LEDS_LED2</td><td>Green</td><td>Bicolor Indicator 1</td><td>High</td><td>PORTC.5</td></tr>
+ * <tr><td>LEDS_LED3</td><td>Red</td><td>Bicolor Indicator 2</td><td>High</td><td>PORTC.6</td></tr>
+ * <tr><td>LEDS_LED4</td><td>Green</td><td>Bicolor Indicator 2</td><td>High</td><td>PORTC.7</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_DUCE_H__
+#define __LEDS_DUCE_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 4)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1 << 5)
+
+ /** LED mask for the third LED on the board. */
+ #define LEDS_LED3 (1 << 6)
+
+ /** LED mask for the fourth LED on the board. */
+ #define LEDS_LED4 (1 << 7)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3 | LEDS_LED4)
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRC |= LEDS_ALL_LEDS;
+ PORTC &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRC &= ~LEDS_ALL_LEDS;
+ PORTC &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTC |= LEDMask;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTC &= ~LEDMask;
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTC = ((PORTC & ~LEDS_ALL_LEDS) | LEDMask);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTC = ((PORTC & ~LEDMask) | ActiveMask);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PINC = LEDMask;
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return (PORTC & LEDS_ALL_LEDS);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/EVK527/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/EVK527/Board.h
new file mode 100644
index 000000000..c77c18b9b
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/EVK527/Board.h
@@ -0,0 +1,90 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Atmel EVK527.
+ * \copydetails Group_BoardInfo_EVK527
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_EVK527 EVK527
+ * \brief Board specific information header for the Atmel EVK527.
+ *
+ * Board specific information header for the Atmel EVK527.
+ *
+ * @{
+ */
+
+#ifndef __BOARD_EVK527_H__
+#define __BOARD_EVK527_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../Buttons.h"
+ #include "../../Dataflash.h"
+ #include "../../Joystick.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware Buttons mounted. */
+ #define BOARD_HAS_BUTTONS
+
+ /** Indicates the board has a hardware Dataflash mounted. */
+ #define BOARD_HAS_DATAFLASH
+
+ /** Indicates the board has a hardware Joystick mounted. */
+ #define BOARD_HAS_JOYSTICK
+
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/EVK527/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/EVK527/Buttons.h
new file mode 100644
index 000000000..239880cc6
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/EVK527/Buttons.h
@@ -0,0 +1,103 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Buttons driver header for the Atmel EVK527.
+ * \copydetails Group_Buttons_EVK527
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Buttons driver
+ * dispatch header located in LUFA/Drivers/Board/Buttons.h.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_EVK527 EVK527
+ * \brief Board specific Buttons driver header for the Atmel EVK527.
+ *
+ * Board specific Buttons driver header for the Atmel EVK527.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>BUTTONS_BUTTON1</td><td>HWB Button</td><td>Low</td><td>PORTE.2</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __BUTTONS_EVK527_H__
+#define __BUTTONS_EVK527_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Button mask for the first button on the board. */
+ #define BUTTONS_BUTTON1 (1 << 2)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+ DDRE &= ~BUTTONS_BUTTON1;
+ PORTE |= BUTTONS_BUTTON1;
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+ DDRE &= ~BUTTONS_BUTTON1;
+ PORTE &= ~BUTTONS_BUTTON1;
+ }
+
+ static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Buttons_GetStatus(void)
+ {
+ return ((PINE & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/EVK527/Dataflash.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/EVK527/Dataflash.h
new file mode 100644
index 000000000..38b2b5889
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/EVK527/Dataflash.h
@@ -0,0 +1,222 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Dataflash driver header for the Atmel EVK527.
+ * \copydetails Group_Dataflash_EVK527
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the dataflash driver
+ * dispatch header located in LUFA/Drivers/Board/Dataflash.h.
+ */
+
+/** \ingroup Group_Dataflash
+ * \defgroup Group_Dataflash_EVK527 EVK527
+ * \brief Board specific Dataflash driver header for the Atmel EVK527.
+ *
+ * Board specific Dataflash driver header for the Atmel EVK527.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Select Pin</th><th>SPI Port</th></tr>
+ * <tr><td>DATAFLASH_CHIP1</td><td>AT45DB321C (4MB)</td><td>PORTE.6</td><td>SPI0</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __DATAFLASH_EVK527_H__
+#define __DATAFLASH_EVK527_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../../Misc/AT45DB321C.h"
+ #include "../../../Peripheral/SPI.h"
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_DATAFLASH_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Dataflash.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define DATAFLASH_CHIPCS_MASK DATAFLASH_CHIP1
+ #define DATAFLASH_CHIPCS_DDR DDRE
+ #define DATAFLASH_CHIPCS_PORT PORTE
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Constant indicating the total number of dataflash ICs mounted on the selected board. */
+ #define DATAFLASH_TOTALCHIPS 1
+
+ /** Mask for no dataflash chip selected. */
+ #define DATAFLASH_NO_CHIP 0
+
+ /** Mask for the first dataflash chip selected. */
+ #define DATAFLASH_CHIP1 (1 << 6)
+
+ /** Internal main memory page size for the board's dataflash IC. */
+ #define DATAFLASH_PAGE_SIZE 512
+
+ /** Total number of pages inside the board's dataflash IC. */
+ #define DATAFLASH_PAGES 8192
+
+ /* Inline Functions: */
+ /** Initializes the dataflash driver so that commands and data may be sent to an attached dataflash IC.
+ * The appropriate SPI interface will be automatically configured.
+ */
+ static inline void Dataflash_Init(void)
+ {
+ DATAFLASH_CHIPCS_DDR |= DATAFLASH_CHIPCS_MASK;
+ DATAFLASH_CHIPCS_PORT |= DATAFLASH_CHIPCS_MASK;
+
+ SPI_Init(SPI_SPEED_FCPU_DIV_2 | SPI_ORDER_MSB_FIRST | SPI_SCK_LEAD_FALLING | SPI_SAMPLE_TRAILING | SPI_MODE_MASTER);
+ }
+
+ /** Sends a byte to the currently selected dataflash IC, and returns a byte from the dataflash.
+ *
+ * \param[in] Byte Byte of data to send to the dataflash
+ *
+ * \return Last response byte from the dataflash
+ */
+ static inline uint8_t Dataflash_TransferByte(const uint8_t Byte) ATTR_ALWAYS_INLINE;
+ static inline uint8_t Dataflash_TransferByte(const uint8_t Byte)
+ {
+ return SPI_TransferByte(Byte);
+ }
+
+ /** Sends a byte to the currently selected dataflash IC, and ignores the next byte from the dataflash.
+ *
+ * \param[in] Byte Byte of data to send to the dataflash
+ */
+ static inline void Dataflash_SendByte(const uint8_t Byte) ATTR_ALWAYS_INLINE;
+ static inline void Dataflash_SendByte(const uint8_t Byte)
+ {
+ SPI_SendByte(Byte);
+ }
+
+ /** Sends a dummy byte to the currently selected dataflash IC, and returns the next byte from the dataflash.
+ *
+ * \return Last response byte from the dataflash
+ */
+ static inline uint8_t Dataflash_ReceiveByte(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Dataflash_ReceiveByte(void)
+ {
+ return SPI_ReceiveByte();
+ }
+
+ /** Determines the currently selected dataflash chip.
+ *
+ * \return Mask of the currently selected Dataflash chip, either \ref DATAFLASH_NO_CHIP if no chip is selected
+ * or a DATAFLASH_CHIPn mask (where n is the chip number).
+ */
+ static inline uint8_t Dataflash_GetSelectedChip(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Dataflash_GetSelectedChip(void)
+ {
+ return (~DATAFLASH_CHIPCS_PORT & DATAFLASH_CHIPCS_MASK);
+ }
+
+ /** Selects the given dataflash chip.
+ *
+ * \param[in] ChipMask Mask of the Dataflash IC to select, in the form of a \c DATAFLASH_CHIPn mask (where n is
+ * the chip number).
+ */
+ static inline void Dataflash_SelectChip(const uint8_t ChipMask) ATTR_ALWAYS_INLINE;
+ static inline void Dataflash_SelectChip(const uint8_t ChipMask)
+ {
+ DATAFLASH_CHIPCS_PORT = ((DATAFLASH_CHIPCS_PORT | DATAFLASH_CHIPCS_MASK) & ~ChipMask);
+ }
+
+ /** Deselects the current dataflash chip, so that no dataflash is selected. */
+ static inline void Dataflash_DeselectChip(void) ATTR_ALWAYS_INLINE;
+ static inline void Dataflash_DeselectChip(void)
+ {
+ Dataflash_SelectChip(DATAFLASH_NO_CHIP);
+ }
+
+ /** Selects a dataflash IC from the given page number, which should range from 0 to
+ * ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1). For boards containing only one
+ * dataflash IC, this will select DATAFLASH_CHIP1. If the given page number is outside
+ * the total number of pages contained in the boards dataflash ICs, all dataflash ICs
+ * are deselected.
+ *
+ * \param[in] PageAddress Address of the page to manipulate, ranging from
+ * 0 to ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1).
+ */
+ static inline void Dataflash_SelectChipFromPage(const uint16_t PageAddress)
+ {
+ Dataflash_DeselectChip();
+
+ if (PageAddress >= DATAFLASH_PAGES)
+ return;
+
+ Dataflash_SelectChip(DATAFLASH_CHIP1);
+ }
+
+ /** Toggles the select line of the currently selected dataflash IC, so that it is ready to receive
+ * a new command.
+ */
+ static inline void Dataflash_ToggleSelectedChipCS(void)
+ {
+ uint8_t SelectedChipMask = Dataflash_GetSelectedChip();
+
+ Dataflash_DeselectChip();
+ Dataflash_SelectChip(SelectedChipMask);
+ }
+
+ /** Spin-loops while the currently selected dataflash is busy executing a command, such as a main
+ * memory page program or main memory to buffer transfer.
+ */
+ static inline void Dataflash_WaitWhileBusy(void)
+ {
+ Dataflash_ToggleSelectedChipCS();
+ Dataflash_SendByte(DF_CMD_GETSTATUS);
+ while (!(Dataflash_ReceiveByte() & DF_STATUS_READY));
+ Dataflash_ToggleSelectedChipCS();
+ }
+
+ /** Sends a set of page and buffer address bytes to the currently selected dataflash IC, for use with
+ * dataflash commands which require a complete 24-bit address.
+ *
+ * \param[in] PageAddress Page address within the selected dataflash IC
+ * \param[in] BufferByte Address within the dataflash's buffer
+ */
+ static inline void Dataflash_SendAddressBytes(uint16_t PageAddress,
+ const uint16_t BufferByte)
+ {
+ Dataflash_SendByte(PageAddress >> 5);
+ Dataflash_SendByte((PageAddress << 3) | (BufferByte >> 8));
+ Dataflash_SendByte(BufferByte);
+ }
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/EVK527/Joystick.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/EVK527/Joystick.h
new file mode 100644
index 000000000..492c70699
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/EVK527/Joystick.h
@@ -0,0 +1,130 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific joystick driver header for the Atmel EVK527.
+ * \copydetails Group_Joystick_EVK527
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the joystick driver
+ * dispatch header located in LUFA/Drivers/Board/Joystick.h.
+ */
+
+/** \ingroup Group_Joystick
+ * \defgroup Group_Joystick_EVK527 EVK527
+ * \brief Board specific joystick driver header for the Atmel EVK527.
+ *
+ * Board specific joystick driver header for the Atmel EVK527.
+ *
+ * <table>
+ * <tr><th>Left Port Pin</th><th>Up Port Pin</th><th>Right Port Pin</th><th>Down Port Pin</th><th>Press Port Pin</th></tr>
+ * <tr><td>PORTF.4</td><td>PORTF.5</td><td>PORTF.7</td><td>PORTC.6</td><td>PORTF.6</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __JOYSTICK_EVK527_H__
+#define __JOYSTICK_EVK527_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_JOYSTICK_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Joystick.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define JOY_FMASK ((1 << 4) | (1 << 5) | (1 << 6) | (1 << 7))
+ #define JOY_CMASK (1 << 6)
+
+ #define JOY_PORTC_MASK_SHIFT 3
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Mask for the joystick being pushed in the left direction. */
+ #define JOY_LEFT (1 << 4)
+
+ /** Mask for the joystick being pushed in the right direction. */
+ #define JOY_RIGHT (1 << 7)
+
+ /** Mask for the joystick being pushed in the upward direction. */
+ #define JOY_UP (1 << 5)
+
+ /** Mask for the joystick being pushed in the downward direction. */
+ #define JOY_DOWN ((1 << 6) >> JOY_PORTC_MASK_SHIFT)
+
+ /** Mask for the joystick being pushed inward. */
+ #define JOY_PRESS (1 << 6)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Joystick_Init(void)
+ {
+ DDRF &= ~JOY_FMASK;
+ DDRC &= ~JOY_CMASK;
+
+ PORTF |= JOY_FMASK;
+ PORTC |= JOY_CMASK;
+ }
+
+ static inline void Joystick_Disable(void)
+ {
+ DDRF &= ~JOY_FMASK;
+ DDRC &= ~JOY_CMASK;
+
+ PORTF &= ~JOY_FMASK;
+ PORTC &= ~JOY_CMASK;
+ }
+
+ static inline uint8_t Joystick_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Joystick_GetStatus(void)
+ {
+ return (((uint8_t)~PINF & JOY_FMASK) | (((uint8_t)~PINC & JOY_CMASK) >> JOY_PORTC_MASK_SHIFT));
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/EVK527/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/EVK527/LEDs.h
new file mode 100644
index 000000000..84e689a4b
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/EVK527/LEDs.h
@@ -0,0 +1,143 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Atmel EVK527.
+ * \copydetails Group_LEDs_EVK527
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_EVK527 EVK527
+ * \brief Board specific LED driver header for the Atmel EVK527.
+ *
+ * Board specific LED driver header for the Atmel EVK527.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Green</td><td>General Indicator</td><td>High</td><td>PORTD.5</td></tr>
+ * <tr><td>LEDS_LED2</td><td>Green</td><td>General Indicator</td><td>High</td><td>PORTD.6</td></tr>
+ * <tr><td>LEDS_LED3</td><td>Green</td><td>General Indicator</td><td>High</td><td>PORTD.7</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_EVK527_H__
+#define __LEDS_EVK527_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 5)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1 << 6)
+
+ /** LED mask for the third LED on the board. */
+ #define LEDS_LED3 (1 << 7)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3)
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRD |= LEDS_ALL_LEDS;
+ PORTD &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRD &= ~LEDS_ALL_LEDS;
+ PORTD &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTD |= LEDMask;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTD &= ~LEDMask;
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTD = ((PORTD & ~LEDS_ALL_LEDS) | LEDMask);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTD = ((PORTD & ~LEDMask) | ActiveMask);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PIND = LEDMask;
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return (PORTD & LEDS_ALL_LEDS);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/JMDBU2/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/JMDBU2/Board.h
new file mode 100644
index 000000000..0f1aca09d
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/JMDBU2/Board.h
@@ -0,0 +1,82 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Mattairtech JM-DB-U2.
+ * \copydetails Group_BoardInfo_JMDBU2
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_JMDBU2 JMDBU2
+ * \brief Board specific information header for the Mattairtech JM-DB-U2.
+ *
+ * Board specific information header for the Mattairtech JM-DB-U2 (http://u2.mattair.net/index.html).
+ *
+ * @{
+ */
+
+#ifndef __BOARD_JMDBU2_H__
+#define __BOARD_JMDBU2_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../Buttons.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware Buttons mounted. */
+ #define BOARD_HAS_BUTTONS
+
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/JMDBU2/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/JMDBU2/Buttons.h
new file mode 100644
index 000000000..80500993d
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/JMDBU2/Buttons.h
@@ -0,0 +1,103 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Buttons driver header for the Mattairtech JM-DB-U2.
+ * \copydetails Group_Buttons_JMDBU2
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Buttons driver
+ * dispatch header located in LUFA/Drivers/Board/Buttons.h.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_JMDBU2 JMDBU2
+ * \brief Board specific Buttons driver header for the Mattairtech JM-DB-U2.
+ *
+ * Board specific Buttons driver header for the Mattairtech JM-DB-U2 (http://u2.mattair.net/index.html).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>BUTTONS_BUTTON1</td><td>HWB Button</td><td>Low</td><td>PORTD.7</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __BUTTONS_JMDBU2_H__
+#define __BUTTONS_JMDBU2_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Button mask for the first button on the board. */
+ #define BUTTONS_BUTTON1 (1 << 7)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+ DDRD &= ~BUTTONS_BUTTON1;
+ PORTD |= BUTTONS_BUTTON1;
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+ DDRD &= ~BUTTONS_BUTTON1;
+ PORTD &= ~BUTTONS_BUTTON1;
+ }
+
+ static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Buttons_GetStatus(void)
+ {
+ return ((PIND & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/JMDBU2/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/JMDBU2/LEDs.h
new file mode 100644
index 000000000..562103e33
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/JMDBU2/LEDs.h
@@ -0,0 +1,135 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Mattairtech JM-DB-U2.
+ * \copydetails Group_LEDs_JMDBU2
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_JMDBU2 JMDBU2
+ * \brief Board specific LED driver header for the Mattairtech JM-DB-U2.
+ *
+ * Board specific LED driver header for the Mattairtech JM-DB-U2 (http://u2.mattair.net/index.html).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Green</td><td>General Indicator</td><td>High</td><td>PORTD.4</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_JMDBU2_H__
+#define __LEDS_JMDBU2_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 4)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS LEDS_LED1
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRD |= LEDS_ALL_LEDS;
+ PORTD &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRD &= ~LEDS_ALL_LEDS;
+ PORTD &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTD |= LEDMask;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTD &= ~LEDMask;
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTD = ((PORTD & ~LEDS_ALL_LEDS) | LEDMask);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTD = ((PORTD & ~LEDMask) | ActiveMask);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PIND = LEDMask;
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return (PORTD & LEDS_ALL_LEDS);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/LEONARDO/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/LEONARDO/Board.h
new file mode 100644
index 000000000..95ef437f5
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/LEONARDO/Board.h
@@ -0,0 +1,78 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Arduino Leonardo board.
+ * \copydetails Group_BoardInfo_LEONARDO
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_LEONARDO LEONARDO
+ * \brief Board specific information header for the Arduino Leonardo board.
+ *
+ * Board specific information header for the Arduino Leonardo board (http://arduino.cc/en/Main/arduinoBoardLeonardo).
+ *
+ * @{
+ */
+
+#ifndef __BOARD_LEONARDO_H__
+#define __BOARD_LEONARDO_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/LEONARDO/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/LEONARDO/LEDs.h
new file mode 100644
index 000000000..ea7d41c01
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/LEONARDO/LEDs.h
@@ -0,0 +1,169 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Arduino Leonardo board.
+ * \copydetails Group_LEDs_LEONARDO
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_LEONARDO LEONARDO
+ * \brief Board specific LED driver header for the Arduino Leonardo board.
+ *
+ * Board specific LED driver header for the Arduino Leonardo board (http://arduino.cc/en/Main/arduinoBoardLeonardo).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Yellow</td><td>RX</td><td>Low</td><td>PORTB.0</td></tr>
+ * <tr><td>LEDS_LED2</td><td>Yellow</td><td>TX</td><td>Low</td><td>PORTD.5</td></tr>
+ * <tr><td>LEDS_LED3</td><td>Yellow</td><td>General Indicator</td><td>High</td><td>PORTC.7</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_LEONARDO_H__
+#define __LEDS_LEONARDO_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define LEDS_PORTB_LEDS (LEDS_LED1)
+ #define LEDS_PORTD_LEDS (LEDS_LED2)
+ #define LEDS_PORTC_LEDS (LEDS_LED3)
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 0)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1 << 5)
+
+ /** LED mask for the third LED on the board. */
+ #define LEDS_LED3 (1 << 7)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3)
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRB |= LEDS_PORTB_LEDS;
+ PORTB |= LEDS_PORTB_LEDS;
+ DDRD |= LEDS_PORTD_LEDS;
+ PORTD |= LEDS_PORTD_LEDS;
+ DDRC |= LEDS_PORTC_LEDS;
+ PORTC &= ~LEDS_PORTC_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRB &= ~LEDS_PORTB_LEDS;
+ PORTB &= ~LEDS_PORTB_LEDS;
+ DDRD &= ~LEDS_PORTD_LEDS;
+ PORTD &= ~LEDS_PORTD_LEDS;
+ DDRC &= ~LEDS_PORTC_LEDS;
+ PORTC &= ~LEDS_PORTC_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTB &= ~(LEDMask & LEDS_PORTB_LEDS);
+ PORTD &= ~(LEDMask & LEDS_PORTD_LEDS);
+ PORTC |= (LEDMask & LEDS_PORTC_LEDS);
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTB |= (LEDMask & LEDS_PORTB_LEDS);
+ PORTD |= (LEDMask & LEDS_PORTD_LEDS);
+ PORTC &= ~(LEDMask & LEDS_PORTC_LEDS);
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTB = ((PORTB | LEDS_PORTB_LEDS) & ~(LEDMask & LEDS_PORTB_LEDS));
+ PORTD = ((PORTD | LEDS_PORTD_LEDS) & ~(LEDMask & LEDS_PORTD_LEDS));
+ PORTC = ((PORTC & ~LEDS_PORTC_LEDS) | (LEDMask & LEDS_PORTC_LEDS));
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTB = ((PORTB | (LEDMask & LEDS_PORTB_LEDS)) & ~(ActiveMask & LEDS_PORTB_LEDS));
+ PORTD = ((PORTD | (LEDMask & LEDS_PORTD_LEDS)) & ~(ActiveMask & LEDS_PORTD_LEDS));
+ PORTC = ((PORTC & ~(LEDMask & LEDS_PORTC_LEDS)) | (ActiveMask & LEDS_PORTC_LEDS));
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PINB = (LEDMask & LEDS_PORTB_LEDS);
+ PIND = (LEDMask & LEDS_PORTD_LEDS);
+ PINC = (LEDMask & LEDS_PORTC_LEDS);
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return ((~PORTB & LEDS_PORTB_LEDS) | (~PORTD & LEDS_PORTD_LEDS) | (PORTC & LEDS_PORTC_LEDS));
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MAXIMUS/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MAXIMUS/Board.h
new file mode 100644
index 000000000..929e60a8c
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MAXIMUS/Board.h
@@ -0,0 +1,78 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Maximus board.
+ * \copydetails Group_BoardInfo_MAXIMUS
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_MAXIMUS MAXIMUS
+ * \brief Board specific information header for the Maximus board.
+ *
+ * Board specific information header for the Maximus (http://www.avrusb.com/).
+ *
+ * @{
+ */
+
+#ifndef __BOARD_MAXIMUS_H__
+#define __BOARD_MAXIMUS_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MAXIMUS/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MAXIMUS/LEDs.h
new file mode 100644
index 000000000..695949a17
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MAXIMUS/LEDs.h
@@ -0,0 +1,139 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Maximus.
+ * \copydetails Group_LEDs_MAXIMUS
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_MAXIMUS MAXIMUS
+ * \brief Board specific LED driver header for the Maximus.
+ *
+ * Board specific LED driver header for the Maximus (http://www.avrusb.com/).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Green</td><td>LG</td><td>High</td><td>PORTB.6</td></tr>
+ * <tr><td>LEDS_LED2</td><td>Red</td><td>LR</td><td>High</td><td>PORTB.7</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_MAXIMUS_H__
+#define __LEDS_MAXIMUS_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 6)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1 << 7)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2)
+
+ /** LED mask for the none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRB |= LEDS_ALL_LEDS;
+ PORTB &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRB &= ~LEDS_ALL_LEDS;
+ PORTB &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTB |= LEDMask;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTB &= ~LEDMask;
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTB = ((PORTB & ~LEDS_ALL_LEDS) | LEDMask);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTB = ((PORTB & ~LEDMask) | ActiveMask);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PINB = LEDMask;
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return (PORTB & LEDS_ALL_LEDS);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICRO/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICRO/Board.h
new file mode 100644
index 000000000..622bfc8b9
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICRO/Board.h
@@ -0,0 +1,78 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Arduino Micro board.
+ * \copydetails Group_BoardInfo_MICRO
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_MICRO MICRO
+ * \brief Board specific information header for the Arduino Micro board.
+ *
+ * Board specific information header for the Arduino Micro board (http://arduino.cc/en/Main/arduinoBoardMicro).
+ *
+ * @{
+ */
+
+#ifndef __BOARD_MICRO_H__
+#define __BOARD_MICRO_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICRO/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICRO/LEDs.h
new file mode 100644
index 000000000..c3e471d5f
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICRO/LEDs.h
@@ -0,0 +1,169 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Arduino Micro board.
+ * \copydetails Group_LEDs_MICRO
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_MICRO MICRO
+ * \brief Board specific LED driver header for the Arduino Micro board.
+ *
+ * Board specific LED driver header for the Arduino Micro board (http://arduino.cc/en/Main/arduinoBoardMicro).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Yellow</td><td>RX</td><td>High</td><td>PORTB.0</td></tr>
+ * <tr><td>LEDS_LED2</td><td>Yellow</td><td>TX</td><td>High</td><td>PORTD.5</td></tr>
+ * <tr><td>LEDS_LED3</td><td>Green</td><td>General Indicator</td><td>High</td><td>PORTC.7</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_MICRO_H__
+#define __LEDS_MICRO_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define LEDS_PORTB_LEDS (LEDS_LED1)
+ #define LEDS_PORTD_LEDS (LEDS_LED2)
+ #define LEDS_PORTC_LEDS (LEDS_LED3)
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 0)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1 << 5)
+
+ /** LED mask for the third LED on the board. */
+ #define LEDS_LED3 (1 << 7)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3)
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRB |= LEDS_PORTB_LEDS;
+ PORTB &= ~LEDS_PORTB_LEDS;
+ DDRD |= LEDS_PORTD_LEDS;
+ PORTD &= ~LEDS_PORTD_LEDS;
+ DDRC |= LEDS_PORTC_LEDS;
+ PORTC &= ~LEDS_PORTC_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRB &= ~LEDS_PORTB_LEDS;
+ PORTB &= ~LEDS_PORTB_LEDS;
+ DDRD &= ~LEDS_PORTD_LEDS;
+ PORTD &= ~LEDS_PORTD_LEDS;
+ DDRC &= ~LEDS_PORTC_LEDS;
+ PORTC &= ~LEDS_PORTC_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTB |= (LEDMask & LEDS_PORTB_LEDS);
+ PORTD |= (LEDMask & LEDS_PORTD_LEDS);
+ PORTC |= (LEDMask & LEDS_PORTC_LEDS);
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTB &= ~(LEDMask & LEDS_PORTB_LEDS);
+ PORTD &= ~(LEDMask & LEDS_PORTD_LEDS);
+ PORTC &= ~(LEDMask & LEDS_PORTC_LEDS);
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTB = ((PORTB & ~LEDS_PORTB_LEDS) | (LEDMask & LEDS_PORTB_LEDS));
+ PORTD = ((PORTD & ~LEDS_PORTD_LEDS) | (LEDMask & LEDS_PORTD_LEDS));
+ PORTC = ((PORTC & ~LEDS_PORTC_LEDS) | (LEDMask & LEDS_PORTC_LEDS));
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTB = ((PORTB & ~(LEDMask & LEDS_PORTB_LEDS)) | (ActiveMask & LEDS_PORTB_LEDS));
+ PORTD = ((PORTD & ~(LEDMask & LEDS_PORTD_LEDS)) | (ActiveMask & LEDS_PORTD_LEDS));
+ PORTC = ((PORTC & ~(LEDMask & LEDS_PORTC_LEDS)) | (ActiveMask & LEDS_PORTC_LEDS));
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PORTB ^= (LEDMask & LEDS_PORTB_LEDS);
+ PORTD ^= (LEDMask & LEDS_PORTD_LEDS);
+ PORTC ^= (LEDMask & LEDS_PORTC_LEDS);
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return ((PORTB & LEDS_PORTB_LEDS) | (PORTD & LEDS_PORTD_LEDS) | (PORTC & LEDS_PORTC_LEDS));
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICROPENDOUS/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICROPENDOUS/Board.h
new file mode 100644
index 000000000..b84bf790b
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICROPENDOUS/Board.h
@@ -0,0 +1,149 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Micropendous series boards.
+ * \copydetails Group_BoardInfo_MICROPENDOUS_32U2
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_MICROPENDOUS_A MICROPENDOUS_A
+ * \brief Board specific information header for the Micropendous A (https://code.google.com/p/micropendous/wiki/MicropendousA).
+ *
+ * See \ref Group_BoardInfo_MICROPENDOUS_32U2 for more details.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_MICROPENDOUS_1 MICROPENDOUS_1
+ * \brief Board specific information header for the Micropendous 1 (https://code.google.com/p/micropendous/wiki/Micropendous1).
+ *
+ * See \ref Group_BoardInfo_MICROPENDOUS_32U2 for more details.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_MICROPENDOUS_2 MICROPENDOUS_2
+ * \brief Board specific information header for the Micropendous 2 (https://code.google.com/p/micropendous/wiki/Micropendous2).
+ *
+ * See \ref Group_BoardInfo_MICROPENDOUS_32U2 for more details.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_MICROPENDOUS_3 MICROPENDOUS_3
+ * \brief Board specific information header for the Micropendous 3 (https://code.google.com/p/micropendous/wiki/Micropendous3).
+ *
+ * See \ref Group_BoardInfo_MICROPENDOUS_32U2 for more details.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_MICROPENDOUS_4 MICROPENDOUS_4
+ * \brief Board specific information header for the Micropendous 4 (https://code.google.com/p/micropendous/wiki/Micropendous4).
+ *
+ * See \ref Group_BoardInfo_MICROPENDOUS_32U2 for more details.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_MICROPENDOUS_DIP MICROPENDOUS_DIP
+ * \brief Board specific information header for the Micropendous DIP (https://code.google.com/p/micropendous/wiki/MicropendousDIP).
+ *
+ * See \ref Group_BoardInfo_MICROPENDOUS_32U2 for more details.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_MICROPENDOUS_REV1 MICROPENDOUS_REV1
+ * \brief Board specific information header for the Micropendous Arduino-like Revision 1 (https://code.google.com/p/micropendous/wiki/Micropendous).
+ *
+ * See \ref Group_BoardInfo_MICROPENDOUS_32U2 for more details.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_MICROPENDOUS_REV2 MICROPENDOUS_REV2
+ * \brief Board specific information header for the Micropendous Arduino-like Revision 2 (https://code.google.com/p/micropendous/wiki/Micropendous).
+ *
+ * See \ref Group_BoardInfo_MICROPENDOUS_32U2 for more details.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_MICROPENDOUS_32U2 MICROPENDOUS_32U2
+ * \brief Board specific information header for the Micropendous series boards.
+ *
+ * Board specific information header for the Micropendous series boards (https://code.google.com/p/micropendous).
+ *
+ * @{
+ */
+
+#ifndef __BOARD_MICROPENDOUS_H__
+#define __BOARD_MICROPENDOUS_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ #if ((BOARD == BOARD_MICROPENDOUS_32U2) || (BOARD == BOARD_MICROPENDOUS_A) || \
+ (BOARD == BOARD_MICROPENDOUS_1) || (BOARD == BOARD_MICROPENDOUS_2) || \
+ (BOARD == BOARD_MICROPENDOUS_3) || (BOARD == BOARD_MICROPENDOUS_4) || \
+ (BOARD == BOARD_MICROPENDOUS_REV1) || (BOARD == BOARD_MICROPENDOUS_REV2) || \
+ (BOARD == BOARD_MICROPENDOUS_DIP) || defined(__DOXYGEN__))
+ #include "../../Buttons.h"
+
+ /** Indicates the board has hardware Buttons mounted. */
+ #define BOARD_HAS_BUTTONS
+ #endif
+
+ #if ((BOARD == BOARD_MICROPENDOUS_REV1) || (BOARD == BOARD_MICROPENDOUS_REV2) || \
+ (BOARD == BOARD_MICROPENDOUS_32U2) || defined(__DOXYGEN__))
+ #include "../../LEDs.h"
+
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICROPENDOUS/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICROPENDOUS/Buttons.h
new file mode 100644
index 000000000..8adff2d30
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICROPENDOUS/Buttons.h
@@ -0,0 +1,205 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Buttons driver header for the Micropendous series boards.
+ * \copydetails Group_Buttons_MICROPENDOUS_32U2
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Buttons driver
+ * dispatch header located in LUFA/Drivers/Board/Buttons.h.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_MICROPENDOUS_A MICROPENDOUS_A
+ * \brief Board specific Button driver header for the Micropendous A (https://code.google.com/p/micropendous/wiki/MicropendousA).
+ *
+ * See \ref Group_Buttons_MICROPENDOUS_32U2 for more details.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_MICROPENDOUS_1 MICROPENDOUS_1
+ * \brief Board specific Button driver header for the Micropendous 1 (https://code.google.com/p/micropendous/wiki/Micropendous1).
+ *
+ * See \ref Group_Buttons_MICROPENDOUS_32U2 for more details.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_MICROPENDOUS_2 MICROPENDOUS_2
+ * \brief Board specific Button driver header for the Micropendous 2 (https://code.google.com/p/micropendous/wiki/Micropendous2).
+ *
+ * See \ref Group_Buttons_MICROPENDOUS_32U2 for more details.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_MICROPENDOUS_3 MICROPENDOUS_3
+ * \brief Board specific Button driver header for the Micropendous 3 (https://code.google.com/p/micropendous/wiki/Micropendous3).
+ *
+ * See \ref Group_Buttons_MICROPENDOUS_32U2 for more details.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_MICROPENDOUS_4 MICROPENDOUS_4
+ * \brief Board specific Button driver header for the Micropendous 4 (https://code.google.com/p/micropendous/wiki/Micropendous4).
+ *
+ * See \ref Group_Buttons_MICROPENDOUS_32U2 for more details.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_MICROPENDOUS_DIP MICROPENDOUS_DIP
+ * \brief Board specific Button driver header for the Micropendous DIP (https://code.google.com/p/micropendous/wiki/MicropendousDIP).
+ *
+ * See \ref Group_Buttons_MICROPENDOUS_32U2 for more details.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_MICROPENDOUS_REV1 MICROPENDOUS_REV1
+ * \brief Board specific Button driver header for the Micropendous Arduino-like Revision 1 (https://code.google.com/p/micropendous/wiki/Micropendous).
+ *
+ * See \ref Group_Buttons_MICROPENDOUS_32U2 for more details.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_MICROPENDOUS_REV2 MICROPENDOUS_REV2
+ * \brief Board specific Button driver header for the Micropendous Arduino-like Revision 2 (https://code.google.com/p/micropendous/wiki/Micropendous).
+ *
+ * See \ref Group_Buttons_MICROPENDOUS_32U2 for more details.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_MICROPENDOUS_32U2 MICROPENDOUS_32U2
+ * \brief Board specific Buttons driver header for the Micropendous 32U2.
+ *
+ * \note There are multiple supported Micropendous boards, compile with <code>BOARD = MICROPENDOUS_{VERSION}</code>.
+ *
+ * Board specific Buttons driver header for the Micropendous 32U2 (https://code.google.com/p/micropendous/wiki/Micropendous_32U2).
+ *
+ * <b>BOARD_MICROPENDOUS_1 and BOARD_MICROPENDOUS_32U2</b>:
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>BUTTONS_BUTTON1</td><td>HWB Button</td><td>Low</td><td>PORTD.7</td></tr>
+ * </table>
+ *
+ * <b>Other Revisions</b>:
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>BUTTONS_BUTTON1</td><td>HWB Button</td><td>Low</td><td>PORTE.2</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __BUTTONS_MICROPENDOUS_H__
+#define __BUTTONS_MICROPENDOUS_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ #if (BOARD == BOARD_MICROPENDOUS_32U2)
+ #define _BOARD_BUTTON1_MASK (1 << 7)
+ #define _BOARD_BUTTON_PORTLETTER D
+ #elif (BOARD == BOARD_MICROPENDOUS_A)
+ #define _BOARD_BUTTON1_MASK (1 << 2)
+ #define _BOARD_BUTTON_PORTLETTER E
+ #elif (BOARD == BOARD_MICROPENDOUS_1)
+ #define _BOARD_BUTTON1_MASK (1 << 7)
+ #define _BOARD_BUTTON_PORTLETTER D
+ #elif (BOARD == BOARD_MICROPENDOUS_2)
+ #define _BOARD_BUTTON1_MASK (1 << 2)
+ #define _BOARD_BUTTON_PORTLETTER E
+ #elif (BOARD == BOARD_MICROPENDOUS_3)
+ #define _BOARD_BUTTON1_MASK (1 << 2)
+ #define _BOARD_BUTTON_PORTLETTER E
+ #elif (BOARD == BOARD_MICROPENDOUS_4)
+ #define _BOARD_BUTTON1_MASK (1 << 2)
+ #define _BOARD_BUTTON_PORTLETTER E
+ #elif (BOARD == BOARD_MICROPENDOUS_DIP)
+ #define _BOARD_BUTTON1_MASK (1 << 2)
+ #define _BOARD_BUTTON_PORTLETTER E
+ #elif (BOARD == BOARD_MICROPENDOUS_REV1)
+ #define _BOARD_BUTTON1_MASK (1 << 2)
+ #define _BOARD_BUTTON_PORTLETTER E
+ #elif (BOARD == BOARD_MICROPENDOUS_REV2)
+ #define _BOARD_BUTTON1_MASK (1 << 2)
+ #define _BOARD_BUTTON_PORTLETTER E
+ #endif
+
+ #define _BOARD_BUTTON_PORT CONCAT_EXPANDED(PORT, _BOARD_BUTTON_PORTLETTER)
+ #define _BOARD_BUTTON_PIN CONCAT_EXPANDED(PIN, _BOARD_BUTTON_PORTLETTER)
+ #define _BOARD_BUTTON_DDR CONCAT_EXPANDED(DDR, _BOARD_BUTTON_PORTLETTER)
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Button mask for the first button on the board. */
+ #define BUTTONS_BUTTON1 _BOARD_BUTTON1_MASK
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+ _BOARD_BUTTON_DDR &= ~BUTTONS_BUTTON1;
+ _BOARD_BUTTON_PORT |= BUTTONS_BUTTON1;
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+ _BOARD_BUTTON_DDR &= ~BUTTONS_BUTTON1;
+ _BOARD_BUTTON_PORT &= ~BUTTONS_BUTTON1;
+ }
+
+ static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Buttons_GetStatus(void)
+ {
+ return ((_BOARD_BUTTON_PIN & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICROPENDOUS/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICROPENDOUS/LEDs.h
new file mode 100644
index 000000000..253ad3142
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICROPENDOUS/LEDs.h
@@ -0,0 +1,174 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Micropendous series boards.
+ * \copydetails Group_LEDs_MICROPENDOUS_32U2
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_MICROPENDOUS_REV1 MICROPENDOUS_REV1
+ * \brief Board specific LED driver header for the Micropendous Arduino-like Revision 1 (https://code.google.com/p/micropendous/wiki/Micropendous).
+ *
+ * See \ref Group_LEDs_MICROPENDOUS_32U2 for more details.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_MICROPENDOUS_REV2 MICROPENDOUS_REV2
+ * \brief Board specific LED driver header for the Micropendous Arduino-like Revision 2 (https://code.google.com/p/micropendous/wiki/Micropendous).
+ *
+ * See \ref Group_LEDs_MICROPENDOUS_32U2 for more details.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_MICROPENDOUS_32U2 MICROPENDOUS_32U2
+ * \brief Board specific LED driver header for the Micropendous-32U2.
+ *
+ * Board specific LED driver header for the Micropendous 32U2 (https://code.google.com/p/micropendous/wiki/Micropendous_32U2).
+ *
+ * <b>BOARD_MICROPENDOUS_32U2</b>:
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Green</td><td>General Indicator</td><td>High</td><td>PORTD.6</td></tr>
+ * </table>
+ *
+ * <b>Other Revisions</b>:
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Green</td><td>General Indicator</td><td>High</td><td>PORTB.1</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_MICROPENDOUS_H__
+#define __LEDS_MICROPENDOUS_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ #if (BOARD == BOARD_MICROPENDOUS_32U2)
+ #define _BOARD_LED1_MASK (1 << 6)
+ #define _BOARD_LED_PORTLETTER D
+ #elif (BOARD == BOARD_MICROPENDOUS_REV1)
+ #define _BOARD_LED1_MASK (1 << 1)
+ #define _BOARD_LED_PORTLETTER B
+ #elif (BOARD == BOARD_MICROPENDOUS_REV2)
+ #define _BOARD_LED1_MASK (1 << 1)
+ #define _BOARD_LED_PORTLETTER B
+ #endif
+
+ #define _BOARD_LED_PORT CONCAT_EXPANDED(PORT, _BOARD_LED_PORTLETTER)
+ #define _BOARD_LED_PIN CONCAT_EXPANDED(PIN, _BOARD_LED_PORTLETTER)
+ #define _BOARD_LED_DDR CONCAT_EXPANDED(DDR, _BOARD_LED_PORTLETTER)
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 _BOARD_LED1_MASK
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS LEDS_LED1
+
+ /** LED mask for the none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ _BOARD_LED_DDR |= LEDS_ALL_LEDS;
+ _BOARD_LED_PORT &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ _BOARD_LED_DDR &= ~LEDS_ALL_LEDS;
+ _BOARD_LED_PORT &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ _BOARD_LED_PORT |= LEDMask;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ _BOARD_LED_PORT &= ~LEDMask;
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ _BOARD_LED_PORT = ((_BOARD_LED_PORT & ~LEDS_ALL_LEDS) | LEDMask);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ _BOARD_LED_PORT = ((_BOARD_LED_PORT & ~LEDMask) | ActiveMask);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ _BOARD_LED_PIN = LEDMask;
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return (_BOARD_LED_PORT & LEDS_ALL_LEDS);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICROSIN162/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICROSIN162/Board.h
new file mode 100644
index 000000000..3ffb028c0
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICROSIN162/Board.h
@@ -0,0 +1,82 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Microsin AVR-USB162 board.
+ * \copydetails Group_BoardInfo_MICROSIN162
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_MICROSIN162 MICROSIN162
+ * \brief Board specific information header for the Microsin AVR-USB162 board.
+ *
+ * Board specific information header for the Microsin AVR-USB162 board (http://microsin.ru/content/view/685/44/).
+ *
+ * @{
+ */
+
+#ifndef __BOARD_MICROSIN162_H__
+#define __BOARD_MICROSIN162_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../Buttons.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware Buttons mounted. */
+ #define BOARD_HAS_BUTTONS
+
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICROSIN162/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICROSIN162/Buttons.h
new file mode 100644
index 000000000..68344feb2
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICROSIN162/Buttons.h
@@ -0,0 +1,103 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Buttons driver header for the Microsin AVR-USB162 board.
+ * \copydetails Group_Buttons_MICROSIN162
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Buttons driver
+ * dispatch header located in LUFA/Drivers/Board/Buttons.h.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_MICROSIN162 MICROSIN162
+ * \brief Board specific Buttons driver header for the Microsin AVR-USB162 board.
+ *
+ * Board specific Buttons driver header for the Microsin AVR-USB162 board (http://microsin.ru/content/view/685/44/).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>BUTTONS_BUTTON1</td><td>HWB Button</td><td>Low</td><td>PORTD.7</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __BUTTONS_MICROSIN162_H__
+#define __BUTTONS_MICROSIN162_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Button mask for the first button on the board. */
+ #define BUTTONS_BUTTON1 (1 << 7)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+ DDRD &= ~BUTTONS_BUTTON1;
+ PORTD |= BUTTONS_BUTTON1;
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+ DDRD &= ~BUTTONS_BUTTON1;
+ PORTD &= ~BUTTONS_BUTTON1;
+ }
+
+ static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Buttons_GetStatus(void)
+ {
+ return ((PIND & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICROSIN162/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICROSIN162/LEDs.h
new file mode 100644
index 000000000..51d1b3eba
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MICROSIN162/LEDs.h
@@ -0,0 +1,135 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Microsin AVR-USB162 board.
+ * \copydetails Group_LEDs_MICROSIN162
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_MICROSIN162 MICROSIN162
+ * \brief Board specific LED driver header for the Microsin AVR-USB162 board.
+ *
+ * Board specific LED driver header for the Microsin AVR-USB162 board (http://microsin.ru/content/view/685/44/).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Green</td><td>General Indicator</td><td>Low</td><td>PORTD.4</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_MICROSIN162_H__
+#define __LEDS_MICROSIN162_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 4)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS LEDS_LED1
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRD |= LEDS_ALL_LEDS;
+ PORTD |= LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRD &= ~LEDS_ALL_LEDS;
+ PORTD &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTD &= ~LEDMask;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTD |= LEDMask;
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTD = ((PORTD | LEDS_ALL_LEDS) & ~LEDMask);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTD = ((PORTD | LEDMask) & ~ActiveMask);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PIND = LEDMask;
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return (~PORTD & LEDS_ALL_LEDS);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MINIMUS/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MINIMUS/Board.h
new file mode 100644
index 000000000..80b8b3c86
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MINIMUS/Board.h
@@ -0,0 +1,82 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the MINIMUS.
+ * \copydetails Group_BoardInfo_MINIMUS
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_MINIMUS MINIMUS
+ * \brief Board specific information header for the MINIMUS.
+ *
+ * Board specific information header for the MINIMUS.
+ *
+ * @{
+ */
+
+#ifndef __BOARD_MINIMUS_H__
+#define __BOARD_MINIMUS_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../Buttons.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware Buttons mounted. */
+ #define BOARD_HAS_BUTTONS
+
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MINIMUS/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MINIMUS/Buttons.h
new file mode 100644
index 000000000..ec94445a8
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MINIMUS/Buttons.h
@@ -0,0 +1,103 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Buttons driver header for the MINIMUS.
+ * \copydetails Group_Buttons_MINIMUS
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Buttons driver
+ * dispatch header located in LUFA/Drivers/Board/Buttons.h.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_MINIMUS MINIMUS
+ * \brief Board specific Buttons driver header for the MINIMUS.
+ *
+ * Board specific Buttons driver header for the MINIMUS.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>BUTTONS_BUTTON1</td><td>HWB Button</td><td>Low</td><td>PORTD.7</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __BUTTONS_MINIMUS_H__
+#define __BUTTONS_MINIMUS_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Button mask for the first button on the board. */
+ #define BUTTONS_BUTTON1 (1 << 7)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+ DDRD &= ~BUTTONS_BUTTON1;
+ PORTD |= BUTTONS_BUTTON1;
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+ DDRD &= ~BUTTONS_BUTTON1;
+ PORTD &= ~BUTTONS_BUTTON1;
+ }
+
+ static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Buttons_GetStatus(void)
+ {
+ return ((PIND & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MINIMUS/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MINIMUS/LEDs.h
new file mode 100644
index 000000000..adc34686f
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MINIMUS/LEDs.h
@@ -0,0 +1,139 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the MINIMUS.
+ * \copydetails Group_LEDs_MINIMUS
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_MINIMUS MINIMUS
+ * \brief Board specific LED driver header for the MINIMUS.
+ *
+ * Board specific LED driver header for the Minimus USB (http://www.minimususb.com/).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Blue</td><td>General Indicator</td><td>Low</td><td>PORTD.5</td></tr>
+ * <tr><td>LEDS_LED2</td><td>Red</td><td>General Indicator</td><td>Low</td><td>PORTD.6</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_MINIMUS_H__
+#define __LEDS_MINIMUS_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 5)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1 << 6)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2)
+
+ /** LED mask for the none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRD |= LEDS_ALL_LEDS;
+ PORTD |= LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRD &= ~LEDS_ALL_LEDS;
+ PORTD &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTD &= ~LEDMask;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTD |= LEDMask;
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTD = ((PORTD | LEDS_ALL_LEDS) & ~LEDMask);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTD = ((PORTD & ~LEDMask) | ActiveMask);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PIND = LEDMask;
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return (~PORTD & LEDS_ALL_LEDS);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MULTIO/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MULTIO/Board.h
new file mode 100644
index 000000000..84f3d8725
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MULTIO/Board.h
@@ -0,0 +1,78 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Bitwizard Multio.
+ * \copydetails Group_BoardInfo_MULTIO
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_MULTIO MULTIO
+ * \brief Board specific information header for the Bitwizard Multio.
+ *
+ * Board specific information header for the Bitwizard Multio (http://www.bitwizard.nl/wiki/index.php/USB-multio).
+ *
+ * @{
+ */
+
+#ifndef __BOARD_MULTIO_H__
+#define __BOARD_MULTIO_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MULTIO/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MULTIO/LEDs.h
new file mode 100644
index 000000000..ca6d44041
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/MULTIO/LEDs.h
@@ -0,0 +1,161 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Bitwizard Multio.
+ * \copydetails Group_LEDs_MULTIO
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_MULTIO MULTIO
+ * \brief Board specific LED driver header for the Bitwizard Multio.
+ *
+ * Board specific LED driver header for the Bitwizard Multio (http://www.bitwizard.nl/wiki/index.php/USB-multio).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Green</td><td>General Indicator</td><td>High</td><td>PORTD.0</td></tr>
+ * <tr><td>LEDS_LED2</td><td>Green</td><td>General Indicator</td><td>High</td><td>PORTC.2</td></tr>
+ * <tr><td>LEDS_LED3</td><td>Green</td><td>General Indicator</td><td>High</td><td>PORTD.7</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_MULTIO_H__
+#define __LEDS_MULTIO_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define LEDS_PORTD_LEDS (LEDS_LED1 | LEDS_LED3)
+ #define LEDS_PORTC_LEDS LEDS_LED2
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 0)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1 << 2)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED3 (1 << 7)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3)
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRD |= LEDS_PORTD_LEDS;
+ DDRC |= LEDS_PORTC_LEDS;
+
+ PORTD &= ~LEDS_PORTD_LEDS;
+ PORTC &= ~LEDS_PORTC_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRD &= ~LEDS_PORTD_LEDS;
+ DDRC &= ~LEDS_PORTC_LEDS;
+
+ PORTD &= ~LEDS_PORTD_LEDS;
+ PORTC &= ~LEDS_PORTC_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTD |= (LEDMask & LEDS_PORTD_LEDS);
+ PORTC |= (LEDMask & LEDS_PORTC_LEDS);
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTD &= ~(LEDMask & LEDS_PORTD_LEDS);
+ PORTC &= ~(LEDMask & LEDS_PORTC_LEDS);
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTD = (PORTD & ~LEDS_PORTD_LEDS) | (LEDMask & LEDS_PORTD_LEDS);
+ PORTC = (PORTC & ~LEDS_PORTC_LEDS) | (LEDMask & LEDS_PORTC_LEDS);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTD = (PORTD & ~(LEDMask & LEDS_PORTD_LEDS)) | (ActiveMask & LEDS_PORTD_LEDS);
+ PORTC = (PORTC & ~(LEDMask & LEDS_PORTC_LEDS)) | (ActiveMask & LEDS_PORTC_LEDS);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PIND = (LEDMask & LEDS_PORTD_LEDS);
+ PINC = (LEDMask & LEDS_PORTC_LEDS);
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return ((PORTD & LEDS_PORTD_LEDS) | (PORTC & LEDS_PORTC_LEDS));
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEX162/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEX162/Board.h
new file mode 100644
index 000000000..b9bcf7734
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEX162/Board.h
@@ -0,0 +1,82 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Olimex AVR-USB-162 Development Board.
+ * \copydetails Group_BoardInfo_OLIMEX162
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_OLIMEX162 OLIMEX162
+ * \brief Board specific information header for the Olimex AVR-USB-162 Development Board.
+ *
+ * Board specific information header for the Olimex AVR-USB-162 Development Board (http://www.olimex.com/dev/avr-usb-162.html).
+ *
+ * @{
+ */
+
+#ifndef __BOARD_OLIMEX162_H__
+#define __BOARD_OLIMEX162_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../Buttons.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware Buttons mounted. */
+ #define BOARD_HAS_BUTTONS
+
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEX162/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEX162/Buttons.h
new file mode 100644
index 000000000..3714c5e9a
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEX162/Buttons.h
@@ -0,0 +1,103 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Buttons driver header for the Olimex AVR-USB-162 Development Board.
+ * \copydetails Group_Buttons_OLIMEX162
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Buttons driver
+ * dispatch header located in LUFA/Drivers/Board/Buttons.h.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_OLIMEX162 OLIMEX162
+ * \brief Board specific Buttons driver header for the Olimex AVR-USB-162 Development Board.
+ *
+ * Board specific Buttons driver header for the Olimex AVR-USB-162 Development Board (http://www.olimex.com/dev/avr-usb-162.html).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>BUTTONS_BUTTON1</td><td>HWB Button</td><td>Low</td><td>PORTD.7</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __BUTTONS_OLIMEX162_H__
+#define __BUTTONS_OLIMEX162_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Button mask for the first button on the board. */
+ #define BUTTONS_BUTTON1 (1 << 7)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+ DDRD &= ~BUTTONS_BUTTON1;
+ PORTD |= BUTTONS_BUTTON1;
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+ DDRD &= ~BUTTONS_BUTTON1;
+ PORTD &= ~BUTTONS_BUTTON1;
+ }
+
+ static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Buttons_GetStatus(void)
+ {
+ return ((PIND & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEX162/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEX162/LEDs.h
new file mode 100644
index 000000000..5ecc1f5d7
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEX162/LEDs.h
@@ -0,0 +1,135 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Olimex AVR-USB-162.
+ * \copydetails Group_LEDs_OLIMEX162
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_OLIMEX162 OLIMEX162
+ * \brief Board specific LED driver header for the Olimex AVR-USB-162.
+ *
+ * Board specific LED driver header for the Olimex AVR-USB-162 (http://www.olimex.com/dev/avr-usb-162.html).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Yellow</td><td>General Indicator</td><td>High</td><td>PORTD.4</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_OLIMEX162_H__
+#define __LEDS_OLIMEX162_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 4)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS LEDS_LED1
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRD |= LEDS_ALL_LEDS;
+ PORTD &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRD &= ~LEDS_ALL_LEDS;
+ PORTD &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTD |= LEDMask;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTD &= ~LEDMask;
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTD = ((PORTD & ~LEDS_ALL_LEDS) | LEDMask);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTD = ((PORTD & ~LEDMask) | ActiveMask);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PIND = LEDMask;
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return (PORTD & LEDS_ALL_LEDS);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEX32U4/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEX32U4/Board.h
new file mode 100644
index 000000000..657b15c6d
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEX32U4/Board.h
@@ -0,0 +1,82 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Olimex AVR-USB-32U4 Development Board.
+ * \copydetails Group_BoardInfo_OLIMEX32U4
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_OLIMEX32U4 OLIMEX32U4
+ * \brief Board specific information header for the Olimex AVR-USB-32U4 Development Board.
+ *
+ * Board specific information header for the Olimex AVR-USB-32U4 Development Board (http://www.olimex.com/dev/olimexino-32u4.html).
+ *
+ * @{
+ */
+
+#ifndef __BOARD_OLIMEX32U4_H__
+#define __BOARD_OLIMEX32U4_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../Buttons.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware Buttons mounted. */
+ #define BOARD_HAS_BUTTONS
+
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEX32U4/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEX32U4/Buttons.h
new file mode 100644
index 000000000..8e33fd965
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEX32U4/Buttons.h
@@ -0,0 +1,103 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Buttons driver header for the Olimex AVR-USB-32U4 Development Board.
+ * \copydetails Group_Buttons_OLIMEX32U4
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Buttons driver
+ * dispatch header located in LUFA/Drivers/Board/Buttons.h.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_OLIMEX32U4 OLIMEX32U4
+ * \brief Board specific Buttons driver header for the Olimex AVR-USB-32U4 Development Board.
+ *
+ * Board specific Buttons driver header for the Olimex AVR-USB-32U4 Development Board (http://www.olimex.com/dev/olimexino-32u4.html).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>BUTTONS_BUTTON1</td><td>HWB Button</td><td>Low</td><td>PORTE.2</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __BUTTONS_OLIMEX32U4_H__
+#define __BUTTONS_OLIMEX32U4_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Button mask for the first button on the board. */
+ #define BUTTONS_BUTTON1 (1 << 2)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+ DDRE &= ~BUTTONS_BUTTON1;
+ PORTE |= BUTTONS_BUTTON1;
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+ DDRE &= ~BUTTONS_BUTTON1;
+ PORTE &= ~BUTTONS_BUTTON1;
+ }
+
+ static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Buttons_GetStatus(void)
+ {
+ return ((PINE & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEX32U4/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEX32U4/LEDs.h
new file mode 100644
index 000000000..259859c90
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEX32U4/LEDs.h
@@ -0,0 +1,179 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Olimex AVR-USB-32U4.
+ * \copydetails Group_LEDs_OLIMEX32U4
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_OLIMEX32U4 OLIMEX32U4
+ * \brief Board specific LED driver header for the Olimex AVR-USB-32U4.
+ *
+ * Board specific LED driver header for the Olimex AVR-USB-32U4 (http://www.olimex.com/dev/olimexino-32u4.html).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Green</td><td>TX</td><td>High</td><td>PORTD.5</td></tr>
+ * <tr><td>LEDS_LED2</td><td>Yellow</td><td>RX</td><td>High</td><td>PORTB.0</td></tr>
+ * <tr><td>LEDS_LED3</td><td>Green</td><td>General Indicator (Default Unconnected)</td><td>High</td><td>PORTE.6</td></tr>
+ * <tr><td>LEDS_LED4</td><td>Yellow</td><td>General Indicator (Default Unconnected)</td><td>High</td><td>PORTB.5</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_OLIMEX32U4_H__
+#define __LEDS_OLIMEX32U4_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define LEDS_PORTB_LEDS (LEDS_LED2 | LEDS_LED4)
+ #define LEDS_PORTD_LEDS (LEDS_LED1)
+ #define LEDS_PORTE_LEDS (LEDS_LED3)
+
+ #define LEDS_PORTD_MASK_SHIFT 1
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 ((1 << 5) >> LEDS_PORTD_MASK_SHIFT)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1 << 0)
+
+ /** LED mask for the third LED on the board. */
+ #define LEDS_LED3 (1 << 6)
+
+ /** LED mask for the fourth LED on the board. */
+ #define LEDS_LED4 (1 << 5)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3 | LEDS_LED4)
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRB |= LEDS_PORTB_LEDS;
+ PORTB &= ~LEDS_PORTB_LEDS;
+ DDRD |= (LEDS_PORTD_LEDS << LEDS_PORTD_MASK_SHIFT);
+ PORTD &= ~(LEDS_PORTD_LEDS << LEDS_PORTD_MASK_SHIFT);
+ DDRE |= LEDS_PORTE_LEDS;
+ PORTE &= ~LEDS_PORTE_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRB &= ~LEDS_PORTB_LEDS;
+ PORTB &= ~LEDS_PORTB_LEDS;
+ DDRD &= ~(LEDS_PORTD_LEDS << LEDS_PORTD_MASK_SHIFT);
+ PORTD &= ~(LEDS_PORTD_LEDS << LEDS_PORTD_MASK_SHIFT);
+ DDRE &= ~LEDS_PORTE_LEDS;
+ PORTE &= ~LEDS_PORTE_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTB |= (LEDMask & LEDS_PORTB_LEDS);
+ PORTD |= ((LEDMask & LEDS_PORTD_LEDS) << LEDS_PORTD_MASK_SHIFT);
+ PORTE |= (LEDMask & LEDS_PORTE_LEDS);
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTB &= ~(LEDMask & LEDS_PORTB_LEDS);
+ PORTD &= ~((LEDMask & LEDS_PORTD_LEDS) << LEDS_PORTD_MASK_SHIFT);
+ PORTE &= ~(LEDMask & LEDS_PORTE_LEDS);
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTB = ((PORTB & ~LEDS_PORTB_LEDS) | (LEDMask & LEDS_PORTB_LEDS));
+ PORTD = ((PORTD & ~(LEDS_PORTD_LEDS << LEDS_PORTD_MASK_SHIFT)) |
+ ((LEDMask & LEDS_PORTD_LEDS) << LEDS_PORTD_MASK_SHIFT));
+ PORTE = ((PORTE & ~LEDS_PORTE_LEDS) | (LEDMask & LEDS_PORTE_LEDS));
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTB = ((PORTB & ~(LEDMask & LEDS_PORTB_LEDS)) | (ActiveMask & LEDS_PORTB_LEDS));
+ PORTD = ((PORTD & ~((LEDMask & LEDS_PORTD_LEDS) << LEDS_PORTD_MASK_SHIFT)) |
+ ((ActiveMask & LEDS_PORTD_LEDS) << LEDS_PORTD_MASK_SHIFT));
+ PORTE = ((PORTE & ~(LEDMask & LEDS_PORTE_LEDS)) | (ActiveMask & LEDS_PORTE_LEDS));
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PINB = (LEDMask & LEDS_PORTB_LEDS);
+ PIND = ((LEDMask & LEDS_PORTD_LEDS) << LEDS_PORTD_MASK_SHIFT);
+ PINE = (LEDMask & LEDS_PORTE_LEDS);
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return ((PORTB & LEDS_PORTB_LEDS) |
+ ((PORTD & (LEDS_PORTD_LEDS << LEDS_PORTD_MASK_SHIFT)) >> LEDS_PORTD_MASK_SHIFT) |
+ (PORTE & LEDS_PORTE_LEDS));
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/Board.h
new file mode 100644
index 000000000..d318a82b0
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/Board.h
@@ -0,0 +1,82 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Olimex AVR-ISP-MK2 Development Board.
+ * \copydetails Group_BoardInfo_OLIMEXISPMK2
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_OLIMEXISPMK2 OLIMEXISPMK2
+ * \brief Board specific information header for the Olimex AVR-ISP-MK2 Development Board.
+ *
+ * Board specific information header for the Olimex AVR-ISP-MK2 Development Board (https://www.olimex.com/dev/avr-isp-mk2.html).
+ *
+ * @{
+ */
+
+#ifndef __BOARD_OLIMEXISPMK2_H__
+#define __BOARD_OLIMEXISPMK2_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../Buttons.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware Buttons mounted. */
+ #define BOARD_HAS_BUTTONS
+
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/Buttons.h
new file mode 100644
index 000000000..aff10b103
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/Buttons.h
@@ -0,0 +1,103 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Buttons driver header for the Olimex AVR-ISP-MK2 Development Board.
+ * \copydetails Group_Buttons_OLIMEXISPMK2
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Buttons driver
+ * dispatch header located in LUFA/Drivers/Board/Buttons.h.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_OLIMEXISPMK2 OLIMEXISPMK2
+ * \brief Board specific Buttons driver header for the Olimex AVR-ISP-MK2.
+ *
+ * Board specific Buttons driver header for the Olimex AVR-ISP-MK2 Development Board (https://www.olimex.com/dev/avr-isp-mk2.html).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>BUTTONS_BUTTON1</td><td>HWB Button</td><td>Low</td><td>PORTD.7</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __BUTTONS_OLIMEXISPMK2_H__
+#define __BUTTONS_OLIMEXISPMK2_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Button mask for the first button on the board. */
+ #define BUTTONS_BUTTON1 (1 << 7)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+ DDRD &= ~BUTTONS_BUTTON1;
+ PORTD |= BUTTONS_BUTTON1;
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+ DDRD &= ~BUTTONS_BUTTON1;
+ PORTD &= ~BUTTONS_BUTTON1;
+ }
+
+ static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Buttons_GetStatus(void)
+ {
+ return ((PIND & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/LEDs.h
new file mode 100644
index 000000000..033fca05e
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/LEDs.h
@@ -0,0 +1,143 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Olimex AVR-ISP-MK2 Development Board.
+ * \copydetails Group_LEDs_OLIMEXISPMK2
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_OLIMEXISPMK2 OLIMEXISPMK2
+ * \brief Board specific LED driver header for the Olimex AVR-ISP-MK2.
+ *
+ * Board specific LED driver header for the Olimex AVR-ISP-MK2 Development Board (https://www.olimex.com/dev/avr-isp-mk2.html).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Yellow</td><td>Target Power</td><td>High</td><td>PORTB.5</td></tr>
+ * <tr><td>LEDS_LED2</td><td>Red</td><td>Activity</td><td>High</td><td>PORTB.6</td></tr>
+ * <tr><td>LEDS_LED3</td><td>Green</td><td>Ready</td><td>High</td><td>PORTB.7</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_OLIMEXISPMK2_H__
+#define __LEDS_OLIMEXISPMK2_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 5)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1 << 6)
+
+ /** LED mask for the third LED on the board. */
+ #define LEDS_LED3 (1 << 7)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3)
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRB |= LEDS_ALL_LEDS;
+ PORTB &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRB &= ~LEDS_ALL_LEDS;
+ PORTB &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTB |= LEDMask;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTB &= ~LEDMask;
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTB = ((PORTB & ~LEDS_ALL_LEDS) | LEDMask);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTB = ((PORTB & ~LEDMask) | ActiveMask);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PINB = LEDMask;
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return (PORTB & LEDS_ALL_LEDS);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/Board.h
new file mode 100644
index 000000000..690fee153
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/Board.h
@@ -0,0 +1,82 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Olimex AVR-USB-T32U4 Development Board.
+ * \copydetails Group_BoardInfo_OLIMEXT32U4
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_OLIMEXT32U4 OLIMEXT32U4
+ * \brief Board specific information header for the Olimex AVR-USB-T32U4 Development Board.
+ *
+ * Board specific information header for the Olimex AVR-USB-T32U4 Development Board (http://www.olimex.com/dev/avr-t32u4.html).
+ *
+ * @{
+ */
+
+#ifndef __BOARD_OLIMEXT32U4_H__
+#define __BOARD_OLIMEXT32U4_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../Buttons.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware Buttons mounted. */
+ #define BOARD_HAS_BUTTONS
+
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/Buttons.h
new file mode 100644
index 000000000..634eda9cb
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/Buttons.h
@@ -0,0 +1,103 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Buttons driver header for the Olimex AVR-USB-T32U4 Development Board.
+ * \copydetails Group_Buttons_OLIMEXT32U4
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Buttons driver
+ * dispatch header located in LUFA/Drivers/Board/Buttons.h.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_OLIMEXT32U4 OLIMEXT32U4
+ * \brief Board specific Buttons driver header for the Olimex AVR-USB-32U4 Development Board.
+ *
+ * Board specific Buttons driver header for the Olimex AVR-USB-T32U4 Development Board (http://www.olimex.com/dev/avr-t32u4.html).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>BUTTONS_BUTTON1</td><td>HWB Button</td><td>Low</td><td>PORTE.2</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __BUTTONS_OLIMEXT32U4_H__
+#define __BUTTONS_OLIMEXT32U4_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Button mask for the first button on the board. */
+ #define BUTTONS_BUTTON1 (1 << 2)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+ DDRE &= ~BUTTONS_BUTTON1;
+ PORTE |= BUTTONS_BUTTON1;
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+ DDRE &= ~BUTTONS_BUTTON1;
+ PORTE &= ~BUTTONS_BUTTON1;
+ }
+
+ static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Buttons_GetStatus(void)
+ {
+ return ((PINE & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/LEDs.h
new file mode 100644
index 000000000..2bbaf6826
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/LEDs.h
@@ -0,0 +1,169 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Olimex AVR-USB-T32U4.
+ * \copydetails Group_LEDs_OLIMEXT32U4
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_OLIMEXT32U4 OLIMEXT32U4
+ * \brief Board specific LED driver header for the Olimex AVR-USB-T32U4.
+ *
+ * Board specific LED driver header for the Olimex AVR-USB-T32U4 (http://www.olimex.com/dev/avr-t32u4.html).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Yellow</td><td>RX</td><td>High</td><td>PORTB.0</td></tr>
+ * <tr><td>LEDS_LED2</td><td>Green</td><td>TX</td><td>High</td><td>PORTD.5</td></tr>
+ * <tr><td>LEDS_LED3</td><td>N/A</td><td>General Indicator (Not Mounted)</td><td>High</td><td>PORTE.6</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_OLIMEXT32U4_H__
+#define __LEDS_OLIMEXT32U4_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define LEDS_PORTB_LEDS (LEDS_LED1)
+ #define LEDS_PORTD_LEDS (LEDS_LED2)
+ #define LEDS_PORTE_LEDS (LEDS_LED3)
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 0)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1 << 5)
+
+ /** LED mask for the third LED on the board. */
+ #define LEDS_LED3 (1 << 6)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3)
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRB |= LEDS_PORTB_LEDS;
+ PORTB &= ~LEDS_PORTB_LEDS;
+ DDRD |= LEDS_PORTD_LEDS;
+ PORTD &= ~LEDS_PORTD_LEDS;
+ DDRE |= LEDS_PORTE_LEDS;
+ PORTE &= ~LEDS_PORTE_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRB &= ~LEDS_PORTB_LEDS;
+ PORTB &= ~LEDS_PORTB_LEDS;
+ DDRD &= ~LEDS_PORTD_LEDS;
+ PORTD &= ~LEDS_PORTD_LEDS;
+ DDRE &= ~LEDS_PORTE_LEDS;
+ PORTE &= ~LEDS_PORTE_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTB |= (LEDMask & LEDS_PORTB_LEDS);
+ PORTD |= (LEDMask & LEDS_PORTD_LEDS);
+ PORTE |= (LEDMask & LEDS_PORTE_LEDS);
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTB &= ~(LEDMask & LEDS_PORTB_LEDS);
+ PORTD &= ~(LEDMask & LEDS_PORTD_LEDS);
+ PORTE &= ~(LEDMask & LEDS_PORTE_LEDS);
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTB = ((PORTB & ~LEDS_PORTB_LEDS) | (LEDMask & LEDS_PORTB_LEDS));
+ PORTD = ((PORTD & ~LEDS_PORTD_LEDS) | (LEDMask & LEDS_PORTD_LEDS));
+ PORTE = ((PORTE & ~LEDS_PORTE_LEDS) | (LEDMask & LEDS_PORTE_LEDS));
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTB = ((PORTB & ~(LEDMask & LEDS_PORTB_LEDS)) | (ActiveMask & LEDS_PORTB_LEDS));
+ PORTD = ((PORTD & ~(LEDMask & LEDS_PORTD_LEDS)) | (ActiveMask & LEDS_PORTD_LEDS));
+ PORTE = ((PORTE & ~(LEDMask & LEDS_PORTE_LEDS)) | (ActiveMask & LEDS_PORTE_LEDS));
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PINB = (LEDMask & LEDS_PORTB_LEDS);
+ PIND = (LEDMask & LEDS_PORTD_LEDS);
+ PINE = (LEDMask & LEDS_PORTE_LEDS);
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return ((PORTB & LEDS_PORTB_LEDS) | (PORTD & LEDS_PORTD_LEDS) | (PORTE & LEDS_PORTE_LEDS));
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/RZUSBSTICK/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/RZUSBSTICK/Board.h
new file mode 100644
index 000000000..6fc366673
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/RZUSBSTICK/Board.h
@@ -0,0 +1,78 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Atmel RZUSBSTICK.
+ * \copydetails Group_BoardInfo_RZUSBSTICK
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_RZUSBSTICK RZUSBSTICK
+ * \brief Board specific information header for the Atmel RZUSBSTICK.
+ *
+ * Board specific information header for the Atmel RZUSBSTICK.
+ *
+ * @{
+ */
+
+#ifndef __BOARD_RZUSBSTICK_H__
+#define __BOARD_RZUSBSTICK_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/RZUSBSTICK/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/RZUSBSTICK/LEDs.h
new file mode 100644
index 000000000..6ebcdfc6b
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/RZUSBSTICK/LEDs.h
@@ -0,0 +1,175 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Atmel RZUSBSTICK.
+ * \copydetails Group_LEDs_RZUSBSTICK
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_RZUSBSTICK RZUSBSTICK
+ * \brief Board specific LED driver header for the Atmel RZUSBSTICK.
+ *
+ * Board specific LED driver header for the Atmel RZUSBSTICK.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Blue</td><td>General Indicator</td><td>High</td><td>PORTD.7</td></tr>
+ * <tr><td>LEDS_LED1</td><td>Red</td><td>General Indicator</td><td>Low</td><td>PORTD.5</td></tr>
+ * <tr><td>LEDS_LED1</td><td>Green</td><td>General Indicator</td><td>Low</td><td>PORTE.6</td></tr>
+ * <tr><td>LEDS_LED1</td><td>Yellow</td><td>General Indicator</td><td>Low</td><td>PORTE.7</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_RZUSBSTICK_H__
+#define __LEDS_RZUSBSTICK_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define LEDS_PORTD_LEDS (LEDS_LED1 | LEDS_LED2)
+ #define LEDS_PORTE_LEDS (LEDS_LED3 | LEDS_LED4)
+
+ #define LEDS_PORTE_MASK_SHIFT 4
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 7)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1 << 5)
+
+ /** LED mask for the third LED on the board. */
+ #define LEDS_LED3 ((1 << 6) >> LEDS_PORTE_MASK_SHIFT)
+
+ /** LED mask for the fourth LED on the board. */
+ #define LEDS_LED4 ((1 << 7) >> LEDS_PORTE_MASK_SHIFT)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3 | LEDS_LED4)
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRD |= LEDS_PORTD_LEDS;
+ PORTD &= ~LEDS_LED1;
+ PORTD |= LEDS_LED2;
+
+ DDRE |= (LEDS_PORTE_LEDS << LEDS_PORTE_MASK_SHIFT);
+ PORTE |= (LEDS_PORTE_LEDS << LEDS_PORTE_MASK_SHIFT);
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRD &= ~LEDS_PORTD_LEDS;
+ PORTD &= ~LEDS_PORTD_LEDS;
+
+ DDRE &= ~(LEDS_PORTE_LEDS << LEDS_PORTE_MASK_SHIFT);
+ PORTE &= ~(LEDS_PORTE_LEDS << LEDS_PORTE_MASK_SHIFT);
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTD |= (LEDMask & LEDS_LED1);
+ PORTD &= ~(LEDMask & LEDS_LED2);
+ PORTE &= ~((LEDMask & LEDS_PORTE_LEDS) << LEDS_PORTE_MASK_SHIFT);
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTD &= ~(LEDMask & LEDS_LED1);
+ PORTD |= (LEDMask & LEDS_LED2);
+ PORTE |= ((LEDMask & LEDS_PORTE_LEDS) << LEDS_PORTE_MASK_SHIFT);
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTD = (((PORTD & ~LEDS_LED1) | (LEDMask & LEDS_LED1)) |
+ ((PORTD | LEDS_LED2) & ~(LEDMask & LEDS_LED2)));
+ PORTE = ((PORTE | (LEDS_PORTE_LEDS << LEDS_PORTE_MASK_SHIFT)) &
+ ~((LEDMask & LEDS_PORTE_LEDS) << LEDS_PORTE_MASK_SHIFT));
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTD = (((PORTD & ~(LEDMask & LEDS_LED1)) | (ActiveMask & LEDS_LED1)) |
+ ((PORTD | (LEDMask & LEDS_LED2)) & ~(ActiveMask & LEDS_LED2)));
+ PORTE = ((PORTE | ((LEDMask & LEDS_PORTE_LEDS) << LEDS_PORTE_MASK_SHIFT)) &
+ ~((ActiveMask & LEDS_PORTE_LEDS) << LEDS_PORTE_MASK_SHIFT));
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PIND = (LEDMask & LEDS_PORTD_LEDS);
+ PINE = ((LEDMask & LEDS_PORTE_LEDS) << LEDS_PORTE_MASK_SHIFT);
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return (((PORTD & LEDS_LED1) | (~PORTD & LEDS_LED2)) |
+ ((~PORTE & (LEDS_PORTE_LEDS << LEDS_PORTE_MASK_SHIFT)) >> LEDS_PORTE_MASK_SHIFT));
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/SPARKFUN8U2/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/SPARKFUN8U2/Board.h
new file mode 100644
index 000000000..49cc2e510
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/SPARKFUN8U2/Board.h
@@ -0,0 +1,78 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Sparkfun ATMEGA8U2 breakout board.
+ * \copydetails Group_BoardInfo_SPARKFUN8U2
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_SPARKFUN8U2 SPARKFUN8U2
+ * \brief Board specific information header for the Sparkfun ATMEGA8U2 breakout board.
+ *
+ * Board specific information header for the Sparkfun ATMEGA8U2 breakout board (http://www.sparkfun.com/products/10277).
+ *
+ * @{
+ */
+
+#ifndef __BOARD_SPARKFUN8U2_H__
+#define __BOARD_SPARKFUN8U2_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/SPARKFUN8U2/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/SPARKFUN8U2/LEDs.h
new file mode 100644
index 000000000..b8eb4abfe
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/SPARKFUN8U2/LEDs.h
@@ -0,0 +1,135 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Sparkfun ATMEGA8U2 breakout board.
+ * \copydetails Group_LEDs_SPARKFUN8U2
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_SPARKFUN8U2 SPARKFUN8U2
+ * \brief Board specific LED driver header for the Sparkfun ATMEGA8U2 breakout board.
+ *
+ * Board specific LED driver header for the Sparkfun ATMEGA8U2 breakout board (http://www.sparkfun.com/products/10277).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Green</td><td>General Indicator</td><td>Low</td><td>PORTB.4</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_SPARKFUN8U2_H__
+#define __LEDS_SPARKFUN8U2_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 4)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS LEDS_LED1
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRB |= LEDS_ALL_LEDS;
+ PORTB |= LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRB &= ~LEDS_ALL_LEDS;
+ PORTB &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTB &= ~LEDMask;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTB |= LEDMask;
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTB = ((PORTB | LEDS_ALL_LEDS) & ~LEDMask);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTB = ((PORTB | LEDMask) & ~ActiveMask);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PINB = LEDMask;
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return (~PORTB & LEDS_ALL_LEDS);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STANGE_ISP/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STANGE_ISP/Board.h
new file mode 100644
index 000000000..36594fcc0
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STANGE_ISP/Board.h
@@ -0,0 +1,82 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Dimex Stange-ISP board.
+ * \copydetails Group_BoardInfo_STANGE_ISP
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_STANGE_ISP STANGE_ISP
+ * \brief Board specific information header for the Dimex Stange-ISP board.
+ *
+ * Board specific information header for the Dimex Stange-ISP board (http://www.diamex.de/dxshop/USB-ISP-Programmer-fuer-Atmel-AVR).
+ *
+ * @{
+ */
+
+#ifndef __BOARD_STANGE_ISP_H__
+#define __BOARD_STANGE_ISP_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../Buttons.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware Buttons mounted. */
+ #define BOARD_HAS_BUTTONS
+
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STANGE_ISP/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STANGE_ISP/Buttons.h
new file mode 100644
index 000000000..d4576b688
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STANGE_ISP/Buttons.h
@@ -0,0 +1,103 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific button driver header for the Dimex Stange-ISP board.
+ * \copydetails Group_Buttons_STANGE_ISP
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Buttons driver
+ * dispatch header located in LUFA/Drivers/Board/Buttons.h.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_STANGE_ISP STANGE_ISP
+ * \brief Board specific Buttons driver header for the Dimex Stange-ISP.
+ *
+ * Board specific Buttons driver header for the Dimex Stange-ISP board (http://www.diamex.de/dxshop/USB-ISP-Programmer-fuer-Atmel-AVR).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>BUTTONS_BUTTON1</td><td>HWB Button</td><td>Low</td><td>PORTD.7</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __BUTTONS_STANGE_ISP_H__
+#define __BUTTONS_STANGE_ISP_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Button mask for the first button on the board. */
+ #define BUTTONS_BUTTON1 (1 << 7)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+ DDRD &= ~BUTTONS_BUTTON1;
+ PORTD |= BUTTONS_BUTTON1;
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+ DDRD &= ~BUTTONS_BUTTON1;
+ PORTD &= ~BUTTONS_BUTTON1;
+ }
+
+ static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Buttons_GetStatus(void)
+ {
+ return ((PIND & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STANGE_ISP/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STANGE_ISP/LEDs.h
new file mode 100644
index 000000000..9f1068379
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STANGE_ISP/LEDs.h
@@ -0,0 +1,138 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Dimex Stange-ISP board.
+ * \copydetails Group_LEDs_STANGE_ISP
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_STANGE_ISP STANGE_ISP
+ * \brief Board specific LED driver header for the Dimex Stange-ISP board.
+ *
+ * Board specific LED driver header for the Dimex Stange-ISP board (http://www.diamex.de/dxshop/USB-ISP-Programmer-fuer-Atmel-AVR).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Green</td><td>General Indicator</td><td>Low</td><td>PORTD.0</td></tr>
+ * <tr><td>LEDS_LED2</td><td>Red</td><td>General Indicator</td><td>Low</td><td>PORTD.1</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_STANGE_ISP_LEDS_H__
+#define __LEDS_STANGE_ISP_LEDS_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 0)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1 << 1)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2)
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRD |= LEDS_ALL_LEDS;
+ PORTD |= LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRD &= ~LEDS_ALL_LEDS;
+ PORTD &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTD &= ~LEDMask;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTD |= LEDMask;
+ }
+
+ static inline void LEDs_SetAllLEDs (const uint8_t LEDMask)
+ {
+ PORTD = ((PORTD | LEDS_ALL_LEDS) & ~LEDMask);
+ }
+
+ static inline void LEDs_ChangeLEDs ( const uint8_t LEDMask, const uint8_t ActiveMask)
+ {
+ PORTD = ((PORTD | LEDMask) & ~ActiveMask);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PIND = LEDMask;
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return (~PORTD & LEDS_ALL_LEDS);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK525/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK525/Board.h
new file mode 100644
index 000000000..bda925bb5
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK525/Board.h
@@ -0,0 +1,90 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Atmel STK525.
+ * \copydetails Group_BoardInfo_STK525
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_STK525 STK525
+ * \brief Board specific information header for the Atmel STK525.
+ *
+ * Board specific information header for the Atmel STK525.
+ *
+ * @{
+ */
+
+#ifndef __BOARD_STK525_H__
+#define __BOARD_STK525_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../Buttons.h"
+ #include "../../Dataflash.h"
+ #include "../../Joystick.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware Buttons mounted. */
+ #define BOARD_HAS_BUTTONS
+
+ /** Indicates the board has a hardware Dataflash mounted. */
+ #define BOARD_HAS_DATAFLASH
+
+ /** Indicates the board has a hardware Joystick mounted. */
+ #define BOARD_HAS_JOYSTICK
+
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK525/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK525/Buttons.h
new file mode 100644
index 000000000..532a46f1d
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK525/Buttons.h
@@ -0,0 +1,103 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Buttons driver header for the Atmel STK525.
+ * \copydetails Group_Buttons_STK525
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Buttons driver
+ * dispatch header located in LUFA/Drivers/Board/Buttons.h.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_STK525 STK525
+ * \brief Board specific Buttons driver header for the Atmel STK525.
+ *
+ * Board specific Buttons driver header for the Atmel STK525.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>BUTTONS_BUTTON1</td><td>HWB Button</td><td>Low</td><td>PORTE.2</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __BUTTONS_STK525_H__
+#define __BUTTONS_STK525_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Button mask for the first button on the board. */
+ #define BUTTONS_BUTTON1 (1 << 2)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+ DDRE &= ~BUTTONS_BUTTON1;
+ PORTE |= BUTTONS_BUTTON1;
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+ DDRE &= ~BUTTONS_BUTTON1;
+ PORTE &= ~BUTTONS_BUTTON1;
+ }
+
+ static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Buttons_GetStatus(void)
+ {
+ return ((PINE & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK525/Dataflash.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK525/Dataflash.h
new file mode 100644
index 000000000..825a7a524
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK525/Dataflash.h
@@ -0,0 +1,222 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Dataflash driver header for the Atmel STK525.
+ * \copydetails Group_Dataflash_STK525
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the dataflash driver
+ * dispatch header located in LUFA/Drivers/Board/Dataflash.h.
+ */
+
+/** \ingroup Group_Dataflash
+ * \defgroup Group_Dataflash_STK525 STK525
+ * \brief Board specific Dataflash driver header for the Atmel STK525.
+ *
+ * Board specific Dataflash driver header for the Atmel STK525.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Select Pin</th><th>SPI Port</th></tr>
+ * <tr><td>DATAFLASH_CHIP1</td><td>AT45DB321C (4MB)</td><td>PORTB.4</td><td>SPI0</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __DATAFLASH_STK525_H__
+#define __DATAFLASH_STK525_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../../Misc/AT45DB321C.h"
+ #include "../../../Peripheral/SPI.h"
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_DATAFLASH_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Dataflash.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define DATAFLASH_CHIPCS_MASK DATAFLASH_CHIP1
+ #define DATAFLASH_CHIPCS_DDR DDRB
+ #define DATAFLASH_CHIPCS_PORT PORTB
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Constant indicating the total number of dataflash ICs mounted on the selected board. */
+ #define DATAFLASH_TOTALCHIPS 1
+
+ /** Mask for no dataflash chip selected. */
+ #define DATAFLASH_NO_CHIP 0
+
+ /** Mask for the first dataflash chip selected. */
+ #define DATAFLASH_CHIP1 (1 << 4)
+
+ /** Internal main memory page size for the board's dataflash IC. */
+ #define DATAFLASH_PAGE_SIZE 512
+
+ /** Total number of pages inside the board's dataflash IC. */
+ #define DATAFLASH_PAGES 8192
+
+ /* Inline Functions: */
+ /** Initializes the dataflash driver so that commands and data may be sent to an attached dataflash IC.
+ * The appropriate SPI interface will be automatically configured.
+ */
+ static inline void Dataflash_Init(void)
+ {
+ DATAFLASH_CHIPCS_DDR |= DATAFLASH_CHIPCS_MASK;
+ DATAFLASH_CHIPCS_PORT |= DATAFLASH_CHIPCS_MASK;
+
+ SPI_Init(SPI_SPEED_FCPU_DIV_2 | SPI_ORDER_MSB_FIRST | SPI_SCK_LEAD_FALLING | SPI_SAMPLE_TRAILING | SPI_MODE_MASTER);
+ }
+
+ /** Sends a byte to the currently selected dataflash IC, and returns a byte from the dataflash.
+ *
+ * \param[in] Byte Byte of data to send to the dataflash
+ *
+ * \return Last response byte from the dataflash
+ */
+ static inline uint8_t Dataflash_TransferByte(const uint8_t Byte) ATTR_ALWAYS_INLINE;
+ static inline uint8_t Dataflash_TransferByte(const uint8_t Byte)
+ {
+ return SPI_TransferByte(Byte);
+ }
+
+ /** Sends a byte to the currently selected dataflash IC, and ignores the next byte from the dataflash.
+ *
+ * \param[in] Byte Byte of data to send to the dataflash
+ */
+ static inline void Dataflash_SendByte(const uint8_t Byte) ATTR_ALWAYS_INLINE;
+ static inline void Dataflash_SendByte(const uint8_t Byte)
+ {
+ SPI_SendByte(Byte);
+ }
+
+ /** Sends a dummy byte to the currently selected dataflash IC, and returns the next byte from the dataflash.
+ *
+ * \return Last response byte from the dataflash
+ */
+ static inline uint8_t Dataflash_ReceiveByte(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Dataflash_ReceiveByte(void)
+ {
+ return SPI_ReceiveByte();
+ }
+
+ /** Determines the currently selected dataflash chip.
+ *
+ * \return Mask of the currently selected Dataflash chip, either \ref DATAFLASH_NO_CHIP if no chip is selected
+ * or a DATAFLASH_CHIPn mask (where n is the chip number).
+ */
+ static inline uint8_t Dataflash_GetSelectedChip(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Dataflash_GetSelectedChip(void)
+ {
+ return (~DATAFLASH_CHIPCS_PORT & DATAFLASH_CHIPCS_MASK);
+ }
+
+ /** Selects the given dataflash chip.
+ *
+ * \param[in] ChipMask Mask of the Dataflash IC to select, in the form of a \c DATAFLASH_CHIPn mask (where n is
+ * the chip number).
+ */
+ static inline void Dataflash_SelectChip(const uint8_t ChipMask) ATTR_ALWAYS_INLINE;
+ static inline void Dataflash_SelectChip(const uint8_t ChipMask)
+ {
+ DATAFLASH_CHIPCS_PORT = ((DATAFLASH_CHIPCS_PORT | DATAFLASH_CHIPCS_MASK) & ~ChipMask);
+ }
+
+ /** Deselects the current dataflash chip, so that no dataflash is selected. */
+ static inline void Dataflash_DeselectChip(void) ATTR_ALWAYS_INLINE;
+ static inline void Dataflash_DeselectChip(void)
+ {
+ Dataflash_SelectChip(DATAFLASH_NO_CHIP);
+ }
+
+ /** Selects a dataflash IC from the given page number, which should range from 0 to
+ * ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1). For boards containing only one
+ * dataflash IC, this will select DATAFLASH_CHIP1. If the given page number is outside
+ * the total number of pages contained in the boards dataflash ICs, all dataflash ICs
+ * are deselected.
+ *
+ * \param[in] PageAddress Address of the page to manipulate, ranging from
+ * 0 to ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1).
+ */
+ static inline void Dataflash_SelectChipFromPage(const uint16_t PageAddress)
+ {
+ Dataflash_DeselectChip();
+
+ if (PageAddress >= DATAFLASH_PAGES)
+ return;
+
+ Dataflash_SelectChip(DATAFLASH_CHIP1);
+ }
+
+ /** Toggles the select line of the currently selected dataflash IC, so that it is ready to receive
+ * a new command.
+ */
+ static inline void Dataflash_ToggleSelectedChipCS(void)
+ {
+ uint8_t SelectedChipMask = Dataflash_GetSelectedChip();
+
+ Dataflash_DeselectChip();
+ Dataflash_SelectChip(SelectedChipMask);
+ }
+
+ /** Spin-loops while the currently selected dataflash is busy executing a command, such as a main
+ * memory page program or main memory to buffer transfer.
+ */
+ static inline void Dataflash_WaitWhileBusy(void)
+ {
+ Dataflash_ToggleSelectedChipCS();
+ Dataflash_SendByte(DF_CMD_GETSTATUS);
+ while (!(Dataflash_ReceiveByte() & DF_STATUS_READY));
+ Dataflash_ToggleSelectedChipCS();
+ }
+
+ /** Sends a set of page and buffer address bytes to the currently selected dataflash IC, for use with
+ * dataflash commands which require a complete 24-bit address.
+ *
+ * \param[in] PageAddress Page address within the selected dataflash IC
+ * \param[in] BufferByte Address within the dataflash's buffer
+ */
+ static inline void Dataflash_SendAddressBytes(uint16_t PageAddress,
+ const uint16_t BufferByte)
+ {
+ Dataflash_SendByte(PageAddress >> 6);
+ Dataflash_SendByte((PageAddress << 2) | (BufferByte >> 8));
+ Dataflash_SendByte(BufferByte);
+ }
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK525/Joystick.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK525/Joystick.h
new file mode 100644
index 000000000..6b9b4f42c
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK525/Joystick.h
@@ -0,0 +1,130 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific joystick driver header for the Atmel STK525.
+ * \copydetails Group_Joystick_STK525
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the joystick driver
+ * dispatch header located in LUFA/Drivers/Board/Joystick.h.
+ */
+
+/** \ingroup Group_Joystick
+ * \defgroup Group_Joystick_STK525 STK525
+ * \brief Board specific joystick driver header for the Atmel STK525.
+ *
+ * Board specific joystick driver header for the Atmel STK525.
+ *
+ * <table>
+ * <tr><th>Left Port Pin</th><th>Up Port Pin</th><th>Right Port Pin</th><th>Down Port Pin</th><th>Press Port Pin</th></tr>
+ * <tr><td>PORTB.6</td><td>PORTB.7</td><td>PORTE.4</td><td>PORTE.5</td><td>PORTB.5</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __JOYSTICK_STK525_H__
+#define __JOYSTICK_STK525_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_JOYSTICK_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Joystick.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define JOY_BMASK ((1 << 5) | (1 << 6) | (1 << 7))
+ #define JOY_EMASK ((1 << 4) | (1 << 5))
+
+ #define JOY_PORTE_MASK_SHIFT 1
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Mask for the joystick being pushed in the left direction. */
+ #define JOY_LEFT (1 << 6)
+
+ /** Mask for the joystick being pushed in the right direction. */
+ #define JOY_RIGHT ((1 << 4) >> JOY_PORTE_MASK_SHIFT)
+
+ /** Mask for the joystick being pushed in the upward direction. */
+ #define JOY_UP (1 << 7)
+
+ /** Mask for the joystick being pushed in the downward direction. */
+ #define JOY_DOWN ((1 << 5) >> JOY_PORTE_MASK_SHIFT)
+
+ /** Mask for the joystick being pushed inward. */
+ #define JOY_PRESS (1 << 5)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Joystick_Init(void)
+ {
+ DDRB &= ~JOY_BMASK;
+ DDRE &= ~JOY_EMASK;
+
+ PORTB |= JOY_BMASK;
+ PORTE |= JOY_EMASK;
+ }
+
+ static inline void Joystick_Disable(void)
+ {
+ DDRB &= ~JOY_BMASK;
+ DDRE &= ~JOY_EMASK;
+
+ PORTB &= ~JOY_BMASK;
+ PORTE &= ~JOY_EMASK;
+ }
+
+ static inline uint8_t Joystick_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Joystick_GetStatus(void)
+ {
+ return (((uint8_t)~PINB & JOY_BMASK) | (((uint8_t)~PINE & JOY_EMASK) >> JOY_PORTE_MASK_SHIFT));
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK525/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK525/LEDs.h
new file mode 100644
index 000000000..53948b461
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK525/LEDs.h
@@ -0,0 +1,147 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Atmel STK525.
+ * \copydetails Group_LEDs_STK525
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_STK525 STK525
+ * \brief Board specific LED driver header for the Atmel STK525.
+ *
+ * Board specific LED driver header for the Atmel STK525.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Green</td><td>General Indicator</td><td>High</td><td>PORTD.4</td></tr>
+ * <tr><td>LEDS_LED2</td><td>Green</td><td>General Indicator</td><td>High</td><td>PORTD.5</td></tr>
+ * <tr><td>LEDS_LED3</td><td>Green</td><td>General Indicator</td><td>High</td><td>PORTD.6</td></tr>
+ * <tr><td>LEDS_LED4</td><td>Green</td><td>General Indicator</td><td>High</td><td>PORTD.7</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_STK525_H__
+#define __LEDS_STK525_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 4)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1 << 5)
+
+ /** LED mask for the third LED on the board. */
+ #define LEDS_LED3 (1 << 7)
+
+ /** LED mask for the fourth LED on the board. */
+ #define LEDS_LED4 (1 << 6)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3 | LEDS_LED4)
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRD |= LEDS_ALL_LEDS;
+ PORTD &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRD &= ~LEDS_ALL_LEDS;
+ PORTD &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTD |= LEDMask;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTD &= ~LEDMask;
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTD = ((PORTD & ~LEDS_ALL_LEDS) | LEDMask);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTD = ((PORTD & ~LEDMask) | ActiveMask);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PIND = LEDMask;
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return (PORTD & LEDS_ALL_LEDS);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK526/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK526/Board.h
new file mode 100644
index 000000000..6be146fcd
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK526/Board.h
@@ -0,0 +1,90 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Atmel STK526.
+ * \copydetails Group_BoardInfo_STK526
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_STK526 STK526
+ * \brief Board specific information header for the Atmel STK526.
+ *
+ * Board specific information header for the Atmel STK526.
+ *
+ * @{
+ */
+
+#ifndef __BOARD_STK526_H__
+#define __BOARD_STK526_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../Buttons.h"
+ #include "../../Dataflash.h"
+ #include "../../Joystick.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware Buttons mounted. */
+ #define BOARD_HAS_BUTTONS
+
+ /** Indicates the board has a hardware Dataflash mounted. */
+ #define BOARD_HAS_DATAFLASH
+
+ /** Indicates the board has a hardware Joystick mounted. */
+ #define BOARD_HAS_JOYSTICK
+
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK526/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK526/Buttons.h
new file mode 100644
index 000000000..bc598d389
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK526/Buttons.h
@@ -0,0 +1,103 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Buttons driver header for the Atmel STK526.
+ * \copydetails Group_Buttons_STK526
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Buttons driver
+ * dispatch header located in LUFA/Drivers/Board/Buttons.h.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_STK526 STK526
+ * \brief Board specific Buttons driver header for the Atmel STK526.
+ *
+ * Board specific Buttons driver header for the Atmel STK526.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>BUTTONS_BUTTON1</td><td>HWB Button</td><td>Low</td><td>PORTD.7</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __BUTTONS_STK526_H__
+#define __BUTTONS_STK526_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Button mask for the first button on the board. */
+ #define BUTTONS_BUTTON1 (1 << 7)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+ DDRD &= ~BUTTONS_BUTTON1;
+ PORTD |= BUTTONS_BUTTON1;
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+ DDRD &= ~BUTTONS_BUTTON1;
+ PORTD &= ~BUTTONS_BUTTON1;
+ }
+
+ static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Buttons_GetStatus(void)
+ {
+ return ((PIND & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK526/Dataflash.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK526/Dataflash.h
new file mode 100644
index 000000000..d2a59b12e
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK526/Dataflash.h
@@ -0,0 +1,222 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Dataflash driver header for the Atmel STK525.
+ * \copydetails Group_Dataflash_STK526
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the dataflash driver
+ * dispatch header located in LUFA/Drivers/Board/Dataflash.h.
+ */
+
+/** \ingroup Group_Dataflash
+ * \defgroup Group_Dataflash_STK526 STK526
+ * \brief Board specific Dataflash driver header for the Atmel STK525.
+ *
+ * Board specific Dataflash driver header for the Atmel STK525.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Select Pin</th><th>SPI Port</th></tr>
+ * <tr><td>DATAFLASH_CHIP1</td><td>AT45DB642D (8MB)</td><td>PORTC.2</td><td>SPI0</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __DATAFLASH_STK526_H__
+#define __DATAFLASH_STK526_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../../Misc/AT45DB642D.h"
+ #include "../../../Peripheral/SPI.h"
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_DATAFLASH_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Dataflash.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define DATAFLASH_CHIPCS_MASK DATAFLASH_CHIP1
+ #define DATAFLASH_CHIPCS_DDR DDRC
+ #define DATAFLASH_CHIPCS_PORT PORTC
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Constant indicating the total number of dataflash ICs mounted on the selected board. */
+ #define DATAFLASH_TOTALCHIPS 1
+
+ /** Mask for no dataflash chip selected. */
+ #define DATAFLASH_NO_CHIP 0
+
+ /** Mask for the first dataflash chip selected. */
+ #define DATAFLASH_CHIP1 (1 << 2)
+
+ /** Internal main memory page size for the board's dataflash IC. */
+ #define DATAFLASH_PAGE_SIZE 1024
+
+ /** Total number of pages inside the board's dataflash IC. */
+ #define DATAFLASH_PAGES 8192
+
+ /* Inline Functions: */
+ /** Initializes the dataflash driver so that commands and data may be sent to an attached dataflash IC.
+ * The appropriate SPI interface will be automatically configured.
+ */
+ static inline void Dataflash_Init(void)
+ {
+ DATAFLASH_CHIPCS_DDR |= DATAFLASH_CHIPCS_MASK;
+ DATAFLASH_CHIPCS_PORT |= DATAFLASH_CHIPCS_MASK;
+
+ SPI_Init(SPI_SPEED_FCPU_DIV_2 | SPI_ORDER_MSB_FIRST | SPI_SCK_LEAD_FALLING | SPI_SAMPLE_TRAILING | SPI_MODE_MASTER);
+ }
+
+ /** Sends a byte to the currently selected dataflash IC, and returns a byte from the dataflash.
+ *
+ * \param[in] Byte Byte of data to send to the dataflash
+ *
+ * \return Last response byte from the dataflash
+ */
+ static inline uint8_t Dataflash_TransferByte(const uint8_t Byte) ATTR_ALWAYS_INLINE;
+ static inline uint8_t Dataflash_TransferByte(const uint8_t Byte)
+ {
+ return SPI_TransferByte(Byte);
+ }
+
+ /** Sends a byte to the currently selected dataflash IC, and ignores the next byte from the dataflash.
+ *
+ * \param[in] Byte Byte of data to send to the dataflash
+ */
+ static inline void Dataflash_SendByte(const uint8_t Byte) ATTR_ALWAYS_INLINE;
+ static inline void Dataflash_SendByte(const uint8_t Byte)
+ {
+ SPI_SendByte(Byte);
+ }
+
+ /** Sends a dummy byte to the currently selected dataflash IC, and returns the next byte from the dataflash.
+ *
+ * \return Last response byte from the dataflash
+ */
+ static inline uint8_t Dataflash_ReceiveByte(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Dataflash_ReceiveByte(void)
+ {
+ return SPI_ReceiveByte();
+ }
+
+ /** Determines the currently selected dataflash chip.
+ *
+ * \return Mask of the currently selected Dataflash chip, either \ref DATAFLASH_NO_CHIP if no chip is selected
+ * or a DATAFLASH_CHIPn mask (where n is the chip number).
+ */
+ static inline uint8_t Dataflash_GetSelectedChip(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Dataflash_GetSelectedChip(void)
+ {
+ return (~DATAFLASH_CHIPCS_PORT & DATAFLASH_CHIPCS_MASK);
+ }
+
+ /** Selects the given dataflash chip.
+ *
+ * \param[in] ChipMask Mask of the Dataflash IC to select, in the form of a \c DATAFLASH_CHIPn mask (where n is
+ * the chip number).
+ */
+ static inline void Dataflash_SelectChip(const uint8_t ChipMask) ATTR_ALWAYS_INLINE;
+ static inline void Dataflash_SelectChip(const uint8_t ChipMask)
+ {
+ DATAFLASH_CHIPCS_PORT = ((DATAFLASH_CHIPCS_PORT | DATAFLASH_CHIPCS_MASK) & ~ChipMask);
+ }
+
+ /** Deselects the current dataflash chip, so that no dataflash is selected. */
+ static inline void Dataflash_DeselectChip(void) ATTR_ALWAYS_INLINE;
+ static inline void Dataflash_DeselectChip(void)
+ {
+ Dataflash_SelectChip(DATAFLASH_NO_CHIP);
+ }
+
+ /** Selects a dataflash IC from the given page number, which should range from 0 to
+ * ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1). For boards containing only one
+ * dataflash IC, this will select DATAFLASH_CHIP1. If the given page number is outside
+ * the total number of pages contained in the boards dataflash ICs, all dataflash ICs
+ * are deselected.
+ *
+ * \param[in] PageAddress Address of the page to manipulate, ranging from
+ * 0 to ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1).
+ */
+ static inline void Dataflash_SelectChipFromPage(const uint16_t PageAddress)
+ {
+ Dataflash_DeselectChip();
+
+ if (PageAddress >= DATAFLASH_PAGES)
+ return;
+
+ Dataflash_SelectChip(DATAFLASH_CHIP1);
+ }
+
+ /** Toggles the select line of the currently selected dataflash IC, so that it is ready to receive
+ * a new command.
+ */
+ static inline void Dataflash_ToggleSelectedChipCS(void)
+ {
+ uint8_t SelectedChipMask = Dataflash_GetSelectedChip();
+
+ Dataflash_DeselectChip();
+ Dataflash_SelectChip(SelectedChipMask);
+ }
+
+ /** Spin-loops while the currently selected dataflash is busy executing a command, such as a main
+ * memory page program or main memory to buffer transfer.
+ */
+ static inline void Dataflash_WaitWhileBusy(void)
+ {
+ Dataflash_ToggleSelectedChipCS();
+ Dataflash_SendByte(DF_CMD_GETSTATUS);
+ while (!(Dataflash_ReceiveByte() & DF_STATUS_READY));
+ Dataflash_ToggleSelectedChipCS();
+ }
+
+ /** Sends a set of page and buffer address bytes to the currently selected dataflash IC, for use with
+ * dataflash commands which require a complete 24-bit address.
+ *
+ * \param[in] PageAddress Page address within the selected dataflash IC
+ * \param[in] BufferByte Address within the dataflash's buffer
+ */
+ static inline void Dataflash_SendAddressBytes(uint16_t PageAddress,
+ const uint16_t BufferByte)
+ {
+ Dataflash_SendByte(PageAddress >> 5);
+ Dataflash_SendByte((PageAddress << 3) | (BufferByte >> 8));
+ Dataflash_SendByte(BufferByte);
+ }
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK526/Joystick.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK526/Joystick.h
new file mode 100644
index 000000000..7decabc5d
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK526/Joystick.h
@@ -0,0 +1,123 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific joystick driver header for the Atmel STK526.
+ * \copydetails Group_Joystick_STK526
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the joystick driver
+ * dispatch header located in LUFA/Drivers/Board/Joystick.h.
+ */
+
+/** \ingroup Group_Joystick
+ * \defgroup Group_Joystick_STK526 STK526
+ * \brief Board specific joystick driver header for the Atmel STK526.
+ *
+ * Board specific joystick driver header for the Atmel STK526.
+ *
+ * <table>
+ * <tr><th>Left Port Pin</th><th>Up Port Pin</th><th>Right Port Pin</th><th>Down Port Pin</th><th>Press Port Pin</th></tr>
+ * <tr><td>PORTB.4</td><td>PORTB.5</td><td>PORTB.6</td><td>PORTB.7</td><td>PORTB.0</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __JOYSTICK_STK526_H__
+#define __JOYSTICK_STK526_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_JOYSTICK_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Joystick.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define JOY_BMASK ((1 << 0) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7))
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Mask for the joystick being pushed in the left direction. */
+ #define JOY_LEFT (1 << 4)
+
+ /** Mask for the joystick being pushed in the right direction. */
+ #define JOY_RIGHT (1 << 6)
+
+ /** Mask for the joystick being pushed in the upward direction. */
+ #define JOY_UP (1 << 5)
+
+ /** Mask for the joystick being pushed in the downward direction. */
+ #define JOY_DOWN (1 << 7)
+
+ /** Mask for the joystick being pushed inward. */
+ #define JOY_PRESS (1 << 0)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Joystick_Init(void)
+ {
+ DDRB &= ~JOY_BMASK;
+
+ PORTB |= JOY_BMASK;
+ }
+
+ static inline void Joystick_Disable(void)
+ {
+ DDRB &= ~JOY_BMASK;
+
+ PORTB &= ~JOY_BMASK;
+ }
+
+ static inline uint8_t Joystick_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Joystick_GetStatus(void)
+ {
+ return ((uint8_t)~PINB & JOY_BMASK);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK526/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK526/LEDs.h
new file mode 100644
index 000000000..71525e961
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/STK526/LEDs.h
@@ -0,0 +1,147 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Atmel STK526.
+ * \copydetails Group_LEDs_STK526
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_STK526 STK526
+ * \brief Board specific LED driver header for the Atmel STK526.
+ *
+ * Board specific LED driver header for the Atmel STK526.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Green</td><td>General Indicator</td><td>High</td><td>PORTD.1</td></tr>
+ * <tr><td>LEDS_LED2</td><td>Green</td><td>General Indicator</td><td>High</td><td>PORTD.0</td></tr>
+ * <tr><td>LEDS_LED3</td><td>Green</td><td>General Indicator</td><td>High</td><td>PORTD.5</td></tr>
+ * <tr><td>LEDS_LED4</td><td>Green</td><td>General Indicator</td><td>High</td><td>PORTD.4</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_STK526_H__
+#define __LEDS_STK526_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 1)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1 << 0)
+
+ /** LED mask for the third LED on the board. */
+ #define LEDS_LED3 (1 << 5)
+
+ /** LED mask for the fourth LED on the board. */
+ #define LEDS_LED4 (1 << 4)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3 | LEDS_LED4)
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRD |= LEDS_ALL_LEDS;
+ PORTD &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRD &= ~LEDS_ALL_LEDS;
+ PORTD &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTD |= LEDMask;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTD &= ~LEDMask;
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTD = ((PORTD & ~LEDS_ALL_LEDS) | LEDMask);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTD = ((PORTD & ~LEDMask) | ActiveMask);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PIND = LEDMask;
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return (PORTD & LEDS_ALL_LEDS);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/TEENSY/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/TEENSY/Board.h
new file mode 100644
index 000000000..52e4d6114
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/TEENSY/Board.h
@@ -0,0 +1,85 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the PJRC Teensy 1.x/2.x boards.
+ * \copydetails Group_BoardInfo_TEENSY
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_TEENSY2 TEENSY2
+ * \brief Board specific information header for the PJRC Teensy 2 boards.
+ *
+ * See \ref Group_BoardInfo_TEENSY for more details.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_TEENSY TEENSY
+ * \brief Board specific information header for the PJRC Teensy 1.x/2.x boards.
+ *
+ * Board specific information header for the PJRC Teensy boards (http://www.pjrc.com/teensy/index.html).
+ *
+ * @{
+ */
+
+#ifndef __BOARD_TEENSY_H__
+#define __BOARD_TEENSY_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/TEENSY/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/TEENSY/LEDs.h
new file mode 100644
index 000000000..9f872247e
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/TEENSY/LEDs.h
@@ -0,0 +1,176 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the PJRC Teensy 1.x/2.x boards.
+ * \copydetails Group_LEDs_TEENSY
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_TEENSY2 TEENSY2
+ * \brief Board specific LED driver header for the PJRC Teensy 2 boards.
+ *
+ * See \ref Group_LEDs_TEENSY for more details.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_TEENSY TEENSY
+ * \brief Board specific LED driver header for the PJRC Teensy 1.x/2.x boards.
+ *
+ * \note For version 2 Teensy boards, compile with <code>BOARD = TEENSY2</code>.
+ *
+ * Board specific LED driver header for the PJRC Teensy boards (http://www.pjrc.com/teensy/index.html).
+ *
+ * <b>TEENSY</b>:
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Green</td><td>General Indicator</td><td>High</td><td>PORTD.6</td></tr>
+ * </table>
+ *
+ * <b>TEENSY2</b>:
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Green</td><td>General Indicator</td><td>Low</td><td>PORTD.6</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_TEENSY_H__
+#define __LEDS_TEENSY_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 6)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS LEDS_LED1
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRD |= LEDS_ALL_LEDS;
+
+ #if (BOARD == BOARD_TEENSY2)
+ PORTD &= ~LEDS_ALL_LEDS;
+ #else
+ PORTD |= LEDS_ALL_LEDS;
+ #endif
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRD &= ~LEDS_ALL_LEDS;
+ PORTD &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ #if (BOARD == BOARD_TEENSY2)
+ PORTD |= LEDMask;
+ #else
+ PORTD &= ~LEDMask;
+ #endif
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ #if (BOARD == BOARD_TEENSY2)
+ PORTD &= ~LEDMask;
+ #else
+ PORTD |= LEDMask;
+ #endif
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ #if (BOARD == BOARD_TEENSY2)
+ PORTD = ((PORTD & ~LEDS_ALL_LEDS) | LEDMask);
+ #else
+ PORTD = ((PORTD | LEDS_ALL_LEDS) & ~LEDMask);
+ #endif
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ #if (BOARD == BOARD_TEENSY2)
+ PORTD = ((PORTD & ~LEDMask) | ActiveMask);
+ #else
+ PORTD = ((PORTD | LEDMask) & ~ActiveMask);
+ #endif
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PIND = LEDMask;
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ #if (BOARD == BOARD_TEENSY2)
+ return (PORTD & LEDS_ALL_LEDS);
+ #else
+ return (~PORTD & LEDS_ALL_LEDS);
+ #endif
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/TUL/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/TUL/Board.h
new file mode 100644
index 000000000..7759c37cb
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/TUL/Board.h
@@ -0,0 +1,82 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the TUL.
+ * \copydetails Group_BoardInfo_TUL
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_TUL TUL
+ * \brief Board specific information header for the TUL.
+ *
+ * Board specific information header for the Busware TUL (http://www.busware.de/tiki-index.php?page=TUL).
+ *
+ * @{
+ */
+
+#ifndef __BOARD_TUL_H__
+#define __BOARD_TUL_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../Buttons.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware Buttons mounted. */
+ #define BOARD_HAS_BUTTONS
+
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/TUL/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/TUL/Buttons.h
new file mode 100644
index 000000000..bbcca263d
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/TUL/Buttons.h
@@ -0,0 +1,103 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Buttons driver header for the TUL.
+ * \copydetails Group_Buttons_TUL
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Buttons driver
+ * dispatch header located in LUFA/Drivers/Board/Buttons.h.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_TUL TUL
+ * \brief Board specific Buttons driver header for the TUL.
+ *
+ * Board specific Buttons driver header for the Busware TUL (http://www.busware.de/tiki-index.php?page=TUL).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>BUTTONS_BUTTON1</td><td>HWB Button</td><td>Low</td><td>PORTE.2</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __BUTTONS_TUL_H__
+#define __BUTTONS_TUL_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Button mask for the first button on the board. */
+ #define BUTTONS_BUTTON1 (1 << 2)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+ DDRE &= ~BUTTONS_BUTTON1;
+ PORTE |= BUTTONS_BUTTON1;
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+ DDRE &= ~BUTTONS_BUTTON1;
+ PORTE &= ~BUTTONS_BUTTON1;
+ }
+
+ static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Buttons_GetStatus(void)
+ {
+ return ((PINE & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/TUL/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/TUL/LEDs.h
new file mode 100644
index 000000000..8a14b8a9a
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/TUL/LEDs.h
@@ -0,0 +1,135 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Busware TUL.
+ * \copydetails Group_LEDs_TUL
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_TUL TUL
+ * \brief Board specific LED driver header for the Busware TUL.
+ *
+ * Board specific LED driver header for the Busware TUL (http://www.busware.de/tiki-index.php?page=TUL).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Green</td><td>General Indicator</td><td>High</td><td>PORTF.0</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_TUL_H__
+#define __LEDS_TUL_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 0)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS LEDS_LED1
+
+ /** LED mask for the none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRF |= LEDS_ALL_LEDS;
+ PORTF &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRF &= ~LEDS_ALL_LEDS;
+ PORTF &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTF |= LEDMask;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTF &= ~LEDMask;
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTF = ((PORTF & ~LEDS_ALL_LEDS) | LEDMask);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTF = ((PORTF & ~LEDMask) | ActiveMask);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PINF = LEDMask;
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return (PORTF & LEDS_ALL_LEDS);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/U2S/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/U2S/Board.h
new file mode 100644
index 000000000..128580a95
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/U2S/Board.h
@@ -0,0 +1,82 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the U2S.
+ * \copydetails Group_BoardInfo_U2S
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_U2S U2S
+ * \brief Board specific information header for the U2S.
+ *
+ * Board specific information header for the U2S (http://sites.google.com/site/megau2s/).
+ *
+ * @{
+ */
+
+#ifndef __BOARD_U2S__
+#define __BOARD_U2S__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../Buttons.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has a hardware Buttons mounted. */
+ #define BOARD_HAS_BUTTONS
+
+ /** Indicates the board has a hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/U2S/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/U2S/Buttons.h
new file mode 100644
index 000000000..30f0a9f5b
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/U2S/Buttons.h
@@ -0,0 +1,103 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Buttons driver header for the U2S.
+ * \copydetails Group_Buttons_U2S
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Buttons driver
+ * dispatch header located in LUFA/Drivers/Board/Buttons.h.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_U2S U2S
+ * \brief Board specific Buttons driver header for the U2S.
+ *
+ * Board specific Buttons driver header for the U2S (http://sites.google.com/site/megau2s/).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>BUTTONS_BUTTON1</td><td>HWB Button</td><td>Low</td><td>PORTC.4</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __BUTTONS_U2S__
+#define __BUTTONS_U2S__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Button mask for the first button on the board. */
+ #define BUTTONS_BUTTON1 (1 << 4)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+ DDRC &= ~BUTTONS_BUTTON1;
+ PORTC |= BUTTONS_BUTTON1;
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+ DDRC &= ~BUTTONS_BUTTON1;
+ PORTC &= ~BUTTONS_BUTTON1;
+ }
+
+ static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Buttons_GetStatus(void)
+ {
+ return ((PINC & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/U2S/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/U2S/LEDs.h
new file mode 100644
index 000000000..d7cf7cfb1
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/U2S/LEDs.h
@@ -0,0 +1,135 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the U2S.
+ * \copydetails Group_LEDs_U2S
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_U2S U2S
+ * \brief Board specific LED driver header for the U2S.
+ *
+ * Board specific LED driver header for the U2S (http://sites.google.com/site/megau2s/).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Red</td><td>General Indicator</td><td>Low</td><td>PORTC.2</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_U2S__
+#define __LEDS_U2S__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 2)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS LEDS_LED1
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRC |= LEDS_ALL_LEDS;
+ PORTC |= LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRC &= ~LEDS_ALL_LEDS;
+ PORTC &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTC &= ~LEDMask;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTC |= LEDMask;
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTC = ((PORTC | LEDS_ALL_LEDS) & ~LEDMask);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTC = ((PORTC | LEDMask) & ~ActiveMask);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PINC = LEDMask;
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return (~PORTC & LEDS_ALL_LEDS);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/UDIP/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/UDIP/Board.h
new file mode 100644
index 000000000..3a400053c
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/UDIP/Board.h
@@ -0,0 +1,82 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the UDIP.
+ * \copydetails Group_BoardInfo_UDIP
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_UDIP UDIP
+ * \brief Board specific information header for the UDIP.
+ *
+ * Board specific information header for the Linnix UDIP (http://linnix.com/udip/).
+ *
+ * @{
+ */
+
+#ifndef __BOARD_UDIP_H__
+#define __BOARD_UDIP_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../Buttons.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware Buttons mounted. */
+ #define BOARD_HAS_BUTTONS
+
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/UDIP/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/UDIP/Buttons.h
new file mode 100644
index 000000000..dab29a60a
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/UDIP/Buttons.h
@@ -0,0 +1,103 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Buttons driver header for the UDIP.
+ * \copydetails Group_Buttons_UDIP
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Buttons driver
+ * dispatch header located in LUFA/Drivers/Board/Buttons.h.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_UDIP UDIP
+ * \brief Board specific Buttons driver header for the UDIP.
+ *
+ * Board specific Buttons driver header for the Linnix UDIP (http://linnix.com/udip/).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>BUTTONS_BUTTON1</td><td>HWB Button</td><td>Low</td><td>PORTD.7</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __BUTTONS_UDIP_H__
+#define __BUTTONS_UDIP_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Button mask for the first button on the board. */
+ #define BUTTONS_BUTTON1 (1 << 7)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+ DDRD &= ~BUTTONS_BUTTON1;
+ PORTD |= BUTTONS_BUTTON1;
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+ DDRD &= ~BUTTONS_BUTTON1;
+ PORTD &= ~BUTTONS_BUTTON1;
+ }
+
+ static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Buttons_GetStatus(void)
+ {
+ return ((PIND & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/UDIP/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/UDIP/LEDs.h
new file mode 100644
index 000000000..fbcc8ff66
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/UDIP/LEDs.h
@@ -0,0 +1,163 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Linnix UDIP.
+ * \copydetails Group_LEDs_UDIP
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_UDIP UDIP
+ * \brief Board specific LED driver header for the Linnix UDIP.
+ *
+ * Board specific LED driver header for the Linnix UDIP (http://linnix.com/udip/).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Green</td><td>Bicolor Indicator 1</td><td>High</td><td>PORTB.6</td></tr>
+ * <tr><td>LEDS_LED2</td><td>Red</td><td>Bicolor Indicator 1</td><td>High</td><td>PORTB.5</td></tr>
+ * <tr><td>LEDS_LED3</td><td>Green</td><td>Bicolor Indicator 2</td><td>High</td><td>PORTD.5</td></tr>
+ * <tr><td>LEDS_LED4</td><td>Red</td><td>Bicolor Indicator 2</td><td>High</td><td>PORTD.4</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_UDIP_H__
+#define __LEDS_UDIP_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define LEDS_PORTB_LEDS (LEDS_LED1 | LEDS_LED2)
+ #define LEDS_PORTD_LEDS (LEDS_LED3 | LEDS_LED4)
+
+ #define LEDS_PORTD_MASK_SHIFT 1
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 6)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1 << 5)
+
+ /** LED mask for the third LED on the board. */
+ #define LEDS_LED3 ((1 << 5) >> LEDS_PORTD_MASK_SHIFT)
+
+ /** LED mask for the fourth LED on the board. */
+ #define LEDS_LED4 ((1 << 4) >> LEDS_PORTD_MASK_SHIFT)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3 | LEDS_LED4)
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRB |= LEDS_PORTB_LEDS;
+ DDRD |= (LEDS_PORTD_LEDS << LEDS_PORTD_MASK_SHIFT);
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRB &= ~LEDS_PORTB_LEDS;
+ DDRD &= ~(LEDS_PORTD_LEDS << LEDS_PORTD_MASK_SHIFT);
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTB |= (LEDMask & LEDS_PORTB_LEDS);
+ PORTD |= ((LEDMask & LEDS_PORTD_LEDS) << LEDS_PORTD_MASK_SHIFT);
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTB &= ~(LEDMask & LEDS_PORTB_LEDS);
+ PORTD &= ~((LEDMask & LEDS_PORTD_LEDS) << LEDS_PORTD_MASK_SHIFT);
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTB = (PORTB & ~LEDS_PORTB_LEDS) | (LEDMask & LEDS_PORTB_LEDS);
+ PORTD = (PORTD & ~(LEDS_PORTD_LEDS << LEDS_PORTD_MASK_SHIFT)) |
+ ((LEDMask & LEDS_PORTD_LEDS) << LEDS_PORTD_MASK_SHIFT);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTB = (PORTB & ~(LEDMask & LEDS_PORTB_LEDS)) | (ActiveMask & LEDS_PORTB_LEDS);
+ PORTD = (PORTD & ~((LEDMask & LEDS_PORTD_LEDS) << LEDS_PORTD_MASK_SHIFT)) |
+ ((ActiveMask & LEDS_PORTD_LEDS) << LEDS_PORTD_MASK_SHIFT);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PINB = (LEDMask & LEDS_PORTB_LEDS);
+ PIND = ((LEDMask & LEDS_PORTD_LEDS) << LEDS_PORTD_MASK_SHIFT);
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return ((PORTB & LEDS_PORTB_LEDS) | ((PORTD & LEDS_PORTD_LEDS) >> LEDS_PORTD_MASK_SHIFT));
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/UNO/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/UNO/Board.h
new file mode 100644
index 000000000..b23f8d0fd
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/UNO/Board.h
@@ -0,0 +1,78 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Arduino Uno.
+ * \copydetails Group_BoardInfo_UNO
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_UNO UNO
+ * \brief Board specific information header for the Arduino Uno.
+ *
+ * Board specific information header for the Arduino Uno (http://arduino.cc/en/Main/ArduinoBoardUno).
+ *
+ * @{
+ */
+
+#ifndef __BOARD_UNO_H__
+#define __BOARD_UNO_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/UNO/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/UNO/LEDs.h
new file mode 100644
index 000000000..006c3a5dd
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/UNO/LEDs.h
@@ -0,0 +1,139 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Arduino Uno.
+ * \copydetails Group_LEDs_UNO
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_UNO UNO
+ * \brief Board specific LED driver header for the Arduino Uno.
+ *
+ * Board specific LED driver header for the Arduino Uno (http://arduino.cc/en/Main/ArduinoBoardUno).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Yellow</td><td>RX</td><td>Low</td><td>PORTD.4</td></tr>
+ * <tr><td>LEDS_LED2</td><td>Yellow</td><td>TX</td><td>Low</td><td>PORTD.5</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_UNO_H__
+#define __LEDS_UNO_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 4)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1 << 5)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2)
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRD |= LEDS_ALL_LEDS;
+ PORTD |= LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRD &= ~LEDS_ALL_LEDS;
+ PORTD &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTD &= ~LEDMask;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTD |= LEDMask;
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTD = ((PORTD | LEDS_ALL_LEDS) & ~LEDMask);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTD = ((PORTD | LEDMask) & ~ActiveMask);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PIND = LEDMask;
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return (~PORTD & LEDS_ALL_LEDS);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USB2AX/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USB2AX/Board.h
new file mode 100644
index 000000000..05a4dea5a
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USB2AX/Board.h
@@ -0,0 +1,105 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Xevelabs USB2AX.
+ * \copydetails Group_BoardInfo_USB2AX
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_USB2AX_V31 USB2AX_V31
+ * \brief Board specific information header for the Xevelabs USB2AX revision 3.1.
+ *
+ * See \ref Group_BoardInfo_USB2AX for more details.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_USB2AX_V3 USB2AX_V3
+ * \brief Board specific information header for the Xevelabs USB2AX revision 3.
+ *
+ * See \ref Group_BoardInfo_USB2AX for more details.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_USB2AX USB2AX
+ * \brief Board specific information header for the Xevelabs USB2AX.
+ *
+ * Board specific information header for the Xevelabs USB2AX (http://paranoidstudio.assembla.com/wiki/show/paranoidstudio/USB2AX).
+ *
+ * @{
+ */
+
+#ifndef __BOARD_USB2AX_H__
+#define __BOARD_USB2AX_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../Buttons.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ #if (BOARD == BOARD_USB2AX) || (BOARD == BOARD_USB2AX_V3) || \
+ defined(__DOXYGEN__)
+ #include "../../Buttons.h"
+
+ /** Indicates the board has hardware Buttons mounted. */
+ #define BOARD_HAS_BUTTONS
+ #endif
+
+ #if ((BOARD == BOARD_USB2AX) || (BOARD == BOARD_USB2AX_V3) || \
+ (BOARD == BOARD_USB2AX_V31) || defined(__DOXYGEN__))
+ #include "../../LEDs.h"
+
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USB2AX/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USB2AX/Buttons.h
new file mode 100644
index 000000000..170a9affb
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USB2AX/Buttons.h
@@ -0,0 +1,120 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Buttons driver header for the Xevelabs USB2AX.
+ * \copydetails Group_Buttons_USB2AX
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Buttons driver
+ * dispatch header located in LUFA/Drivers/Board/Buttons.h.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_USB2AX_V31 USB2AX_V31
+ * \brief Board specific Button driver header for the Xevelabs USB2AX revision 3.1.
+ *
+ * See \ref Group_Buttons_USB2AX for more details.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_USB2AX_V3 USB2AX_V3
+ * \brief Board specific Button driver header for the Xevelabs USB2AX revision 3.
+ *
+ * See \ref Group_Buttons_USB2AX for more details.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_USB2AX USB2AX
+ * \brief Board specific Buttons driver header for the Xevelabs USB2AX revisions 1 and 2.
+ *
+ * \note For version 3 USB2AX boards, compile with <code>BOARD = USB2AX_V3</code> and for version 3.1, with <code>BOARD = USB2AX_V31</code>.
+ *
+ * Board specific Buttons driver header for the Paranoid Studio USB2AX (http://paranoidstudio.assembla.com/wiki/show/paranoidstudio/USB2AX).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>BUTTONS_BUTTON1</td><td>HWB Button</td><td>Low</td><td>PORTD.7</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __BUTTONS_USB2AX_H__
+#define __BUTTONS_USB2AX_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Button mask for the first button on the board. */
+ #define BUTTONS_BUTTON1 (1 << 7)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+ DDRD &= ~BUTTONS_BUTTON1;
+ PORTD |= BUTTONS_BUTTON1;
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+ DDRD &= ~BUTTONS_BUTTON1;
+ PORTD &= ~BUTTONS_BUTTON1;
+ }
+
+ static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Buttons_GetStatus(void)
+ {
+ return ((PIND & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USB2AX/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USB2AX/LEDs.h
new file mode 100644
index 000000000..03550fc00
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USB2AX/LEDs.h
@@ -0,0 +1,218 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Xevelabs USB2AX.
+ * \copydetails Group_LEDs_USB2AX
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_USB2AX_V31 USB2AX_V31
+ * \brief Board specific LED driver header for the Xevelabs USB2AX revision 3.1.
+ *
+ * See \ref Group_LEDs_USB2AX for more details.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_USB2AX_V3 USB2AX_V3
+ * \brief Board specific LED driver header for the Xevelabs USB2AX revision 3.
+ *
+ * See \ref Group_LEDs_USB2AX for more details.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_USB2AX USB2AX
+ * \brief Board specific LED driver header for the Xevelabs USB2AX revisions 1 and 2.
+ *
+ * \note For version 3 USB2AX boards, compile with <code>BOARD = USB2AX_V3</code> and for version 3.1, with <code>BOARD = USB2AX_V31</code>.
+ *
+ * Board specific LED driver header for the Xevelabs USB2AX (http://paranoidstudio.assembla.com/wiki/show/paranoidstudio/USB2AX).
+ *
+ * <b>USB2AX</b>:
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Green</td><td>General Indicator</td><td>High</td><td>PORTC.6</td></tr>
+ * </table>
+ *
+ * <b>USB2AX_V3</b>:
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Green</td><td>General Indicator</td><td>High</td><td>PORTD.1</td></tr>
+ * </table>
+ *
+ * <b>USB2AX_V31</b>:
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Green</td><td>General Indicator</td><td>High</td><td>PORTD.5</td></tr>
+ * <tr><td>LEDS_LED2</td><td>Red</td><td>General Indicator</td><td>High</td><td>PORTD.6</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_USB2AX_H__
+#define __LEDS_USB2AX_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #if (BOARD == BOARD_USB2AX_V31)
+ #define USB2AX_LEDS_LED1 (1 << 5)
+ #define USB2AX_LEDS_LED2 (1 << 6)
+ #elif (BOARD == BOARD_USB2AX_V3)
+ #define USB2AX_LEDS_LED1 (1 << 1)
+ #define USB2AX_LEDS_LED2 0
+ #else
+ #define USB2AX_LEDS_LED1 (1 << 6)
+ #define USB2AX_LEDS_LED2 0
+ #endif
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 USB2AX_LEDS_LED1
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 USB2AX_LEDS_LED2
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2)
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ #if (BOARD == BOARD_USB2AX)
+ DDRC |= LEDS_ALL_LEDS;
+ PORTC &= ~LEDS_ALL_LEDS;
+ #else
+ DDRD |= LEDS_ALL_LEDS;
+ PORTD &= ~LEDS_ALL_LEDS;
+ #endif
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ #if (BOARD == BOARD_USB2AX)
+ DDRC &= ~LEDS_ALL_LEDS;
+ PORTC &= ~LEDS_ALL_LEDS;
+ #else
+ DDRD &= ~LEDS_ALL_LEDS;
+ PORTD &= ~LEDS_ALL_LEDS;
+ #endif
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ #if (BOARD == BOARD_USB2AX)
+ PORTC |= LEDMask;
+ #else
+ PORTD |= LEDMask;
+ #endif
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ #if (BOARD == BOARD_USB2AX)
+ PORTC &= ~LEDMask;
+ #else
+ PORTD &= ~LEDMask;
+ #endif
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ #if (BOARD == BOARD_USB2AX)
+ PORTC = ((PORTC & ~LEDS_ALL_LEDS) | LEDMask);
+ #else
+ PORTD = ((PORTD & ~LEDS_ALL_LEDS) | LEDMask);
+ #endif
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ #if (BOARD == BOARD_USB2AX)
+ PORTC = ((PORTC & ~LEDMask) | ActiveMask);
+ #else
+ PORTD = ((PORTD & ~LEDMask) | ActiveMask);
+ #endif
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ #if (BOARD == BOARD_USB2AX)
+ PINC = LEDMask;
+ #else
+ PIND = LEDMask;
+ #endif
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ #if (BOARD == BOARD_USB2AX)
+ return (PORTC & LEDS_ALL_LEDS);
+ #else
+ return (PORTD & LEDS_ALL_LEDS);
+ #endif
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBFOO/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBFOO/Board.h
new file mode 100644
index 000000000..15c41ab5e
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBFOO/Board.h
@@ -0,0 +1,82 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Kernel Concepts USBFOO.
+ * \copydetails Group_BoardInfo_USBFOO
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_USBFOO USBFOO
+ * \brief Board specific information header for the Kernel Concepts USBFOO.
+ *
+ * Board specific information header for the Kernel Concepts USBFOO (http://shop.kernelconcepts.de/product_info.php?products_id=102).
+ *
+ * @{
+ */
+
+#ifndef __BOARD_USBFOO_H__
+#define __BOARD_USBFOO_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../Buttons.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware Buttons mounted. */
+ #define BOARD_HAS_BUTTONS
+
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBFOO/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBFOO/Buttons.h
new file mode 100644
index 000000000..e901437d7
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBFOO/Buttons.h
@@ -0,0 +1,103 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Buttons driver header for the Kernel Concepts USBFOO.
+ * \copydetails Group_Buttons_USBFOO
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Buttons driver
+ * dispatch header located in LUFA/Drivers/Board/Buttons.h.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_USBFOO USBFOO
+ * \brief Board specific Buttons driver header for the Kernel Concepts USBFOO.
+ *
+ * Board specific Buttons driver header for the Kernel Concepts USBFOO (http://shop.kernelconcepts.de/product_info.php?products_id=102).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>BUTTONS_BUTTON1</td><td>HWB Button</td><td>Low</td><td>PORTD.7</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __BUTTONS_USBFOO_H__
+#define __BUTTONS_USBFOO_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Button mask for the first button on the board. */
+ #define BUTTONS_BUTTON1 (1 << 7)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+ DDRD &= ~BUTTONS_BUTTON1;
+ PORTD |= BUTTONS_BUTTON1;
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+ DDRD &= ~BUTTONS_BUTTON1;
+ PORTD &= ~BUTTONS_BUTTON1;
+ }
+
+ static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Buttons_GetStatus(void)
+ {
+ return ((PIND & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBFOO/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBFOO/LEDs.h
new file mode 100644
index 000000000..e396630df
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBFOO/LEDs.h
@@ -0,0 +1,135 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Kernel Concepts USBFOO.
+ * \copydetails Group_LEDs_USBFOO
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_USBFOO USBFOO
+ * \brief Board specific LED driver header for the Kernel Concepts USBFOO.
+ *
+ * Board specific LED driver header for the Kernel Concepts USBFOO (http://shop.kernelconcepts.de/product_info.php?products_id=102).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Green</td><td>General Indicator</td><td>Low</td><td>PORTD.4</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_USBFOO_H__
+#define __LEDS_USBFOO_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 4)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS LEDS_LED1
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRD |= LEDS_ALL_LEDS;
+ PORTD |= LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRD &= ~LEDS_ALL_LEDS;
+ PORTD &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTD &= ~LEDMask;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTD |= LEDMask;
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTD = ((PORTD | LEDS_ALL_LEDS) & ~LEDMask);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTD = ((PORTD | LEDMask) & ~ActiveMask);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PIND = LEDMask;
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return (~PORTD & LEDS_ALL_LEDS);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBKEY/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBKEY/Board.h
new file mode 100644
index 000000000..366305656
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBKEY/Board.h
@@ -0,0 +1,90 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Atmel USBKEY.
+ * \copydetails Group_BoardInfo_USBKEY
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_USBKEY USBKEY
+ * \brief Board specific information header for the Atmel USBKEY.
+ *
+ * Board specific information header for the Atmel USBKEY.
+ *
+ * @{
+ */
+
+#ifndef __BOARD_USBKEY_H__
+#define __BOARD_USBKEY_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../Buttons.h"
+ #include "../../Dataflash.h"
+ #include "../../Joystick.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware Buttons mounted. */
+ #define BOARD_HAS_BUTTONS
+
+ /** Indicates the board has a hardware Dataflash mounted. */
+ #define BOARD_HAS_DATAFLASH
+
+ /** Indicates the board has a hardware Joystick mounted. */
+ #define BOARD_HAS_JOYSTICK
+
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBKEY/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBKEY/Buttons.h
new file mode 100644
index 000000000..3ec7b3acd
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBKEY/Buttons.h
@@ -0,0 +1,103 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Buttons driver header for the Atmel USBKEY.
+ * \copydetails Group_Buttons_USBKEY
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Buttons driver
+ * dispatch header located in LUFA/Drivers/Board/Buttons.h.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_USBKEY USBKEY
+ * \brief Board specific Buttons driver header for the Atmel USBKEY.
+ *
+ * Board specific Buttons driver header for the Atmel USBKEY.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>BUTTONS_BUTTON1</td><td>HWB Button</td><td>Low</td><td>PORTE.2</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __BUTTONS_USBKEY_H__
+#define __BUTTONS_USBKEY_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Button mask for the first button on the board. */
+ #define BUTTONS_BUTTON1 (1 << 2)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+ DDRE &= ~BUTTONS_BUTTON1;
+ PORTE |= BUTTONS_BUTTON1;
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+ DDRE &= ~BUTTONS_BUTTON1;
+ PORTE &= ~BUTTONS_BUTTON1;
+ }
+
+ static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Buttons_GetStatus(void)
+ {
+ return ((PINE & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBKEY/Dataflash.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBKEY/Dataflash.h
new file mode 100644
index 000000000..85a8dda3d
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBKEY/Dataflash.h
@@ -0,0 +1,237 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Dataflash driver header for the Atmel USBKEY.
+ * \copydetails Group_Dataflash_USBKEY
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the dataflash driver
+ * dispatch header located in LUFA/Drivers/Board/Dataflash.h.
+ */
+
+/** \ingroup Group_Dataflash
+ * \defgroup Group_Dataflash_USBKEY USBKEY
+ * \brief Board specific Dataflash driver header for the Atmel USBKEY.
+ *
+ * Board specific Dataflash driver header for the Atmel USBKEY board.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Select Pin</th><th>SPI Port</th></tr>
+ * <tr><td>DATAFLASH_CHIP1</td><td>AT45DB642D (8MB)</td><td>PORTE.0</td><td>SPI0</td></tr>
+ * <tr><td>DATAFLASH_CHIP2</td><td>AT45DB642D (8MB)</td><td>PORTE.1</td><td>SPI0</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __DATAFLASH_USBKEY_H__
+#define __DATAFLASH_USBKEY_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../../Misc/AT45DB642D.h"
+ #include "../../../Peripheral/SPI.h"
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_DATAFLASH_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Dataflash.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define DATAFLASH_CHIPCS_MASK (DATAFLASH_CHIP1 | DATAFLASH_CHIP2)
+ #define DATAFLASH_CHIPCS_DDR DDRE
+ #define DATAFLASH_CHIPCS_PORT PORTE
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Constant indicating the total number of dataflash ICs mounted on the selected board. */
+ #define DATAFLASH_TOTALCHIPS 2
+
+ /** Mask for no dataflash chip selected. */
+ #define DATAFLASH_NO_CHIP 0
+
+ /** Mask for the first dataflash chip selected. */
+ #define DATAFLASH_CHIP1 (1 << 0)
+
+ /** Mask for the second dataflash chip selected. */
+ #define DATAFLASH_CHIP2 (1 << 1)
+
+ /** Internal main memory page size for the board's dataflash ICs. */
+ #define DATAFLASH_PAGE_SIZE 1024
+
+ /** Total number of pages inside each of the board's dataflash ICs. */
+ #define DATAFLASH_PAGES 8192
+
+ /* Inline Functions: */
+ /** Initializes the dataflash driver so that commands and data may be sent to an attached dataflash IC.
+ * The appropriate SPI interface will be automatically configured.
+ */
+ static inline void Dataflash_Init(void)
+ {
+ DATAFLASH_CHIPCS_DDR |= DATAFLASH_CHIPCS_MASK;
+ DATAFLASH_CHIPCS_PORT |= DATAFLASH_CHIPCS_MASK;
+
+ SPI_Init(SPI_SPEED_FCPU_DIV_2 | SPI_ORDER_MSB_FIRST | SPI_SCK_LEAD_FALLING | SPI_SAMPLE_TRAILING | SPI_MODE_MASTER);
+ }
+
+ /** Sends a byte to the currently selected dataflash IC, and returns a byte from the dataflash.
+ *
+ * \param[in] Byte Byte of data to send to the dataflash
+ *
+ * \return Last response byte from the dataflash
+ */
+ static inline uint8_t Dataflash_TransferByte(const uint8_t Byte) ATTR_ALWAYS_INLINE;
+ static inline uint8_t Dataflash_TransferByte(const uint8_t Byte)
+ {
+ return SPI_TransferByte(Byte);
+ }
+
+ /** Sends a byte to the currently selected dataflash IC, and ignores the next byte from the dataflash.
+ *
+ * \param[in] Byte Byte of data to send to the dataflash
+ */
+ static inline void Dataflash_SendByte(const uint8_t Byte) ATTR_ALWAYS_INLINE;
+ static inline void Dataflash_SendByte(const uint8_t Byte)
+ {
+ SPI_SendByte(Byte);
+ }
+
+ /** Sends a dummy byte to the currently selected dataflash IC, and returns the next byte from the dataflash.
+ *
+ * \return Last response byte from the dataflash
+ */
+ static inline uint8_t Dataflash_ReceiveByte(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Dataflash_ReceiveByte(void)
+ {
+ return SPI_ReceiveByte();
+ }
+
+ /** Determines the currently selected dataflash chip.
+ *
+ * \return Mask of the currently selected Dataflash chip, either \ref DATAFLASH_NO_CHIP if no chip is selected
+ * or a DATAFLASH_CHIPn mask (where n is the chip number).
+ */
+ static inline uint8_t Dataflash_GetSelectedChip(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Dataflash_GetSelectedChip(void)
+ {
+ return (~DATAFLASH_CHIPCS_PORT & DATAFLASH_CHIPCS_MASK);
+ }
+
+ /** Selects the given dataflash chip.
+ *
+ * \param[in] ChipMask Mask of the Dataflash IC to select, in the form of a \c DATAFLASH_CHIPn mask (where n is
+ * the chip number).
+ */
+ static inline void Dataflash_SelectChip(const uint8_t ChipMask) ATTR_ALWAYS_INLINE;
+ static inline void Dataflash_SelectChip(const uint8_t ChipMask)
+ {
+ DATAFLASH_CHIPCS_PORT = ((DATAFLASH_CHIPCS_PORT | DATAFLASH_CHIPCS_MASK) & ~ChipMask);
+ }
+
+ /** Deselects the current dataflash chip, so that no dataflash is selected. */
+ static inline void Dataflash_DeselectChip(void) ATTR_ALWAYS_INLINE;
+ static inline void Dataflash_DeselectChip(void)
+ {
+ Dataflash_SelectChip(DATAFLASH_NO_CHIP);
+ }
+
+ /** Selects a dataflash IC from the given page number, which should range from 0 to
+ * ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1). For boards containing only one
+ * dataflash IC, this will select DATAFLASH_CHIP1. If the given page number is outside
+ * the total number of pages contained in the boards dataflash ICs, all dataflash ICs
+ * are deselected.
+ *
+ * \param[in] PageAddress Address of the page to manipulate, ranging from
+ * 0 to ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1).
+ */
+ static inline void Dataflash_SelectChipFromPage(const uint16_t PageAddress)
+ {
+ Dataflash_DeselectChip();
+
+ if (PageAddress >= (DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS))
+ return;
+
+ #if (DATAFLASH_TOTALCHIPS == 2)
+ if (PageAddress & 0x01)
+ Dataflash_SelectChip(DATAFLASH_CHIP2);
+ else
+ Dataflash_SelectChip(DATAFLASH_CHIP1);
+ #else
+ Dataflash_SelectChip(DATAFLASH_CHIP1);
+ #endif
+ }
+
+ /** Toggles the select line of the currently selected dataflash IC, so that it is ready to receive
+ * a new command.
+ */
+ static inline void Dataflash_ToggleSelectedChipCS(void)
+ {
+ uint8_t SelectedChipMask = Dataflash_GetSelectedChip();
+
+ Dataflash_DeselectChip();
+ Dataflash_SelectChip(SelectedChipMask);
+ }
+
+ /** Spin-loops while the currently selected dataflash is busy executing a command, such as a main
+ * memory page program or main memory to buffer transfer.
+ */
+ static inline void Dataflash_WaitWhileBusy(void)
+ {
+ Dataflash_ToggleSelectedChipCS();
+ Dataflash_SendByte(DF_CMD_GETSTATUS);
+ while (!(Dataflash_ReceiveByte() & DF_STATUS_READY));
+ Dataflash_ToggleSelectedChipCS();
+ }
+
+ /** Sends a set of page and buffer address bytes to the currently selected dataflash IC, for use with
+ * dataflash commands which require a complete 24-bit address.
+ *
+ * \param[in] PageAddress Page address within the selected dataflash IC
+ * \param[in] BufferByte Address within the dataflash's buffer
+ */
+ static inline void Dataflash_SendAddressBytes(uint16_t PageAddress,
+ const uint16_t BufferByte)
+ {
+ #if (DATAFLASH_TOTALCHIPS == 2)
+ PageAddress >>= 1;
+ #endif
+
+ Dataflash_SendByte(PageAddress >> 5);
+ Dataflash_SendByte((PageAddress << 3) | (BufferByte >> 8));
+ Dataflash_SendByte(BufferByte);
+ }
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBKEY/Joystick.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBKEY/Joystick.h
new file mode 100644
index 000000000..45d5a66a8
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBKEY/Joystick.h
@@ -0,0 +1,130 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific joystick driver header for the Atmel USBKEY.
+ * \copydetails Group_Joystick_USBKEY
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the joystick driver
+ * dispatch header located in LUFA/Drivers/Board/Joystick.h.
+ */
+
+/** \ingroup Group_Joystick
+ * \defgroup Group_Joystick_USBKEY USBKEY
+ * \brief Board specific joystick driver header for the Atmel USBKEY.
+ *
+ * Board specific joystick driver header for the Atmel USBKEY.
+ *
+ * <table>
+ * <tr><th>Left Port Pin</th><th>Up Port Pin</th><th>Right Port Pin</th><th>Down Port Pin</th><th>Press Port Pin</th></tr>
+ * <tr><td>PORTB.6</td><td>PORTB.7</td><td>PORTE.4</td><td>PORTE.5</td><td>PORTB.5</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __JOYSTICK_USBKEY_H__
+#define __JOYSTICK_USBKEY_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_JOYSTICK_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Joystick.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define JOY_BMASK ((1 << 5) | (1 << 6) | (1 << 7))
+ #define JOY_EMASK ((1 << 4) | (1 << 5))
+
+ #define JOY_PORTE_MASK_SHIFT 1
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Mask for the joystick being pushed in the left direction. */
+ #define JOY_LEFT (1 << 6)
+
+ /** Mask for the joystick being pushed in the right direction. */
+ #define JOY_RIGHT ((1 << 4) >> JOY_PORTE_MASK_SHIFT)
+
+ /** Mask for the joystick being pushed in the upward direction. */
+ #define JOY_UP (1 << 7)
+
+ /** Mask for the joystick being pushed in the downward direction. */
+ #define JOY_DOWN ((1 << 5) >> JOY_PORTE_MASK_SHIFT)
+
+ /** Mask for the joystick being pushed inward. */
+ #define JOY_PRESS (1 << 5)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Joystick_Init(void)
+ {
+ DDRB &= ~JOY_BMASK;
+ DDRE &= ~JOY_EMASK;
+
+ PORTB |= JOY_BMASK;
+ PORTE |= JOY_EMASK;
+ }
+
+ static inline void Joystick_Disable(void)
+ {
+ DDRB &= ~JOY_BMASK;
+ DDRE &= ~JOY_EMASK;
+
+ PORTB &= ~JOY_BMASK;
+ PORTE &= ~JOY_EMASK;
+ }
+
+ static inline uint8_t Joystick_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Joystick_GetStatus(void)
+ {
+ return (((uint8_t)~PINB & JOY_BMASK) | (((uint8_t)~PINE & JOY_EMASK) >> JOY_PORTE_MASK_SHIFT));
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBKEY/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBKEY/LEDs.h
new file mode 100644
index 000000000..dc02da52e
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBKEY/LEDs.h
@@ -0,0 +1,147 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Atmel USBKEY.
+ * \copydetails Group_LEDs_USBKEY
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_USBKEY USBKEY
+ * \brief Board specific LED driver header for the Atmel USBKEY.
+ *
+ * Board specific LED driver header for the Atmel USBKEY.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Red</td><td>Bicolor Indicator 1</td><td>High</td><td>PORTD.4</td></tr>
+ * <tr><td>LEDS_LED2</td><td>Green</td><td>Bicolor Indicator 1</td><td>High</td><td>PORTD.5</td></tr>
+ * <tr><td>LEDS_LED3</td><td>Red</td><td>Bicolor Indicator 2</td><td>High</td><td>PORTD.6</td></tr>
+ * <tr><td>LEDS_LED4</td><td>Green</td><td>Bicolor Indicator 2</td><td>High</td><td>PORTD.7</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_USBKEY_H__
+#define __LEDS_USBKEY_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 4)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1 << 5)
+
+ /** LED mask for the third LED on the board. */
+ #define LEDS_LED3 (1 << 7)
+
+ /** LED mask for the fourth LED on the board. */
+ #define LEDS_LED4 (1 << 6)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3 | LEDS_LED4)
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRD |= LEDS_ALL_LEDS;
+ PORTD &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRD &= ~LEDS_ALL_LEDS;
+ PORTD &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTD |= LEDMask;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTD &= ~LEDMask;
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTD = ((PORTD & ~LEDS_ALL_LEDS) | LEDMask);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTD = ((PORTD & ~LEDMask) | ActiveMask);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PIND = LEDMask;
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return (PORTD & LEDS_ALL_LEDS);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBTINYMKII/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBTINYMKII/Board.h
new file mode 100644
index 000000000..492aced78
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBTINYMKII/Board.h
@@ -0,0 +1,82 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for Tom's USBTINY MKII.
+ * \copydetails Group_BoardInfo_USBTINYMKII
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_USBTINYMKII USBTINYMKII
+ * \brief Board specific information header for Tom's USBTINY MKII.
+ *
+ * Board specific information header for Tom's USBTINY MKII (http://tom-itx.dyndns.org:81/~webpage/).
+ *
+ * @{
+ */
+
+#ifndef __BOARD_USBTINYMKII_H__
+#define __BOARD_USBTINYMKII_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../Buttons.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware Buttons mounted. */
+ #define BOARD_HAS_BUTTONS
+
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBTINYMKII/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBTINYMKII/Buttons.h
new file mode 100644
index 000000000..682239cd7
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBTINYMKII/Buttons.h
@@ -0,0 +1,103 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Buttons driver header for Tom's USBTINY MKII.
+ * \copydetails Group_Buttons_USBTINYMKII
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Buttons driver
+ * dispatch header located in LUFA/Drivers/Board/Buttons.h.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_USBTINYMKII USBTINYMKII
+ * \brief Board specific Buttons driver header for Tom's USBTINY MKII.
+ *
+ * Board specific Buttons driver header for Tom's USBTINY MKII (http://tom-itx.dyndns.org:81/~webpage/).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>BUTTONS_BUTTON1</td><td>HWB Button</td><td>Low</td><td>PORTD.7</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __BUTTONS_USBTINYMKII_H__
+#define __BUTTONS_USBTINYMKII_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Button mask for the first button on the board. */
+ #define BUTTONS_BUTTON1 (1 << 7)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+ DDRD &= ~BUTTONS_BUTTON1;
+ PORTD |= BUTTONS_BUTTON1;
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+ DDRD &= ~BUTTONS_BUTTON1;
+ PORTD &= ~BUTTONS_BUTTON1;
+ }
+
+ static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Buttons_GetStatus(void)
+ {
+ return ((PIND & BUTTONS_BUTTON1) ^ BUTTONS_BUTTON1);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBTINYMKII/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBTINYMKII/LEDs.h
new file mode 100644
index 000000000..a2decbc49
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/USBTINYMKII/LEDs.h
@@ -0,0 +1,143 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for Tom's USBTINY MKII.
+ * \copydetails Group_LEDs_USBTINYMKII
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_USBTINYMKII USBTINYMKII
+ * \brief Board specific LED driver header for Tom's USBTINY MKII.
+ *
+ * Board specific LED driver header for Tom's USBTINY MKII (http://tom-itx.dyndns.org:81/~webpage/).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Red</td><td>Bicolor Indicator 1</td><td>High</td><td>PORTB.6</td></tr>
+ * <tr><td>LEDS_LED2</td><td>Green</td><td>Bicolor Indicator 1</td><td>High</td><td>PORTB.7</td></tr>
+ * <tr><td>LEDS_LED3</td><td>Red</td><td>Target Power</td><td>High</td><td>PORTB.5</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_USBTINYMKII_H__
+#define __LEDS_USBTINYMKII_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 6)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1 << 7)
+
+ /** LED mask for the third LED on the board. */
+ #define LEDS_LED3 (1 << 5)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3)
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRB |= LEDS_ALL_LEDS;
+ PORTB &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRB &= ~LEDS_ALL_LEDS;
+ PORTB &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LedMask)
+ {
+ PORTB |= LedMask;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LedMask)
+ {
+ PORTB &= ~LedMask;
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LedMask)
+ {
+ PORTB = ((PORTB & ~LEDS_ALL_LEDS) | LedMask);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LedMask,
+ const uint8_t ActiveMask)
+ {
+ PORTB = ((PORTB & ~LedMask) | ActiveMask);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PINB = LEDMask;
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return (PORTB & LEDS_ALL_LEDS);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/XPLAIN/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/XPLAIN/Board.h
new file mode 100644
index 000000000..57ad4c98b
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/XPLAIN/Board.h
@@ -0,0 +1,89 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the original Atmel XPLAIN.
+ * \copydetails Group_BoardInfo_XPLAIN
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_XPLAIN_REV1 XPLAIN_REV1
+ * \brief Board specific information header for the original Atmel XPLAIN, revision 1.
+ *
+ * See \ref Group_BoardInfo_XPLAIN for more details.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_XPLAIN XPLAIN
+ * \brief Board specific information header for the original Atmel XPLAIN.
+ *
+ * Board specific information header for the original Atmel XPLAIN.
+ *
+ * @{
+ */
+
+#ifndef __BOARD_XPLAIN_H__
+#define __BOARD_XPLAIN_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../Dataflash.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has a hardware Dataflash mounted. */
+ #define BOARD_HAS_DATAFLASH
+
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/XPLAIN/Dataflash.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/XPLAIN/Dataflash.h
new file mode 100644
index 000000000..a8078f61f
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/XPLAIN/Dataflash.h
@@ -0,0 +1,245 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Dataflash driver header for the original Atmel XPLAIN.
+ * \copydetails Group_Dataflash_XPLAIN
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the dataflash driver
+ * dispatch header located in LUFA/Drivers/Board/Dataflash.h.
+ */
+
+/** \ingroup Group_Dataflash
+ * \defgroup Group_Dataflash_XPLAIN_REV1 XPLAIN_REV1
+ * \brief Board specific Dataflash driver header for the original Atmel XPLAIN, revision 1.
+ *
+ * See \ref Group_Dataflash_XPLAIN for more details.
+ */
+
+/** \ingroup Group_Dataflash
+ * \defgroup Group_Dataflash_XPLAIN XPLAIN
+ * \brief Board specific Dataflash driver header for the original Atmel XPLAIN.
+ *
+ * \note For the first revision XPLAIN board, compile with <code>BOARD = BOARD_XPLAIN_REV1</code>.
+ *
+ * Board specific Dataflash driver header for the Atmel XPLAIN.
+ *
+ * <b>Revision 1 Boards</b>:
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Select Pin</th><th>SPI Port</th></tr>
+ * <tr><td>DATAFLASH_CHIP1</td><td>AT45DB041D (512KB)</td><td>PORTB.5</td><td>SPI0</td></tr>
+ * </table>
+ *
+ * <b>Other Board Revisions</b>:
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Select Pin</th><th>SPI Port</th></tr>
+ * <tr><td>DATAFLASH_CHIP1</td><td>AT45DB642D (8MB)</td><td>PORTB.5</td><td>SPI0</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __DATAFLASH_XPLAIN_H__
+#define __DATAFLASH_XPLAIN_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ #include "../../../Misc/AT45DB642D.h"
+ #include "../../../Peripheral/SPI.h"
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_DATAFLASH_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Dataflash.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define DATAFLASH_CHIPCS_MASK DATAFLASH_CHIP1
+ #define DATAFLASH_CHIPCS_DDR DDRB
+ #define DATAFLASH_CHIPCS_PORT PORTB
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Constant indicating the total number of dataflash ICs mounted on the selected board. */
+ #define DATAFLASH_TOTALCHIPS 1
+
+ /** Mask for no dataflash chip selected. */
+ #define DATAFLASH_NO_CHIP 0
+
+ /** Mask for the first dataflash chip selected. */
+ #define DATAFLASH_CHIP1 (1 << 5)
+
+ #if ((BOARD != BOARD_XPLAIN_REV1) || defined(__DOXYGEN__))
+ /** Internal main memory page size for the board's dataflash ICs. */
+ #define DATAFLASH_PAGE_SIZE 1024
+
+ /** Total number of pages inside each of the board's dataflash ICs. */
+ #define DATAFLASH_PAGES 8192
+ #else
+ #define DATAFLASH_PAGE_SIZE 256
+
+ #define DATAFLASH_PAGES 2048
+ #endif
+
+ /* Inline Functions: */
+ /** Initializes the dataflash driver so that commands and data may be sent to an attached dataflash IC.
+ * The appropriate SPI interface will be automatically configured.
+ */
+ static inline void Dataflash_Init(void)
+ {
+ DATAFLASH_CHIPCS_DDR |= DATAFLASH_CHIPCS_MASK;
+ DATAFLASH_CHIPCS_PORT |= DATAFLASH_CHIPCS_MASK;
+
+ SPI_Init(SPI_SPEED_FCPU_DIV_2 | SPI_ORDER_MSB_FIRST | SPI_SCK_LEAD_FALLING | SPI_SAMPLE_TRAILING | SPI_MODE_MASTER);
+ }
+
+ /** Sends a byte to the currently selected dataflash IC, and returns a byte from the dataflash.
+ *
+ * \param[in] Byte Byte of data to send to the dataflash
+ *
+ * \return Last response byte from the dataflash
+ */
+ static inline uint8_t Dataflash_TransferByte(const uint8_t Byte) ATTR_ALWAYS_INLINE;
+ static inline uint8_t Dataflash_TransferByte(const uint8_t Byte)
+ {
+ return SPI_TransferByte(Byte);
+ }
+
+ /** Sends a byte to the currently selected dataflash IC, and ignores the next byte from the dataflash.
+ *
+ * \param[in] Byte Byte of data to send to the dataflash
+ */
+ static inline void Dataflash_SendByte(const uint8_t Byte) ATTR_ALWAYS_INLINE;
+ static inline void Dataflash_SendByte(const uint8_t Byte)
+ {
+ SPI_SendByte(Byte);
+ }
+
+ /** Sends a dummy byte to the currently selected dataflash IC, and returns the next byte from the dataflash.
+ *
+ * \return Last response byte from the dataflash
+ */
+ static inline uint8_t Dataflash_ReceiveByte(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Dataflash_ReceiveByte(void)
+ {
+ return SPI_ReceiveByte();
+ }
+
+ /** Determines the currently selected dataflash chip.
+ *
+ * \return Mask of the currently selected Dataflash chip, either \ref DATAFLASH_NO_CHIP if no chip is selected
+ * or a DATAFLASH_CHIPn mask (where n is the chip number).
+ */
+ static inline uint8_t Dataflash_GetSelectedChip(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Dataflash_GetSelectedChip(void)
+ {
+ return (~DATAFLASH_CHIPCS_PORT & DATAFLASH_CHIPCS_MASK);
+ }
+
+ /** Selects the given dataflash chip.
+ *
+ * \param[in] ChipMask Mask of the Dataflash IC to select, in the form of a \c DATAFLASH_CHIPn mask (where n is
+ * the chip number).
+ */
+ static inline void Dataflash_SelectChip(const uint8_t ChipMask) ATTR_ALWAYS_INLINE;
+ static inline void Dataflash_SelectChip(const uint8_t ChipMask)
+ {
+ DATAFLASH_CHIPCS_PORT = ((DATAFLASH_CHIPCS_PORT | DATAFLASH_CHIPCS_MASK) & ~ChipMask);
+ }
+
+ /** Deselects the current dataflash chip, so that no dataflash is selected. */
+ static inline void Dataflash_DeselectChip(void) ATTR_ALWAYS_INLINE;
+ static inline void Dataflash_DeselectChip(void)
+ {
+ Dataflash_SelectChip(DATAFLASH_NO_CHIP);
+ }
+
+ /** Selects a dataflash IC from the given page number, which should range from 0 to
+ * ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1). For boards containing only one
+ * dataflash IC, this will select DATAFLASH_CHIP1. If the given page number is outside
+ * the total number of pages contained in the boards dataflash ICs, all dataflash ICs
+ * are deselected.
+ *
+ * \param[in] PageAddress Address of the page to manipulate, ranging from
+ * 0 to ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1).
+ */
+ static inline void Dataflash_SelectChipFromPage(const uint16_t PageAddress)
+ {
+ Dataflash_DeselectChip();
+
+ if (PageAddress >= DATAFLASH_PAGES)
+ return;
+
+ Dataflash_SelectChip(DATAFLASH_CHIP1);
+ }
+
+ /** Toggles the select line of the currently selected dataflash IC, so that it is ready to receive
+ * a new command.
+ */
+ static inline void Dataflash_ToggleSelectedChipCS(void)
+ {
+ uint8_t SelectedChipMask = Dataflash_GetSelectedChip();
+
+ Dataflash_DeselectChip();
+ Dataflash_SelectChip(SelectedChipMask);
+ }
+
+ /** Spin-loops while the currently selected dataflash is busy executing a command, such as a main
+ * memory page program or main memory to buffer transfer.
+ */
+ static inline void Dataflash_WaitWhileBusy(void)
+ {
+ Dataflash_ToggleSelectedChipCS();
+ Dataflash_SendByte(DF_CMD_GETSTATUS);
+ while (!(Dataflash_ReceiveByte() & DF_STATUS_READY));
+ Dataflash_ToggleSelectedChipCS();
+ }
+
+ /** Sends a set of page and buffer address bytes to the currently selected dataflash IC, for use with
+ * dataflash commands which require a complete 24-bit address.
+ *
+ * \param[in] PageAddress Page address within the selected dataflash IC
+ * \param[in] BufferByte Address within the dataflash's buffer
+ */
+ static inline void Dataflash_SendAddressBytes(uint16_t PageAddress,
+ const uint16_t BufferByte)
+ {
+ Dataflash_SendByte(PageAddress >> 5);
+ Dataflash_SendByte((PageAddress << 3) | (BufferByte >> 8));
+ Dataflash_SendByte(BufferByte);
+ }
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/XPLAIN/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/XPLAIN/LEDs.h
new file mode 100644
index 000000000..338b1b419
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/XPLAIN/LEDs.h
@@ -0,0 +1,142 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the original Atmel XPLAIN.
+ * \copydetails Group_LEDs_XPLAIN
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_XPLAIN_REV1 XPLAIN_REV1
+ * \brief Board specific LED driver header for the original Atmel XPLAIN, revision 1.
+ *
+ * See \ref Group_LEDs_XPLAIN for more details.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_XPLAIN XPLAIN
+ * \brief Board specific LED driver header for the original Atmel XPLAIN.
+ *
+ * Board specific LED driver header for the Atmel XPLAIN.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Green</td><td>General Indicator</td><td>Low</td><td>PORTB.6</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_XPLAIN_H__
+#define __LEDS_XPLAIN_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 6)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS LEDS_LED1
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRB |= LEDS_ALL_LEDS;
+ PORTB |= LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRB &= ~LEDS_ALL_LEDS;
+ PORTB &= ~LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTB &= ~LEDMask;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTB |= LEDMask;
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTB = ((PORTB | LEDS_ALL_LEDS) & ~LEDMask);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTB = ((PORTB | LEDMask) & ~ActiveMask);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PINB = LEDMask;
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return (~PORTB & LEDS_ALL_LEDS);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/YUN/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/YUN/Board.h
new file mode 100644
index 000000000..1d99302f6
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/YUN/Board.h
@@ -0,0 +1,78 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Arduino Yun board.
+ * \copydetails Group_BoardInfo_YUN
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_YUN YUN
+ * \brief Board specific information header for the Arduino Yun board.
+ *
+ * Board specific information header for the Arduino Yun board (http://arduino.cc/en/Main/arduinoBoardYun).
+ *
+ * @{
+ */
+
+#ifndef __BOARD_YUN_H__
+#define __BOARD_YUN_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/YUN/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/YUN/LEDs.h
new file mode 100644
index 000000000..bcdd47f9b
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/AVR8/YUN/LEDs.h
@@ -0,0 +1,169 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Arduino Yun board.
+ * \copydetails Group_LEDs_YUN
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_YUN YUN
+ * \brief Board specific LED driver header for the Arduino Yun board.
+ *
+ * Board specific LED driver header for the Arduino Yun board (http://arduino.cc/en/Main/arduinoBoardYun).
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Yellow</td><td>RX</td><td>Low</td><td>PORTB.0</td></tr>
+ * <tr><td>LEDS_LED2</td><td>Yellow</td><td>TX</td><td>Low</td><td>PORTD.5</td></tr>
+ * <tr><td>LEDS_LED3</td><td>Red</td><td>General Indicator</td><td>High</td><td>PORTC.7</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_YUN_H__
+#define __LEDS_YUN_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define LEDS_PORTB_LEDS (LEDS_LED1)
+ #define LEDS_PORTD_LEDS (LEDS_LED2)
+ #define LEDS_PORTC_LEDS (LEDS_LED3)
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 0)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1 << 5)
+
+ /** LED mask for the third LED on the board. */
+ #define LEDS_LED3 (1 << 7)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3)
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ DDRB |= LEDS_PORTB_LEDS;
+ PORTB |= LEDS_PORTB_LEDS;
+ DDRD |= LEDS_PORTD_LEDS;
+ PORTD |= LEDS_PORTD_LEDS;
+ DDRC |= LEDS_PORTC_LEDS;
+ PORTC &= ~LEDS_PORTC_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ DDRB &= ~LEDS_PORTB_LEDS;
+ PORTB &= ~LEDS_PORTB_LEDS;
+ DDRD &= ~LEDS_PORTD_LEDS;
+ PORTD &= ~LEDS_PORTD_LEDS;
+ DDRC &= ~LEDS_PORTC_LEDS;
+ PORTC &= ~LEDS_PORTC_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTB &= ~(LEDMask & LEDS_PORTB_LEDS);
+ PORTD &= ~(LEDMask & LEDS_PORTD_LEDS);
+ PORTC |= (LEDMask & LEDS_PORTC_LEDS);
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTB |= (LEDMask & LEDS_PORTB_LEDS);
+ PORTD |= (LEDMask & LEDS_PORTD_LEDS);
+ PORTC &= ~(LEDMask & LEDS_PORTC_LEDS);
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTB = ((PORTB | LEDS_PORTB_LEDS) & ~(LEDMask & LEDS_PORTB_LEDS));
+ PORTD = ((PORTD | LEDS_PORTD_LEDS) & ~(LEDMask & LEDS_PORTD_LEDS));
+ PORTC = ((PORTC & ~LEDS_PORTC_LEDS) | (LEDMask & LEDS_PORTC_LEDS));
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTB = ((PORTB | (LEDMask & LEDS_PORTB_LEDS)) & ~(ActiveMask & LEDS_PORTB_LEDS));
+ PORTD = ((PORTD | (LEDMask & LEDS_PORTD_LEDS)) & ~(ActiveMask & LEDS_PORTD_LEDS));
+ PORTC = ((PORTC & ~(LEDMask & LEDS_PORTC_LEDS)) | (ActiveMask & LEDS_PORTC_LEDS));
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PINB = (LEDMask & LEDS_PORTB_LEDS);
+ PIND = (LEDMask & LEDS_PORTD_LEDS);
+ PINC = (LEDMask & LEDS_PORTC_LEDS);
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return ((~PORTB & LEDS_PORTB_LEDS) | (~PORTD & LEDS_PORTD_LEDS) | (PORTC & LEDS_PORTC_LEDS));
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/Board.h
new file mode 100644
index 000000000..27f495361
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/Board.h
@@ -0,0 +1,167 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board hardware information driver.
+ *
+ * This file is the master dispatch header file for the board-specific information driver, to give information
+ * on the hardware contained on a specific board.
+ *
+ * User code should include this file, which will in turn include the correct board driver header file for the
+ * currently selected board.
+ *
+ * If the \c BOARD value is set to \c BOARD_USER, this will include the \c /Board/Board.h file in the user project
+ * directory.
+ *
+ * For possible \c BOARD makefile values, see \ref Group_BoardTypes.
+ */
+
+/** \ingroup Group_BoardDrivers
+ * \defgroup Group_BoardInfo Board Information Driver - LUFA/Drivers/Board/Board.h
+ * \brief Board hardware information driver.
+ *
+ * \section Sec_BoardInfo_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - None
+ *
+ * @{
+ */
+
+#ifndef __BOARD_H__
+#define __BOARD_H__
+
+ /* Macros: */
+ #define __INCLUDE_FROM_BOARD_H
+
+ /* Includes: */
+ #include "../../Common/Common.h"
+
+ #if (BOARD == BOARD_USBKEY)
+ #include "AVR8/USBKEY/Board.h"
+ #elif (BOARD == BOARD_STK525)
+ #include "AVR8/STK525/Board.h"
+ #elif (BOARD == BOARD_STK526)
+ #include "AVR8/STK526/Board.h"
+ #elif (BOARD == BOARD_RZUSBSTICK)
+ #include "AVR8/RZUSBSTICK/Board.h"
+ #elif (BOARD == BOARD_ATAVRUSBRF01)
+ #include "AVR8/ATAVRUSBRF01/Board.h"
+ #elif ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
+ #include "AVR8/XPLAIN/Board.h"
+ #elif (BOARD == BOARD_BUMBLEB)
+ #include "AVR8/BUMBLEB/Board.h"
+ #elif (BOARD == BOARD_EVK527)
+ #include "AVR8/EVK527/Board.h"
+ #elif ((BOARD == BOARD_TEENSY) || (BOARD == BOARD_TEENSY2))
+ #include "AVR8/TEENSY/Board.h"
+ #elif (BOARD == BOARD_USBTINYMKII)
+ #include "AVR8/USBTINYMKII/Board.h"
+ #elif (BOARD == BOARD_BENITO)
+ #include "AVR8/BENITO/Board.h"
+ #elif (BOARD == BOARD_JMDBU2)
+ #include "AVR8/JMDBU2/Board.h"
+ #elif (BOARD == BOARD_OLIMEX162)
+ #include "AVR8/OLIMEX162/Board.h"
+ #elif (BOARD == BOARD_USBFOO)
+ #include "AVR8/USBFOO/Board.h"
+ #elif (BOARD == BOARD_UDIP)
+ #include "AVR8/UDIP/Board.h"
+ #elif (BOARD == BOARD_BUI)
+ #include "AVR8/BUI/Board.h"
+ #elif (BOARD == BOARD_UNO)
+ #include "AVR8/UNO/Board.h"
+ #elif (BOARD == BOARD_CULV3)
+ #include "AVR8/CULV3/Board.h"
+ #elif (BOARD == BOARD_BLACKCAT)
+ #include "AVR8/BLACKCAT/Board.h"
+ #elif (BOARD == BOARD_MAXIMUS)
+ #include "AVR8/MAXIMUS/Board.h"
+ #elif (BOARD == BOARD_MINIMUS)
+ #include "AVR8/MINIMUS/Board.h"
+ #elif (BOARD == BOARD_ADAFRUITU4)
+ #include "AVR8/ADAFRUITU4/Board.h"
+ #elif (BOARD == BOARD_MICROSIN162)
+ #include "AVR8/MICROSIN162/Board.h"
+ #elif (BOARD == BOARD_SPARKFUN8U2)
+ #include "AVR8/SPARKFUN8U2/Board.h"
+ #elif (BOARD == BOARD_EVK1101)
+ #include "UC3/EVK1101/Board.h"
+ #elif (BOARD == BOARD_TUL)
+ #include "AVR8/TUL/Board.h"
+ #elif (BOARD == BOARD_EVK1100)
+ #include "UC3/EVK1100/Board.h"
+ #elif (BOARD == BOARD_EVK1104)
+ #include "UC3/EVK1104/Board.h"
+ #elif (BOARD == BOARD_A3BU_XPLAINED)
+ #include "XMEGA/A3BU_XPLAINED/Board.h"
+ #elif ((BOARD == BOARD_USB2AX) || (BOARD == BOARD_USB2AX_V3) || (BOARD == BOARD_USB2AX_V31))
+ #include "AVR8/USB2AX/Board.h"
+ #elif ((BOARD == BOARD_MICROPENDOUS_REV1) || (BOARD == BOARD_MICROPENDOUS_REV2) || \
+ (BOARD == BOARD_MICROPENDOUS_32U2) || (BOARD == BOARD_MICROPENDOUS_A) || \
+ (BOARD == BOARD_MICROPENDOUS_1) || (BOARD == BOARD_MICROPENDOUS_2) || \
+ (BOARD == BOARD_MICROPENDOUS_3) || (BOARD == BOARD_MICROPENDOUS_4) || \
+ (BOARD == BOARD_MICROPENDOUS_DIP))
+ #include "AVR8/MICROPENDOUS/Board.h"
+ #elif (BOARD == BOARD_B1_XPLAINED)
+ #include "XMEGA/B1_XPLAINED/Board.h"
+ #elif (BOARD == BOARD_MULTIO)
+ #include "AVR8/MULTIO/Board.h"
+ #elif (BOARD == BOARD_BIGMULTIO)
+ #include "AVR8/BIGMULTIO/Board.h"
+ #elif (BOARD == BOARD_DUCE)
+ #include "AVR8/DUCE/Board.h"
+ #elif (BOARD == BOARD_OLIMEX32U4)
+ #include "AVR8/OLIMEX32U4/Board.h"
+ #elif (BOARD == BOARD_OLIMEXT32U4)
+ #include "AVR8/OLIMEXT32U4/Board.h"
+ #elif (BOARD == BOARD_OLIMEXISPMK2)
+ #include "AVR8/OLIMEXISPMK2/Board.h"
+ #elif (BOARD == BOARD_LEONARDO)
+ #include "AVR8/LEONARDO/Board.h"
+ #elif (BOARD == BOARD_UC3A3_XPLAINED)
+ #include "UC3/UC3A3_XPLAINED/Board.h"
+ #elif (BOARD == BOARD_STANGE_ISP)
+ #include "AVR8/STANGE_ISP/Board.h"
+ #elif (BOARD == BOARD_C3_XPLAINED)
+ #include "XMEGA/C3_XPLAINED/Board.h"
+ #elif (BOARD == BOARD_U2S)
+ #include "AVR8/U2S/Board.h"
+ #elif (BOARD == BOARD_YUN)
+ #include "AVR8/YUN/Board.h"
+ #elif (BOARD == BOARD_MICRO)
+ #include "AVR8/MICRO/Board.h"
+ #else
+ #include "Board/Board.h"
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/Buttons.h
new file mode 100644
index 000000000..dc22cc1ab
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/Buttons.h
@@ -0,0 +1,188 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Digital button board hardware driver.
+ *
+ * This file is the master dispatch header file for the board-specific Buttons driver, for boards containing
+ * physical pushbuttons connected to the microcontroller's GPIO pins.
+ *
+ * User code should include this file, which will in turn include the correct Button driver header file for the
+ * currently selected board.
+ *
+ * If the \c BOARD value is set to \c BOARD_USER, this will include the \c /Board/Buttons.h file in the user project
+ * directory.
+ *
+ * For possible \c BOARD makefile values, see \ref Group_BoardTypes.
+ */
+
+/** \ingroup Group_BoardDrivers
+ * \defgroup Group_Buttons Buttons Driver - LUFA/Drivers/Board/Buttons.h
+ * \brief Digital button board hardware driver.
+ *
+ * \section Sec_Buttons_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - None
+ *
+ * \section Sec_Buttons_ModDescription Module Description
+ * Hardware buttons driver. This provides an easy to use driver for the hardware buttons present on many boards.
+ * It provides a way to easily configure and check the status of all the buttons on the board so that appropriate
+ * actions can be taken.
+ *
+ * If the \c BOARD value is set to \c BOARD_USER, this will include the \c /Board/Buttons.h file in the user project
+ * directory. Otherwise, it will include the appropriate built-in board driver header file.
+ *
+ * For possible \c BOARD makefile values, see \ref Group_BoardTypes.
+ *
+ * \section Sec_Buttons_ExampleUsage Example Usage
+ * The following snippet is an example of how this module may be used within a typical
+ * application.
+ *
+ * \code
+ * // Initialize the button driver before first use
+ * Buttons_Init();
+ *
+ * printf("Waiting for button press...\r\n");
+ *
+ * // Loop until a board button has been pressed
+ * uint8_t ButtonPress;
+ * while (!(ButtonPress = Buttons_GetStatus())) {};
+ *
+ * // Display which button was pressed (assuming two board buttons)
+ * printf("Button pressed: %s\r\n", (ButtonPress == BUTTONS_BUTTON1) ? "Button 1" : "Button 2");
+ * \endcode
+ *
+ * @{
+ */
+
+#ifndef __BUTTONS_H__
+#define __BUTTONS_H__
+
+ /* Macros: */
+ #define __INCLUDE_FROM_BUTTONS_H
+
+ /* Includes: */
+ #include "../../Common/Common.h"
+
+ #if (BOARD == BOARD_NONE)
+ #define BUTTONS_BUTTON1 0
+ static inline void Buttons_Init(void) {};
+ static inline uint_reg_t Buttons_GetStatus(void) { return 0; };
+ #elif (BOARD == BOARD_USBKEY)
+ #include "AVR8/USBKEY/Buttons.h"
+ #elif (BOARD == BOARD_STK525)
+ #include "AVR8/STK525/Buttons.h"
+ #elif (BOARD == BOARD_STK526)
+ #include "AVR8/STK526/Buttons.h"
+ #elif (BOARD == BOARD_ATAVRUSBRF01)
+ #include "AVR8/ATAVRUSBRF01/Buttons.h"
+ #elif (BOARD == BOARD_BUMBLEB)
+ #include "AVR8/BUMBLEB/Buttons.h"
+ #elif (BOARD == BOARD_EVK527)
+ #include "AVR8/EVK527/Buttons.h"
+ #elif (BOARD == BOARD_USBTINYMKII)
+ #include "AVR8/USBTINYMKII/Buttons.h"
+ #elif (BOARD == BOARD_BENITO)
+ #include "AVR8/BENITO/Buttons.h"
+ #elif (BOARD == BOARD_JMDBU2)
+ #include "AVR8/JMDBU2/Buttons.h"
+ #elif (BOARD == BOARD_OLIMEX162)
+ #include "AVR8/OLIMEX162/Buttons.h"
+ #elif (BOARD == BOARD_USBFOO)
+ #include "AVR8/USBFOO/Buttons.h"
+ #elif (BOARD == BOARD_UDIP)
+ #include "AVR8/UDIP/Buttons.h"
+ #elif (BOARD == BOARD_CULV3)
+ #include "AVR8/CULV3/Buttons.h"
+ #elif (BOARD == BOARD_MINIMUS)
+ #include "AVR8/MINIMUS/Buttons.h"
+ #elif (BOARD == BOARD_MICROSIN162)
+ #include "AVR8/MICROSIN162/Buttons.h"
+ #elif (BOARD == BOARD_EVK1101)
+ #include "UC3/EVK1101/Buttons.h"
+ #elif (BOARD == BOARD_TUL)
+ #include "AVR8/TUL/Buttons.h"
+ #elif (BOARD == BOARD_EVK1100)
+ #include "UC3/EVK1100/Buttons.h"
+ #elif (BOARD == BOARD_EVK1104)
+ #include "UC3/EVK1104/Buttons.h"
+ #elif (BOARD == BOARD_A3BU_XPLAINED)
+ #include "XMEGA/A3BU_XPLAINED/Buttons.h"
+ #elif ((BOARD == BOARD_USB2AX) || (BOARD == BOARD_USB2AX_V3))
+ #include "AVR8/USB2AX/Buttons.h"
+ #elif ((BOARD == BOARD_MICROPENDOUS_32U2) || (BOARD == BOARD_MICROPENDOUS_A) || \
+ (BOARD == BOARD_MICROPENDOUS_1) || (BOARD == BOARD_MICROPENDOUS_2) || \
+ (BOARD == BOARD_MICROPENDOUS_3) || (BOARD == BOARD_MICROPENDOUS_4) || \
+ (BOARD == BOARD_MICROPENDOUS_REV1) || (BOARD == BOARD_MICROPENDOUS_REV2) || \
+ (BOARD == BOARD_MICROPENDOUS_DIP))
+ #include "AVR8/MICROPENDOUS/Buttons.h"
+ #elif (BOARD == BOARD_B1_XPLAINED)
+ #include "XMEGA/B1_XPLAINED/Buttons.h"
+ #elif (BOARD == BOARD_OLIMEX32U4)
+ #include "AVR8/OLIMEX32U4/Buttons.h"
+ #elif (BOARD == BOARD_OLIMEXT32U4)
+ #include "AVR8/OLIMEXT32U4/Buttons.h"
+ #elif (BOARD == BOARD_OLIMEXISPMK2)
+ #include "AVR8/OLIMEXISPMK2/Buttons.h"
+ #elif (BOARD == BOARD_UC3A3_XPLAINED)
+ #include "UC3/UC3A3_XPLAINED/Buttons.h"
+ #elif (BOARD == BOARD_STANGE_ISP)
+ #include "AVR8/STANGE_ISP/Buttons.h"
+ #elif (BOARD == BOARD_C3_XPLAINED)
+ #include "XMEGA/C3_XPLAINED/Buttons.h"
+ #elif (BOARD == BOARD_U2S)
+ #include "AVR8/U2S/Buttons.h"
+ #else
+ #include "Board/Buttons.h"
+ #endif
+
+ /* Pseudo-Functions for Doxygen: */
+ #if defined(__DOXYGEN__)
+ /** Initializes the buttons driver, so that the current button position can be read. This sets the appropriate
+ * I/O pins to an inputs with pull-ups enabled.
+ *
+ * This must be called before any Button driver functions are used.
+ */
+ static inline void Buttons_Init(void);
+
+ /** Disables the buttons driver, releasing the I/O pins back to their default high-impedance input mode. */
+ static inline void Buttons_Disable(void);
+
+ /** Returns a mask indicating which board buttons are currently pressed.
+ *
+ * \return Mask of \c BUTTONS_BUTTON* constants indicating which board buttons are currently pressed.
+ */
+ static inline uint_reg_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/Dataflash.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/Dataflash.h
new file mode 100644
index 000000000..9b4bf5613
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/Dataflash.h
@@ -0,0 +1,264 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Master include file for the board dataflash IC driver.
+ * \brief Atmel Dataflash storage IC board hardware driver.
+ *
+ * This file is the master dispatch header file for the board-specific Atmel dataflash driver, for boards containing
+ * Atmel Dataflash ICs for external non-volatile storage.
+ *
+ * User code should include this file, which will in turn include the correct dataflash driver header file for
+ * the currently selected board.
+ *
+ * If the \c BOARD value is set to \c BOARD_USER, this will include the \c /Board/Dataflash.h file in the user project
+ * directory.
+ *
+ * For possible \c BOARD makefile values, see \ref Group_BoardTypes.
+ */
+
+/** \ingroup Group_BoardDrivers
+ * \defgroup Group_Dataflash Dataflash Driver - LUFA/Drivers/Board/Dataflash.h
+ * \brief Atmel Dataflash storage IC board hardware driver.
+ *
+ * \section Sec_Dataflash_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - None
+ *
+ * \section Sec_Dataflash_ModDescription Module Description
+ * Dataflash driver. This module provides an easy to use interface for the Dataflash ICs located on many boards,
+ * for the storage of large amounts of data into the Dataflash's non-volatile memory.
+ *
+ * If the \c BOARD value is set to \c BOARD_USER, this will include the \c /Board/Dataflash.h file in the user project
+ * directory. Otherwise, it will include the appropriate built-in board driver header file.
+ *
+ * For possible \c BOARD makefile values, see \ref Group_BoardTypes.
+ *
+ * \section Sec_Dataflash_ExampleUsage Example Usage
+ * The following snippet is an example of how this module may be used within a typical
+ * application.
+ *
+ * \code
+ * // Initialize the board Dataflash driver before first use
+ * Dataflash_Init();
+ *
+ * uint8_t WriteBuffer[DATAFLASH_PAGE_SIZE];
+ * uint8_t ReadBuffer[DATAFLASH_PAGE_SIZE];
+ *
+ * // Fill page write buffer with a repeating pattern
+ * for (uint16_t i = 0; i < DATAFLASH_PAGE_SIZE; i++)
+ * WriteBuffer[i] = (i & 0xFF);
+ *
+ * // Must select the chip of interest first before operating on it
+ * Dataflash_SelectChip(DATAFLASH_CHIP1);
+ *
+ * // Write to the Dataflash's first internal memory buffer
+ * printf("Writing data to first dataflash buffer:\r\n");
+ * Dataflash_SendByte(DF_CMD_BUFF1WRITE);
+ * Dataflash_SendAddressBytes(0, 0);
+ *
+ * for (uint16_t i = 0; i < DATAFLASH_PAGE_SIZE; i++)
+ * Dataflash_SendByte(WriteBuffer[i]);
+ *
+ * // Commit the Dataflash's first memory buffer to the non-volatile FLASH memory
+ * printf("Committing page to non-volatile memory page index 5:\r\n");
+ * Dataflash_SendByte(DF_CMD_BUFF1TOMAINMEMWITHERASE);
+ * Dataflash_SendAddressBytes(5, 0);
+ * Dataflash_WaitWhileBusy();
+ *
+ * // Read the page from non-volatile FLASH memory into the Dataflash's second memory buffer
+ * printf("Reading data into second dataflash buffer:\r\n");
+ * Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF2);
+ * Dataflash_SendAddressBytes(5, 0);
+ * Dataflash_WaitWhileBusy();
+ *
+ * // Read the Dataflash's second internal memory buffer
+ * Dataflash_SendByte(DF_CMD_BUFF2READ);
+ * Dataflash_SendAddressBytes(0, 0);
+ *
+ * for (uint16_t i = 0; i < DATAFLASH_PAGE_SIZE; i++)
+ * ReadBuffer[i] = Dataflash_ReceiveByte();
+ *
+ * // Deselect the chip after use
+ * Dataflash_DeselectChip();
+ * \endcode
+ *
+ * @{
+ */
+
+#ifndef __DATAFLASH_H__
+#define __DATAFLASH_H__
+
+ /* Macros: */
+ #define __INCLUDE_FROM_DATAFLASH_H
+
+ /* Includes: */
+ #include "../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Retrieves the Dataflash chip select mask for the given Dataflash chip index.
+ *
+ * \attention This macro will only work correctly on chip index numbers that are compile-time
+ * constants defined by the preprocessor.
+ *
+ * \param[in] index Index of the dataflash chip mask to retrieve.
+ *
+ * \return Mask for the given Dataflash chip's /CS pin
+ */
+ #define DATAFLASH_CHIP_MASK(index) CONCAT_EXPANDED(DATAFLASH_CHIP, index)
+
+ /* Inline Functions: */
+ /** Initializes the dataflash driver so that commands and data may be sent to an attached dataflash IC.
+ *
+ * \note The microcontroller's physical interface driver connected to the Dataflash IC must be initialized before
+ * any of the dataflash commands are used. This is usually a SPI hardware port, but on some devices/boards may
+ * be a USART operating in SPI Master mode.
+ */
+ static inline void Dataflash_Init(void);
+
+ /** Determines the currently selected dataflash chip.
+ *
+ * \return Mask of the currently selected Dataflash chip, either \ref DATAFLASH_NO_CHIP if no chip is selected
+ * or a \c DATAFLASH_CHIPn mask (where n is the chip number).
+ */
+ static inline uint8_t Dataflash_GetSelectedChip(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+
+ /** Selects the given dataflash chip.
+ *
+ * \param[in] ChipMask Mask of the Dataflash IC to select, in the form of a \c DATAFLASH_CHIPn mask (where n is
+ * the chip number).
+ */
+ static inline void Dataflash_SelectChip(const uint8_t ChipMask) ATTR_ALWAYS_INLINE;
+
+ /** Deselects the current dataflash chip, so that no dataflash is selected. */
+ static inline void Dataflash_DeselectChip(void) ATTR_ALWAYS_INLINE;
+
+ /** Selects a dataflash IC from the given page number, which should range from 0 to
+ * ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1). For boards containing only one
+ * dataflash IC, this will select \ref DATAFLASH_CHIP1. If the given page number is outside
+ * the total number of pages contained in the boards dataflash ICs, all dataflash ICs
+ * are deselected.
+ *
+ * \param[in] PageAddress Address of the page to manipulate, ranging from
+ * 0 to ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1).
+ */
+ static inline void Dataflash_SelectChipFromPage(const uint16_t PageAddress);
+
+ /** Toggles the select line of the currently selected dataflash IC, so that it is ready to receive
+ * a new command.
+ */
+ static inline void Dataflash_ToggleSelectedChipCS(void);
+
+ /** Spin-loops while the currently selected dataflash is busy executing a command, such as a main
+ * memory page program or main memory to buffer transfer.
+ */
+ static inline void Dataflash_WaitWhileBusy(void);
+
+ /** Sends a set of page and buffer address bytes to the currently selected dataflash IC, for use with
+ * dataflash commands which require a complete 24-bit address.
+ *
+ * \param[in] PageAddress Page address within the selected dataflash IC
+ * \param[in] BufferByte Address within the dataflash's buffer
+ */
+ static inline void Dataflash_SendAddressBytes(uint16_t PageAddress,
+ const uint16_t BufferByte);
+
+ /** Sends a byte to the currently selected dataflash IC, and returns a byte from the dataflash.
+ *
+ * \param[in] Byte Byte of data to send to the dataflash
+ *
+ * \return Last response byte from the dataflash
+ */
+ static inline uint8_t Dataflash_TransferByte(const uint8_t Byte) ATTR_ALWAYS_INLINE;
+
+ /** Sends a byte to the currently selected dataflash IC, and ignores the next byte from the dataflash.
+ *
+ * \param[in] Byte Byte of data to send to the dataflash
+ */
+ static inline void Dataflash_SendByte(const uint8_t Byte) ATTR_ALWAYS_INLINE;
+
+ /** Sends a dummy byte to the currently selected dataflash IC, and returns the next byte from the dataflash.
+ *
+ * \return Last response byte from the dataflash
+ */
+ static inline uint8_t Dataflash_ReceiveByte(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+
+ /* Includes: */
+ #if (BOARD == BOARD_NONE)
+ #define DATAFLASH_TOTALCHIPS 0
+ #define DATAFLASH_NO_CHIP 0
+ #define DATAFLASH_CHIP1 0
+ #define DATAFLASH_PAGE_SIZE 0
+ #define DATAFLASH_PAGES 0
+ static inline void Dataflash_Init(void) {};
+ static inline uint8_t Dataflash_TransferByte(const uint8_t Byte) { return 0; };
+ static inline void Dataflash_SendByte(const uint8_t Byte) {};
+ static inline uint8_t Dataflash_ReceiveByte(void) { return 0; };
+ static inline uint8_t Dataflash_GetSelectedChip(void) { return 0; };
+ static inline void Dataflash_SelectChip(const uint8_t ChipMask) {};
+ static inline void Dataflash_DeselectChip(void) {};
+ static inline void Dataflash_SelectChipFromPage(const uint16_t PageAddress) {};
+ static inline void Dataflash_ToggleSelectedChipCS(void) {};
+ static inline void Dataflash_WaitWhileBusy(void) {};
+ static inline void Dataflash_SendAddressBytes(uint16_t PageAddress,
+ const uint16_t BufferByte) {};
+ #elif (BOARD == BOARD_USBKEY)
+ #include "AVR8/USBKEY/Dataflash.h"
+ #elif (BOARD == BOARD_STK525)
+ #include "AVR8/STK525/Dataflash.h"
+ #elif (BOARD == BOARD_STK526)
+ #include "AVR8/STK526/Dataflash.h"
+ #elif ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
+ #include "AVR8/XPLAIN/Dataflash.h"
+ #elif (BOARD == BOARD_EVK527)
+ #include "AVR8/EVK527/Dataflash.h"
+ #elif (BOARD == BOARD_A3BU_XPLAINED)
+ #include "XMEGA/A3BU_XPLAINED/Dataflash.h"
+ #elif (BOARD == BOARD_B1_XPLAINED)
+ #include "XMEGA/B1_XPLAINED/Dataflash.h"
+ #else
+ #include "Board/Dataflash.h"
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/Joystick.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/Joystick.h
new file mode 100644
index 000000000..4ecf61fef
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/Joystick.h
@@ -0,0 +1,151 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Digital joystick board hardware driver.
+ *
+ * This file is the master dispatch header file for the board-specific Joystick driver, for boards containing a
+ * digital joystick.
+ *
+ * User code should include this file, which will in turn include the correct joystick driver header file for the
+ * currently selected board.
+ *
+ * If the \c BOARD value is set to \c BOARD_USER, this will include the \c /Board/Joystick.h file in the user project
+ * directory.
+ *
+ * For possible \c BOARD makefile values, see \ref Group_BoardTypes.
+ */
+
+/** \ingroup Group_BoardDrivers
+ * \defgroup Group_Joystick Joystick Driver - LUFA/Drivers/Board/Joystick.h
+ * \brief Digital joystick board hardware driver.
+ *
+ * \section Sec_Joystick_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - None
+ *
+ * \section Sec_Joystick_ModDescription Module Description
+ * Hardware Joystick driver. This module provides an easy to use interface to control the hardware digital Joystick
+ * located on many boards.
+ *
+ * If the \c BOARD value is set to \c BOARD_USER, this will include the \c /Board/Joystick.h file in the user project
+ * directory. Otherwise, it will include the appropriate built-in board driver header file.
+ *
+ * For possible \c BOARD makefile values, see \ref Group_BoardTypes.
+ *
+ * \section Sec_Joystick_ExampleUsage Example Usage
+ * The following snippet is an example of how this module may be used within a typical
+ * application.
+ *
+ * \code
+ * // Initialize the board Joystick driver before first use
+ * Joystick_Init();
+ *
+ * printf("Waiting for joystick movement...\r\n");
+ *
+ * // Loop until a the joystick has been moved
+ * uint8_t JoystickMovement;
+ * while (!(JoystickMovement = Joystick_GetStatus())) {};
+ *
+ * // Display which direction the joystick was moved in
+ * printf("Joystick moved:\r\n");
+ *
+ * if (JoystickMovement & (JOY_UP | JOY_DOWN))
+ * printf("%s ", (JoystickMovement & JOY_UP) ? "Up" : "Down");
+ *
+ * if (JoystickMovement & (JOY_LEFT | JOY_RIGHT))
+ * printf("%s ", (JoystickMovement & JOY_LEFT) ? "Left" : "Right");
+ *
+ * if (JoystickMovement & JOY_PRESS)
+ * printf("Pressed");
+ * \endcode
+ *
+ * @{
+ */
+
+#ifndef __JOYSTICK_H__
+#define __JOYSTICK_H__
+
+ /* Macros: */
+ #define __INCLUDE_FROM_JOYSTICK_H
+
+ /* Includes: */
+ #include "../../Common/Common.h"
+
+ #if (BOARD == BOARD_NONE)
+ #define JOY_UP 0
+ #define JOY_DOWN 0
+ #define JOY_LEFT 0
+ #define JOY_RIGHT 0
+ #define JOY_PRESS 0
+ static inline void Joystick_Init(void) {};
+ static inline uint_reg_t Joystick_GetStatus(void) { return 0; };
+ #elif (BOARD == BOARD_USBKEY)
+ #include "AVR8/USBKEY/Joystick.h"
+ #elif (BOARD == BOARD_STK525)
+ #include "AVR8/STK525/Joystick.h"
+ #elif (BOARD == BOARD_STK526)
+ #include "AVR8/STK526/Joystick.h"
+ #elif (BOARD == BOARD_BUMBLEB)
+ #include "AVR8/BUMBLEB/Joystick.h"
+ #elif (BOARD == BOARD_EVK527)
+ #include "AVR8/EVK527/Joystick.h"
+ #elif (BOARD == BOARD_EVK1101)
+ #include "UC3/EVK1101/Joystick.h"
+ #elif (BOARD == BOARD_EVK1100)
+ #include "UC3/EVK1100/Joystick.h"
+ #else
+ #include "Board/Joystick.h"
+ #endif
+
+ /* Pseudo-Functions for Doxygen: */
+ #if defined(__DOXYGEN__)
+ /** Initializes the joystick driver so that the joystick position can be read. This sets the appropriate
+ * I/O pins to inputs with their pull-ups enabled.
+ *
+ * This must be called before any Joystick driver functions are used.
+ */
+ static inline void Joystick_Init(void);
+
+ /** Disables the joystick driver, releasing the I/O pins back to their default high-impedance input mode. */
+ static inline void Joystick_Disable(void);
+
+ /** Returns the current status of the joystick, as a mask indicating the direction the joystick is
+ * currently facing in (multiple bits can be set).
+ *
+ * \return Mask of \c JOYSTICK_* constants indicating the current joystick direction(s).
+ */
+ static inline uint_reg_t Joystick_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/LEDs.h
new file mode 100644
index 000000000..392714a4e
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/LEDs.h
@@ -0,0 +1,298 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief LED board hardware driver.
+ *
+ * This file is the master dispatch header file for the board-specific LED driver, for boards containing user
+ * controllable LEDs.
+ *
+ * User code should include this file, which will in turn include the correct LED driver header file for the
+ * currently selected board.
+ *
+ * If the \c BOARD value is set to \c BOARD_USER, this will include the \c /Board/LEDs.h file in the user project
+ * directory.
+ *
+ * For possible \c BOARD makefile values, see \ref Group_BoardTypes.
+ */
+
+/** \ingroup Group_BoardDrivers
+ * \defgroup Group_LEDs LEDs Driver - LUFA/Drivers/Board/LEDs.h
+ * \brief LED board hardware driver.
+ *
+ * \section Sec_LEDs_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - None
+ *
+ * \section Sec_LEDs_ModDescription Module Description
+ * Hardware LEDs driver. This provides an easy to use driver for the hardware LEDs present on many boards. It
+ * provides an interface to configure, test and change the status of all the board LEDs.
+ *
+ * If the \c BOARD value is set to \c BOARD_USER, this will include the \c /Board/LEDs.h file in the user project
+ * directory. Otherwise, it will include the appropriate built-in board driver header file. If the BOARD value
+ * is set to \c BOARD_NONE, this driver is silently disabled.
+ *
+ * For possible \c BOARD makefile values, see \ref Group_BoardTypes.
+ *
+ * \note To make code as compatible as possible, it is assumed that all boards carry a minimum of four LEDs. If
+ * a board contains less than four LEDs, the remaining LED masks are defined to 0 so as to have no effect.
+ * If other behavior is desired, either alias the remaining LED masks to existing LED masks via the -D
+ * switch in the project makefile, or alias them to nothing in the makefile to cause compilation errors when
+ * a non-existing LED is referenced in application code. Note that this means that it is possible to make
+ * compatible code for a board with no LEDs by making a board LED driver (see \ref Page_WritingBoardDrivers)
+ * which contains only stub functions and defines no LEDs.
+ *
+ * \section Sec_LEDs_ExampleUsage Example Usage
+ * The following snippet is an example of how this module may be used within a typical
+ * application.
+ *
+ * \code
+ * // Initialize the board LED driver before first use
+ * LEDs_Init();
+ *
+ * // Turn on each of the four LEDs in turn
+ * LEDs_SetAllLEDs(LEDS_LED1);
+ * Delay_MS(500);
+ * LEDs_SetAllLEDs(LEDS_LED2);
+ * Delay_MS(500);
+ * LEDs_SetAllLEDs(LEDS_LED3);
+ * Delay_MS(500);
+ * LEDs_SetAllLEDs(LEDS_LED4);
+ * Delay_MS(500);
+ *
+ * // Turn on all LEDs
+ * LEDs_SetAllLEDs(LEDS_ALL_LEDS);
+ * Delay_MS(1000);
+ *
+ * // Turn on LED 1, turn off LED 2, leaving LEDs 3 and 4 in their current state
+ * LEDs_ChangeLEDs((LEDS_LED1 | LEDS_LED2), LEDS_LED1);
+ * \endcode
+ *
+ * @{
+ */
+
+#ifndef __LEDS_H__
+#define __LEDS_H__
+
+ /* Macros: */
+ #define __INCLUDE_FROM_LEDS_H
+
+ /* Includes: */
+ #include "../../Common/Common.h"
+
+ #if (BOARD == BOARD_NONE)
+ static inline void LEDs_Init(void) {};
+ static inline void LEDs_Disable(void) {};
+ static inline void LEDs_TurnOnLEDs(const uint_reg_t LEDMask) {};
+ static inline void LEDs_TurnOffLEDs(const uint_reg_t LEDMask) {};
+ static inline void LEDs_SetAllLEDs(const uint_reg_t LEDMask) {};
+ static inline void LEDs_ChangeLEDs(const uint_reg_t LEDMask, const uint_reg_t ActiveMask) {};
+ static inline void LEDs_ToggleLEDs(const uint_reg_t LEDMask) {};
+ static inline uint_reg_t LEDs_GetLEDs(void) { return 0; }
+ #elif (BOARD == BOARD_USBKEY)
+ #include "AVR8/USBKEY/LEDs.h"
+ #elif (BOARD == BOARD_STK525)
+ #include "AVR8/STK525/LEDs.h"
+ #elif (BOARD == BOARD_STK526)
+ #include "AVR8/STK526/LEDs.h"
+ #elif (BOARD == BOARD_RZUSBSTICK)
+ #include "AVR8/RZUSBSTICK/LEDs.h"
+ #elif (BOARD == BOARD_ATAVRUSBRF01)
+ #include "AVR8/ATAVRUSBRF01/LEDs.h"
+ #elif ((BOARD == BOARD_XPLAIN) || (BOARD == BOARD_XPLAIN_REV1))
+ #include "AVR8/XPLAIN/LEDs.h"
+ #elif (BOARD == BOARD_BUMBLEB)
+ #include "AVR8/BUMBLEB/LEDs.h"
+ #elif (BOARD == BOARD_EVK527)
+ #include "AVR8/EVK527/LEDs.h"
+ #elif ((BOARD == BOARD_TEENSY) || (BOARD == BOARD_TEENSY2))
+ #include "AVR8/TEENSY/LEDs.h"
+ #elif (BOARD == BOARD_USBTINYMKII)
+ #include "AVR8/USBTINYMKII/LEDs.h"
+ #elif (BOARD == BOARD_BENITO)
+ #include "AVR8/BENITO/LEDs.h"
+ #elif (BOARD == BOARD_JMDBU2)
+ #include "AVR8/JMDBU2/LEDs.h"
+ #elif (BOARD == BOARD_OLIMEX162)
+ #include "AVR8/OLIMEX162/LEDs.h"
+ #elif (BOARD == BOARD_USBFOO)
+ #include "AVR8/USBFOO/LEDs.h"
+ #elif (BOARD == BOARD_UDIP)
+ #include "AVR8/UDIP/LEDs.h"
+ #elif (BOARD == BOARD_BUI)
+ #include "AVR8/BUI/LEDs.h"
+ #elif (BOARD == BOARD_UNO)
+ #include "AVR8/UNO/LEDs.h"
+ #elif (BOARD == BOARD_CULV3)
+ #include "AVR8/CULV3/LEDs.h"
+ #elif (BOARD == BOARD_BLACKCAT)
+ #include "AVR8/BLACKCAT/LEDs.h"
+ #elif (BOARD == BOARD_MAXIMUS)
+ #include "AVR8/MAXIMUS/LEDs.h"
+ #elif (BOARD == BOARD_MINIMUS)
+ #include "AVR8/MINIMUS/LEDs.h"
+ #elif (BOARD == BOARD_ADAFRUITU4)
+ #include "AVR8/ADAFRUITU4/LEDs.h"
+ #elif (BOARD == BOARD_MICROSIN162)
+ #include "AVR8/MICROSIN162/LEDs.h"
+ #elif (BOARD == BOARD_SPARKFUN8U2)
+ #include "AVR8/SPARKFUN8U2/LEDs.h"
+ #elif (BOARD == BOARD_EVK1101)
+ #include "UC3/EVK1101/LEDs.h"
+ #elif (BOARD == BOARD_TUL)
+ #include "AVR8/TUL/LEDs.h"
+ #elif (BOARD == BOARD_EVK1100)
+ #include "UC3/EVK1100/LEDs.h"
+ #elif (BOARD == BOARD_EVK1104)
+ #include "UC3/EVK1104/LEDs.h"
+ #elif (BOARD == BOARD_A3BU_XPLAINED)
+ #include "XMEGA/A3BU_XPLAINED/LEDs.h"
+ #elif ((BOARD == BOARD_USB2AX) || (BOARD == BOARD_USB2AX_V3) || (BOARD == BOARD_USB2AX_V31))
+ #include "AVR8/USB2AX/LEDs.h"
+ #elif ((BOARD == BOARD_MICROPENDOUS_REV1) || (BOARD == BOARD_MICROPENDOUS_REV2) || \
+ (BOARD == BOARD_MICROPENDOUS_32U2))
+ #include "AVR8/MICROPENDOUS/LEDs.h"
+ #elif (BOARD == BOARD_B1_XPLAINED)
+ #include "XMEGA/B1_XPLAINED/LEDs.h"
+ #elif (BOARD == BOARD_MULTIO)
+ #include "AVR8/MULTIO/LEDs.h"
+ #elif (BOARD == BOARD_BIGMULTIO)
+ #include "AVR8/BIGMULTIO/LEDs.h"
+ #elif (BOARD == BOARD_DUCE)
+ #include "AVR8/DUCE/LEDs.h"
+ #elif (BOARD == BOARD_OLIMEX32U4)
+ #include "AVR8/OLIMEX32U4/LEDs.h"
+ #elif (BOARD == BOARD_OLIMEXT32U4)
+ #include "AVR8/OLIMEXT32U4/LEDs.h"
+ #elif (BOARD == BOARD_OLIMEXISPMK2)
+ #include "AVR8/OLIMEXISPMK2/LEDs.h"
+ #elif (BOARD == BOARD_LEONARDO)
+ #include "AVR8/LEONARDO/LEDs.h"
+ #elif (BOARD == BOARD_UC3A3_XPLAINED)
+ #include "UC3/UC3A3_XPLAINED/LEDs.h"
+ #elif (BOARD == BOARD_STANGE_ISP)
+ #include "AVR8/STANGE_ISP/LEDs.h"
+ #elif (BOARD == BOARD_C3_XPLAINED)
+ #include "XMEGA/C3_XPLAINED/LEDs.h"
+ #elif (BOARD == BOARD_U2S)
+ #include "AVR8/U2S/LEDs.h"
+ #elif (BOARD == BOARD_YUN)
+ #include "AVR8/YUN/LEDs.h"
+ #elif (BOARD == BOARD_MICRO)
+ #include "AVR8/MICRO/LEDs.h"
+ #else
+ #include "Board/LEDs.h"
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__DOXYGEN__)
+ #if !defined(LEDS_NO_LEDS)
+ #define LEDS_NO_LEDS 0
+ #endif
+
+ #if !defined(LEDS_ALL_LEDS)
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3 | LEDS_LED4)
+ #endif
+
+ #if !defined(LEDS_LED1)
+ #define LEDS_LED1 0
+ #endif
+
+ #if !defined(LEDS_LED2)
+ #define LEDS_LED2 0
+ #endif
+
+ #if !defined(LEDS_LED3)
+ #define LEDS_LED3 0
+ #endif
+
+ #if !defined(LEDS_LED4)
+ #define LEDS_LED4 0
+ #endif
+ #endif
+
+ /* Pseudo-Functions for Doxygen: */
+ #if defined(__DOXYGEN__)
+ /** Initializes the board LED driver so that the LEDs can be controlled. This sets the appropriate port
+ * I/O pins as outputs, and sets the LEDs to default to off.
+ *
+ * This must be called before any LED driver functions are used.
+ */
+ static inline void LEDs_Init(void);
+
+ /** Disables the board LED driver, releasing the I/O pins back to their default high-impedance input mode. */
+ static inline void LEDs_Disable(void);
+
+ /** Turns on the LEDs specified in the given LED mask.
+ *
+ * \param[in] LEDMask Mask of the board LEDs to manipulate (see board-specific LEDs.h driver file).
+ */
+ static inline void LEDs_TurnOnLEDs(const uint_reg_t LEDMask);
+
+ /** Turns off the LEDs specified in the given LED mask.
+ *
+ * \param[in] LEDMask Mask of the board LEDs to manipulate (see board-specific LEDs.h driver file).
+ */
+ static inline void LEDs_TurnOffLEDs(const uint_reg_t LEDMask);
+
+ /** Turns off all LEDs not specified in the given LED mask, and turns on all the LEDs in the given LED
+ * mask.
+ *
+ * \param[in] LEDMask Mask of the board LEDs to manipulate (see board-specific LEDs.h driver file).
+ */
+ static inline void LEDs_SetAllLEDs(const uint_reg_t LEDMask);
+
+ /** Turns off all LEDs in the LED mask that are not set in the active mask, and turns on all the LEDs
+ * specified in both the LED and active masks.
+ *
+ * \param[in] LEDMask Mask of the board LEDs to manipulate (see board-specific LEDs.h driver file).
+ * \param[in] ActiveMask Mask of whether the LEDs in the LED mask should be turned on or off.
+ */
+ static inline void LEDs_ChangeLEDs(const uint_reg_t LEDMask,
+ const uint_reg_t ActiveMask);
+
+ /** Toggles all LEDs in the LED mask, leaving all others in their current states.
+ *
+ * \param[in] LEDMask Mask of the board LEDs to manipulate (see board-specific LEDs.h driver file).
+ */
+ static inline void LEDs_ToggleLEDs(const uint_reg_t LEDMask);
+
+ /** Returns the status of all the board LEDs; set LED masks in the return value indicate that the
+ * corresponding LED is on.
+ *
+ * \return Mask of \c LEDS_LED* constants indicating which of the board LEDs are currently turned on.
+ */
+ static inline uint_reg_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/Temperature.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/Temperature.c
new file mode 100644
index 000000000..8b09f1094
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/Temperature.c
@@ -0,0 +1,66 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#define __INCLUDE_FROM_TEMPERATURE_C
+#include "Temperature.h"
+
+#if defined(TEMPERATURE_SENSOR_DRIVER_COMPATIBLE)
+
+static const uint16_t PROGMEM Temperature_Lookup[TEMP_TABLE_SIZE] =
+{
+ 0x3B4, 0x3B0, 0x3AB, 0x3A6, 0x3A0, 0x39A, 0x394, 0x38E, 0x388, 0x381, 0x37A, 0x373,
+ 0x36B, 0x363, 0x35B, 0x353, 0x34A, 0x341, 0x338, 0x32F, 0x325, 0x31B, 0x311, 0x307,
+ 0x2FC, 0x2F1, 0x2E6, 0x2DB, 0x2D0, 0x2C4, 0x2B8, 0x2AC, 0x2A0, 0x294, 0x288, 0x27C,
+ 0x26F, 0x263, 0x256, 0x24A, 0x23D, 0x231, 0x225, 0x218, 0x20C, 0x200, 0x1F3, 0x1E7,
+ 0x1DB, 0x1CF, 0x1C4, 0x1B8, 0x1AC, 0x1A1, 0x196, 0x18B, 0x180, 0x176, 0x16B, 0x161,
+ 0x157, 0x14D, 0x144, 0x13A, 0x131, 0x128, 0x11F, 0x117, 0x10F, 0x106, 0x0FE, 0x0F7,
+ 0x0EF, 0x0E8, 0x0E1, 0x0DA, 0x0D3, 0x0CD, 0x0C7, 0x0C0, 0x0BA, 0x0B5, 0x0AF, 0x0AA,
+ 0x0A4, 0x09F, 0x09A, 0x096, 0x091, 0x08C, 0x088, 0x084, 0x080, 0x07C, 0x078, 0x074,
+ 0x071, 0x06D, 0x06A, 0x067, 0x064, 0x061, 0x05E, 0x05B, 0x058, 0x055, 0x053, 0x050,
+ 0x04E, 0x04C, 0x049, 0x047, 0x045, 0x043, 0x041, 0x03F, 0x03D, 0x03C, 0x03A, 0x038
+};
+
+int8_t Temperature_GetTemperature(void)
+{
+ uint16_t Temp_ADC = ADC_GetChannelReading(ADC_REFERENCE_AVCC | ADC_RIGHT_ADJUSTED | TEMP_ADC_CHANNEL_MASK);
+
+ if (Temp_ADC > pgm_read_word(&Temperature_Lookup[0]))
+ return TEMP_MIN_TEMP;
+
+ for (uint16_t Index = 0; Index < TEMP_TABLE_SIZE; Index++)
+ {
+ if (Temp_ADC > pgm_read_word(&Temperature_Lookup[Index]))
+ return (Index + TEMP_TABLE_OFFSET_DEGREES);
+ }
+
+ return TEMP_MAX_TEMP;
+}
+
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/Temperature.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/Temperature.h
new file mode 100644
index 000000000..d20c6f701
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/Temperature.h
@@ -0,0 +1,147 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief NTC Temperature Sensor board hardware driver.
+ *
+ * Master include file for the board temperature sensor driver, for the USB boards which contain a temperature sensor.
+ */
+
+/** \ingroup Group_BoardDrivers
+ * \defgroup Group_Temperature Temperature Sensor Driver - LUFA/Drivers/Board/Temperature.h
+ * \brief NTC Temperature Sensor board hardware driver.
+ *
+ * \section Sec_Temperature_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Drivers/Board/Temperature.c <i>(Makefile source module name: LUFA_SRC_TEMPERATURE)</i>
+ *
+ * \section Sec_Temperature_ModDescription Module Description
+ * Temperature sensor driver. This provides an easy to use interface for the hardware temperature sensor located
+ * on many boards. It provides an interface to configure the sensor and appropriate ADC channel, plus read out the
+ * current temperature in degrees C. It is designed for and will only work with the temperature sensor located on the
+ * official Atmel USB AVR boards, as each sensor has different characteristics.
+ *
+ * \section Sec_Temperature_ExampleUsage Example Usage
+ * The following snippet is an example of how this module may be used within a typical
+ * application.
+ *
+ * \code
+ * // Initialize the ADC and board temperature sensor drivers before first use
+ * ADC_Init(ADC_FREE_RUNNING | ADC_PRESCALE_128);
+ * Temperature_Init();
+ *
+ * // Display converted temperature in degrees Celsius
+ * printf("Current Temperature: %d Degrees\r\n", Temperature_GetTemperature());
+ * \endcode
+ *
+ * @{
+ */
+
+#ifndef __TEMPERATURE_H__
+#define __TEMPERATURE_H__
+
+ /* Includes: */
+ #include "../../Common/Common.h"
+
+ /* Preprocessor Checks: */
+ #if ((BOARD == BOARD_USBKEY) || (BOARD == BOARD_STK525) || \
+ (BOARD == BOARD_STK526) || (BOARD == BOARD_EVK527))
+ #define TEMPERATURE_SENSOR_DRIVER_COMPATIBLE
+ #endif
+
+ #if !defined(__INCLUDE_FROM_TEMPERATURE_C) && !defined(TEMPERATURE_SENSOR_DRIVER_COMPATIBLE)
+ #error The selected board does not contain a compatible temperature sensor.
+ #endif
+
+ #if defined(TEMPERATURE_SENSOR_DRIVER_COMPATIBLE)
+
+ /* Includes: */
+ #include "../Peripheral/ADC.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** ADC channel number for the temperature sensor. */
+ #define TEMP_ADC_CHANNEL 0
+
+ /** ADC channel MUX mask for the temperature sensor. */
+ #define TEMP_ADC_CHANNEL_MASK ADC_CHANNEL0
+
+ /** Size of the temperature sensor lookup table, in lookup values */
+ #define TEMP_TABLE_SIZE 120
+
+ /** Minimum returnable temperature from the \ref Temperature_GetTemperature() function. */
+ #define TEMP_MIN_TEMP TEMP_TABLE_OFFSET_DEGREES
+
+ /** Maximum returnable temperature from the \ref Temperature_GetTemperature() function. */
+ #define TEMP_MAX_TEMP ((TEMP_TABLE_SIZE - 1) + TEMP_TABLE_OFFSET_DEGREES)
+
+ /* Inline Functions: */
+ /** Initializes the temperature sensor driver, including setting up the appropriate ADC channel.
+ * This must be called before any other temperature sensor routines.
+ *
+ * \pre The ADC itself (not the ADC channel) must be configured separately before calling the
+ * temperature sensor functions.
+ */
+ static inline void Temperature_Init(void) ATTR_ALWAYS_INLINE;
+ static inline void Temperature_Init(void)
+ {
+ ADC_SetupChannel(TEMP_ADC_CHANNEL);
+ }
+
+ /* Function Prototypes: */
+ /** Performs a complete ADC on the temperature sensor channel, and converts the result into a
+ * valid temperature between \ref TEMP_MIN_TEMP and \ref TEMP_MAX_TEMP in degrees Celsius.
+ *
+ * \return Signed temperature value in degrees Celsius.
+ */
+ int8_t Temperature_GetTemperature(void) ATTR_WARN_UNUSED_RESULT;
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define TEMP_TABLE_OFFSET_DEGREES -21
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1100/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1100/Board.h
new file mode 100644
index 000000000..0c34a3f04
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1100/Board.h
@@ -0,0 +1,86 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Atmel EVK1100.
+ * \copydetails Group_BoardInfo_EVK1100
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_EVK1100 EVK1100
+ * \brief Board specific information header for the Atmel Atmel EVK1100.
+ *
+ * Board specific information header for the Atmel Atmel EVK1100.
+ *
+ * @{
+ */
+
+#ifndef __BOARD_EVK1100_H__
+#define __BOARD_EVK1100_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../Buttons.h"
+ #include "../../Joystick.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware Buttons mounted. */
+ #define BOARD_HAS_BUTTONS
+
+ /** Indicates the board has a hardware Joystick mounted. */
+ #define BOARD_HAS_JOYSTICK
+
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1100/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1100/Buttons.h
new file mode 100644
index 000000000..fa452003f
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1100/Buttons.h
@@ -0,0 +1,117 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Buttons driver header for the Atmel EVK1100.
+ * \copydetails Group_Buttons_EVK1100
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Buttons driver
+ * dispatch header located in LUFA/Drivers/Board/Buttons.h.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_EVK1100 EVK1100
+ * \brief Board specific Buttons driver header for the Atmel EVK1100.
+ *
+ * Board specific Buttons driver header for the Atmel EVK1100.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>BUTTONS_BUTTON1</td><td>SW0 Button</td><td>Low</td><td>GPIO88</td></tr>
+ * <tr><td>BUTTONS_BUTTON2</td><td>SW1 Button</td><td>Low</td><td>GPIO85</td></tr>
+ * <tr><td>BUTTONS_BUTTON3</td><td>SW2 Button</td><td>Low</td><td>GPIO82</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __BUTTONS_EVK1100_H__
+#define __BUTTONS_EVK1100_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define BUTTONS_PORT 2
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Mask of the first button on the board */
+ #define BUTTONS_BUTTON1 (1UL << 24)
+
+ /** Mask of the second button on the board */
+ #define BUTTONS_BUTTON2 (1UL << 21)
+
+ /** Mask of the third button on the board */
+ #define BUTTONS_BUTTON3 (1UL << 18)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+ AVR32_GPIO.port[BUTTONS_PORT].gpers = (BUTTONS_BUTTON1 | BUTTONS_BUTTON2);
+ AVR32_GPIO.port[BUTTONS_PORT].puers = (BUTTONS_BUTTON1 | BUTTONS_BUTTON2);
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+ AVR32_GPIO.port[BUTTONS_PORT].gperc = (BUTTONS_BUTTON1 | BUTTONS_BUTTON2);
+ AVR32_GPIO.port[BUTTONS_PORT].puerc = (BUTTONS_BUTTON1 | BUTTONS_BUTTON2);
+ }
+
+ static inline uint32_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint32_t Buttons_GetStatus(void)
+ {
+ return (~(AVR32_GPIO.port[JOY_MOVE_PORT].pvr & (BUTTONS_BUTTON1 | BUTTONS_BUTTON2)));
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1100/Joystick.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1100/Joystick.h
new file mode 100644
index 000000000..72dd769b0
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1100/Joystick.h
@@ -0,0 +1,122 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific joystick driver header for the Atmel EVK1100.
+ * \copydetails Group_Joystick_EVK1100
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the joystick driver
+ * dispatch header located in LUFA/Drivers/Board/Joystick.h.
+ */
+
+/** \ingroup Group_Joystick
+ * \defgroup Group_Joystick_EVK1100 EVK1100
+ * \brief Board specific joystick driver header for the Atmel EVK1100.
+ *
+ * Board specific joystick driver header for the Atmel EVK1100.
+ *
+ * <table>
+ * <tr><th>Left Port Pin</th><th>Up Port Pin</th><th>Right Port Pin</th><th>Down Port Pin</th><th>Press Port Pin</th></tr>
+ * <tr><td>GPIO25</td><td>GPIO26</td><td>GPIO28</td><td>GPIO27</td><td>GPIO20</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __JOYSTICK_EVK1100_H__
+#define __JOYSTICK_EVK1100_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_JOYSTICK_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Joystick.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define JOY_PORT 0
+ #define JOY_MASK ((1UL << 28) | (1UL << 27) | (1UL << 26) | (1UL << 25) | (1UL << 20))
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Mask for the joystick being pushed in the left direction. */
+ #define JOY_LEFT (1UL << 25)
+
+ /** Mask for the joystick being pushed in the upward direction. */
+ #define JOY_UP (1UL << 26)
+
+ /** Mask for the joystick being pushed in the right direction. */
+ #define JOY_RIGHT (1UL << 28)
+
+ /** Mask for the joystick being pushed in the downward direction. */
+ #define JOY_DOWN (1UL << 27)
+
+ /** Mask for the joystick being pushed inward. */
+ #define JOY_PRESS (1UL << 20)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Joystick_Init(void)
+ {
+ AVR32_GPIO.port[JOY_PORT].gpers = JOY_MASK;
+ AVR32_GPIO.port[JOY_PORT].gpers = JOY_MASK;
+ };
+
+ static inline void Joystick_Disable(void)
+ {
+ AVR32_GPIO.port[JOY_PORT].gperc = JOY_MASK;
+ AVR32_GPIO.port[JOY_PORT].gperc = JOY_MASK;
+ };
+
+ static inline uint32_t Joystick_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint32_t Joystick_GetStatus(void)
+ {
+ return (uint32_t)(~(AVR32_GPIO.port[JOY_PORT].pvr & JOY_MASK));
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1100/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1100/LEDs.h
new file mode 100644
index 000000000..f66eddbc1
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1100/LEDs.h
@@ -0,0 +1,173 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Atmel EVK1100.
+ * \copydetails Group_LEDs_EVK1100
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_EVK1100 EVK1100
+ * \brief Board specific LED driver header for the Atmel EVK1100.
+ *
+ * Board specific LED driver header for the Atmel EVK1100.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Green</td><td>LED0 LED</td><td>Low</td><td>GPIO51</td></tr>
+ * <tr><td>LEDS_LED2</td><td>Green</td><td>LED1 LED</td><td>Low</td><td>GPIO52</td></tr>
+ * <tr><td>LEDS_LED3</td><td>Green</td><td>LED2 LED</td><td>Low</td><td>GPIO53</td></tr>
+ * <tr><td>LEDS_LED4</td><td>Green</td><td>LED3 LED</td><td>Low</td><td>GPIO54</td></tr>
+ * <tr><td>LEDS_LED5</td><td>Green</td><td>LED4 LED</td><td>Low</td><td>GPIO59</td></tr>
+ * <tr><td>LEDS_LED6</td><td>Green</td><td>LED5 LED</td><td>Low</td><td>GPIO60</td></tr>
+ * <tr><td>LEDS_LED7</td><td>Green</td><td>LED6 LED</td><td>Low</td><td>GPIO61</td></tr>
+ * <tr><td>LEDS_LED8</td><td>Green</td><td>LED7 LED</td><td>Low</td><td>GPIO62</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_EVK1100_H__
+#define __LEDS_EVK1100_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define LEDS_PORT 1
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1UL << 19)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1UL << 20)
+
+ /** LED mask for the third LED on the board. */
+ #define LEDS_LED3 (1UL << 21)
+
+ /** LED mask for the fourth LED on the board. */
+ #define LEDS_LED4 (1UL << 22)
+
+ /** LED mask for the fifth LED on the board. */
+ #define LEDS_LED5 (1UL << 27)
+
+ /** LED mask for the sixth LED on the board. */
+ #define LEDS_LED6 (1UL << 28)
+
+ /** LED mask for the seventh LED on the board. */
+ #define LEDS_LED7 (1UL << 29)
+
+ /** LED mask for the eighth LED on the board. */
+ #define LEDS_LED8 (1UL << 30)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3 | LEDS_LED4 \
+ LEDS_LED5 | LEDS_LED6 | LEDS_LED7 | LEDS_LED8)
+
+ /** LED mask for the none of the board LEDs */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ AVR32_GPIO.port[LEDS_PORT].gpers = LEDS_ALL_LEDS;
+ AVR32_GPIO.port[LEDS_PORT].oders = LEDS_ALL_LEDS;
+ AVR32_GPIO.port[LEDS_PORT].ovrs = LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ AVR32_GPIO.port[LEDS_PORT].gperc = LEDS_ALL_LEDS;
+ AVR32_GPIO.port[LEDS_PORT].oderc = LEDS_ALL_LEDS;
+ AVR32_GPIO.port[LEDS_PORT].ovrc = LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint32_t LEDMask)
+ {
+ AVR32_GPIO.port[LEDS_PORT].ovrc = LEDMask;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint32_t LEDMask)
+ {
+ AVR32_GPIO.port[LEDS_PORT].ovrs = LEDMask;
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint32_t LEDMask)
+ {
+ AVR32_GPIO.port[LEDS_PORT].ovrs = LEDS_ALL_LEDS;
+ AVR32_GPIO.port[LEDS_PORT].ovrc = LEDMask;
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint32_t LEDMask, const uint32_t ActiveMask)
+ {
+ AVR32_GPIO.port[LEDS_PORT].ovrs = LEDMask;
+ AVR32_GPIO.port[LEDS_PORT].ovrc = ActiveMask;
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint32_t LEDMask)
+ {
+ AVR32_GPIO.port[LEDS_PORT].ovrt = LEDMask;
+ }
+
+ static inline uint32_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint32_t LEDs_GetLEDs(void)
+ {
+ return (~AVR32_GPIO.port[LEDS_PORT].ovr & LEDS_ALL_LEDS);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1101/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1101/Board.h
new file mode 100644
index 000000000..5d5f95a6a
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1101/Board.h
@@ -0,0 +1,86 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Atmel EVK1101.
+ * \copydetails Group_BoardInfo_EVK1101
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_EVK1101 EVK1101
+ * \brief Board specific information header for the Atmel Atmel EVK1101.
+ *
+ * Board specific information header for the Atmel Atmel EVK1101.
+ *
+ * @{
+ */
+
+#ifndef __BOARD_EVK1101_H__
+#define __BOARD_EVK1101_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../Buttons.h"
+ #include "../../Joystick.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware Buttons mounted. */
+ #define BOARD_HAS_BUTTONS
+
+ /** Indicates the board has a hardware Joystick mounted. */
+ #define BOARD_HAS_JOYSTICK
+
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1101/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1101/Buttons.h
new file mode 100644
index 000000000..3de4b3373
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1101/Buttons.h
@@ -0,0 +1,113 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Buttons driver header for the Atmel EVK1101.
+ * \copydetails Group_Buttons_EVK1101
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Buttons driver
+ * dispatch header located in LUFA/Drivers/Board/Buttons.h.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_EVK1101 EVK1101
+ * \brief Board specific Buttons driver header for the Atmel EVK1101.
+ *
+ * Board specific Buttons driver header for the Atmel EVK1101.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>BUTTONS_BUTTON1</td><td>SW0 Button</td><td>Low</td><td>GPIO34</td></tr>
+ * <tr><td>BUTTONS_BUTTON2</td><td>SW1 Button</td><td>Low</td><td>GPIO35</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __BUTTONS_EVK1101_H__
+#define __BUTTONS_EVK1101_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define BUTTONS_PORT 1
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Mask of the first button on the board */
+ #define BUTTONS_BUTTON1 (1UL << 2)
+
+ /** Mask of the second button on the board */
+ #define BUTTONS_BUTTON2 (1UL << 3)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+ AVR32_GPIO.port[BUTTONS_PORT].gpers = (BUTTONS_BUTTON1 | BUTTONS_BUTTON2);
+ AVR32_GPIO.port[BUTTONS_PORT].puers = (BUTTONS_BUTTON1 | BUTTONS_BUTTON2);
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+ AVR32_GPIO.port[BUTTONS_PORT].gperc = (BUTTONS_BUTTON1 | BUTTONS_BUTTON2);
+ AVR32_GPIO.port[BUTTONS_PORT].puerc = (BUTTONS_BUTTON1 | BUTTONS_BUTTON2);
+ }
+
+ static inline uint32_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint32_t Buttons_GetStatus(void)
+ {
+ return (~(AVR32_GPIO.port[BUTTONS_PORT].pvr & (BUTTONS_BUTTON1 | BUTTONS_BUTTON2)));
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1101/Joystick.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1101/Joystick.h
new file mode 100644
index 000000000..f7a9a7538
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1101/Joystick.h
@@ -0,0 +1,131 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific joystick driver header for the Atmel EVK1101.
+ * \copydetails Group_Joystick_EVK1101
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the joystick driver
+ * dispatch header located in LUFA/Drivers/Board/Joystick.h.
+ */
+
+/** \ingroup Group_Joystick
+ * \defgroup Group_Joystick_EVK1101 EVK1101
+ * \brief Board specific joystick driver header for the Atmel EVK1101.
+ *
+ * Board specific joystick driver header for the Atmel EVK1101.
+ *
+ * <table>
+ * <tr><th>Left Port Pin</th><th>Up Port Pin</th><th>Right Port Pin</th><th>Down Port Pin</th><th>Press Port Pin</th></tr>
+ * <tr><td>GPIO38</td><td>GPIO39</td><td>GPIO41</td><td>GPIO40</td><td>GPIO13</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __JOYSTICK_EVK1101_H__
+#define __JOYSTICK_EVK1101_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_JOYSTICK_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Joystick.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define JOY_MOVE_PORT 1
+ #define JOY_MOVE_MASK ((1UL << 6) | (1UL << 7) | (1UL << 8) | (1UL << 9))
+ #define JOY_PRESS_PORT 0
+ #define JOY_PRESS_MASK (1UL << 13)
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Mask for the joystick being pushed in the left direction. */
+ #define JOY_LEFT (1UL << 6)
+
+ /** Mask for the joystick being pushed in the upward direction. */
+ #define JOY_UP (1UL << 7)
+
+ /** Mask for the joystick being pushed in the right direction. */
+ #define JOY_RIGHT (1UL << 9)
+
+ /** Mask for the joystick being pushed in the downward direction. */
+ #define JOY_DOWN (1UL << 8)
+
+ /** Mask for the joystick being pushed inward. */
+ #define JOY_PRESS (1UL << 13)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Joystick_Init(void)
+ {
+ AVR32_GPIO.port[JOY_MOVE_PORT].gpers = JOY_MOVE_MASK;
+ AVR32_GPIO.port[JOY_PRESS_PORT].gpers = JOY_PRESS_MASK;
+
+ AVR32_GPIO.port[JOY_MOVE_PORT].puers = JOY_MOVE_MASK;
+ AVR32_GPIO.port[JOY_PRESS_PORT].puers = JOY_PRESS_MASK;
+ };
+
+ static inline void Joystick_Disable(void)
+ {
+ AVR32_GPIO.port[JOY_MOVE_PORT].gperc = JOY_MOVE_MASK;
+ AVR32_GPIO.port[JOY_PRESS_PORT].gperc = JOY_PRESS_MASK;
+
+ AVR32_GPIO.port[JOY_MOVE_PORT].puerc = JOY_MOVE_MASK;
+ AVR32_GPIO.port[JOY_PRESS_PORT].puerc = JOY_PRESS_MASK;
+ };
+
+ static inline uint32_t Joystick_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint32_t Joystick_GetStatus(void)
+ {
+ return (uint32_t)(~((AVR32_GPIO.port[JOY_MOVE_PORT].pvr & JOY_MOVE_MASK) |
+ (AVR32_GPIO.port[JOY_PRESS_PORT].pvr & JOY_PRESS_MASK)));
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1101/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1101/LEDs.h
new file mode 100644
index 000000000..dad7771a2
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1101/LEDs.h
@@ -0,0 +1,156 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Atmel EVK1101.
+ * \copydetails Group_LEDs_EVK1101
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_EVK1101 EVK1101
+ * \brief Board specific LED driver header for the Atmel EVK1101.
+ *
+ * Board specific LED driver header for the Atmel EVK1101.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Green</td><td>LED0 LED</td><td>Low</td><td>GPIO7</td></tr>
+ * <tr><td>LEDS_LED2</td><td>Green</td><td>LED1 LED</td><td>Low</td><td>GPIO8</td></tr>
+ * <tr><td>LEDS_LED3</td><td>Green</td><td>LED2 LED</td><td>Low</td><td>GPIO21</td></tr>
+ * <tr><td>LEDS_LED4</td><td>Green</td><td>LED3 LED</td><td>Low</td><td>GPIO22</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_EVK1101_H__
+#define __LEDS_EVK1101_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define LEDS_PORT 0
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1UL << 7)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1UL << 8)
+
+ /** LED mask for the third LED on the board. */
+ #define LEDS_LED3 (1UL << 21)
+
+ /** LED mask for the fourth LED on the board. */
+ #define LEDS_LED4 (1UL << 22)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3 | LEDS_LED4)
+
+ /** LED mask for the none of the board LEDs */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ AVR32_GPIO.port[LEDS_PORT].gpers = LEDS_ALL_LEDS;
+ AVR32_GPIO.port[LEDS_PORT].oders = LEDS_ALL_LEDS;
+ AVR32_GPIO.port[LEDS_PORT].ovrs = LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ AVR32_GPIO.port[LEDS_PORT].gperc = LEDS_ALL_LEDS;
+ AVR32_GPIO.port[LEDS_PORT].oderc = LEDS_ALL_LEDS;
+ AVR32_GPIO.port[LEDS_PORT].ovrc = LEDS_ALL_LEDS;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint32_t LEDMask)
+ {
+ AVR32_GPIO.port[LEDS_PORT].ovrc = LEDMask;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint32_t LEDMask)
+ {
+ AVR32_GPIO.port[LEDS_PORT].ovrs = LEDMask;
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint32_t LEDMask)
+ {
+ AVR32_GPIO.port[LEDS_PORT].ovrs = LEDS_ALL_LEDS;
+ AVR32_GPIO.port[LEDS_PORT].ovrc = LEDMask;
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint32_t LEDMask, const uint32_t ActiveMask)
+ {
+ AVR32_GPIO.port[LEDS_PORT].ovrs = LEDMask;
+ AVR32_GPIO.port[LEDS_PORT].ovrc = ActiveMask;
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint32_t LEDMask)
+ {
+ AVR32_GPIO.port[LEDS_PORT].ovrt = LEDMask;
+ }
+
+ static inline uint32_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint32_t LEDs_GetLEDs(void)
+ {
+ return (~AVR32_GPIO.port[LEDS_PORT].ovr & LEDS_ALL_LEDS);
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1104/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1104/Board.h
new file mode 100644
index 000000000..aa7adbfb0
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1104/Board.h
@@ -0,0 +1,82 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Atmel EVK1104.
+ * \copydetails Group_BoardInfo_EVK1104
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_EVK1104 EVK1104
+ * \brief Board specific information header for the Atmel Atmel EVK1104.
+ *
+ * Board specific information header for the Atmel Atmel EVK1104.
+ *
+ * @{
+ */
+
+#ifndef __BOARD_EVK1104_H__
+#define __BOARD_EVK1104_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../Buttons.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware Buttons mounted. */
+ #define BOARD_HAS_BUTTONS
+
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1104/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1104/Buttons.h
new file mode 100644
index 000000000..dfcfb665e
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1104/Buttons.h
@@ -0,0 +1,109 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Buttons driver header for the Atmel EVK1104.
+ * \copydetails Group_Buttons_EVK1104
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Buttons driver
+ * dispatch header located in LUFA/Drivers/Board/Buttons.h.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_EVK1104 EVK1104
+ * \brief Board specific Buttons driver header for the Atmel EVK1104.
+ *
+ * Board specific Buttons driver header for the Atmel EVK1104.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>BUTTONS_BUTTON1</td><td>SW0 Button</td><td>Low</td><td>GPIO42</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __BUTTONS_EVK1104_H__
+#define __BUTTONS_EVK1104_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define BUTTONS_PORT 1
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Mask of the first button on the board */
+ #define BUTTONS_BUTTON1 (1UL << 10)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+ AVR32_GPIO.port[BUTTONS_PORT].gpers = (BUTTONS_BUTTON1 | BUTTONS_BUTTON2);
+ AVR32_GPIO.port[BUTTONS_PORT].puers = (BUTTONS_BUTTON1 | BUTTONS_BUTTON2);
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+ AVR32_GPIO.port[BUTTONS_PORT].gperc = (BUTTONS_BUTTON1 | BUTTONS_BUTTON2);
+ AVR32_GPIO.port[BUTTONS_PORT].puerc = (BUTTONS_BUTTON1 | BUTTONS_BUTTON2);
+ }
+
+ static inline uint32_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint32_t Buttons_GetStatus(void)
+ {
+ return (~(AVR32_GPIO.port[JOY_MOVE_PORT].pvr & (BUTTONS_BUTTON1 | BUTTONS_BUTTON2)));
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1104/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1104/LEDs.h
new file mode 100644
index 000000000..2258a267f
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/EVK1104/LEDs.h
@@ -0,0 +1,174 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Atmel EVK1104.
+ * \copydetails Group_LEDs_EVK1104
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_EVK1104 EVK1104
+ * \brief Board specific LED driver header for the Atmel EVK1104.
+ *
+ * Board specific LED driver header for the Atmel EVK1104.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Green</td><td>LED0 LED</td><td>Low</td><td>GPIO67</td></tr>
+ * <tr><td>LEDS_LED2</td><td>Green</td><td>LED1 LED</td><td>Low</td><td>GPIO101</td></tr>
+ * <tr><td>LEDS_LED3</td><td>Green</td><td>LED2 LED</td><td>Low</td><td>GPIO102</td></tr>
+ * <tr><td>LEDS_LED4</td><td>Green</td><td>LED3 LED</td><td>Low</td><td>GPIO105</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_EVK1104_H__
+#define __LEDS_EVK1104_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define LEDS_LEDMASK2 (1UL << 3)
+ #define LEDS_LEDMASK3 ((1UL << 9) | (1UL << 6) | (1UL << 5))
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1UL << 3)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1UL << 5)
+
+ /** LED mask for the third LED on the board. */
+ #define LEDS_LED3 (1UL << 9)
+
+ /** LED mask for the fourth LED on the board. */
+ #define LEDS_LED4 (1UL << 6)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3 | LEDS_LED4)
+
+ /** LED mask for the none of the board LEDs */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ AVR32_GPIO.port[2].gpers = LEDS_LEDMASK2;
+ AVR32_GPIO.port[2].oders = LEDS_LEDMASK2;
+ AVR32_GPIO.port[2].ovrs = LEDS_LEDMASK2;
+
+ AVR32_GPIO.port[3].gpers = LEDS_LEDMASK3;
+ AVR32_GPIO.port[3].oders = LEDS_LEDMASK3;
+ AVR32_GPIO.port[3].ovrs = LEDS_LEDMASK3;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ AVR32_GPIO.port[2].gperc = LEDS_LEDMASK2;
+ AVR32_GPIO.port[2].oderc = LEDS_LEDMASK2;
+ AVR32_GPIO.port[2].ovrc = LEDS_LEDMASK2;
+
+ AVR32_GPIO.port[3].gperc = LEDS_LEDMASK3;
+ AVR32_GPIO.port[3].oderc = LEDS_LEDMASK3;
+ AVR32_GPIO.port[3].ovrc = LEDS_LEDMASK3;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint32_t LEDMask)
+ {
+ AVR32_GPIO.port[2].ovrc = (LEDMask & LEDS_LEDMASK2);
+ AVR32_GPIO.port[3].ovrc = (LEDMask & LEDS_LEDMASK3);
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint32_t LEDMask)
+ {
+ AVR32_GPIO.port[2].ovrs = (LEDMask & LEDS_LEDMASK2);
+ AVR32_GPIO.port[3].ovrs = (LEDMask & LEDS_LEDMASK3);
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint32_t LEDMask)
+ {
+ AVR32_GPIO.port[2].ovrs = LEDS_LEDMASK2;
+ AVR32_GPIO.port[2].ovrc = (LEDMask & LEDS_LEDMASK2);
+
+ AVR32_GPIO.port[3].ovrs = LEDS_LEDMASK3;
+ AVR32_GPIO.port[3].ovrc = (LEDMask & LEDS_LEDMASK3);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint32_t LEDMask, const uint32_t ActiveMask)
+ {
+ AVR32_GPIO.port[2].ovrs = (LEDMask & LEDS_LEDMASK2);
+ AVR32_GPIO.port[2].ovrc = (ActiveMask & LEDS_LEDMASK2);
+
+ AVR32_GPIO.port[3].ovrs = (LEDMask & LEDS_LEDMASK3);
+ AVR32_GPIO.port[3].ovrc = (ActiveMask & LEDS_LEDMASK3);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint32_t LEDMask)
+ {
+ AVR32_GPIO.port[2].ovrt = (LEDMask & LEDS_LEDMASK2);
+ AVR32_GPIO.port[3].ovrt = (LEDMask & LEDS_LEDMASK3);
+ }
+
+ static inline uint32_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint32_t LEDs_GetLEDs(void)
+ {
+ return ((~AVR32_GPIO.port[2].ovr & LEDS_LEDMASK2) | (~AVR32_GPIO.port[3].ovr & LEDS_LEDMASK3));
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/UC3A3_XPLAINED/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/UC3A3_XPLAINED/Board.h
new file mode 100644
index 000000000..ec4d9c7c9
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/UC3A3_XPLAINED/Board.h
@@ -0,0 +1,82 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Atmel UC3-A3 Xplained.
+ * \copydetails Group_BoardInfo_UC3_A3_XPLAINED
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_UC3_A3_XPLAINED UC3_A3_XPLAINED
+ * \brief Board specific information header for the Atmel UC3-A3 Xplained.
+ *
+ * Board specific information header for the Atmel UC3-A3 Xplained.
+ *
+ * @{
+ */
+
+#ifndef __BOARD_UC3_A3_XPLAINED_H__
+#define __BOARD_UC3_A3_XPLAINED_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../Buttons.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware Buttons mounted. */
+ #define BOARD_HAS_BUTTONS
+
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/UC3A3_XPLAINED/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/UC3A3_XPLAINED/Buttons.h
new file mode 100644
index 000000000..8accb6fe1
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/UC3A3_XPLAINED/Buttons.h
@@ -0,0 +1,109 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Buttons driver header for the Atmel UC3-A3 Xplained.
+ * \copydetails Group_Buttons_UC3A3_XPLAINED
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Buttons driver
+ * dispatch header located in LUFA/Drivers/Board/Buttons.h.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_UC3A3_XPLAINED UC3A3_XPLAINED
+ * \brief Board specific Buttons driver header for the Atmel UC3-A3 Xplained.
+ *
+ * Board specific Buttons driver header for the Atmel UC3-A3 Xplained.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>BUTTONS_BUTTON1</td><td>SW0 Button</td><td>Low</td><td>GPIO32</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __BUTTONS_UC3A3_XPLAINED_H__
+#define __BUTTONS_UC3A3_XPLAINED_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define BUTTONS_PORT 1
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Mask of the first button on the board */
+ #define BUTTONS_BUTTON1 (1UL << 0)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+ AVR32_GPIO.port[BUTTONS_PORT].gpers = (BUTTONS_BUTTON1 | BUTTONS_BUTTON2);
+ AVR32_GPIO.port[BUTTONS_PORT].puers = (BUTTONS_BUTTON1 | BUTTONS_BUTTON2);
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+ AVR32_GPIO.port[BUTTONS_PORT].gperc = (BUTTONS_BUTTON1 | BUTTONS_BUTTON2);
+ AVR32_GPIO.port[BUTTONS_PORT].puerc = (BUTTONS_BUTTON1 | BUTTONS_BUTTON2);
+ }
+
+ static inline uint32_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint32_t Buttons_GetStatus(void)
+ {
+ return (~(AVR32_GPIO.port[JOY_MOVE_PORT].pvr & (BUTTONS_BUTTON1 | BUTTONS_BUTTON2)));
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/UC3A3_XPLAINED/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/UC3A3_XPLAINED/LEDs.h
new file mode 100644
index 000000000..66b7834c7
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/UC3/UC3A3_XPLAINED/LEDs.h
@@ -0,0 +1,182 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Atmel UC3-A3 Xplained.
+ * \copydetails Group_LEDs_UC3A3_XPLAINED
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_UC3A3_XPLAINED UC3A3_XPLAINED
+ * \brief Board specific LED driver header for the Atmel UC3-A3 Xplained.
+ *
+ * Board specific LED driver header for the Atmel UC3-A3 Xplained.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Yellow</td><td>LED0 LED</td><td>Low</td><td>GPIO35</td></tr>
+ * <tr><td>LEDS_LED2</td><td>Yellow</td><td>LED1 LED</td><td>Low</td><td>GPIO73</td></tr>
+ * <tr><td>LEDS_LED3</td><td>Yellow</td><td>LED2 LED</td><td>Low</td><td>GPIO34</td></tr>
+ * <tr><td>LEDS_LED4</td><td>Yellow</td><td>LED3 LED</td><td>Low</td><td>GPIO38</td></tr>
+ * <tr><td>LEDS_LED5</td><td>Green</td><td>Status</td><td>Low</td><td>GPIO50</td></tr>
+ * <tr><td>LEDS_LED6</td><td>Red</td><td>Power</td><td>High</td><td>GPIO49</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_UC3A3_XPLAINED_H__
+#define __LEDS_UC3A3_XPLAINED_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define LEDS_LEDMASK1 ((1UL << 3) | (1UL << 2) | (1UL << 6) | (1UL << 18) | (1UL << 17))
+ #define LEDS_LEDMASK3 (1UL << 9)
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1UL << 3)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1UL << 9)
+
+ /** LED mask for the third LED on the board. */
+ #define LEDS_LED3 (1UL << 2)
+
+ /** LED mask for the fourth LED on the board. */
+ #define LEDS_LED4 (1UL << 6)
+
+ /** LED mask for the fifth LED on the board. */
+ #define LEDS_LED5 (1UL << 18)
+
+ /** LED mask for the sixth LED on the board. */
+ #define LEDS_LED6 (1UL << 17)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3 | LEDS_LED4 | LEDS_LED5 | LEDS_LED6)
+
+ /** LED mask for the none of the board LEDs */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ AVR32_GPIO.port[1].gpers = LEDS_LEDMASK1;
+ AVR32_GPIO.port[1].oders = LEDS_LEDMASK1;
+ AVR32_GPIO.port[1].ovrs = LEDS_LEDMASK1;
+
+ AVR32_GPIO.port[3].gpers = LEDS_LEDMASK3;
+ AVR32_GPIO.port[3].oders = LEDS_LEDMASK3;
+ AVR32_GPIO.port[3].ovrs = LEDS_LEDMASK3;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ AVR32_GPIO.port[1].gperc = LEDS_LEDMASK1;
+ AVR32_GPIO.port[1].oderc = LEDS_LEDMASK1;
+ AVR32_GPIO.port[1].ovrc = LEDS_LEDMASK1;
+
+ AVR32_GPIO.port[3].gperc = LEDS_LEDMASK3;
+ AVR32_GPIO.port[3].oderc = LEDS_LEDMASK3;
+ AVR32_GPIO.port[3].ovrc = LEDS_LEDMASK3;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint32_t LEDMask)
+ {
+ AVR32_GPIO.port[1].ovrc = (LEDMask & LEDS_LEDMASK1);
+ AVR32_GPIO.port[3].ovrc = (LEDMask & LEDS_LEDMASK3);
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint32_t LEDMask)
+ {
+ AVR32_GPIO.port[1].ovrs = (LEDMask & LEDS_LEDMASK1);
+ AVR32_GPIO.port[3].ovrs = (LEDMask & LEDS_LEDMASK3);
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint32_t LEDMask)
+ {
+ AVR32_GPIO.port[1].ovrs = LEDS_LEDMASK1;
+ AVR32_GPIO.port[1].ovrc = (LEDMask & LEDS_LEDMASK1);
+
+ AVR32_GPIO.port[3].ovrs = LEDS_LEDMASK3;
+ AVR32_GPIO.port[3].ovrc = (LEDMask & LEDS_LEDMASK3);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint32_t LEDMask, const uint32_t ActiveMask)
+ {
+ AVR32_GPIO.port[1].ovrs = (LEDMask & LEDS_LEDMASK1);
+ AVR32_GPIO.port[1].ovrc = (ActiveMask & LEDS_LEDMASK1);
+
+ AVR32_GPIO.port[3].ovrs = (LEDMask & LEDS_LEDMASK3);
+ AVR32_GPIO.port[3].ovrc = (ActiveMask & LEDS_LEDMASK3);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint32_t LEDMask)
+ {
+ AVR32_GPIO.port[1].ovrt = (LEDMask & LEDS_LEDMASK1);
+ AVR32_GPIO.port[3].ovrt = (LEDMask & LEDS_LEDMASK3);
+ }
+
+ static inline uint32_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint32_t LEDs_GetLEDs(void)
+ {
+ return ((~AVR32_GPIO.port[1].ovr & LEDS_LEDMASK1) | (~AVR32_GPIO.port[3].ovr & LEDS_LEDMASK3));
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Board.h
new file mode 100644
index 000000000..824c3db49
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Board.h
@@ -0,0 +1,86 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Atmel XMEGA A3BU Xplained.
+ * \copydetails Group_BoardInfo_A3BU_XPLAINED
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_A3BU_XPLAINED A3BU_XPLAINED
+ * \brief Board specific information header for the Atmel XMEGA A3BU Xplained.
+ *
+ * Board specific information header for the Atmel XMEGA A3BU Xplained.
+ *
+ * @{
+ */
+
+#ifndef __BOARD_A3BU_XPLAINED_H__
+#define __BOARD_A3BU_XPLAINED_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../Buttons.h"
+ #include "../../Dataflash.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware Buttons mounted. */
+ #define BOARD_HAS_BUTTONS
+
+ /** Indicates the board has a hardware Dataflash mounted. */
+ #define BOARD_HAS_DATAFLASH
+
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Buttons.h
new file mode 100644
index 000000000..d5119eb5c
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Buttons.h
@@ -0,0 +1,119 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Buttons driver header for the Atmel XMEGA A3BU Xplained.
+ * \copydetails Group_Buttons_A3BU_XPLAINED
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Buttons driver
+ * dispatch header located in LUFA/Drivers/Board/Buttons.h.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_A3BU_XPLAINED A3BU_XPLAINED
+ * \brief Board specific Buttons driver header for the Atmel XMEGA A3BU Xplained.
+ *
+ * Board specific Buttons driver header for the Atmel XMEGA A3BU Xplained.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>BUTTONS_BUTTON1</td><td>SW0 Button</td><td>Low</td><td>PORTE.5</td></tr>
+ * <tr><td>BUTTONS_BUTTON2</td><td>SW1 Button</td><td>Low</td><td>PORTF.1</td></tr>
+ * <tr><td>BUTTONS_BUTTON3</td><td>SW2 Button</td><td>Low</td><td>PORTF.2</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __BUTTONS_A3BU_XPLAINED_H__
+#define __BUTTONS_A3BU_XPLAINED_H__
+
+ /* Includes: */
+ #include <avr/io.h>
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Button mask for the first button on the board. */
+ #define BUTTONS_BUTTON1 (1 << 5)
+
+ /** Button mask for the second button on the board. */
+ #define BUTTONS_BUTTON2 (1 << 1)
+
+ /** Button mask for the third button on the board. */
+ #define BUTTONS_BUTTON3 (1 << 2)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+ PORTE.OUTCLR = BUTTONS_BUTTON1;
+ PORTE.PIN5CTRL = (PORT_OPC_PULLUP_gc | PORT_INVEN_bm);
+
+ PORTF.OUTCLR = (BUTTONS_BUTTON2 | BUTTONS_BUTTON3);
+ PORTF.PIN1CTRL = (PORT_OPC_PULLUP_gc | PORT_INVEN_bm);
+ PORTF.PIN2CTRL = (PORT_OPC_PULLUP_gc | PORT_INVEN_bm);
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+ PORTE.OUTCLR = BUTTONS_BUTTON1;
+ PORTE.PIN5CTRL = 0;
+
+ PORTF.OUTCLR = (BUTTONS_BUTTON2 | BUTTONS_BUTTON3);
+ PORTF.PIN1CTRL = 0;
+ PORTF.PIN2CTRL = 0;
+ }
+
+ static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Buttons_GetStatus(void)
+ {
+ return ((PORTE_IN & BUTTONS_BUTTON1) | (PORTF_IN & (BUTTONS_BUTTON2 | BUTTONS_BUTTON3)));
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Dataflash.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Dataflash.h
new file mode 100644
index 000000000..2d0983941
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Dataflash.h
@@ -0,0 +1,228 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Dataflash driver header for the Atmel XMEGA A3BU Xplained.
+ * \copydetails Group_Dataflash_A3BU_XPLAINED
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the dataflash driver
+ * dispatch header located in LUFA/Drivers/Board/Dataflash.h.
+ */
+
+/** \ingroup Group_Dataflash
+ * \defgroup Group_Dataflash_A3BU_XPLAINED A3BU_XPLAINED
+ * \brief Board specific Dataflash driver header for the Atmel XMEGA A3BU Xplained.
+ *
+ * Board specific Dataflash driver header for the Atmel XMEGA A3BU Xplained board.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Select Pin</th><th>SPI Port</th></tr>
+ * <tr><td>DATAFLASH_CHIP1</td><td>AT45DB642D (8MB)</td><td>PORTF.4</td><td>USARTD0 (In SPI Mode)</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __DATAFLASH_A3BU_XPLAINED_H__
+#define __DATAFLASH_A3BU_XPLAINED_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../../Misc/AT45DB642D.h"
+ #include "../../../Peripheral/SerialSPI.h"
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_DATAFLASH_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Dataflash.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define DATAFLASH_CHIPCS_MASK DATAFLASH_CHIP1
+ #define DATAFLASH_CHIPCS_PORT PORTF
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Constant indicating the total number of dataflash ICs mounted on the selected board. */
+ #define DATAFLASH_TOTALCHIPS 1
+
+ /** Mask for no dataflash chip selected. */
+ #define DATAFLASH_NO_CHIP 0
+
+ /** Mask for the first dataflash chip selected. */
+ #define DATAFLASH_CHIP1 (1 << 4)
+
+ /** Internal main memory page size for the board's dataflash ICs. */
+ #define DATAFLASH_PAGE_SIZE 1024
+
+ /** Total number of pages inside each of the board's dataflash ICs. */
+ #define DATAFLASH_PAGES 8192
+
+ /* Inline Functions: */
+ /** Initializes the dataflash driver so that commands and data may be sent to an attached dataflash IC.
+ * The appropriate SPI interface will be automatically configured.
+ */
+ static inline void Dataflash_Init(void)
+ {
+ DATAFLASH_CHIPCS_PORT.DIRSET = DATAFLASH_CHIPCS_MASK;
+
+ PORTCFG.MPCMASK = DATAFLASH_CHIPCS_MASK;
+ DATAFLASH_CHIPCS_PORT.PIN0CTRL = PORT_INVEN_bm;
+
+ SerialSPI_Init(&USARTD0, (USART_SPI_SCK_LEAD_RISING | USART_SPI_SAMPLE_LEADING | USART_SPI_ORDER_MSB_FIRST), (F_CPU / 2));
+
+ PORTD.DIRSET = PIN3_bm | PIN1_bm;
+ PORTD.DIRCLR = PIN2_bm;
+ PORTC.PIN2CTRL = PORT_OPC_PULLUP_gc;
+ }
+
+ /** Sends a byte to the currently selected dataflash IC, and returns a byte from the dataflash.
+ *
+ * \param[in] Byte Byte of data to send to the dataflash
+ *
+ * \return Last response byte from the dataflash
+ */
+ static inline uint8_t Dataflash_TransferByte(const uint8_t Byte) ATTR_ALWAYS_INLINE;
+ static inline uint8_t Dataflash_TransferByte(const uint8_t Byte)
+ {
+ return SerialSPI_TransferByte(&USARTD0, Byte);
+ }
+
+ /** Sends a byte to the currently selected dataflash IC, and ignores the next byte from the dataflash.
+ *
+ * \param[in] Byte Byte of data to send to the dataflash
+ */
+ static inline void Dataflash_SendByte(const uint8_t Byte) ATTR_ALWAYS_INLINE;
+ static inline void Dataflash_SendByte(const uint8_t Byte)
+ {
+ SerialSPI_SendByte(&USARTD0, Byte);
+ }
+
+ /** Sends a dummy byte to the currently selected dataflash IC, and returns the next byte from the dataflash.
+ *
+ * \return Last response byte from the dataflash
+ */
+ static inline uint8_t Dataflash_ReceiveByte(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Dataflash_ReceiveByte(void)
+ {
+ return SerialSPI_ReceiveByte(&USARTD0);
+ }
+
+ /** Determines the currently selected dataflash chip.
+ *
+ * \return Mask of the currently selected Dataflash chip, either \ref DATAFLASH_NO_CHIP if no chip is selected
+ * or a DATAFLASH_CHIPn mask (where n is the chip number).
+ */
+ static inline uint8_t Dataflash_GetSelectedChip(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Dataflash_GetSelectedChip(void)
+ {
+ return (DATAFLASH_CHIPCS_PORT.OUT & DATAFLASH_CHIPCS_MASK);
+ }
+
+ /** Selects the given dataflash chip.
+ *
+ * \param[in] ChipMask Mask of the Dataflash IC to select, in the form of a \c DATAFLASH_CHIPn mask (where n is
+ * the chip number).
+ */
+ static inline void Dataflash_SelectChip(const uint8_t ChipMask) ATTR_ALWAYS_INLINE;
+ static inline void Dataflash_SelectChip(const uint8_t ChipMask)
+ {
+ DATAFLASH_CHIPCS_PORT.OUTCLR = DATAFLASH_CHIPCS_MASK;
+ DATAFLASH_CHIPCS_PORT.OUTSET = ChipMask;
+ }
+
+ /** Deselects the current dataflash chip, so that no dataflash is selected. */
+ static inline void Dataflash_DeselectChip(void) ATTR_ALWAYS_INLINE;
+ static inline void Dataflash_DeselectChip(void)
+ {
+ Dataflash_SelectChip(DATAFLASH_NO_CHIP);
+ }
+
+ /** Selects a dataflash IC from the given page number, which should range from 0 to
+ * ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1). For boards containing only one
+ * dataflash IC, this will select DATAFLASH_CHIP1. If the given page number is outside
+ * the total number of pages contained in the boards dataflash ICs, all dataflash ICs
+ * are deselected.
+ *
+ * \param[in] PageAddress Address of the page to manipulate, ranging from
+ * 0 to ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1).
+ */
+ static inline void Dataflash_SelectChipFromPage(const uint16_t PageAddress)
+ {
+ Dataflash_DeselectChip();
+
+ if (PageAddress >= (DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS))
+ return;
+
+ Dataflash_SelectChip(DATAFLASH_CHIP1);
+ }
+
+ /** Toggles the select line of the currently selected dataflash IC, so that it is ready to receive
+ * a new command.
+ */
+ static inline void Dataflash_ToggleSelectedChipCS(void)
+ {
+ uint8_t SelectedChipMask = Dataflash_GetSelectedChip();
+
+ Dataflash_DeselectChip();
+ Dataflash_SelectChip(SelectedChipMask);
+ }
+
+ /** Spin-loops while the currently selected dataflash is busy executing a command, such as a main
+ * memory page program or main memory to buffer transfer.
+ */
+ static inline void Dataflash_WaitWhileBusy(void)
+ {
+ Dataflash_ToggleSelectedChipCS();
+ Dataflash_SendByte(DF_CMD_GETSTATUS);
+ while (!(Dataflash_ReceiveByte() & DF_STATUS_READY));
+ Dataflash_ToggleSelectedChipCS();
+ }
+
+ /** Sends a set of page and buffer address bytes to the currently selected dataflash IC, for use with
+ * dataflash commands which require a complete 24-bit address.
+ *
+ * \param[in] PageAddress Page address within the selected dataflash IC
+ * \param[in] BufferByte Address within the dataflash's buffer
+ */
+ static inline void Dataflash_SendAddressBytes(uint16_t PageAddress,
+ const uint16_t BufferByte)
+ {
+ Dataflash_SendByte(PageAddress >> 5);
+ Dataflash_SendByte((PageAddress << 3) | (BufferByte >> 8));
+ Dataflash_SendByte(BufferByte);
+ }
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/LEDs.h
new file mode 100644
index 000000000..16abfbc97
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/LEDs.h
@@ -0,0 +1,181 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Atmel XMEGA A3BU Xplained.
+ * \copydetails Group_LEDs_A3BU_XPLAINED
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_A3BU_XPLAINED A3BU_XPLAINED
+ * \brief Board specific LED driver header for the Atmel XMEGA A3BU Xplained.
+ *
+ * Board specific LED driver header for the Atmel XMEGA A3BU Xplained.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Yellow</td><td>LED0 LED</td><td>Low</td><td>PORTR.0</td></tr>
+ * <tr><td>LEDS_LED2</td><td>Yellow</td><td>LED1 LED</td><td>Low</td><td>PORTR.1</td></tr>
+ * <tr><td>LEDS_LED3</td><td>Red</td><td>Status Bicolour Red LED</td><td>Low</td><td>PORTD.4</td></tr>
+ * <tr><td>LEDS_LED4</td><td>Green</td><td>Status Bicolour Green LED</td><td>High</td><td>PORTD.5</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_A3BU_XPLAINED_H__
+#define __LEDS_A3BU_XPLAINED_H__
+
+ /* Includes: */
+ #include <avr/io.h>
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define LEDS_PORTR_LEDS (LEDS_LED1 | LEDS_LED2)
+ #define LEDS_PORTD_LEDS (LEDS_LED3 | LEDS_LED4)
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 0)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1 << 1)
+
+ /** LED mask for the third LED on the board. */
+ #define LEDS_LED3 (1 << 4)
+
+ /** LED mask for the fourth LED on the board. */
+ #define LEDS_LED4 (1 << 5)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3 | LEDS_LED4)
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ PORTR.DIRSET = LEDS_PORTR_LEDS;
+ PORTR.OUTCLR = LEDS_PORTR_LEDS;
+
+ PORTCFG.MPCMASK = LEDS_PORTR_LEDS;
+ PORTR.PIN0CTRL = PORT_INVEN_bm;
+
+ PORTD.DIRSET = LEDS_PORTD_LEDS;
+ PORTD.OUTCLR = LEDS_PORTD_LEDS;
+
+ PORTD.PIN4CTRL = PORT_INVEN_bm;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ PORTR.DIRCLR = LEDS_PORTR_LEDS;
+ PORTR.OUTCLR = LEDS_PORTR_LEDS;
+
+ PORTCFG.MPCMASK = 0;
+ PORTR.PIN0CTRL = LEDS_PORTR_LEDS;
+
+ PORTD.DIRCLR = LEDS_PORTD_LEDS;
+ PORTD.OUTCLR = LEDS_PORTD_LEDS;
+
+ PORTD.PIN4CTRL = 0;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTR_OUTSET = LEDMask & LEDS_PORTR_LEDS;
+ PORTD_OUTSET = LEDMask & LEDS_PORTD_LEDS;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTR_OUTCLR = LEDMask & LEDS_PORTR_LEDS;
+ PORTD_OUTCLR = LEDMask & LEDS_PORTD_LEDS;
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTR_OUTCLR = LEDS_PORTR_LEDS;
+ PORTD_OUTCLR = LEDS_PORTD_LEDS;
+
+ PORTR_OUTSET = (LEDMask & LEDS_PORTR_LEDS);
+ PORTD_OUTSET = (LEDMask & LEDS_PORTD_LEDS);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTR_OUTCLR = (LEDMask & LEDS_PORTR_LEDS);
+ PORTD_OUTCLR = (LEDMask & LEDS_PORTD_LEDS);
+
+ PORTR_OUTSET = (ActiveMask & LEDS_PORTR_LEDS);
+ PORTD_OUTSET = (ActiveMask & LEDS_PORTD_LEDS);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PORTR_OUTTGL = (LEDMask & LEDS_PORTR_LEDS);
+ PORTD_OUTTGL = (LEDMask & LEDS_PORTD_LEDS);
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return ((PORTR_OUT & LEDS_PORTR_LEDS) | (PORTD_OUT & LEDS_PORTD_LEDS));
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Board.h
new file mode 100644
index 000000000..d807d18b3
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Board.h
@@ -0,0 +1,86 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Atmel XMEGA B1 Xplained.
+ * \copydetails Group_BoardInfo_B1_XPLAINED
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_B1_XPLAINED B1_XPLAINED
+ * \brief Board specific information header for the Atmel XMEGA B1 Xplained.
+ *
+ * Board specific information header for the Atmel XMEGA B1 Xplained.
+ *
+ * @{
+ */
+
+#ifndef __BOARD_B1_XPLAINED_H__
+#define __BOARD_B1_XPLAINED_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../Buttons.h"
+ #include "../../Dataflash.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware Buttons mounted. */
+ #define BOARD_HAS_BUTTONS
+
+ /** Indicates the board has a hardware Dataflash mounted. */
+ #define BOARD_HAS_DATAFLASH
+
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Buttons.h
new file mode 100644
index 000000000..9c458b496
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Buttons.h
@@ -0,0 +1,119 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Buttons driver header for the Atmel XMEGA B1 Xplained.
+ * \copydetails Group_Buttons_B1_XPLAINED
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Buttons driver
+ * dispatch header located in LUFA/Drivers/Board/Buttons.h.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_B1_XPLAINED B1_XPLAINED
+ * \brief Board specific Buttons driver header for the Atmel XMEGA B1 Xplained.
+ *
+ * Board specific Buttons driver header for the Atmel XMEGA B1 Xplained.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>BUTTONS_BUTTON1</td><td>Touch CS0 Button</td><td>Low</td><td>PORTE.0</td></tr>
+ * <tr><td>BUTTONS_BUTTON2</td><td>Touch CS1 Button</td><td>Low</td><td>PORTE.1</td></tr>
+ * <tr><td>BUTTONS_BUTTON3</td><td>Touch CS2 Button</td><td>Low</td><td>PORTE.2</td></tr>
+ * <tr><td>BUTTONS_BUTTON4</td><td>Touch CS3 Button</td><td>Low</td><td>PORTE.3</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __BUTTONS_B1_XPLAINED_H__
+#define __BUTTONS_B1_XPLAINED_H__
+
+ /* Includes: */
+ #include <avr/io.h>
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Button mask for the first button on the board. */
+ #define BUTTONS_BUTTON1 (1 << 0)
+
+ /** Button mask for the second button on the board. */
+ #define BUTTONS_BUTTON2 (1 << 1)
+
+ /** Button mask for the third button on the board. */
+ #define BUTTONS_BUTTON3 (1 << 2)
+
+ /** Button mask for the fourth button on the board. */
+ #define BUTTONS_BUTTON4 (1 << 3)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+ PORTE.OUTSET = (BUTTONS_BUTTON1 | BUTTONS_BUTTON2 | BUTTONS_BUTTON3 | BUTTONS_BUTTON4);
+
+ PORTCFG.MPCMASK = (BUTTONS_BUTTON1 | BUTTONS_BUTTON2 | BUTTONS_BUTTON3 | BUTTONS_BUTTON4);
+ PORTE.PIN0CTRL = (PORT_INVEN_bm | PORT_OPC_PULLUP_gc);
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+ PORTE.OUTCLR = (BUTTONS_BUTTON1 | BUTTONS_BUTTON2 | BUTTONS_BUTTON3 | BUTTONS_BUTTON4);
+
+ PORTCFG.MPCMASK = (BUTTONS_BUTTON1 | BUTTONS_BUTTON2 | BUTTONS_BUTTON3 | BUTTONS_BUTTON4);
+ PORTE.PIN0CTRL = 0;
+ }
+
+ static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Buttons_GetStatus(void)
+ {
+ return (PORTE_IN & (BUTTONS_BUTTON1 | BUTTONS_BUTTON2 | BUTTONS_BUTTON3 | BUTTONS_BUTTON4));
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Dataflash.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Dataflash.h
new file mode 100644
index 000000000..f02ca4af0
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Dataflash.h
@@ -0,0 +1,229 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Dataflash driver header for the Atmel XMEGA B1 Xplained.
+ * \copydetails Group_Dataflash_B1_XPLAINED
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the dataflash driver
+ * dispatch header located in LUFA/Drivers/Board/Dataflash.h.
+ */
+
+/** \ingroup Group_Dataflash
+ * \defgroup Group_Dataflash_B1_XPLAINED B1_XPLAINED
+ * \brief Board specific Dataflash driver header for the Atmel XMEGA B1 Xplained.
+ *
+ * Board specific Dataflash driver header for the Atmel XMEGA B1 Xplained board.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Select Pin</th><th>SPI Port</th></tr>
+ * <tr><td>DATAFLASH_CHIP1</td><td>AT45DB642D (8MB)</td><td>PORTD.2</td><td>USARTC0 (In SPI Mode, Remapped)</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __DATAFLASH_B1_XPLAINED_H__
+#define __DATAFLASH_B1_XPLAINED_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../../Misc/AT45DB642D.h"
+ #include "../../../Peripheral/SerialSPI.h"
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_DATAFLASH_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Dataflash.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define DATAFLASH_CHIPCS_MASK DATAFLASH_CHIP1
+ #define DATAFLASH_CHIPCS_PORT PORTD
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Constant indicating the total number of dataflash ICs mounted on the selected board. */
+ #define DATAFLASH_TOTALCHIPS 1
+
+ /** Mask for no dataflash chip selected. */
+ #define DATAFLASH_NO_CHIP 0
+
+ /** Mask for the first dataflash chip selected. */
+ #define DATAFLASH_CHIP1 (1 << 2)
+
+ /** Internal main memory page size for the board's dataflash ICs. */
+ #define DATAFLASH_PAGE_SIZE 1024
+
+ /** Total number of pages inside each of the board's dataflash ICs. */
+ #define DATAFLASH_PAGES 8192
+
+ /* Inline Functions: */
+ /** Initializes the dataflash driver so that commands and data may be sent to an attached dataflash IC.
+ * The appropriate SPI interface will be automatically configured.
+ */
+ static inline void Dataflash_Init(void)
+ {
+ DATAFLASH_CHIPCS_PORT.DIRSET = DATAFLASH_CHIPCS_MASK;
+
+ PORTCFG.MPCMASK = DATAFLASH_CHIPCS_MASK;
+ DATAFLASH_CHIPCS_PORT.PIN0CTRL = PORT_INVEN_bm;
+
+ SerialSPI_Init(&USARTC0, (USART_SPI_SCK_LEAD_RISING | USART_SPI_SAMPLE_LEADING | USART_SPI_ORDER_MSB_FIRST), (F_CPU / 2));
+
+ PORTC.REMAP |= PORT_USART0_bm;
+ PORTC.DIRSET = PIN7_bm | PIN5_bm;
+ PORTC.DIRCLR = PIN6_bm;
+ PORTC.PIN6CTRL = PORT_OPC_PULLUP_gc;
+ }
+
+ /** Sends a byte to the currently selected dataflash IC, and returns a byte from the dataflash.
+ *
+ * \param[in] Byte Byte of data to send to the dataflash
+ *
+ * \return Last response byte from the dataflash
+ */
+ static inline uint8_t Dataflash_TransferByte(const uint8_t Byte) ATTR_ALWAYS_INLINE;
+ static inline uint8_t Dataflash_TransferByte(const uint8_t Byte)
+ {
+ return SerialSPI_TransferByte(&USARTC0, Byte);
+ }
+
+ /** Sends a byte to the currently selected dataflash IC, and ignores the next byte from the dataflash.
+ *
+ * \param[in] Byte Byte of data to send to the dataflash
+ */
+ static inline void Dataflash_SendByte(const uint8_t Byte) ATTR_ALWAYS_INLINE;
+ static inline void Dataflash_SendByte(const uint8_t Byte)
+ {
+ SerialSPI_SendByte(&USARTC0, Byte);
+ }
+
+ /** Sends a dummy byte to the currently selected dataflash IC, and returns the next byte from the dataflash.
+ *
+ * \return Last response byte from the dataflash
+ */
+ static inline uint8_t Dataflash_ReceiveByte(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Dataflash_ReceiveByte(void)
+ {
+ return SerialSPI_ReceiveByte(&USARTC0);
+ }
+
+ /** Determines the currently selected dataflash chip.
+ *
+ * \return Mask of the currently selected Dataflash chip, either \ref DATAFLASH_NO_CHIP if no chip is selected
+ * or a DATAFLASH_CHIPn mask (where n is the chip number).
+ */
+ static inline uint8_t Dataflash_GetSelectedChip(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Dataflash_GetSelectedChip(void)
+ {
+ return (DATAFLASH_CHIPCS_PORT.OUT & DATAFLASH_CHIPCS_MASK);
+ }
+
+ /** Selects the given dataflash chip.
+ *
+ * \param[in] ChipMask Mask of the Dataflash IC to select, in the form of a \c DATAFLASH_CHIPn mask (where n is
+ * the chip number).
+ */
+ static inline void Dataflash_SelectChip(const uint8_t ChipMask) ATTR_ALWAYS_INLINE;
+ static inline void Dataflash_SelectChip(const uint8_t ChipMask)
+ {
+ DATAFLASH_CHIPCS_PORT.OUTCLR = DATAFLASH_CHIPCS_MASK;
+ DATAFLASH_CHIPCS_PORT.OUTSET = (ChipMask & DATAFLASH_CHIPCS_MASK);
+ }
+
+ /** Deselects the current dataflash chip, so that no dataflash is selected. */
+ static inline void Dataflash_DeselectChip(void) ATTR_ALWAYS_INLINE;
+ static inline void Dataflash_DeselectChip(void)
+ {
+ Dataflash_SelectChip(DATAFLASH_NO_CHIP);
+ }
+
+ /** Selects a dataflash IC from the given page number, which should range from 0 to
+ * ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1). For boards containing only one
+ * dataflash IC, this will select DATAFLASH_CHIP1. If the given page number is outside
+ * the total number of pages contained in the boards dataflash ICs, all dataflash ICs
+ * are deselected.
+ *
+ * \param[in] PageAddress Address of the page to manipulate, ranging from
+ * 0 to ((DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS) - 1).
+ */
+ static inline void Dataflash_SelectChipFromPage(const uint16_t PageAddress)
+ {
+ Dataflash_DeselectChip();
+
+ if (PageAddress >= (DATAFLASH_PAGES * DATAFLASH_TOTALCHIPS))
+ return;
+
+ Dataflash_SelectChip(DATAFLASH_CHIP1);
+ }
+
+ /** Toggles the select line of the currently selected dataflash IC, so that it is ready to receive
+ * a new command.
+ */
+ static inline void Dataflash_ToggleSelectedChipCS(void)
+ {
+ uint8_t SelectedChipMask = Dataflash_GetSelectedChip();
+
+ Dataflash_DeselectChip();
+ Dataflash_SelectChip(SelectedChipMask);
+ }
+
+ /** Spin-loops while the currently selected dataflash is busy executing a command, such as a main
+ * memory page program or main memory to buffer transfer.
+ */
+ static inline void Dataflash_WaitWhileBusy(void)
+ {
+ Dataflash_ToggleSelectedChipCS();
+ Dataflash_SendByte(DF_CMD_GETSTATUS);
+ while (!(Dataflash_ReceiveByte() & DF_STATUS_READY));
+ Dataflash_ToggleSelectedChipCS();
+ }
+
+ /** Sends a set of page and buffer address bytes to the currently selected dataflash IC, for use with
+ * dataflash commands which require a complete 24-bit address.
+ *
+ * \param[in] PageAddress Page address within the selected dataflash IC
+ * \param[in] BufferByte Address within the dataflash's buffer
+ */
+ static inline void Dataflash_SendAddressBytes(uint16_t PageAddress,
+ const uint16_t BufferByte)
+ {
+ Dataflash_SendByte(PageAddress >> 5);
+ Dataflash_SendByte((PageAddress << 3) | (BufferByte >> 8));
+ Dataflash_SendByte(BufferByte);
+ }
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/LEDs.h
new file mode 100644
index 000000000..7bd31ad09
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/LEDs.h
@@ -0,0 +1,183 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Atmel XMEGA B1 Xplained.
+ * \copydetails Group_LEDs_B1_XPLAINED
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_B1_XPLAINED B1_XPLAINED
+ * \brief Board specific LED driver header for the Atmel XMEGA B1 Xplained.
+ *
+ * Board specific LED driver header for the Atmel XMEGA B1 Xplained.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Yellow</td><td>LED0 LED</td><td>High</td><td>PORTB.4</td></tr>
+ * <tr><td>LEDS_LED2</td><td>Yellow</td><td>LED1 LED</td><td>High</td><td>PORTB.5</td></tr>
+ * <tr><td>LEDS_LED3</td><td>Yellow</td><td>LED2 LED</td><td>High</td><td>PORTB.6</td></tr>
+ * <tr><td>LEDS_LED4</td><td>Yellow</td><td>LED3 LED</td><td>High</td><td>PORTB.7</td></tr>
+ * <tr><td>LEDS_LED5</td><td>Green</td><td>USB LED</td><td>Low</td><td>PORTE.4</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_B1_XPLAINED_H__
+#define __LEDS_B1_XPLAINED_H__
+
+ /* Includes: */
+ #include <avr/io.h>
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define LEDS_PORTB_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3 | LEDS_LED4)
+ #define LEDS_PORTE_LEDS LEDS_LED5
+
+ #define LEDS_PORTE_MASK_SHIFT 1
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 4)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1 << 5)
+
+ /** LED mask for the third LED on the board. */
+ #define LEDS_LED3 (1 << 6)
+
+ /** LED mask for the fourth LED on the board. */
+ #define LEDS_LED4 (1 << 7)
+
+ /** LED mask for the fifth LED on the board. */
+ #define LEDS_LED5 ((1 << 4) >> LEDS_PORTE_MASK_SHIFT)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3 | LEDS_LED4 | LEDS_LED5)
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ PORTB.DIRSET = LEDS_PORTB_LEDS;
+ PORTB.OUTCLR = LEDS_PORTB_LEDS;
+
+ PORTCFG.MPCMASK = LEDS_PORTB_LEDS;
+ PORTB.PIN0CTRL = PORT_INVEN_bm;
+
+ PORTE.DIRSET = (LEDS_PORTE_LEDS << LEDS_PORTE_MASK_SHIFT);
+ PORTE.OUTCLR = (LEDS_PORTE_LEDS << LEDS_PORTE_MASK_SHIFT);
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ PORTB.DIRCLR = LEDS_PORTB_LEDS;
+ PORTB.OUTCLR = LEDS_PORTB_LEDS;
+
+ PORTCFG.MPCMASK = 0;
+ PORTB.PIN0CTRL = LEDS_PORTB_LEDS;
+
+ PORTE.DIRCLR = (LEDS_PORTE_LEDS << LEDS_PORTE_MASK_SHIFT);
+ PORTE.OUTCLR = (LEDS_PORTE_LEDS << LEDS_PORTE_MASK_SHIFT);
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTB_OUTSET = (LEDMask & LEDS_PORTB_LEDS);
+ PORTE_OUTSET = ((LEDMask & LEDS_PORTE_LEDS) << LEDS_PORTE_MASK_SHIFT);
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTB_OUTCLR = (LEDMask & LEDS_PORTB_LEDS);
+ PORTE_OUTCLR = ((LEDMask & LEDS_PORTE_LEDS) << LEDS_PORTE_MASK_SHIFT);
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTB_OUTCLR = LEDS_PORTB_LEDS;
+ PORTE_OUTCLR = (LEDS_PORTE_LEDS << LEDS_PORTE_MASK_SHIFT);
+
+ PORTB_OUTSET = (LEDMask & LEDS_PORTB_LEDS);
+ PORTE_OUTSET = ((LEDMask & LEDS_PORTE_LEDS) << LEDS_PORTE_MASK_SHIFT);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTB_OUTCLR = (LEDMask & LEDS_PORTB_LEDS);
+ PORTE_OUTCLR = ((LEDMask & LEDS_PORTE_LEDS) << LEDS_PORTE_MASK_SHIFT);
+
+ PORTB_OUTSET = (ActiveMask & LEDS_PORTB_LEDS);
+ PORTE_OUTSET = ((ActiveMask & LEDS_PORTE_LEDS) << LEDS_PORTE_MASK_SHIFT);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PORTB_OUTTGL = (LEDMask & LEDS_PORTB_LEDS);
+ PORTE_OUTTGL = ((LEDMask & LEDS_PORTE_LEDS) << LEDS_PORTE_MASK_SHIFT);
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return ((PORTB_OUT & LEDS_PORTB_LEDS) | (PORTE_OUT & (LEDS_PORTE_LEDS << LEDS_PORTE_MASK_SHIFT)));
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/C3_XPLAINED/Board.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/C3_XPLAINED/Board.h
new file mode 100644
index 000000000..d90cc3a5c
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/C3_XPLAINED/Board.h
@@ -0,0 +1,83 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific information header for the Atmel XMEGA C3 Xplained.
+ * \copydetails Group_BoardInfo_C3_XPLAINED
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Board driver
+ * dispatch header located in LUFA/Drivers/Board/Board.h.
+ */
+
+/** \ingroup Group_BoardInfo
+ * \defgroup Group_BoardInfo_C3_XPLAINED C3_XPLAINED
+ * \brief Board specific information header for the Atmel XMEGA C3 Xplained.
+ *
+ * Board specific information header for the Atmel XMEGA C3 Xplained.
+ *
+ * @{
+ */
+
+#ifndef __BOARD_C3_XPLAINED_H__
+#define __BOARD_C3_XPLAINED_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../../Buttons.h"
+ #include "../../Dataflash.h"
+ #include "../../LEDs.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BOARD_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Board.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the board has hardware Buttons mounted. */
+ #define BOARD_HAS_BUTTONS
+
+ /** Indicates the board has hardware LEDs mounted. */
+ #define BOARD_HAS_LEDS
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/C3_XPLAINED/Buttons.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/C3_XPLAINED/Buttons.h
new file mode 100644
index 000000000..db62b1d1f
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/C3_XPLAINED/Buttons.h
@@ -0,0 +1,109 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific Buttons driver header for the Atmel XMEGA C3 Xplained.
+ * \copydetails Group_Buttons_C3_XPLAINED
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the Buttons driver
+ * dispatch header located in LUFA/Drivers/Board/Buttons.h.
+ */
+
+/** \ingroup Group_Buttons
+ * \defgroup Group_Buttons_C3_XPLAINED C3_XPLAINED
+ * \brief Board specific Buttons driver header for the Atmel XMEGA C3 Xplained.
+ *
+ * Board specific Buttons driver header for the Atmel XMEGA C3 Xplained.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>BUTTONS_BUTTON1</td><td>SW0 Button</td><td>Low</td><td>PORTF.1</td></tr>
+ * <tr><td>BUTTONS_BUTTON2</td><td>SW1 Button</td><td>Low</td><td>PORTF.2</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __BUTTONS_C3_XPLAINED_H__
+#define __BUTTONS_C3_XPLAINED_H__
+
+ /* Includes: */
+ #include <avr/io.h>
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_BUTTONS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/Buttons.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Button mask for the first button on the board. */
+ #define BUTTONS_BUTTON1 (1 << 1)
+
+ /** Button mask for the second button on the board. */
+ #define BUTTONS_BUTTON2 (1 << 2)
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void Buttons_Init(void)
+ {
+ PORTF.OUTCLR = (BUTTONS_BUTTON1 | BUTTONS_BUTTON2);
+ PORTF.PIN1CTRL = (PORT_OPC_PULLUP_gc | PORT_INVEN_bm);
+ PORTF.PIN2CTRL = (PORT_OPC_PULLUP_gc | PORT_INVEN_bm);
+ }
+
+ static inline void Buttons_Disable(void)
+ {
+ PORTF.OUTCLR = (BUTTONS_BUTTON1 | BUTTONS_BUTTON2);
+ PORTF.PIN1CTRL = 0;
+ PORTF.PIN2CTRL = 0;
+ }
+
+ static inline uint8_t Buttons_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Buttons_GetStatus(void)
+ {
+ return (PORTF_IN & (BUTTONS_BUTTON1 | BUTTONS_BUTTON2));
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/C3_XPLAINED/LEDs.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/C3_XPLAINED/LEDs.h
new file mode 100644
index 000000000..737624bd3
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Board/XMEGA/C3_XPLAINED/LEDs.h
@@ -0,0 +1,181 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Board specific LED driver header for the Atmel XMEGA C3 Xplained.
+ * \copydetails Group_LEDs_C3_XPLAINED
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the LEDs driver
+ * dispatch header located in LUFA/Drivers/Board/LEDs.h.
+ */
+
+/** \ingroup Group_LEDs
+ * \defgroup Group_LEDs_C3_XPLAINED C3_XPLAINED
+ * \brief Board specific LED driver header for the Atmel XMEGA C3 Xplained.
+ *
+ * Board specific LED driver header for the Atmel XMEGA C3 Xplained.
+ *
+ * <table>
+ * <tr><th>Name</th><th>Color</th><th>Info</th><th>Active Level</th><th>Port Pin</th></tr>
+ * <tr><td>LEDS_LED1</td><td>Yellow</td><td>LED0 LED</td><td>Low</td><td>PORTR.0</td></tr>
+ * <tr><td>LEDS_LED2</td><td>Yellow</td><td>LED1 LED</td><td>Low</td><td>PORTR.1</td></tr>
+ * <tr><td>LEDS_LED3</td><td>Red</td><td>Status Bicolour Red LED</td><td>Low</td><td>PORTD.4</td></tr>
+ * <tr><td>LEDS_LED4</td><td>Green</td><td>Status Bicolour Green LED</td><td>High</td><td>PORTD.5</td></tr>
+ * </table>
+ *
+ * @{
+ */
+
+#ifndef __LEDS_C3_XPLAINED_H__
+#define __LEDS_C3_XPLAINED_H__
+
+ /* Includes: */
+ #include <avr/io.h>
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_LEDS_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Board/LEDS.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define LEDS_PORTR_LEDS (LEDS_LED1 | LEDS_LED2)
+ #define LEDS_PORTD_LEDS (LEDS_LED3 | LEDS_LED4)
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** LED mask for the first LED on the board. */
+ #define LEDS_LED1 (1 << 0)
+
+ /** LED mask for the second LED on the board. */
+ #define LEDS_LED2 (1 << 1)
+
+ /** LED mask for the third LED on the board. */
+ #define LEDS_LED3 (1 << 4)
+
+ /** LED mask for the fourth LED on the board. */
+ #define LEDS_LED4 (1 << 5)
+
+ /** LED mask for all the LEDs on the board. */
+ #define LEDS_ALL_LEDS (LEDS_LED1 | LEDS_LED2 | LEDS_LED3 | LEDS_LED4)
+
+ /** LED mask for none of the board LEDs. */
+ #define LEDS_NO_LEDS 0
+
+ /* Inline Functions: */
+ #if !defined(__DOXYGEN__)
+ static inline void LEDs_Init(void)
+ {
+ PORTR.DIRSET = LEDS_PORTR_LEDS;
+ PORTR.OUTCLR = LEDS_PORTR_LEDS;
+
+ PORTCFG.MPCMASK = LEDS_PORTR_LEDS;
+ PORTR.PIN0CTRL = PORT_INVEN_bm;
+
+ PORTD.DIRSET = LEDS_PORTD_LEDS;
+ PORTD.OUTCLR = LEDS_PORTD_LEDS;
+
+ PORTD.PIN4CTRL = PORT_INVEN_bm;
+ }
+
+ static inline void LEDs_Disable(void)
+ {
+ PORTR.DIRCLR = LEDS_PORTR_LEDS;
+ PORTR.OUTCLR = LEDS_PORTR_LEDS;
+
+ PORTCFG.MPCMASK = 0;
+ PORTR.PIN0CTRL = LEDS_PORTR_LEDS;
+
+ PORTD.DIRCLR = LEDS_PORTD_LEDS;
+ PORTD.OUTCLR = LEDS_PORTD_LEDS;
+
+ PORTD.PIN4CTRL = 0;
+ }
+
+ static inline void LEDs_TurnOnLEDs(const uint8_t LEDMask)
+ {
+ PORTR_OUTSET = LEDMask & LEDS_PORTR_LEDS;
+ PORTD_OUTSET = LEDMask & LEDS_PORTD_LEDS;
+ }
+
+ static inline void LEDs_TurnOffLEDs(const uint8_t LEDMask)
+ {
+ PORTR_OUTCLR = LEDMask & LEDS_PORTR_LEDS;
+ PORTD_OUTCLR = LEDMask & LEDS_PORTD_LEDS;
+ }
+
+ static inline void LEDs_SetAllLEDs(const uint8_t LEDMask)
+ {
+ PORTR_OUTCLR = LEDS_PORTR_LEDS;
+ PORTD_OUTCLR = LEDS_PORTD_LEDS;
+
+ PORTR_OUTSET = (LEDMask & LEDS_PORTR_LEDS);
+ PORTD_OUTSET = (LEDMask & LEDS_PORTD_LEDS);
+ }
+
+ static inline void LEDs_ChangeLEDs(const uint8_t LEDMask,
+ const uint8_t ActiveMask)
+ {
+ PORTR_OUTCLR = (LEDMask & LEDS_PORTR_LEDS);
+ PORTD_OUTCLR = (LEDMask & LEDS_PORTD_LEDS);
+
+ PORTR_OUTSET = (ActiveMask & LEDS_PORTR_LEDS);
+ PORTD_OUTSET = (ActiveMask & LEDS_PORTD_LEDS);
+ }
+
+ static inline void LEDs_ToggleLEDs(const uint8_t LEDMask)
+ {
+ PORTR_OUTTGL = (LEDMask & LEDS_PORTR_LEDS);
+ PORTD_OUTTGL = (LEDMask & LEDS_PORTD_LEDS);
+ }
+
+ static inline uint8_t LEDs_GetLEDs(void) ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t LEDs_GetLEDs(void)
+ {
+ return ((PORTR_OUT & LEDS_PORTR_LEDS) | (PORTD_OUT & LEDS_PORTD_LEDS));
+ }
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Misc/AT45DB321C.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Misc/AT45DB321C.h
new file mode 100644
index 000000000..25069286f
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Misc/AT45DB321C.h
@@ -0,0 +1,100 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Command constants for the Atmel AT45DB321C Dataflash.
+ * \copydetails Group_AT45DB321C
+ */
+
+/** \ingroup Group_MiscDrivers
+ * \defgroup Group_AT45DB321C Atmel AT45DB321C Dataflash Commands - LUFA/Drivers/Misc/AT45DB321C.h
+ * \brief Command constants for the Atmel AT45DB321C Dataflash.
+ *
+ * Dataflash command constants for the Atmel AT45DB321C Dataflash IC.
+ *
+ * @{
+ */
+
+#ifndef __AT45DB321C_CMDS_H__
+#define __AT45DB321C_CMDS_H__
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** \name Dataflash Status Values */
+ //@{
+ #define DF_STATUS_READY (1 << 7)
+ #define DF_STATUS_COMPMISMATCH (1 << 6)
+ #define DF_STATUS_SECTORPROTECTION_ON (1 << 1)
+ //@}
+
+ /** \name Dataflash Commands */
+ //@{
+ #define DF_CMD_GETSTATUS 0xD7
+
+ #define DF_CMD_MAINMEMTOBUFF1 0x53
+ #define DF_CMD_MAINMEMTOBUFF2 0x55
+ #define DF_CMD_MAINMEMTOBUFF1COMP 0x60
+ #define DF_CMD_MAINMEMTOBUFF2COMP 0x61
+ #define DF_CMD_AUTOREWRITEBUFF1 0x58
+ #define DF_CMD_AUTOREWRITEBUFF2 0x59
+
+ #define DF_CMD_MAINMEMPAGEREAD 0xD2
+ #define DF_CMD_CONTARRAYREAD_LF 0xE8
+ #define DF_CMD_BUFF1READ_LF 0xD4
+ #define DF_CMD_BUFF2READ_LF 0xD6
+
+ #define DF_CMD_BUFF1WRITE 0x84
+ #define DF_CMD_BUFF2WRITE 0x87
+ #define DF_CMD_BUFF1TOMAINMEMWITHERASE 0x83
+ #define DF_CMD_BUFF2TOMAINMEMWITHERASE 0x86
+ #define DF_CMD_BUFF1TOMAINMEM 0x88
+ #define DF_CMD_BUFF2TOMAINMEM 0x89
+ #define DF_CMD_MAINMEMPAGETHROUGHBUFF1 0x82
+ #define DF_CMD_MAINMEMPAGETHROUGHBUFF2 0x85
+
+ #define DF_CMD_PAGEERASE 0x81
+ #define DF_CMD_BLOCKERASE 0x50
+
+ #define DF_CMD_SECTORPROTECTIONOFF ((char[]){0x3D, 0x2A, 0x7F, 0xCF})
+ #define DF_CMD_SECTORPROTECTIONOFF_BYTE1 0x3D
+ #define DF_CMD_SECTORPROTECTIONOFF_BYTE2 0x2A
+ #define DF_CMD_SECTORPROTECTIONOFF_BYTE3 0x7F
+ #define DF_CMD_SECTORPROTECTIONOFF_BYTE4 0xCF
+
+ #define DF_CMD_READMANUFACTURERDEVICEINFO 0x9F
+ //@}
+
+ /** Manufacturer code for Atmel Corporation, returned by Atmel Dataflash ICs in response to the \c DF_CMD_READMANUFACTURERDEVICEINFO command. */
+ #define DF_MANUFACTURER_ATMEL 0x1F
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Misc/AT45DB642D.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Misc/AT45DB642D.h
new file mode 100644
index 000000000..ebbad71f9
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Misc/AT45DB642D.h
@@ -0,0 +1,116 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Command constants for the Atmel AT45DB642D Dataflash.
+ * \copydetails Group_AT45DB642D
+ */
+
+/** \ingroup Group_MiscDrivers
+ * \defgroup Group_AT45DB642D Atmel AT45DB642D Dataflash Commands - LUFA/Drivers/Misc/AT45DB642D.h
+ * \brief Command constants for the Atmel AT45DB642D Dataflash.
+ *
+ * Dataflash command constants for the Atmel AT45DB642D Dataflash IC.
+ *
+ * @{
+ */
+
+#ifndef __AT45DB642D_CMDS_H__
+#define __AT45DB642D_CMDS_H__
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** \name Dataflash Status Values */
+ //@{
+ #define DF_STATUS_READY (1 << 7)
+ #define DF_STATUS_COMPMISMATCH (1 << 6)
+ #define DF_STATUS_SECTORPROTECTION_ON (1 << 1)
+ #define DF_STATUS_BINARYPAGESIZE_ON (1 << 0)
+ //@}
+
+ /** \name Dataflash Commands */
+ //@{
+ #define DF_CMD_GETSTATUS 0xD7
+ #define DF_CMD_POWERDOWN 0xB9
+ #define DF_CMD_WAKEUP 0xAB
+
+ #define DF_CMD_MAINMEMTOBUFF1 0x53
+ #define DF_CMD_MAINMEMTOBUFF2 0x55
+ #define DF_CMD_MAINMEMTOBUFF1COMP 0x60
+ #define DF_CMD_MAINMEMTOBUFF2COMP 0x61
+ #define DF_CMD_AUTOREWRITEBUFF1 0x58
+ #define DF_CMD_AUTOREWRITEBUFF2 0x59
+
+ #define DF_CMD_MAINMEMPAGEREAD 0xD2
+ #define DF_CMD_CONTARRAYREAD_LF 0x03
+ #define DF_CMD_BUFF1READ_LF 0xD1
+ #define DF_CMD_BUFF2READ_LF 0xD3
+
+ #define DF_CMD_BUFF1WRITE 0x84
+ #define DF_CMD_BUFF2WRITE 0x87
+ #define DF_CMD_BUFF1TOMAINMEMWITHERASE 0x83
+ #define DF_CMD_BUFF2TOMAINMEMWITHERASE 0x86
+ #define DF_CMD_BUFF1TOMAINMEM 0x88
+ #define DF_CMD_BUFF2TOMAINMEM 0x89
+ #define DF_CMD_MAINMEMPAGETHROUGHBUFF1 0x82
+ #define DF_CMD_MAINMEMPAGETHROUGHBUFF2 0x85
+
+ #define DF_CMD_PAGEERASE 0x81
+ #define DF_CMD_BLOCKERASE 0x50
+ #define DF_CMD_SECTORERASE 0x7C
+
+ #define DF_CMD_CHIPERASE ((char[]){0xC7, 0x94, 0x80, 0x9A})
+ #define DF_CMD_CHIPERASE_BYTE1 0xC7
+ #define DF_CMD_CHIPERASE_BYTE2 0x94
+ #define DF_CMD_CHIPERASE_BYTE3 0x80
+ #define DF_CMD_CHIPERASE_BYTE4 0x9A
+
+ #define DF_CMD_SECTORPROTECTIONOFF ((char[]){0x3D, 0x2A, 0x7F, 0x9A})
+ #define DF_CMD_SECTORPROTECTIONOFF_BYTE1 0x3D
+ #define DF_CMD_SECTORPROTECTIONOFF_BYTE2 0x2A
+ #define DF_CMD_SECTORPROTECTIONOFF_BYTE3 0x7F
+ #define DF_CMD_SECTORPROTECTIONOFF_BYTE4 0x9A
+
+ #define DF_CMD_BINARYPAGESIZEMODEON ((char[]){0x3D, 0x2A, 0x80, 0xA6})
+ #define DF_CMD_BINARYPAGESIZEMODEON_BYTE1 0x3D
+ #define DF_CMD_BINARYPAGESIZEMODEON_BYTE2 0x2A
+ #define DF_CMD_BINARYPAGESIZEMODEON_BYTE3 0x80
+ #define DF_CMD_BINARYPAGESIZEMODEON_BYTE4 0xA6
+
+ #define DF_CMD_READMANUFACTURERDEVICEINFO 0x9F
+ //@}
+
+ /** Manufacturer code for Atmel Corporation, returned by Atmel Dataflash ICs in response to the \c DF_CMD_READMANUFACTURERDEVICEINFO command. */
+ #define DF_MANUFACTURER_ATMEL 0x1F
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Misc/RingBuffer.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Misc/RingBuffer.h
new file mode 100644
index 000000000..68fdb8e92
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Misc/RingBuffer.h
@@ -0,0 +1,308 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Lightweight ring (circular) buffer, for fast insertion/deletion of bytes.
+ *
+ * Lightweight ring buffer, for fast insertion/deletion. Multiple buffers can be created of
+ * different sizes to suit different needs.
+ *
+ * Note that for each buffer, insertion and removal operations may occur at the same time (via
+ * a multi-threaded ISR based system) however the same kind of operation (two or more insertions
+ * or deletions) must not overlap. If there is possibility of two or more of the same kind of
+ * operating occurring at the same point in time, atomic (mutex) locking should be used.
+ */
+
+/** \ingroup Group_MiscDrivers
+ * \defgroup Group_RingBuff Generic Byte Ring Buffer - LUFA/Drivers/Misc/RingBuffer.h
+ * \brief Lightweight ring buffer, for fast insertion/deletion of bytes.
+ *
+ * \section Sec_RingBuff_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - None
+ *
+ * \section Sec_RingBuff_ModDescription Module Description
+ * Lightweight ring buffer, for fast insertion/deletion. Multiple buffers can be created of
+ * different sizes to suit different needs.
+ *
+ * Note that for each buffer, insertion and removal operations may occur at the same time (via
+ * a multi-threaded ISR based system) however the same kind of operation (two or more insertions
+ * or deletions) must not overlap. If there is possibility of two or more of the same kind of
+ * operating occurring at the same point in time, atomic (mutex) locking should be used.
+ *
+ * \section Sec_RingBuff_ExampleUsage Example Usage
+ * The following snippet is an example of how this module may be used within a typical
+ * application.
+ *
+ * \code
+ * // Create the buffer structure and its underlying storage array
+ * RingBuffer_t Buffer;
+ * uint8_t BufferData[128];
+ *
+ * // Initialize the buffer with the created storage array
+ * RingBuffer_InitBuffer(&Buffer, BufferData, sizeof(BufferData));
+ *
+ * // Insert some data into the buffer
+ * RingBuffer_Insert(&Buffer, 'H');
+ * RingBuffer_Insert(&Buffer, 'E');
+ * RingBuffer_Insert(&Buffer, 'L');
+ * RingBuffer_Insert(&Buffer, 'L');
+ * RingBuffer_Insert(&Buffer, 'O');
+ *
+ * // Cache the number of stored bytes in the buffer
+ * uint16_t BufferCount = RingBuffer_GetCount(&Buffer);
+ *
+ * // Printer stored data length
+ * printf("Buffer Length: %d, Buffer Data: \r\n", BufferCount);
+ *
+ * // Print contents of the buffer one character at a time
+ * while (BufferCount--)
+ * putc(RingBuffer_Remove(&Buffer));
+ * \endcode
+ *
+ * @{
+ */
+
+#ifndef __RING_BUFFER_H__
+#define __RING_BUFFER_H__
+
+ /* Includes: */
+ #include "../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Type Defines: */
+ /** \brief Ring Buffer Management Structure.
+ *
+ * Type define for a new ring buffer object. Buffers should be initialized via a call to
+ * \ref RingBuffer_InitBuffer() before use.
+ */
+ typedef struct
+ {
+ uint8_t* In; /**< Current storage location in the circular buffer. */
+ uint8_t* Out; /**< Current retrieval location in the circular buffer. */
+ uint8_t* Start; /**< Pointer to the start of the buffer's underlying storage array. */
+ uint8_t* End; /**< Pointer to the end of the buffer's underlying storage array. */
+ uint16_t Size; /**< Size of the buffer's underlying storage array. */
+ uint16_t Count; /**< Number of bytes currently stored in the buffer. */
+ } RingBuffer_t;
+
+ /* Inline Functions: */
+ /** Initializes a ring buffer ready for use. Buffers must be initialized via this function
+ * before any operations are called upon them. Already initialized buffers may be reset
+ * by re-initializing them using this function.
+ *
+ * \param[out] Buffer Pointer to a ring buffer structure to initialize.
+ * \param[out] DataPtr Pointer to a global array that will hold the data stored into the ring buffer.
+ * \param[out] Size Maximum number of bytes that can be stored in the underlying data array.
+ */
+ static inline void RingBuffer_InitBuffer(RingBuffer_t* Buffer,
+ uint8_t* const DataPtr,
+ const uint16_t Size) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+ static inline void RingBuffer_InitBuffer(RingBuffer_t* Buffer,
+ uint8_t* const DataPtr,
+ const uint16_t Size)
+ {
+ GCC_FORCE_POINTER_ACCESS(Buffer);
+
+ uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask();
+ GlobalInterruptDisable();
+
+ Buffer->In = DataPtr;
+ Buffer->Out = DataPtr;
+ Buffer->Start = &DataPtr[0];
+ Buffer->End = &DataPtr[Size];
+ Buffer->Size = Size;
+ Buffer->Count = 0;
+
+ SetGlobalInterruptMask(CurrentGlobalInt);
+ }
+
+ /** Retrieves the current number of bytes stored in a particular buffer. This value is computed
+ * by entering an atomic lock on the buffer, so that the buffer cannot be modified while the
+ * computation takes place. This value should be cached when reading out the contents of the buffer,
+ * so that as small a time as possible is spent in an atomic lock.
+ *
+ * \note The value returned by this function is guaranteed to only be the minimum number of bytes
+ * stored in the given buffer; this value may change as other threads write new data, thus
+ * the returned number should be used only to determine how many successive reads may safely
+ * be performed on the buffer.
+ *
+ * \param[in] Buffer Pointer to a ring buffer structure whose count is to be computed.
+ *
+ * \return Number of bytes currently stored in the buffer.
+ */
+ static inline uint16_t RingBuffer_GetCount(RingBuffer_t* const Buffer) ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ static inline uint16_t RingBuffer_GetCount(RingBuffer_t* const Buffer)
+ {
+ uint16_t Count;
+
+ uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask();
+ GlobalInterruptDisable();
+
+ Count = Buffer->Count;
+
+ SetGlobalInterruptMask(CurrentGlobalInt);
+ return Count;
+ }
+
+ /** Retrieves the free space in a particular buffer. This value is computed by entering an atomic lock
+ * on the buffer, so that the buffer cannot be modified while the computation takes place.
+ *
+ * \note The value returned by this function is guaranteed to only be the maximum number of bytes
+ * free in the given buffer; this value may change as other threads write new data, thus
+ * the returned number should be used only to determine how many successive writes may safely
+ * be performed on the buffer when there is a single writer thread.
+ *
+ * \param[in] Buffer Pointer to a ring buffer structure whose free count is to be computed.
+ *
+ * \return Number of free bytes in the buffer.
+ */
+ static inline uint16_t RingBuffer_GetFreeCount(RingBuffer_t* const Buffer) ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ static inline uint16_t RingBuffer_GetFreeCount(RingBuffer_t* const Buffer)
+ {
+ return (Buffer->Size - RingBuffer_GetCount(Buffer));
+ }
+
+ /** Atomically determines if the specified ring buffer contains any data. This should
+ * be tested before removing data from the buffer, to ensure that the buffer does not
+ * underflow.
+ *
+ * If the data is to be removed in a loop, store the total number of bytes stored in the
+ * buffer (via a call to the \ref RingBuffer_GetCount() function) in a temporary variable
+ * to reduce the time spent in atomicity locks.
+ *
+ * \param[in,out] Buffer Pointer to a ring buffer structure to insert into.
+ *
+ * \return Boolean \c true if the buffer contains no free space, \c false otherwise.
+ */
+ static inline bool RingBuffer_IsEmpty(RingBuffer_t* const Buffer) ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ static inline bool RingBuffer_IsEmpty(RingBuffer_t* const Buffer)
+ {
+ return (RingBuffer_GetCount(Buffer) == 0);
+ }
+
+ /** Atomically determines if the specified ring buffer contains any free space. This should
+ * be tested before storing data to the buffer, to ensure that no data is lost due to a
+ * buffer overrun.
+ *
+ * \param[in,out] Buffer Pointer to a ring buffer structure to insert into.
+ *
+ * \return Boolean \c true if the buffer contains no free space, \c false otherwise.
+ */
+ static inline bool RingBuffer_IsFull(RingBuffer_t* const Buffer) ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ static inline bool RingBuffer_IsFull(RingBuffer_t* const Buffer)
+ {
+ return (RingBuffer_GetCount(Buffer) == Buffer->Size);
+ }
+
+ /** Inserts an element into the ring buffer.
+ *
+ * \warning Only one execution thread (main program thread or an ISR) may insert into a single buffer
+ * otherwise data corruption may occur. Insertion and removal may occur from different execution
+ * threads.
+ *
+ * \param[in,out] Buffer Pointer to a ring buffer structure to insert into.
+ * \param[in] Data Data element to insert into the buffer.
+ */
+ static inline void RingBuffer_Insert(RingBuffer_t* Buffer,
+ const uint8_t Data) ATTR_NON_NULL_PTR_ARG(1);
+ static inline void RingBuffer_Insert(RingBuffer_t* Buffer,
+ const uint8_t Data)
+ {
+ GCC_FORCE_POINTER_ACCESS(Buffer);
+
+ *Buffer->In = Data;
+
+ if (++Buffer->In == Buffer->End)
+ Buffer->In = Buffer->Start;
+
+ uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask();
+ GlobalInterruptDisable();
+
+ Buffer->Count++;
+
+ SetGlobalInterruptMask(CurrentGlobalInt);
+ }
+
+ /** Removes an element from the ring buffer.
+ *
+ * \warning Only one execution thread (main program thread or an ISR) may remove from a single buffer
+ * otherwise data corruption may occur. Insertion and removal may occur from different execution
+ * threads.
+ *
+ * \param[in,out] Buffer Pointer to a ring buffer structure to retrieve from.
+ *
+ * \return Next data element stored in the buffer.
+ */
+ static inline uint8_t RingBuffer_Remove(RingBuffer_t* Buffer) ATTR_NON_NULL_PTR_ARG(1);
+ static inline uint8_t RingBuffer_Remove(RingBuffer_t* Buffer)
+ {
+ GCC_FORCE_POINTER_ACCESS(Buffer);
+
+ uint8_t Data = *Buffer->Out;
+
+ if (++Buffer->Out == Buffer->End)
+ Buffer->Out = Buffer->Start;
+
+ uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask();
+ GlobalInterruptDisable();
+
+ Buffer->Count--;
+
+ SetGlobalInterruptMask(CurrentGlobalInt);
+
+ return Data;
+ }
+
+ /** Returns the next element stored in the ring buffer, without removing it.
+ *
+ * \param[in,out] Buffer Pointer to a ring buffer structure to retrieve from.
+ *
+ * \return Next data element stored in the buffer.
+ */
+ static inline uint8_t RingBuffer_Peek(RingBuffer_t* const Buffer) ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ static inline uint8_t RingBuffer_Peek(RingBuffer_t* const Buffer)
+ {
+ return *Buffer->Out;
+ }
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Misc/TerminalCodes.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Misc/TerminalCodes.h
new file mode 100644
index 000000000..d43fe010c
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Misc/TerminalCodes.h
@@ -0,0 +1,231 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief ANSI terminal special escape code macros.
+ *
+ * ANSI terminal compatible escape sequences. These escape sequences are designed to be concatenated with existing
+ * strings to modify their display on a compatible terminal application.
+ */
+
+/** \ingroup Group_MiscDrivers
+ * \defgroup Group_Terminal ANSI Terminal Escape Codes - LUFA/Drivers/Misc/TerminalCodes.h
+ * \brief ANSI terminal special escape code macros.
+ *
+ * \section Sec_Terminal_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - None
+ *
+ * \section Sec_Terminal_ModDescription Module Description
+ * Escape code macros for ANSI compliant text terminals.
+ *
+ * \note If desired, the macro \c DISABLE_TERMINAL_CODES can be defined in the project makefile and passed to the GCC
+ * compiler via the -D switch to disable the terminal codes without modifying the source, for use with non
+ * compatible terminals (any terminal codes then equate to empty strings).
+ *
+ * \section Sec_Terminal_ExampleUsage Example Usage
+ * The following snippet is an example of how this module may be used within a typical
+ * application.
+ *
+ * \code
+ * printf("Normal String, "
+ * ESC_BOLD_ON "Bold String, "
+ * ESC_UNDERLINE_ON "Bold and Underlined String"
+ * ESC_RESET ESC_FG_BLUE ESC_BG_YELLOW "Normal Blue-on-Yellow String");
+ * \endcode
+ *
+ * @{
+ */
+
+#ifndef __TERMINALCODES_H__
+#define __TERMINALCODES_H__
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ #if !defined(DISABLE_TERMINAL_CODES)
+ /** Creates an ANSI escape sequence with the specified payload.
+ *
+ * \param[in] EscapeSeq Payload to encode as an ANSI escape sequence, a \c ESC_* mask.
+ */
+ #define ANSI_ESCAPE_SEQUENCE(EscapeSeq) "\33[" EscapeSeq
+ #else
+ #define ANSI_ESCAPE_SEQUENCE(EscapeSeq)
+ #endif
+
+ /** \name Text Display Modifier Control Sequences */
+ //@{
+ /** Turns on bold so that any following text is printed to the terminal in bold. */
+ #define ESC_BOLD_ON ANSI_ESCAPE_SEQUENCE("1m")
+
+ /** Turns on italics so that any following text is printed to the terminal in italics. */
+ #define ESC_ITALICS_ON ANSI_ESCAPE_SEQUENCE("3m")
+
+ /** Turns on underline so that any following text is printed to the terminal underlined. */
+ #define ESC_UNDERLINE_ON ANSI_ESCAPE_SEQUENCE("4m")
+
+ /** Turns on inverse so that any following text is printed to the terminal in inverted colours. */
+ #define ESC_INVERSE_ON ANSI_ESCAPE_SEQUENCE("7m")
+
+ /** Turns on strike-through so that any following text is printed to the terminal with a line through the
+ * center.
+ */
+ #define ESC_STRIKETHROUGH_ON ANSI_ESCAPE_SEQUENCE("9m")
+
+ /** Turns off bold so that any following text is printed to the terminal in non bold. */
+ #define ESC_BOLD_OFF ANSI_ESCAPE_SEQUENCE("22m")
+
+ /** Turns off italics so that any following text is printed to the terminal in non italics. */
+ #define ESC_ITALICS_OFF ANSI_ESCAPE_SEQUENCE("23m")
+
+ /** Turns off underline so that any following text is printed to the terminal non underlined. */
+ #define ESC_UNDERLINE_OFF ANSI_ESCAPE_SEQUENCE("24m")
+
+ /** Turns off inverse so that any following text is printed to the terminal in non inverted colours. */
+ #define ESC_INVERSE_OFF ANSI_ESCAPE_SEQUENCE("27m")
+
+ /** Turns off strike-through so that any following text is printed to the terminal without a line through
+ * the center.
+ */
+ #define ESC_STRIKETHROUGH_OFF ANSI_ESCAPE_SEQUENCE("29m")
+ //@}
+
+ /** \name Text Colour Control Sequences */
+ //@{
+ /** Sets the foreground (text) colour to black. */
+ #define ESC_FG_BLACK ANSI_ESCAPE_SEQUENCE("30m")
+
+ /** Sets the foreground (text) colour to red. */
+ #define ESC_FG_RED ANSI_ESCAPE_SEQUENCE("31m")
+
+ /** Sets the foreground (text) colour to green. */
+ #define ESC_FG_GREEN ANSI_ESCAPE_SEQUENCE("32m")
+
+ /** Sets the foreground (text) colour to yellow. */
+ #define ESC_FG_YELLOW ANSI_ESCAPE_SEQUENCE("33m")
+
+ /** Sets the foreground (text) colour to blue. */
+ #define ESC_FG_BLUE ANSI_ESCAPE_SEQUENCE("34m")
+
+ /** Sets the foreground (text) colour to magenta. */
+ #define ESC_FG_MAGENTA ANSI_ESCAPE_SEQUENCE("35m")
+
+ /** Sets the foreground (text) colour to cyan. */
+ #define ESC_FG_CYAN ANSI_ESCAPE_SEQUENCE("36m")
+
+ /** Sets the foreground (text) colour to white. */
+ #define ESC_FG_WHITE ANSI_ESCAPE_SEQUENCE("37m")
+
+ /** Sets the foreground (text) colour to the terminal's default. */
+ #define ESC_FG_DEFAULT ANSI_ESCAPE_SEQUENCE("39m")
+
+ /** Sets the text background colour to black. */
+ #define ESC_BG_BLACK ANSI_ESCAPE_SEQUENCE("40m")
+
+ /** Sets the text background colour to red. */
+ #define ESC_BG_RED ANSI_ESCAPE_SEQUENCE("41m")
+
+ /** Sets the text background colour to green. */
+ #define ESC_BG_GREEN ANSI_ESCAPE_SEQUENCE("42m")
+
+ /** Sets the text background colour to yellow. */
+ #define ESC_BG_YELLOW ANSI_ESCAPE_SEQUENCE("43m")
+
+ /** Sets the text background colour to blue. */
+ #define ESC_BG_BLUE ANSI_ESCAPE_SEQUENCE("44m")
+
+ /** Sets the text background colour to magenta. */
+ #define ESC_BG_MAGENTA ANSI_ESCAPE_SEQUENCE("45m")
+
+ /** Sets the text background colour to cyan. */
+ #define ESC_BG_CYAN ANSI_ESCAPE_SEQUENCE("46m")
+
+ /** Sets the text background colour to white. */
+ #define ESC_BG_WHITE ANSI_ESCAPE_SEQUENCE("47m")
+
+ /** Sets the text background colour to the terminal's default. */
+ #define ESC_BG_DEFAULT ANSI_ESCAPE_SEQUENCE("49m")
+ //@}
+
+ /** \name Cursor Positioning Control Sequences */
+ //@{
+ /** Saves the current cursor position so that it may be restored with \ref ESC_CURSOR_POS_RESTORE. */
+ #define ESC_CURSOR_POS_SAVE ANSI_ESCAPE_SEQUENCE("s")
+
+ /** Restores the cursor position to the last position saved with \ref ESC_CURSOR_POS_SAVE. */
+ #define ESC_CURSOR_POS_RESTORE ANSI_ESCAPE_SEQUENCE("u")
+
+ /** Sets the cursor position to the given line and column.
+ *
+ * \param[in] Line Line number to position the cursor at.
+ * \param[in] Column Column number to position the cursor at.
+ */
+ #define ESC_CURSOR_POS(Line, Column) ANSI_ESCAPE_SEQUENCE(#Line ";" #Column "H")
+
+ /** Moves the cursor up the given number of lines.
+ *
+ * \param[in] Lines Number of lines to move the cursor position
+ */
+ #define ESC_CURSOR_UP(Lines) ANSI_ESCAPE_SEQUENCE(#Lines "A")
+
+ /** Moves the cursor down the given number of lines.
+ *
+ * \param[in] Lines Number of lines to move the cursor position
+ */
+ #define ESC_CURSOR_DOWN(Lines) ANSI_ESCAPE_SEQUENCE(#Lines "B")
+
+ /** Moves the cursor to the right the given number of columns.
+ *
+ * \param[in] Columns Number of columns to move the cursor position
+ */
+ #define ESC_CURSOR_FORWARD(Columns) ANSI_ESCAPE_SEQUENCE(#Columns "C")
+
+ /** Moves the cursor to the left the given number of columns.
+ *
+ * \param[in] Columns Number of columns to move the cursor position
+ */
+ #define ESC_CURSOR_BACKWARD(Columns) ANSI_ESCAPE_SEQUENCE(#Columns "D")
+ //@}
+
+ /** \name Miscellaneous Control Sequences */
+ //@{
+ /** Resets any escape sequence modifiers back to their defaults. */
+ #define ESC_RESET ANSI_ESCAPE_SEQUENCE("0m")
+
+ /** Erases the entire display, returning the cursor to the top left. */
+ #define ESC_ERASE_DISPLAY ANSI_ESCAPE_SEQUENCE("2J")
+
+ /** Erases the current line, returning the cursor to the far left. */
+ #define ESC_ERASE_LINE ANSI_ESCAPE_SEQUENCE("K")
+ //@}
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/ADC.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/ADC.h
new file mode 100644
index 000000000..295c6e1e8
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/ADC.h
@@ -0,0 +1,75 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Hardware Analogue-to-Digital converter driver.
+ *
+ * This file is the master dispatch header file for the device-specific ADC driver, for microcontrollers
+ * containing an ADC.
+ *
+ * User code should include this file, which will in turn include the correct ADC driver header file for the
+ * currently selected architecture and microcontroller model.
+ */
+
+/** \ingroup Group_PeripheralDrivers
+ * \defgroup Group_ADC ADC Driver - LUFA/Drivers/Peripheral/ADC.h
+ * \brief Hardware Analogue-to-Digital converter driver.
+ *
+ * \section Sec_ADC_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - None
+ *
+ * \section Sec_ADC_ModDescription Module Description
+ * Hardware ADC driver. This module provides an easy to use driver for the hardware ADC
+ * present on many microcontrollers, for the conversion of analogue signals into the
+ * digital domain.
+ *
+ * \note The exact API for this driver may vary depending on the target used - see
+ * individual target module documentation for the API specific to your target processor.
+ */
+
+#ifndef __ADC_H__
+#define __ADC_H__
+
+ /* Macros: */
+ #define __INCLUDE_FROM_ADC_H
+
+ /* Includes: */
+ #include "../../Common/Common.h"
+
+ /* Includes: */
+ #if (ARCH == ARCH_AVR8)
+ #include "AVR8/ADC_AVR8.h"
+ #else
+ #error The ADC peripheral driver is not currently available for your selected architecture.
+ #endif
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/AVR8/ADC_AVR8.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/AVR8/ADC_AVR8.h
new file mode 100644
index 000000000..03b6ed0c2
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/AVR8/ADC_AVR8.h
@@ -0,0 +1,446 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief ADC Peripheral Driver (AVR8)
+ *
+ * On-chip Analogue-to-Digital converter (ADC) driver for supported U4, U6 and U7 model AVRs that contain an ADC
+ * peripheral internally.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the ADC driver
+ * dispatch header located in LUFA/Drivers/Peripheral/ADC.h.
+ */
+
+/** \ingroup Group_ADC
+ * \defgroup Group_ADC_AVR8 ADC Peripheral Driver (AVR8)
+ *
+ * \section Sec_ADC_AVR8_ModDescription Module Description
+ * On-chip Analogue-to-Digital converter (ADC) driver for supported U4, U6 and U7 model AVRs that contain an ADC
+ * peripheral internally.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the ADC driver
+ * dispatch header located in LUFA/Drivers/Peripheral/ADC.h.
+ *
+ * \section Sec_ADC_AVR8_ExampleUsage Example Usage
+ * The following snippet is an example of how this module may be used within a typical
+ * application.
+ *
+ * \code
+ * // Initialize the ADC driver before first use
+ * ADC_Init(ADC_FREE_RUNNING | ADC_PRESCALE_32);
+ *
+ * // Must setup the ADC channel to read beforehand
+ * ADC_SetupChannel(1);
+ *
+ * // Perform a single conversion of the ADC channel 1
+ * ADC_GetChannelReading(ADC_REFERENCE_AVCC | ADC_RIGHT_ADJUSTED | ADC_CHANNEL1);
+ * printf("Conversion Result: %d\r\n", ADC_GetResult());
+ *
+ * // Start reading ADC channel 1 in free running (continuous conversion) mode
+ * ADC_StartReading(ADC_REFERENCE_AVCC | ADC_RIGHT_ADJUSTED | ADC_CHANNEL1);
+ * for (;;)
+ * {
+ * while (!(ADC_IsReadingComplete())) {};
+ * printf("Conversion Result: %d\r\n", ADC_GetResult());
+ * }
+ * \endcode
+ *
+ * @{
+ */
+
+#ifndef __ADC_AVR8_H__
+#define __ADC_AVR8_H__
+
+ /* Includes: */
+ #include "../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_ADC_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Peripheral/ADC.h instead.
+ #endif
+
+ #if !(defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || \
+ defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB647__) || \
+ defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
+ #error The ADC peripheral driver is not currently available for your selected microcontroller model.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** \name ADC Reference Configuration Masks */
+ //@{
+ /** Reference mask, for using the voltage present at the AVR's AREF pin for the ADC reference. */
+ #define ADC_REFERENCE_AREF 0
+
+ /** Reference mask, for using the voltage present at the AVR's AVCC pin for the ADC reference. */
+ #define ADC_REFERENCE_AVCC (1 << REFS0)
+
+ /** Reference mask, for using the internally generated 2.56V reference voltage as the ADC reference. */
+ #define ADC_REFERENCE_INT2560MV ((1 << REFS1) | (1 << REFS0))
+ //@}
+
+ /** \name ADC Result Adjustment Configuration Masks */
+ //@{
+ /** Left-adjusts the 10-bit ADC result, so that the upper 8 bits of the value returned by the
+ * \ref ADC_GetResult() macro contain the 8 most significant bits of the result.
+ */
+ #define ADC_LEFT_ADJUSTED (1 << ADLAR)
+
+ /** Right-adjusts the 10-bit ADC result, so that the lower 8 bits of the value returned by the
+ * \ref ADC_GetResult() macro contain the 8 least significant bits of the result.
+ */
+ #define ADC_RIGHT_ADJUSTED (0 << ADLAR)
+ //@}
+
+ /** \name ADC Mode Configuration Masks */
+ //@{
+ /** Sets the ADC mode to free running, so that conversions take place continuously as fast as the ADC
+ * is capable of at the given input clock speed.
+ */
+ #define ADC_FREE_RUNNING (1 << ADATE)
+
+ /** Sets the ADC mode to single conversion, so that only a single conversion will take place before
+ * the ADC returns to idle.
+ */
+ #define ADC_SINGLE_CONVERSION (0 << ADATE)
+ //@}
+
+ /** \name ADC Prescaler Configuration Masks */
+ //@{
+ /** Sets the ADC input clock to prescale by a factor of 2 the AVR's system clock. */
+ #define ADC_PRESCALE_2 (1 << ADPS0)
+
+ /** Sets the ADC input clock to prescale by a factor of 4 the AVR's system clock. */
+ #define ADC_PRESCALE_4 (1 << ADPS1)
+
+ /** Sets the ADC input clock to prescale by a factor of 8 the AVR's system clock. */
+ #define ADC_PRESCALE_8 ((1 << ADPS0) | (1 << ADPS1))
+
+ /** Sets the ADC input clock to prescale by a factor of 16 the AVR's system clock. */
+ #define ADC_PRESCALE_16 (1 << ADPS2)
+
+ /** Sets the ADC input clock to prescale by a factor of 32 the AVR's system clock. */
+ #define ADC_PRESCALE_32 ((1 << ADPS2) | (1 << ADPS0))
+
+ /** Sets the ADC input clock to prescale by a factor of 64 the AVR's system clock. */
+ #define ADC_PRESCALE_64 ((1 << ADPS2) | (1 << ADPS1))
+
+ /** Sets the ADC input clock to prescale by a factor of 128 the AVR's system clock. */
+ #define ADC_PRESCALE_128 ((1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0))
+ //@}
+
+ /** \name ADC MUX Masks */
+ //@{
+ /** MUX mask define for the ADC0 channel of the ADC. See \ref ADC_StartReading() and \ref ADC_GetChannelReading(). */
+ #define ADC_CHANNEL0 (0x00 << MUX0)
+
+ /** MUX mask define for the ADC1 channel of the ADC. See \ref ADC_StartReading() and \ref ADC_GetChannelReading(). */
+ #define ADC_CHANNEL1 (0x01 << MUX0)
+
+ #if (!(defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)) || defined(__DOXYGEN__))
+ /** MUX mask define for the ADC2 channel of the ADC. See \ref ADC_StartReading() and \ref ADC_GetChannelReading().
+ *
+ * \note Not available on all AVR models.
+ */
+ #define ADC_CHANNEL2 (0x02 << MUX0)
+
+ /** MUX mask define for the ADC3 channel of the ADC. See \ref ADC_StartReading() and \ref ADC_GetChannelReading().
+ *
+ * \note Not available on all AVR models.
+ */
+ #define ADC_CHANNEL3 (0x03 << MUX0)
+ #endif
+
+ /** MUX mask define for the ADC4 channel of the ADC. See \ref ADC_StartReading() and \ref ADC_GetChannelReading(). */
+ #define ADC_CHANNEL4 (0x04 << MUX0)
+
+ /** MUX mask define for the ADC5 channel of the ADC. See \ref ADC_StartReading() and \ref ADC_GetChannelReading(). */
+ #define ADC_CHANNEL5 (0x05 << MUX0)
+
+ /** MUX mask define for the ADC6 channel of the ADC. See \ref ADC_StartReading() and \ref ADC_GetChannelReading(). */
+ #define ADC_CHANNEL6 (0x06 << MUX0)
+
+ /** MUX mask define for the ADC7 channel of the ADC. See \ref ADC_StartReading and \ref ADC_GetChannelReading. */
+ #define ADC_CHANNEL7 (0x07 << MUX0)
+
+ #if (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || defined(__DOXYGEN__))
+ /** MUX mask define for the ADC8 channel of the ADC. See \ref ADC_StartReading() and \ref ADC_GetChannelReading().
+ *
+ * \note Not available on all AVR models.
+ */
+ #define ADC_CHANNEL8 ((1 << 8) | (0x00 << MUX0))
+
+ /** MUX mask define for the ADC9 channel of the ADC. See \ref ADC_StartReading() and \ref ADC_GetChannelReading().
+ *
+ * \note Not available on all AVR models.
+ */
+ #define ADC_CHANNEL9 ((1 << 8) | (0x01 << MUX0))
+
+ /** MUX mask define for the ADC10 channel of the ADC. See \ref ADC_StartReading() and \ref ADC_GetChannelReading().
+ *
+ * \note Not available on all AVR models.
+ */
+ #define ADC_CHANNEL10 ((1 << 8) | (0x02 << MUX0))
+
+ /** MUX mask define for the ADC11 channel of the ADC. See \ref ADC_StartReading() and \ref ADC_GetChannelReading().
+ *
+ * \note Not available on all AVR models.
+ */
+ #define ADC_CHANNEL11 ((1 << 8) | (0x03 << MUX0))
+
+ /** MUX mask define for the ADC12 channel of the ADC. See \ref ADC_StartReading() and \ref ADC_GetChannelReading().
+ *
+ * \note Not available on all AVR models.
+ */
+ #define ADC_CHANNEL12 ((1 << 8) | (0x04 << MUX0))
+
+ /** MUX mask define for the ADC13 channel of the ADC. See \ref ADC_StartReading() and \ref ADC_GetChannelReading().
+ *
+ * \note Not available on all AVR models.
+ */
+ #define ADC_CHANNEL13 ((1 << 8) | (0x05 << MUX0))
+
+ /** MUX mask define for the internal temperature sensor channel of the ADC. See \ref ADC_StartReading() and
+ * \ref ADC_GetChannelReading().
+ *
+ * \note Not available on all AVR models.
+ */
+ #define ADC_INT_TEMP_SENS ((1 << 8) | (0x07 << MUX0))
+ #endif
+
+ /** MUX mask define for the internal 1.1V band-gap channel of the ADC. See \ref ADC_StartReading() and \ref ADC_GetChannelReading(). */
+ #define ADC_1100MV_BANDGAP (0x1E << MUX0)
+
+ /** Retrieves the ADC MUX mask for the given ADC channel number.
+ *
+ * \attention This macro will only work correctly on channel numbers that are compile-time
+ * constants defined by the preprocessor.
+ *
+ * \param[in] Channel Index of the ADC channel whose MUX mask is to be retrieved.
+ */
+ #define ADC_GET_CHANNEL_MASK(Channel) CONCAT_EXPANDED(ADC_CHANNEL, Channel)
+ //@}
+
+ /* Inline Functions: */
+ /** Configures the given ADC channel, ready for ADC conversions. This function sets the
+ * associated port pin as an input and disables the digital portion of the I/O to reduce
+ * power consumption.
+ *
+ * \note This must only be called for ADC channels with are connected to a physical port
+ * pin of the AVR, denoted by its special alternative function ADCx.
+ *
+ * \warning The channel number must be specified as an integer, and <b>not</b> a \c ADC_CHANNEL* mask.
+ *
+ * \param[in] ChannelIndex ADC channel number to set up for conversions.
+ */
+ static inline void ADC_SetupChannel(const uint8_t ChannelIndex)
+ {
+ #if (defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || \
+ defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB647__))
+ DDRF &= ~(1 << ChannelIndex);
+ DIDR0 |= (1 << ChannelIndex);
+ #elif (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
+ if (ChannelIndex < 8)
+ {
+ DDRF &= ~(1 << ChannelIndex);
+ DIDR0 |= (1 << ChannelIndex);
+ }
+ else if (ChannelIndex == 8)
+ {
+ DDRD &= ~(1 << 4);
+ DIDR2 |= (1 << 0);
+ }
+ else if (ChannelIndex < 11)
+ {
+ DDRD &= ~(1 << (ChannelIndex - 3));
+ DIDR2 |= (1 << (ChannelIndex - 8));
+ }
+ else
+ {
+ DDRB &= ~(1 << (ChannelIndex - 7));
+ DIDR2 |= (1 << (ChannelIndex - 8));
+ }
+ #endif
+ }
+
+ /** De-configures the given ADC channel, re-enabling digital I/O mode instead of analog. This
+ * function sets the associated port pin as an input and re-enabled the digital portion of
+ * the I/O.
+ *
+ * \note This must only be called for ADC channels with are connected to a physical port
+ * pin of the AVR, denoted by its special alternative function ADCx.
+ *
+ * \warning The channel number must be specified as an integer, and <b>not</b> a \c ADC_CHANNEL* mask.
+ *
+ * \param[in] ChannelIndex ADC channel number to set up for conversions.
+ */
+ static inline void ADC_DisableChannel(const uint8_t ChannelIndex)
+ {
+ #if (defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || \
+ defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB647__))
+ DDRF &= ~(1 << ChannelIndex);
+ DIDR0 &= ~(1 << ChannelIndex);
+ #elif (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
+ if (ChannelIndex < 8)
+ {
+ DDRF &= ~(1 << ChannelIndex);
+ DIDR0 &= ~(1 << ChannelIndex);
+ }
+ else if (ChannelIndex == 8)
+ {
+ DDRD &= ~(1 << 4);
+ DIDR2 &= ~(1 << 0);
+ }
+ else if (ChannelIndex < 11)
+ {
+ DDRD &= ~(1 << (ChannelIndex - 3));
+ DIDR2 &= ~(1 << (ChannelIndex - 8));
+ }
+ else
+ {
+ DDRB &= ~(1 << (ChannelIndex - 7));
+ DIDR2 &= ~(1 << (ChannelIndex - 8));
+ }
+ #endif
+ }
+
+ /** Starts the reading of the given channel, but does not wait until the conversion has completed.
+ * Once executed, the conversion status can be determined via the \ref ADC_IsReadingComplete() macro and
+ * the result read via the \ref ADC_GetResult() macro.
+ *
+ * If the ADC has been initialized in free running mode, calling this function once will begin the repeated
+ * conversions. If the ADC is in single conversion mode (or the channel to convert from is to be changed),
+ * this function must be called each time a conversion is to take place.
+ *
+ * \param[in] MUXMask ADC channel mask, reference mask and adjustment mask.
+ */
+ static inline void ADC_StartReading(const uint16_t MUXMask)
+ {
+ ADMUX = MUXMask;
+
+ #if (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || defined(__DOXYGEN__))
+ if (MUXMask & (1 << 8))
+ ADCSRB |= (1 << MUX5);
+ else
+ ADCSRB &= ~(1 << MUX5);
+ #endif
+
+ ADCSRA |= (1 << ADSC);
+ }
+
+ /** Indicates if the current ADC conversion is completed, or still in progress.
+ *
+ * \return Boolean \c false if the reading is still taking place, or true if the conversion is
+ * complete and ready to be read out with \ref ADC_GetResult().
+ */
+ static inline bool ADC_IsReadingComplete(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool ADC_IsReadingComplete(void)
+ {
+ return ((ADCSRA & (1 << ADIF)) ? true : false);
+ }
+
+ /** Retrieves the conversion value of the last completed ADC conversion and clears the reading
+ * completion flag.
+ *
+ * \return The result of the last ADC conversion as an unsigned value.
+ */
+ static inline uint16_t ADC_GetResult(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint16_t ADC_GetResult(void)
+ {
+ ADCSRA |= (1 << ADIF);
+ return ADC;
+ }
+
+ /** Performs a complete single reading from channel, including a polling spin-loop to wait for the
+ * conversion to complete, and the returning of the converted value.
+ *
+ * \note For free running mode, the automated conversions should be initialized with a single call
+ * to \ref ADC_StartReading() to select the channel and begin the automated conversions, and
+ * the results read directly from the \ref ADC_GetResult() instead to reduce overhead.
+ *
+ * \param[in] MUXMask Mask comprising of an ADC channel mask, reference mask and adjustment mask.
+ *
+ * \return Converted ADC result for the given ADC channel.
+ */
+ static inline uint16_t ADC_GetChannelReading(const uint16_t MUXMask) ATTR_WARN_UNUSED_RESULT;
+ static inline uint16_t ADC_GetChannelReading(const uint16_t MUXMask)
+ {
+ ADC_StartReading(MUXMask);
+
+ while (!(ADC_IsReadingComplete()));
+
+ return ADC_GetResult();
+ }
+
+ /** Initializes the ADC, ready for conversions. This must be called before any other ADC operations.
+ * The "mode" parameter should be a mask comprised of a conversion mode (free running or single) and
+ * prescaler masks.
+ *
+ * \param[in] Mode Mask of ADC prescale and mode settings.
+ */
+ static inline void ADC_Init(const uint8_t Mode) ATTR_ALWAYS_INLINE;
+ static inline void ADC_Init(const uint8_t Mode)
+ {
+ ADCSRA = ((1 << ADEN) | Mode);
+ }
+
+ /** Turns off the ADC. If this is called, any further ADC operations will require a call to
+ * \ref ADC_Init() before the ADC can be used again.
+ */
+ static inline void ADC_Disable(void) ATTR_ALWAYS_INLINE;
+ static inline void ADC_Disable(void)
+ {
+ ADCSRA = 0;
+ }
+
+ /** Indicates if the ADC is currently enabled.
+ *
+ * \return Boolean \c true if the ADC subsystem is currently enabled, \c false otherwise.
+ */
+ static inline bool ADC_GetStatus(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool ADC_GetStatus(void)
+ {
+ return ((ADCSRA & (1 << ADEN)) ? true : false);
+ }
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/AVR8/SPI_AVR8.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/AVR8/SPI_AVR8.h
new file mode 100644
index 000000000..1b8f53e2b
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/AVR8/SPI_AVR8.h
@@ -0,0 +1,258 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief SPI Peripheral Driver (AVR8)
+ *
+ * On-chip SPI driver for the 8-bit AVR microcontrollers.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the SPI driver
+ * dispatch header located in LUFA/Drivers/Peripheral/SPI.h.
+ */
+
+/** \ingroup Group_SPI
+ * \defgroup Group_SPI_AVR8 SPI Peripheral Driver (AVR8)
+ *
+ * \section Sec_SPI_AVR8_ModDescription Module Description
+ * Driver for the hardware SPI port available on most 8-bit AVR microcontroller models. This
+ * module provides an easy to use driver for the setup and transfer of data over the
+ * AVR's SPI port.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the SPI driver
+ * dispatch header located in LUFA/Drivers/Peripheral/SPI.h.
+ *
+ * \section Sec_SPI_AVR8_ExampleUsage Example Usage
+ * The following snippet is an example of how this module may be used within a typical
+ * application.
+ *
+ * \code
+ * // Initialize the SPI driver before first use
+ * SPI_Init(SPI_SPEED_FCPU_DIV_2 | SPI_ORDER_MSB_FIRST | SPI_SCK_LEAD_FALLING |
+ * SPI_SAMPLE_TRAILING | SPI_MODE_MASTER);
+ *
+ * // Send several bytes, ignoring the returned data
+ * SPI_SendByte(0x01);
+ * SPI_SendByte(0x02);
+ * SPI_SendByte(0x03);
+ *
+ * // Receive several bytes, sending a dummy 0x00 byte each time
+ * uint8_t Byte1 = SPI_ReceiveByte();
+ * uint8_t Byte2 = SPI_ReceiveByte();
+ * uint8_t Byte3 = SPI_ReceiveByte();
+ *
+ * // Send a byte, and store the received byte from the same transaction
+ * uint8_t ResponseByte = SPI_TransferByte(0xDC);
+ * \endcode
+ *
+ * @{
+ */
+
+#ifndef __SPI_AVR8_H__
+#define __SPI_AVR8_H__
+
+ /* Includes: */
+ #include "../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_SPI_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Peripheral/SPI.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define SPI_USE_DOUBLESPEED (1 << SPE)
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** \name SPI Prescaler Configuration Masks */
+ //@{
+ /** SPI prescaler mask for \ref SPI_Init(). Divides the system clock by a factor of 2. */
+ #define SPI_SPEED_FCPU_DIV_2 SPI_USE_DOUBLESPEED
+
+ /** SPI prescaler mask for \ref SPI_Init(). Divides the system clock by a factor of 4. */
+ #define SPI_SPEED_FCPU_DIV_4 0
+
+ /** SPI prescaler mask for \ref SPI_Init(). Divides the system clock by a factor of 8. */
+ #define SPI_SPEED_FCPU_DIV_8 (SPI_USE_DOUBLESPEED | (1 << SPR0))
+
+ /** SPI prescaler mask for \ref SPI_Init(). Divides the system clock by a factor of 16. */
+ #define SPI_SPEED_FCPU_DIV_16 (1 << SPR0)
+
+ /** SPI prescaler mask for \ref SPI_Init(). Divides the system clock by a factor of 32. */
+ #define SPI_SPEED_FCPU_DIV_32 (SPI_USE_DOUBLESPEED | (1 << SPR1))
+
+ /** SPI prescaler mask for \ref SPI_Init(). Divides the system clock by a factor of 64. */
+ #define SPI_SPEED_FCPU_DIV_64 (SPI_USE_DOUBLESPEED | (1 << SPR1) | (1 << SPR0))
+
+ /** SPI prescaler mask for \ref SPI_Init(). Divides the system clock by a factor of 128. */
+ #define SPI_SPEED_FCPU_DIV_128 ((1 << SPR1) | (1 << SPR0))
+ //@}
+
+ /** \name SPI SCK Polarity Configuration Masks */
+ //@{
+ /** SPI clock polarity mask for \ref SPI_Init(). Indicates that the SCK should lead on the rising edge. */
+ #define SPI_SCK_LEAD_RISING (0 << CPOL)
+
+ /** SPI clock polarity mask for \ref SPI_Init(). Indicates that the SCK should lead on the falling edge. */
+ #define SPI_SCK_LEAD_FALLING (1 << CPOL)
+ //@}
+
+ /** \name SPI Sample Edge Configuration Masks */
+ //@{
+ /** SPI data sample mode mask for \ref SPI_Init(). Indicates that the data should sampled on the leading edge. */
+ #define SPI_SAMPLE_LEADING (0 << CPHA)
+
+ /** SPI data sample mode mask for \ref SPI_Init(). Indicates that the data should be sampled on the trailing edge. */
+ #define SPI_SAMPLE_TRAILING (1 << CPHA)
+ //@}
+
+ /** \name SPI Data Ordering Configuration Masks */
+ //@{
+ /** SPI data order mask for \ref SPI_Init(). Indicates that data should be shifted out MSB first. */
+ #define SPI_ORDER_MSB_FIRST (0 << DORD)
+
+ /** SPI data order mask for \ref SPI_Init(). Indicates that data should be shifted out LSB first. */
+ #define SPI_ORDER_LSB_FIRST (1 << DORD)
+ //@}
+
+ /** \name SPI Mode Configuration Masks */
+ //@{
+ /** SPI mode mask for \ref SPI_Init(). Indicates that the SPI interface should be initialized into slave mode. */
+ #define SPI_MODE_SLAVE (0 << MSTR)
+
+ /** SPI mode mask for \ref SPI_Init(). Indicates that the SPI interface should be initialized into master mode. */
+ #define SPI_MODE_MASTER (1 << MSTR)
+ //@}
+
+ /* Inline Functions: */
+ /** Initializes the SPI subsystem, ready for transfers. Must be called before calling any other
+ * SPI routines.
+ *
+ * \param[in] SPIOptions SPI Options, a mask consisting of one of each of the \c SPI_SPEED_*,
+ * \c SPI_SCK_*, \c SPI_SAMPLE_*, \c SPI_ORDER_* and \c SPI_MODE_* masks.
+ */
+ static inline void SPI_Init(const uint8_t SPIOptions);
+ static inline void SPI_Init(const uint8_t SPIOptions)
+ {
+ /* Prevent high rise times on PB.0 (/SS) from forcing a change to SPI slave mode */
+ DDRB |= (1 << 0);
+ PORTB |= (1 << 0);
+
+ DDRB |= ((1 << 1) | (1 << 2));
+ DDRB &= ~(1 << 3);
+ PORTB |= (1 << 3);
+
+ if (SPIOptions & SPI_USE_DOUBLESPEED)
+ SPSR |= (1 << SPI2X);
+ else
+ SPSR &= ~(1 << SPI2X);
+
+ /* Switch /SS to input mode after configuration to allow for forced mode changes */
+ DDRB &= ~(1 << 0);
+
+ SPCR = ((1 << SPE) | SPIOptions);
+ }
+
+ /** Turns off the SPI driver, disabling and returning used hardware to their default configuration. */
+ static inline void SPI_Disable(void);
+ static inline void SPI_Disable(void)
+ {
+ DDRB &= ~((1 << 1) | (1 << 2));
+ PORTB &= ~((1 << 0) | (1 << 3));
+
+ SPCR = 0;
+ SPSR = 0;
+ }
+
+ /** Retrieves the currently selected SPI mode, once the SPI interface has been configured.
+ *
+ * \return \ref SPI_MODE_MASTER if the interface is currently in SPI Master mode, \ref SPI_MODE_SLAVE otherwise
+ */
+ static inline uint8_t SPI_GetCurrentMode(void) ATTR_ALWAYS_INLINE;
+ static inline uint8_t SPI_GetCurrentMode(void)
+ {
+ return (SPCR & SPI_MODE_MASTER);
+ }
+
+ /** Sends and receives a byte through the SPI interface, blocking until the transfer is complete.
+ *
+ * \param[in] Byte Byte to send through the SPI interface.
+ *
+ * \return Response byte from the attached SPI device.
+ */
+ static inline uint8_t SPI_TransferByte(const uint8_t Byte) ATTR_ALWAYS_INLINE;
+ static inline uint8_t SPI_TransferByte(const uint8_t Byte)
+ {
+ SPDR = Byte;
+ while (!(SPSR & (1 << SPIF)));
+ return SPDR;
+ }
+
+ /** Sends a byte through the SPI interface, blocking until the transfer is complete. The response
+ * byte sent to from the attached SPI device is ignored.
+ *
+ * \param[in] Byte Byte to send through the SPI interface.
+ */
+ static inline void SPI_SendByte(const uint8_t Byte) ATTR_ALWAYS_INLINE;
+ static inline void SPI_SendByte(const uint8_t Byte)
+ {
+ SPDR = Byte;
+ while (!(SPSR & (1 << SPIF)));
+ }
+
+ /** Sends a dummy byte through the SPI interface, blocking until the transfer is complete. The response
+ * byte from the attached SPI device is returned.
+ *
+ * \return The response byte from the attached SPI device.
+ */
+ static inline uint8_t SPI_ReceiveByte(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t SPI_ReceiveByte(void)
+ {
+ SPDR = 0x00;
+ while (!(SPSR & (1 << SPIF)));
+ return SPDR;
+ }
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/AVR8/SerialSPI_AVR8.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/AVR8/SerialSPI_AVR8.h
new file mode 100644
index 000000000..8d58369a1
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/AVR8/SerialSPI_AVR8.h
@@ -0,0 +1,208 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Master SPI Mode Serial USART Peripheral Driver (XMEGA)
+ *
+ * On-chip Master SPI mode USART driver for the XMEGA AVR microcontrollers.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the SPI Master
+ * Mode USART driver dispatch header located in LUFA/Drivers/Peripheral/Serial.h.
+ */
+
+/** \ingroup Group_SerialSPI
+ * \defgroup Group_SerialSPI_AVR8 Master SPI Mode Serial USART Peripheral Driver (AVR8)
+ *
+ * \section Sec_SerialSPI_AVR8_ModDescription Module Description
+ * On-chip serial USART driver for the 8-bit AVR8 microcontrollers.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the SPI Master
+ * driver dispatch header located in LUFA/Drivers/Peripheral/SerialSPI.h.
+ *
+ * \section Sec_SerialSPI_AVR8_ExampleUsage Example Usage
+ * The following snippet is an example of how this module may be used within a typical
+ * application.
+ *
+ * \code
+ * // Initialize the Master SPI mode USART driver before first use, with 1Mbit baud
+ * SerialSPI_Init((USART_SPI_SCK_LEAD_RISING | USART_SPI_SAMPLE_LEADING | USART_SPI_ORDER_MSB_FIRST), 1000000);
+ *
+ * // Send several bytes, ignoring the returned data
+ * SerialSPI_SendByte(0x01);
+ * SerialSPI_SendByte(0x02);
+ * SerialSPI_SendByte(0x03);
+ *
+ * // Receive several bytes, sending a dummy 0x00 byte each time
+ * uint8_t Byte1 = SerialSPI_ReceiveByte();
+ * uint8_t Byte2 = SerialSPI_ReceiveByte();
+ * uint8_t Byte3 = SerialSPI_ReceiveByte();
+ *
+ * // Send a byte, and store the received byte from the same transaction
+ * uint8_t ResponseByte = SerialSPI_TransferByte(0xDC);
+ * \endcode
+ *
+ * @{
+ */
+
+#ifndef __SERIAL_SPI_AVR8_H__
+#define __SERIAL_SPI_AVR8_H__
+
+ /* Includes: */
+ #include "../../../Common/Common.h"
+
+ #include <stdio.h>
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_SERIAL_SPI_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Peripheral/Serial.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ #define SERIAL_SPI_UBBRVAL(Baud) ((Baud < (F_CPU / 2)) ? ((F_CPU / (2 * Baud)) - 1) : 0)
+
+ /* Master USART SPI mode flag definitions missing in the AVR8 toolchain */
+ #if !defined(UCPHA1)
+ #define UCPHA1 1
+ #endif
+ #if !defined(UDORD1)
+ #define UDORD1 2
+ #endif
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** \name SPI SCK Polarity Configuration Masks */
+ //@{
+ /** SPI clock polarity mask for \ref SPI_Init(). Indicates that the SCK should lead on the rising edge. */
+ #define USART_SPI_SCK_LEAD_RISING (0 << UCPOL1)
+
+ /** SPI clock polarity mask for \ref SPI_Init(). Indicates that the SCK should lead on the falling edge. */
+ #define USART_SPI_SCK_LEAD_FALLING (1 << UCPOL1)
+ //@}
+
+ /** \name SPI Sample Edge Configuration Masks */
+ //@{
+ /** SPI data sample mode mask for \ref SerialSPI_Init(). Indicates that the data should sampled on the leading edge. */
+ #define USART_SPI_SAMPLE_LEADING (0 << UCPHA1)
+
+ /** SPI data sample mode mask for \ref SerialSPI_Init(). Indicates that the data should be sampled on the trailing edge. */
+ #define USART_SPI_SAMPLE_TRAILING (1 << UCPHA1)
+ //@}
+
+ /** \name SPI Data Ordering Configuration Masks */
+ //@{
+ /** SPI data order mask for \ref SerialSPI_Init(). Indicates that data should be shifted out MSB first. */
+ #define USART_SPI_ORDER_MSB_FIRST (0 << UDORD1)
+
+ /** SPI data order mask for \ref SerialSPI_Init(). Indicates that data should be shifted out LSB first. */
+ #define USART_SPI_ORDER_LSB_FIRST (1 << UDORD1)
+ //@}
+
+ /* Inline Functions: */
+ /** Initialize the USART module in Master SPI mode.
+ *
+ * \param[in] SPIOptions USART SPI Options, a mask consisting of one of each of the \c USART_SPI_SCK_*,
+ * \c USART_SPI_SAMPLE_* and \c USART_SPI_ORDER_* masks.
+ * \param[in] BaudRate SPI baud rate, in bits per second.
+ */
+ static inline void SerialSPI_Init(const uint8_t SPIOptions,
+ const uint32_t BaudRate)
+ {
+ DDRD |= ((1 << 3) | (1 << 5));
+ PORTD |= (1 << 2);
+
+ UCSR1C = ((1 << UMSEL11) | (1 << UMSEL10) | SPIOptions);
+ UCSR1B = ((1 << TXEN1) | (1 << RXEN1));
+
+ UBRR1 = SERIAL_SPI_UBBRVAL(BaudRate);
+ }
+
+ /** Turns off the USART driver, disabling and returning used hardware to their default configuration. */
+ static inline void SerialSPI_Disable(void)
+ {
+ UCSR1B = 0;
+ UCSR1A = 0;
+ UCSR1C = 0;
+
+ UBRR1 = 0;
+
+ DDRD &= ~((1 << 3) | (1 << 5));
+ PORTD &= ~(1 << 2);
+ }
+
+ /** Sends and receives a byte through the USART SPI interface, blocking until the transfer is complete.
+ *
+ * \param[in] DataByte Byte to send through the USART SPI interface.
+ *
+ * \return Response byte from the attached SPI device.
+ */
+ static inline uint8_t SerialSPI_TransferByte(const uint8_t DataByte)
+ {
+ UDR1 = DataByte;
+ while (!(UCSR1A & (1 << TXC1)));
+ UCSR1A = (1 << TXC1);
+ return UDR1;
+ }
+
+ /** Sends a byte through the USART SPI interface, blocking until the transfer is complete. The response
+ * byte sent to from the attached SPI device is ignored.
+ *
+ * \param[in] DataByte Byte to send through the USART SPI interface.
+ */
+ static inline void SerialSPI_SendByte(const uint8_t DataByte)
+ {
+ SerialSPI_TransferByte(DataByte);
+ }
+
+ /** Sends a dummy byte through the USART SPI interface, blocking until the transfer is complete. The response
+ * byte from the attached SPI device is returned.
+ *
+ * \return The response byte from the attached SPI device.
+ */
+ static inline uint8_t SerialSPI_ReceiveByte(void)
+ {
+ return SerialSPI_TransferByte(0);
+ }
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/AVR8/Serial_AVR8.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/AVR8/Serial_AVR8.c
new file mode 100644
index 000000000..8785a4b6d
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/AVR8/Serial_AVR8.c
@@ -0,0 +1,119 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "../../../Common/Common.h"
+#if (ARCH == ARCH_AVR8)
+
+#define __INCLUDE_FROM_SERIAL_C
+#include "../Serial.h"
+
+FILE USARTSerialStream;
+
+int Serial_putchar(char DataByte,
+ FILE *Stream)
+{
+ (void)Stream;
+
+ Serial_SendByte(DataByte);
+ return 0;
+}
+
+int Serial_getchar(FILE *Stream)
+{
+ (void)Stream;
+
+ if (!(Serial_IsCharReceived()))
+ return _FDEV_EOF;
+
+ return Serial_ReceiveByte();
+}
+
+int Serial_getchar_Blocking(FILE *Stream)
+{
+ (void)Stream;
+
+ while (!(Serial_IsCharReceived()));
+ return Serial_ReceiveByte();
+}
+
+void Serial_SendString_P(const char* FlashStringPtr)
+{
+ uint8_t CurrByte;
+
+ while ((CurrByte = pgm_read_byte(FlashStringPtr)) != 0x00)
+ {
+ Serial_SendByte(CurrByte);
+ FlashStringPtr++;
+ }
+}
+
+void Serial_SendString(const char* StringPtr)
+{
+ uint8_t CurrByte;
+
+ while ((CurrByte = *StringPtr) != 0x00)
+ {
+ Serial_SendByte(CurrByte);
+ StringPtr++;
+ }
+}
+
+void Serial_SendData(const void* Buffer,
+ uint16_t Length)
+{
+ while (Length--)
+ Serial_SendByte(*((uint8_t*)Buffer++));
+}
+
+void Serial_CreateStream(FILE* Stream)
+{
+ if (!(Stream))
+ {
+ Stream = &USARTSerialStream;
+ stdin = Stream;
+ stdout = Stream;
+ }
+
+ *Stream = (FILE)FDEV_SETUP_STREAM(Serial_putchar, Serial_getchar, _FDEV_SETUP_RW);
+}
+
+void Serial_CreateBlockingStream(FILE* Stream)
+{
+ if (!(Stream))
+ {
+ Stream = &USARTSerialStream;
+ stdin = Stream;
+ stdout = Stream;
+ }
+
+ *Stream = (FILE)FDEV_SETUP_STREAM(Serial_putchar, Serial_getchar_Blocking, _FDEV_SETUP_RW);
+}
+
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/AVR8/Serial_AVR8.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/AVR8/Serial_AVR8.h
new file mode 100644
index 000000000..e8860a511
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/AVR8/Serial_AVR8.h
@@ -0,0 +1,270 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Serial USART Peripheral Driver (AVR8)
+ *
+ * On-chip serial USART driver for the 8-bit AVR microcontrollers.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USART driver
+ * dispatch header located in LUFA/Drivers/Peripheral/Serial.h.
+ */
+
+/** \ingroup Group_Serial
+ * \defgroup Group_Serial_AVR8 Serial USART Peripheral Driver (AVR8)
+ *
+ * \section Sec_Serial_AVR8_ModDescription Module Description
+ * On-chip serial USART driver for the 8-bit AVR microcontrollers.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USART driver
+ * dispatch header located in LUFA/Drivers/Peripheral/Serial.h.
+ *
+ * \section Sec_Serial_AVR8_ExampleUsage Example Usage
+ * The following snippet is an example of how this module may be used within a typical
+ * application.
+ *
+ * \code
+ * // Initialize the serial USART driver before first use, with 9600 baud (and no double-speed mode)
+ * Serial_Init(9600, false);
+ *
+ * // Send a string through the USART
+ * Serial_SendString("Test String\r\n");
+ *
+ * // Send a raw byte through the USART
+ * Serial_SendByte(0xDC);
+ *
+ * // Receive a byte through the USART (or -1 if no data received)
+ * int16_t DataByte = Serial_ReceiveByte();
+ * \endcode
+ *
+ * @{
+ */
+
+#ifndef __SERIAL_AVR8_H__
+#define __SERIAL_AVR8_H__
+
+ /* Includes: */
+ #include "../../../Common/Common.h"
+ #include "../../Misc/TerminalCodes.h"
+
+ #include <stdio.h>
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_SERIAL_H) && !defined(__INCLUDE_FROM_SERIAL_C)
+ #error Do not include this file directly. Include LUFA/Drivers/Peripheral/Serial.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* External Variables: */
+ extern FILE USARTSerialStream;
+
+ /* Function Prototypes: */
+ int Serial_putchar(char DataByte,
+ FILE *Stream);
+ int Serial_getchar(FILE *Stream);
+ int Serial_getchar_Blocking(FILE *Stream);
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Macro for calculating the baud value from a given baud rate when the \c U2X (double speed) bit is
+ * not set.
+ *
+ * \param[in] Baud Target serial UART baud rate.
+ *
+ * \return Closest UBRR register value for the given UART frequency.
+ */
+ #define SERIAL_UBBRVAL(Baud) ((((F_CPU / 16) + (Baud / 2)) / (Baud)) - 1)
+
+ /** Macro for calculating the baud value from a given baud rate when the \c U2X (double speed) bit is
+ * set.
+ *
+ * \param[in] Baud Target serial UART baud rate.
+ *
+ * \return Closest UBRR register value for the given UART frequency.
+ */
+ #define SERIAL_2X_UBBRVAL(Baud) ((((F_CPU / 8) + (Baud / 2)) / (Baud)) - 1)
+
+ /* Function Prototypes: */
+ /** Transmits a given NUL terminated string located in program space (FLASH) through the USART.
+ *
+ * \param[in] FlashStringPtr Pointer to a string located in program space.
+ */
+ void Serial_SendString_P(const char* FlashStringPtr) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Transmits a given NUL terminated string located in SRAM memory through the USART.
+ *
+ * \param[in] StringPtr Pointer to a string located in SRAM space.
+ */
+ void Serial_SendString(const char* StringPtr) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Transmits a given buffer located in SRAM memory through the USART.
+ *
+ * \param[in] Buffer Pointer to a buffer containing the data to send.
+ * \param[in] Length Length of the data to send, in bytes.
+ */
+ void Serial_SendData(const void* Buffer, uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Creates a standard character stream from the USART so that it can be used with all the regular functions
+ * in the avr-libc \c <stdio.h> library that accept a \c FILE stream as a destination (e.g. \c fprintf). The created
+ * stream is bidirectional and can be used for both input and output functions.
+ *
+ * Reading data from this stream is non-blocking, i.e. in most instances, complete strings cannot be read in by a single
+ * fetch, as the endpoint will not be ready at some point in the transmission, aborting the transfer. However, this may
+ * be used when the read data is processed byte-per-bye (via \c getc()) or when the user application will implement its own
+ * line buffering.
+ *
+ * \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed, if \c NULL, \c stdout
+ * and \c stdin will be configured to use the USART.
+ *
+ * \pre The USART must first be configured via a call to \ref Serial_Init() before the stream is used.
+ */
+ void Serial_CreateStream(FILE* Stream);
+
+ /** Identical to \ref Serial_CreateStream(), except that reads are blocking until the calling stream function terminates
+ * the transfer.
+ *
+ * \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed, if \c NULL, \c stdout
+ * and \c stdin will be configured to use the USART.
+ *
+ * \pre The USART must first be configured via a call to \ref Serial_Init() before the stream is used.
+ */
+ void Serial_CreateBlockingStream(FILE* Stream);
+
+ /* Inline Functions: */
+ /** Initializes the USART, ready for serial data transmission and reception. This initializes the interface to
+ * standard 8-bit, no parity, 1 stop bit settings suitable for most applications.
+ *
+ * \param[in] BaudRate Serial baud rate, in bits per second.
+ * \param[in] DoubleSpeed Enables double speed mode when set, halving the sample time to double the baud rate.
+ */
+ static inline void Serial_Init(const uint32_t BaudRate,
+ const bool DoubleSpeed);
+ static inline void Serial_Init(const uint32_t BaudRate,
+ const bool DoubleSpeed)
+ {
+ UBRR1 = (DoubleSpeed ? SERIAL_2X_UBBRVAL(BaudRate) : SERIAL_UBBRVAL(BaudRate));
+
+ UCSR1C = ((1 << UCSZ11) | (1 << UCSZ10));
+ UCSR1A = (DoubleSpeed ? (1 << U2X1) : 0);
+ UCSR1B = ((1 << TXEN1) | (1 << RXEN1));
+
+ DDRD |= (1 << 3);
+ PORTD |= (1 << 2);
+ }
+
+ /** Turns off the USART driver, disabling and returning used hardware to their default configuration. */
+ static inline void Serial_Disable(void);
+ static inline void Serial_Disable(void)
+ {
+ UCSR1B = 0;
+ UCSR1A = 0;
+ UCSR1C = 0;
+
+ UBRR1 = 0;
+
+ DDRD &= ~(1 << 3);
+ PORTD &= ~(1 << 2);
+ }
+
+ /** Indicates whether a character has been received through the USART.
+ *
+ * \return Boolean \c true if a character has been received, \c false otherwise.
+ */
+ static inline bool Serial_IsCharReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Serial_IsCharReceived(void)
+ {
+ return ((UCSR1A & (1 << RXC1)) ? true : false);
+ }
+
+ /** Indicates whether there is hardware buffer space for a new transmit on the USART. This
+ * function can be used to determine if a call to \ref Serial_SendByte() will block in advance.
+ *
+ * \return Boolean \c true if a character can be queued for transmission immediately, \c false otherwise.
+ */
+ static inline bool Serial_IsSendReady(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Serial_IsSendReady(void)
+ {
+ return ((UCSR1A & (1 << UDRE1)) ? true : false);
+ }
+
+ /** Indicates whether the hardware USART transmit buffer is completely empty, indicating all
+ * pending transmissions have completed.
+ *
+ * \return Boolean \c true if no characters are buffered for transmission, \c false otherwise.
+ */
+ static inline bool Serial_IsSendComplete(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Serial_IsSendComplete(void)
+ {
+ return ((UCSR1A & (1 << TXC1)) ? true : false);
+ }
+
+ /** Transmits a given byte through the USART.
+ *
+ * \note If no buffer space is available in the hardware USART, this function will block. To check if
+ * space is available before calling this function, see \ref Serial_IsSendReady().
+ *
+ * \param[in] DataByte Byte to transmit through the USART.
+ */
+ static inline void Serial_SendByte(const char DataByte) ATTR_ALWAYS_INLINE;
+ static inline void Serial_SendByte(const char DataByte)
+ {
+ while (!(Serial_IsSendReady()));
+ UDR1 = DataByte;
+ }
+
+ /** Receives the next byte from the USART.
+ *
+ * \return Next byte received from the USART, or a negative value if no byte has been received.
+ */
+ static inline int16_t Serial_ReceiveByte(void) ATTR_ALWAYS_INLINE;
+ static inline int16_t Serial_ReceiveByte(void)
+ {
+ if (!(Serial_IsCharReceived()))
+ return -1;
+
+ return UDR1;
+ }
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.c
new file mode 100644
index 000000000..2a6c160e8
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.c
@@ -0,0 +1,209 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "../../../Common/Common.h"
+#if (ARCH == ARCH_AVR8) && defined(TWCR)
+
+#define __INCLUDE_FROM_TWI_C
+#include "../TWI.h"
+
+uint8_t TWI_StartTransmission(const uint8_t SlaveAddress,
+ const uint8_t TimeoutMS)
+{
+ for (;;)
+ {
+ bool BusCaptured = false;
+ uint16_t TimeoutRemaining;
+
+ TWCR = ((1 << TWINT) | (1 << TWSTA) | (1 << TWEN));
+
+ TimeoutRemaining = (TimeoutMS * 100);
+ while (TimeoutRemaining && !(BusCaptured))
+ {
+ if (TWCR & (1 << TWINT))
+ {
+ switch (TWSR & TW_STATUS_MASK)
+ {
+ case TW_START:
+ case TW_REP_START:
+ BusCaptured = true;
+ break;
+ case TW_MT_ARB_LOST:
+ TWCR = ((1 << TWINT) | (1 << TWSTA) | (1 << TWEN));
+ continue;
+ default:
+ TWCR = (1 << TWEN);
+ return TWI_ERROR_BusFault;
+ }
+ }
+
+ _delay_us(10);
+ TimeoutRemaining--;
+ }
+
+ if (!(TimeoutRemaining))
+ {
+ TWCR = (1 << TWEN);
+ return TWI_ERROR_BusCaptureTimeout;
+ }
+
+ TWDR = SlaveAddress;
+ TWCR = ((1 << TWINT) | (1 << TWEN));
+
+ TimeoutRemaining = (TimeoutMS * 100);
+ while (TimeoutRemaining)
+ {
+ if (TWCR & (1 << TWINT))
+ break;
+
+ _delay_us(10);
+ TimeoutRemaining--;
+ }
+
+ if (!(TimeoutRemaining))
+ return TWI_ERROR_SlaveResponseTimeout;
+
+ switch (TWSR & TW_STATUS_MASK)
+ {
+ case TW_MT_SLA_ACK:
+ case TW_MR_SLA_ACK:
+ return TWI_ERROR_NoError;
+ default:
+ TWCR = ((1 << TWINT) | (1 << TWSTO) | (1 << TWEN));
+ return TWI_ERROR_SlaveNotReady;
+ }
+ }
+}
+
+bool TWI_SendByte(const uint8_t Byte)
+{
+ TWDR = Byte;
+ TWCR = ((1 << TWINT) | (1 << TWEN));
+ while (!(TWCR & (1 << TWINT)));
+
+ return ((TWSR & TW_STATUS_MASK) == TW_MT_DATA_ACK);
+}
+
+bool TWI_ReceiveByte(uint8_t* const Byte,
+ const bool LastByte)
+{
+ uint8_t TWCRMask;
+
+ if (LastByte)
+ TWCRMask = ((1 << TWINT) | (1 << TWEN));
+ else
+ TWCRMask = ((1 << TWINT) | (1 << TWEN) | (1 << TWEA));
+
+ TWCR = TWCRMask;
+ while (!(TWCR & (1 << TWINT)));
+ *Byte = TWDR;
+
+ uint8_t Status = (TWSR & TW_STATUS_MASK);
+
+ return ((LastByte) ? (Status == TW_MR_DATA_NACK) : (Status == TW_MR_DATA_ACK));
+}
+
+uint8_t TWI_ReadPacket(const uint8_t SlaveAddress,
+ const uint8_t TimeoutMS,
+ const uint8_t* InternalAddress,
+ uint8_t InternalAddressLen,
+ uint8_t* Buffer,
+ uint8_t Length)
+{
+ uint8_t ErrorCode;
+
+ if ((ErrorCode = TWI_StartTransmission((SlaveAddress & TWI_DEVICE_ADDRESS_MASK) | TWI_ADDRESS_WRITE,
+ TimeoutMS)) == TWI_ERROR_NoError)
+ {
+ while (InternalAddressLen--)
+ {
+ if (!(TWI_SendByte(*(InternalAddress++))))
+ {
+ ErrorCode = TWI_ERROR_SlaveNAK;
+ break;
+ }
+ }
+
+ if ((ErrorCode = TWI_StartTransmission((SlaveAddress & TWI_DEVICE_ADDRESS_MASK) | TWI_ADDRESS_READ,
+ TimeoutMS)) == TWI_ERROR_NoError)
+ {
+ while (Length--)
+ {
+ if (!(TWI_ReceiveByte(Buffer++, (Length == 0))))
+ {
+ ErrorCode = TWI_ERROR_SlaveNAK;
+ break;
+ }
+ }
+
+ TWI_StopTransmission();
+ }
+ }
+
+ return ErrorCode;
+}
+
+uint8_t TWI_WritePacket(const uint8_t SlaveAddress,
+ const uint8_t TimeoutMS,
+ const uint8_t* InternalAddress,
+ uint8_t InternalAddressLen,
+ const uint8_t* Buffer,
+ uint8_t Length)
+{
+ uint8_t ErrorCode;
+
+ if ((ErrorCode = TWI_StartTransmission((SlaveAddress & TWI_DEVICE_ADDRESS_MASK) | TWI_ADDRESS_WRITE,
+ TimeoutMS)) == TWI_ERROR_NoError)
+ {
+ while (InternalAddressLen--)
+ {
+ if (!(TWI_SendByte(*(InternalAddress++))))
+ {
+ ErrorCode = TWI_ERROR_SlaveNAK;
+ break;
+ }
+ }
+
+ while (Length--)
+ {
+ if (!(TWI_SendByte(*(Buffer++))))
+ {
+ ErrorCode = TWI_ERROR_SlaveNAK;
+ break;
+ }
+ }
+
+ TWI_StopTransmission();
+ }
+
+ return ErrorCode;
+}
+
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.h
new file mode 100644
index 000000000..584b584fe
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.h
@@ -0,0 +1,305 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief TWI Peripheral Driver (AVR8)
+ *
+ * On-chip TWI driver for the 8-bit AVR microcontrollers.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the TWI driver
+ * dispatch header located in LUFA/Drivers/Peripheral/TWI.h.
+ */
+
+/** \ingroup Group_TWI
+ * \defgroup Group_TWI_AVR8 TWI Peripheral Driver (AVR8)
+ *
+ * \section Sec_TWI_AVR8_ModDescription Module Description
+ * Master mode TWI driver for the 8-bit AVR microcontrollers which contain a hardware TWI module.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the TWI driver
+ * dispatch header located in LUFA/Drivers/Peripheral/TWI.h.
+ *
+ * \section Sec_TWI_AVR8_ExampleUsage Example Usage
+ * The following snippet is an example of how this module may be used within a typical
+ * application.
+ *
+ * <b>Low Level API Example:</b>
+ * \code
+ * // Initialize the TWI driver before first use at 200KHz
+ * TWI_Init(TWI_BIT_PRESCALE_1, TWI_BITLENGTH_FROM_FREQ(1, 200000));
+ *
+ * // Start a write session to device at device address 0xA0, internal address 0xDC with a 10ms timeout
+ * if (TWI_StartTransmission(0xA0 | TWI_ADDRESS_WRITE, 10) == TWI_ERROR_NoError)
+ * {
+ * TWI_SendByte(0xDC);
+ *
+ * TWI_SendByte(0x01);
+ * TWI_SendByte(0x02);
+ * TWI_SendByte(0x03);
+ *
+ * // Must stop transmission afterwards to release the bus
+ * TWI_StopTransmission();
+ * }
+ *
+ * // Start a read session to device at address 0xA0, internal address 0xDC with a 10ms timeout
+ * if (TWI_StartTransmission(0xA0 | TWI_ADDRESS_WRITE, 10) == TWI_ERROR_NoError)
+ * {
+ * TWI_SendByte(0xDC);
+ * TWI_StopTransmission();
+ *
+ * if (TWI_StartTransmission(0xA0 | TWI_ADDRESS_READ, 10) == TWI_ERROR_NoError)
+ * {
+ * uint8_t Byte1, Byte2, Byte3;
+ *
+ * // Read three bytes, acknowledge after the third byte is received
+ * TWI_ReceiveByte(&Byte1, false);
+ * TWI_ReceiveByte(&Byte2, false);
+ * TWI_ReceiveByte(&Byte3, true);
+ *
+ * // Must stop transmission afterwards to release the bus
+ * TWI_StopTransmission();
+ * }
+ * }
+ * \endcode
+ *
+ * <b>High Level API Example:</b>
+ * \code
+ * // Initialize the TWI driver before first use at 200KHz
+ * TWI_Init(TWI_BIT_PRESCALE_1, TWI_BITLENGTH_FROM_FREQ(1, 200000));
+ *
+ * // Start a write session to device at device address 0xA0, internal address 0xDC with a 10ms timeout
+ * uint8_t InternalWriteAddress = 0xDC;
+ * uint8_t WritePacket[3] = {0x01, 0x02, 0x03};
+ *
+ * TWI_WritePacket(0xA0, 10, &InternalWriteAddress, sizeof(InternalWriteAddress),
+ * &WritePacket, sizeof(WritePacket);
+ *
+ * // Start a read session to device at address 0xA0, internal address 0xDC with a 10ms timeout
+ * uint8_t InternalReadAddress = 0xDC;
+ * uint8_t ReadPacket[3];
+ *
+ * TWI_ReadPacket(0xA0, 10, &InternalReadAddress, sizeof(InternalReadAddress),
+ * &ReadPacket, sizeof(ReadPacket);
+ * \endcode
+ *
+ * @{
+ */
+
+#ifndef __TWI_AVR8_H__
+#define __TWI_AVR8_H__
+
+ /* Includes: */
+ #include "../../../Common/Common.h"
+
+ #include <stdio.h>
+ #include <util/twi.h>
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_TWI_H) && !defined(__INCLUDE_FROM_TWI_C)
+ #error Do not include this file directly. Include LUFA/Drivers/Peripheral/TWI.h instead.
+ #endif
+
+ #if !(defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || \
+ defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB647__) || \
+ defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
+ #error The TWI peripheral driver is not currently available for your selected microcontroller model.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** TWI slave device address mask for a read session. Mask with a slave device base address to obtain
+ * the correct TWI bus address for the slave device when reading data from it.
+ */
+ #define TWI_ADDRESS_READ 0x01
+
+ /** TWI slave device address mask for a write session. Mask with a slave device base address to obtain
+ * the correct TWI bus address for the slave device when writing data to it.
+ */
+ #define TWI_ADDRESS_WRITE 0x00
+
+ /** Mask to retrieve the base address for a TWI device, which can then be ORed with \ref TWI_ADDRESS_READ
+ * or \ref TWI_ADDRESS_WRITE to obtain the device's read and write address respectively.
+ */
+ #define TWI_DEVICE_ADDRESS_MASK 0xFE
+
+ /** Bit length prescaler for \ref TWI_Init(). This mask multiplies the TWI bit length prescaler by 1. */
+ #define TWI_BIT_PRESCALE_1 ((0 << TWPS1) | (0 << TWPS0))
+
+ /** Bit length prescaler for \ref TWI_Init(). This mask multiplies the TWI bit length prescaler by 4. */
+ #define TWI_BIT_PRESCALE_4 ((0 << TWPS1) | (1 << TWPS0))
+
+ /** Bit length prescaler for \ref TWI_Init(). This mask multiplies the TWI bit length prescaler by 16. */
+ #define TWI_BIT_PRESCALE_16 ((1 << TWPS1) | (0 << TWPS0))
+
+ /** Bit length prescaler for \ref TWI_Init(). This mask multiplies the TWI bit length prescaler by 64. */
+ #define TWI_BIT_PRESCALE_64 ((1 << TWPS1) | (1 << TWPS0))
+
+ /** Calculates the length of each bit on the TWI bus for a given target frequency. This may be used with
+ * the \ref TWI_Init() function to convert a bus frequency to a number of clocks for the \c BitLength
+ * parameter.
+ *
+ * \param[in] Prescale Prescaler set on the TWI bus.
+ * \param[in] Frequency Desired TWI bus frequency in Hz.
+ *
+ * \return Bit length in clocks for the given TWI bus frequency at the given prescaler value.
+ */
+ #define TWI_BITLENGTH_FROM_FREQ(Prescale, Frequency) ((((F_CPU / (Prescale)) / (Frequency)) - 16) / 2)
+
+ /* Enums: */
+ /** Enum for the possible return codes of the TWI transfer start routine and other dependant TWI functions. */
+ enum TWI_ErrorCodes_t
+ {
+ TWI_ERROR_NoError = 0, /**< Indicates that the command completed successfully. */
+ TWI_ERROR_BusFault = 1, /**< A TWI bus fault occurred while attempting to capture the bus. */
+ TWI_ERROR_BusCaptureTimeout = 2, /**< A timeout occurred whilst waiting for the bus to be ready. */
+ TWI_ERROR_SlaveResponseTimeout = 3, /**< No ACK received at the nominated slave address within the timeout period. */
+ TWI_ERROR_SlaveNotReady = 4, /**< Slave NAKed the TWI bus START condition. */
+ TWI_ERROR_SlaveNAK = 5, /**< Slave NAKed whilst attempting to send data to the device. */
+ };
+
+ /* Inline Functions: */
+ /** Initializes the TWI hardware into master mode, ready for data transmission and reception. This must be
+ * before any other TWI operations.
+ *
+ * The generated SCL frequency will be according to the formula <pre>F_CPU / (16 + 2 * BitLength + 4 ^ Prescale)</pre>.
+ *
+ * \attention The value of the \c BitLength parameter should not be set below 10 or invalid bus conditions may
+ * occur, as indicated in the AVR8 microcontroller datasheet.
+ *
+ * \param[in] Prescale Prescaler to use when determining the bus frequency, a \c TWI_BIT_PRESCALE_* value.
+ * \param[in] BitLength Length of the bits sent on the bus.
+ */
+ static inline void TWI_Init(const uint8_t Prescale,
+ const uint8_t BitLength) ATTR_ALWAYS_INLINE;
+ static inline void TWI_Init(const uint8_t Prescale,
+ const uint8_t BitLength)
+ {
+ TWCR |= (1 << TWEN);
+ TWSR = Prescale;
+ TWBR = BitLength;
+ }
+
+ /** Turns off the TWI driver hardware. If this is called, any further TWI operations will require a call to
+ * \ref TWI_Init() before the TWI can be used again.
+ */
+ static inline void TWI_Disable(void) ATTR_ALWAYS_INLINE;
+ static inline void TWI_Disable(void)
+ {
+ TWCR &= ~(1 << TWEN);
+ }
+
+ /** Sends a TWI STOP onto the TWI bus, terminating communication with the currently addressed device. */
+ static inline void TWI_StopTransmission(void) ATTR_ALWAYS_INLINE;
+ static inline void TWI_StopTransmission(void)
+ {
+ TWCR = ((1 << TWINT) | (1 << TWSTO) | (1 << TWEN));
+ }
+
+ /* Function Prototypes: */
+ /** Begins a master mode TWI bus communication with the given slave device address.
+ *
+ * \param[in] SlaveAddress Address of the slave TWI device to communicate with.
+ * \param[in] TimeoutMS Timeout period within which the slave must respond, in milliseconds.
+ *
+ * \return A value from the \ref TWI_ErrorCodes_t enum.
+ */
+ uint8_t TWI_StartTransmission(const uint8_t SlaveAddress,
+ const uint8_t TimeoutMS);
+
+ /** Sends a byte to the currently addressed device on the TWI bus.
+ *
+ * \param[in] Byte Byte to send to the currently addressed device
+ *
+ * \return Boolean \c true if the recipient ACKed the byte, \c false otherwise
+ */
+ bool TWI_SendByte(const uint8_t Byte);
+
+ /** Receives a byte from the currently addressed device on the TWI bus.
+ *
+ * \param[in] Byte Location where the read byte is to be stored.
+ * \param[in] LastByte Indicates if the byte should be ACKed if false, NAKed if true.
+ *
+ * \return Boolean \c true if the byte reception successfully completed, \c false otherwise.
+ */
+ bool TWI_ReceiveByte(uint8_t* const Byte,
+ const bool LastByte) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** High level function to perform a complete packet transfer over the TWI bus to the specified
+ * device.
+ *
+ * \param[in] SlaveAddress Base address of the TWI slave device to communicate with.
+ * \param[in] TimeoutMS Timeout for bus capture and slave START ACK, in milliseconds.
+ * \param[in] InternalAddress Pointer to a location where the internal slave read start address is stored.
+ * \param[in] InternalAddressLen Size of the internal device address, in bytes.
+ * \param[in] Buffer Pointer to a buffer where the read packet data is to be stored.
+ * \param[in] Length Size of the packet to read, in bytes.
+ *
+ * \return A value from the \ref TWI_ErrorCodes_t enum.
+ */
+ uint8_t TWI_ReadPacket(const uint8_t SlaveAddress,
+ const uint8_t TimeoutMS,
+ const uint8_t* InternalAddress,
+ uint8_t InternalAddressLen,
+ uint8_t* Buffer,
+ uint8_t Length) ATTR_NON_NULL_PTR_ARG(3);
+
+ /** High level function to perform a complete packet transfer over the TWI bus from the specified
+ * device.
+ *
+ * \param[in] SlaveAddress Base address of the TWI slave device to communicate with
+ * \param[in] TimeoutMS Timeout for bus capture and slave START ACK, in milliseconds
+ * \param[in] InternalAddress Pointer to a location where the internal slave write start address is stored
+ * \param[in] InternalAddressLen Size of the internal device address, in bytes
+ * \param[in] Buffer Pointer to a buffer where the packet data to send is stored
+ * \param[in] Length Size of the packet to send, in bytes
+ *
+ * \return A value from the \ref TWI_ErrorCodes_t enum.
+ */
+ uint8_t TWI_WritePacket(const uint8_t SlaveAddress,
+ const uint8_t TimeoutMS,
+ const uint8_t* InternalAddress,
+ uint8_t InternalAddressLen,
+ const uint8_t* Buffer,
+ uint8_t Length) ATTR_NON_NULL_PTR_ARG(3);
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/SPI.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/SPI.h
new file mode 100644
index 000000000..54c46423e
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/SPI.h
@@ -0,0 +1,76 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Hardware Serial Peripheral Interface driver.
+ *
+ * This file is the master dispatch header file for the device-specific SPI driver, for microcontrollers
+ * containing a hardware SPI.
+ *
+ * User code should include this file, which will in turn include the correct SPI driver header file for the
+ * currently selected architecture and microcontroller model.
+ */
+
+/** \ingroup Group_PeripheralDrivers
+ * \defgroup Group_SPI SPI Driver - LUFA/Drivers/Peripheral/SPI.h
+ * \brief Hardware Serial Peripheral Interface driver.
+ *
+ * \section Sec_SPI_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - None
+ *
+ * \section Sec_SPI_ModDescription Module Description
+ * Hardware SPI driver. This module provides an easy to use driver for the setup and transfer of data over
+ * the selected architecture and microcontroller model's SPI port.
+ *
+ * \note The exact API for this driver may vary depending on the target used - see
+ * individual target module documentation for the API specific to your target processor.
+ */
+
+#ifndef __SPI_H__
+#define __SPI_H__
+
+ /* Macros: */
+ #define __INCLUDE_FROM_SPI_H
+
+ /* Includes: */
+ #include "../../Common/Common.h"
+
+ /* Includes: */
+ #if (ARCH == ARCH_AVR8)
+ #include "AVR8/SPI_AVR8.h"
+ #elif (ARCH == ARCH_XMEGA)
+ #include "XMEGA/SPI_XMEGA.h"
+ #else
+ #error The SPI peripheral driver is not currently available for your selected architecture.
+ #endif
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/Serial.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/Serial.h
new file mode 100644
index 000000000..46ee61b20
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/Serial.h
@@ -0,0 +1,76 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Hardware Serial USART driver.
+ *
+ * This file is the master dispatch header file for the device-specific USART driver, for microcontrollers
+ * containing a hardware USART.
+ *
+ * User code should include this file, which will in turn include the correct ADC driver header file for the
+ * currently selected architecture and microcontroller model.
+ */
+
+/** \ingroup Group_PeripheralDrivers
+ * \defgroup Group_Serial Serial USART Driver - LUFA/Drivers/Peripheral/Serial.h
+ * \brief Hardware Serial USART driver.
+ *
+ * \section Sec_Serial_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Drivers/Peripheral/<i>ARCH</i>/Serial_<i>ARCH</i>.c <i>(Makefile source module name: LUFA_SRC_SERIAL)</i>
+ *
+ * \section Sec_Serial_ModDescription Module Description
+ * Hardware serial USART driver. This module provides an easy to use driver for the setup and transfer
+ * of data over the selected architecture and microcontroller model's USART port.
+ *
+ * \note The exact API for this driver may vary depending on the target used - see
+ * individual target module documentation for the API specific to your target processor.
+ */
+
+#ifndef __SERIAL_H__
+#define __SERIAL_H__
+
+ /* Macros: */
+ #define __INCLUDE_FROM_SERIAL_H
+
+ /* Includes: */
+ #include "../../Common/Common.h"
+
+ /* Includes: */
+ #if (ARCH == ARCH_AVR8)
+ #include "AVR8/Serial_AVR8.h"
+ #elif (ARCH == ARCH_XMEGA)
+ #include "XMEGA/Serial_XMEGA.h"
+ #else
+ #error The Serial peripheral driver is not currently available for your selected architecture.
+ #endif
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/SerialSPI.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/SerialSPI.h
new file mode 100644
index 000000000..9a42ba5d9
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/SerialSPI.h
@@ -0,0 +1,76 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Hardware SPI Master Mode Serial USART driver.
+ *
+ * This file is the master dispatch header file for the device-specific SPI Master Mode USART driver, for
+ * microcontrollers containing a hardware USART capable of operating in a Master SPI mode.
+ *
+ * User code should include this file, which will in turn include the correct ADC driver header file for the
+ * currently selected architecture and microcontroller model.
+ */
+
+/** \ingroup Group_PeripheralDrivers
+ * \defgroup Group_SerialSPI Master SPI Mode Serial USART Driver - LUFA/Drivers/Peripheral/SerialSPI.h
+ * \brief Hardware SPI Master Mode Serial USART driver.
+ *
+ * \section Sec_SerialSPI_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - None
+ *
+ * \section Sec_SerialSPI_ModDescription Module Description
+ * Hardware SPI Master Mode serial USART driver. This module provides an easy to use driver for the setup and transfer
+ * of data over the selected architecture and microcontroller model's USART port, using a SPI framing format.
+ *
+ * \note The exact API for this driver may vary depending on the target used - see
+ * individual target module documentation for the API specific to your target processor.
+ */
+
+#ifndef __SERIAL_SPI_H__
+#define __SERIAL_SPI_H__
+
+ /* Macros: */
+ #define __INCLUDE_FROM_SERIAL_SPI_H
+
+ /* Includes: */
+ #include "../../Common/Common.h"
+
+ /* Includes: */
+ #if (ARCH == ARCH_AVR8)
+ #include "AVR8/SerialSPI_AVR8.h"
+ #elif (ARCH == ARCH_XMEGA)
+ #include "XMEGA/SerialSPI_XMEGA.h"
+ #else
+ #error The Serial SPI Master Mode peripheral driver is not currently available for your selected architecture.
+ #endif
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/TWI.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/TWI.h
new file mode 100644
index 000000000..5290e6679
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/TWI.h
@@ -0,0 +1,76 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Hardware Two Wire Interface (I2C) driver.
+ *
+ * This file is the master dispatch header file for the device-specific SPI driver, for microcontrollers
+ * containing a hardware TWI.
+ *
+ * User code should include this file, which will in turn include the correct TWI driver header file for the
+ * currently selected architecture and microcontroller model.
+ */
+
+/** \ingroup Group_PeripheralDrivers
+ * \defgroup Group_TWI TWI Driver - LUFA/Drivers/Peripheral/TWI.h
+ * \brief Hardware Two Wire Interface (I2C) driver.
+ *
+ * \section Sec_TWI_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Drivers/Peripheral/<i>ARCH</i>/TWI_<i>ARCH</i>.c <i>(Makefile source module name: LUFA_SRC_TWI)</i>
+ *
+ * \section Sec_TWI_ModDescription Module Description
+ * Hardware TWI driver. This module provides an easy to use driver for the setup and transfer of data over
+ * the selected architecture and microcontroller model's TWI bus port.
+ *
+ * \note The exact API for this driver may vary depending on the target used - see
+ * individual target module documentation for the API specific to your target processor.
+ */
+
+#ifndef __TWI_H__
+#define __TWI_H__
+
+ /* Macros: */
+ #define __INCLUDE_FROM_TWI_H
+
+ /* Includes: */
+ #include "../../Common/Common.h"
+
+ /* Includes: */
+ #if (ARCH == ARCH_AVR8)
+ #include "AVR8/TWI_AVR8.h"
+ #elif (ARCH == ARCH_XMEGA)
+ #include "XMEGA/TWI_XMEGA.h"
+ #else
+ #error The TWI peripheral driver is not currently available for your selected architecture.
+ #endif
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/XMEGA/SPI_XMEGA.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/XMEGA/SPI_XMEGA.h
new file mode 100644
index 000000000..c6230481e
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/XMEGA/SPI_XMEGA.h
@@ -0,0 +1,251 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief SPI Peripheral Driver (XMEGA)
+ *
+ * On-chip SPI driver for the XMEGA microcontrollers.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the SPI driver
+ * dispatch header located in LUFA/Drivers/Peripheral/SPI.h.
+ */
+
+/** \ingroup Group_SPI
+ * \defgroup Group_SPI_XMEGA SPI Peripheral Driver (XMEGA)
+ *
+ * \section Sec_SPI_XMEGA_ModDescription Module Description
+ * Driver for the hardware SPI port(s) available on XMEGA AVR microcontroller models. This
+ * module provides an easy to use driver for the setup and transfer of data over the AVR's
+ * SPI ports.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the SPI driver
+ * dispatch header located in LUFA/Drivers/Peripheral/SPI.h.
+ *
+ * \code
+ * // Initialize the SPI driver before first use
+ * SPI_Init(&SPIC,
+ * SPI_SPEED_FCPU_DIV_2 | SPI_ORDER_MSB_FIRST | SPI_SCK_LEAD_FALLING |
+ * SPI_SAMPLE_TRAILING | SPI_MODE_MASTER);
+ *
+ * // Send several bytes, ignoring the returned data
+ * SPI_SendByte(&SPIC, 0x01);
+ * SPI_SendByte(&SPIC, 0x02);
+ * SPI_SendByte(&SPIC, 0x03);
+ *
+ * // Receive several bytes, sending a dummy 0x00 byte each time
+ * uint8_t Byte1 = SPI_ReceiveByte(&SPIC);
+ * uint8_t Byte2 = SPI_ReceiveByte(&SPIC);
+ * uint8_t Byte3 = SPI_ReceiveByte(&SPIC);
+ *
+ * // Send a byte, and store the received byte from the same transaction
+ * uint8_t ResponseByte = SPI_TransferByte(&SPIC, 0xDC);
+ * \endcode
+ *
+ * @{
+ */
+
+#ifndef __SPI_XMEGA_H__
+#define __SPI_XMEGA_H__
+
+ /* Includes: */
+ #include "../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_SPI_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Peripheral/SPI.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define SPI_USE_DOUBLESPEED SPI_CLK2X_bm
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** \name SPI Prescaler Configuration Masks */
+ //@{
+ /** SPI prescaler mask for \ref SPI_Init(). Divides the system clock by a factor of 2. */
+ #define SPI_SPEED_FCPU_DIV_2 SPI_USE_DOUBLESPEED
+
+ /** SPI prescaler mask for \ref SPI_Init(). Divides the system clock by a factor of 4. */
+ #define SPI_SPEED_FCPU_DIV_4 0
+
+ /** SPI prescaler mask for \ref SPI_Init(). Divides the system clock by a factor of 8. */
+ #define SPI_SPEED_FCPU_DIV_8 (SPI_USE_DOUBLESPEED | (1 << SPI_PRESCALER_gp))
+
+ /** SPI prescaler mask for \ref SPI_Init(). Divides the system clock by a factor of 16. */
+ #define SPI_SPEED_FCPU_DIV_16 (1 << SPI_PRESCALER_gp)
+
+ /** SPI prescaler mask for \ref SPI_Init(). Divides the system clock by a factor of 32. */
+ #define SPI_SPEED_FCPU_DIV_32 (SPI_USE_DOUBLESPEED | (2 << SPI_PRESCALER_gp))
+
+ /** SPI prescaler mask for \ref SPI_Init(). Divides the system clock by a factor of 64. */
+ #define SPI_SPEED_FCPU_DIV_64 (2 << SPI_PRESCALER_gp)
+
+ /** SPI prescaler mask for \ref SPI_Init(). Divides the system clock by a factor of 128. */
+ #define SPI_SPEED_FCPU_DIV_128 (3 << SPI_PRESCALER_gp)
+ //@}
+
+ /** \name SPI SCK Polarity Configuration Masks */
+ //@{
+ /** SPI clock polarity mask for \ref SPI_Init(). Indicates that the SCK should lead on the rising edge. */
+ #define SPI_SCK_LEAD_RISING 0
+
+ /** SPI clock polarity mask for \ref SPI_Init(). Indicates that the SCK should lead on the falling edge. */
+ #define SPI_SCK_LEAD_FALLING SPI_MODE1_bm
+ //@}
+
+ /** \name SPI Sample Edge Configuration Masks */
+ //@{
+ /** SPI data sample mode mask for \ref SPI_Init(). Indicates that the data should sampled on the leading edge. */
+ #define SPI_SAMPLE_LEADING 0
+
+ /** SPI data sample mode mask for \ref SPI_Init(). Indicates that the data should be sampled on the trailing edge. */
+ #define SPI_SAMPLE_TRAILING SPI_MODE0_bm
+ //@}
+
+ /** \name SPI Data Ordering Configuration Masks */
+ //@{
+ /** SPI data order mask for \ref SPI_Init(). Indicates that data should be shifted out MSB first. */
+ #define SPI_ORDER_MSB_FIRST 0
+
+ /** SPI data order mask for \ref SPI_Init(). Indicates that data should be shifted out LSB first. */
+ #define SPI_ORDER_LSB_FIRST SPI_DORD_bm
+ //@}
+
+ /** \name SPI Mode Configuration Masks */
+ //@{
+ /** SPI mode mask for \ref SPI_Init(). Indicates that the SPI interface should be initialized into slave mode. */
+ #define SPI_MODE_SLAVE 0
+
+ /** SPI mode mask for \ref SPI_Init(). Indicates that the SPI interface should be initialized into master mode. */
+ #define SPI_MODE_MASTER SPI_MASTER_bm
+ //@}
+
+ /* Inline Functions: */
+ /** Initializes the SPI subsystem, ready for transfers. Must be called before calling any other
+ * SPI routines.
+ *
+ * \param[in,out] SPI Pointer to the base of the SPI peripheral within the device.
+ * \param[in] SPIOptions SPI Options, a mask consisting of one of each of the \c SPI_SPEED_*,
+ * \c SPI_SCK_*, \c SPI_SAMPLE_*, \c SPI_ORDER_* and \c SPI_MODE_* masks.
+ */
+ static inline void SPI_Init(SPI_t* const SPI,
+ const uint8_t SPIOptions) ATTR_NON_NULL_PTR_ARG(1);
+ static inline void SPI_Init(SPI_t* const SPI,
+ const uint8_t SPIOptions)
+ {
+ SPI->CTRL = (SPIOptions | SPI_ENABLE_bm);
+ }
+
+ /** Turns off the SPI driver, disabling and returning used hardware to their default configuration.
+ *
+ * \param[in,out] SPI Pointer to the base of the SPI peripheral within the device.
+ */
+ static inline void SPI_Disable(SPI_t* const SPI) ATTR_NON_NULL_PTR_ARG(1);
+ static inline void SPI_Disable(SPI_t* const SPI)
+ {
+ SPI->CTRL &= ~SPI_ENABLE_bm;
+ }
+
+ /** Retrieves the currently selected SPI mode, once the SPI interface has been configured.
+ *
+ * \param[in,out] SPI Pointer to the base of the SPI peripheral within the device.
+ *
+ * \return \ref SPI_MODE_MASTER if the interface is currently in SPI Master mode, \ref SPI_MODE_SLAVE otherwise
+ */
+ static inline uint8_t SPI_GetCurrentMode(SPI_t* const SPI) ATTR_ALWAYS_INLINE ATTR_NON_NULL_PTR_ARG(1);
+ static inline uint8_t SPI_GetCurrentMode(SPI_t* const SPI)
+ {
+ return (SPI->CTRL & SPI_MASTER_bm);
+ }
+
+ /** Sends and receives a byte through the SPI interface, blocking until the transfer is complete.
+ *
+ * \param[in,out] SPI Pointer to the base of the SPI peripheral within the device.
+ * \param[in] Byte Byte to send through the SPI interface.
+ *
+ * \return Response byte from the attached SPI device.
+ */
+ static inline uint8_t SPI_TransferByte(SPI_t* const SPI,
+ const uint8_t Byte) ATTR_ALWAYS_INLINE ATTR_NON_NULL_PTR_ARG(1);
+ static inline uint8_t SPI_TransferByte(SPI_t* const SPI,
+ const uint8_t Byte)
+ {
+ SPI->DATA = Byte;
+ while (!(SPI->STATUS & SPI_IF_bm));
+ return SPI->DATA;
+ }
+
+ /** Sends a byte through the SPI interface, blocking until the transfer is complete. The response
+ * byte sent to from the attached SPI device is ignored.
+ *
+ * \param[in,out] SPI Pointer to the base of the SPI peripheral within the device.
+ * \param[in] Byte Byte to send through the SPI interface.
+ */
+ static inline void SPI_SendByte(SPI_t* const SPI,
+ const uint8_t Byte) ATTR_ALWAYS_INLINE ATTR_NON_NULL_PTR_ARG(1);
+ static inline void SPI_SendByte(SPI_t* const SPI,
+ const uint8_t Byte)
+ {
+ SPI->DATA = Byte;
+ while (!(SPI->STATUS & SPI_IF_bm));
+ }
+
+ /** Sends a dummy byte through the SPI interface, blocking until the transfer is complete. The response
+ * byte from the attached SPI device is returned.
+ *
+ * \param[in,out] SPI Pointer to the base of the SPI peripheral within the device.
+ *
+ * \return The response byte from the attached SPI device.
+ */
+ static inline uint8_t SPI_ReceiveByte(SPI_t* const SPI) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ static inline uint8_t SPI_ReceiveByte(SPI_t* const SPI)
+ {
+ SPI->DATA = 0;
+ while (!(SPI->STATUS & SPI_IF_bm));
+ return SPI->DATA;
+ }
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/XMEGA/SerialSPI_XMEGA.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/XMEGA/SerialSPI_XMEGA.h
new file mode 100644
index 000000000..a981ce6a6
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/XMEGA/SerialSPI_XMEGA.h
@@ -0,0 +1,212 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Master SPI Mode Serial USART Peripheral Driver (XMEGA)
+ *
+ * On-chip Master SPI mode USART driver for the XMEGA AVR microcontrollers.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the SPI Master
+ * Mode USART driver dispatch header located in LUFA/Drivers/Peripheral/Serial.h.
+ */
+
+/** \ingroup Group_SerialSPI
+ * \defgroup Group_SerialSPI_XMEGA Master SPI Mode Serial USART Peripheral Driver (XMEGA)
+ *
+ * \section Sec_SerialSPI_XMEGA_ModDescription Module Description
+ * On-chip serial USART driver for the XMEGA AVR microcontrollers.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the ADC driver
+ * dispatch header located in LUFA/Drivers/Peripheral/SerialSPI.h.
+ *
+ * \section Sec_SerialSPI_XMEGA_ExampleUsage Example Usage
+ * The following snippet is an example of how this module may be used within a typical
+ * application.
+ *
+ * \code
+ * // Initialize the Master SPI mode USART driver before first use, with 1Mbit baud
+ * SerialSPI_Init(&USARTD0, (USART_SPI_SCK_LEAD_RISING | USART_SPI_SAMPLE_LEADING | USART_SPI_ORDER_MSB_FIRST), 1000000);
+ *
+ * // Send several bytes, ignoring the returned data
+ * SerialSPI_SendByte(&USARTD0, 0x01);
+ * SerialSPI_SendByte(&USARTD0, 0x02);
+ * SerialSPI_SendByte(&USARTD0, 0x03);
+ *
+ * // Receive several bytes, sending a dummy 0x00 byte each time
+ * uint8_t Byte1 = SerialSPI_ReceiveByte(&USARTD);
+ * uint8_t Byte2 = SerialSPI_ReceiveByte(&USARTD);
+ * uint8_t Byte3 = SerialSPI_ReceiveByte(&USARTD);
+ *
+ * // Send a byte, and store the received byte from the same transaction
+ * uint8_t ResponseByte = SerialSPI_TransferByte(&USARTD0, 0xDC);
+ * \endcode
+ *
+ * @{
+ */
+
+#ifndef __SERIAL_SPI_XMEGA_H__
+#define __SERIAL_SPI_XMEGA_H__
+
+ /* Includes: */
+ #include "../../../Common/Common.h"
+
+ #include <stdio.h>
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_SERIAL_SPI_H)
+ #error Do not include this file directly. Include LUFA/Drivers/Peripheral/Serial.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ #define SERIAL_SPI_UBBRVAL(Baud) ((Baud < (F_CPU / 2)) ? ((F_CPU / (2 * Baud)) - 1) : 0)
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** \name SPI SCK Polarity Configuration Masks */
+ //@{
+ /** SPI clock polarity mask for \ref SerialSPI_Init(). Indicates that the SCK should lead on the rising edge. */
+ #define USART_SPI_SCK_LEAD_RISING 0
+ //@}
+
+ /** \name SPI Sample Edge Configuration Masks */
+ //@{
+ /** SPI data sample mode mask for \ref SerialSPI_Init(). Indicates that the data should sampled on the leading edge. */
+ #define USART_SPI_SAMPLE_LEADING 0
+
+ /** SPI data sample mode mask for \ref SerialSPI_Init(). Indicates that the data should be sampled on the trailing edge. */
+ #define USART_SPI_SAMPLE_TRAILING (1 << 1)
+ //@}
+
+ /** \name SPI Data Ordering Configuration Masks */
+ //@{
+ /** SPI data order mask for \ref SerialSPI_Init(). Indicates that data should be shifted out MSB first. */
+ #define USART_SPI_ORDER_MSB_FIRST 0
+
+ /** SPI data order mask for \ref SerialSPI_Init(). Indicates that data should be shifted out LSB first. */
+ #define USART_SPI_ORDER_LSB_FIRST (1 << 2)
+ //@}
+
+ /* Inline Functions: */
+ /** Initialize the USART module in Master SPI mode.
+ *
+ * \param[in,out] USART Pointer to the base of the USART peripheral within the device.
+ * \param[in] SPIOptions USART SPI Options, a mask consisting of one of each of the \c USART_SPI_SCK_*,
+ * \c USART_SPI_SAMPLE_* and \c USART_SPI_ORDER_* masks.
+ * \param[in] BaudRate SPI baud rate, in bits per second.
+ */
+ static inline void SerialSPI_Init(USART_t* const USART,
+ const uint8_t SPIOptions,
+ const uint32_t BaudRate) ATTR_NON_NULL_PTR_ARG(1);
+ static inline void SerialSPI_Init(USART_t* const USART,
+ const uint8_t SPIOptions,
+ const uint32_t BaudRate)
+ {
+ uint16_t BaudValue = SERIAL_SPI_UBBRVAL(BaudRate);
+
+ USART->BAUDCTRLB = (BaudValue >> 8);
+ USART->BAUDCTRLA = (BaudValue & 0xFF);
+
+ USART->CTRLC = (USART_CMODE_MSPI_gc | SPIOptions);
+ USART->CTRLB = (USART_RXEN_bm | USART_TXEN_bm);
+ }
+
+ /** Turns off the USART driver, disabling and returning used hardware to their default configuration.
+ *
+ * \param[in,out] USART Pointer to the base of the USART peripheral within the device.
+ */
+ static inline void SerialSPI_Disable(USART_t* const USART) ATTR_ALWAYS_INLINE ATTR_NON_NULL_PTR_ARG(1);
+ static inline void SerialSPI_Disable(USART_t* const USART)
+ {
+ USART->CTRLA = 0;
+ USART->CTRLB = 0;
+ USART->CTRLC = 0;
+ }
+
+ /** Sends and receives a byte through the USART SPI interface, blocking until the transfer is complete.
+ *
+ * \param[in,out] USART Pointer to the base of the USART peripheral within the device.
+ * \param[in] DataByte Byte to send through the USART SPI interface.
+ *
+ * \return Response byte from the attached SPI device.
+ */
+ static inline uint8_t SerialSPI_TransferByte(USART_t* const USART,
+ const uint8_t DataByte) ATTR_ALWAYS_INLINE ATTR_NON_NULL_PTR_ARG(1);
+ static inline uint8_t SerialSPI_TransferByte(USART_t* const USART,
+ const uint8_t DataByte)
+ {
+ USART->DATA = DataByte;
+ while (!(USART->STATUS & USART_TXCIF_bm));
+ USART->STATUS = USART_TXCIF_bm;
+ return USART->DATA;
+ }
+
+ /** Sends a byte through the USART SPI interface, blocking until the transfer is complete. The response
+ * byte sent to from the attached SPI device is ignored.
+ *
+ * \param[in,out] USART Pointer to the base of the USART peripheral within the device.
+ * \param[in] DataByte Byte to send through the USART SPI interface.
+ */
+ static inline void SerialSPI_SendByte(USART_t* const USART,
+ const uint8_t DataByte) ATTR_ALWAYS_INLINE ATTR_NON_NULL_PTR_ARG(1);
+ static inline void SerialSPI_SendByte(USART_t* const USART,
+ const uint8_t DataByte)
+ {
+ SerialSPI_TransferByte(USART, DataByte);
+ }
+
+ /** Sends a dummy byte through the USART SPI interface, blocking until the transfer is complete. The response
+ * byte from the attached SPI device is returned.
+ *
+ * \param[in,out] USART Pointer to the base of the USART peripheral within the device.
+ *
+ * \return The response byte from the attached SPI device.
+ */
+ static inline uint8_t SerialSPI_ReceiveByte(USART_t* const USART) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ static inline uint8_t SerialSPI_ReceiveByte(USART_t* const USART)
+ {
+ return SerialSPI_TransferByte(USART, 0);
+ }
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.c
new file mode 100644
index 000000000..4e2935730
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.c
@@ -0,0 +1,122 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "../../../Common/Common.h"
+#if (ARCH == ARCH_XMEGA)
+
+#define __INCLUDE_FROM_SERIAL_C
+#include "../Serial.h"
+
+FILE USARTSerialStream;
+
+int Serial_putchar(char DataByte,
+ FILE *Stream)
+{
+ USART_t* USART = fdev_get_udata(Stream);
+
+ Serial_SendByte(USART, DataByte);
+ return 0;
+}
+
+int Serial_getchar(FILE *Stream)
+{
+ USART_t* USART = fdev_get_udata(Stream);
+
+ if (!(Serial_IsCharReceived(USART)))
+ return _FDEV_EOF;
+
+ return Serial_ReceiveByte(USART);
+}
+
+int Serial_getchar_Blocking(FILE *Stream)
+{
+ USART_t* USART = fdev_get_udata(Stream);
+
+ while (!(Serial_IsCharReceived(USART)));
+ return Serial_ReceiveByte(USART);
+}
+
+void Serial_SendString_P(USART_t* const USART,
+ const char* FlashStringPtr)
+{
+ uint8_t CurrByte;
+
+ while ((CurrByte = pgm_read_byte(FlashStringPtr)) != 0x00)
+ {
+ Serial_SendByte(USART, CurrByte);
+ FlashStringPtr++;
+ }
+}
+
+void Serial_SendString(USART_t* const USART,
+ const char* StringPtr)
+{
+ uint8_t CurrByte;
+
+ while ((CurrByte = *StringPtr) != 0x00)
+ {
+ Serial_SendByte(USART, CurrByte);
+ StringPtr++;
+ }
+}
+
+void Serial_SendData(USART_t* const USART,
+ const void* Buffer,
+ uint16_t Length)
+{
+ while (Length--)
+ Serial_SendByte(USART, *((uint8_t*)Buffer++));
+}
+
+void Serial_CreateStream(FILE* Stream)
+{
+ if (!(Stream))
+ {
+ Stream = &USARTSerialStream;
+ stdin = Stream;
+ stdout = Stream;
+ }
+
+ *Stream = (FILE)FDEV_SETUP_STREAM(Serial_putchar, Serial_getchar, _FDEV_SETUP_RW);
+}
+
+void Serial_CreateBlockingStream(FILE* Stream)
+{
+ if (!(Stream))
+ {
+ Stream = &USARTSerialStream;
+ stdin = Stream;
+ stdout = Stream;
+ }
+
+ *Stream = (FILE)FDEV_SETUP_STREAM(Serial_putchar, Serial_getchar_Blocking, _FDEV_SETUP_RW);
+}
+
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.h
new file mode 100644
index 000000000..ad34c8535
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.h
@@ -0,0 +1,286 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Serial USART Peripheral Driver (XMEGA)
+ *
+ * On-chip serial USART driver for the XMEGA AVR microcontrollers.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USART driver
+ * dispatch header located in LUFA/Drivers/Peripheral/Serial.h.
+ */
+
+/** \ingroup Group_Serial
+ * \defgroup Group_Serial_XMEGA Serial USART Peripheral Driver (XMEGA)
+ *
+ * \section Sec_Serial_XMEGA_ModDescription Module Description
+ * On-chip serial USART driver for the XMEGA AVR microcontrollers.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USART driver
+ * dispatch header located in LUFA/Drivers/Peripheral/Serial.h.
+ *
+ * \section Sec_Serial_XMEGA_ExampleUsage Example Usage
+ * The following snippet is an example of how this module may be used within a typical
+ * application.
+ *
+ * \code
+ * // Initialize the serial USART driver before first use, with 9600 baud (and no double-speed mode)
+ * Serial_Init(&USARTD0, 9600, false);
+ *
+ * // Send a string through the USART
+ * Serial_TxString(&USARTD0, "Test String\r\n");
+ *
+ * // Receive a byte through the USART
+ * uint8_t DataByte = Serial_RxByte(&USARTD0);
+ * \endcode
+ *
+ * @{
+ */
+
+#ifndef __SERIAL_XMEGA_H__
+#define __SERIAL_XMEGA_H__
+
+ /* Includes: */
+ #include "../../../Common/Common.h"
+ #include "../../Misc/TerminalCodes.h"
+
+ #include <stdio.h>
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_SERIAL_H) && !defined(__INCLUDE_FROM_SERIAL_C)
+ #error Do not include this file directly. Include LUFA/Drivers/Peripheral/Serial.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* External Variables: */
+ extern FILE USARTSerialStream;
+
+ /* Function Prototypes: */
+ int Serial_putchar(char DataByte,
+ FILE *Stream);
+ int Serial_getchar(FILE *Stream);
+ int Serial_getchar_Blocking(FILE *Stream);
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Macro for calculating the baud value from a given baud rate when the \c U2X (double speed) bit is
+ * not set.
+ *
+ * \param[in] Baud Target serial UART baud rate.
+ *
+ * \return Closest UBRR register value for the given UART frequency.
+ */
+ #define SERIAL_UBBRVAL(Baud) ((((F_CPU / 16) + (Baud / 2)) / (Baud)) - 1)
+
+ /** Macro for calculating the baud value from a given baud rate when the \c U2X (double speed) bit is
+ * set.
+ *
+ * \param[in] Baud Target serial UART baud rate.
+ *
+ * \return Closest UBRR register value for the given UART frequency.
+ */
+ #define SERIAL_2X_UBBRVAL(Baud) ((((F_CPU / 8) + (Baud / 2)) / (Baud)) - 1)
+
+ /* Function Prototypes: */
+ /** Transmits a given string located in program space (FLASH) through the USART.
+ *
+ * \param[in,out] USART Pointer to the base of the USART peripheral within the device.
+ * \param[in] FlashStringPtr Pointer to a string located in program space.
+ */
+ void Serial_SendString_P(USART_t* const USART,
+ const char* FlashStringPtr) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Transmits a given string located in SRAM memory through the USART.
+ *
+ * \param[in,out] USART Pointer to the base of the USART peripheral within the device.
+ * \param[in] StringPtr Pointer to a string located in SRAM space.
+ */
+ void Serial_SendString(USART_t* const USART,
+ const char* StringPtr) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Transmits a given buffer located in SRAM memory through the USART.
+ *
+ * \param[in,out] USART Pointer to the base of the USART peripheral within the device.
+ * \param[in] Buffer Pointer to a buffer containing the data to send.
+ * \param[in] Length Length of the data to send, in bytes.
+ */
+ void Serial_SendData(USART_t* const USART,
+ const void* Buffer,
+ uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Creates a standard character stream from the USART so that it can be used with all the regular functions
+ * in the avr-libc \c <stdio.h> library that accept a \c FILE stream as a destination (e.g. \c fprintf). The created
+ * stream is bidirectional and can be used for both input and output functions.
+ *
+ * Reading data from this stream is non-blocking, i.e. in most instances, complete strings cannot be read in by a single
+ * fetch, as the endpoint will not be ready at some point in the transmission, aborting the transfer. However, this may
+ * be used when the read data is processed byte-per-bye (via \c getc()) or when the user application will implement its own
+ * line buffering.
+ *
+ * \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed, if \c NULL, \c stdout
+ * and \c stdin will be configured to use the USART.
+ *
+ * \pre The USART must first be configured via a call to \ref Serial_Init() before the stream is used.
+ */
+ void Serial_CreateStream(FILE* Stream);
+
+ /** Identical to \ref Serial_CreateStream(), except that reads are blocking until the calling stream function terminates
+ * the transfer.
+ *
+ * \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed, if \c NULL, \c stdout
+ * and \c stdin will be configured to use the USART.
+ *
+ * \pre The USART must first be configured via a call to \ref Serial_Init() before the stream is used.
+ */
+ void Serial_CreateBlockingStream(FILE* Stream);
+
+ /* Inline Functions: */
+ /** Initializes the USART, ready for serial data transmission and reception. This initializes the interface to
+ * standard 8-bit, no parity, 1 stop bit settings suitable for most applications.
+ *
+ * \param[in,out] USART Pointer to the base of the USART peripheral within the device.
+ * \param[in] BaudRate Serial baud rate, in bits per second.
+ * \param[in] DoubleSpeed Enables double speed mode when set, halving the sample time to double the baud rate.
+ */
+ static inline void Serial_Init(USART_t* const USART,
+ const uint32_t BaudRate,
+ const bool DoubleSpeed) ATTR_NON_NULL_PTR_ARG(1);
+ static inline void Serial_Init(USART_t* const USART,
+ const uint32_t BaudRate,
+ const bool DoubleSpeed)
+ {
+ uint16_t BaudValue = (DoubleSpeed ? SERIAL_2X_UBBRVAL(BaudRate) : SERIAL_UBBRVAL(BaudRate));
+
+ USART->BAUDCTRLB = (BaudValue >> 8);
+ USART->BAUDCTRLA = (BaudValue & 0xFF);
+
+ USART->CTRLC = (USART_CMODE_ASYNCHRONOUS_gc | USART_PMODE_DISABLED_gc | USART_CHSIZE_8BIT_gc);
+ USART->CTRLB = (USART_RXEN_bm | USART_TXEN_bm | (DoubleSpeed ? USART_CLK2X_bm : 0));
+ }
+
+ /** Turns off the USART driver, disabling and returning used hardware to their default configuration.
+ *
+ * \param[in,out] USART Pointer to the base of the USART peripheral within the device.
+ */
+ static inline void Serial_Disable(USART_t* const USART) ATTR_ALWAYS_INLINE ATTR_NON_NULL_PTR_ARG(1);
+ static inline void Serial_Disable(USART_t* const USART)
+ {
+ USART->CTRLA = 0;
+ USART->CTRLB = 0;
+ USART->CTRLC = 0;
+ }
+
+ /** Indicates whether a character has been received through the USART.
+ *
+ * \param[in,out] USART Pointer to the base of the USART peripheral within the device.
+ *
+ * \return Boolean \c true if a character has been received, \c false otherwise.
+ */
+ static inline bool Serial_IsCharReceived(USART_t* const USART) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ static inline bool Serial_IsCharReceived(USART_t* const USART)
+ {
+ return ((USART->STATUS & USART_RXCIF_bm) ? true : false);
+ }
+
+ /** Indicates whether there is hardware buffer space for a new transmit on the USART. This
+ * function can be used to determine if a call to \ref Serial_SendByte() will block in advance.
+ *
+ * \param[in,out] USART Pointer to the base of the USART peripheral within the device.
+ *
+ * \return Boolean \c true if a character can be queued for transmission immediately, \c false otherwise.
+ */
+ static inline bool Serial_IsSendReady(USART_t* const USART) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ static inline bool Serial_IsSendReady(USART_t* const USART)
+ {
+ return (USART->STATUS & USART_DREIF_bm) ? true : false;
+ }
+
+ /** Indicates whether the hardware USART transmit buffer is completely empty, indicating all
+ * pending transmissions have completed.
+ *
+ * \param[in,out] USART Pointer to the base of the USART peripheral within the device.
+ *
+ * \return Boolean \c true if no characters are buffered for transmission, \c false otherwise.
+ */
+ static inline bool Serial_IsSendComplete(USART_t* const USART) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ static inline bool Serial_IsSendComplete(USART_t* const USART)
+ {
+ return (USART->STATUS & USART_TXCIF_bm) ? true : false;
+ }
+
+ /** Transmits a given byte through the USART.
+ *
+ * \note If no buffer space is available in the hardware USART, this function will block. To check if
+ * space is available before calling this function, see \ref Serial_IsSendReady().
+ *
+ * \param[in,out] USART Pointer to the base of the USART peripheral within the device.
+ * \param[in] DataByte Byte to transmit through the USART.
+ */
+ static inline void Serial_SendByte(USART_t* const USART,
+ const char DataByte) ATTR_ALWAYS_INLINE ATTR_NON_NULL_PTR_ARG(1);
+ static inline void Serial_SendByte(USART_t* const USART,
+ const char DataByte)
+ {
+ while (!(Serial_IsSendReady(USART)));
+ USART->DATA = DataByte;
+ }
+
+ /** Receives the next byte from the USART.
+ *
+ * \param[in,out] USART Pointer to the base of the USART peripheral within the device.
+ *
+ * \return Next byte received from the USART, or a negative value if no byte has been received.
+ */
+ static inline int16_t Serial_ReceiveByte(USART_t* const USART) ATTR_ALWAYS_INLINE ATTR_NON_NULL_PTR_ARG(1);
+ static inline int16_t Serial_ReceiveByte(USART_t* const USART)
+ {
+ if (!(Serial_IsCharReceived(USART)))
+ return -1;
+
+ USART->STATUS = USART_RXCIF_bm;
+ return USART->DATA;
+ }
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/XMEGA/TWI_XMEGA.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/XMEGA/TWI_XMEGA.c
new file mode 100644
index 000000000..6f8ab1d4c
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/XMEGA/TWI_XMEGA.c
@@ -0,0 +1,185 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "../../../Common/Common.h"
+#if (ARCH == ARCH_XMEGA)
+
+#define __INCLUDE_FROM_TWI_C
+#include "../TWI.h"
+
+uint8_t TWI_StartTransmission(TWI_t* const TWI,
+ const uint8_t SlaveAddress,
+ const uint8_t TimeoutMS)
+{
+ uint16_t TimeoutRemaining;
+
+ TWI->MASTER.ADDR = SlaveAddress;
+
+ TimeoutRemaining = (TimeoutMS * 100);
+ while (TimeoutRemaining)
+ {
+ uint8_t status = TWI->MASTER.STATUS;
+
+ if ((status & (TWI_MASTER_WIF_bm | TWI_MASTER_ARBLOST_bm)) == (TWI_MASTER_WIF_bm | TWI_MASTER_ARBLOST_bm))
+ {
+ TWI->MASTER.ADDR = SlaveAddress;
+ }
+ else if ((status & (TWI_MASTER_WIF_bm | TWI_MASTER_RXACK_bm)) == (TWI_MASTER_WIF_bm | TWI_MASTER_RXACK_bm))
+ {
+ TWI_StopTransmission(TWI);
+ return TWI_ERROR_SlaveResponseTimeout;
+ }
+ else if (status & (TWI_MASTER_WIF_bm | TWI_MASTER_RIF_bm))
+ {
+ return TWI_ERROR_NoError;
+ }
+
+ _delay_us(10);
+ TimeoutRemaining--;
+ }
+
+ if (!(TimeoutRemaining)) {
+ if (TWI->MASTER.STATUS & TWI_MASTER_CLKHOLD_bm) {
+ TWI_StopTransmission(TWI);
+ }
+ }
+
+ return TWI_ERROR_BusCaptureTimeout;
+}
+
+bool TWI_SendByte(TWI_t* const TWI,
+ const uint8_t Byte)
+{
+ TWI->MASTER.DATA = Byte;
+
+ while (!(TWI->MASTER.STATUS & TWI_MASTER_WIF_bm));
+
+ return (TWI->MASTER.STATUS & TWI_MASTER_WIF_bm) && !(TWI->MASTER.STATUS & TWI_MASTER_RXACK_bm);
+}
+
+bool TWI_ReceiveByte(TWI_t* const TWI,
+ uint8_t* const Byte,
+ const bool LastByte)
+{
+ if ((TWI->MASTER.STATUS & (TWI_MASTER_BUSERR_bm | TWI_MASTER_ARBLOST_bm)) == (TWI_MASTER_BUSERR_bm | TWI_MASTER_ARBLOST_bm)) {
+ return false;
+ }
+
+ while (!(TWI->MASTER.STATUS & TWI_MASTER_RIF_bm));
+
+ *Byte = TWI->MASTER.DATA;
+
+ if (LastByte)
+ TWI->MASTER.CTRLC = TWI_MASTER_ACKACT_bm | TWI_MASTER_CMD_STOP_gc;
+ else
+ TWI->MASTER.CTRLC = TWI_MASTER_CMD_RECVTRANS_gc;
+
+ return true;
+}
+
+uint8_t TWI_ReadPacket(TWI_t* const TWI,
+ const uint8_t SlaveAddress,
+ const uint8_t TimeoutMS,
+ const uint8_t* InternalAddress,
+ uint8_t InternalAddressLen,
+ uint8_t* Buffer,
+ uint8_t Length)
+{
+ uint8_t ErrorCode;
+
+ if ((ErrorCode = TWI_StartTransmission(TWI, (SlaveAddress & TWI_DEVICE_ADDRESS_MASK) | TWI_ADDRESS_WRITE,
+ TimeoutMS)) == TWI_ERROR_NoError)
+ {
+ while (InternalAddressLen--)
+ {
+ if (!(TWI_SendByte(TWI, *(InternalAddress++))))
+ {
+ ErrorCode = TWI_ERROR_SlaveNAK;
+ break;
+ }
+ }
+
+ if ((ErrorCode = TWI_StartTransmission(TWI, (SlaveAddress & TWI_DEVICE_ADDRESS_MASK) | TWI_ADDRESS_READ,
+ TimeoutMS)) == TWI_ERROR_NoError)
+ {
+ while (Length--)
+ {
+ if (!(TWI_ReceiveByte(TWI, Buffer++, (Length == 0))))
+ {
+ ErrorCode = TWI_ERROR_SlaveNAK;
+ break;
+ }
+ }
+ }
+
+ TWI_StopTransmission(TWI);
+ }
+
+ return ErrorCode;
+}
+
+uint8_t TWI_WritePacket(TWI_t* const TWI,
+ const uint8_t SlaveAddress,
+ const uint8_t TimeoutMS,
+ const uint8_t* InternalAddress,
+ uint8_t InternalAddressLen,
+ const uint8_t* Buffer,
+ uint8_t Length)
+{
+ uint8_t ErrorCode;
+
+ if ((ErrorCode = TWI_StartTransmission(TWI, (SlaveAddress & TWI_DEVICE_ADDRESS_MASK) | TWI_ADDRESS_WRITE,
+ TimeoutMS)) == TWI_ERROR_NoError)
+ {
+ while (InternalAddressLen--)
+ {
+ if (!(TWI_SendByte(TWI, *(InternalAddress++))))
+ {
+ ErrorCode = TWI_ERROR_SlaveNAK;
+ break;
+ }
+ }
+
+ while (Length--)
+ {
+ if (!(TWI_SendByte(TWI, *(Buffer++))))
+ {
+ ErrorCode = TWI_ERROR_SlaveNAK;
+ break;
+ }
+ }
+
+ TWI_StopTransmission(TWI);
+ }
+
+ return ErrorCode;
+}
+
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/XMEGA/TWI_XMEGA.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/XMEGA/TWI_XMEGA.h
new file mode 100644
index 000000000..72437e5e1
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/Peripheral/XMEGA/TWI_XMEGA.h
@@ -0,0 +1,302 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief TWI Peripheral Driver (XMEGA)
+ *
+ * On-chip TWI driver for the XMEGA Family of AVR microcontrollers.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the TWI driver
+ * dispatch header located in LUFA/Drivers/Peripheral/TWI.h.
+ */
+
+/** \ingroup Group_TWI
+ * \defgroup Group_TWI_XMEGA TWI Peripheral Driver (XMEGA)
+ *
+ * \section Sec_TWI_XMEGA_ModDescription Module Description
+ * Master mode TWI driver for the 8-bit AVR microcontrollers which contain a hardware TWI module.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the TWI driver
+ * dispatch header located in LUFA/Drivers/Peripheral/TWI.h.
+ *
+ * \section Sec_TWI_XMEGA_ExampleUsage Example Usage
+ * The following snippet is an example of how this module may be used within a typical
+ * application.
+ *
+ * <b>Low Level API Example:</b>
+ * \code
+ * // Initialize the TWI driver before first use at 200KHz
+ * TWI_Init(&TWIC, TWI_BAUD_FROM_FREQ(200000));
+ *
+ * // Start a write session to device at device address 0xA0, internal address 0xDC with a 10ms timeout
+ * if (TWI_StartTransmission(&TWIC, 0xA0 | TWI_ADDRESS_WRITE, 10) == TWI_ERROR_NoError)
+ * {
+ * TWI_SendByte(&TWIC, 0xDC);
+ *
+ * TWI_SendByte(&TWIC, 0x01);
+ * TWI_SendByte(&TWIC, 0x02);
+ * TWI_SendByte(&TWIC, 0x03);
+ *
+ * // Must stop transmission afterwards to release the bus
+ * TWI_StopTransmission(&TWIC);
+ * }
+ *
+ * // Start a read session to device at address 0xA0, internal address 0xDC with a 10ms timeout
+ * if (TWI_StartTransmission(&TWIC, 0xA0 | TWI_ADDRESS_WRITE, 10) == TWI_ERROR_NoError)
+ * {
+ * TWI_SendByte(&TWIC, 0xDC);
+ * TWI_StopTransmission(&TWIC);
+ *
+ * if (TWI_StartTransmission(&TWIC, 0xA0 | TWI_ADDRESS_READ, 10) == TWI_ERROR_NoError)
+ * {
+ * uint8_t Byte1, Byte2, Byte3;
+ *
+ * // Read three bytes, acknowledge after the third byte is received
+ * TWI_ReceiveByte(&TWIC, &Byte1, false);
+ * TWI_ReceiveByte(&TWIC, &Byte2, false);
+ * TWI_ReceiveByte(&TWIC, &Byte3, true);
+ *
+ * // Must stop transmission afterwards to release the bus
+ * TWI_StopTransmission(&TWIC);
+ * }
+ * }
+ * \endcode
+ *
+ * <b>High Level API Example:</b>
+ * \code
+ * // Initialize the TWI driver before first use at 200KHz
+ * TWI_Init(&TWIC, TWI_BAUD_FROM_FREQ(200000));
+ *
+ * // Start a write session to device at device address 0xA0, internal address 0xDC with a 10ms timeout
+ * uint8_t InternalWriteAddress = 0xDC;
+ * uint8_t WritePacket[3] = {0x01, 0x02, 0x03};
+ *
+ * TWI_WritePacket(&TWIC, 0xA0, 10, &InternalWriteAddress, sizeof(InternalWriteAddress),
+ * &WritePacket, sizeof(WritePacket);
+ *
+ * // Start a read session to device at address 0xA0, internal address 0xDC with a 10ms timeout
+ * uint8_t InternalReadAddress = 0xDC;
+ * uint8_t ReadPacket[3];
+ *
+ * TWI_ReadPacket(&TWIC, 0xA0, 10, &InternalReadAddress, sizeof(InternalReadAddress),
+ * &ReadPacket, sizeof(ReadPacket);
+ * \endcode
+ *
+ * @{
+ */
+
+#ifndef __TWI_XMEGA_H__
+#define __TWI_XMEGA_H__
+
+ /* Includes: */
+ #include "../../../Common/Common.h"
+
+ #include <stdio.h>
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_TWI_H) && !defined(__INCLUDE_FROM_TWI_C)
+ #error Do not include this file directly. Include LUFA/Drivers/Peripheral/TWI.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** TWI slave device address mask for a read session. Mask with a slave device base address to obtain
+ * the correct TWI bus address for the slave device when reading data from it.
+ */
+ #define TWI_ADDRESS_READ 0x01
+
+ /** TWI slave device address mask for a write session. Mask with a slave device base address to obtain
+ * the correct TWI bus address for the slave device when writing data to it.
+ */
+ #define TWI_ADDRESS_WRITE 0x00
+
+ /** Mask to retrieve the base address for a TWI device, which can then be ORed with \ref TWI_ADDRESS_READ
+ * or \ref TWI_ADDRESS_WRITE to obtain the device's read and write address respectively.
+ */
+ #define TWI_DEVICE_ADDRESS_MASK 0xFE
+
+ /** Calculates the length of each bit on the TWI bus for a given target frequency. This may be used with
+ * the \ref TWI_Init() function to convert a bus frequency to a number of clocks for the \c BitLength
+ * parameter.
+ *
+ * \param[in] Frequency Desired TWI bus frequency in Hz.
+ *
+ * \return Bit length in clocks for the given TWI bus frequency at the given prescaler value.
+ */
+ #define TWI_BAUD_FROM_FREQ(Frequency) ((F_CPU / (2 * Frequency)) - 5)
+
+ /* Enums: */
+ /** Enum for the possible return codes of the TWI transfer start routine and other dependant TWI functions. */
+ enum TWI_ErrorCodes_t
+ {
+ TWI_ERROR_NoError = 0, /**< Indicates that the command completed successfully. */
+ TWI_ERROR_BusFault = 1, /**< A TWI bus fault occurred while attempting to capture the bus. */
+ TWI_ERROR_BusCaptureTimeout = 2, /**< A timeout occurred whilst waiting for the bus to be ready. */
+ TWI_ERROR_SlaveResponseTimeout = 3, /**< No ACK received at the nominated slave address within the timeout period. */
+ TWI_ERROR_SlaveNotReady = 4, /**< Slave NAKed the TWI bus START condition. */
+ TWI_ERROR_SlaveNAK = 5, /**< Slave NAKed whilst attempting to send data to the device. */
+ };
+
+ /* Inline Functions: */
+ /** Initializes the TWI hardware into master mode, ready for data transmission and reception. This must be
+ * before any other TWI operations.
+ *
+ * The generated SCL frequency will be according to the formula <pre>F_CPU / (2 * (5 + (BAUD)))</pre>.
+ *
+ * \attention The value of the \c BitLength parameter should not be set below 10 or invalid bus conditions may
+ * occur, as indicated in the XMEGA microcontroller datasheet.
+ *
+ * \param[in] TWI Pointer to the base of the TWI peripheral within the device.
+ * \param[in] Baud Value of the BAUD register of the TWI Master.
+ */
+ static inline void TWI_Init(TWI_t* const TWI,
+ const uint8_t Baud) ATTR_ALWAYS_INLINE ATTR_NON_NULL_PTR_ARG(1);
+ static inline void TWI_Init(TWI_t* const TWI,
+ const uint8_t Baud)
+ {
+ TWI->CTRL = 0x00;
+ TWI->MASTER.BAUD = Baud;
+ TWI->MASTER.CTRLA = TWI_MASTER_ENABLE_bm;
+ TWI->MASTER.CTRLB = 0;
+ TWI->MASTER.STATUS = TWI_MASTER_BUSSTATE_IDLE_gc;
+ }
+
+ /** Turns off the TWI driver hardware. If this is called, any further TWI operations will require a call to
+ * \ref TWI_Init() before the TWI can be used again.
+ *
+ * \param[in] TWI Pointer to the base of the TWI peripheral within the device.
+ */
+ static inline void TWI_Disable(TWI_t* const TWI) ATTR_ALWAYS_INLINE ATTR_NON_NULL_PTR_ARG(1);
+ static inline void TWI_Disable(TWI_t* const TWI)
+ {
+ TWI->MASTER.CTRLA &= ~TWI_MASTER_ENABLE_bm;
+ }
+
+ /** Sends a TWI STOP onto the TWI bus, terminating communication with the currently addressed device.
+ *
+ * \param[in] TWI Pointer to the base of the TWI peripheral within the device.
+ */
+ static inline void TWI_StopTransmission(TWI_t* const TWI) ATTR_ALWAYS_INLINE ATTR_NON_NULL_PTR_ARG(1);
+ static inline void TWI_StopTransmission(TWI_t* const TWI)
+ {
+ TWI->MASTER.CTRLC = TWI_MASTER_ACKACT_bm | TWI_MASTER_CMD_STOP_gc;
+ }
+
+ /* Function Prototypes: */
+ /** Begins a master mode TWI bus communication with the given slave device address.
+ *
+ * \param[in] TWI Pointer to the base of the TWI peripheral within the device.
+ * \param[in] SlaveAddress Address of the slave TWI device to communicate with.
+ * \param[in] TimeoutMS Timeout period within which the slave must respond, in milliseconds.
+ *
+ * \return A value from the \ref TWI_ErrorCodes_t enum.
+ */
+ uint8_t TWI_StartTransmission(TWI_t* const TWI,
+ const uint8_t SlaveAddress,
+ const uint8_t TimeoutMS) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Sends a byte to the currently addressed device on the TWI bus.
+ *
+ * \param[in] TWI Pointer to the base of the TWI peripheral within the device.
+ * \param[in] Byte Byte to send to the currently addressed device
+ *
+ * \return Boolean \c true if the recipient ACKed the byte, \c false otherwise
+ */
+ bool TWI_SendByte(TWI_t* const TWI,
+ const uint8_t Byte) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Receives a byte from the currently addressed device on the TWI bus.
+ *
+ * \param[in] TWI Pointer to the base of the TWI peripheral within the device.
+ * \param[in] Byte Location where the read byte is to be stored.
+ * \param[in] LastByte Indicates if the byte should be ACKed if false, NAKed if true.
+ *
+ * \return Boolean \c true if the byte reception successfully completed, \c false otherwise.
+ */
+ bool TWI_ReceiveByte(TWI_t* const TWI,
+ uint8_t* const Byte,
+ const bool LastByte) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+
+ /** High level function to perform a complete packet transfer over the TWI bus to the specified
+ * device.
+ *
+ * \param[in] TWI Pointer to the base of the TWI peripheral within the device.
+ * \param[in] SlaveAddress Base address of the TWI slave device to communicate with.
+ * \param[in] TimeoutMS Timeout for bus capture and slave START ACK, in milliseconds.
+ * \param[in] InternalAddress Pointer to a location where the internal slave read start address is stored.
+ * \param[in] InternalAddressLen Size of the internal device address, in bytes.
+ * \param[in] Buffer Pointer to a buffer where the read packet data is to be stored.
+ * \param[in] Length Size of the packet to read, in bytes.
+ *
+ * \return A value from the \ref TWI_ErrorCodes_t enum.
+ */
+ uint8_t TWI_ReadPacket(TWI_t* const TWI,
+ const uint8_t SlaveAddress,
+ const uint8_t TimeoutMS,
+ const uint8_t* InternalAddress,
+ uint8_t InternalAddressLen,
+ uint8_t* Buffer,
+ uint8_t Length) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(4);
+
+ /** High level function to perform a complete packet transfer over the TWI bus from the specified
+ * device.
+ *
+ * \param[in] TWI Pointer to the base of the TWI peripheral within the device.
+ * \param[in] SlaveAddress Base address of the TWI slave device to communicate with
+ * \param[in] TimeoutMS Timeout for bus capture and slave START ACK, in milliseconds
+ * \param[in] InternalAddress Pointer to a location where the internal slave write start address is stored
+ * \param[in] InternalAddressLen Size of the internal device address, in bytes
+ * \param[in] Buffer Pointer to a buffer where the packet data to send is stored
+ * \param[in] Length Size of the packet to send, in bytes
+ *
+ * \return A value from the \ref TWI_ErrorCodes_t enum.
+ */
+ uint8_t TWI_WritePacket(TWI_t* const TWI,
+ const uint8_t SlaveAddress,
+ const uint8_t TimeoutMS,
+ const uint8_t* InternalAddress,
+ uint8_t InternalAddressLen,
+ const uint8_t* Buffer,
+ uint8_t Length) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(4);
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/AndroidAccessoryClass.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/AndroidAccessoryClass.h
new file mode 100644
index 000000000..24978ca2e
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/AndroidAccessoryClass.h
@@ -0,0 +1,77 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Master include file for the library USB Android Open Accessory Class driver.
+ *
+ * Master include file for the library USB Android Open Accessory Class driver, for both host and device modes, where available.
+ *
+ * This file should be included in all user projects making use of this optional class driver, instead of
+ * including any headers in the USB/ClassDriver/Device, USB/ClassDriver/Host or USB/ClassDriver/Common subdirectories.
+ */
+
+/** \ingroup Group_USBClassDrivers
+ * \defgroup Group_USBClassAOA Android Open Accessory Class Driver
+ * \brief USB class driver for the Google Android Open Accessory class standard.
+ *
+ * \section Sec_USBClassAOA_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Drivers/USB/Class/Host/AndroidAccessoryClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ *
+ * \section Sec_USBClassAOA_ModDescription Module Description
+ * Android Open Accessory Class Driver module. This module contains an internal implementation of the USB Android Open Accessory
+ * Class, for Host USB mode. User applications can use this class driver instead of implementing the Android Open Accessory Class
+ * manually via the low-level LUFA APIs.
+ *
+ * This module is designed to simplify the user code by exposing only the required interface needed to interface with
+ * Host using the USB Android Open Accessory Class.
+ *
+ * @{
+ */
+
+#ifndef _AOA_CLASS_H_
+#define _AOA_CLASS_H_
+
+ /* Macros: */
+ #define __INCLUDE_FROM_USB_DRIVER
+ #define __INCLUDE_FROM_AOA_DRIVER
+
+ /* Includes: */
+ #include "../Core/USBMode.h"
+
+ #if defined(USB_CAN_BE_HOST)
+ #include "Host/AndroidAccessoryClassHost.h"
+ #endif
+
+#endif
+
+/** @} */
+
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/AudioClass.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/AudioClass.h
new file mode 100644
index 000000000..0e3ca8d75
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/AudioClass.h
@@ -0,0 +1,81 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Master include file for the library USB Audio 1.0 Class driver.
+ *
+ * Master include file for the library USB Audio 1.0 Class driver, for both host and device modes, where available.
+ *
+ * This file should be included in all user projects making use of this optional class driver, instead of
+ * including any headers in the USB/ClassDriver/Device, USB/ClassDriver/Host or USB/ClassDriver/Common subdirectories.
+ */
+
+/** \ingroup Group_USBClassDrivers
+ * \defgroup Group_USBClassAudio Audio 1.0 Class Driver
+ * \brief USB class driver for the USB-IF Audio 1.0 class standard.
+ *
+ * \section Sec_USBClassAudio_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Drivers/USB/Class/Device/AudioClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ * - LUFA/Drivers/USB/Class/Host/AudioClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ *
+ * \section Sec_USBClassAudio_ModDescription Module Description
+ * Audio 1.0 Class Driver module. This module contains an internal implementation of the USB Audio 1.0 Class, for both
+ * Device and Host USB modes. User applications can use this class driver instead of implementing the Audio 1.0 class
+ * manually via the low-level LUFA APIs.
+ *
+ * This module is designed to simplify the user code by exposing only the required interface needed to interface with
+ * Hosts or Devices using the USB Audio 1.0 Class.
+ *
+ * @{
+ */
+
+#ifndef _AUDIO_CLASS_H_
+#define _AUDIO_CLASS_H_
+
+ /* Macros: */
+ #define __INCLUDE_FROM_USB_DRIVER
+ #define __INCLUDE_FROM_AUDIO_DRIVER
+
+ /* Includes: */
+ #include "../Core/USBMode.h"
+
+ #if defined(USB_CAN_BE_DEVICE)
+ #include "Device/AudioClassDevice.h"
+ #endif
+
+ #if defined(USB_CAN_BE_HOST)
+ #include "Host/AudioClassHost.h"
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/CDCClass.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/CDCClass.h
new file mode 100644
index 000000000..3bad74bfa
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/CDCClass.h
@@ -0,0 +1,81 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Master include file for the library USB CDC-ACM Class driver.
+ *
+ * Master include file for the library USB CDC Class driver, for both host and device modes, where available.
+ *
+ * This file should be included in all user projects making use of this optional class driver, instead of
+ * including any headers in the USB/ClassDriver/Device, USB/ClassDriver/Host or USB/ClassDriver/Common subdirectories.
+ */
+
+/** \ingroup Group_USBClassDrivers
+ * \defgroup Group_USBClassCDC CDC-ACM (Virtual Serial) Class Driver
+ * \brief USB class driver for the USB-IF CDC-ACM (Virtual Serial) class standard.
+ *
+ * \section Sec_USBClassCDC_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Drivers/USB/Class/Device/CDCClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ * - LUFA/Drivers/USB/Class/Host/CDCClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ *
+ * \section Sec_USBClassCDC_ModDescription Module Description
+ * CDC Class Driver module. This module contains an internal implementation of the USB CDC-ACM class Virtual Serial
+ * Ports, for both Device and Host USB modes. User applications can use this class driver instead of implementing the
+ * CDC class manually via the low-level LUFA APIs.
+ *
+ * This module is designed to simplify the user code by exposing only the required interface needed to interface with
+ * Hosts or Devices using the USB CDC Class.
+ *
+ * @{
+ */
+
+#ifndef _CDC_CLASS_H_
+#define _CDC_CLASS_H_
+
+ /* Macros: */
+ #define __INCLUDE_FROM_USB_DRIVER
+ #define __INCLUDE_FROM_CDC_DRIVER
+
+ /* Includes: */
+ #include "../Core/USBMode.h"
+
+ #if defined(USB_CAN_BE_DEVICE)
+ #include "Device/CDCClassDevice.h"
+ #endif
+
+ #if defined(USB_CAN_BE_HOST)
+ #include "Host/CDCClassHost.h"
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/AndroidAccessoryClassCommon.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/AndroidAccessoryClassCommon.h
new file mode 100644
index 000000000..c3153dab7
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/AndroidAccessoryClassCommon.h
@@ -0,0 +1,129 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Common definitions and declarations for the library USB Android Open Accessory Class driver.
+ *
+ * Common definitions and declarations for the library USB Android Open Accessory Class driver.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB module driver
+ * dispatch header located in LUFA/Drivers/USB.h.
+ */
+
+/** \ingroup Group_USBClassAOA
+ * \defgroup Group_USBClassAOACommon Common Class Definitions
+ *
+ * \section Sec_USBClassAOACommon_ModDescription Module Description
+ * Constants, Types and Enum definitions that are common to both Device and Host modes for the USB
+ * Android Open Accessory Class.
+ *
+ * @{
+ */
+
+#ifndef _AOA_CLASS_COMMON_H_
+#define _AOA_CLASS_COMMON_H_
+
+ /* Includes: */
+ #include "../../Core/StdDescriptors.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_AOA_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
+ #endif
+
+ /* Macros: */
+ /** Product ID value in a Device Descriptor to indicate an Android device in Open Accessory mode. */
+ #define ANDROID_ACCESSORY_PRODUCT_ID 0x2D00
+
+ /** Product ID value in a Device Descriptor to indicate an Android device in Open Accessory and Android Debug mode. */
+ #define ANDROID_ACCESSORY_ADB_PRODUCT_ID 0x2D01
+
+ /* Enums: */
+ /** Enum for possible Class, Subclass and Protocol values of device and interface descriptors relating to the
+ * Android Open Accessory class.
+ */
+ enum AOA_Descriptor_ClassSubclassProtocol_t
+ {
+ AOA_CSCP_AOADataClass = 0xFF, /**< Descriptor Class value indicating that the device or interface
+ * belongs to the AOA data class.
+ */
+ AOA_CSCP_AOADataSubclass = 0xFF, /**< Descriptor Subclass value indicating that the device or interface
+ * belongs to AOA data subclass.
+ */
+ AOA_CSCP_AOADataProtocol = 0x00, /**< Descriptor Protocol value indicating that the device or interface
+ * belongs to the AOA data class protocol.
+ */
+ };
+
+ /** Enum for the Android Open Accessory class specific control requests that can be issued by the USB bus host. */
+ enum AOA_ClassRequests_t
+ {
+ AOA_REQ_GetAccessoryProtocol = 0x33, /**< Android Open Accessory control request to retrieve the device's supported Accessory Protocol version. */
+ AOA_REQ_SendString = 0x34, /**< Android Open Accessory control request to set an accessory property string in the device. */
+ AOA_REQ_StartAccessoryMode = 0x35, /**< Android Open Accessory control request to switch the device into Accessory mode. */
+ };
+
+ /** Enum for the possible Android Open Accessory property string indexes. */
+ enum AOA_Strings_t
+ {
+ AOA_STRING_Manufacturer = 0, /**< Index of the Manufacturer property string. */
+ AOA_STRING_Model = 1, /**< Index of the Model Name property string. */
+ AOA_STRING_Description = 2, /**< Index of the Description property string. */
+ AOA_STRING_Version = 3, /**< Index of the Version Number property string. */
+ AOA_STRING_URI = 4, /**< Index of the URI Information property string. */
+ AOA_STRING_Serial = 5, /**< Index of the Serial Number property string. */
+
+ #if !defined(__DOXYGEN__)
+ AOA_STRING_TOTAL_STRINGS
+ #endif
+ };
+
+ /** Enum for the possible Android Open Accessory protocol versions. */
+ enum AOA_Protocols_t
+ {
+ AOA_PROTOCOL_AccessoryV1 = 0x0001, /**< Android Open Accessory version 1. */
+ AOA_PROTOCOL_AccessoryV2 = 0x0002, /**< Android Open Accessory version 2. */
+ };
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/AudioClassCommon.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/AudioClassCommon.h
new file mode 100644
index 000000000..2db5eeea1
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/AudioClassCommon.h
@@ -0,0 +1,780 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Common definitions and declarations for the library USB Audio 1.0 Class driver.
+ *
+ * Common definitions and declarations for the library USB Audio 1.0 Class driver.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB module driver
+ * dispatch header located in LUFA/Drivers/USB.h.
+ */
+
+/** \ingroup Group_USBClassAudio
+ * \defgroup Group_USBClassAudioCommon Common Class Definitions
+ *
+ * \section Sec_USBClassAudioCommon_ModDescription Module Description
+ * Constants, Types and Enum definitions that are common to both Device and Host modes for the USB
+ * Audio 1.0 Class.
+ *
+ * @{
+ */
+
+#ifndef _AUDIO_CLASS_COMMON_H_
+#define _AUDIO_CLASS_COMMON_H_
+
+ /* Includes: */
+ #include "../../Core/StdDescriptors.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_AUDIO_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
+ #endif
+
+ /* Macros: */
+ /** \name Audio Channel Masks */
+ //@{
+ /** Supported channel mask for an Audio class terminal descriptor. See the Audio class specification for more details. */
+ #define AUDIO_CHANNEL_LEFT_FRONT (1 << 0)
+
+ /** Supported channel mask for an Audio class terminal descriptor. See the Audio class specification for more details. */
+ #define AUDIO_CHANNEL_RIGHT_FRONT (1 << 1)
+
+ /** Supported channel mask for an Audio class terminal descriptor. See the Audio class specification for more details. */
+ #define AUDIO_CHANNEL_CENTER_FRONT (1 << 2)
+
+ /** Supported channel mask for an Audio class terminal descriptor. See the Audio class specification for more details. */
+ #define AUDIO_CHANNEL_LOW_FREQ_ENHANCE (1 << 3)
+
+ /** Supported channel mask for an Audio class terminal descriptor. See the Audio class specification for more details. */
+ #define AUDIO_CHANNEL_LEFT_SURROUND (1 << 4)
+
+ /** Supported channel mask for an Audio class terminal descriptor. See the Audio class specification for more details. */
+ #define AUDIO_CHANNEL_RIGHT_SURROUND (1 << 5)
+
+ /** Supported channel mask for an Audio class terminal descriptor. See the Audio class specification for more details. */
+ #define AUDIO_CHANNEL_LEFT_OF_CENTER (1 << 6)
+
+ /** Supported channel mask for an Audio class terminal descriptor. See the Audio class specification for more details. */
+ #define AUDIO_CHANNEL_RIGHT_OF_CENTER (1 << 7)
+
+ /** Supported channel mask for an Audio class terminal descriptor. See the Audio class specification for more details. */
+ #define AUDIO_CHANNEL_SURROUND (1 << 8)
+
+ /** Supported channel mask for an Audio class terminal descriptor. See the Audio class specification for more details. */
+ #define AUDIO_CHANNEL_SIDE_LEFT (1 << 9)
+
+ /** Supported channel mask for an Audio class terminal descriptor. See the Audio class specification for more details. */
+ #define AUDIO_CHANNEL_SIDE_RIGHT (1 << 10)
+
+ /** Supported channel mask for an Audio class terminal descriptor. See the Audio class specification for more details. */
+ #define AUDIO_CHANNEL_TOP (1 << 11)
+ //@}
+
+ /** \name Audio Feature Masks */
+ //@{
+ /** Supported feature mask for an Audio class feature unit descriptor. See the Audio class specification for more details. */
+ #define AUDIO_FEATURE_MUTE (1 << 0)
+
+ /** Supported feature mask for an Audio class feature unit descriptor. See the Audio class specification for more details. */
+ #define AUDIO_FEATURE_VOLUME (1 << 1)
+
+ /** Supported feature mask for an Audio class feature unit descriptor. See the Audio class specification for more details. */
+ #define AUDIO_FEATURE_BASS (1 << 2)
+
+ /** Supported feature mask for an Audio class feature unit descriptor. See the Audio class specification for more details. */
+ #define AUDIO_FEATURE_MID (1 << 3)
+
+ /** Supported feature mask for an Audio class feature unit descriptor. See the Audio class specification for more details. */
+ #define AUDIO_FEATURE_TREBLE (1 << 4)
+
+ /** Supported feature mask for an Audio class feature unit descriptor. See the Audio class specification for more details. */
+ #define AUDIO_FEATURE_GRAPHIC_EQUALIZER (1 << 5)
+
+ /** Supported feature mask for an Audio class feature unit descriptor. See the Audio class specification for more details. */
+ #define AUDIO_FEATURE_AUTOMATIC_GAIN (1 << 6)
+
+ /** Supported feature mask for an Audio class feature unit descriptor. See the Audio class specification for more details. */
+ #define AUDIO_FEATURE_DELAY (1 << 7)
+
+ /** Supported feature mask for an Audio class feature unit descriptor. See the Audio class specification for more details. */
+ #define AUDIO_FEATURE_BASS_BOOST (1 << 8)
+
+ /** Supported feature mask for an Audio class feature unit descriptor. See the Audio class specification for more details. */
+ #define AUDIO_FEATURE_BASS_LOUDNESS (1 << 9)
+ //@}
+
+ /** \name Audio Terminal Types */
+ //@{
+ /** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
+ #define AUDIO_TERMINAL_UNDEFINED 0x0100
+
+ /** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
+ #define AUDIO_TERMINAL_STREAMING 0x0101
+
+ /** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
+ #define AUDIO_TERMINAL_VENDOR 0x01FF
+
+ /** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
+ #define AUDIO_TERMINAL_IN_UNDEFINED 0x0200
+
+ /** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
+ #define AUDIO_TERMINAL_IN_MIC 0x0201
+
+ /** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
+ #define AUDIO_TERMINAL_IN_DESKTOP_MIC 0x0202
+
+ /** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
+ #define AUDIO_TERMINAL_IN_PERSONAL_MIC 0x0203
+
+ /** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
+ #define AUDIO_TERMINAL_IN_OMNIDIR_MIC 0x0204
+
+ /** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
+ #define AUDIO_TERMINAL_IN_MIC_ARRAY 0x0205
+
+ /** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
+ #define AUDIO_TERMINAL_IN_PROCESSING_MIC 0x0206
+
+ /** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
+ #define AUDIO_TERMINAL_IN_OUT_UNDEFINED 0x0300
+
+ /** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
+ #define AUDIO_TERMINAL_OUT_SPEAKER 0x0301
+
+ /** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
+ #define AUDIO_TERMINAL_OUT_HEADPHONES 0x0302
+
+ /** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
+ #define AUDIO_TERMINAL_OUT_HEAD_MOUNTED 0x0303
+
+ /** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
+ #define AUDIO_TERMINAL_OUT_DESKTOP 0x0304
+
+ /** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
+ #define AUDIO_TERMINAL_OUT_ROOM 0x0305
+
+ /** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
+ #define AUDIO_TERMINAL_OUT_COMMUNICATION 0x0306
+
+ /** Terminal type constant for an Audio class terminal descriptor. See the Audio class specification for more details. */
+ #define AUDIO_TERMINAL_OUT_LOWFREQ 0x0307
+ //@}
+
+ /** Convenience macro to fill a 24-bit \ref USB_Audio_SampleFreq_t structure with the given sample rate as a 24-bit number.
+ *
+ * \param[in] freq Required audio sampling frequency in HZ
+ */
+ #define AUDIO_SAMPLE_FREQ(freq) {.Byte1 = ((uint32_t)freq & 0xFF), .Byte2 = (((uint32_t)freq >> 8) & 0xFF), .Byte3 = (((uint32_t)freq >> 16) & 0xFF)}
+
+ /** Mask for the attributes parameter of an Audio class-specific Endpoint descriptor, indicating that the endpoint
+ * accepts only filled endpoint packets of audio samples.
+ */
+ #define AUDIO_EP_FULL_PACKETS_ONLY (1 << 7)
+
+ /** Mask for the attributes parameter of an Audio class-specific Endpoint descriptor, indicating that the endpoint
+ * will accept partially filled endpoint packets of audio samples.
+ */
+ #define AUDIO_EP_ACCEPTS_SMALL_PACKETS (0 << 7)
+
+ /** Mask for the attributes parameter of an Audio class-specific Endpoint descriptor, indicating that the endpoint
+ * allows for sampling frequency adjustments to be made via control requests directed at the endpoint.
+ */
+ #define AUDIO_EP_SAMPLE_FREQ_CONTROL (1 << 0)
+
+ /** Mask for the attributes parameter of an Audio class-specific Endpoint descriptor, indicating that the endpoint
+ * allows for pitch adjustments to be made via control requests directed at the endpoint.
+ */
+ #define AUDIO_EP_PITCH_CONTROL (1 << 1)
+
+ /* Enums: */
+ /** Enum for possible Class, Subclass and Protocol values of device and interface descriptors relating to the Audio
+ * device class.
+ */
+ enum Audio_Descriptor_ClassSubclassProtocol_t
+ {
+ AUDIO_CSCP_AudioClass = 0x01, /**< Descriptor Class value indicating that the device or
+ * interface belongs to the USB Audio 1.0 class.
+ */
+ AUDIO_CSCP_ControlSubclass = 0x01, /**< Descriptor Subclass value indicating that the device or
+ * interface belongs to the Audio Control subclass.
+ */
+ AUDIO_CSCP_ControlProtocol = 0x00, /**< Descriptor Protocol value indicating that the device or
+ * interface belongs to the Audio Control protocol.
+ */
+ AUDIO_CSCP_AudioStreamingSubclass = 0x02, /**< Descriptor Subclass value indicating that the device or
+ * interface belongs to the MIDI Streaming subclass.
+ */
+ AUDIO_CSCP_MIDIStreamingSubclass = 0x03, /**< Descriptor Subclass value indicating that the device or
+ * interface belongs to the Audio streaming subclass.
+ */
+ AUDIO_CSCP_StreamingProtocol = 0x00, /**< Descriptor Protocol value indicating that the device or
+ * interface belongs to the Streaming Audio protocol.
+ */
+ };
+
+ /** Audio class specific interface description subtypes, for the Audio Control interface. */
+ enum Audio_CSInterface_AC_SubTypes_t
+ {
+ AUDIO_DSUBTYPE_CSInterface_Header = 0x01, /**< Audio class specific control interface header. */
+ AUDIO_DSUBTYPE_CSInterface_InputTerminal = 0x02, /**< Audio class specific control interface Input Terminal. */
+ AUDIO_DSUBTYPE_CSInterface_OutputTerminal = 0x03, /**< Audio class specific control interface Output Terminal. */
+ AUDIO_DSUBTYPE_CSInterface_Mixer = 0x04, /**< Audio class specific control interface Mixer Unit. */
+ AUDIO_DSUBTYPE_CSInterface_Selector = 0x05, /**< Audio class specific control interface Selector Unit. */
+ AUDIO_DSUBTYPE_CSInterface_Feature = 0x06, /**< Audio class specific control interface Feature Unit. */
+ AUDIO_DSUBTYPE_CSInterface_Processing = 0x07, /**< Audio class specific control interface Processing Unit. */
+ AUDIO_DSUBTYPE_CSInterface_Extension = 0x08, /**< Audio class specific control interface Extension Unit. */
+ };
+
+ /** Audio class specific interface description subtypes, for the Audio Streaming interface. */
+ enum Audio_CSInterface_AS_SubTypes_t
+ {
+ AUDIO_DSUBTYPE_CSInterface_General = 0x01, /**< Audio class specific streaming interface general descriptor. */
+ AUDIO_DSUBTYPE_CSInterface_FormatType = 0x02, /**< Audio class specific streaming interface format type descriptor. */
+ AUDIO_DSUBTYPE_CSInterface_FormatSpecific = 0x03, /**< Audio class specific streaming interface format information descriptor. */
+ };
+
+ /** Audio class specific endpoint description subtypes, for the Audio Streaming interface. */
+ enum Audio_CSEndpoint_SubTypes_t
+ {
+ AUDIO_DSUBTYPE_CSEndpoint_General = 0x01, /**< Audio class specific endpoint general descriptor. */
+ };
+
+ /** Enum for the Audio class specific control requests that can be issued by the USB bus host. */
+ enum Audio_ClassRequests_t
+ {
+ AUDIO_REQ_SetCurrent = 0x01, /**< Audio class-specific request to set the current value of a parameter within the device. */
+ AUDIO_REQ_SetMinimum = 0x02, /**< Audio class-specific request to set the minimum value of a parameter within the device. */
+ AUDIO_REQ_SetMaximum = 0x03, /**< Audio class-specific request to set the maximum value of a parameter within the device. */
+ AUDIO_REQ_SetResolution = 0x04, /**< Audio class-specific request to set the resolution value of a parameter within the device. */
+ AUDIO_REQ_SetMemory = 0x05, /**< Audio class-specific request to set the memory value of a parameter within the device. */
+ AUDIO_REQ_GetCurrent = 0x81, /**< Audio class-specific request to get the current value of a parameter within the device. */
+ AUDIO_REQ_GetMinimum = 0x82, /**< Audio class-specific request to get the minimum value of a parameter within the device. */
+ AUDIO_REQ_GetMaximum = 0x83, /**< Audio class-specific request to get the maximum value of a parameter within the device. */
+ AUDIO_REQ_GetResolution = 0x84, /**< Audio class-specific request to get the resolution value of a parameter within the device. */
+ AUDIO_REQ_GetMemory = 0x85, /**< Audio class-specific request to get the memory value of a parameter within the device. */
+ AUDIO_REQ_GetStatus = 0xFF, /**< Audio class-specific request to get the device status. */
+ };
+
+ /** Enum for Audio class specific Endpoint control modifiers which can be set and retrieved by a USB host, if the corresponding
+ * endpoint control is indicated to be supported in the Endpoint's Audio-class specific endpoint descriptor.
+ */
+ enum Audio_EndpointControls_t
+ {
+ AUDIO_EPCONTROL_SamplingFreq = 0x01, /**< Sampling frequency adjustment of the endpoint. */
+ AUDIO_EPCONTROL_Pitch = 0x02, /**< Pitch adjustment of the endpoint. */
+ };
+
+ /* Type Defines: */
+ /** \brief Audio class-specific Input Terminal Descriptor (LUFA naming conventions).
+ *
+ * Type define for an Audio class-specific input terminal descriptor. This indicates to the host that the device
+ * contains an input audio source, either from a physical terminal on the device, or a logical terminal (for example,
+ * a USB endpoint). See the USB Audio specification for more details.
+ *
+ * \see \ref USB_Audio_StdDescriptor_InputTerminal_t for the version of this type with standard element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Header_t Header; /**< Regular descriptor header containing the descriptor's type and length. */
+ uint8_t Subtype; /**< Sub type value used to distinguish between audio class-specific descriptors,
+ * must be \ref AUDIO_DSUBTYPE_CSInterface_InputTerminal.
+ */
+
+ uint8_t TerminalID; /**< ID value of this terminal unit - must be a unique value within the device. */
+ uint16_t TerminalType; /**< Type of terminal, a \c TERMINAL_* mask. */
+ uint8_t AssociatedOutputTerminal; /**< ID of associated output terminal, for physically grouped terminals
+ * such as the speaker and microphone of a phone handset.
+ */
+ uint8_t TotalChannels; /**< Total number of separate audio channels within this interface (right, left, etc.) */
+ uint16_t ChannelConfig; /**< \c CHANNEL_* masks indicating what channel layout is supported by this terminal. */
+
+ uint8_t ChannelStrIndex; /**< Index of a string descriptor describing this channel within the device. */
+ uint8_t TerminalStrIndex; /**< Index of a string descriptor describing this descriptor within the device. */
+ } ATTR_PACKED USB_Audio_Descriptor_InputTerminal_t;
+
+ /** \brief Audio class-specific Input Terminal Descriptor (USB-IF naming conventions).
+ *
+ * Type define for an Audio class-specific input terminal descriptor. This indicates to the host that the device
+ * contains an input audio source, either from a physical terminal on the device, or a logical terminal (for example,
+ * a USB endpoint). See the USB Audio specification for more details.
+ *
+ * \see \ref USB_Audio_Descriptor_InputTerminal_t for the version of this type with non-standard LUFA specific
+ * element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint8_t bLength; /**< Size of the descriptor, in bytes. */
+ uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
+ * given by the specific class.
+ */
+
+ uint8_t bDescriptorSubtype; /**< Sub type value used to distinguish between audio class-specific descriptors,
+ * must be \ref AUDIO_DSUBTYPE_CSInterface_InputTerminal.
+ */
+ uint8_t bTerminalID; /**< ID value of this terminal unit - must be a unique value within the device. */
+ uint16_t wTerminalType; /**< Type of terminal, a \c TERMINAL_* mask. */
+ uint8_t bAssocTerminal; /**< ID of associated output terminal, for physically grouped terminals
+ * such as the speaker and microphone of a phone handset.
+ */
+ uint8_t bNrChannels; /**< Total number of separate audio channels within this interface (right, left, etc.) */
+ uint16_t wChannelConfig; /**< \c CHANNEL_* masks indicating what channel layout is supported by this terminal. */
+
+ uint8_t iChannelNames; /**< Index of a string descriptor describing this channel within the device. */
+ uint8_t iTerminal; /**< Index of a string descriptor describing this descriptor within the device. */
+ } ATTR_PACKED USB_Audio_StdDescriptor_InputTerminal_t;
+
+ /** \brief Audio class-specific Output Terminal Descriptor (LUFA naming conventions).
+ *
+ * Type define for an Audio class-specific output terminal descriptor. This indicates to the host that the device
+ * contains an output audio sink, either to a physical terminal on the device, or a logical terminal (for example,
+ * a USB endpoint). See the USB Audio specification for more details.
+ *
+ * \see \ref USB_Audio_StdDescriptor_OutputTerminal_t for the version of this type with standard element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Header_t Header; /**< Regular descriptor header containing the descriptor's type and length. */
+ uint8_t Subtype; /**< Sub type value used to distinguish between audio class-specific descriptors,
+ * must be \ref AUDIO_DSUBTYPE_CSInterface_OutputTerminal.
+ */
+
+ uint8_t TerminalID; /**< ID value of this terminal unit - must be a unique value within the device. */
+ uint16_t TerminalType; /**< Type of terminal, a \c TERMINAL_* mask. */
+ uint8_t AssociatedInputTerminal; /**< ID of associated input terminal, for physically grouped terminals
+ * such as the speaker and microphone of a phone handset.
+ */
+ uint8_t SourceID; /**< ID value of the unit this terminal's audio is sourced from. */
+
+ uint8_t TerminalStrIndex; /**< Index of a string descriptor describing this descriptor within the device. */
+ } ATTR_PACKED USB_Audio_Descriptor_OutputTerminal_t;
+
+ /** \brief Audio class-specific Output Terminal Descriptor (USB-IF naming conventions).
+ *
+ * Type define for an Audio class-specific output terminal descriptor. This indicates to the host that the device
+ * contains an output audio sink, either to a physical terminal on the device, or a logical terminal (for example,
+ * a USB endpoint). See the USB Audio specification for more details.
+ *
+ * \see \ref USB_Audio_Descriptor_OutputTerminal_t for the version of this type with non-standard LUFA specific
+ * element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint8_t bLength; /**< Size of the descriptor, in bytes. */
+ uint8_t bDescriptorType; /**< Sub type value used to distinguish between audio class-specific descriptors,
+ * must be \ref AUDIO_DSUBTYPE_CSInterface_OutputTerminal.
+ */
+
+ uint8_t bDescriptorSubtype; /**< Sub type value used to distinguish between audio class-specific descriptors,
+ * a value from the \ref Audio_CSInterface_AC_SubTypes_t enum.
+ */
+ uint8_t bTerminalID; /**< ID value of this terminal unit - must be a unique value within the device. */
+ uint16_t wTerminalType; /**< Type of terminal, a \c TERMINAL_* mask. */
+ uint8_t bAssocTerminal; /**< ID of associated input terminal, for physically grouped terminals
+ * such as the speaker and microphone of a phone handset.
+ */
+ uint8_t bSourceID; /**< ID value of the unit this terminal's audio is sourced from. */
+
+ uint8_t iTerminal; /**< Index of a string descriptor describing this descriptor within the device. */
+ } ATTR_PACKED USB_Audio_StdDescriptor_OutputTerminal_t;
+
+ /** \brief Audio class-specific Interface Descriptor (LUFA naming conventions).
+ *
+ * Type define for an Audio class-specific interface descriptor. This follows a regular interface descriptor to
+ * supply extra information about the audio device's layout to the host. See the USB Audio specification for more
+ * details.
+ *
+ * \see \ref USB_Audio_StdDescriptor_Interface_AC_t for the version of this type with standard element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Header_t Header; /**< Regular descriptor header containing the descriptor's type and length. */
+ uint8_t Subtype; /**< Sub type value used to distinguish between audio class-specific descriptors,
+ * a value from the \ref Audio_CSInterface_AS_SubTypes_t enum.
+ */
+
+ uint16_t ACSpecification; /**< Binary Coded Decimal value, indicating the supported Audio Class specification version.
+ *
+ * \see \ref VERSION_BCD() utility macro.
+ */
+ uint16_t TotalLength; /**< Total length of the Audio class-specific descriptors, including this descriptor. */
+
+ uint8_t InCollection; /**< Total number of Audio Streaming interfaces linked to this Audio Control interface (must be 1). */
+ uint8_t InterfaceNumber; /**< Interface number of the associated Audio Streaming interface. */
+ } ATTR_PACKED USB_Audio_Descriptor_Interface_AC_t;
+
+ /** \brief Audio class-specific Interface Descriptor (USB-IF naming conventions).
+ *
+ * Type define for an Audio class-specific interface descriptor. This follows a regular interface descriptor to
+ * supply extra information about the audio device's layout to the host. See the USB Audio specification for more
+ * details.
+ *
+ * \see \ref USB_Audio_Descriptor_Interface_AC_t for the version of this type with non-standard LUFA specific
+ * element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint8_t bLength; /**< Size of the descriptor, in bytes. */
+ uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
+ * given by the specific class.
+ */
+
+ uint8_t bDescriptorSubtype;/**< Sub type value used to distinguish between audio class-specific descriptors,
+ * a value from the \ref Audio_CSInterface_AS_SubTypes_t enum.
+ */
+
+ uint16_t bcdADC; /**< Binary coded decimal value, indicating the supported Audio Class specification version.
+ *
+ * \see \ref VERSION_BCD() utility macro.
+ */
+ uint16_t wTotalLength; /**< Total length of the Audio class-specific descriptors, including this descriptor. */
+
+ uint8_t bInCollection; /**< Total number of Audio Streaming interfaces linked to this Audio Control interface (must be 1). */
+ uint8_t bInterfaceNumbers; /**< Interface number of the associated Audio Streaming interface. */
+ } ATTR_PACKED USB_Audio_StdDescriptor_Interface_AC_t;
+
+ /** \brief Audio class-specific Feature Unit Descriptor (LUFA naming conventions).
+ *
+ * Type define for an Audio class-specific Feature Unit descriptor. This indicates to the host what features
+ * are present in the device's audio stream for basic control, such as per-channel volume. See the USB Audio
+ * specification for more details.
+ *
+ * \see \ref USB_Audio_StdDescriptor_FeatureUnit_t for the version of this type with standard element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Header_t Header; /**< Regular descriptor header containing the descriptor's type and length. */
+ uint8_t Subtype; /**< Sub type value used to distinguish between audio class-specific descriptors,
+ * must be \ref AUDIO_DSUBTYPE_CSInterface_Feature.
+ */
+
+ uint8_t UnitID; /**< ID value of this feature unit - must be a unique value within the device. */
+ uint8_t SourceID; /**< Source ID value of the audio source input into this feature unit. */
+
+ uint8_t ControlSize; /**< Size of each element in the \c ChannelControls array. */
+ uint8_t ChannelControls[3]; /**< Feature masks for the control channel, and each separate audio channel. */
+
+ uint8_t FeatureUnitStrIndex; /**< Index of a string descriptor describing this descriptor within the device. */
+ } ATTR_PACKED USB_Audio_Descriptor_FeatureUnit_t;
+
+ /** \brief Audio class-specific Feature Unit Descriptor (USB-IF naming conventions).
+ *
+ * Type define for an Audio class-specific Feature Unit descriptor. This indicates to the host what features
+ * are present in the device's audio stream for basic control, such as per-channel volume. See the USB Audio
+ * specification for more details.
+ *
+ * \see \ref USB_Audio_Descriptor_FeatureUnit_t for the version of this type with non-standard LUFA specific
+ * element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint8_t bLength; /**< Size of the descriptor, in bytes. */
+ uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
+ * given by the specific class.
+ */
+
+ uint8_t bDescriptorSubtype; /**< Sub type value used to distinguish between audio class-specific descriptors,
+ * must be \ref AUDIO_DSUBTYPE_CSInterface_Feature.
+ */
+
+ uint8_t bUnitID; /**< ID value of this feature unit - must be a unique value within the device. */
+ uint8_t bSourceID; /**< Source ID value of the audio source input into this feature unit. */
+
+ uint8_t bControlSize; /**< Size of each element in the \c ChannelControls array. */
+ uint8_t bmaControls[3]; /**< Feature masks for the control channel, and each separate audio channel. */
+
+ uint8_t iFeature; /**< Index of a string descriptor describing this descriptor within the device. */
+ } ATTR_PACKED USB_Audio_StdDescriptor_FeatureUnit_t;
+
+ /** \brief Audio class-specific Streaming Audio Interface Descriptor (LUFA naming conventions).
+ *
+ * Type define for an Audio class-specific streaming interface descriptor. This indicates to the host
+ * how audio streams within the device are formatted. See the USB Audio specification for more details.
+ *
+ * \see \ref USB_Audio_StdDescriptor_Interface_AS_t for the version of this type with standard element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Header_t Header; /**< Regular descriptor header containing the descriptor's type and length. */
+ uint8_t Subtype; /**< Sub type value used to distinguish between audio class-specific descriptors,
+ * a value from the \ref Audio_CSInterface_AS_SubTypes_t enum.
+ */
+
+ uint8_t TerminalLink; /**< ID value of the output terminal this descriptor is describing. */
+
+ uint8_t FrameDelay; /**< Delay in frames resulting from the complete sample processing from input to output. */
+ uint16_t AudioFormat; /**< Format of the audio stream, see Audio Device Formats specification. */
+ } ATTR_PACKED USB_Audio_Descriptor_Interface_AS_t;
+
+ /** \brief Audio class-specific Streaming Audio Interface Descriptor (USB-IF naming conventions).
+ *
+ * Type define for an Audio class-specific streaming interface descriptor. This indicates to the host
+ * how audio streams within the device are formatted. See the USB Audio specification for more details.
+ *
+ * \see \ref USB_Audio_Descriptor_Interface_AS_t for the version of this type with non-standard LUFA specific
+ * element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint8_t bLength; /**< Size of the descriptor, in bytes. */
+ uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
+ * given by the specific class.
+ */
+
+ uint8_t bDescriptorSubtype; /**< Sub type value used to distinguish between audio class-specific descriptors,
+ * a value from the \ref Audio_CSInterface_AS_SubTypes_t enum.
+ */
+
+ uint8_t bTerminalLink; /**< ID value of the output terminal this descriptor is describing. */
+
+ uint8_t bDelay; /**< Delay in frames resulting from the complete sample processing from input to output. */
+ uint16_t wFormatTag; /**< Format of the audio stream, see Audio Device Formats specification. */
+ } ATTR_PACKED USB_Audio_StdDescriptor_Interface_AS_t;
+
+ /** \brief Audio class-specific Format Descriptor (LUFA naming conventions).
+ *
+ * Type define for an Audio class-specific audio format descriptor. This is used to give the host full details
+ * about the number of channels, the sample resolution, acceptable sample frequencies and encoding method used
+ * in the device's audio streams. See the USB Audio specification for more details.
+ *
+ * \attention This descriptor <b>must</b> be followed by one or more \ref USB_Audio_SampleFreq_t elements containing
+ * the continuous or discrete sample frequencies.
+ *
+ * \see \ref USB_Audio_StdDescriptor_Format_t for the version of this type with standard element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Header_t Header; /**< Regular descriptor header containing the descriptor's type and length. */
+ uint8_t Subtype; /**< Sub type value used to distinguish between audio class-specific descriptors,
+ * must be \ref AUDIO_DSUBTYPE_CSInterface_FormatType.
+ */
+
+ uint8_t FormatType; /**< Format of the audio stream, see Audio Device Formats specification. */
+ uint8_t Channels; /**< Total number of discrete channels in the stream. */
+
+ uint8_t SubFrameSize; /**< Size in bytes of each channel's sample data in the stream. */
+ uint8_t BitResolution; /**< Bits of resolution of each channel's samples in the stream. */
+
+ uint8_t TotalDiscreteSampleRates; /**< Total number of discrete sample frequencies supported by the device. When
+ * zero, this must be followed by the lower and upper continuous sampling
+ * frequencies supported by the device; otherwise, this must be followed
+ * by the given number of discrete sampling frequencies supported.
+ */
+ } ATTR_PACKED USB_Audio_Descriptor_Format_t;
+
+ /** \brief 24-Bit Audio Frequency Structure.
+ *
+ * Type define for a 24-bit audio sample frequency structure. As GCC does not contain a built in 24-bit datatype,
+ * this this structure is used to build up the value instead. Fill this structure with the \ref AUDIO_SAMPLE_FREQ() macro.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint8_t Byte1; /**< Lowest 8 bits of the 24-bit value. */
+ uint8_t Byte2; /**< Middle 8 bits of the 24-bit value. */
+ uint8_t Byte3; /**< Upper 8 bits of the 24-bit value. */
+ } ATTR_PACKED USB_Audio_SampleFreq_t;
+
+ /** \brief Audio class-specific Format Descriptor (USB-IF naming conventions).
+ *
+ * Type define for an Audio class-specific audio format descriptor. This is used to give the host full details
+ * about the number of channels, the sample resolution, acceptable sample frequencies and encoding method used
+ * in the device's audio streams. See the USB Audio specification for more details.
+ *
+ * \attention This descriptor <b>must</b> be followed by one or more 24-bit integer elements containing the continuous
+ * or discrete sample frequencies.
+ *
+ * \see \ref USB_Audio_Descriptor_Format_t for the version of this type with non-standard LUFA specific
+ * element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint8_t bLength; /**< Size of the descriptor, in bytes. */
+ uint8_t bDescriptorType; /**< Sub type value used to distinguish between audio class-specific descriptors,
+ * must be \ref AUDIO_DSUBTYPE_CSInterface_FormatType.
+ */
+
+ uint8_t bDescriptorSubtype;/**< Sub type value used to distinguish between audio class-specific descriptors,
+ * a value from the \ref Audio_CSInterface_AS_SubTypes_t enum.
+ */
+
+ uint8_t bFormatType; /**< Format of the audio stream, see Audio Device Formats specification. */
+ uint8_t bNrChannels; /**< Total number of discrete channels in the stream. */
+
+ uint8_t bSubFrameSize; /**< Size in bytes of each channel's sample data in the stream. */
+ uint8_t bBitResolution; /**< Bits of resolution of each channel's samples in the stream. */
+
+ uint8_t bSampleFrequencyType; /**< Total number of sample frequencies supported by the device. When
+ * zero, this must be followed by the lower and upper continuous sampling
+ * frequencies supported by the device; otherwise, this must be followed
+ * by the given number of discrete sampling frequencies supported.
+ */
+ } ATTR_PACKED USB_Audio_StdDescriptor_Format_t;
+
+ /** \brief Audio class-specific Streaming Endpoint Descriptor (LUFA naming conventions).
+ *
+ * Type define for an Audio class-specific endpoint descriptor. This contains a regular endpoint
+ * descriptor with a few Audio-class-specific extensions. See the USB Audio specification for more details.
+ *
+ * \see \ref USB_Audio_StdDescriptor_StreamEndpoint_Std_t for the version of this type with standard element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Endpoint_t Endpoint; /**< Standard endpoint descriptor describing the audio endpoint. */
+
+ uint8_t Refresh; /**< Always set to zero for Audio class devices. */
+ uint8_t SyncEndpointNumber; /**< Endpoint address to send synchronization information to, if needed (zero otherwise). */
+ } ATTR_PACKED USB_Audio_Descriptor_StreamEndpoint_Std_t;
+
+ /** \brief Audio class-specific Streaming Endpoint Descriptor (USB-IF naming conventions).
+ *
+ * Type define for an Audio class-specific endpoint descriptor. This contains a regular endpoint
+ * descriptor with a few Audio-class-specific extensions. See the USB Audio specification for more details.
+ *
+ * \see \ref USB_Audio_Descriptor_StreamEndpoint_Std_t for the version of this type with non-standard LUFA specific
+ * element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint8_t bLength; /**< Size of the descriptor, in bytes. */
+ uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a
+ * value given by the specific class.
+ */
+ uint8_t bEndpointAddress; /**< Logical address of the endpoint within the device for the current
+ * configuration, including direction mask.
+ */
+ uint8_t bmAttributes; /**< Endpoint attributes, comprised of a mask of the endpoint type (\c EP_TYPE_*)
+ * and attributes (\c ENDPOINT_ATTR_*) masks.
+ */
+ uint16_t wMaxPacketSize; /**< Size of the endpoint bank, in bytes. This indicates the maximum packet size
+ * that the endpoint can receive at a time.
+ */
+ uint8_t bInterval; /**< Polling interval in milliseconds for the endpoint if it is an INTERRUPT or
+ * ISOCHRONOUS type.
+ */
+
+ uint8_t bRefresh; /**< Always set to zero for Audio class devices. */
+ uint8_t bSynchAddress; /**< Endpoint address to send synchronization information to, if needed (zero otherwise). */
+ } ATTR_PACKED USB_Audio_StdDescriptor_StreamEndpoint_Std_t;
+
+ /** \brief Audio class-specific Extended Endpoint Descriptor (LUFA naming conventions).
+ *
+ * Type define for an Audio class-specific extended endpoint descriptor. This contains extra information
+ * on the usage of endpoints used to stream audio in and out of the USB Audio device, and follows an Audio
+ * class-specific extended endpoint descriptor. See the USB Audio specification for more details.
+ *
+ * \see \ref USB_Audio_StdDescriptor_StreamEndpoint_Spc_t for the version of this type with standard element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Header_t Header; /**< Regular descriptor header containing the descriptor's type and length. */
+ uint8_t Subtype; /**< Sub type value used to distinguish between audio class-specific descriptors,
+ * a value from the \ref Audio_CSEndpoint_SubTypes_t enum.
+ */
+
+ uint8_t Attributes; /**< Audio class-specific endpoint attributes, such as \ref AUDIO_EP_FULL_PACKETS_ONLY. */
+
+ uint8_t LockDelayUnits; /**< Units used for the LockDelay field, see Audio class specification. */
+ uint16_t LockDelay; /**< Time required to internally lock endpoint's internal clock recovery circuitry. */
+ } ATTR_PACKED USB_Audio_Descriptor_StreamEndpoint_Spc_t;
+
+ /** \brief Audio class-specific Extended Endpoint Descriptor (USB-IF naming conventions).
+ *
+ * Type define for an Audio class-specific extended endpoint descriptor. This contains extra information
+ * on the usage of endpoints used to stream audio in and out of the USB Audio device, and follows an Audio
+ * class-specific extended endpoint descriptor. See the USB Audio specification for more details.
+ *
+ * \see \ref USB_Audio_Descriptor_StreamEndpoint_Spc_t for the version of this type with non-standard LUFA specific
+ * element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint8_t bLength; /**< Size of the descriptor, in bytes. */
+ uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
+ * given by the specific class.
+ */
+
+ uint8_t bDescriptorSubtype; /**< Sub type value used to distinguish between audio class-specific descriptors,
+ * a value from the \ref Audio_CSEndpoint_SubTypes_t enum.
+ */
+
+ uint8_t bmAttributes; /**< Audio class-specific endpoint attributes, such as \ref AUDIO_EP_FULL_PACKETS_ONLY. */
+
+ uint8_t bLockDelayUnits; /**< Units used for the LockDelay field, see Audio class specification. */
+ uint16_t wLockDelay; /**< Time required to internally lock endpoint's internal clock recovery circuitry. */
+ } ATTR_PACKED USB_Audio_StdDescriptor_StreamEndpoint_Spc_t;
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/CDCClassCommon.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/CDCClassCommon.h
new file mode 100644
index 000000000..94e6c68db
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/CDCClassCommon.h
@@ -0,0 +1,391 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Common definitions and declarations for the library USB CDC Class driver.
+ *
+ * Common definitions and declarations for the library USB CDC Class driver.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB module driver
+ * dispatch header located in LUFA/Drivers/USB.h.
+ */
+
+/** \ingroup Group_USBClassCDC
+ * \defgroup Group_USBClassCDCCommon Common Class Definitions
+ *
+ * \section Sec_USBClassCDCCommon_ModDescription Module Description
+ * Constants, Types and Enum definitions that are common to both Device and Host modes for the USB
+ * CDC Class.
+ *
+ * @{
+ */
+
+#ifndef _CDC_CLASS_COMMON_H_
+#define _CDC_CLASS_COMMON_H_
+
+ /* Includes: */
+ #include "../../Core/StdDescriptors.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_CDC_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
+ #endif
+
+ /* Macros: */
+ /** \name Virtual Control Line Masks */
+ //@{
+ /** Mask for the DTR handshake line for use with the \ref CDC_REQ_SetControlLineState class-specific request
+ * from the host, to indicate that the DTR line state should be high.
+ */
+ #define CDC_CONTROL_LINE_OUT_DTR (1 << 0)
+
+ /** Mask for the RTS handshake line for use with the \ref CDC_REQ_SetControlLineState class-specific request
+ * from the host, to indicate that the RTS line state should be high.
+ */
+ #define CDC_CONTROL_LINE_OUT_RTS (1 << 1)
+
+ /** Mask for the DCD handshake line for use with the \ref CDC_NOTIF_SerialState class-specific notification
+ * from the device to the host, to indicate that the DCD line state is currently high.
+ */
+ #define CDC_CONTROL_LINE_IN_DCD (1 << 0)
+
+ /** Mask for the DSR handshake line for use with the \ref CDC_NOTIF_SerialState class-specific notification
+ * from the device to the host, to indicate that the DSR line state is currently high.
+ */
+ #define CDC_CONTROL_LINE_IN_DSR (1 << 1)
+
+ /** Mask for the BREAK handshake line for use with the \ref CDC_NOTIF_SerialState class-specific notification
+ * from the device to the host, to indicate that the BREAK line state is currently high.
+ */
+ #define CDC_CONTROL_LINE_IN_BREAK (1 << 2)
+
+ /** Mask for the RING handshake line for use with the \ref CDC_NOTIF_SerialState class-specific notification
+ * from the device to the host, to indicate that the RING line state is currently high.
+ */
+ #define CDC_CONTROL_LINE_IN_RING (1 << 3)
+
+ /** Mask for use with the \ref CDC_NOTIF_SerialState class-specific notification from the device to the host,
+ * to indicate that a framing error has occurred on the virtual serial port.
+ */
+ #define CDC_CONTROL_LINE_IN_FRAMEERROR (1 << 4)
+
+ /** Mask for use with the \ref CDC_NOTIF_SerialState class-specific notification from the device to the host,
+ * to indicate that a parity error has occurred on the virtual serial port.
+ */
+ #define CDC_CONTROL_LINE_IN_PARITYERROR (1 << 5)
+
+ /** Mask for use with the \ref CDC_NOTIF_SerialState class-specific notification from the device to the host,
+ * to indicate that a data overrun error has occurred on the virtual serial port.
+ */
+ #define CDC_CONTROL_LINE_IN_OVERRUNERROR (1 << 6)
+ //@}
+
+ /** Macro to define a CDC class-specific functional descriptor. CDC functional descriptors have a
+ * uniform structure but variable sized data payloads, thus cannot be represented accurately by
+ * a single \c typedef \c struct. A macro is used instead so that functional descriptors can be created
+ * easily by specifying the size of the payload. This allows \c sizeof() to work correctly.
+ *
+ * \param[in] DataSize Size in bytes of the CDC functional descriptor's data payload.
+ */
+ #define CDC_FUNCTIONAL_DESCRIPTOR(DataSize) \
+ struct \
+ { \
+ USB_Descriptor_Header_t Header; \
+ uint8_t SubType; \
+ uint8_t Data[DataSize]; \
+ }
+
+ /* Enums: */
+ /** Enum for possible Class, Subclass and Protocol values of device and interface descriptors relating to the CDC
+ * device class.
+ */
+ enum CDC_Descriptor_ClassSubclassProtocol_t
+ {
+ CDC_CSCP_CDCClass = 0x02, /**< Descriptor Class value indicating that the device or interface
+ * belongs to the CDC class.
+ */
+ CDC_CSCP_NoSpecificSubclass = 0x00, /**< Descriptor Subclass value indicating that the device or interface
+ * belongs to no specific subclass of the CDC class.
+ */
+ CDC_CSCP_ACMSubclass = 0x02, /**< Descriptor Subclass value indicating that the device or interface
+ * belongs to the Abstract Control Model CDC subclass.
+ */
+ CDC_CSCP_ATCommandProtocol = 0x01, /**< Descriptor Protocol value indicating that the device or interface
+ * belongs to the AT Command protocol of the CDC class.
+ */
+ CDC_CSCP_NoSpecificProtocol = 0x00, /**< Descriptor Protocol value indicating that the device or interface
+ * belongs to no specific protocol of the CDC class.
+ */
+ CDC_CSCP_VendorSpecificProtocol = 0xFF, /**< Descriptor Protocol value indicating that the device or interface
+ * belongs to a vendor-specific protocol of the CDC class.
+ */
+ CDC_CSCP_CDCDataClass = 0x0A, /**< Descriptor Class value indicating that the device or interface
+ * belongs to the CDC Data class.
+ */
+ CDC_CSCP_NoDataSubclass = 0x00, /**< Descriptor Subclass value indicating that the device or interface
+ * belongs to no specific subclass of the CDC data class.
+ */
+ CDC_CSCP_NoDataProtocol = 0x00, /**< Descriptor Protocol value indicating that the device or interface
+ * belongs to no specific protocol of the CDC data class.
+ */
+ };
+
+ /** Enum for the CDC class specific control requests that can be issued by the USB bus host. */
+ enum CDC_ClassRequests_t
+ {
+ CDC_REQ_SendEncapsulatedCommand = 0x00, /**< CDC class-specific request to send an encapsulated command to the device. */
+ CDC_REQ_GetEncapsulatedResponse = 0x01, /**< CDC class-specific request to retrieve an encapsulated command response from the device. */
+ CDC_REQ_SetLineEncoding = 0x20, /**< CDC class-specific request to set the current virtual serial port configuration settings. */
+ CDC_REQ_GetLineEncoding = 0x21, /**< CDC class-specific request to get the current virtual serial port configuration settings. */
+ CDC_REQ_SetControlLineState = 0x22, /**< CDC class-specific request to set the current virtual serial port handshake line states. */
+ CDC_REQ_SendBreak = 0x23, /**< CDC class-specific request to send a break to the receiver via the carrier channel. */
+ };
+
+ /** Enum for the CDC class specific notification requests that can be issued by a CDC device to a host. */
+ enum CDC_ClassNotifications_t
+ {
+ CDC_NOTIF_SerialState = 0x20, /**< Notification type constant for a change in the virtual serial port
+ * handshake line states, for use with a \ref USB_Request_Header_t
+ * notification structure when sent to the host via the CDC notification
+ * endpoint.
+ */
+ };
+
+ /** Enum for the CDC class specific interface descriptor subtypes. */
+ enum CDC_DescriptorSubtypes_t
+ {
+ CDC_DSUBTYPE_CSInterface_Header = 0x00, /**< CDC class-specific Header functional descriptor. */
+ CDC_DSUBTYPE_CSInterface_CallManagement = 0x01, /**< CDC class-specific Call Management functional descriptor. */
+ CDC_DSUBTYPE_CSInterface_ACM = 0x02, /**< CDC class-specific Abstract Control Model functional descriptor. */
+ CDC_DSUBTYPE_CSInterface_DirectLine = 0x03, /**< CDC class-specific Direct Line functional descriptor. */
+ CDC_DSUBTYPE_CSInterface_TelephoneRinger = 0x04, /**< CDC class-specific Telephone Ringer functional descriptor. */
+ CDC_DSUBTYPE_CSInterface_TelephoneCall = 0x05, /**< CDC class-specific Telephone Call functional descriptor. */
+ CDC_DSUBTYPE_CSInterface_Union = 0x06, /**< CDC class-specific Union functional descriptor. */
+ CDC_DSUBTYPE_CSInterface_CountrySelection = 0x07, /**< CDC class-specific Country Selection functional descriptor. */
+ CDC_DSUBTYPE_CSInterface_TelephoneOpModes = 0x08, /**< CDC class-specific Telephone Operation Modes functional descriptor. */
+ CDC_DSUBTYPE_CSInterface_USBTerminal = 0x09, /**< CDC class-specific USB Terminal functional descriptor. */
+ CDC_DSUBTYPE_CSInterface_NetworkChannel = 0x0A, /**< CDC class-specific Network Channel functional descriptor. */
+ CDC_DSUBTYPE_CSInterface_ProtocolUnit = 0x0B, /**< CDC class-specific Protocol Unit functional descriptor. */
+ CDC_DSUBTYPE_CSInterface_ExtensionUnit = 0x0C, /**< CDC class-specific Extension Unit functional descriptor. */
+ CDC_DSUBTYPE_CSInterface_MultiChannel = 0x0D, /**< CDC class-specific Multi-Channel Management functional descriptor. */
+ CDC_DSUBTYPE_CSInterface_CAPI = 0x0E, /**< CDC class-specific Common ISDN API functional descriptor. */
+ CDC_DSUBTYPE_CSInterface_Ethernet = 0x0F, /**< CDC class-specific Ethernet functional descriptor. */
+ CDC_DSUBTYPE_CSInterface_ATM = 0x10, /**< CDC class-specific Asynchronous Transfer Mode functional descriptor. */
+ };
+
+ /** Enum for the possible line encoding formats of a virtual serial port. */
+ enum CDC_LineEncodingFormats_t
+ {
+ CDC_LINEENCODING_OneStopBit = 0, /**< Each frame contains one stop bit. */
+ CDC_LINEENCODING_OneAndAHalfStopBits = 1, /**< Each frame contains one and a half stop bits. */
+ CDC_LINEENCODING_TwoStopBits = 2, /**< Each frame contains two stop bits. */
+ };
+
+ /** Enum for the possible line encoding parity settings of a virtual serial port. */
+ enum CDC_LineEncodingParity_t
+ {
+ CDC_PARITY_None = 0, /**< No parity bit mode on each frame. */
+ CDC_PARITY_Odd = 1, /**< Odd parity bit mode on each frame. */
+ CDC_PARITY_Even = 2, /**< Even parity bit mode on each frame. */
+ CDC_PARITY_Mark = 3, /**< Mark parity bit mode on each frame. */
+ CDC_PARITY_Space = 4, /**< Space parity bit mode on each frame. */
+ };
+
+ /* Type Defines: */
+ /** \brief CDC class-specific Functional Header Descriptor (LUFA naming conventions).
+ *
+ * Type define for a CDC class-specific functional header descriptor. This indicates to the host that the device
+ * contains one or more CDC functional data descriptors, which give the CDC interface's capabilities and configuration.
+ * See the CDC class specification for more details.
+ *
+ * \see \ref USB_CDC_StdDescriptor_FunctionalHeader_t for the version of this type with standard element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Header_t Header; /**< Regular descriptor header containing the descriptor's type and length. */
+ uint8_t Subtype; /**< Sub type value used to distinguish between CDC class-specific descriptors,
+ * must be \ref CDC_DSUBTYPE_CSInterface_Header.
+ */
+ uint16_t CDCSpecification; /**< Version number of the CDC specification implemented by the device,
+ * encoded in BCD format.
+ *
+ * \see \ref VERSION_BCD() utility macro.
+ */
+ } ATTR_PACKED USB_CDC_Descriptor_FunctionalHeader_t;
+
+ /** \brief CDC class-specific Functional Header Descriptor (USB-IF naming conventions).
+ *
+ * Type define for a CDC class-specific functional header descriptor. This indicates to the host that the device
+ * contains one or more CDC functional data descriptors, which give the CDC interface's capabilities and configuration.
+ * See the CDC class specification for more details.
+ *
+ * \see \ref USB_CDC_Descriptor_FunctionalHeader_t for the version of this type with non-standard LUFA specific
+ * element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint8_t bFunctionLength; /**< Size of the descriptor, in bytes. */
+ uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
+ * given by the specific class.
+ */
+ uint8_t bDescriptorSubType; /**< Sub type value used to distinguish between CDC class-specific descriptors,
+ * must be \ref CDC_DSUBTYPE_CSInterface_Header.
+ */
+ uint16_t bcdCDC; /**< Version number of the CDC specification implemented by the device, encoded in BCD format.
+ *
+ * \see \ref VERSION_BCD() utility macro.
+ */
+ } ATTR_PACKED USB_CDC_StdDescriptor_FunctionalHeader_t;
+
+ /** \brief CDC class-specific Functional ACM Descriptor (LUFA naming conventions).
+ *
+ * Type define for a CDC class-specific functional ACM descriptor. This indicates to the host that the CDC interface
+ * supports the CDC ACM subclass of the CDC specification. See the CDC class specification for more details.
+ *
+ * \see \ref USB_CDC_StdDescriptor_FunctionalACM_t for the version of this type with standard element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Header_t Header; /**< Regular descriptor header containing the descriptor's type and length. */
+ uint8_t Subtype; /**< Sub type value used to distinguish between CDC class-specific descriptors,
+ * must be \ref CDC_DSUBTYPE_CSInterface_ACM.
+ */
+ uint8_t Capabilities; /**< Capabilities of the ACM interface, given as a bit mask. For most devices,
+ * this should be set to a fixed value of \c 0x06 - for other capabilities, refer
+ * to the CDC ACM specification.
+ */
+ } ATTR_PACKED USB_CDC_Descriptor_FunctionalACM_t;
+
+ /** \brief CDC class-specific Functional ACM Descriptor (USB-IF naming conventions).
+ *
+ * Type define for a CDC class-specific functional ACM descriptor. This indicates to the host that the CDC interface
+ * supports the CDC ACM subclass of the CDC specification. See the CDC class specification for more details.
+ *
+ * \see \ref USB_CDC_Descriptor_FunctionalACM_t for the version of this type with non-standard LUFA specific
+ * element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint8_t bFunctionLength; /**< Size of the descriptor, in bytes. */
+ uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
+ * given by the specific class.
+ */
+ uint8_t bDescriptorSubType; /**< Sub type value used to distinguish between CDC class-specific descriptors,
+ * must be \ref CDC_DSUBTYPE_CSInterface_ACM.
+ */
+ uint8_t bmCapabilities; /**< Capabilities of the ACM interface, given as a bit mask. For most devices,
+ * this should be set to a fixed value of 0x06 - for other capabilities, refer
+ * to the CDC ACM specification.
+ */
+ } ATTR_PACKED USB_CDC_StdDescriptor_FunctionalACM_t;
+
+ /** \brief CDC class-specific Functional Union Descriptor (LUFA naming conventions).
+ *
+ * Type define for a CDC class-specific functional Union descriptor. This indicates to the host that specific
+ * CDC control and data interfaces are related. See the CDC class specification for more details.
+ *
+ * \see \ref USB_CDC_StdDescriptor_FunctionalUnion_t for the version of this type with standard element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Header_t Header; /**< Regular descriptor header containing the descriptor's type and length. */
+ uint8_t Subtype; /**< Sub type value used to distinguish between CDC class-specific descriptors,
+ * must be \ref CDC_DSUBTYPE_CSInterface_Union.
+ */
+ uint8_t MasterInterfaceNumber; /**< Interface number of the CDC Control interface. */
+ uint8_t SlaveInterfaceNumber; /**< Interface number of the CDC Data interface. */
+ } ATTR_PACKED USB_CDC_Descriptor_FunctionalUnion_t;
+
+ /** \brief CDC class-specific Functional Union Descriptor (USB-IF naming conventions).
+ *
+ * Type define for a CDC class-specific functional Union descriptor. This indicates to the host that specific
+ * CDC control and data interfaces are related. See the CDC class specification for more details.
+ *
+ * \see \ref USB_CDC_Descriptor_FunctionalUnion_t for the version of this type with non-standard LUFA specific
+ * element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint8_t bFunctionLength; /**< Size of the descriptor, in bytes. */
+ uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
+ * given by the specific class.
+ */
+ uint8_t bDescriptorSubType; /**< Sub type value used to distinguish between CDC class-specific descriptors,
+ * must be \ref CDC_DSUBTYPE_CSInterface_Union.
+ */
+ uint8_t bMasterInterface; /**< Interface number of the CDC Control interface. */
+ uint8_t bSlaveInterface0; /**< Interface number of the CDC Data interface. */
+ } ATTR_PACKED USB_CDC_StdDescriptor_FunctionalUnion_t;
+
+ /** \brief CDC Virtual Serial Port Line Encoding Settings Structure.
+ *
+ * Type define for a CDC Line Encoding structure, used to hold the various encoding parameters for a virtual
+ * serial port.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint32_t BaudRateBPS; /**< Baud rate of the virtual serial port, in bits per second. */
+ uint8_t CharFormat; /**< Character format of the virtual serial port, a value from the
+ * \ref CDC_LineEncodingFormats_t enum.
+ */
+ uint8_t ParityType; /**< Parity setting of the virtual serial port, a value from the
+ * \ref CDC_LineEncodingParity_t enum.
+ */
+ uint8_t DataBits; /**< Bits of data per character of the virtual serial port. */
+ } ATTR_PACKED CDC_LineEncoding_t;
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/HIDClassCommon.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/HIDClassCommon.h
new file mode 100644
index 000000000..9d701fbeb
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/HIDClassCommon.h
@@ -0,0 +1,682 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Common definitions and declarations for the library USB HID Class driver.
+ *
+ * Common definitions and declarations for the library USB HID Class driver.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB module driver
+ * dispatch header located in LUFA/Drivers/USB.h.
+ */
+
+/** \ingroup Group_USBClassHID
+ * \defgroup Group_USBClassHIDCommon Common Class Definitions
+ *
+ * \section Sec_USBClassHIDCommon_ModDescription Module Description
+ * Constants, Types and Enum definitions that are common to both Device and Host modes for the USB
+ * HID Class.
+ *
+ * @{
+ */
+
+#ifndef _HID_CLASS_COMMON_H_
+#define _HID_CLASS_COMMON_H_
+
+ /* Includes: */
+ #include "../../Core/StdDescriptors.h"
+ #include "HIDParser.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_HID_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
+ #endif
+
+ /* Macros: */
+ /** \name Keyboard Standard Report Modifier Masks */
+ //@{
+ /** Constant for a keyboard report modifier byte, indicating that the keyboard's left control key is currently pressed. */
+ #define HID_KEYBOARD_MODIFIER_LEFTCTRL (1 << 0)
+
+ /** Constant for a keyboard report modifier byte, indicating that the keyboard's left shift key is currently pressed. */
+ #define HID_KEYBOARD_MODIFIER_LEFTSHIFT (1 << 1)
+
+ /** Constant for a keyboard report modifier byte, indicating that the keyboard's left alt key is currently pressed. */
+ #define HID_KEYBOARD_MODIFIER_LEFTALT (1 << 2)
+
+ /** Constant for a keyboard report modifier byte, indicating that the keyboard's left GUI key is currently pressed. */
+ #define HID_KEYBOARD_MODIFIER_LEFTGUI (1 << 3)
+
+ /** Constant for a keyboard report modifier byte, indicating that the keyboard's right control key is currently pressed. */
+ #define HID_KEYBOARD_MODIFIER_RIGHTCTRL (1 << 4)
+
+ /** Constant for a keyboard report modifier byte, indicating that the keyboard's right shift key is currently pressed. */
+ #define HID_KEYBOARD_MODIFIER_RIGHTSHIFT (1 << 5)
+
+ /** Constant for a keyboard report modifier byte, indicating that the keyboard's right alt key is currently pressed. */
+ #define HID_KEYBOARD_MODIFIER_RIGHTALT (1 << 6)
+
+ /** Constant for a keyboard report modifier byte, indicating that the keyboard's right GUI key is currently pressed. */
+ #define HID_KEYBOARD_MODIFIER_RIGHTGUI (1 << 7)
+ //@}
+
+ /** \name Keyboard Standard Report LED Masks */
+ //@{
+ /** Constant for a keyboard output report LED byte, indicating that the host's NUM LOCK mode is currently set. */
+ #define HID_KEYBOARD_LED_NUMLOCK (1 << 0)
+
+ /** Constant for a keyboard output report LED byte, indicating that the host's CAPS LOCK mode is currently set. */
+ #define HID_KEYBOARD_LED_CAPSLOCK (1 << 1)
+
+ /** Constant for a keyboard output report LED byte, indicating that the host's SCROLL LOCK mode is currently set. */
+ #define HID_KEYBOARD_LED_SCROLLLOCK (1 << 2)
+
+ /** Constant for a keyboard output report LED byte, indicating that the host's COMPOSE mode is currently set. */
+ #define HID_KEYBOARD_LED_COMPOSE (1 << 3)
+
+ /** Constant for a keyboard output report LED byte, indicating that the host's KANA mode is currently set. */
+ #define HID_KEYBOARD_LED_KANA (1 << 4)
+ //@}
+
+ /** \name Keyboard Standard Report Key Scan-codes */
+ //@{
+ #define HID_KEYBOARD_SC_ERROR_ROLLOVER 0x01
+ #define HID_KEYBOARD_SC_POST_FAIL 0x02
+ #define HID_KEYBOARD_SC_ERROR_UNDEFINED 0x03
+ #define HID_KEYBOARD_SC_A 0x04
+ #define HID_KEYBOARD_SC_B 0x05
+ #define HID_KEYBOARD_SC_C 0x06
+ #define HID_KEYBOARD_SC_D 0x07
+ #define HID_KEYBOARD_SC_E 0x08
+ #define HID_KEYBOARD_SC_F 0x09
+ #define HID_KEYBOARD_SC_G 0x0A
+ #define HID_KEYBOARD_SC_H 0x0B
+ #define HID_KEYBOARD_SC_I 0x0C
+ #define HID_KEYBOARD_SC_J 0x0D
+ #define HID_KEYBOARD_SC_K 0x0E
+ #define HID_KEYBOARD_SC_L 0x0F
+ #define HID_KEYBOARD_SC_M 0x10
+ #define HID_KEYBOARD_SC_N 0x11
+ #define HID_KEYBOARD_SC_O 0x12
+ #define HID_KEYBOARD_SC_P 0x13
+ #define HID_KEYBOARD_SC_Q 0x14
+ #define HID_KEYBOARD_SC_R 0x15
+ #define HID_KEYBOARD_SC_S 0x16
+ #define HID_KEYBOARD_SC_T 0x17
+ #define HID_KEYBOARD_SC_U 0x18
+ #define HID_KEYBOARD_SC_V 0x19
+ #define HID_KEYBOARD_SC_W 0x1A
+ #define HID_KEYBOARD_SC_X 0x1B
+ #define HID_KEYBOARD_SC_Y 0x1C
+ #define HID_KEYBOARD_SC_Z 0x1D
+ #define HID_KEYBOARD_SC_1_AND_EXCLAMATION 0x1E
+ #define HID_KEYBOARD_SC_2_AND_AT 0x1F
+ #define HID_KEYBOARD_SC_3_AND_HASHMARK 0x20
+ #define HID_KEYBOARD_SC_4_AND_DOLLAR 0x21
+ #define HID_KEYBOARD_SC_5_AND_PERCENTAGE 0x22
+ #define HID_KEYBOARD_SC_6_AND_CARET 0x23
+ #define HID_KEYBOARD_SC_7_AND_AMPERSAND 0x24
+ #define HID_KEYBOARD_SC_8_AND_ASTERISK 0x25
+ #define HID_KEYBOARD_SC_9_AND_OPENING_PARENTHESIS 0x26
+ #define HID_KEYBOARD_SC_0_AND_CLOSING_PARENTHESIS 0x27
+ #define HID_KEYBOARD_SC_ENTER 0x28
+ #define HID_KEYBOARD_SC_ESCAPE 0x29
+ #define HID_KEYBOARD_SC_BACKSPACE 0x2A
+ #define HID_KEYBOARD_SC_TAB 0x2B
+ #define HID_KEYBOARD_SC_SPACE 0x2C
+ #define HID_KEYBOARD_SC_MINUS_AND_UNDERSCORE 0x2D
+ #define HID_KEYBOARD_SC_EQUAL_AND_PLUS 0x2E
+ #define HID_KEYBOARD_SC_OPENING_BRACKET_AND_OPENING_BRACE 0x2F
+ #define HID_KEYBOARD_SC_CLOSING_BRACKET_AND_CLOSING_BRACE 0x30
+ #define HID_KEYBOARD_SC_BACKSLASH_AND_PIPE 0x31
+ #define HID_KEYBOARD_SC_NON_US_HASHMARK_AND_TILDE 0x32
+ #define HID_KEYBOARD_SC_SEMICOLON_AND_COLON 0x33
+ #define HID_KEYBOARD_SC_APOSTROPHE_AND_QUOTE 0x34
+ #define HID_KEYBOARD_SC_GRAVE_ACCENT_AND_TILDE 0x35
+ #define HID_KEYBOARD_SC_COMMA_AND_LESS_THAN_SIGN 0x36
+ #define HID_KEYBOARD_SC_DOT_AND_GREATER_THAN_SIGN 0x37
+ #define HID_KEYBOARD_SC_SLASH_AND_QUESTION_MARK 0x38
+ #define HID_KEYBOARD_SC_CAPS_LOCK 0x39
+ #define HID_KEYBOARD_SC_F1 0x3A
+ #define HID_KEYBOARD_SC_F2 0x3B
+ #define HID_KEYBOARD_SC_F3 0x3C
+ #define HID_KEYBOARD_SC_F4 0x3D
+ #define HID_KEYBOARD_SC_F5 0x3E
+ #define HID_KEYBOARD_SC_F6 0x3F
+ #define HID_KEYBOARD_SC_F7 0x40
+ #define HID_KEYBOARD_SC_F8 0x41
+ #define HID_KEYBOARD_SC_F9 0x42
+ #define HID_KEYBOARD_SC_F10 0x43
+ #define HID_KEYBOARD_SC_F11 0x44
+ #define HID_KEYBOARD_SC_F12 0x45
+ #define HID_KEYBOARD_SC_PRINT_SCREEN 0x46
+ #define HID_KEYBOARD_SC_SCROLL_LOCK 0x47
+ #define HID_KEYBOARD_SC_PAUSE 0x48
+ #define HID_KEYBOARD_SC_INSERT 0x49
+ #define HID_KEYBOARD_SC_HOME 0x4A
+ #define HID_KEYBOARD_SC_PAGE_UP 0x4B
+ #define HID_KEYBOARD_SC_DELETE 0x4C
+ #define HID_KEYBOARD_SC_END 0x4D
+ #define HID_KEYBOARD_SC_PAGE_DOWN 0x4E
+ #define HID_KEYBOARD_SC_RIGHT_ARROW 0x4F
+ #define HID_KEYBOARD_SC_LEFT_ARROW 0x50
+ #define HID_KEYBOARD_SC_DOWN_ARROW 0x51
+ #define HID_KEYBOARD_SC_UP_ARROW 0x52
+ #define HID_KEYBOARD_SC_NUM_LOCK 0x53
+ #define HID_KEYBOARD_SC_KEYPAD_SLASH 0x54
+ #define HID_KEYBOARD_SC_KEYPAD_ASTERISK 0x55
+ #define HID_KEYBOARD_SC_KEYPAD_MINUS 0x56
+ #define HID_KEYBOARD_SC_KEYPAD_PLUS 0x57
+ #define HID_KEYBOARD_SC_KEYPAD_ENTER 0x58
+ #define HID_KEYBOARD_SC_KEYPAD_1_AND_END 0x59
+ #define HID_KEYBOARD_SC_KEYPAD_2_AND_DOWN_ARROW 0x5A
+ #define HID_KEYBOARD_SC_KEYPAD_3_AND_PAGE_DOWN 0x5B
+ #define HID_KEYBOARD_SC_KEYPAD_4_AND_LEFT_ARROW 0x5C
+ #define HID_KEYBOARD_SC_KEYPAD_5 0x5D
+ #define HID_KEYBOARD_SC_KEYPAD_6_AND_RIGHT_ARROW 0x5E
+ #define HID_KEYBOARD_SC_KEYPAD_7_AND_HOME 0x5F
+ #define HID_KEYBOARD_SC_KEYPAD_8_AND_UP_ARROW 0x60
+ #define HID_KEYBOARD_SC_KEYPAD_9_AND_PAGE_UP 0x61
+ #define HID_KEYBOARD_SC_KEYPAD_0_AND_INSERT 0x62
+ #define HID_KEYBOARD_SC_KEYPAD_DOT_AND_DELETE 0x63
+ #define HID_KEYBOARD_SC_NON_US_BACKSLASH_AND_PIPE 0x64
+ #define HID_KEYBOARD_SC_APPLICATION 0x65
+ #define HID_KEYBOARD_SC_POWER 0x66
+ #define HID_KEYBOARD_SC_KEYPAD_EQUAL_SIGN 0x67
+ #define HID_KEYBOARD_SC_F13 0x68
+ #define HID_KEYBOARD_SC_F14 0x69
+ #define HID_KEYBOARD_SC_F15 0x6A
+ #define HID_KEYBOARD_SC_F16 0x6B
+ #define HID_KEYBOARD_SC_F17 0x6C
+ #define HID_KEYBOARD_SC_F18 0x6D
+ #define HID_KEYBOARD_SC_F19 0x6E
+ #define HID_KEYBOARD_SC_F20 0x6F
+ #define HID_KEYBOARD_SC_F21 0x70
+ #define HID_KEYBOARD_SC_F22 0x71
+ #define HID_KEYBOARD_SC_F23 0x72
+ #define HID_KEYBOARD_SC_F24 0x73
+ #define HID_KEYBOARD_SC_EXECUTE 0x74
+ #define HID_KEYBOARD_SC_HELP 0x75
+ #define HID_KEYBOARD_SC_MENU 0x76
+ #define HID_KEYBOARD_SC_SELECT 0x77
+ #define HID_KEYBOARD_SC_STOP 0x78
+ #define HID_KEYBOARD_SC_AGAIN 0x79
+ #define HID_KEYBOARD_SC_UNDO 0x7A
+ #define HID_KEYBOARD_SC_CUT 0x7B
+ #define HID_KEYBOARD_SC_COPY 0x7C
+ #define HID_KEYBOARD_SC_PASTE 0x7D
+ #define HID_KEYBOARD_SC_FIND 0x7E
+ #define HID_KEYBOARD_SC_MUTE 0x7F
+ #define HID_KEYBOARD_SC_VOLUME_UP 0x80
+ #define HID_KEYBOARD_SC_VOLUME_DOWN 0x81
+ #define HID_KEYBOARD_SC_LOCKING_CAPS_LOCK 0x82
+ #define HID_KEYBOARD_SC_LOCKING_NUM_LOCK 0x83
+ #define HID_KEYBOARD_SC_LOCKING_SCROLL_LOCK 0x84
+ #define HID_KEYBOARD_SC_KEYPAD_COMMA 0x85
+ #define HID_KEYBOARD_SC_KEYPAD_EQUAL_SIGN_AS400 0x86
+ #define HID_KEYBOARD_SC_INTERNATIONAL1 0x87
+ #define HID_KEYBOARD_SC_INTERNATIONAL2 0x88
+ #define HID_KEYBOARD_SC_INTERNATIONAL3 0x89
+ #define HID_KEYBOARD_SC_INTERNATIONAL4 0x8A
+ #define HID_KEYBOARD_SC_INTERNATIONAL5 0x8B
+ #define HID_KEYBOARD_SC_INTERNATIONAL6 0x8C
+ #define HID_KEYBOARD_SC_INTERNATIONAL7 0x8D
+ #define HID_KEYBOARD_SC_INTERNATIONAL8 0x8E
+ #define HID_KEYBOARD_SC_INTERNATIONAL9 0x8F
+ #define HID_KEYBOARD_SC_LANG1 0x90
+ #define HID_KEYBOARD_SC_LANG2 0x91
+ #define HID_KEYBOARD_SC_LANG3 0x92
+ #define HID_KEYBOARD_SC_LANG4 0x93
+ #define HID_KEYBOARD_SC_LANG5 0x94
+ #define HID_KEYBOARD_SC_LANG6 0x95
+ #define HID_KEYBOARD_SC_LANG7 0x96
+ #define HID_KEYBOARD_SC_LANG8 0x97
+ #define HID_KEYBOARD_SC_LANG9 0x98
+ #define HID_KEYBOARD_SC_ALTERNATE_ERASE 0x99
+ #define HID_KEYBOARD_SC_SYSREQ 0x9A
+ #define HID_KEYBOARD_SC_CANCEL 0x9B
+ #define HID_KEYBOARD_SC_CLEAR 0x9C
+ #define HID_KEYBOARD_SC_PRIOR 0x9D
+ #define HID_KEYBOARD_SC_RETURN 0x9E
+ #define HID_KEYBOARD_SC_SEPARATOR 0x9F
+ #define HID_KEYBOARD_SC_OUT 0xA0
+ #define HID_KEYBOARD_SC_OPER 0xA1
+ #define HID_KEYBOARD_SC_CLEAR_AND_AGAIN 0xA2
+ #define HID_KEYBOARD_SC_CRSEL_AND_PROPS 0xA3
+ #define HID_KEYBOARD_SC_EXSEL 0xA4
+ #define HID_KEYBOARD_SC_KEYPAD_00 0xB0
+ #define HID_KEYBOARD_SC_KEYPAD_000 0xB1
+ #define HID_KEYBOARD_SC_THOUSANDS_SEPARATOR 0xB2
+ #define HID_KEYBOARD_SC_DECIMAL_SEPARATOR 0xB3
+ #define HID_KEYBOARD_SC_CURRENCY_UNIT 0xB4
+ #define HID_KEYBOARD_SC_CURRENCY_SUB_UNIT 0xB5
+ #define HID_KEYBOARD_SC_KEYPAD_OPENING_PARENTHESIS 0xB6
+ #define HID_KEYBOARD_SC_KEYPAD_CLOSING_PARENTHESIS 0xB7
+ #define HID_KEYBOARD_SC_KEYPAD_OPENING_BRACE 0xB8
+ #define HID_KEYBOARD_SC_KEYPAD_CLOSING_BRACE 0xB9
+ #define HID_KEYBOARD_SC_KEYPAD_TAB 0xBA
+ #define HID_KEYBOARD_SC_KEYPAD_BACKSPACE 0xBB
+ #define HID_KEYBOARD_SC_KEYPAD_A 0xBC
+ #define HID_KEYBOARD_SC_KEYPAD_B 0xBD
+ #define HID_KEYBOARD_SC_KEYPAD_C 0xBE
+ #define HID_KEYBOARD_SC_KEYPAD_D 0xBF
+ #define HID_KEYBOARD_SC_KEYPAD_E 0xC0
+ #define HID_KEYBOARD_SC_KEYPAD_F 0xC1
+ #define HID_KEYBOARD_SC_KEYPAD_XOR 0xC2
+ #define HID_KEYBOARD_SC_KEYPAD_CARET 0xC3
+ #define HID_KEYBOARD_SC_KEYPAD_PERCENTAGE 0xC4
+ #define HID_KEYBOARD_SC_KEYPAD_LESS_THAN_SIGN 0xC5
+ #define HID_KEYBOARD_SC_KEYPAD_GREATER_THAN_SIGN 0xC6
+ #define HID_KEYBOARD_SC_KEYPAD_AMP 0xC7
+ #define HID_KEYBOARD_SC_KEYPAD_AMP_AMP 0xC8
+ #define HID_KEYBOARD_SC_KEYPAD_PIPE 0xC9
+ #define HID_KEYBOARD_SC_KEYPAD_PIPE_PIPE 0xCA
+ #define HID_KEYBOARD_SC_KEYPAD_COLON 0xCB
+ #define HID_KEYBOARD_SC_KEYPAD_HASHMARK 0xCC
+ #define HID_KEYBOARD_SC_KEYPAD_SPACE 0xCD
+ #define HID_KEYBOARD_SC_KEYPAD_AT 0xCE
+ #define HID_KEYBOARD_SC_KEYPAD_EXCLAMATION_SIGN 0xCF
+ #define HID_KEYBOARD_SC_KEYPAD_MEMORY_STORE 0xD0
+ #define HID_KEYBOARD_SC_KEYPAD_MEMORY_RECALL 0xD1
+ #define HID_KEYBOARD_SC_KEYPAD_MEMORY_CLEAR 0xD2
+ #define HID_KEYBOARD_SC_KEYPAD_MEMORY_ADD 0xD3
+ #define HID_KEYBOARD_SC_KEYPAD_MEMORY_SUBTRACT 0xD4
+ #define HID_KEYBOARD_SC_KEYPAD_MEMORY_MULTIPLY 0xD5
+ #define HID_KEYBOARD_SC_KEYPAD_MEMORY_DIVIDE 0xD6
+ #define HID_KEYBOARD_SC_KEYPAD_PLUS_AND_MINUS 0xD7
+ #define HID_KEYBOARD_SC_KEYPAD_CLEAR 0xD8
+ #define HID_KEYBOARD_SC_KEYPAD_CLEAR_ENTRY 0xD9
+ #define HID_KEYBOARD_SC_KEYPAD_BINARY 0xDA
+ #define HID_KEYBOARD_SC_KEYPAD_OCTAL 0xDB
+ #define HID_KEYBOARD_SC_KEYPAD_DECIMAL 0xDC
+ #define HID_KEYBOARD_SC_KEYPAD_HEXADECIMAL 0xDD
+ #define HID_KEYBOARD_SC_LEFT_CONTROL 0xE0
+ #define HID_KEYBOARD_SC_LEFT_SHIFT 0xE1
+ #define HID_KEYBOARD_SC_LEFT_ALT 0xE2
+ #define HID_KEYBOARD_SC_LEFT_GUI 0xE3
+ #define HID_KEYBOARD_SC_RIGHT_CONTROL 0xE4
+ #define HID_KEYBOARD_SC_RIGHT_SHIFT 0xE5
+ #define HID_KEYBOARD_SC_RIGHT_ALT 0xE6
+ #define HID_KEYBOARD_SC_RIGHT_GUI 0xE7
+ #define HID_KEYBOARD_SC_MEDIA_PLAY 0xE8
+ #define HID_KEYBOARD_SC_MEDIA_STOP 0xE9
+ #define HID_KEYBOARD_SC_MEDIA_PREVIOUS_TRACK 0xEA
+ #define HID_KEYBOARD_SC_MEDIA_NEXT_TRACK 0xEB
+ #define HID_KEYBOARD_SC_MEDIA_EJECT 0xEC
+ #define HID_KEYBOARD_SC_MEDIA_VOLUME_UP 0xED
+ #define HID_KEYBOARD_SC_MEDIA_VOLUME_DOWN 0xEE
+ #define HID_KEYBOARD_SC_MEDIA_MUTE 0xEF
+ #define HID_KEYBOARD_SC_MEDIA_WWW 0xF0
+ #define HID_KEYBOARD_SC_MEDIA_BACKWARD 0xF1
+ #define HID_KEYBOARD_SC_MEDIA_FORWARD 0xF2
+ #define HID_KEYBOARD_SC_MEDIA_CANCEL 0xF3
+ #define HID_KEYBOARD_SC_MEDIA_SEARCH 0xF4
+ #define HID_KEYBOARD_SC_MEDIA_SLEEP 0xF8
+ #define HID_KEYBOARD_SC_MEDIA_LOCK 0xF9
+ #define HID_KEYBOARD_SC_MEDIA_RELOAD 0xFA
+ #define HID_KEYBOARD_SC_MEDIA_CALCULATOR 0xFB
+ //@}
+
+ /** \name Common HID Device Report Descriptors */
+ //@{
+ /** \hideinitializer
+ * A list of HID report item array elements that describe a typical HID USB Joystick. The resulting report
+ * descriptor is structured according to the following layout:
+ *
+ * \code
+ * struct
+ * {
+ * intA_t X; // Signed X axis value
+ * intA_t Y; // Signed Y axis value
+ * intA_t Z; // Signed Z axis value
+ * uintB_t Buttons; // Pressed buttons bitmask
+ * } Joystick_Report;
+ * \endcode
+ *
+ * Where \c uintA_t is a type large enough to hold the ranges of the signed \c MinAxisVal and \c MaxAxisVal values,
+ * and \c intB_t is a type large enough to hold one bit per button.
+ *
+ * \param[in] MinAxisVal Minimum logical axis value (16-bit).
+ * \param[in] MaxAxisVal Maximum logical axis value (16-bit).
+ * \param[in] MinPhysicalVal Minimum physical axis value, for movement resolution calculations (16-bit).
+ * \param[in] MaxPhysicalVal Maximum physical axis value, for movement resolution calculations (16-bit).
+ * \param[in] Buttons Total number of buttons in the device (8-bit).
+ */
+ #define HID_DESCRIPTOR_JOYSTICK(MinAxisVal, MaxAxisVal, MinPhysicalVal, MaxPhysicalVal, Buttons) \
+ HID_RI_USAGE_PAGE(8, 0x01), \
+ HID_RI_USAGE(8, 0x04), \
+ HID_RI_COLLECTION(8, 0x01), \
+ HID_RI_USAGE(8, 0x01), \
+ HID_RI_COLLECTION(8, 0x00), \
+ HID_RI_USAGE(8, 0x30), \
+ HID_RI_USAGE(8, 0x31), \
+ HID_RI_USAGE(8, 0x32), \
+ HID_RI_LOGICAL_MINIMUM(16, MinAxisVal), \
+ HID_RI_LOGICAL_MAXIMUM(16, MaxAxisVal), \
+ HID_RI_PHYSICAL_MINIMUM(16, MinPhysicalVal), \
+ HID_RI_PHYSICAL_MAXIMUM(16, MaxPhysicalVal), \
+ HID_RI_REPORT_COUNT(8, 3), \
+ HID_RI_REPORT_SIZE(8, (((MinAxisVal >= -128) && (MaxAxisVal <= 127)) ? 8 : 16)), \
+ HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), \
+ HID_RI_END_COLLECTION(0), \
+ HID_RI_USAGE_PAGE(8, 0x09), \
+ HID_RI_USAGE_MINIMUM(8, 0x01), \
+ HID_RI_USAGE_MAXIMUM(8, Buttons), \
+ HID_RI_LOGICAL_MINIMUM(8, 0x00), \
+ HID_RI_LOGICAL_MAXIMUM(8, 0x01), \
+ HID_RI_REPORT_SIZE(8, 0x01), \
+ HID_RI_REPORT_COUNT(8, Buttons), \
+ HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), \
+ HID_RI_REPORT_SIZE(8, (Buttons % 8) ? (8 - (Buttons % 8)) : 0), \
+ HID_RI_REPORT_COUNT(8, 0x01), \
+ HID_RI_INPUT(8, HID_IOF_CONSTANT), \
+ HID_RI_END_COLLECTION(0)
+
+ /** \hideinitializer
+ * A list of HID report item array elements that describe a typical HID USB keyboard. The resulting report descriptor
+ * is compatible with \ref USB_KeyboardReport_Data_t when \c MaxKeys is equal to 6. For other values, the report will
+ * be structured according to the following layout:
+ *
+ * \code
+ * struct
+ * {
+ * uint8_t Modifier; // Keyboard modifier byte indicating pressed modifier keys (\c HID_KEYBOARD_MODIFER_* masks)
+ * uint8_t Reserved; // Reserved for OEM use, always set to 0.
+ * uint8_t KeyCode[MaxKeys]; // Length determined by the number of keys that can be reported
+ * } Keyboard_Report;
+ * \endcode
+ *
+ * \param[in] MaxKeys Number of simultaneous keys that can be reported at the one time (8-bit).
+ */
+ #define HID_DESCRIPTOR_KEYBOARD(MaxKeys) \
+ HID_RI_USAGE_PAGE(8, 0x01), \
+ HID_RI_USAGE(8, 0x06), \
+ HID_RI_COLLECTION(8, 0x01), \
+ HID_RI_USAGE_PAGE(8, 0x07), \
+ HID_RI_USAGE_MINIMUM(8, 0xE0), \
+ HID_RI_USAGE_MAXIMUM(8, 0xE7), \
+ HID_RI_LOGICAL_MINIMUM(8, 0x00), \
+ HID_RI_LOGICAL_MAXIMUM(8, 0x01), \
+ HID_RI_REPORT_SIZE(8, 0x01), \
+ HID_RI_REPORT_COUNT(8, 0x08), \
+ HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), \
+ HID_RI_REPORT_COUNT(8, 0x01), \
+ HID_RI_REPORT_SIZE(8, 0x08), \
+ HID_RI_INPUT(8, HID_IOF_CONSTANT), \
+ HID_RI_USAGE_PAGE(8, 0x08), \
+ HID_RI_USAGE_MINIMUM(8, 0x01), \
+ HID_RI_USAGE_MAXIMUM(8, 0x05), \
+ HID_RI_REPORT_COUNT(8, 0x05), \
+ HID_RI_REPORT_SIZE(8, 0x01), \
+ HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE), \
+ HID_RI_REPORT_COUNT(8, 0x01), \
+ HID_RI_REPORT_SIZE(8, 0x03), \
+ HID_RI_OUTPUT(8, HID_IOF_CONSTANT), \
+ HID_RI_LOGICAL_MINIMUM(8, 0x00), \
+ HID_RI_LOGICAL_MAXIMUM(8, 0xFF), \
+ HID_RI_USAGE_PAGE(8, 0x07), \
+ HID_RI_USAGE_MINIMUM(8, 0x00), \
+ HID_RI_USAGE_MAXIMUM(8, 0xFF), \
+ HID_RI_REPORT_COUNT(8, MaxKeys), \
+ HID_RI_REPORT_SIZE(8, 0x08), \
+ HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE), \
+ HID_RI_END_COLLECTION(0)
+
+ /** \hideinitializer
+ * A list of HID report item array elements that describe a typical HID USB mouse. The resulting report descriptor
+ * is compatible with \ref USB_MouseReport_Data_t if the \c MinAxisVal and \c MaxAxisVal values fit within a \c int8_t range
+ * and the number of Buttons is less than 8. For other values, the report is structured according to the following layout:
+ *
+ * \code
+ * struct
+ * {
+ * uintA_t Buttons; // Pressed buttons bitmask
+ * intB_t X; // X axis value
+ * intB_t Y; // Y axis value
+ * } Mouse_Report;
+ * \endcode
+ *
+ * Where \c intA_t is a type large enough to hold one bit per button, and \c intB_t is a type large enough to hold the
+ * ranges of the signed \c MinAxisVal and \c MaxAxisVal values.
+ *
+ * \param[in] MinAxisVal Minimum X/Y logical axis value (16-bit).
+ * \param[in] MaxAxisVal Maximum X/Y logical axis value (16-bit).
+ * \param[in] MinPhysicalVal Minimum X/Y physical axis value, for movement resolution calculations (16-bit).
+ * \param[in] MaxPhysicalVal Maximum X/Y physical axis value, for movement resolution calculations (16-bit).
+ * \param[in] Buttons Total number of buttons in the device (8-bit).
+ * \param[in] AbsoluteCoords Boolean \c true to use absolute X/Y coordinates (e.g. touchscreen).
+ */
+ #define HID_DESCRIPTOR_MOUSE(MinAxisVal, MaxAxisVal, MinPhysicalVal, MaxPhysicalVal, Buttons, AbsoluteCoords) \
+ HID_RI_USAGE_PAGE(8, 0x01), \
+ HID_RI_USAGE(8, 0x02), \
+ HID_RI_COLLECTION(8, 0x01), \
+ HID_RI_USAGE(8, 0x01), \
+ HID_RI_COLLECTION(8, 0x00), \
+ HID_RI_USAGE_PAGE(8, 0x09), \
+ HID_RI_USAGE_MINIMUM(8, 0x01), \
+ HID_RI_USAGE_MAXIMUM(8, Buttons), \
+ HID_RI_LOGICAL_MINIMUM(8, 0x00), \
+ HID_RI_LOGICAL_MAXIMUM(8, 0x01), \
+ HID_RI_REPORT_COUNT(8, Buttons), \
+ HID_RI_REPORT_SIZE(8, 0x01), \
+ HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), \
+ HID_RI_REPORT_COUNT(8, 0x01), \
+ HID_RI_REPORT_SIZE(8, (Buttons % 8) ? (8 - (Buttons % 8)) : 0), \
+ HID_RI_INPUT(8, HID_IOF_CONSTANT), \
+ HID_RI_USAGE_PAGE(8, 0x01), \
+ HID_RI_USAGE(8, 0x30), \
+ HID_RI_USAGE(8, 0x31), \
+ HID_RI_LOGICAL_MINIMUM(16, MinAxisVal), \
+ HID_RI_LOGICAL_MAXIMUM(16, MaxAxisVal), \
+ HID_RI_PHYSICAL_MINIMUM(16, MinPhysicalVal), \
+ HID_RI_PHYSICAL_MAXIMUM(16, MaxPhysicalVal), \
+ HID_RI_REPORT_COUNT(8, 0x02), \
+ HID_RI_REPORT_SIZE(8, (((MinAxisVal >= -128) && (MaxAxisVal <= 127)) ? 8 : 16)), \
+ HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | (AbsoluteCoords ? HID_IOF_ABSOLUTE : HID_IOF_RELATIVE)), \
+ HID_RI_END_COLLECTION(0), \
+ HID_RI_END_COLLECTION(0)
+
+ /** \hideinitializer
+ * A list of HID report item array elements that describe a typical Vendor Defined byte array HID report descriptor,
+ * used for transporting arbitrary data between the USB host and device via HID reports. The resulting report should be
+ * a \c uint8_t byte array of the specified length in both Device to Host (IN) and Host to Device (OUT) directions.
+ *
+ * \param[in] VendorPageNum Vendor Defined HID Usage Page index, ranging from 0x00 to 0xFF.
+ * \param[in] CollectionUsage Vendor Usage for the encompassing report IN and OUT collection, ranging from 0x00 to 0xFF.
+ * \param[in] DataINUsage Vendor Usage for the IN report data, ranging from 0x00 to 0xFF.
+ * \param[in] DataOUTUsage Vendor Usage for the OUT report data, ranging from 0x00 to 0xFF.
+ * \param[in] NumBytes Length of the data IN and OUT reports.
+ */
+ #define HID_DESCRIPTOR_VENDOR(VendorPageNum, CollectionUsage, DataINUsage, DataOUTUsage, NumBytes) \
+ HID_RI_USAGE_PAGE(16, (0xFF00 | VendorPageNum)), \
+ HID_RI_USAGE(8, CollectionUsage), \
+ HID_RI_COLLECTION(8, 0x01), \
+ HID_RI_USAGE(8, DataINUsage), \
+ HID_RI_LOGICAL_MINIMUM(8, 0x00), \
+ HID_RI_LOGICAL_MAXIMUM(8, 0xFF), \
+ HID_RI_REPORT_SIZE(8, 0x08), \
+ HID_RI_REPORT_COUNT(8, NumBytes), \
+ HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), \
+ HID_RI_USAGE(8, DataOUTUsage), \
+ HID_RI_LOGICAL_MINIMUM(8, 0x00), \
+ HID_RI_LOGICAL_MAXIMUM(8, 0xFF), \
+ HID_RI_REPORT_SIZE(8, 0x08), \
+ HID_RI_REPORT_COUNT(8, NumBytes), \
+ HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE), \
+ HID_RI_END_COLLECTION(0)
+ //@}
+
+ /* Type Defines: */
+ /** Enum for possible Class, Subclass and Protocol values of device and interface descriptors relating to the HID
+ * device class.
+ */
+ enum HID_Descriptor_ClassSubclassProtocol_t
+ {
+ HID_CSCP_HIDClass = 0x03, /**< Descriptor Class value indicating that the device or interface
+ * belongs to the HID class.
+ */
+ HID_CSCP_NonBootSubclass = 0x00, /**< Descriptor Subclass value indicating that the device or interface
+ * does not implement a HID boot protocol.
+ */
+ HID_CSCP_BootSubclass = 0x01, /**< Descriptor Subclass value indicating that the device or interface
+ * implements a HID boot protocol.
+ */
+ HID_CSCP_NonBootProtocol = 0x00, /**< Descriptor Protocol value indicating that the device or interface
+ * does not belong to a HID boot protocol.
+ */
+ HID_CSCP_KeyboardBootProtocol = 0x01, /**< Descriptor Protocol value indicating that the device or interface
+ * belongs to the Keyboard HID boot protocol.
+ */
+ HID_CSCP_MouseBootProtocol = 0x02, /**< Descriptor Protocol value indicating that the device or interface
+ * belongs to the Mouse HID boot protocol.
+ */
+ };
+
+ /** Enum for the HID class specific control requests that can be issued by the USB bus host. */
+ enum HID_ClassRequests_t
+ {
+ HID_REQ_GetReport = 0x01, /**< HID class-specific Request to get the current HID report from the device. */
+ HID_REQ_GetIdle = 0x02, /**< HID class-specific Request to get the current device idle count. */
+ HID_REQ_GetProtocol = 0x03, /**< HID class-specific Request to get the current HID report protocol mode. */
+ HID_REQ_SetReport = 0x09, /**< HID class-specific Request to set the current HID report to the device. */
+ HID_REQ_SetIdle = 0x0A, /**< HID class-specific Request to set the device's idle count. */
+ HID_REQ_SetProtocol = 0x0B, /**< HID class-specific Request to set the current HID report protocol mode. */
+ };
+
+ /** Enum for the HID class specific descriptor types. */
+ enum HID_DescriptorTypes_t
+ {
+ HID_DTYPE_HID = 0x21, /**< Descriptor header type value, to indicate a HID class HID descriptor. */
+ HID_DTYPE_Report = 0x22, /**< Descriptor header type value, to indicate a HID class HID report descriptor. */
+ };
+
+ /** Enum for the different types of HID reports. */
+ enum HID_ReportItemTypes_t
+ {
+ HID_REPORT_ITEM_In = 0, /**< Indicates that the item is an IN report type. */
+ HID_REPORT_ITEM_Out = 1, /**< Indicates that the item is an OUT report type. */
+ HID_REPORT_ITEM_Feature = 2, /**< Indicates that the item is a FEATURE report type. */
+ };
+
+ /** \brief HID class-specific HID Descriptor (LUFA naming conventions).
+ *
+ * Type define for the HID class-specific HID descriptor, to describe the HID device's specifications. Refer to the HID
+ * specification for details on the structure elements.
+ *
+ * \see \ref USB_HID_StdDescriptor_HID_t for the version of this type with standard element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Header_t Header; /**< Regular descriptor header containing the descriptor's type and length. */
+
+ uint16_t HIDSpec; /**< BCD encoded version that the HID descriptor and device complies to.
+ *
+ * \see \ref VERSION_BCD() utility macro.
+ */
+ uint8_t CountryCode; /**< Country code of the localized device, or zero if universal. */
+
+ uint8_t TotalReportDescriptors; /**< Total number of HID report descriptors for the interface. */
+
+ uint8_t HIDReportType; /**< Type of HID report, set to \ref HID_DTYPE_Report. */
+ uint16_t HIDReportLength; /**< Length of the associated HID report descriptor, in bytes. */
+ } ATTR_PACKED USB_HID_Descriptor_HID_t;
+
+ /** \brief HID class-specific HID Descriptor (USB-IF naming conventions).
+ *
+ * Type define for the HID class-specific HID descriptor, to describe the HID device's specifications. Refer to the HID
+ * specification for details on the structure elements.
+ *
+ * \see \ref USB_HID_Descriptor_HID_t for the version of this type with non-standard LUFA specific
+ * element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint8_t bLength; /**< Size of the descriptor, in bytes. */
+ uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
+ * given by the specific class.
+ */
+
+ uint16_t bcdHID; /**< BCD encoded version that the HID descriptor and device complies to.
+ *
+ * \see \ref VERSION_BCD() utility macro.
+ */
+ uint8_t bCountryCode; /**< Country code of the localized device, or zero if universal. */
+
+ uint8_t bNumDescriptors; /**< Total number of HID report descriptors for the interface. */
+
+ uint8_t bDescriptorType2; /**< Type of HID report, set to \ref HID_DTYPE_Report. */
+ uint16_t wDescriptorLength; /**< Length of the associated HID report descriptor, in bytes. */
+ } ATTR_PACKED USB_HID_StdDescriptor_HID_t;
+
+ /** \brief Standard HID Boot Protocol Mouse Report.
+ *
+ * Type define for a standard Boot Protocol Mouse report
+ */
+ typedef struct
+ {
+ uint8_t Button; /**< Button mask for currently pressed buttons in the mouse. */
+ int8_t X; /**< Current delta X movement of the mouse. */
+ int8_t Y; /**< Current delta Y movement on the mouse. */
+ } ATTR_PACKED USB_MouseReport_Data_t;
+
+ /** \brief Standard HID Boot Protocol Keyboard Report.
+ *
+ * Type define for a standard Boot Protocol Keyboard report
+ */
+ typedef struct
+ {
+ uint8_t Modifier; /**< Keyboard modifier byte, indicating pressed modifier keys (a combination of
+ * \c HID_KEYBOARD_MODIFER_* masks).
+ */
+ uint8_t Reserved; /**< Reserved for OEM use, always set to 0. */
+ uint8_t KeyCode[6]; /**< Key codes of the currently pressed keys. */
+ } ATTR_PACKED USB_KeyboardReport_Data_t;
+
+ /** Type define for the data type used to store HID report descriptor elements. */
+ typedef uint8_t USB_Descriptor_HIDReport_Datatype_t;
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/HIDParser.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/HIDParser.c
new file mode 100644
index 000000000..d93508f49
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/HIDParser.c
@@ -0,0 +1,389 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#define __INCLUDE_FROM_USB_DRIVER
+#define __INCLUDE_FROM_HID_DRIVER
+#include "HIDParser.h"
+
+uint8_t USB_ProcessHIDReport(const uint8_t* ReportData,
+ uint16_t ReportSize,
+ HID_ReportInfo_t* const ParserData)
+{
+ HID_StateTable_t StateTable[HID_STATETABLE_STACK_DEPTH];
+ HID_StateTable_t* CurrStateTable = &StateTable[0];
+ HID_CollectionPath_t* CurrCollectionPath = NULL;
+ HID_ReportSizeInfo_t* CurrReportIDInfo = &ParserData->ReportIDSizes[0];
+ uint16_t UsageList[HID_USAGE_STACK_DEPTH];
+ uint8_t UsageListSize = 0;
+ HID_MinMax_t UsageMinMax = {0, 0};
+
+ memset(ParserData, 0x00, sizeof(HID_ReportInfo_t));
+ memset(CurrStateTable, 0x00, sizeof(HID_StateTable_t));
+ memset(CurrReportIDInfo, 0x00, sizeof(HID_ReportSizeInfo_t));
+
+ ParserData->TotalDeviceReports = 1;
+
+ while (ReportSize)
+ {
+ uint8_t HIDReportItem = *ReportData;
+ uint32_t ReportItemData;
+
+ ReportData++;
+ ReportSize--;
+
+ switch (HIDReportItem & HID_RI_DATA_SIZE_MASK)
+ {
+ case HID_RI_DATA_BITS_32:
+ ReportItemData = (((uint32_t)ReportData[3] << 24) | ((uint32_t)ReportData[2] << 16) |
+ ((uint16_t)ReportData[1] << 8) | ReportData[0]);
+ ReportSize -= 4;
+ ReportData += 4;
+ break;
+
+ case HID_RI_DATA_BITS_16:
+ ReportItemData = (((uint16_t)ReportData[1] << 8) | (ReportData[0]));
+ ReportSize -= 2;
+ ReportData += 2;
+ break;
+
+ case HID_RI_DATA_BITS_8:
+ ReportItemData = ReportData[0];
+ ReportSize -= 1;
+ ReportData += 1;
+ break;
+
+ default:
+ ReportItemData = 0;
+ break;
+ }
+
+ switch (HIDReportItem & (HID_RI_TYPE_MASK | HID_RI_TAG_MASK))
+ {
+ case HID_RI_PUSH(0):
+ if (CurrStateTable == &StateTable[HID_STATETABLE_STACK_DEPTH - 1])
+ return HID_PARSE_HIDStackOverflow;
+
+ memcpy((CurrStateTable + 1),
+ CurrStateTable,
+ sizeof(HID_ReportItem_t));
+
+ CurrStateTable++;
+ break;
+
+ case HID_RI_POP(0):
+ if (CurrStateTable == &StateTable[0])
+ return HID_PARSE_HIDStackUnderflow;
+
+ CurrStateTable--;
+ break;
+
+ case HID_RI_USAGE_PAGE(0):
+ if ((HIDReportItem & HID_RI_DATA_SIZE_MASK) == HID_RI_DATA_BITS_32)
+ CurrStateTable->Attributes.Usage.Page = (ReportItemData >> 16);
+
+ CurrStateTable->Attributes.Usage.Page = ReportItemData;
+ break;
+
+ case HID_RI_LOGICAL_MINIMUM(0):
+ CurrStateTable->Attributes.Logical.Minimum = ReportItemData;
+ break;
+
+ case HID_RI_LOGICAL_MAXIMUM(0):
+ CurrStateTable->Attributes.Logical.Maximum = ReportItemData;
+ break;
+
+ case HID_RI_PHYSICAL_MINIMUM(0):
+ CurrStateTable->Attributes.Physical.Minimum = ReportItemData;
+ break;
+
+ case HID_RI_PHYSICAL_MAXIMUM(0):
+ CurrStateTable->Attributes.Physical.Maximum = ReportItemData;
+ break;
+
+ case HID_RI_UNIT_EXPONENT(0):
+ CurrStateTable->Attributes.Unit.Exponent = ReportItemData;
+ break;
+
+ case HID_RI_UNIT(0):
+ CurrStateTable->Attributes.Unit.Type = ReportItemData;
+ break;
+
+ case HID_RI_REPORT_SIZE(0):
+ CurrStateTable->Attributes.BitSize = ReportItemData;
+ break;
+
+ case HID_RI_REPORT_COUNT(0):
+ CurrStateTable->ReportCount = ReportItemData;
+ break;
+
+ case HID_RI_REPORT_ID(0):
+ CurrStateTable->ReportID = ReportItemData;
+
+ if (ParserData->UsingReportIDs)
+ {
+ CurrReportIDInfo = NULL;
+
+ for (uint8_t i = 0; i < ParserData->TotalDeviceReports; i++)
+ {
+ if (ParserData->ReportIDSizes[i].ReportID == CurrStateTable->ReportID)
+ {
+ CurrReportIDInfo = &ParserData->ReportIDSizes[i];
+ break;
+ }
+ }
+
+ if (CurrReportIDInfo == NULL)
+ {
+ if (ParserData->TotalDeviceReports == HID_MAX_REPORT_IDS)
+ return HID_PARSE_InsufficientReportIDItems;
+
+ CurrReportIDInfo = &ParserData->ReportIDSizes[ParserData->TotalDeviceReports++];
+ memset(CurrReportIDInfo, 0x00, sizeof(HID_ReportSizeInfo_t));
+ }
+ }
+
+ ParserData->UsingReportIDs = true;
+
+ CurrReportIDInfo->ReportID = CurrStateTable->ReportID;
+ break;
+
+ case HID_RI_USAGE(0):
+ if (UsageListSize == HID_USAGE_STACK_DEPTH)
+ return HID_PARSE_UsageListOverflow;
+
+ UsageList[UsageListSize++] = ReportItemData;
+ break;
+
+ case HID_RI_USAGE_MINIMUM(0):
+ UsageMinMax.Minimum = ReportItemData;
+ break;
+
+ case HID_RI_USAGE_MAXIMUM(0):
+ UsageMinMax.Maximum = ReportItemData;
+ break;
+
+ case HID_RI_COLLECTION(0):
+ if (CurrCollectionPath == NULL)
+ {
+ CurrCollectionPath = &ParserData->CollectionPaths[0];
+ }
+ else
+ {
+ HID_CollectionPath_t* ParentCollectionPath = CurrCollectionPath;
+
+ CurrCollectionPath = &ParserData->CollectionPaths[1];
+
+ while (CurrCollectionPath->Parent != NULL)
+ {
+ if (CurrCollectionPath == &ParserData->CollectionPaths[HID_MAX_COLLECTIONS - 1])
+ return HID_PARSE_InsufficientCollectionPaths;
+
+ CurrCollectionPath++;
+ }
+
+ CurrCollectionPath->Parent = ParentCollectionPath;
+ }
+
+ CurrCollectionPath->Type = ReportItemData;
+ CurrCollectionPath->Usage.Page = CurrStateTable->Attributes.Usage.Page;
+
+ if (UsageListSize)
+ {
+ CurrCollectionPath->Usage.Usage = UsageList[0];
+
+ for (uint8_t i = 1; i < UsageListSize; i++)
+ UsageList[i - 1] = UsageList[i];
+
+ UsageListSize--;
+ }
+ else if (UsageMinMax.Minimum <= UsageMinMax.Maximum)
+ {
+ CurrCollectionPath->Usage.Usage = UsageMinMax.Minimum++;
+ }
+
+ break;
+
+ case HID_RI_END_COLLECTION(0):
+ if (CurrCollectionPath == NULL)
+ return HID_PARSE_UnexpectedEndCollection;
+
+ CurrCollectionPath = CurrCollectionPath->Parent;
+ break;
+
+ case HID_RI_INPUT(0):
+ case HID_RI_OUTPUT(0):
+ case HID_RI_FEATURE(0):
+ for (uint8_t ReportItemNum = 0; ReportItemNum < CurrStateTable->ReportCount; ReportItemNum++)
+ {
+ HID_ReportItem_t NewReportItem;
+
+ memcpy(&NewReportItem.Attributes,
+ &CurrStateTable->Attributes,
+ sizeof(HID_ReportItem_Attributes_t));
+
+ NewReportItem.ItemFlags = ReportItemData;
+ NewReportItem.CollectionPath = CurrCollectionPath;
+ NewReportItem.ReportID = CurrStateTable->ReportID;
+
+ if (UsageListSize)
+ {
+ NewReportItem.Attributes.Usage.Usage = UsageList[0];
+
+ for (uint8_t i = 1; i < UsageListSize; i++)
+ UsageList[i - 1] = UsageList[i];
+
+ UsageListSize--;
+ }
+ else if (UsageMinMax.Minimum <= UsageMinMax.Maximum)
+ {
+ NewReportItem.Attributes.Usage.Usage = UsageMinMax.Minimum++;
+ }
+
+ uint8_t ItemTypeTag = (HIDReportItem & (HID_RI_TYPE_MASK | HID_RI_TAG_MASK));
+
+ if (ItemTypeTag == HID_RI_INPUT(0))
+ NewReportItem.ItemType = HID_REPORT_ITEM_In;
+ else if (ItemTypeTag == HID_RI_OUTPUT(0))
+ NewReportItem.ItemType = HID_REPORT_ITEM_Out;
+ else
+ NewReportItem.ItemType = HID_REPORT_ITEM_Feature;
+
+ NewReportItem.BitOffset = CurrReportIDInfo->ReportSizeBits[NewReportItem.ItemType];
+
+ CurrReportIDInfo->ReportSizeBits[NewReportItem.ItemType] += CurrStateTable->Attributes.BitSize;
+
+ ParserData->LargestReportSizeBits = MAX(ParserData->LargestReportSizeBits, CurrReportIDInfo->ReportSizeBits[NewReportItem.ItemType]);
+
+ if (ParserData->TotalReportItems == HID_MAX_REPORTITEMS)
+ return HID_PARSE_InsufficientReportItems;
+
+ memcpy(&ParserData->ReportItems[ParserData->TotalReportItems],
+ &NewReportItem, sizeof(HID_ReportItem_t));
+
+ if (!(ReportItemData & HID_IOF_CONSTANT) && CALLBACK_HIDParser_FilterHIDReportItem(&NewReportItem))
+ ParserData->TotalReportItems++;
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ if ((HIDReportItem & HID_RI_TYPE_MASK) == HID_RI_TYPE_MAIN)
+ {
+ UsageMinMax.Minimum = 0;
+ UsageMinMax.Maximum = 0;
+ UsageListSize = 0;
+ }
+ }
+
+ if (!(ParserData->TotalReportItems))
+ return HID_PARSE_NoUnfilteredReportItems;
+
+ return HID_PARSE_Successful;
+}
+
+bool USB_GetHIDReportItemInfo(const uint8_t* ReportData,
+ HID_ReportItem_t* const ReportItem)
+{
+ if (ReportItem == NULL)
+ return false;
+
+ uint16_t DataBitsRem = ReportItem->Attributes.BitSize;
+ uint16_t CurrentBit = ReportItem->BitOffset;
+ uint32_t BitMask = (1 << 0);
+
+ if (ReportItem->ReportID)
+ {
+ if (ReportItem->ReportID != ReportData[0])
+ return false;
+
+ ReportData++;
+ }
+
+ ReportItem->PreviousValue = ReportItem->Value;
+ ReportItem->Value = 0;
+
+ while (DataBitsRem--)
+ {
+ if (ReportData[CurrentBit / 8] & (1 << (CurrentBit % 8)))
+ ReportItem->Value |= BitMask;
+
+ CurrentBit++;
+ BitMask <<= 1;
+ }
+
+ return true;
+}
+
+void USB_SetHIDReportItemInfo(uint8_t* ReportData,
+ HID_ReportItem_t* const ReportItem)
+{
+ if (ReportItem == NULL)
+ return;
+
+ uint16_t DataBitsRem = ReportItem->Attributes.BitSize;
+ uint16_t CurrentBit = ReportItem->BitOffset;
+ uint32_t BitMask = (1 << 0);
+
+ if (ReportItem->ReportID)
+ {
+ ReportData[0] = ReportItem->ReportID;
+ ReportData++;
+ }
+
+ ReportItem->PreviousValue = ReportItem->Value;
+
+ while (DataBitsRem--)
+ {
+ if (ReportItem->Value & (1 << (CurrentBit % 8)))
+ ReportData[CurrentBit / 8] |= BitMask;
+
+ CurrentBit++;
+ BitMask <<= 1;
+ }
+}
+
+uint16_t USB_GetHIDReportSize(HID_ReportInfo_t* const ParserData,
+ const uint8_t ReportID,
+ const uint8_t ReportType)
+{
+ for (uint8_t i = 0; i < HID_MAX_REPORT_IDS; i++)
+ {
+ uint16_t ReportSizeBits = ParserData->ReportIDSizes[i].ReportSizeBits[ReportType];
+
+ if (ParserData->ReportIDSizes[i].ReportID == ReportID)
+ return (ReportSizeBits / 8) + ((ReportSizeBits % 8) ? 1 : 0);
+ }
+
+ return 0;
+}
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/HIDParser.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/HIDParser.h
new file mode 100644
index 000000000..1f84ef44f
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/HIDParser.h
@@ -0,0 +1,364 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief USB Human Interface Device (HID) Class report descriptor parser.
+ *
+ * This file allows for the easy parsing of complex HID report descriptors, which describes the data that
+ * a HID device transmits to the host. It also provides an easy API for extracting and processing the data
+ * elements inside a HID report sent from an attached HID device.
+ */
+
+/** \ingroup Group_USB
+ * \defgroup Group_HIDParser HID Report Parser
+ * \brief USB Human Interface Device (HID) Class report descriptor parser.
+ *
+ * \section Sec_HIDParser_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Drivers/USB/Class/Host/HIDParser.c <i>(Makefile source module name: LUFA_SRC_USB)</i>
+ *
+ * \section Sec_HIDParser_ModDescription Module Description
+ * Human Interface Device (HID) class report descriptor parser. This module implements a parser than is
+ * capable of processing a complete HID report descriptor, and outputting a flat structure containing the
+ * contents of the report in an a more friendly format. The parsed data may then be further processed and used
+ * within an application to process sent and received HID reports to and from an attached HID device.
+ *
+ * A HID report descriptor consists of a set of HID report items, which describe the function and layout
+ * of data exchanged between a HID device and a host, including both the physical encoding of each item
+ * (such as a button, key press or joystick axis) in the sent and received data packets - known as "reports" -
+ * as well as other information about each item such as the usages, data range, physical location and other
+ * characteristics. In this way a HID device can retain a high degree of flexibility in its capabilities, as it
+ * is not forced to comply with a given report layout or feature-set.
+ *
+ * This module also contains routines for the processing of data in an actual HID report, using the parsed report
+ * descriptor data as a guide for the encoding.
+ *
+ * @{
+ */
+
+#ifndef __HIDPARSER_H__
+#define __HIDPARSER_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ #include "HIDReportData.h"
+ #include "HIDClassCommon.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Macros: */
+ #if !defined(HID_STATETABLE_STACK_DEPTH) || defined(__DOXYGEN__)
+ /** Constant indicating the maximum stack depth of the state table. A larger state table
+ * allows for more PUSH/POP report items to be nested, but consumes more memory. By default
+ * this is set to 2 levels (allowing non-nested PUSH items) but this can be overridden by
+ * defining \c HID_STATETABLE_STACK_DEPTH to another value in the user project makefile, passing the
+ * define to the compiler using the -D compiler switch.
+ */
+ #define HID_STATETABLE_STACK_DEPTH 2
+ #endif
+
+ #if !defined(HID_USAGE_STACK_DEPTH) || defined(__DOXYGEN__)
+ /** Constant indicating the maximum stack depth of the usage table. A larger usage table
+ * allows for more USAGE items to be indicated sequentially for REPORT COUNT entries of more than
+ * one, but requires more stack space. By default this is set to 8 levels (allowing for a report
+ * item with a count of 8) but this can be overridden by defining \c HID_USAGE_STACK_DEPTH to another
+ * value in the user project makefile, passing the define to the compiler using the -D compiler
+ * switch.
+ */
+ #define HID_USAGE_STACK_DEPTH 8
+ #endif
+
+ #if !defined(HID_MAX_COLLECTIONS) || defined(__DOXYGEN__)
+ /** Constant indicating the maximum number of COLLECTION items (nested or unnested) that can be
+ * processed in the report item descriptor. A large value allows for more COLLECTION items to be
+ * processed, but consumes more memory. By default this is set to 10 collections, but this can be
+ * overridden by defining \c HID_MAX_COLLECTIONS to another value in the user project makefile, passing
+ * the define to the compiler using the -D compiler switch.
+ */
+ #define HID_MAX_COLLECTIONS 10
+ #endif
+
+ #if !defined(HID_MAX_REPORTITEMS) || defined(__DOXYGEN__)
+ /** Constant indicating the maximum number of report items (IN, OUT or FEATURE) that can be processed
+ * in the report item descriptor and stored in the user HID Report Info structure. A large value allows
+ * for more report items to be stored, but consumes more memory. By default this is set to 20 items,
+ * but this can be overridden by defining \c HID_MAX_REPORTITEMS to another value in the user project
+ * makefile, and passing the define to the compiler using the -D compiler switch.
+ */
+ #define HID_MAX_REPORTITEMS 20
+ #endif
+
+ #if !defined(HID_MAX_REPORT_IDS) || defined(__DOXYGEN__)
+ /** Constant indicating the maximum number of unique report IDs that can be processed in the report item
+ * descriptor for the report size information array in the user HID Report Info structure. A large value
+ * allows for more report ID report sizes to be stored, but consumes more memory. By default this is set
+ * to 10 items, but this can be overridden by defining \c HID_MAX_REPORT_IDS to another value in the user project
+ * makefile, and passing the define to the compiler using the -D compiler switch. Note that IN, OUT and FEATURE
+ * items sharing the same report ID consume only one size item in the array.
+ */
+ #define HID_MAX_REPORT_IDS 10
+ #endif
+
+ /** Returns the value a given HID report item (once its value has been fetched via \ref USB_GetHIDReportItemInfo())
+ * left-aligned to the given data type. This allows for signed data to be interpreted correctly, by shifting the data
+ * leftwards until the data's sign bit is in the correct position.
+ *
+ * \param[in] ReportItem HID Report Item whose retrieved value is to be aligned.
+ * \param[in] Type Data type to align the HID report item's value to.
+ *
+ * \return Left-aligned data of the given report item's pre-retrieved value for the given datatype.
+ */
+ #define HID_ALIGN_DATA(ReportItem, Type) ((Type)(ReportItem->Value << ((8 * sizeof(Type)) - ReportItem->Attributes.BitSize)))
+
+ /* Public Interface - May be used in end-application: */
+ /* Enums: */
+ /** Enum for the possible error codes in the return value of the \ref USB_ProcessHIDReport() function. */
+ enum HID_Parse_ErrorCodes_t
+ {
+ HID_PARSE_Successful = 0, /**< Successful parse of the HID report descriptor, no error. */
+ HID_PARSE_HIDStackOverflow = 1, /**< More than \ref HID_STATETABLE_STACK_DEPTH nested PUSHes in the report. */
+ HID_PARSE_HIDStackUnderflow = 2, /**< A POP was found when the state table stack was empty. */
+ HID_PARSE_InsufficientReportItems = 3, /**< More than \ref HID_MAX_REPORTITEMS report items in the report. */
+ HID_PARSE_UnexpectedEndCollection = 4, /**< An END COLLECTION item found without matching COLLECTION item. */
+ HID_PARSE_InsufficientCollectionPaths = 5, /**< More than \ref HID_MAX_COLLECTIONS collections in the report. */
+ HID_PARSE_UsageListOverflow = 6, /**< More than \ref HID_USAGE_STACK_DEPTH usages listed in a row. */
+ HID_PARSE_InsufficientReportIDItems = 7, /**< More than \ref HID_MAX_REPORT_IDS report IDs in the device. */
+ HID_PARSE_NoUnfilteredReportItems = 8, /**< All report items from the device were filtered by the filtering callback routine. */
+ };
+
+ /* Type Defines: */
+ /** \brief HID Parser Report Item Min/Max Structure.
+ *
+ * Type define for an attribute with both minimum and maximum values (e.g. Logical Min/Max).
+ */
+ typedef struct
+ {
+ uint32_t Minimum; /**< Minimum value for the attribute. */
+ uint32_t Maximum; /**< Maximum value for the attribute. */
+ } HID_MinMax_t;
+
+ /** \brief HID Parser Report Item Unit Structure.
+ *
+ * Type define for the Unit attributes of a report item.
+ */
+ typedef struct
+ {
+ uint32_t Type; /**< Unit type (refer to HID specifications for details). */
+ uint8_t Exponent; /**< Unit exponent (refer to HID specifications for details). */
+ } HID_Unit_t;
+
+ /** \brief HID Parser Report Item Usage Structure.
+ *
+ * Type define for the Usage attributes of a report item.
+ */
+ typedef struct
+ {
+ uint16_t Page; /**< Usage page of the report item. */
+ uint16_t Usage; /**< Usage of the report item. */
+ } HID_Usage_t;
+
+ /** \brief HID Parser Report Item Collection Path Structure.
+ *
+ * Type define for a COLLECTION object. Contains the collection attributes and a reference to the
+ * parent collection if any.
+ */
+ typedef struct HID_CollectionPath
+ {
+ uint8_t Type; /**< Collection type (e.g. "Generic Desktop"). */
+ HID_Usage_t Usage; /**< Collection usage. */
+ struct HID_CollectionPath* Parent; /**< Reference to parent collection, or \c NULL if root collection. */
+ } HID_CollectionPath_t;
+
+ /** \brief HID Parser Report Item Attributes Structure.
+ *
+ * Type define for all the data attributes of a report item, except flags.
+ */
+ typedef struct
+ {
+ uint8_t BitSize; /**< Size in bits of the report item's data. */
+
+ HID_Usage_t Usage; /**< Usage of the report item. */
+ HID_Unit_t Unit; /**< Unit type and exponent of the report item. */
+ HID_MinMax_t Logical; /**< Logical minimum and maximum of the report item. */
+ HID_MinMax_t Physical; /**< Physical minimum and maximum of the report item. */
+ } HID_ReportItem_Attributes_t;
+
+ /** \brief HID Parser Report Item Details Structure.
+ *
+ * Type define for a report item (IN, OUT or FEATURE) layout attributes and other details.
+ */
+ typedef struct
+ {
+ uint16_t BitOffset; /**< Bit offset in the IN, OUT or FEATURE report of the item. */
+ uint8_t ItemType; /**< Report item type, a value in \ref HID_ReportItemTypes_t. */
+ uint16_t ItemFlags; /**< Item data flags, a mask of \c HID_IOF_* constants. */
+ uint8_t ReportID; /**< Report ID this item belongs to, or 0x00 if device has only one report */
+ HID_CollectionPath_t* CollectionPath; /**< Collection path of the item. */
+
+ HID_ReportItem_Attributes_t Attributes; /**< Report item attributes. */
+
+ uint32_t Value; /**< Current value of the report item - use \ref HID_ALIGN_DATA() when processing
+ * a retrieved value so that it is aligned to a specific type.
+ */
+ uint32_t PreviousValue; /**< Previous value of the report item. */
+ } HID_ReportItem_t;
+
+ /** \brief HID Parser Report Size Structure.
+ *
+ * Type define for a report item size information structure, to retain the size of a device's reports by ID.
+ */
+ typedef struct
+ {
+ uint8_t ReportID; /**< Report ID of the report within the HID interface. */
+ uint16_t ReportSizeBits[3]; /**< Total number of bits in each report type for the given Report ID,
+ * indexed by the \ref HID_ReportItemTypes_t enum.
+ */
+ } HID_ReportSizeInfo_t;
+
+ /** \brief HID Parser State Structure.
+ *
+ * Type define for a complete processed HID report, including all report item data and collections.
+ */
+ typedef struct
+ {
+ uint8_t TotalReportItems; /**< Total number of report items stored in the \c ReportItems array. */
+ HID_ReportItem_t ReportItems[HID_MAX_REPORTITEMS]; /**< Report items array, including all IN, OUT
+ * and FEATURE items.
+ */
+ HID_CollectionPath_t CollectionPaths[HID_MAX_COLLECTIONS]; /**< All collection items, referenced
+ * by the report items.
+ */
+ uint8_t TotalDeviceReports; /**< Number of reports within the HID interface */
+ HID_ReportSizeInfo_t ReportIDSizes[HID_MAX_REPORT_IDS]; /**< Report sizes for each report in the interface */
+ uint16_t LargestReportSizeBits; /**< Largest report that the attached device will generate, in bits */
+ bool UsingReportIDs; /**< Indicates if the device has at least one REPORT ID
+ * element in its HID report descriptor.
+ */
+ } HID_ReportInfo_t;
+
+ /* Function Prototypes: */
+ /** Function to process a given HID report returned from an attached device, and store it into a given
+ * \ref HID_ReportInfo_t structure.
+ *
+ * \param[in] ReportData Buffer containing the device's HID report table.
+ * \param[in] ReportSize Size in bytes of the HID report table.
+ * \param[out] ParserData Pointer to a \ref HID_ReportInfo_t instance for the parser output.
+ *
+ * \return A value in the \ref HID_Parse_ErrorCodes_t enum.
+ */
+ uint8_t USB_ProcessHIDReport(const uint8_t* ReportData,
+ uint16_t ReportSize,
+ HID_ReportInfo_t* const ParserData) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
+
+ /** Extracts the given report item's value out of the given HID report and places it into the Value
+ * member of the report item's \ref HID_ReportItem_t structure.
+ *
+ * When called on a report with an item that exists in that report, this copies the report item's \c Value
+ * to its \c PreviousValue element for easy checking to see if an item's value has changed before processing
+ * a report. If the given item does not exist in the report, the function does not modify the report item's
+ * data.
+ *
+ * \param[in] ReportData Buffer containing an IN or FEATURE report from an attached device.
+ * \param[in,out] ReportItem Pointer to the report item of interest in a \ref HID_ReportInfo_t ReportItem array.
+ *
+ * \returns Boolean \c true if the item to retrieve was located in the given report, \c false otherwise.
+ */
+ bool USB_GetHIDReportItemInfo(const uint8_t* ReportData,
+ HID_ReportItem_t* const ReportItem) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Retrieves the given report item's value out of the \c Value member of the report item's
+ * \ref HID_ReportItem_t structure and places it into the correct position in the HID report
+ * buffer. The report buffer is assumed to have the appropriate bits cleared before calling
+ * this function (i.e., the buffer should be explicitly cleared before report values are added).
+ *
+ * When called, this copies the report item's \c Value element to its \c PreviousValue element for easy
+ * checking to see if an item's value has changed before sending a report.
+ *
+ * If the device has multiple HID reports, the first byte in the report is set to the report ID of the given item.
+ *
+ * \param[out] ReportData Buffer holding the current OUT or FEATURE report data.
+ * \param[in] ReportItem Pointer to the report item of interest in a \ref HID_ReportInfo_t ReportItem array.
+ */
+ void USB_SetHIDReportItemInfo(uint8_t* ReportData,
+ HID_ReportItem_t* const ReportItem) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Retrieves the size of a given HID report in bytes from its Report ID.
+ *
+ * \param[in] ParserData Pointer to a \ref HID_ReportInfo_t instance containing the parser output.
+ * \param[in] ReportID Report ID of the report whose size is to be determined.
+ * \param[in] ReportType Type of the report whose size is to be determined, a value from the
+ * \ref HID_ReportItemTypes_t enum.
+ *
+ * \return Size of the report in bytes, or \c 0 if the report does not exist.
+ */
+ uint16_t USB_GetHIDReportSize(HID_ReportInfo_t* const ParserData,
+ const uint8_t ReportID,
+ const uint8_t ReportType) ATTR_CONST ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Callback routine for the HID Report Parser. This callback <b>must</b> be implemented by the user code when
+ * the parser is used, to determine what report IN, OUT and FEATURE item's information is stored into the user
+ * \ref HID_ReportInfo_t structure. This can be used to filter only those items the application will be using, so that
+ * no RAM is wasted storing the attributes for report items which will never be referenced by the application.
+ *
+ * Report item pointers passed to this callback function may be cached by the user application for later use
+ * when processing report items. This provides faster report processing in the user application than would
+ * a search of the entire parsed report item table for each received or sent report.
+ *
+ * \param[in] CurrentItem Pointer to the current report item for user checking.
+ *
+ * \return Boolean \c true if the item should be stored into the \ref HID_ReportInfo_t structure, \c false if
+ * it should be ignored.
+ */
+ bool CALLBACK_HIDParser_FilterHIDReportItem(HID_ReportItem_t* const CurrentItem);
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Type Defines: */
+ typedef struct
+ {
+ HID_ReportItem_Attributes_t Attributes;
+ uint8_t ReportCount;
+ uint8_t ReportID;
+ } HID_StateTable_t;
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/HIDReportData.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/HIDReportData.h
new file mode 100644
index 000000000..df4302cc7
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/HIDReportData.h
@@ -0,0 +1,126 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Constants for HID report item attributes.
+ *
+ * HID report item constants for report item attributes. Refer to the HID specification for
+ * details on each flag's meaning when applied to an IN, OUT or FEATURE item.
+ */
+
+/** \ingroup Group_HIDParser
+ * \defgroup Group_HIDReportItemConst HID Report Descriptor Item Constants
+ *
+ * General HID constant definitions for HID Report Descriptor elements.
+ *
+ * @{
+ */
+
+#ifndef __HIDREPORTDATA_H__
+#define __HIDREPORTDATA_H__
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define HID_RI_DATA_SIZE_MASK 0x03
+ #define HID_RI_TYPE_MASK 0x0C
+ #define HID_RI_TAG_MASK 0xF0
+
+ #define HID_RI_TYPE_MAIN 0x00
+ #define HID_RI_TYPE_GLOBAL 0x04
+ #define HID_RI_TYPE_LOCAL 0x08
+
+ #define HID_RI_DATA_BITS_0 0x00
+ #define HID_RI_DATA_BITS_8 0x01
+ #define HID_RI_DATA_BITS_16 0x02
+ #define HID_RI_DATA_BITS_32 0x03
+ #define HID_RI_DATA_BITS(DataBits) CONCAT_EXPANDED(HID_RI_DATA_BITS_, DataBits)
+
+ #define _HID_RI_ENCODE_0(Data)
+ #define _HID_RI_ENCODE_8(Data) , (Data & 0xFF)
+ #define _HID_RI_ENCODE_16(Data) _HID_RI_ENCODE_8(Data) _HID_RI_ENCODE_8(Data >> 8)
+ #define _HID_RI_ENCODE_32(Data) _HID_RI_ENCODE_16(Data) _HID_RI_ENCODE_16(Data >> 16)
+ #define _HID_RI_ENCODE(DataBits, ...) CONCAT_EXPANDED(_HID_RI_ENCODE_, DataBits(__VA_ARGS__))
+
+ #define _HID_RI_ENTRY(Type, Tag, DataBits, ...) (Type | Tag | HID_RI_DATA_BITS(DataBits)) _HID_RI_ENCODE(DataBits, (__VA_ARGS__))
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** \name HID Input, Output and Feature Report Descriptor Item Flags */
+ //@{
+ #define HID_IOF_CONSTANT (1 << 0)
+ #define HID_IOF_DATA (0 << 0)
+ #define HID_IOF_VARIABLE (1 << 1)
+ #define HID_IOF_ARRAY (0 << 1)
+ #define HID_IOF_RELATIVE (1 << 2)
+ #define HID_IOF_ABSOLUTE (0 << 2)
+ #define HID_IOF_WRAP (1 << 3)
+ #define HID_IOF_NO_WRAP (0 << 3)
+ #define HID_IOF_NON_LINEAR (1 << 4)
+ #define HID_IOF_LINEAR (0 << 4)
+ #define HID_IOF_NO_PREFERRED_STATE (1 << 5)
+ #define HID_IOF_PREFERRED_STATE (0 << 5)
+ #define HID_IOF_NULLSTATE (1 << 6)
+ #define HID_IOF_NO_NULL_POSITION (0 << 6)
+ #define HID_IOF_VOLATILE (1 << 7)
+ #define HID_IOF_NON_VOLATILE (0 << 7)
+ #define HID_IOF_BUFFERED_BYTES (1 << 8)
+ #define HID_IOF_BITFIELD (0 << 8)
+ //@}
+
+ /** \name HID Report Descriptor Item Macros */
+ //@{
+ #define HID_RI_INPUT(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_MAIN , 0x80, DataBits, __VA_ARGS__)
+ #define HID_RI_OUTPUT(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_MAIN , 0x90, DataBits, __VA_ARGS__)
+ #define HID_RI_COLLECTION(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_MAIN , 0xA0, DataBits, __VA_ARGS__)
+ #define HID_RI_FEATURE(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_MAIN , 0xB0, DataBits, __VA_ARGS__)
+ #define HID_RI_END_COLLECTION(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_MAIN , 0xC0, DataBits, __VA_ARGS__)
+ #define HID_RI_USAGE_PAGE(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_GLOBAL, 0x00, DataBits, __VA_ARGS__)
+ #define HID_RI_LOGICAL_MINIMUM(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_GLOBAL, 0x10, DataBits, __VA_ARGS__)
+ #define HID_RI_LOGICAL_MAXIMUM(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_GLOBAL, 0x20, DataBits, __VA_ARGS__)
+ #define HID_RI_PHYSICAL_MINIMUM(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_GLOBAL, 0x30, DataBits, __VA_ARGS__)
+ #define HID_RI_PHYSICAL_MAXIMUM(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_GLOBAL, 0x40, DataBits, __VA_ARGS__)
+ #define HID_RI_UNIT_EXPONENT(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_GLOBAL, 0x50, DataBits, __VA_ARGS__)
+ #define HID_RI_UNIT(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_GLOBAL, 0x60, DataBits, __VA_ARGS__)
+ #define HID_RI_REPORT_SIZE(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_GLOBAL, 0x70, DataBits, __VA_ARGS__)
+ #define HID_RI_REPORT_ID(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_GLOBAL, 0x80, DataBits, __VA_ARGS__)
+ #define HID_RI_REPORT_COUNT(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_GLOBAL, 0x90, DataBits, __VA_ARGS__)
+ #define HID_RI_PUSH(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_GLOBAL, 0xA0, DataBits, __VA_ARGS__)
+ #define HID_RI_POP(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_GLOBAL, 0xB0, DataBits, __VA_ARGS__)
+ #define HID_RI_USAGE(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_LOCAL , 0x00, DataBits, __VA_ARGS__)
+ #define HID_RI_USAGE_MINIMUM(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_LOCAL , 0x10, DataBits, __VA_ARGS__)
+ #define HID_RI_USAGE_MAXIMUM(DataBits, ...) _HID_RI_ENTRY(HID_RI_TYPE_LOCAL , 0x20, DataBits, __VA_ARGS__)
+ //@}
+
+/** @} */
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/MIDIClassCommon.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/MIDIClassCommon.h
new file mode 100644
index 000000000..b6f603455
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/MIDIClassCommon.h
@@ -0,0 +1,363 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Common definitions and declarations for the library USB MIDI Class driver.
+ *
+ * Common definitions and declarations for the library USB MIDI Class driver.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB module driver
+ * dispatch header located in LUFA/Drivers/USB.h.
+ */
+
+/** \ingroup Group_USBClassMIDI
+ * \defgroup Group_USBClassMIDICommon Common Class Definitions
+ *
+ * \section Sec_USBClassMIDICommon_ModDescription Module Description
+ * Constants, Types and Enum definitions that are common to both Device and Host modes for the USB
+ * MIDI Class.
+ *
+ * @{
+ */
+
+#ifndef _MIDI_CLASS_COMMON_H_
+#define _MIDI_CLASS_COMMON_H_
+
+ /* Macros: */
+ #define __INCLUDE_FROM_AUDIO_DRIVER
+
+ /* Includes: */
+ #include "../../Core/StdDescriptors.h"
+ #include "AudioClassCommon.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_MIDI_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
+ #endif
+
+ /* Macros: */
+ /** \name MIDI Command Values
+ * See http://www.midi.org/techspecs/midimessages.php for more information.
+ */
+ //@{
+ /** MIDI command for System Exclusive (SysEx) single event that has one byte of data total. */
+ #define MIDI_COMMAND_SYSEX_1BYTE MIDI_COMMAND_SYSEX_END_1BYTE
+
+ /** MIDI command for System Exclusive (SysEx) single event that has two bytes of data total. */
+ #define MIDI_COMMAND_SYSEX_2BYTE 0x20
+
+ /** MIDI command for System Exclusive (SysEx) single event that has three bytes of data total. */
+ #define MIDI_COMMAND_SYSEX_3BYTE 0x30
+
+ /** MIDI command for System Exclusive (SysEx) stream event that has at least four bytes of data total. */
+ #define MIDI_COMMAND_SYSEX_START_3BYTE 0x40
+
+ /** MIDI command for System Exclusive (SysEx) stream event terminator with one remaining data byte. */
+ #define MIDI_COMMAND_SYSEX_END_1BYTE 0x50
+
+ /** MIDI command for System Exclusive (SysEx) stream event terminator with two remaining data bytes. */
+ #define MIDI_COMMAND_SYSEX_END_2BYTE 0x60
+
+ /** MIDI command for System Exclusive (SysEx) stream event terminator with three remaining data bytes. */
+ #define MIDI_COMMAND_SYSEX_END_3BYTE 0x70
+
+ /** MIDI command for a note off (deactivation) event. */
+ #define MIDI_COMMAND_NOTE_OFF 0x80
+
+ /** MIDI command for a note on (activation) event. */
+ #define MIDI_COMMAND_NOTE_ON 0x90
+
+ /** MIDI command for a note pressure change event. */
+ #define MIDI_COMMAND_NOTE_PRESSURE 0xA0
+
+ /** MIDI command for a control change event. */
+ #define MIDI_COMMAND_CONTROL_CHANGE 0xB0
+
+ /** MIDI command for a control change event. */
+ #define MIDI_COMMAND_PROGRAM_CHANGE 0xC0
+
+ /** MIDI command for a channel pressure change event. */
+ #define MIDI_COMMAND_CHANNEL_PRESSURE 0xD0
+
+ /** MIDI command for a pitch change event. */
+ #define MIDI_COMMAND_PITCH_WHEEL_CHANGE 0xE0
+ //@}
+
+ /** Standard key press velocity value used for all note events. */
+ #define MIDI_STANDARD_VELOCITY 64
+
+ /** Convenience macro. MIDI channels are numbered from 1-10 (natural numbers) however the logical channel
+ * addresses are zero-indexed. This converts a natural MIDI channel number into the logical channel address.
+ *
+ * \param[in] channel MIDI channel number to address.
+ *
+ * \return Constructed MIDI channel ID.
+ */
+ #define MIDI_CHANNEL(channel) ((channel) - 1)
+
+ /** Constructs a MIDI event ID from a given MIDI command and a virtual MIDI cable index. This can then be
+ * used to create and decode \ref MIDI_EventPacket_t MIDI event packets.
+ *
+ * \param[in] virtualcable Index of the virtual MIDI cable the event relates to
+ * \param[in] command MIDI command to send through the virtual MIDI cable
+ *
+ * \return Constructed MIDI event ID.
+ */
+ #define MIDI_EVENT(virtualcable, command) (((virtualcable) << 4) | ((command) >> 4))
+
+ /* Enums: */
+ /** Enum for the possible MIDI jack types in a MIDI device jack descriptor. */
+ enum MIDI_JackTypes_t
+ {
+ MIDI_JACKTYPE_Embedded = 0x01, /**< MIDI class descriptor jack type value for an embedded (logical) MIDI input or output jack. */
+ MIDI_JACKTYPE_External = 0x02, /**< MIDI class descriptor jack type value for an external (physical) MIDI input or output jack. */
+ };
+
+ /* Type Defines: */
+ /** \brief MIDI class-specific Streaming Interface Descriptor (LUFA naming conventions).
+ *
+ * Type define for an Audio class-specific MIDI streaming interface descriptor. This indicates to the host
+ * how MIDI the specification compliance of the device and the total length of the Audio class-specific descriptors.
+ * See the USB Audio specification for more details.
+ *
+ * \see \ref USB_MIDI_StdDescriptor_AudioInterface_AS_t for the version of this type with standard element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Header_t Header; /**< Regular descriptor header containing the descriptor's type and length. */
+ uint8_t Subtype; /**< Sub type value used to distinguish between audio class-specific descriptors. */
+
+ uint16_t AudioSpecification; /**< Binary coded decimal value, indicating the supported Audio Class
+ * specification version.
+ *
+ * \see \ref VERSION_BCD() utility macro.
+ */
+ uint16_t TotalLength; /**< Total length of the Audio class-specific descriptors, including this descriptor. */
+ } ATTR_PACKED USB_MIDI_Descriptor_AudioInterface_AS_t;
+
+ /** \brief MIDI class-specific Streaming Interface Descriptor (USB-IF naming conventions).
+ *
+ * Type define for an Audio class-specific MIDI streaming interface descriptor. This indicates to the host
+ * how MIDI the specification compliance of the device and the total length of the Audio class-specific descriptors.
+ * See the USB Audio specification for more details.
+ *
+ * \see \ref USB_MIDI_Descriptor_AudioInterface_AS_t for the version of this type with non-standard LUFA specific
+ * element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint8_t bLength; /**< Size of the descriptor, in bytes. */
+ uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
+ * given by the specific class.
+ */
+
+ uint8_t bDescriptorSubtype; /**< Sub type value used to distinguish between audio class-specific descriptors. */
+
+ uint16_t bcdMSC; /**< Binary coded decimal value, indicating the supported MIDI Class specification version.
+ *
+ * \see \ref VERSION_BCD() utility macro.
+ */
+ uint16_t wTotalLength; /**< Total length of the Audio class-specific descriptors, including this descriptor. */
+ } ATTR_PACKED USB_MIDI_StdDescriptor_AudioInterface_AS_t;
+
+ /** \brief MIDI class-specific Input Jack Descriptor (LUFA naming conventions).
+ *
+ * Type define for an Audio class-specific MIDI IN jack. This gives information to the host on a MIDI input, either
+ * a physical input jack, or a logical jack (receiving input data internally, or from the host via an endpoint).
+ *
+ * \see \ref USB_MIDI_StdDescriptor_InputJack_t for the version of this type with standard element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Header_t Header; /**< Regular descriptor header containing the descriptor's type and length. */
+ uint8_t Subtype; /**< Sub type value used to distinguish between audio class-specific descriptors. */
+
+ uint8_t JackType; /**< Type of jack, one of the \c JACKTYPE_* mask values. */
+ uint8_t JackID; /**< ID value of this jack - must be a unique value within the device. */
+
+ uint8_t JackStrIndex; /**< Index of a string descriptor describing this descriptor within the device. */
+ } ATTR_PACKED USB_MIDI_Descriptor_InputJack_t;
+
+ /** \brief MIDI class-specific Input Jack Descriptor (USB-IF naming conventions).
+ *
+ * Type define for an Audio class-specific MIDI IN jack. This gives information to the host on a MIDI input, either
+ * a physical input jack, or a logical jack (receiving input data internally, or from the host via an endpoint).
+ *
+ * \see \ref USB_MIDI_Descriptor_InputJack_t for the version of this type with non-standard LUFA specific
+ * element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint8_t bLength; /**< Size of the descriptor, in bytes. */
+ uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
+ * given by the specific class.
+ */
+
+ uint8_t bDescriptorSubtype; /**< Sub type value used to distinguish between audio class-specific descriptors. */
+
+ uint8_t bJackType; /**< Type of jack, one of the \c JACKTYPE_* mask values. */
+ uint8_t bJackID; /**< ID value of this jack - must be a unique value within the device. */
+
+ uint8_t iJack; /**< Index of a string descriptor describing this descriptor within the device. */
+ } ATTR_PACKED USB_MIDI_StdDescriptor_InputJack_t;
+
+ /** \brief MIDI class-specific Output Jack Descriptor (LUFA naming conventions).
+ *
+ * Type define for an Audio class-specific MIDI OUT jack. This gives information to the host on a MIDI output, either
+ * a physical output jack, or a logical jack (sending output data internally, or to the host via an endpoint).
+ *
+ * \see \ref USB_MIDI_StdDescriptor_OutputJack_t for the version of this type with standard element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Header_t Header; /**< Regular descriptor header containing the descriptor's type and length. */
+ uint8_t Subtype; /**< Sub type value used to distinguish between audio class-specific descriptors. */
+
+ uint8_t JackType; /**< Type of jack, one of the \c JACKTYPE_* mask values. */
+ uint8_t JackID; /**< ID value of this jack - must be a unique value within the device. */
+
+ uint8_t NumberOfPins; /**< Number of output channels within the jack, either physical or logical. */
+ uint8_t SourceJackID[1]; /**< ID of each output pin's source data jack. */
+ uint8_t SourcePinID[1]; /**< Pin number in the input jack of each output pin's source data. */
+
+ uint8_t JackStrIndex; /**< Index of a string descriptor describing this descriptor within the device. */
+ } ATTR_PACKED USB_MIDI_Descriptor_OutputJack_t;
+
+ /** \brief MIDI class-specific Output Jack Descriptor (USB-IF naming conventions).
+ *
+ * Type define for an Audio class-specific MIDI OUT jack. This gives information to the host on a MIDI output, either
+ * a physical output jack, or a logical jack (sending output data internally, or to the host via an endpoint).
+ *
+ * \see \ref USB_MIDI_Descriptor_OutputJack_t for the version of this type with non-standard LUFA specific
+ * element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint8_t bLength; /**< Size of the descriptor, in bytes. */
+ uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
+ * given by the specific class.
+ */
+
+ uint8_t bDescriptorSubtype; /**< Sub type value used to distinguish between audio class-specific descriptors. */
+
+ uint8_t bJackType; /**< Type of jack, one of the \c JACKTYPE_* mask values. */
+ uint8_t bJackID; /**< ID value of this jack - must be a unique value within the device. */
+
+ uint8_t bNrInputPins; /**< Number of output channels within the jack, either physical or logical. */
+ uint8_t baSourceID[1]; /**< ID of each output pin's source data jack. */
+ uint8_t baSourcePin[1]; /**< Pin number in the input jack of each output pin's source data. */
+
+ uint8_t iJack; /**< Index of a string descriptor describing this descriptor within the device. */
+ } ATTR_PACKED USB_MIDI_StdDescriptor_OutputJack_t;
+
+ /** \brief Audio class-specific Jack Endpoint Descriptor (LUFA naming conventions).
+ *
+ * Type define for an Audio class-specific extended MIDI jack endpoint descriptor. This contains extra information
+ * on the usage of MIDI endpoints used to stream MIDI events in and out of the USB Audio device, and follows an Audio
+ * class-specific extended MIDI endpoint descriptor. See the USB Audio specification for more details.
+ *
+ * \see \ref USB_MIDI_StdDescriptor_Jack_Endpoint_t for the version of this type with standard element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Header_t Header; /**< Regular descriptor header containing the descriptor's type and length. */
+ uint8_t Subtype; /**< Sub type value used to distinguish between audio class-specific descriptors. */
+
+ uint8_t TotalEmbeddedJacks; /**< Total number of jacks inside this endpoint. */
+ uint8_t AssociatedJackID[1]; /**< IDs of each jack inside the endpoint. */
+ } ATTR_PACKED USB_MIDI_Descriptor_Jack_Endpoint_t;
+
+ /** \brief Audio class-specific Jack Endpoint Descriptor (USB-IF naming conventions).
+ *
+ * Type define for an Audio class-specific extended MIDI jack endpoint descriptor. This contains extra information
+ * on the usage of MIDI endpoints used to stream MIDI events in and out of the USB Audio device, and follows an Audio
+ * class-specific extended MIDI endpoint descriptor. See the USB Audio specification for more details.
+ *
+ * \see \ref USB_MIDI_Descriptor_Jack_Endpoint_t for the version of this type with non-standard LUFA specific
+ * element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint8_t bLength; /**< Size of the descriptor, in bytes. */
+ uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
+ * given by the specific class.
+ */
+
+ uint8_t bDescriptorSubtype; /**< Sub type value used to distinguish between audio class-specific descriptors. */
+
+ uint8_t bNumEmbMIDIJack; /**< Total number of jacks inside this endpoint. */
+ uint8_t bAssocJackID[1]; /**< IDs of each jack inside the endpoint. */
+ } ATTR_PACKED USB_MIDI_StdDescriptor_Jack_Endpoint_t;
+
+ /** \brief MIDI Class Driver Event Packet.
+ *
+ * Type define for a USB MIDI event packet, used to encapsulate sent and received MIDI messages from a USB MIDI interface.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint8_t Event; /**< MIDI event type, constructed with the \ref MIDI_EVENT() macro. */
+
+ uint8_t Data1; /**< First byte of data in the MIDI event. */
+ uint8_t Data2; /**< Second byte of data in the MIDI event. */
+ uint8_t Data3; /**< Third byte of data in the MIDI event. */
+ } ATTR_PACKED MIDI_EventPacket_t;
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/MassStorageClassCommon.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/MassStorageClassCommon.h
new file mode 100644
index 000000000..8a12f31b8
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/MassStorageClassCommon.h
@@ -0,0 +1,368 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Common definitions and declarations for the library USB Mass Storage Class driver.
+ *
+ * Common definitions and declarations for the library USB Mass Storage Class driver.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB module driver
+ * dispatch header located in LUFA/Drivers/USB.h.
+ */
+
+/** \ingroup Group_USBClassMS
+ * \defgroup Group_USBClassMSCommon Common Class Definitions
+ *
+ * \section Sec_USBClassMSCommon_ModDescription Module Description
+ * Constants, Types and Enum definitions that are common to both Device and Host modes for the USB
+ * Mass Storage Class.
+ *
+ * @{
+ */
+
+#ifndef _MS_CLASS_COMMON_H_
+#define _MS_CLASS_COMMON_H_
+
+ /* Includes: */
+ #include "../../Core/StdDescriptors.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_MS_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
+ #endif
+
+ /* Macros: */
+ /** Magic signature for a Command Block Wrapper used in the Mass Storage Bulk-Only transport protocol. */
+ #define MS_CBW_SIGNATURE 0x43425355UL
+
+ /** Magic signature for a Command Status Wrapper used in the Mass Storage Bulk-Only transport protocol. */
+ #define MS_CSW_SIGNATURE 0x53425355UL
+
+ /** Mask for a Command Block Wrapper's flags attribute to specify a command with data sent from host-to-device. */
+ #define MS_COMMAND_DIR_DATA_OUT (0 << 7)
+
+ /** Mask for a Command Block Wrapper's flags attribute to specify a command with data sent from device-to-host. */
+ #define MS_COMMAND_DIR_DATA_IN (1 << 7)
+
+ /** \name SCSI Commands*/
+ //@{
+ /** SCSI Command Code for an INQUIRY command. */
+ #define SCSI_CMD_INQUIRY 0x12
+
+ /** SCSI Command Code for a REQUEST SENSE command. */
+ #define SCSI_CMD_REQUEST_SENSE 0x03
+
+ /** SCSI Command Code for a TEST UNIT READY command. */
+ #define SCSI_CMD_TEST_UNIT_READY 0x00
+
+ /** SCSI Command Code for a READ CAPACITY (10) command. */
+ #define SCSI_CMD_READ_CAPACITY_10 0x25
+
+ /** SCSI Command Code for a START STOP UNIT command. */
+ #define SCSI_CMD_START_STOP_UNIT 0x1B
+
+ /** SCSI Command Code for a SEND DIAGNOSTIC command. */
+ #define SCSI_CMD_SEND_DIAGNOSTIC 0x1D
+
+ /** SCSI Command Code for a PREVENT ALLOW MEDIUM REMOVAL command. */
+ #define SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1E
+
+ /** SCSI Command Code for a WRITE (10) command. */
+ #define SCSI_CMD_WRITE_10 0x2A
+
+ /** SCSI Command Code for a READ (10) command. */
+ #define SCSI_CMD_READ_10 0x28
+
+ /** SCSI Command Code for a WRITE (6) command. */
+ #define SCSI_CMD_WRITE_6 0x0A
+
+ /** SCSI Command Code for a READ (6) command. */
+ #define SCSI_CMD_READ_6 0x08
+
+ /** SCSI Command Code for a VERIFY (10) command. */
+ #define SCSI_CMD_VERIFY_10 0x2F
+
+ /** SCSI Command Code for a MODE SENSE (6) command. */
+ #define SCSI_CMD_MODE_SENSE_6 0x1A
+
+ /** SCSI Command Code for a MODE SENSE (10) command. */
+ #define SCSI_CMD_MODE_SENSE_10 0x5A
+ //@}
+
+ /** \name SCSI Sense Key Values */
+ //@{
+ /** SCSI Sense Code to indicate no error has occurred. */
+ #define SCSI_SENSE_KEY_GOOD 0x00
+
+ /** SCSI Sense Code to indicate that the device has recovered from an error. */
+ #define SCSI_SENSE_KEY_RECOVERED_ERROR 0x01
+
+ /** SCSI Sense Code to indicate that the device is not ready for a new command. */
+ #define SCSI_SENSE_KEY_NOT_READY 0x02
+
+ /** SCSI Sense Code to indicate an error whilst accessing the medium. */
+ #define SCSI_SENSE_KEY_MEDIUM_ERROR 0x03
+
+ /** SCSI Sense Code to indicate a hardware error has occurred. */
+ #define SCSI_SENSE_KEY_HARDWARE_ERROR 0x04
+
+ /** SCSI Sense Code to indicate that an illegal request has been issued. */
+ #define SCSI_SENSE_KEY_ILLEGAL_REQUEST 0x05
+
+ /** SCSI Sense Code to indicate that the unit requires attention from the host to indicate
+ * a reset event, medium removal or other condition.
+ */
+ #define SCSI_SENSE_KEY_UNIT_ATTENTION 0x06
+
+ /** SCSI Sense Code to indicate that a write attempt on a protected block has been made. */
+ #define SCSI_SENSE_KEY_DATA_PROTECT 0x07
+
+ /** SCSI Sense Code to indicate an error while trying to write to a write-once medium. */
+ #define SCSI_SENSE_KEY_BLANK_CHECK 0x08
+
+ /** SCSI Sense Code to indicate a vendor specific error has occurred. */
+ #define SCSI_SENSE_KEY_VENDOR_SPECIFIC 0x09
+
+ /** SCSI Sense Code to indicate that an EXTENDED COPY command has aborted due to an error. */
+ #define SCSI_SENSE_KEY_COPY_ABORTED 0x0A
+
+ /** SCSI Sense Code to indicate that the device has aborted the issued command. */
+ #define SCSI_SENSE_KEY_ABORTED_COMMAND 0x0B
+
+ /** SCSI Sense Code to indicate an attempt to write past the end of a partition has been made. */
+ #define SCSI_SENSE_KEY_VOLUME_OVERFLOW 0x0D
+
+ /** SCSI Sense Code to indicate that the source data did not match the data read from the medium. */
+ #define SCSI_SENSE_KEY_MISCOMPARE 0x0E
+ //@}
+
+ /** \name SCSI Additional Sense Codes */
+ //@{
+ /** SCSI Additional Sense Code to indicate no additional sense information is available. */
+ #define SCSI_ASENSE_NO_ADDITIONAL_INFORMATION 0x00
+
+ /** SCSI Additional Sense Code to indicate that the logical unit (LUN) addressed is not ready. */
+ #define SCSI_ASENSE_LOGICAL_UNIT_NOT_READY 0x04
+
+ /** SCSI Additional Sense Code to indicate an invalid field was encountered while processing the issued command. */
+ #define SCSI_ASENSE_INVALID_FIELD_IN_CDB 0x24
+
+ /** SCSI Additional Sense Code to indicate that a medium that was previously indicated as not ready has now
+ * become ready for use.
+ */
+ #define SCSI_ASENSE_NOT_READY_TO_READY_CHANGE 0x28
+
+ /** SCSI Additional Sense Code to indicate that an attempt to write to a protected area was made. */
+ #define SCSI_ASENSE_WRITE_PROTECTED 0x27
+
+ /** SCSI Additional Sense Code to indicate an error whilst formatting the device medium. */
+ #define SCSI_ASENSE_FORMAT_ERROR 0x31
+
+ /** SCSI Additional Sense Code to indicate an invalid command was issued. */
+ #define SCSI_ASENSE_INVALID_COMMAND 0x20
+
+ /** SCSI Additional Sense Code to indicate a write to a block out outside of the medium's range was issued. */
+ #define SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x21
+
+ /** SCSI Additional Sense Code to indicate that no removable medium is inserted into the device. */
+ #define SCSI_ASENSE_MEDIUM_NOT_PRESENT 0x3A
+ //@}
+
+ /** \name SCSI Additional Sense Key Code Qualifiers */
+ //@{
+ /** SCSI Additional Sense Qualifier Code to indicate no additional sense qualifier information is available. */
+ #define SCSI_ASENSEQ_NO_QUALIFIER 0x00
+
+ /** SCSI Additional Sense Qualifier Code to indicate that a medium format command failed to complete. */
+ #define SCSI_ASENSEQ_FORMAT_COMMAND_FAILED 0x01
+
+ /** SCSI Additional Sense Qualifier Code to indicate that an initializing command must be issued before the issued
+ * command can be executed.
+ */
+ #define SCSI_ASENSEQ_INITIALIZING_COMMAND_REQUIRED 0x02
+
+ /** SCSI Additional Sense Qualifier Code to indicate that an operation is currently in progress. */
+ #define SCSI_ASENSEQ_OPERATION_IN_PROGRESS 0x07
+ //@}
+
+ /* Enums: */
+ /** Enum for possible Class, Subclass and Protocol values of device and interface descriptors relating to the Mass
+ * Storage device class.
+ */
+ enum MS_Descriptor_ClassSubclassProtocol_t
+ {
+ MS_CSCP_MassStorageClass = 0x08, /**< Descriptor Class value indicating that the device or interface
+ * belongs to the Mass Storage class.
+ */
+ MS_CSCP_SCSITransparentSubclass = 0x06, /**< Descriptor Subclass value indicating that the device or interface
+ * belongs to the SCSI Transparent Command Set subclass of the Mass
+ * storage class.
+ */
+ MS_CSCP_BulkOnlyTransportProtocol = 0x50, /**< Descriptor Protocol value indicating that the device or interface
+ * belongs to the Bulk Only Transport protocol of the Mass Storage class.
+ */
+ };
+
+ /** Enum for the Mass Storage class specific control requests that can be issued by the USB bus host. */
+ enum MS_ClassRequests_t
+ {
+ MS_REQ_GetMaxLUN = 0xFE, /**< Mass Storage class-specific request to retrieve the total number of Logical
+ * Units (drives) in the SCSI device.
+ */
+ MS_REQ_MassStorageReset = 0xFF, /**< Mass Storage class-specific request to reset the Mass Storage interface,
+ * ready for the next command.
+ */
+ };
+
+ /** Enum for the possible command status wrapper return status codes. */
+ enum MS_CommandStatusCodes_t
+ {
+ MS_SCSI_COMMAND_Pass = 0, /**< Command completed with no error */
+ MS_SCSI_COMMAND_Fail = 1, /**< Command failed to complete - host may check the exact error via a
+ * SCSI REQUEST SENSE command.
+ */
+ MS_SCSI_COMMAND_PhaseError = 2, /**< Command failed due to being invalid in the current phase. */
+ };
+
+ /* Type Defines: */
+ /** \brief Mass Storage Class Command Block Wrapper.
+ *
+ * Type define for a Command Block Wrapper, used in the Mass Storage Bulk-Only Transport protocol.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint32_t Signature; /**< Command block signature, must be \ref MS_CBW_SIGNATURE to indicate a valid Command Block. */
+ uint32_t Tag; /**< Unique command ID value, to associate a command block wrapper with its command status wrapper. */
+ uint32_t DataTransferLength; /**< Length of the optional data portion of the issued command, in bytes. */
+ uint8_t Flags; /**< Command block flags, indicating command data direction. */
+ uint8_t LUN; /**< Logical Unit number this command is issued to. */
+ uint8_t SCSICommandLength; /**< Length of the issued SCSI command within the SCSI command data array. */
+ uint8_t SCSICommandData[16]; /**< Issued SCSI command in the Command Block. */
+ } ATTR_PACKED MS_CommandBlockWrapper_t;
+
+ /** \brief Mass Storage Class Command Status Wrapper.
+ *
+ * Type define for a Command Status Wrapper, used in the Mass Storage Bulk-Only Transport protocol.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint32_t Signature; /**< Status block signature, must be \ref MS_CSW_SIGNATURE to indicate a valid Command Status. */
+ uint32_t Tag; /**< Unique command ID value, to associate a command block wrapper with its command status wrapper. */
+ uint32_t DataTransferResidue; /**< Number of bytes of data not processed in the SCSI command. */
+ uint8_t Status; /**< Status code of the issued command - a value from the \ref MS_CommandStatusCodes_t enum. */
+ } ATTR_PACKED MS_CommandStatusWrapper_t;
+
+ /** \brief Mass Storage Class SCSI Sense Structure
+ *
+ * Type define for a SCSI Sense structure. Structures of this type are filled out by the
+ * device via the \ref MS_Host_RequestSense() function, indicating the current sense data of the
+ * device (giving explicit error codes for the last issued command). For details of the
+ * structure contents, refer to the SCSI specifications.
+ */
+ typedef struct
+ {
+ uint8_t ResponseCode;
+
+ uint8_t SegmentNumber;
+
+ unsigned SenseKey : 4;
+ unsigned Reserved : 1;
+ unsigned ILI : 1;
+ unsigned EOM : 1;
+ unsigned FileMark : 1;
+
+ uint8_t Information[4];
+ uint8_t AdditionalLength;
+ uint8_t CmdSpecificInformation[4];
+ uint8_t AdditionalSenseCode;
+ uint8_t AdditionalSenseQualifier;
+ uint8_t FieldReplaceableUnitCode;
+ uint8_t SenseKeySpecific[3];
+ } ATTR_PACKED SCSI_Request_Sense_Response_t;
+
+ /** \brief Mass Storage Class SCSI Inquiry Structure.
+ *
+ * Type define for a SCSI Inquiry structure. Structures of this type are filled out by the
+ * device via the \ref MS_Host_GetInquiryData() function, retrieving the attached device's
+ * information.
+ *
+ * For details of the structure contents, refer to the SCSI specifications.
+ */
+ typedef struct
+ {
+ unsigned DeviceType : 5;
+ unsigned PeripheralQualifier : 3;
+
+ unsigned Reserved : 7;
+ unsigned Removable : 1;
+
+ uint8_t Version;
+
+ unsigned ResponseDataFormat : 4;
+ unsigned Reserved2 : 1;
+ unsigned NormACA : 1;
+ unsigned TrmTsk : 1;
+ unsigned AERC : 1;
+
+ uint8_t AdditionalLength;
+ uint8_t Reserved3[2];
+
+ unsigned SoftReset : 1;
+ unsigned CmdQue : 1;
+ unsigned Reserved4 : 1;
+ unsigned Linked : 1;
+ unsigned Sync : 1;
+ unsigned WideBus16Bit : 1;
+ unsigned WideBus32Bit : 1;
+ unsigned RelAddr : 1;
+
+ uint8_t VendorID[8];
+ uint8_t ProductID[16];
+ uint8_t RevisionID[4];
+ } ATTR_PACKED SCSI_Inquiry_Response_t;
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/PrinterClassCommon.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/PrinterClassCommon.h
new file mode 100644
index 000000000..1edd1dd0e
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/PrinterClassCommon.h
@@ -0,0 +1,119 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Common definitions and declarations for the library USB Printer Class driver.
+ *
+ * Common definitions and declarations for the library USB Printer Class driver.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB module driver
+ * dispatch header located in LUFA/Drivers/USB.h.
+ */
+
+/** \ingroup Group_USBClassPrinter
+ * \defgroup Group_USBClassPrinterCommon Common Class Definitions
+ *
+ * \section Sec_USBClassPrinterCommon_ModDescription Module Description
+ * Constants, Types and Enum definitions that are common to both Device and Host modes for the USB
+ * Printer Class.
+ *
+ * @{
+ */
+
+#ifndef _PRINTER_CLASS_COMMON_H_
+#define _PRINTER_CLASS_COMMON_H_
+
+ /* Includes: */
+ #include "../../Core/StdDescriptors.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_PRINTER_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
+ #endif
+
+ /* Macros: */
+ /** \name Virtual Printer Status Line Masks */
+ //@{
+ /** Port status mask for a printer device, indicating that an error has *not* occurred. */
+ #define PRNT_PORTSTATUS_NOTERROR (1 << 3)
+
+ /** Port status mask for a printer device, indicating that the device is currently selected. */
+ #define PRNT_PORTSTATUS_SELECT (1 << 4)
+
+ /** Port status mask for a printer device, indicating that the device is currently out of paper. */
+ #define PRNT_PORTSTATUS_PAPEREMPTY (1 << 5)
+ //@}
+
+ /* Enums: */
+ /** Enum for possible Class, Subclass and Protocol values of device and interface descriptors relating to the Printer
+ * device class.
+ */
+ enum PRNT_Descriptor_ClassSubclassProtocol_t
+ {
+ PRNT_CSCP_PrinterClass = 0x07, /**< Descriptor Class value indicating that the device or interface
+ * belongs to the Printer class.
+ */
+ PRNT_CSCP_PrinterSubclass = 0x01, /**< Descriptor Subclass value indicating that the device or interface
+ * belongs to the Printer subclass.
+ */
+ PRNT_CSCP_BidirectionalProtocol = 0x02, /**< Descriptor Protocol value indicating that the device or interface
+ * belongs to the Bidirectional protocol of the Printer class.
+ */
+ };
+
+ /** Enum for the Printer class specific control requests that can be issued by the USB bus host. */
+ enum PRNT_ClassRequests_t
+ {
+ PRNT_REQ_GetDeviceID = 0x00, /**< Printer class-specific request to retrieve the Unicode ID
+ * string of the device, containing the device's name, manufacturer
+ * and supported printer languages.
+ */
+ PRNT_REQ_GetPortStatus = 0x01, /**< Printer class-specific request to get the current status of the
+ * virtual printer port, for device selection and ready states.
+ */
+ PRNT_REQ_SoftReset = 0x02, /**< Printer class-specific request to reset the device, ready for new
+ * printer commands.
+ */
+ };
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/RNDISClassCommon.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/RNDISClassCommon.h
new file mode 100644
index 000000000..640745efe
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/RNDISClassCommon.h
@@ -0,0 +1,411 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Common definitions and declarations for the library USB RNDIS Class driver.
+ *
+ * Common definitions and declarations for the library USB RNDIS Class driver.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB module driver
+ * dispatch header located in LUFA/Drivers/USB.h.
+ */
+
+/** \ingroup Group_USBClassRNDIS
+ * \defgroup Group_USBClassRNDISCommon Common Class Definitions
+ *
+ * \section Sec_USBClassRNDISCommon_ModDescription Module Description
+ * Constants, Types and Enum definitions that are common to both Device and Host modes for the USB
+ * RNDIS Class.
+ *
+ * @{
+ */
+
+#ifndef _RNDIS_CLASS_COMMON_H_
+#define _RNDIS_CLASS_COMMON_H_
+
+ /* Macros: */
+ #define __INCLUDE_FROM_CDC_DRIVER
+
+ /* Includes: */
+ #include "../../Core/StdDescriptors.h"
+ #include "CDCClassCommon.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_RNDIS_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
+ #endif
+
+ /* Macros: */
+ /** Additional error code for RNDIS functions when a device returns a logical command failure. */
+ #define RNDIS_ERROR_LOGICAL_CMD_FAILED 0x80
+
+ /** Implemented RNDIS Version Major. */
+ #define REMOTE_NDIS_VERSION_MAJOR 0x01
+
+ /** Implemented RNDIS Version Minor. */
+ #define REMOTE_NDIS_VERSION_MINOR 0x00
+
+ /** \name RNDIS Message Values */
+ //@{
+ #define REMOTE_NDIS_PACKET_MSG 0x00000001UL
+ #define REMOTE_NDIS_INITIALIZE_MSG 0x00000002UL
+ #define REMOTE_NDIS_HALT_MSG 0x00000003UL
+ #define REMOTE_NDIS_QUERY_MSG 0x00000004UL
+ #define REMOTE_NDIS_SET_MSG 0x00000005UL
+ #define REMOTE_NDIS_RESET_MSG 0x00000006UL
+ #define REMOTE_NDIS_INDICATE_STATUS_MSG 0x00000007UL
+ #define REMOTE_NDIS_KEEPALIVE_MSG 0x00000008UL
+ //@}
+
+ /** \name RNDIS Response Values */
+ //@{
+ #define REMOTE_NDIS_INITIALIZE_CMPLT 0x80000002UL
+ #define REMOTE_NDIS_QUERY_CMPLT 0x80000004UL
+ #define REMOTE_NDIS_SET_CMPLT 0x80000005UL
+ #define REMOTE_NDIS_RESET_CMPLT 0x80000006UL
+ #define REMOTE_NDIS_KEEPALIVE_CMPLT 0x80000008UL
+ //@}
+
+ /** \name RNDIS Status Values */
+ //@{
+ #define REMOTE_NDIS_STATUS_SUCCESS 0x00000000UL
+ #define REMOTE_NDIS_STATUS_FAILURE 0xC0000001UL
+ #define REMOTE_NDIS_STATUS_INVALID_DATA 0xC0010015UL
+ #define REMOTE_NDIS_STATUS_NOT_SUPPORTED 0xC00000BBUL
+ #define REMOTE_NDIS_STATUS_MEDIA_CONNECT 0x4001000BUL
+ #define REMOTE_NDIS_STATUS_MEDIA_DISCONNECT 0x4001000CUL
+ //@}
+
+ /** \name RNDIS Media States */
+ //@{
+ #define REMOTE_NDIS_MEDIA_STATE_CONNECTED 0x00000000UL
+ #define REMOTE_NDIS_MEDIA_STATE_DISCONNECTED 0x00000001UL
+ //@}
+
+ /** \name RNDIS Media Types */
+ //@{
+ #define REMOTE_NDIS_MEDIUM_802_3 0x00000000UL
+ //@}
+
+ /** \name RNDIS Connection Types */
+ //@{
+ #define REMOTE_NDIS_DF_CONNECTIONLESS 0x00000001UL
+ #define REMOTE_NDIS_DF_CONNECTION_ORIENTED 0x00000002UL
+ //@}
+
+ /** \name RNDIS Packet Types */
+ //@{
+ #define REMOTE_NDIS_PACKET_DIRECTED 0x00000001UL
+ #define REMOTE_NDIS_PACKET_MULTICAST 0x00000002UL
+ #define REMOTE_NDIS_PACKET_ALL_MULTICAST 0x00000004UL
+ #define REMOTE_NDIS_PACKET_BROADCAST 0x00000008UL
+ #define REMOTE_NDIS_PACKET_SOURCE_ROUTING 0x00000010UL
+ #define REMOTE_NDIS_PACKET_PROMISCUOUS 0x00000020UL
+ #define REMOTE_NDIS_PACKET_SMT 0x00000040UL
+ #define REMOTE_NDIS_PACKET_ALL_LOCAL 0x00000080UL
+ #define REMOTE_NDIS_PACKET_GROUP 0x00001000UL
+ #define REMOTE_NDIS_PACKET_ALL_FUNCTIONAL 0x00002000UL
+ #define REMOTE_NDIS_PACKET_FUNCTIONAL 0x00004000UL
+ #define REMOTE_NDIS_PACKET_MAC_FRAME 0x00008000UL
+ //@}
+
+ /** \name RNDIS OID Values */
+ //@{
+ #define OID_GEN_SUPPORTED_LIST 0x00010101UL
+ #define OID_GEN_HARDWARE_STATUS 0x00010102UL
+ #define OID_GEN_MEDIA_SUPPORTED 0x00010103UL
+ #define OID_GEN_MEDIA_IN_USE 0x00010104UL
+ #define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106UL
+ #define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111UL
+ #define OID_GEN_LINK_SPEED 0x00010107UL
+ #define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010AUL
+ #define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010BUL
+ #define OID_GEN_VENDOR_ID 0x0001010CUL
+ #define OID_GEN_VENDOR_DESCRIPTION 0x0001010DUL
+ #define OID_GEN_CURRENT_PACKET_FILTER 0x0001010EUL
+ #define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111UL
+ #define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114UL
+ #define OID_GEN_PHYSICAL_MEDIUM 0x00010202UL
+ #define OID_GEN_XMIT_OK 0x00020101UL
+ #define OID_GEN_RCV_OK 0x00020102UL
+ #define OID_GEN_XMIT_ERROR 0x00020103UL
+ #define OID_GEN_RCV_ERROR 0x00020104UL
+ #define OID_GEN_RCV_NO_BUFFER 0x00020105UL
+ #define OID_802_3_PERMANENT_ADDRESS 0x01010101UL
+ #define OID_802_3_CURRENT_ADDRESS 0x01010102UL
+ #define OID_802_3_MULTICAST_LIST 0x01010103UL
+ #define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104UL
+ #define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101UL
+ #define OID_802_3_XMIT_ONE_COLLISION 0x01020102UL
+ #define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103UL
+ //@}
+
+ /** Maximum size in bytes of an Ethernet frame according to the Ethernet standard. */
+ #define ETHERNET_FRAME_SIZE_MAX 1500
+
+ /* Enums: */
+ /** Enum for the RNDIS class specific control requests that can be issued by the USB bus host. */
+ enum RNDIS_ClassRequests_t
+ {
+ RNDIS_REQ_SendEncapsulatedCommand = 0x00, /**< RNDIS request to issue a host-to-device NDIS command. */
+ RNDIS_REQ_GetEncapsulatedResponse = 0x01, /**< RNDIS request to issue a device-to-host NDIS response. */
+ };
+
+ /** Enum for the possible NDIS adapter states. */
+ enum RNDIS_States_t
+ {
+ RNDIS_Uninitialized = 0, /**< Adapter currently uninitialized. */
+ RNDIS_Initialized = 1, /**< Adapter currently initialized but not ready for data transfers. */
+ RNDIS_Data_Initialized = 2, /**< Adapter currently initialized and ready for data transfers. */
+ };
+
+ /** Enum for the RNDIS class specific notification requests that can be issued by a RNDIS device to a host. */
+ enum RNDIS_ClassNotifications_t
+ {
+ RNDIS_NOTIF_ResponseAvailable = 0x01, /**< Notification request value for a RNDIS Response Available notification. */
+ };
+
+ /** Enum for the NDIS hardware states. */
+ enum NDIS_Hardware_Status_t
+ {
+ NDIS_HardwareStatus_Ready, /**< Hardware Ready to accept commands from the host. */
+ NDIS_HardwareStatus_Initializing, /**< Hardware busy initializing. */
+ NDIS_HardwareStatus_Reset, /**< Hardware reset. */
+ NDIS_HardwareStatus_Closing, /**< Hardware currently closing. */
+ NDIS_HardwareStatus_NotReady /**< Hardware not ready to accept commands from the host. */
+ };
+
+ /* Type Defines: */
+ /** \brief MAC Address Structure.
+ *
+ * Type define for a physical MAC address of a device on a network.
+ */
+ typedef struct
+ {
+ uint8_t Octets[6]; /**< Individual bytes of a MAC address */
+ } ATTR_PACKED MAC_Address_t;
+
+ /** \brief RNDIS Common Message Header Structure.
+ *
+ * Type define for a RNDIS message header, sent before RNDIS messages.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint32_t MessageType; /**< RNDIS message type, a \c REMOTE_NDIS_*_MSG constant */
+ uint32_t MessageLength; /**< Total length of the RNDIS message, in bytes */
+ } ATTR_PACKED RNDIS_Message_Header_t;
+
+ /** \brief RNDIS Message Structure.
+ *
+ * Type define for a RNDIS packet message, used to encapsulate Ethernet packets sent to and from the adapter.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint32_t MessageType;
+ uint32_t MessageLength;
+ uint32_t DataOffset;
+ uint32_t DataLength;
+ uint32_t OOBDataOffset;
+ uint32_t OOBDataLength;
+ uint32_t NumOOBDataElements;
+ uint32_t PerPacketInfoOffset;
+ uint32_t PerPacketInfoLength;
+ uint32_t VcHandle;
+ uint32_t Reserved;
+ } ATTR_PACKED RNDIS_Packet_Message_t;
+
+ /** \brief RNDIS Initialization Message Structure.
+ *
+ * Type define for a RNDIS Initialize command message.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint32_t MessageType;
+ uint32_t MessageLength;
+ uint32_t RequestId;
+
+ uint32_t MajorVersion;
+ uint32_t MinorVersion;
+ uint32_t MaxTransferSize;
+ } ATTR_PACKED RNDIS_Initialize_Message_t;
+
+ /** \brief RNDIS Initialize Complete Message Structure.
+ *
+ * Type define for a RNDIS Initialize Complete response message.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint32_t MessageType;
+ uint32_t MessageLength;
+ uint32_t RequestId;
+ uint32_t Status;
+
+ uint32_t MajorVersion;
+ uint32_t MinorVersion;
+ uint32_t DeviceFlags;
+ uint32_t Medium;
+ uint32_t MaxPacketsPerTransfer;
+ uint32_t MaxTransferSize;
+ uint32_t PacketAlignmentFactor;
+ uint32_t AFListOffset;
+ uint32_t AFListSize;
+ } ATTR_PACKED RNDIS_Initialize_Complete_t;
+
+ /** \brief RNDIS Keep Alive Message Structure.
+ *
+ * Type define for a RNDIS Keep Alive command message.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint32_t MessageType;
+ uint32_t MessageLength;
+ uint32_t RequestId;
+ } ATTR_PACKED RNDIS_KeepAlive_Message_t;
+
+ /** \brief RNDIS Keep Alive Complete Message Structure.
+ *
+ * Type define for a RNDIS Keep Alive Complete response message.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint32_t MessageType;
+ uint32_t MessageLength;
+ uint32_t RequestId;
+ uint32_t Status;
+ } ATTR_PACKED RNDIS_KeepAlive_Complete_t;
+
+ /** \brief RNDIS Reset Complete Message Structure.
+ *
+ * Type define for a RNDIS Reset Complete response message.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint32_t MessageType;
+ uint32_t MessageLength;
+ uint32_t Status;
+
+ uint32_t AddressingReset;
+ } ATTR_PACKED RNDIS_Reset_Complete_t;
+
+ /** \brief RNDIS OID Property Set Message Structure.
+ *
+ * Type define for a RNDIS OID Property Set command message.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint32_t MessageType;
+ uint32_t MessageLength;
+ uint32_t RequestId;
+
+ uint32_t Oid;
+ uint32_t InformationBufferLength;
+ uint32_t InformationBufferOffset;
+ uint32_t DeviceVcHandle;
+ } ATTR_PACKED RNDIS_Set_Message_t;
+
+ /** \brief RNDIS OID Property Set Complete Message Structure.
+ *
+ * Type define for a RNDIS OID Property Set Complete response message.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint32_t MessageType;
+ uint32_t MessageLength;
+ uint32_t RequestId;
+ uint32_t Status;
+ } ATTR_PACKED RNDIS_Set_Complete_t;
+
+ /** \brief RNDIS OID Property Query Message Structure.
+ *
+ * Type define for a RNDIS OID Property Query command message.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint32_t MessageType;
+ uint32_t MessageLength;
+ uint32_t RequestId;
+
+ uint32_t Oid;
+ uint32_t InformationBufferLength;
+ uint32_t InformationBufferOffset;
+ uint32_t DeviceVcHandle;
+ } ATTR_PACKED RNDIS_Query_Message_t;
+
+ /** \brief RNDIS OID Property Query Complete Message Structure.
+ *
+ * Type define for a RNDIS OID Property Query Complete response message.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint32_t MessageType;
+ uint32_t MessageLength;
+ uint32_t RequestId;
+ uint32_t Status;
+
+ uint32_t InformationBufferLength;
+ uint32_t InformationBufferOffset;
+ } ATTR_PACKED RNDIS_Query_Complete_t;
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/StillImageClassCommon.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/StillImageClassCommon.h
new file mode 100644
index 000000000..09a9eab35
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/StillImageClassCommon.h
@@ -0,0 +1,161 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Common definitions and declarations for the library USB Still Image Class driver.
+ *
+ * Common definitions and declarations for the library USB Still Image Class driver.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB module driver
+ * dispatch header located in LUFA/Drivers/USB.h.
+ */
+
+/** \ingroup Group_USBClassSI
+ * \defgroup Group_USBClassSICommon Common Class Definitions
+ *
+ * \section Sec_USBClassSICommon_ModDescription Module Description
+ * Constants, Types and Enum definitions that are common to both Device and Host modes for the USB
+ * Still Image Class.
+ *
+ * @{
+ */
+
+#ifndef _SI_CLASS_COMMON_H_
+#define _SI_CLASS_COMMON_H_
+
+ /* Includes: */
+ #include "../../Core/StdDescriptors.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_SI_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
+ #endif
+
+ /* Macros: */
+ /** Length in bytes of a given Unicode string's character length.
+ *
+ * \param[in] Chars Total number of Unicode characters in the string.
+ *
+ * \return Number of bytes of the given unicode string.
+ */
+ #define UNICODE_STRING_LENGTH(Chars) ((Chars) << 1)
+
+ /** Used in the DataLength field of a PIMA container, to give the total container size in bytes for
+ * a command container.
+ *
+ * \param[in] Params Number of parameters which are to be sent in the \c Param field of the container.
+ */
+ #define PIMA_COMMAND_SIZE(Params) ((sizeof(PIMA_Container_t) - 12) + ((Params) * sizeof(uint32_t)))
+
+ /** Used in the DataLength field of a PIMA container, to give the total container size in bytes for
+ * a data container.
+ *
+ * \param[in] DataLen Length in bytes of the data in the container.
+ */
+ #define PIMA_DATA_SIZE(DataLen) ((sizeof(PIMA_Container_t) - 12) + (DataLen))
+
+ /* Enums: */
+ /** Enum for the possible PIMA contains types. */
+ enum PIMA_Container_Types_t
+ {
+ PIMA_CONTAINER_Undefined = 0, /**< Undefined container type. */
+ PIMA_CONTAINER_CommandBlock = 1, /**< Command Block container type. */
+ PIMA_CONTAINER_DataBlock = 2, /**< Data Block container type. */
+ PIMA_CONTAINER_ResponseBlock = 3, /**< Response container type. */
+ PIMA_CONTAINER_EventBlock = 4, /**< Event Block container type. */
+ };
+
+ /* Enums: */
+ /** Enum for possible Class, Subclass and Protocol values of device and interface descriptors relating to the
+ * Still Image device class.
+ */
+ enum SI_Descriptor_ClassSubclassProtocol_t
+ {
+ SI_CSCP_StillImageClass = 0x06, /**< Descriptor Class value indicating that the device or interface
+ * belongs to the Still Image class.
+ */
+ SI_CSCP_StillImageSubclass = 0x01, /**< Descriptor Subclass value indicating that the device or interface
+ * belongs to the Still Image subclass.
+ */
+ SI_CSCP_BulkOnlyProtocol = 0x01, /**< Descriptor Protocol value indicating that the device or interface
+ * belongs to the Bulk Only Transport protocol of the Still Image class.
+ */
+ };
+
+ /** Enums for the possible status codes of a returned Response Block from an attached PIMA compliant Still Image device. */
+ enum PIMA_ResponseCodes_t
+ {
+ PIMA_RESPONSE_OK = 1, /**< Response code indicating no error in the issued command. */
+ PIMA_RESPONSE_GeneralError = 2, /**< Response code indicating a general error while processing the
+ * issued command.
+ */
+ PIMA_RESPONSE_SessionNotOpen = 3, /**< Response code indicating that the sent command requires an open
+ * session before being issued.
+ */
+ PIMA_RESPONSE_InvalidTransaction = 4, /**< Response code indicating an invalid transaction occurred. */
+ PIMA_RESPONSE_OperationNotSupported = 5, /**< Response code indicating that the issued command is not supported
+ * by the attached device.
+ */
+ PIMA_RESPONSE_ParameterNotSupported = 6, /**< Response code indicating that one or more of the issued command's
+ * parameters are not supported by the device.
+ */
+ };
+
+ /* Type Defines: */
+ /** \brief PIMA Still Image Device Command/Response Container.
+ *
+ * Type define for a PIMA container, use to send commands and receive responses to and from an
+ * attached Still Image device.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint32_t DataLength; /**< Length of the container and data, in bytes. */
+ uint16_t Type; /**< Container type, a value from the \ref PIMA_Container_Types_t enum. */
+ uint16_t Code; /**< Command, event or response code of the container. */
+ uint32_t TransactionID; /**< Unique container ID to link blocks together. */
+ uint32_t Params[3]; /**< Block parameters to be issued along with the block code (command blocks only). */
+ } ATTR_PACKED PIMA_Container_t;
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/AudioClassDevice.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/AudioClassDevice.c
new file mode 100644
index 000000000..f862ba764
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/AudioClassDevice.c
@@ -0,0 +1,197 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../../Core/USBMode.h"
+
+#if defined(USB_CAN_BE_DEVICE)
+
+#define __INCLUDE_FROM_AUDIO_DRIVER
+#define __INCLUDE_FROM_AUDIO_DEVICE_C
+#include "AudioClassDevice.h"
+
+void Audio_Device_ProcessControlRequest(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
+{
+ if (!(Endpoint_IsSETUPReceived()))
+ return;
+
+ if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT) == REQREC_INTERFACE)
+ {
+ uint8_t InterfaceIndex = (USB_ControlRequest.wIndex & 0xFF);
+
+ if ((InterfaceIndex != AudioInterfaceInfo->Config.ControlInterfaceNumber) &&
+ (InterfaceIndex != AudioInterfaceInfo->Config.StreamingInterfaceNumber))
+ {
+ return;
+ }
+ }
+ else if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT) == REQREC_ENDPOINT)
+ {
+ uint8_t EndpointAddress = (USB_ControlRequest.wIndex & 0xFF);
+
+ if ((EndpointAddress != AudioInterfaceInfo->Config.DataINEndpoint.Address) &&
+ (EndpointAddress != AudioInterfaceInfo->Config.DataOUTEndpoint.Address))
+ {
+ return;
+ }
+ }
+
+ switch (USB_ControlRequest.bRequest)
+ {
+ case REQ_SetInterface:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+ Endpoint_ClearStatusStage();
+
+ AudioInterfaceInfo->State.InterfaceEnabled = ((USB_ControlRequest.wValue & 0xFF) != 0);
+ EVENT_Audio_Device_StreamStartStop(AudioInterfaceInfo);
+ }
+
+ break;
+ case AUDIO_REQ_GetStatus:
+ if ((USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) ||
+ (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_ENDPOINT)))
+ {
+ Endpoint_ClearSETUP();
+ Endpoint_ClearStatusStage();
+ }
+
+ break;
+ case AUDIO_REQ_SetCurrent:
+ case AUDIO_REQ_SetMinimum:
+ case AUDIO_REQ_SetMaximum:
+ case AUDIO_REQ_SetResolution:
+ if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT) == REQREC_ENDPOINT)
+ {
+ uint8_t EndpointProperty = USB_ControlRequest.bRequest;
+ uint8_t EndpointAddress = (uint8_t)USB_ControlRequest.wIndex;
+ uint8_t EndpointControl = (USB_ControlRequest.wValue >> 8);
+
+ if (CALLBACK_Audio_Device_GetSetEndpointProperty(AudioInterfaceInfo, EndpointProperty, EndpointAddress,
+ EndpointControl, NULL, NULL))
+ {
+ uint16_t ValueLength = USB_ControlRequest.wLength;
+ uint8_t Value[ValueLength];
+
+ Endpoint_ClearSETUP();
+ Endpoint_Read_Control_Stream_LE(Value, ValueLength);
+ Endpoint_ClearIN();
+
+ CALLBACK_Audio_Device_GetSetEndpointProperty(AudioInterfaceInfo, EndpointProperty, EndpointAddress,
+ EndpointControl, &ValueLength, Value);
+ }
+ }
+ else if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT) == REQREC_INTERFACE)
+ {
+ uint8_t Property = USB_ControlRequest.bRequest;
+ uint8_t Entity = (USB_ControlRequest.wIndex >> 8);
+ uint16_t Parameter = USB_ControlRequest.wValue;
+
+ if (CALLBACK_Audio_Device_GetSetInterfaceProperty(AudioInterfaceInfo, Property, Entity,
+ Parameter, NULL, NULL))
+ {
+ uint16_t ValueLength = USB_ControlRequest.wLength;
+ uint8_t Value[ValueLength];
+
+ Endpoint_ClearSETUP();
+ Endpoint_Read_Control_Stream_LE(Value, ValueLength);
+ Endpoint_ClearIN();
+
+ CALLBACK_Audio_Device_GetSetInterfaceProperty(AudioInterfaceInfo, Property, Entity,
+ Parameter, &ValueLength, Value);
+ }
+ }
+
+ break;
+ case AUDIO_REQ_GetCurrent:
+ case AUDIO_REQ_GetMinimum:
+ case AUDIO_REQ_GetMaximum:
+ case AUDIO_REQ_GetResolution:
+ if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT) == REQREC_ENDPOINT)
+ {
+ uint8_t EndpointProperty = USB_ControlRequest.bRequest;
+ uint8_t EndpointAddress = (uint8_t)USB_ControlRequest.wIndex;
+ uint8_t EndpointControl = (USB_ControlRequest.wValue >> 8);
+ uint16_t ValueLength = USB_ControlRequest.wLength;
+ uint8_t Value[ValueLength];
+
+ if (CALLBACK_Audio_Device_GetSetEndpointProperty(AudioInterfaceInfo, EndpointProperty, EndpointAddress,
+ EndpointControl, &ValueLength, Value))
+ {
+ Endpoint_ClearSETUP();
+ Endpoint_Write_Control_Stream_LE(Value, ValueLength);
+ Endpoint_ClearOUT();
+ }
+ }
+ else if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT) == REQREC_INTERFACE)
+ {
+ uint8_t Property = USB_ControlRequest.bRequest;
+ uint8_t Entity = (USB_ControlRequest.wIndex >> 8);
+ uint16_t Parameter = USB_ControlRequest.wValue;
+ uint16_t ValueLength = USB_ControlRequest.wLength;
+ uint8_t Value[ValueLength];
+
+ if (CALLBACK_Audio_Device_GetSetInterfaceProperty(AudioInterfaceInfo, Property, Entity,
+ Parameter, &ValueLength, Value))
+ {
+ Endpoint_ClearSETUP();
+ Endpoint_Write_Control_Stream_LE(Value, ValueLength);
+ Endpoint_ClearOUT();
+ }
+ }
+
+ break;
+ }
+}
+
+bool Audio_Device_ConfigureEndpoints(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
+{
+ memset(&AudioInterfaceInfo->State, 0x00, sizeof(AudioInterfaceInfo->State));
+
+ AudioInterfaceInfo->Config.DataINEndpoint.Type = EP_TYPE_ISOCHRONOUS;
+ AudioInterfaceInfo->Config.DataOUTEndpoint.Type = EP_TYPE_ISOCHRONOUS;
+
+ if (!(Endpoint_ConfigureEndpointTable(&AudioInterfaceInfo->Config.DataINEndpoint, 1)))
+ return false;
+
+ if (!(Endpoint_ConfigureEndpointTable(&AudioInterfaceInfo->Config.DataOUTEndpoint, 1)))
+ return false;
+
+ return true;
+}
+
+void Audio_Device_Event_Stub(void)
+{
+
+}
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/AudioClassDevice.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/AudioClassDevice.h
new file mode 100644
index 000000000..6cdf4db70
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/AudioClassDevice.h
@@ -0,0 +1,396 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Device mode driver for the library USB Audio 1.0 Class driver.
+ *
+ * Device mode driver for the library USB Audio 1.0 Class driver.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB module driver
+ * dispatch header located in LUFA/Drivers/USB.h.
+ */
+
+/** \ingroup Group_USBClassAudio
+ * \defgroup Group_USBClassAudioDevice Audio 1.0 Class Device Mode Driver
+ *
+ * \section Sec_USBClassAudioDevice_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Drivers/USB/Class/Device/AudioClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ *
+ * \section Sec_USBClassAudioDevice_ModDescription Module Description
+ * Device Mode USB Class driver framework interface, for the Audio 1.0 USB Class driver.
+ *
+ * @{
+ */
+
+#ifndef _AUDIO_CLASS_DEVICE_H_
+#define _AUDIO_CLASS_DEVICE_H_
+
+ /* Includes: */
+ #include "../../USB.h"
+ #include "../Common/AudioClassCommon.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_AUDIO_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Type Defines: */
+ /** \brief Audio Class Device Mode Configuration and State Structure.
+ *
+ * Class state structure. An instance of this structure should be made for each Audio interface
+ * within the user application, and passed to each of the Audio class driver functions as the
+ * \c AudioInterfaceInfo parameter. This stores each Audio interface's configuration and state information.
+ */
+ typedef struct
+ {
+ struct
+ {
+ uint8_t ControlInterfaceNumber; /**< Index of the Audio Control interface within the device this
+ * structure controls.
+ */
+ uint8_t StreamingInterfaceNumber; /**< Index of the Audio Streaming interface within the device this
+ * structure controls.
+ */
+
+ USB_Endpoint_Table_t DataINEndpoint; /**< Data IN endpoint configuration table. */
+ USB_Endpoint_Table_t DataOUTEndpoint; /**< Data OUT endpoint configuration table. */
+ } Config; /**< Config data for the USB class interface within the device. All elements in this section
+ * <b>must</b> be set or the interface will fail to enumerate and operate correctly.
+ */
+ struct
+ {
+ bool InterfaceEnabled; /**< Set and cleared by the class driver to indicate if the host has enabled the streaming endpoints
+ * of the Audio Streaming interface.
+ */
+ } State; /**< State data for the USB class interface within the device. All elements in this section
+ * are reset to their defaults when the interface is enumerated.
+ */
+ } USB_ClassInfo_Audio_Device_t;
+
+ /* Function Prototypes: */
+ /** Configures the endpoints of a given Audio interface, ready for use. This should be linked to the library
+ * \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration containing the
+ * given Audio interface is selected.
+ *
+ * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state.
+ *
+ * \return Boolean \c true if the endpoints were successfully configured, \c false otherwise.
+ */
+ bool Audio_Device_ConfigureEndpoints(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Processes incoming control requests from the host, that are directed to the given Audio class interface. This should be
+ * linked to the library \ref EVENT_USB_Device_ControlRequest() event.
+ *
+ * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state.
+ */
+ void Audio_Device_ProcessControlRequest(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Audio class driver callback for the setting and retrieval of streaming endpoint properties. This callback must be implemented
+ * in the user application to handle property manipulations on streaming audio endpoints.
+ *
+ * When the DataLength parameter is NULL, this callback should only indicate whether the specified operation is valid for
+ * the given endpoint index, and should return as fast as possible. When non-NULL, this value may be altered for GET operations
+ * to indicate the size of the retrieved data.
+ *
+ * \note The length of the retrieved data stored into the Data buffer on GET operations should not exceed the initial value
+ * of the \c DataLength parameter.
+ *
+ * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state.
+ * \param[in] EndpointProperty Property of the endpoint to get or set, a value from \ref Audio_ClassRequests_t.
+ * \param[in] EndpointAddress Address of the streaming endpoint whose property is being referenced.
+ * \param[in] EndpointControl Parameter of the endpoint to get or set, a value from \ref Audio_EndpointControls_t.
+ * \param[in,out] DataLength For SET operations, the length of the parameter data to set. For GET operations, the maximum
+ * length of the retrieved data. When NULL, the function should return whether the given property
+ * and parameter is valid for the requested endpoint without reading or modifying the Data buffer.
+ * \param[in,out] Data Pointer to a location where the parameter data is stored for SET operations, or where
+ * the retrieved data is to be stored for GET operations.
+ *
+ * \return Boolean \c true if the property GET/SET was successful, \c false otherwise
+ */
+ bool CALLBACK_Audio_Device_GetSetEndpointProperty(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,
+ const uint8_t EndpointProperty,
+ const uint8_t EndpointAddress,
+ const uint8_t EndpointControl,
+ uint16_t* const DataLength,
+ uint8_t* Data) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Audio class driver callback for the setting and retrieval of streaming interface properties. This callback must be implemented
+ * in the user application to handle property manipulations on streaming audio interfaces.
+ *
+ * When the DataLength parameter is NULL, this callback should only indicate whether the specified operation is valid for
+ * the given entity and should return as fast as possible. When non-NULL, this value may be altered for GET operations
+ * to indicate the size of the retrieved data.
+ *
+ * \note The length of the retrieved data stored into the Data buffer on GET operations should not exceed the initial value
+ * of the \c DataLength parameter.
+ *
+ * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state.
+ * \param[in] Property Property of the interface to get or set, a value from \ref Audio_ClassRequests_t.
+ * \param[in] EntityAddress Address of the audio entity whose property is being referenced.
+ * \param[in] Parameter Parameter of the entity to get or set, specific to each type of entity (see USB Audio specification).
+ * \param[in,out] DataLength For SET operations, the length of the parameter data to set. For GET operations, the maximum
+ * length of the retrieved data. When NULL, the function should return whether the given property
+ * and parameter is valid for the requested endpoint without reading or modifying the Data buffer.
+ * \param[in,out] Data Pointer to a location where the parameter data is stored for SET operations, or where
+ * the retrieved data is to be stored for GET operations.
+ *
+ * \return Boolean \c true if the property GET/SET was successful, \c false otherwise
+ */
+ bool CALLBACK_Audio_Device_GetSetInterfaceProperty(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,
+ const uint8_t Property,
+ const uint8_t EntityAddress,
+ const uint16_t Parameter,
+ uint16_t* const DataLength,
+ uint8_t* Data) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Audio class driver event for an Audio Stream start/stop change. This event fires each time the device receives a stream enable or
+ * disable control request from the host, to start and stop the audio stream. The current state of the stream can be determined by the
+ * State.InterfaceEnabled value inside the Audio interface structure passed as a parameter.
+ *
+ * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state.
+ */
+ void EVENT_Audio_Device_StreamStartStop(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo);
+
+ /* Inline Functions: */
+ /** General management task for a given Audio class interface, required for the correct operation of the interface. This should
+ * be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
+ *
+ * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state.
+ */
+ static inline void Audio_Device_USBTask(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
+ ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
+ static inline void Audio_Device_USBTask(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
+ {
+ (void)AudioInterfaceInfo;
+ }
+
+ /** Determines if the given audio interface is ready for a sample to be read from it, and selects the streaming
+ * OUT endpoint ready for reading.
+ *
+ * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or
+ * the call will fail.
+ *
+ * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state.
+ *
+ * \return Boolean \c true if the given Audio interface has a sample to be read, \c false otherwise.
+ */
+ static inline bool Audio_Device_IsSampleReceived(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
+ ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
+ static inline bool Audio_Device_IsSampleReceived(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
+ {
+ if ((USB_DeviceState != DEVICE_STATE_Configured) || !(AudioInterfaceInfo->State.InterfaceEnabled))
+ return false;
+
+ Endpoint_SelectEndpoint(AudioInterfaceInfo->Config.DataOUTEndpoint.Address);
+ return Endpoint_IsOUTReceived();
+ }
+
+ /** Determines if the given audio interface is ready to accept the next sample to be written to it, and selects
+ * the streaming IN endpoint ready for writing.
+ *
+ * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or
+ * the call will fail.
+ *
+ * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state.
+ *
+ * \return Boolean \c true if the given Audio interface is ready to accept the next sample, \c false otherwise.
+ */
+ static inline bool Audio_Device_IsReadyForNextSample(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
+ ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
+ static inline bool Audio_Device_IsReadyForNextSample(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
+ {
+ if ((USB_DeviceState != DEVICE_STATE_Configured) || !(AudioInterfaceInfo->State.InterfaceEnabled))
+ return false;
+
+ Endpoint_SelectEndpoint(AudioInterfaceInfo->Config.DataINEndpoint.Address);
+ return Endpoint_IsINReady();
+ }
+
+ /** Reads the next 8-bit audio sample from the current audio interface.
+ *
+ * \pre This should be preceded immediately by a call to the \ref Audio_Device_IsSampleReceived() function to ensure
+ * that the correct endpoint is selected and ready for data.
+ *
+ * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state.
+ *
+ * \return Signed 8-bit audio sample from the audio interface.
+ */
+ static inline int8_t Audio_Device_ReadSample8(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
+ ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
+ static inline int8_t Audio_Device_ReadSample8(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
+ {
+ int8_t Sample;
+
+ (void)AudioInterfaceInfo;
+
+ Sample = Endpoint_Read_8();
+
+ if (!(Endpoint_BytesInEndpoint()))
+ Endpoint_ClearOUT();
+
+ return Sample;
+ }
+
+ /** Reads the next 16-bit audio sample from the current audio interface.
+ *
+ * \pre This should be preceded immediately by a call to the \ref Audio_Device_IsSampleReceived() function to ensure
+ * that the correct endpoint is selected and ready for data.
+ *
+ * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state.
+ *
+ * \return Signed 16-bit audio sample from the audio interface.
+ */
+ static inline int16_t Audio_Device_ReadSample16(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
+ ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
+ static inline int16_t Audio_Device_ReadSample16(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
+ {
+ int16_t Sample;
+
+ (void)AudioInterfaceInfo;
+
+ Sample = (int16_t)Endpoint_Read_16_LE();
+
+ if (!(Endpoint_BytesInEndpoint()))
+ Endpoint_ClearOUT();
+
+ return Sample;
+ }
+
+ /** Reads the next 24-bit audio sample from the current audio interface.
+ *
+ * \pre This should be preceded immediately by a call to the \ref Audio_Device_IsSampleReceived() function to ensure
+ * that the correct endpoint is selected and ready for data.
+ *
+ * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state.
+ *
+ * \return Signed 24-bit audio sample from the audio interface.
+ */
+ static inline int32_t Audio_Device_ReadSample24(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
+ ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
+ static inline int32_t Audio_Device_ReadSample24(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
+ {
+ int32_t Sample;
+
+ (void)AudioInterfaceInfo;
+
+ Sample = (((uint32_t)Endpoint_Read_8() << 16) | Endpoint_Read_16_LE());
+
+ if (!(Endpoint_BytesInEndpoint()))
+ Endpoint_ClearOUT();
+
+ return Sample;
+ }
+
+ /** Writes the next 8-bit audio sample to the current audio interface.
+ *
+ * \pre This should be preceded immediately by a call to the \ref Audio_Device_IsReadyForNextSample() function to
+ * ensure that the correct endpoint is selected and ready for data.
+ *
+ * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state.
+ * \param[in] Sample Signed 8-bit audio sample.
+ */
+ static inline void Audio_Device_WriteSample8(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,
+ const int8_t Sample) ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
+ static inline void Audio_Device_WriteSample8(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,
+ const int8_t Sample)
+ {
+ Endpoint_Write_8(Sample);
+
+ if (Endpoint_BytesInEndpoint() == AudioInterfaceInfo->Config.DataINEndpoint.Size)
+ Endpoint_ClearIN();
+ }
+
+ /** Writes the next 16-bit audio sample to the current audio interface.
+ *
+ * \pre This should be preceded immediately by a call to the \ref Audio_Device_IsReadyForNextSample() function to
+ * ensure that the correct endpoint is selected and ready for data.
+ *
+ * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state.
+ * \param[in] Sample Signed 16-bit audio sample.
+ */
+ static inline void Audio_Device_WriteSample16(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,
+ const int16_t Sample) ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
+ static inline void Audio_Device_WriteSample16(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,
+ const int16_t Sample)
+ {
+ Endpoint_Write_16_LE(Sample);
+
+ if (Endpoint_BytesInEndpoint() == AudioInterfaceInfo->Config.DataINEndpoint.Size)
+ Endpoint_ClearIN();
+ }
+
+ /** Writes the next 24-bit audio sample to the current audio interface.
+ *
+ * \pre This should be preceded immediately by a call to the \ref Audio_Device_IsReadyForNextSample() function to
+ * ensure that the correct endpoint is selected and ready for data.
+ *
+ * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state.
+ * \param[in] Sample Signed 24-bit audio sample.
+ */
+ static inline void Audio_Device_WriteSample24(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,
+ const int32_t Sample) ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
+ static inline void Audio_Device_WriteSample24(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo,
+ const int32_t Sample)
+ {
+ Endpoint_Write_16_LE(Sample);
+ Endpoint_Write_8(Sample >> 16);
+
+ if (Endpoint_BytesInEndpoint() == AudioInterfaceInfo->Config.DataINEndpoint.Size)
+ Endpoint_ClearIN();
+ }
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Function Prototypes: */
+ #if defined(__INCLUDE_FROM_AUDIO_DEVICE_C)
+ void Audio_Device_Event_Stub(void) ATTR_CONST;
+
+ void EVENT_Audio_Device_StreamStartStop(USB_ClassInfo_Audio_Device_t* const AudioInterfaceInfo)
+ ATTR_WEAK ATTR_NON_NULL_PTR_ARG(1) ATTR_ALIAS(Audio_Device_Event_Stub);
+ #endif
+
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/CDCClassDevice.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/CDCClassDevice.c
new file mode 100644
index 000000000..f4e74cf90
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/CDCClassDevice.c
@@ -0,0 +1,341 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../../Core/USBMode.h"
+
+#if defined(USB_CAN_BE_DEVICE)
+
+#define __INCLUDE_FROM_CDC_DRIVER
+#define __INCLUDE_FROM_CDC_DEVICE_C
+#include "CDCClassDevice.h"
+
+void CDC_Device_ProcessControlRequest(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
+{
+ if (!(Endpoint_IsSETUPReceived()))
+ return;
+
+ if (USB_ControlRequest.wIndex != CDCInterfaceInfo->Config.ControlInterfaceNumber)
+ return;
+
+ switch (USB_ControlRequest.bRequest)
+ {
+ case CDC_REQ_GetLineEncoding:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+
+ while (!(Endpoint_IsINReady()));
+
+ Endpoint_Write_32_LE(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS);
+ Endpoint_Write_8(CDCInterfaceInfo->State.LineEncoding.CharFormat);
+ Endpoint_Write_8(CDCInterfaceInfo->State.LineEncoding.ParityType);
+ Endpoint_Write_8(CDCInterfaceInfo->State.LineEncoding.DataBits);
+
+ Endpoint_ClearIN();
+ Endpoint_ClearStatusStage();
+ }
+
+ break;
+ case CDC_REQ_SetLineEncoding:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+
+ while (!(Endpoint_IsOUTReceived()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+
+ CDCInterfaceInfo->State.LineEncoding.BaudRateBPS = Endpoint_Read_32_LE();
+ CDCInterfaceInfo->State.LineEncoding.CharFormat = Endpoint_Read_8();
+ CDCInterfaceInfo->State.LineEncoding.ParityType = Endpoint_Read_8();
+ CDCInterfaceInfo->State.LineEncoding.DataBits = Endpoint_Read_8();
+
+ Endpoint_ClearOUT();
+ Endpoint_ClearStatusStage();
+
+ EVENT_CDC_Device_LineEncodingChanged(CDCInterfaceInfo);
+ }
+
+ break;
+ case CDC_REQ_SetControlLineState:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+ Endpoint_ClearStatusStage();
+
+ CDCInterfaceInfo->State.ControlLineStates.HostToDevice = USB_ControlRequest.wValue;
+
+ EVENT_CDC_Device_ControLineStateChanged(CDCInterfaceInfo);
+ }
+
+ break;
+ case CDC_REQ_SendBreak:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+ Endpoint_ClearStatusStage();
+
+ EVENT_CDC_Device_BreakSent(CDCInterfaceInfo, (uint8_t)USB_ControlRequest.wValue);
+ }
+
+ break;
+ }
+}
+
+bool CDC_Device_ConfigureEndpoints(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
+{
+ memset(&CDCInterfaceInfo->State, 0x00, sizeof(CDCInterfaceInfo->State));
+
+ CDCInterfaceInfo->Config.DataINEndpoint.Type = EP_TYPE_BULK;
+ CDCInterfaceInfo->Config.DataOUTEndpoint.Type = EP_TYPE_BULK;
+ CDCInterfaceInfo->Config.NotificationEndpoint.Type = EP_TYPE_INTERRUPT;
+
+ if (!(Endpoint_ConfigureEndpointTable(&CDCInterfaceInfo->Config.DataINEndpoint, 1)))
+ return false;
+
+ if (!(Endpoint_ConfigureEndpointTable(&CDCInterfaceInfo->Config.DataOUTEndpoint, 1)))
+ return false;
+
+ if (!(Endpoint_ConfigureEndpointTable(&CDCInterfaceInfo->Config.NotificationEndpoint, 1)))
+ return false;
+
+ return true;
+}
+
+void CDC_Device_USBTask(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
+{
+ if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
+ return;
+
+ #if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
+ Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address);
+
+ if (Endpoint_IsINReady())
+ CDC_Device_Flush(CDCInterfaceInfo);
+ #endif
+}
+
+uint8_t CDC_Device_SendString(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
+ const char* const String)
+{
+ if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
+ return ENDPOINT_RWSTREAM_DeviceDisconnected;
+
+ Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address);
+ return Endpoint_Write_Stream_LE(String, strlen(String), NULL);
+}
+
+uint8_t CDC_Device_SendData(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
+ const void* const Buffer,
+ const uint16_t Length)
+{
+ if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
+ return ENDPOINT_RWSTREAM_DeviceDisconnected;
+
+ Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address);
+ return Endpoint_Write_Stream_LE(Buffer, Length, NULL);
+}
+
+uint8_t CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
+ const uint8_t Data)
+{
+ if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
+ return ENDPOINT_RWSTREAM_DeviceDisconnected;
+
+ Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address);
+
+ if (!(Endpoint_IsReadWriteAllowed()))
+ {
+ Endpoint_ClearIN();
+
+ uint8_t ErrorCode;
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
+ return ErrorCode;
+ }
+
+ Endpoint_Write_8(Data);
+ return ENDPOINT_READYWAIT_NoError;
+}
+
+uint8_t CDC_Device_Flush(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
+{
+ if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
+ return ENDPOINT_RWSTREAM_DeviceDisconnected;
+
+ uint8_t ErrorCode;
+
+ Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address);
+
+ if (!(Endpoint_BytesInEndpoint()))
+ return ENDPOINT_READYWAIT_NoError;
+
+ bool BankFull = !(Endpoint_IsReadWriteAllowed());
+
+ Endpoint_ClearIN();
+
+ if (BankFull)
+ {
+ if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
+ return ErrorCode;
+
+ Endpoint_ClearIN();
+ }
+
+ return ENDPOINT_READYWAIT_NoError;
+}
+
+uint16_t CDC_Device_BytesReceived(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
+{
+ if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
+ return 0;
+
+ Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpoint.Address);
+
+ if (Endpoint_IsOUTReceived())
+ {
+ if (!(Endpoint_BytesInEndpoint()))
+ {
+ Endpoint_ClearOUT();
+ return 0;
+ }
+ else
+ {
+ return Endpoint_BytesInEndpoint();
+ }
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+int16_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
+{
+ if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
+ return -1;
+
+ int16_t ReceivedByte = -1;
+
+ Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataOUTEndpoint.Address);
+
+ if (Endpoint_IsOUTReceived())
+ {
+ if (Endpoint_BytesInEndpoint())
+ ReceivedByte = Endpoint_Read_8();
+
+ if (!(Endpoint_BytesInEndpoint()))
+ Endpoint_ClearOUT();
+ }
+
+ return ReceivedByte;
+}
+
+void CDC_Device_SendControlLineStateChange(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
+{
+ if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
+ return;
+
+ Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.NotificationEndpoint.Address);
+
+ USB_Request_Header_t Notification = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
+ .bRequest = CDC_NOTIF_SerialState,
+ .wValue = CPU_TO_LE16(0),
+ .wIndex = CPU_TO_LE16(0),
+ .wLength = CPU_TO_LE16(sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost)),
+ };
+
+ Endpoint_Write_Stream_LE(&Notification, sizeof(USB_Request_Header_t), NULL);
+ Endpoint_Write_Stream_LE(&CDCInterfaceInfo->State.ControlLineStates.DeviceToHost,
+ sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost),
+ NULL);
+ Endpoint_ClearIN();
+}
+
+#if defined(FDEV_SETUP_STREAM)
+void CDC_Device_CreateStream(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
+ FILE* const Stream)
+{
+ *Stream = (FILE)FDEV_SETUP_STREAM(CDC_Device_putchar, CDC_Device_getchar, _FDEV_SETUP_RW);
+ fdev_set_udata(Stream, CDCInterfaceInfo);
+}
+
+void CDC_Device_CreateBlockingStream(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
+ FILE* const Stream)
+{
+ *Stream = (FILE)FDEV_SETUP_STREAM(CDC_Device_putchar, CDC_Device_getchar_Blocking, _FDEV_SETUP_RW);
+ fdev_set_udata(Stream, CDCInterfaceInfo);
+}
+
+static int CDC_Device_putchar(char c,
+ FILE* Stream)
+{
+ return CDC_Device_SendByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream), c) ? _FDEV_ERR : 0;
+}
+
+static int CDC_Device_getchar(FILE* Stream)
+{
+ int16_t ReceivedByte = CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream));
+
+ if (ReceivedByte < 0)
+ return _FDEV_EOF;
+
+ return ReceivedByte;
+}
+
+static int CDC_Device_getchar_Blocking(FILE* Stream)
+{
+ int16_t ReceivedByte;
+
+ while ((ReceivedByte = CDC_Device_ReceiveByte((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream))) < 0)
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return _FDEV_EOF;
+
+ CDC_Device_USBTask((USB_ClassInfo_CDC_Device_t*)fdev_get_udata(Stream));
+ USB_USBTask();
+ }
+
+ return ReceivedByte;
+}
+#endif
+
+void CDC_Device_Event_Stub(void)
+{
+
+}
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/CDCClassDevice.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/CDCClassDevice.h
new file mode 100644
index 000000000..05c0fdddb
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/CDCClassDevice.h
@@ -0,0 +1,352 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Device mode driver for the library USB CDC Class driver.
+ *
+ * Device mode driver for the library USB CDC Class driver.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB module driver
+ * dispatch header located in LUFA/Drivers/USB.h.
+ */
+
+/** \ingroup Group_USBClassCDC
+ * \defgroup Group_USBClassCDCDevice CDC Class Device Mode Driver
+ *
+ * \section Sec_USBClassCDCDevice_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Drivers/USB/Class/Device/CDCClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ *
+ * \section Sec_USBClassCDCDevice_ModDescription Module Description
+ * Device Mode USB Class driver framework interface, for the CDC USB Class driver.
+ *
+ * \note There are several major drawbacks to the CDC-ACM standard USB class, however
+ * it is very standardized and thus usually available as a built-in driver on
+ * most platforms, and so is a better choice than a proprietary serial class.
+ *
+ * One major issue with CDC-ACM is that it requires two Interface descriptors,
+ * which will upset most hosts when part of a multi-function "Composite" USB
+ * device. This is because each interface will be loaded into a separate driver
+ * instance, causing the two interfaces be become unlinked. To prevent this, you
+ * should use the "Interface Association Descriptor" addendum to the USB 2.0 standard
+ * which is available on most OSes when creating Composite devices.
+ *
+ * Another major oversight is that there is no mechanism for the host to notify the
+ * device that there is a data sink on the host side ready to accept data. This
+ * means that the device may try to send data while the host isn't listening, causing
+ * lengthy blocking timeouts in the transmission routines. It is thus highly recommended
+ * that the virtual serial line DTR (Data Terminal Ready) signal be used where possible
+ * to determine if a host application is ready for data.
+ *
+ * @{
+ */
+
+#ifndef _CDC_CLASS_DEVICE_H_
+#define _CDC_CLASS_DEVICE_H_
+
+ /* Includes: */
+ #include "../../USB.h"
+ #include "../Common/CDCClassCommon.h"
+
+ #include <stdio.h>
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_CDC_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Type Defines: */
+ /** \brief CDC Class Device Mode Configuration and State Structure.
+ *
+ * Class state structure. An instance of this structure should be made for each CDC interface
+ * within the user application, and passed to each of the CDC class driver functions as the
+ * CDCInterfaceInfo parameter. This stores each CDC interface's configuration and state information.
+ */
+ typedef struct
+ {
+ struct
+ {
+ uint8_t ControlInterfaceNumber; /**< Interface number of the CDC control interface within the device. */
+
+ USB_Endpoint_Table_t DataINEndpoint; /**< Data IN endpoint configuration table. */
+ USB_Endpoint_Table_t DataOUTEndpoint; /**< Data OUT endpoint configuration table. */
+ USB_Endpoint_Table_t NotificationEndpoint; /**< Notification IN Endpoint configuration table. */
+ } Config; /**< Config data for the USB class interface within the device. All elements in this section
+ * <b>must</b> be set or the interface will fail to enumerate and operate correctly.
+ */
+ struct
+ {
+ struct
+ {
+ uint16_t HostToDevice; /**< Control line states from the host to device, as a set of \c CDC_CONTROL_LINE_OUT_*
+ * masks. This value is updated each time \ref CDC_Device_USBTask() is called.
+ */
+ uint16_t DeviceToHost; /**< Control line states from the device to host, as a set of \c CDC_CONTROL_LINE_IN_*
+ * masks - to notify the host of changes to these values, call the
+ * \ref CDC_Device_SendControlLineStateChange() function.
+ */
+ } ControlLineStates; /**< Current states of the virtual serial port's control lines between the device and host. */
+
+ CDC_LineEncoding_t LineEncoding; /**< Line encoding used in the virtual serial port, for the device's information.
+ * This is generally only used if the virtual serial port data is to be
+ * reconstructed on a physical UART.
+ */
+ } State; /**< State data for the USB class interface within the device. All elements in this section
+ * are reset to their defaults when the interface is enumerated.
+ */
+ } USB_ClassInfo_CDC_Device_t;
+
+ /* Function Prototypes: */
+ /** Configures the endpoints of a given CDC interface, ready for use. This should be linked to the library
+ * \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration containing
+ * the given CDC interface is selected.
+ *
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state.
+ *
+ * \return Boolean \c true if the endpoints were successfully configured, \c false otherwise.
+ */
+ bool CDC_Device_ConfigureEndpoints(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Processes incoming control requests from the host, that are directed to the given CDC class interface. This should be
+ * linked to the library \ref EVENT_USB_Device_ControlRequest() event.
+ *
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state.
+ */
+ void CDC_Device_ProcessControlRequest(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** General management task for a given CDC class interface, required for the correct operation of the interface. This should
+ * be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
+ *
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state.
+ */
+ void CDC_Device_USBTask(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** CDC class driver event for a line encoding change on a CDC interface. This event fires each time the host requests a
+ * line encoding change (containing the serial parity, baud and other configuration information) and may be hooked in the
+ * user program by declaring a handler function with the same name and parameters listed here. The new line encoding
+ * settings are available in the \c LineEncoding structure inside the CDC interface structure passed as a parameter.
+ *
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state.
+ */
+ void EVENT_CDC_Device_LineEncodingChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** CDC class driver event for a control line state change on a CDC interface. This event fires each time the host requests a
+ * control line state change (containing the virtual serial control line states, such as DTR) and may be hooked in the
+ * user program by declaring a handler function with the same name and parameters listed here. The new control line states
+ * are available in the \c ControlLineStates.HostToDevice value inside the CDC interface structure passed as a parameter, set as
+ * a mask of \c CDC_CONTROL_LINE_OUT_* masks.
+ *
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state.
+ */
+ void EVENT_CDC_Device_ControLineStateChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** CDC class driver event for a send break request sent to the device from the host. This is generally used to separate
+ * data or to indicate a special condition to the receiving device.
+ *
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state.
+ * \param[in] Duration Duration of the break that has been sent by the host, in milliseconds.
+ */
+ void EVENT_CDC_Device_BreakSent(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
+ const uint8_t Duration) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Sends a given data buffer to the attached USB host, if connected. If a host is not connected when the function is
+ * called, the string is discarded. Bytes will be queued for transmission to the host until either the endpoint bank
+ * becomes full, or the \ref CDC_Device_Flush() function is called to flush the pending data to the host. This allows
+ * for multiple bytes to be packed into a single endpoint packet, increasing data throughput.
+ *
+ * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or
+ * the call will fail.
+ *
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state.
+ * \param[in] Buffer Pointer to a buffer containing the data to send to the device.
+ * \param[in] Length Length of the data to send to the host.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t CDC_Device_SendData(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
+ const void* const Buffer,
+ const uint16_t Length) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+
+ /** Sends a given null terminated string to the attached USB host, if connected. If a host is not connected when
+ * the function is called, the string is discarded. Bytes will be queued for transmission to the host until either
+ * the endpoint bank becomes full, or the \ref CDC_Device_Flush() function is called to flush the pending data to
+ * the host. This allows for multiple bytes to be packed into a single endpoint packet, increasing data throughput.
+ *
+ * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or
+ * the call will fail.
+ *
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state.
+ * \param[in] String Pointer to the null terminated string to send to the host.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t CDC_Device_SendString(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
+ const char* const String) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+
+ /** Sends a given byte to the attached USB host, if connected. If a host is not connected when the function is called, the
+ * byte is discarded. Bytes will be queued for transmission to the host until either the endpoint bank becomes full, or the
+ * \ref CDC_Device_Flush() function is called to flush the pending data to the host. This allows for multiple bytes to be
+ * packed into a single endpoint packet, increasing data throughput.
+ *
+ * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or
+ * the call will fail.
+ *
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state.
+ * \param[in] Data Byte of data to send to the host.
+ *
+ * \return A value from the \ref Endpoint_WaitUntilReady_ErrorCodes_t enum.
+ */
+ uint8_t CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
+ const uint8_t Data) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Determines the number of bytes received by the CDC interface from the host, waiting to be read. This indicates the number
+ * of bytes in the OUT endpoint bank only, and thus the number of calls to \ref CDC_Device_ReceiveByte() which are guaranteed to
+ * succeed immediately. If multiple bytes are to be received, they should be buffered by the user application, as the endpoint
+ * bank will not be released back to the USB controller until all bytes are read.
+ *
+ * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or
+ * the call will fail.
+ *
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state.
+ *
+ * \return Total number of buffered bytes received from the host.
+ */
+ uint16_t CDC_Device_BytesReceived(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Reads a byte of data from the host. If no data is waiting to be read of if a USB host is not connected, the function
+ * returns a negative value. The \ref CDC_Device_BytesReceived() function may be queried in advance to determine how many
+ * bytes are currently buffered in the CDC interface's data receive endpoint bank, and thus how many repeated calls to this
+ * function which are guaranteed to succeed.
+ *
+ * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or
+ * the call will fail.
+ *
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state.
+ *
+ * \return Next received byte from the host, or a negative value if no data received.
+ */
+ int16_t CDC_Device_ReceiveByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Flushes any data waiting to be sent, ensuring that the send buffer is cleared.
+ *
+ * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or
+ * the call will fail.
+ *
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state.
+ *
+ * \return A value from the \ref Endpoint_WaitUntilReady_ErrorCodes_t enum.
+ */
+ uint8_t CDC_Device_Flush(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Sends a Serial Control Line State Change notification to the host. This should be called when the virtual serial
+ * control lines (DCD, DSR, etc.) have changed states, or to give BREAK notifications to the host. Line states persist
+ * until they are cleared via a second notification. This should be called each time the CDC class driver's
+ * \c ControlLineStates.DeviceToHost value is updated to push the new states to the USB host.
+ *
+ * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or
+ * the call will fail.
+ *
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state.
+ */
+ void CDC_Device_SendControlLineStateChange(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ #if defined(FDEV_SETUP_STREAM) || defined(__DOXYGEN__)
+ /** Creates a standard character stream for the given CDC Device instance so that it can be used with all the regular
+ * functions in the standard <stdio.h> library that accept a \c FILE stream as a destination (e.g. \c fprintf()). The created
+ * stream is bidirectional and can be used for both input and output functions.
+ *
+ * Reading data from this stream is non-blocking, i.e. in most instances, complete strings cannot be read in by a single
+ * fetch, as the endpoint will not be ready at some point in the transmission, aborting the transfer. However, this may
+ * be used when the read data is processed byte-per-bye (via \c getc()) or when the user application will implement its own
+ * line buffering.
+ *
+ * \note The created stream can be given as \c stdout if desired to direct the standard output from all \c <stdio.h> functions
+ * to the given CDC interface.
+ * \n\n
+ *
+ * \note This function is not available on all microcontroller architectures.
+ *
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state.
+ * \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed.
+ */
+ void CDC_Device_CreateStream(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
+ FILE* const Stream) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+
+ /** Identical to \ref CDC_Device_CreateStream(), except that reads are blocking until the calling stream function terminates
+ * the transfer. While blocking, the USB and CDC service tasks are called repeatedly to maintain USB communications.
+ *
+ * \note This function is not available on all microcontroller architectures.
+ *
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state.
+ * \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed.
+ */
+ void CDC_Device_CreateBlockingStream(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
+ FILE* const Stream) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Function Prototypes: */
+ #if defined(__INCLUDE_FROM_CDC_DEVICE_C)
+ #if defined(FDEV_SETUP_STREAM)
+ static int CDC_Device_putchar(char c,
+ FILE* Stream) ATTR_NON_NULL_PTR_ARG(2);
+ static int CDC_Device_getchar(FILE* Stream) ATTR_NON_NULL_PTR_ARG(1);
+ static int CDC_Device_getchar_Blocking(FILE* Stream) ATTR_NON_NULL_PTR_ARG(1);
+ #endif
+
+ void CDC_Device_Event_Stub(void) ATTR_CONST;
+
+ void EVENT_CDC_Device_LineEncodingChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
+ ATTR_WEAK ATTR_NON_NULL_PTR_ARG(1) ATTR_ALIAS(CDC_Device_Event_Stub);
+ void EVENT_CDC_Device_ControLineStateChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
+ ATTR_WEAK ATTR_NON_NULL_PTR_ARG(1) ATTR_ALIAS(CDC_Device_Event_Stub);
+ void EVENT_CDC_Device_BreakSent(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
+ const uint8_t Duration) ATTR_WEAK ATTR_NON_NULL_PTR_ARG(1)
+ ATTR_ALIAS(CDC_Device_Event_Stub);
+ #endif
+
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/HIDClassDevice.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/HIDClassDevice.c
new file mode 100644
index 000000000..03a745c1a
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/HIDClassDevice.c
@@ -0,0 +1,211 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../../Core/USBMode.h"
+
+#if defined(USB_CAN_BE_DEVICE)
+
+#define __INCLUDE_FROM_HID_DRIVER
+#define __INCLUDE_FROM_HID_DEVICE_C
+#include "HIDClassDevice.h"
+
+void HID_Device_ProcessControlRequest(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo)
+{
+ if (!(Endpoint_IsSETUPReceived()))
+ return;
+
+ if (USB_ControlRequest.wIndex != HIDInterfaceInfo->Config.InterfaceNumber)
+ return;
+
+ switch (USB_ControlRequest.bRequest)
+ {
+ case HID_REQ_GetReport:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ uint16_t ReportSize = 0;
+ uint8_t ReportID = (USB_ControlRequest.wValue & 0xFF);
+ uint8_t ReportType = (USB_ControlRequest.wValue >> 8) - 1;
+ uint8_t ReportData[HIDInterfaceInfo->Config.PrevReportINBufferSize];
+
+ memset(ReportData, 0, sizeof(ReportData));
+
+ CALLBACK_HID_Device_CreateHIDReport(HIDInterfaceInfo, &ReportID, ReportType, ReportData, &ReportSize);
+
+ if (HIDInterfaceInfo->Config.PrevReportINBuffer != NULL)
+ {
+ memcpy(HIDInterfaceInfo->Config.PrevReportINBuffer, ReportData,
+ HIDInterfaceInfo->Config.PrevReportINBufferSize);
+ }
+
+ Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);
+
+ Endpoint_ClearSETUP();
+
+ if (ReportID)
+ Endpoint_Write_8(ReportID);
+
+ Endpoint_Write_Control_Stream_LE(ReportData, ReportSize);
+ Endpoint_ClearOUT();
+ }
+
+ break;
+ case HID_REQ_SetReport:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ uint16_t ReportSize = USB_ControlRequest.wLength;
+ uint8_t ReportID = (USB_ControlRequest.wValue & 0xFF);
+ uint8_t ReportType = (USB_ControlRequest.wValue >> 8) - 1;
+ uint8_t ReportData[ReportSize];
+
+ Endpoint_ClearSETUP();
+ Endpoint_Read_Control_Stream_LE(ReportData, ReportSize);
+ Endpoint_ClearIN();
+
+ CALLBACK_HID_Device_ProcessHIDReport(HIDInterfaceInfo, ReportID, ReportType,
+ &ReportData[ReportID ? 1 : 0], ReportSize - (ReportID ? 1 : 0));
+ }
+
+ break;
+ case HID_REQ_GetProtocol:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+ while (!(Endpoint_IsINReady()));
+ Endpoint_Write_8(HIDInterfaceInfo->State.UsingReportProtocol);
+ Endpoint_ClearIN();
+ Endpoint_ClearStatusStage();
+ }
+
+ break;
+ case HID_REQ_SetProtocol:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+ Endpoint_ClearStatusStage();
+
+ HIDInterfaceInfo->State.UsingReportProtocol = ((USB_ControlRequest.wValue & 0xFF) != 0x00);
+ }
+
+ break;
+ case HID_REQ_SetIdle:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+ Endpoint_ClearStatusStage();
+
+ HIDInterfaceInfo->State.IdleCount = ((USB_ControlRequest.wValue & 0xFF00) >> 6);
+ }
+
+ break;
+ case HID_REQ_GetIdle:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+ while (!(Endpoint_IsINReady()));
+ Endpoint_Write_8(HIDInterfaceInfo->State.IdleCount >> 2);
+ Endpoint_ClearIN();
+ Endpoint_ClearStatusStage();
+ }
+
+ break;
+ }
+}
+
+bool HID_Device_ConfigureEndpoints(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo)
+{
+ memset(&HIDInterfaceInfo->State, 0x00, sizeof(HIDInterfaceInfo->State));
+ HIDInterfaceInfo->State.UsingReportProtocol = true;
+ HIDInterfaceInfo->State.IdleCount = 500;
+
+ HIDInterfaceInfo->Config.ReportINEndpoint.Type = EP_TYPE_INTERRUPT;
+
+ if (!(Endpoint_ConfigureEndpointTable(&HIDInterfaceInfo->Config.ReportINEndpoint, 1)))
+ return false;
+
+ return true;
+}
+
+void HID_Device_USBTask(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo)
+{
+ if (USB_DeviceState != DEVICE_STATE_Configured)
+ return;
+
+ if (HIDInterfaceInfo->State.PrevFrameNum == USB_Device_GetFrameNumber())
+ {
+ #if defined(USB_DEVICE_OPT_LOWSPEED)
+ if (!(USB_Options & USB_DEVICE_OPT_LOWSPEED))
+ return;
+ #else
+ return;
+ #endif
+ }
+
+ Endpoint_SelectEndpoint(HIDInterfaceInfo->Config.ReportINEndpoint.Address);
+
+ if (Endpoint_IsReadWriteAllowed())
+ {
+ uint8_t ReportINData[HIDInterfaceInfo->Config.PrevReportINBufferSize];
+ uint8_t ReportID = 0;
+ uint16_t ReportINSize = 0;
+
+ memset(ReportINData, 0, sizeof(ReportINData));
+
+ bool ForceSend = CALLBACK_HID_Device_CreateHIDReport(HIDInterfaceInfo, &ReportID, HID_REPORT_ITEM_In,
+ ReportINData, &ReportINSize);
+ bool StatesChanged = false;
+ bool IdlePeriodElapsed = (HIDInterfaceInfo->State.IdleCount && !(HIDInterfaceInfo->State.IdleMSRemaining));
+
+ if (HIDInterfaceInfo->Config.PrevReportINBuffer != NULL)
+ {
+ StatesChanged = (memcmp(ReportINData, HIDInterfaceInfo->Config.PrevReportINBuffer, ReportINSize) != 0);
+ memcpy(HIDInterfaceInfo->Config.PrevReportINBuffer, ReportINData, HIDInterfaceInfo->Config.PrevReportINBufferSize);
+ }
+
+ if (ReportINSize && (ForceSend || StatesChanged || IdlePeriodElapsed))
+ {
+ HIDInterfaceInfo->State.IdleMSRemaining = HIDInterfaceInfo->State.IdleCount;
+
+ Endpoint_SelectEndpoint(HIDInterfaceInfo->Config.ReportINEndpoint.Address);
+
+ if (ReportID)
+ Endpoint_Write_8(ReportID);
+
+ Endpoint_Write_Stream_LE(ReportINData, ReportINSize, NULL);
+
+ Endpoint_ClearIN();
+ }
+
+ HIDInterfaceInfo->State.PrevFrameNum = USB_Device_GetFrameNumber();
+ }
+}
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/HIDClassDevice.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/HIDClassDevice.h
new file mode 100644
index 000000000..f373cf076
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/HIDClassDevice.h
@@ -0,0 +1,210 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Device mode driver for the library USB HID Class driver.
+ *
+ * Device mode driver for the library USB HID Class driver.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB module driver
+ * dispatch header located in LUFA/Drivers/USB.h.
+ */
+
+/** \ingroup Group_USBClassHID
+ * \defgroup Group_USBClassHIDDevice HID Class Device Mode Driver
+ *
+ * \section Sec_USBClassHIDDevice_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Drivers/USB/Class/Device/HIDClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ *
+ * \section Sec_USBClassHIDDevice_ModDescription Module Description
+ * Device Mode USB Class driver framework interface, for the HID USB Class driver.
+ *
+ * @{
+ */
+
+#ifndef _HID_CLASS_DEVICE_H_
+#define _HID_CLASS_DEVICE_H_
+
+ /* Includes: */
+ #include "../../USB.h"
+ #include "../Common/HIDClassCommon.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_HID_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Type Defines: */
+ /** \brief HID Class Device Mode Configuration and State Structure.
+ *
+ * Class state structure. An instance of this structure should be made for each HID interface
+ * within the user application, and passed to each of the HID class driver functions as the
+ * \c HIDInterfaceInfo parameter. This stores each HID interface's configuration and state information.
+ *
+ * \note Due to technical limitations, the HID device class driver does not utilize a separate OUT
+ * endpoint for host->device communications. Instead, the host->device data (if any) is sent to
+ * the device via the control endpoint.
+ */
+ typedef struct
+ {
+ struct
+ {
+ uint8_t InterfaceNumber; /**< Interface number of the HID interface within the device. */
+
+ USB_Endpoint_Table_t ReportINEndpoint; /**< Data IN HID report endpoint configuration table. */
+
+ void* PrevReportINBuffer; /**< Pointer to a buffer where the previously created HID input report can be
+ * stored by the driver, for comparison purposes to detect report changes that
+ * must be sent immediately to the host. This should point to a buffer big enough
+ * to hold the largest HID input report sent from the HID interface. If this is set
+ * to \c NULL, it is up to the user to force transfers when needed in the
+ * \ref CALLBACK_HID_Device_CreateHIDReport() callback function.
+ *
+ * \note Due to the single buffer, the internal driver can only correctly compare
+ * subsequent reports with identical report IDs. In multiple report devices,
+ * this buffer should be set to \c NULL and the decision to send reports made
+ * by the user application instead.
+ */
+ uint8_t PrevReportINBufferSize; /**< Size in bytes of the given input report buffer. This is used to create a
+ * second buffer of the same size within the driver so that subsequent reports
+ * can be compared. If the user app is to determine when reports are to be sent
+ * exclusively (i.e. \c PrevReportINBuffer is \c NULL) this value must still be
+ * set to the size of the largest report the device can issue to the host.
+ */
+ } Config; /**< Config data for the USB class interface within the device. All elements in this section
+ * <b>must</b> be set or the interface will fail to enumerate and operate correctly.
+ */
+ struct
+ {
+ bool UsingReportProtocol; /**< Indicates if the HID interface is set to Boot or Report protocol mode. */
+ uint16_t PrevFrameNum; /**< Frame number of the previous HID report packet opportunity. */
+ uint16_t IdleCount; /**< Report idle period, in milliseconds, set by the host. */
+ uint16_t IdleMSRemaining; /**< Total number of milliseconds remaining before the idle period elapsed - this
+ * should be decremented by the user application if non-zero each millisecond. */
+ } State; /**< State data for the USB class interface within the device. All elements in this section
+ * are reset to their defaults when the interface is enumerated.
+ */
+ } USB_ClassInfo_HID_Device_t;
+
+ /* Function Prototypes: */
+ /** Configures the endpoints of a given HID interface, ready for use. This should be linked to the library
+ * \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration
+ * containing the given HID interface is selected.
+ *
+ * \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class configuration and state.
+ *
+ * \return Boolean \c true if the endpoints were successfully configured, \c false otherwise.
+ */
+ bool HID_Device_ConfigureEndpoints(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Processes incoming control requests from the host, that are directed to the given HID class interface. This should be
+ * linked to the library \ref EVENT_USB_Device_ControlRequest() event.
+ *
+ * \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class configuration and state.
+ */
+ void HID_Device_ProcessControlRequest(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** General management task for a given HID class interface, required for the correct operation of the interface. This should
+ * be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
+ *
+ * \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class configuration and state.
+ */
+ void HID_Device_USBTask(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** HID class driver callback for the user creation of a HID IN report. This callback may fire in response to either
+ * HID class control requests from the host, or by the normal HID endpoint polling procedure. Inside this callback the
+ * user is responsible for the creation of the next HID input report to be sent to the host.
+ *
+ * \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class configuration and state.
+ * \param[in,out] ReportID If preset to a non-zero value, this is the report ID being requested by the host. If zero,
+ * this should be set to the report ID of the generated HID input report (if any). If multiple
+ * reports are not sent via the given HID interface, this parameter should be ignored.
+ * \param[in] ReportType Type of HID report to generate, either \ref HID_REPORT_ITEM_In or \ref HID_REPORT_ITEM_Feature.
+ * \param[out] ReportData Pointer to a buffer where the generated HID report should be stored.
+ * \param[out] ReportSize Number of bytes in the generated input report, or zero if no report is to be sent.
+ *
+ * \return Boolean \c true to force the sending of the report even if it is identical to the previous report and still within
+ * the idle period (useful for devices which report relative movement), \c false otherwise.
+ */
+ bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,
+ uint8_t* const ReportID,
+ const uint8_t ReportType,
+ void* ReportData,
+ uint16_t* const ReportSize) ATTR_NON_NULL_PTR_ARG(1)
+ ATTR_NON_NULL_PTR_ARG(2) ATTR_NON_NULL_PTR_ARG(4) ATTR_NON_NULL_PTR_ARG(5);
+
+ /** HID class driver callback for the user processing of a received HID OUT report. This callback may fire in response to
+ * either HID class control requests from the host, or by the normal HID endpoint polling procedure. Inside this callback
+ * the user is responsible for the processing of the received HID output report from the host.
+ *
+ * \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class configuration and state.
+ * \param[in] ReportID Report ID of the received output report. If multiple reports are not received via the given HID
+ * interface, this parameter should be ignored.
+ * \param[in] ReportType Type of received HID report, either \ref HID_REPORT_ITEM_Out or \ref HID_REPORT_ITEM_Feature.
+ * \param[in] ReportData Pointer to a buffer where the received HID report is stored.
+ * \param[in] ReportSize Size in bytes of the received report from the host.
+ */
+ void CALLBACK_HID_Device_ProcessHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,
+ const uint8_t ReportID,
+ const uint8_t ReportType,
+ const void* ReportData,
+ const uint16_t ReportSize) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(4);
+
+ /* Inline Functions: */
+ /** Indicates that a millisecond of idle time has elapsed on the given HID interface, and the interface's idle count should be
+ * decremented. This should be called once per millisecond so that hardware key-repeats function correctly. It is recommended
+ * that this be called by the \ref EVENT_USB_Device_StartOfFrame() event, once SOF events have been enabled via
+ * \ref USB_Device_EnableSOFEvents().
+ *
+ * \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class configuration and state.
+ */
+ static inline void HID_Device_MillisecondElapsed(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo) ATTR_ALWAYS_INLINE ATTR_NON_NULL_PTR_ARG(1);
+ static inline void HID_Device_MillisecondElapsed(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo)
+ {
+ if (HIDInterfaceInfo->State.IdleMSRemaining)
+ HIDInterfaceInfo->State.IdleMSRemaining--;
+ }
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.c
new file mode 100644
index 000000000..b00252597
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.c
@@ -0,0 +1,131 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../../Core/USBMode.h"
+
+#if defined(USB_CAN_BE_DEVICE)
+
+#define __INCLUDE_FROM_MIDI_DRIVER
+#define __INCLUDE_FROM_MIDI_DEVICE_C
+#include "MIDIClassDevice.h"
+
+bool MIDI_Device_ConfigureEndpoints(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo)
+{
+ memset(&MIDIInterfaceInfo->State, 0x00, sizeof(MIDIInterfaceInfo->State));
+
+ MIDIInterfaceInfo->Config.DataINEndpoint.Type = EP_TYPE_BULK;
+ MIDIInterfaceInfo->Config.DataOUTEndpoint.Type = EP_TYPE_BULK;
+
+ if (!(Endpoint_ConfigureEndpointTable(&MIDIInterfaceInfo->Config.DataINEndpoint, 1)))
+ return false;
+
+ if (!(Endpoint_ConfigureEndpointTable(&MIDIInterfaceInfo->Config.DataOUTEndpoint, 1)))
+ return false;
+
+ return true;
+}
+
+void MIDI_Device_USBTask(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo)
+{
+ if (USB_DeviceState != DEVICE_STATE_Configured)
+ return;
+
+ #if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
+ Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataINEndpoint.Address);
+
+ if (Endpoint_IsINReady())
+ MIDI_Device_Flush(MIDIInterfaceInfo);
+ #endif
+}
+
+uint8_t MIDI_Device_SendEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo,
+ const MIDI_EventPacket_t* const Event)
+{
+ if (USB_DeviceState != DEVICE_STATE_Configured)
+ return ENDPOINT_RWSTREAM_DeviceDisconnected;
+
+ uint8_t ErrorCode;
+
+ Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataINEndpoint.Address);
+
+ if ((ErrorCode = Endpoint_Write_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NULL)) != ENDPOINT_RWSTREAM_NoError)
+ return ErrorCode;
+
+ if (!(Endpoint_IsReadWriteAllowed()))
+ Endpoint_ClearIN();
+
+ return ENDPOINT_RWSTREAM_NoError;
+}
+
+uint8_t MIDI_Device_Flush(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo)
+{
+ if (USB_DeviceState != DEVICE_STATE_Configured)
+ return ENDPOINT_RWSTREAM_DeviceDisconnected;
+
+ uint8_t ErrorCode;
+
+ Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataINEndpoint.Address);
+
+ if (Endpoint_BytesInEndpoint())
+ {
+ Endpoint_ClearIN();
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
+ return ErrorCode;
+ }
+
+ return ENDPOINT_READYWAIT_NoError;
+}
+
+bool MIDI_Device_ReceiveEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo,
+ MIDI_EventPacket_t* const Event)
+{
+ if (USB_DeviceState != DEVICE_STATE_Configured)
+ return false;
+
+ Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataOUTEndpoint.Address);
+
+ if (!(Endpoint_IsOUTReceived()))
+ return false;
+
+ if (!(Endpoint_IsReadWriteAllowed()))
+ return false;
+
+ Endpoint_Read_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NULL);
+
+ if (!(Endpoint_IsReadWriteAllowed()))
+ Endpoint_ClearOUT();
+
+ return true;
+}
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.h
new file mode 100644
index 000000000..70eb44291
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.h
@@ -0,0 +1,175 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Device mode driver for the library USB MIDI Class driver.
+ *
+ * Device mode driver for the library USB MIDI Class driver.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB module driver
+ * dispatch header located in LUFA/Drivers/USB.h.
+ */
+
+/** \ingroup Group_USBClassMIDI
+ * \defgroup Group_USBClassMIDIDevice MIDI Class Device Mode Driver
+ *
+ * \section Sec_USBClassMIDIDevice_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Drivers/USB/Class/Device/MIDIClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ *
+ * \section Sec_USBClassMIDIDevice_ModDescription Module Description
+ * Device Mode USB Class driver framework interface, for the MIDI USB Class driver.
+ *
+ * @{
+ */
+
+#ifndef _MIDI_CLASS_DEVICE_H_
+#define _MIDI_CLASS_DEVICE_H_
+
+ /* Includes: */
+ #include "../../USB.h"
+ #include "../Common/MIDIClassCommon.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_MIDI_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Type Define: */
+ /** \brief MIDI Class Device Mode Configuration and State Structure.
+ *
+ * Class state structure. An instance of this structure should be made for each MIDI interface
+ * within the user application, and passed to each of the MIDI class driver functions as the
+ * \c MIDIInterfaceInfo parameter. This stores each MIDI interface's configuration and state information.
+ */
+ typedef struct
+ {
+ struct
+ {
+ uint8_t StreamingInterfaceNumber; /**< Index of the Audio Streaming interface within the device this structure controls. */
+
+ USB_Endpoint_Table_t DataINEndpoint; /**< Data IN endpoint configuration table. */
+ USB_Endpoint_Table_t DataOUTEndpoint; /**< Data OUT endpoint configuration table. */
+ } Config; /**< Config data for the USB class interface within the device. All elements in this section
+ * <b>must</b> be set or the interface will fail to enumerate and operate correctly.
+ */
+
+ struct
+ {
+ uint8_t RESERVED; // No state information for this class
+ } State; /**< State data for the USB class interface within the device. All elements in this section
+ * are reset to their defaults when the interface is enumerated.
+ */
+ } USB_ClassInfo_MIDI_Device_t;
+
+ /* Function Prototypes: */
+ /** Configures the endpoints of a given MIDI interface, ready for use. This should be linked to the library
+ * \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration
+ * containing the given MIDI interface is selected.
+ *
+ * \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state.
+ *
+ * \return Boolean \c true if the endpoints were successfully configured, \c false otherwise.
+ */
+ bool MIDI_Device_ConfigureEndpoints(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** General management task for a given MIDI class interface, required for the correct operation of the interface. This should
+ * be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
+ *
+ * \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state.
+ */
+ void MIDI_Device_USBTask(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Sends a MIDI event packet to the host. If no host is connected, the event packet is discarded. Events are queued into the
+ * endpoint bank until either the endpoint bank is full, or \ref MIDI_Device_Flush() is called. This allows for multiple
+ * MIDI events to be packed into a single endpoint packet, increasing data throughput.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state.
+ * \param[in] Event Pointer to a populated \ref MIDI_EventPacket_t structure containing the MIDI event to send.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t MIDI_Device_SendEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo,
+ const MIDI_EventPacket_t* const Event) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+
+
+ /** Flushes the MIDI send buffer, sending any queued MIDI events to the host. This should be called to override the
+ * \ref MIDI_Device_SendEventPacket() function's packing behavior, to flush queued events.
+ *
+ * \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state.
+ *
+ * \return A value from the \ref Endpoint_WaitUntilReady_ErrorCodes_t enum.
+ */
+ uint8_t MIDI_Device_Flush(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Receives a MIDI event packet from the host. Events are unpacked from the endpoint, thus if the endpoint bank contains
+ * multiple MIDI events from the host in the one packet, multiple calls to this function will return each individual event.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state.
+ * \param[out] Event Pointer to a USB_MIDI_EventPacket_t structure where the received MIDI event is to be placed.
+ *
+ * \return Boolean \c true if a MIDI event packet was received, \c false otherwise.
+ */
+ bool MIDI_Device_ReceiveEventPacket(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo,
+ MIDI_EventPacket_t* const Event) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+
+ /* Inline Functions: */
+ /** Processes incoming control requests from the host, that are directed to the given MIDI class interface. This should be
+ * linked to the library \ref EVENT_USB_Device_ControlRequest() event.
+ *
+ * \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state.
+ */
+ static inline void MIDI_Device_ProcessControlRequest(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+ static inline void MIDI_Device_ProcessControlRequest(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo)
+ {
+ (void)MIDIInterfaceInfo;
+ }
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.c
new file mode 100644
index 000000000..d0907963a
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.c
@@ -0,0 +1,215 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../../Core/USBMode.h"
+
+#if defined(USB_CAN_BE_DEVICE)
+
+#define __INCLUDE_FROM_MS_DRIVER
+#define __INCLUDE_FROM_MASSSTORAGE_DEVICE_C
+#include "MassStorageClassDevice.h"
+
+void MS_Device_ProcessControlRequest(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
+{
+ if (!(Endpoint_IsSETUPReceived()))
+ return;
+
+ if (USB_ControlRequest.wIndex != MSInterfaceInfo->Config.InterfaceNumber)
+ return;
+
+ switch (USB_ControlRequest.bRequest)
+ {
+ case MS_REQ_MassStorageReset:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+ Endpoint_ClearStatusStage();
+
+ MSInterfaceInfo->State.IsMassStoreReset = true;
+ }
+
+ break;
+ case MS_REQ_GetMaxLUN:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+ while (!(Endpoint_IsINReady()));
+ Endpoint_Write_8(MSInterfaceInfo->Config.TotalLUNs - 1);
+ Endpoint_ClearIN();
+ Endpoint_ClearStatusStage();
+ }
+
+ break;
+ }
+}
+
+bool MS_Device_ConfigureEndpoints(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
+{
+ memset(&MSInterfaceInfo->State, 0x00, sizeof(MSInterfaceInfo->State));
+
+ MSInterfaceInfo->Config.DataINEndpoint.Type = EP_TYPE_BULK;
+ MSInterfaceInfo->Config.DataOUTEndpoint.Type = EP_TYPE_BULK;
+
+ if (!(Endpoint_ConfigureEndpointTable(&MSInterfaceInfo->Config.DataINEndpoint, 1)))
+ return false;
+
+ if (!(Endpoint_ConfigureEndpointTable(&MSInterfaceInfo->Config.DataOUTEndpoint, 1)))
+ return false;
+
+ return true;
+}
+
+void MS_Device_USBTask(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
+{
+ if (USB_DeviceState != DEVICE_STATE_Configured)
+ return;
+
+ Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpoint.Address);
+
+ if (Endpoint_IsOUTReceived())
+ {
+ if (MS_Device_ReadInCommandBlock(MSInterfaceInfo))
+ {
+ if (MSInterfaceInfo->State.CommandBlock.Flags & MS_COMMAND_DIR_DATA_IN)
+ Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpoint.Address);
+
+ bool SCSICommandResult = CALLBACK_MS_Device_SCSICommandReceived(MSInterfaceInfo);
+
+ MSInterfaceInfo->State.CommandStatus.Status = (SCSICommandResult) ? MS_SCSI_COMMAND_Pass : MS_SCSI_COMMAND_Fail;
+ MSInterfaceInfo->State.CommandStatus.Signature = CPU_TO_LE32(MS_CSW_SIGNATURE);
+ MSInterfaceInfo->State.CommandStatus.Tag = MSInterfaceInfo->State.CommandBlock.Tag;
+ MSInterfaceInfo->State.CommandStatus.DataTransferResidue = MSInterfaceInfo->State.CommandBlock.DataTransferLength;
+
+ if (!(SCSICommandResult) && (le32_to_cpu(MSInterfaceInfo->State.CommandStatus.DataTransferResidue)))
+ Endpoint_StallTransaction();
+
+ MS_Device_ReturnCommandStatus(MSInterfaceInfo);
+ }
+ }
+
+ if (MSInterfaceInfo->State.IsMassStoreReset)
+ {
+ Endpoint_ResetEndpoint(MSInterfaceInfo->Config.DataOUTEndpoint.Address);
+ Endpoint_ResetEndpoint(MSInterfaceInfo->Config.DataINEndpoint.Address);
+
+ Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpoint.Address);
+ Endpoint_ClearStall();
+ Endpoint_ResetDataToggle();
+ Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpoint.Address);
+ Endpoint_ClearStall();
+ Endpoint_ResetDataToggle();
+
+ MSInterfaceInfo->State.IsMassStoreReset = false;
+ }
+}
+
+static bool MS_Device_ReadInCommandBlock(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
+{
+ uint16_t BytesProcessed;
+
+ Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpoint.Address);
+
+ BytesProcessed = 0;
+ while (Endpoint_Read_Stream_LE(&MSInterfaceInfo->State.CommandBlock,
+ (sizeof(MS_CommandBlockWrapper_t) - 16), &BytesProcessed) ==
+ ENDPOINT_RWSTREAM_IncompleteTransfer)
+ {
+ if (MSInterfaceInfo->State.IsMassStoreReset)
+ return false;
+ }
+
+ if ((MSInterfaceInfo->State.CommandBlock.Signature != CPU_TO_LE32(MS_CBW_SIGNATURE)) ||
+ (MSInterfaceInfo->State.CommandBlock.LUN >= MSInterfaceInfo->Config.TotalLUNs) ||
+ (MSInterfaceInfo->State.CommandBlock.Flags & 0x1F) ||
+ (MSInterfaceInfo->State.CommandBlock.SCSICommandLength == 0) ||
+ (MSInterfaceInfo->State.CommandBlock.SCSICommandLength > 16))
+ {
+ Endpoint_StallTransaction();
+ Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpoint.Address);
+ Endpoint_StallTransaction();
+
+ return false;
+ }
+
+ BytesProcessed = 0;
+ while (Endpoint_Read_Stream_LE(&MSInterfaceInfo->State.CommandBlock.SCSICommandData,
+ MSInterfaceInfo->State.CommandBlock.SCSICommandLength, &BytesProcessed) ==
+ ENDPOINT_RWSTREAM_IncompleteTransfer)
+ {
+ if (MSInterfaceInfo->State.IsMassStoreReset)
+ return false;
+ }
+
+ Endpoint_ClearOUT();
+
+ return true;
+}
+
+static void MS_Device_ReturnCommandStatus(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
+{
+ Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataOUTEndpoint.Address);
+
+ while (Endpoint_IsStalled())
+ {
+ #if !defined(INTERRUPT_CONTROL_ENDPOINT)
+ USB_USBTask();
+ #endif
+
+ if (MSInterfaceInfo->State.IsMassStoreReset)
+ return;
+ }
+
+ Endpoint_SelectEndpoint(MSInterfaceInfo->Config.DataINEndpoint.Address);
+
+ while (Endpoint_IsStalled())
+ {
+ #if !defined(INTERRUPT_CONTROL_ENDPOINT)
+ USB_USBTask();
+ #endif
+
+ if (MSInterfaceInfo->State.IsMassStoreReset)
+ return;
+ }
+
+ uint16_t BytesProcessed = 0;
+ while (Endpoint_Write_Stream_LE(&MSInterfaceInfo->State.CommandStatus,
+ sizeof(MS_CommandStatusWrapper_t), &BytesProcessed) ==
+ ENDPOINT_RWSTREAM_IncompleteTransfer)
+ {
+ if (MSInterfaceInfo->State.IsMassStoreReset)
+ return;
+ }
+
+ Endpoint_ClearIN();
+}
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.h
new file mode 100644
index 000000000..513221308
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.h
@@ -0,0 +1,161 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Device mode driver for the library USB Mass Storage Class driver.
+ *
+ * Device mode driver for the library USB Mass Storage Class driver.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB module driver
+ * dispatch header located in LUFA/Drivers/USB.h.
+ */
+
+/** \ingroup Group_USBClassMS
+ * \defgroup Group_USBClassMSDevice Mass Storage Class Device Mode Driver
+ *
+ * \section Sec_USBClassMSDevice_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ *
+ * \section Sec_USBClassMSDevice_ModDescription Module Description
+ * Device Mode USB Class driver framework interface, for the Mass Storage USB Class driver.
+ *
+ * @{
+ */
+
+#ifndef _MS_CLASS_DEVICE_H_
+#define _MS_CLASS_DEVICE_H_
+
+ /* Includes: */
+ #include "../../USB.h"
+ #include "../Common/MassStorageClassCommon.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_MS_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Type Defines: */
+ /** \brief Mass Storage Class Device Mode Configuration and State Structure.
+ *
+ * Class state structure. An instance of this structure should be made for each Mass Storage interface
+ * within the user application, and passed to each of the Mass Storage class driver functions as the
+ * \c MSInterfaceInfo parameter. This stores each Mass Storage interface's configuration and state information.
+ */
+ typedef struct
+ {
+ struct
+ {
+ uint8_t InterfaceNumber; /**< Interface number of the Mass Storage interface within the device. */
+
+ USB_Endpoint_Table_t DataINEndpoint; /**< Data IN endpoint configuration table. */
+ USB_Endpoint_Table_t DataOUTEndpoint; /**< Data OUT endpoint configuration table. */
+
+ uint8_t TotalLUNs; /**< Total number of logical drives in the Mass Storage interface. */
+ } Config; /**< Config data for the USB class interface within the device. All elements in this section
+ * <b>must</b> be set or the interface will fail to enumerate and operate correctly.
+ */
+ struct
+ {
+ MS_CommandBlockWrapper_t CommandBlock; /**< Mass Storage class command block structure, stores the received SCSI
+ * command from the host which is to be processed.
+ */
+ MS_CommandStatusWrapper_t CommandStatus; /**< Mass Storage class command status structure, set elements to indicate
+ * the issued command's success or failure to the host.
+ */
+ volatile bool IsMassStoreReset; /**< Flag indicating that the host has requested that the Mass Storage interface be reset
+ * and that all current Mass Storage operations should immediately abort.
+ */
+ } State; /**< State data for the USB class interface within the device. All elements in this section
+ * are reset to their defaults when the interface is enumerated.
+ */
+ } USB_ClassInfo_MS_Device_t;
+
+ /* Function Prototypes: */
+ /** Configures the endpoints of a given Mass Storage interface, ready for use. This should be linked to the library
+ * \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration
+ * containing the given Mass Storage interface is selected.
+ *
+ * \param[in,out] MSInterfaceInfo Pointer to a structure containing a Mass Storage Class configuration and state.
+ *
+ * \return Boolean \c true if the endpoints were successfully configured, \c false otherwise.
+ */
+ bool MS_Device_ConfigureEndpoints(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Processes incoming control requests from the host, that are directed to the given Mass Storage class interface. This should be
+ * linked to the library \ref EVENT_USB_Device_ControlRequest() event.
+ *
+ * \param[in,out] MSInterfaceInfo Pointer to a structure containing a Mass Storage Class configuration and state.
+ */
+ void MS_Device_ProcessControlRequest(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** General management task for a given Mass Storage class interface, required for the correct operation of the interface. This should
+ * be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
+ *
+ * \param[in,out] MSInterfaceInfo Pointer to a structure containing a Mass Storage configuration and state.
+ */
+ void MS_Device_USBTask(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Mass Storage class driver callback for the user processing of a received SCSI command. This callback will fire each time the
+ * host sends a SCSI command which requires processing by the user application. Inside this callback the user is responsible
+ * for the processing of the received SCSI command from the host. The SCSI command is available in the CommandBlock structure
+ * inside the Mass Storage class state structure passed as a parameter to the callback function.
+ *
+ * \param[in,out] MSInterfaceInfo Pointer to a structure containing a Mass Storage Class configuration and state.
+ *
+ * \return Boolean \c true if the SCSI command was successfully processed, \c false otherwise.
+ */
+ bool CALLBACK_MS_Device_SCSICommandReceived(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Function Prototypes: */
+ #if defined(__INCLUDE_FROM_MASSSTORAGE_DEVICE_C)
+ static void MS_Device_ReturnCommandStatus(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+ static bool MS_Device_ReadInCommandBlock(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+ #endif
+
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/PrinterClassDevice.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/PrinterClassDevice.c
new file mode 100644
index 000000000..fd3454b1a
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/PrinterClassDevice.c
@@ -0,0 +1,314 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../../Core/USBMode.h"
+
+#if defined(USB_CAN_BE_DEVICE)
+
+#define __INCLUDE_FROM_PRINTER_DRIVER
+#define __INCLUDE_FROM_PRINTER_DEVICE_C
+#include "PrinterClassDevice.h"
+
+void PRNT_Device_ProcessControlRequest(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo)
+{
+ if (!(Endpoint_IsSETUPReceived()))
+ return;
+
+ if (USB_ControlRequest.wIndex != PRNTInterfaceInfo->Config.InterfaceNumber)
+ return;
+
+ switch (USB_ControlRequest.bRequest)
+ {
+ case PRNT_REQ_GetDeviceID:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+
+ while (!(Endpoint_IsINReady()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+
+ uint16_t IEEEStringLen = strlen(PRNTInterfaceInfo->Config.IEEE1284String);
+ Endpoint_Write_16_BE(IEEEStringLen);
+ Endpoint_Write_Control_Stream_LE(PRNTInterfaceInfo->Config.IEEE1284String, IEEEStringLen);
+ Endpoint_ClearStatusStage();
+ }
+
+ break;
+ case PRNT_REQ_GetPortStatus:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+
+ while (!(Endpoint_IsINReady()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+
+ Endpoint_Write_8(PRNTInterfaceInfo->State.PortStatus);
+ Endpoint_ClearStatusStage();
+ }
+
+ break;
+ case PRNT_REQ_SoftReset:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+ Endpoint_ClearStatusStage();
+
+ PRNTInterfaceInfo->State.IsPrinterReset = true;
+
+ EVENT_PRNT_Device_SoftReset(PRNTInterfaceInfo);
+ }
+
+ break;
+ }
+}
+
+bool PRNT_Device_ConfigureEndpoints(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo)
+{
+ memset(&PRNTInterfaceInfo->State, 0x00, sizeof(PRNTInterfaceInfo->State));
+ PRNTInterfaceInfo->State.PortStatus = PRNT_PORTSTATUS_NOTERROR | PRNT_PORTSTATUS_SELECT;
+
+ PRNTInterfaceInfo->Config.DataINEndpoint.Type = EP_TYPE_BULK;
+ PRNTInterfaceInfo->Config.DataOUTEndpoint.Type = EP_TYPE_BULK;
+
+ if (!(Endpoint_ConfigureEndpointTable(&PRNTInterfaceInfo->Config.DataINEndpoint, 1)))
+ return false;
+
+ if (!(Endpoint_ConfigureEndpointTable(&PRNTInterfaceInfo->Config.DataOUTEndpoint, 1)))
+ return false;
+
+ return true;
+}
+
+void PRNT_Device_USBTask(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo)
+{
+ if (USB_DeviceState != DEVICE_STATE_Configured)
+ return;
+
+ #if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
+ Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address);
+
+ if (Endpoint_IsINReady())
+ PRNT_Device_Flush(PRNTInterfaceInfo);
+ #endif
+
+ if (PRNTInterfaceInfo->State.IsPrinterReset)
+ {
+ Endpoint_ResetEndpoint(PRNTInterfaceInfo->Config.DataOUTEndpoint.Address);
+ Endpoint_ResetEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address);
+
+ Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataOUTEndpoint.Address);
+ Endpoint_ClearStall();
+ Endpoint_ResetDataToggle();
+ Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address);
+ Endpoint_ClearStall();
+ Endpoint_ResetDataToggle();
+
+ PRNTInterfaceInfo->State.IsPrinterReset = false;
+ }
+}
+
+uint8_t PRNT_Device_SendString(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo,
+ const char* const String)
+{
+ if (USB_DeviceState != DEVICE_STATE_Configured)
+ return ENDPOINT_RWSTREAM_DeviceDisconnected;
+
+ Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address);
+ return Endpoint_Write_Stream_LE(String, strlen(String), NULL);
+}
+
+uint8_t PRNT_Device_SendData(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo,
+ const void* const Buffer,
+ const uint16_t Length)
+{
+ if (USB_DeviceState != DEVICE_STATE_Configured)
+ return ENDPOINT_RWSTREAM_DeviceDisconnected;
+
+ Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address);
+ return Endpoint_Write_Stream_LE(Buffer, Length, NULL);
+}
+
+uint8_t PRNT_Device_SendByte(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo,
+ const uint8_t Data)
+{
+ if (USB_DeviceState != DEVICE_STATE_Configured)
+ return ENDPOINT_RWSTREAM_DeviceDisconnected;
+
+ Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address);
+
+ if (!(Endpoint_IsReadWriteAllowed()))
+ {
+ Endpoint_ClearIN();
+
+ uint8_t ErrorCode;
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
+ return ErrorCode;
+ }
+
+ Endpoint_Write_8(Data);
+ return ENDPOINT_READYWAIT_NoError;
+}
+
+uint8_t PRNT_Device_Flush(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo)
+{
+ if (USB_DeviceState != DEVICE_STATE_Configured)
+ return ENDPOINT_RWSTREAM_DeviceDisconnected;
+
+ uint8_t ErrorCode;
+
+ Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address);
+
+ if (!(Endpoint_BytesInEndpoint()))
+ return ENDPOINT_READYWAIT_NoError;
+
+ bool BankFull = !(Endpoint_IsReadWriteAllowed());
+
+ Endpoint_ClearIN();
+
+ if (BankFull)
+ {
+ if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
+ return ErrorCode;
+
+ Endpoint_ClearIN();
+ }
+
+ return ENDPOINT_READYWAIT_NoError;
+}
+
+uint16_t PRNT_Device_BytesReceived(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo)
+{
+ if (USB_DeviceState != DEVICE_STATE_Configured)
+ return 0;
+
+ Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataOUTEndpoint.Address);
+
+ if (Endpoint_IsOUTReceived())
+ {
+ if (!(Endpoint_BytesInEndpoint()))
+ {
+ Endpoint_ClearOUT();
+ return 0;
+ }
+ else
+ {
+ return Endpoint_BytesInEndpoint();
+ }
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+int16_t PRNT_Device_ReceiveByte(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo)
+{
+ if (USB_DeviceState != DEVICE_STATE_Configured)
+ return -1;
+
+ int16_t ReceivedByte = -1;
+
+ Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataOUTEndpoint.Address);
+
+ if (Endpoint_IsOUTReceived())
+ {
+ if (Endpoint_BytesInEndpoint())
+ ReceivedByte = Endpoint_Read_8();
+
+ if (!(Endpoint_BytesInEndpoint()))
+ Endpoint_ClearOUT();
+ }
+
+ return ReceivedByte;
+}
+
+#if defined(FDEV_SETUP_STREAM)
+void PRNT_Device_CreateStream(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo,
+ FILE* const Stream)
+{
+ *Stream = (FILE)FDEV_SETUP_STREAM(PRNT_Device_putchar, PRNT_Device_getchar, _FDEV_SETUP_RW);
+ fdev_set_udata(Stream, PRNTInterfaceInfo);
+}
+
+void PRNT_Device_CreateBlockingStream(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo,
+ FILE* const Stream)
+{
+ *Stream = (FILE)FDEV_SETUP_STREAM(PRNT_Device_putchar, PRNT_Device_getchar_Blocking, _FDEV_SETUP_RW);
+ fdev_set_udata(Stream, PRNTInterfaceInfo);
+}
+
+static int PRNT_Device_putchar(char c,
+ FILE* Stream)
+{
+ return PRNT_Device_SendByte((USB_ClassInfo_PRNT_Device_t*)fdev_get_udata(Stream), c) ? _FDEV_ERR : 0;
+}
+
+static int PRNT_Device_getchar(FILE* Stream)
+{
+ int16_t ReceivedByte = PRNT_Device_ReceiveByte((USB_ClassInfo_PRNT_Device_t*)fdev_get_udata(Stream));
+
+ if (ReceivedByte < 0)
+ return _FDEV_EOF;
+
+ return ReceivedByte;
+}
+
+static int PRNT_Device_getchar_Blocking(FILE* Stream)
+{
+ int16_t ReceivedByte;
+
+ while ((ReceivedByte = PRNT_Device_ReceiveByte((USB_ClassInfo_PRNT_Device_t*)fdev_get_udata(Stream))) < 0)
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return _FDEV_EOF;
+
+ PRNT_Device_USBTask((USB_ClassInfo_PRNT_Device_t*)fdev_get_udata(Stream));
+ USB_USBTask();
+ }
+
+ return ReceivedByte;
+}
+#endif
+
+void PRNT_Device_Event_Stub(void)
+{
+
+}
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/PrinterClassDevice.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/PrinterClassDevice.h
new file mode 100644
index 000000000..d9d9644cb
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/PrinterClassDevice.h
@@ -0,0 +1,293 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Device mode driver for the library USB Printer Class driver.
+ *
+ * Device mode driver for the library USB Printer Class driver.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB module driver
+ * dispatch header located in LUFA/Drivers/USB.h.
+ */
+
+/** \ingroup Group_USBClassPrinter
+ * \defgroup Group_USBClassPrinterDevice Printer Class Device Mode Driver
+ *
+ * \section Sec_USBClassPrinterDevice_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Drivers/USB/Class/Device/PrinterClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ *
+ * \section Sec_USBClassPrinterDevice_ModDescription Module Description
+ * Device Mode USB Class driver framework interface, for the Printer USB Class driver.
+ *
+ * @{
+ */
+
+#ifndef _PRINTER_CLASS_DEVICE_H_
+#define _PRINTER_CLASS_DEVICE_H_
+
+ /* Includes: */
+ #include "../../USB.h"
+ #include "../Common/PrinterClassCommon.h"
+
+ #include <stdio.h>
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_PRINTER_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Type Defines: */
+ /** \brief Printer Class Device Mode Configuration and State Structure.
+ *
+ * Class state structure. An instance of this structure should be made for each Printer interface
+ * within the user application, and passed to each of the Printer class driver functions as the
+ * PRNTInterfaceInfo parameter. This stores each Printer interface's configuration and state information.
+ */
+ typedef struct
+ {
+ struct
+ {
+ uint8_t InterfaceNumber; /**< Interface number of the Printer interface within the device. */
+
+ USB_Endpoint_Table_t DataINEndpoint; /**< Data IN endpoint configuration table. */
+ USB_Endpoint_Table_t DataOUTEndpoint; /**< Data OUT endpoint configuration table. */
+
+ char* IEEE1284String; /**< IEEE 1284 identification string, sent to the host during enumeration
+ * to identify the printer model, manufacturer and other characteristics.
+ */
+ } Config; /**< Config data for the USB class interface within the device. All elements in this section
+ * <b>must</b> be set or the interface will fail to enumerate and operate correctly.
+ */
+ struct
+ {
+ uint8_t PortStatus; /**< Current status of the Printer virtual port, a collection of \c PRNT_PORTSTATUS_*
+ * bitmask values.
+ */
+
+ volatile bool IsPrinterReset; /**< Flag indicating that the host has requested that the Printer interface be reset
+ * and that all current Mass Storage operations should immediately abort.
+ */
+ } State; /**< State data for the USB class interface within the device. All elements in this section
+ * are reset to their defaults when the interface is enumerated.
+ */
+ } USB_ClassInfo_PRNT_Device_t;
+
+ /* Function Prototypes: */
+ /** Configures the endpoints of a given Printer interface, ready for use. This should be linked to the library
+ * \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration containing
+ * the given Printer interface is selected.
+ *
+ * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state.
+ *
+ * \return Boolean \c true if the endpoints were successfully configured, \c false otherwise.
+ */
+ bool PRNT_Device_ConfigureEndpoints(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Processes incoming control requests from the host, that are directed to the given Printer class interface. This should be
+ * linked to the library \ref EVENT_USB_Device_ControlRequest() event.
+ *
+ * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state.
+ */
+ void PRNT_Device_ProcessControlRequest(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** General management task for a given Printer class interface, required for the correct operation of the interface. This should
+ * be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
+ *
+ * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state.
+ */
+ void PRNT_Device_USBTask(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Printer class driver event for a soft reset request on a Printer interface. This event fires each time the host
+ * requests a reset of the printer interface's internal state, and may be hooked in the user program by declaring a
+ * handler function with the same name and parameters listed here.
+ *
+ * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state.
+ */
+ void EVENT_PRNT_Device_SoftReset(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Sends a given data buffer to the attached USB host, if connected. If a host is not connected when the function is
+ * called, the string is discarded. Bytes will be queued for transmission to the host until either the endpoint bank
+ * becomes full, or the \ref PRNT_Device_Flush() function is called to flush the pending data to the host. This allows
+ * for multiple bytes to be packed into a single endpoint packet, increasing data throughput.
+ *
+ * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or
+ * the call will fail.
+ *
+ * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state.
+ * \param[in] Buffer Pointer to a buffer containing the data to send to the device.
+ * \param[in] Length Length of the data to send to the host.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t PRNT_Device_SendData(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo,
+ const void* const Buffer,
+ const uint16_t Length) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+
+ /** Sends a given null terminated string to the attached USB host, if connected. If a host is not connected when
+ * the function is called, the string is discarded. Bytes will be queued for transmission to the host until either
+ * the endpoint bank becomes full, or the \ref PRNT_Device_Flush() function is called to flush the pending data to
+ * the host. This allows for multiple bytes to be packed into a single endpoint packet, increasing data throughput.
+ *
+ * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or
+ * the call will fail.
+ *
+ * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state.
+ * \param[in] String Pointer to the null terminated string to send to the host.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t PRNT_Device_SendString(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo,
+ const char* const String) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+
+ /** Sends a given byte to the attached USB host, if connected. If a host is not connected when the function is called, the
+ * byte is discarded. Bytes will be queued for transmission to the host until either the endpoint bank becomes full, or the
+ * \ref PRNT_Device_Flush() function is called to flush the pending data to the host. This allows for multiple bytes to be
+ * packed into a single endpoint packet, increasing data throughput.
+ *
+ * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or
+ * the call will fail.
+ *
+ * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state.
+ * \param[in] Data Byte of data to send to the host.
+ *
+ * \return A value from the \ref Endpoint_WaitUntilReady_ErrorCodes_t enum.
+ */
+ uint8_t PRNT_Device_SendByte(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo,
+ const uint8_t Data) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Determines the number of bytes received by the Printer interface from the host, waiting to be read. This indicates the number
+ * of bytes in the OUT endpoint bank only, and thus the number of calls to \ref PRNT_Device_ReceiveByte() which are guaranteed to
+ * succeed immediately. If multiple bytes are to be received, they should be buffered by the user application, as the endpoint
+ * bank will not be released back to the USB controller until all bytes are read.
+ *
+ * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or
+ * the call will fail.
+ *
+ * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state.
+ *
+ * \return Total number of buffered bytes received from the host.
+ */
+ uint16_t PRNT_Device_BytesReceived(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Reads a byte of data from the host. If no data is waiting to be read of if a USB host is not connected, the function
+ * returns a negative value. The \ref PRNT_Device_BytesReceived() function may be queried in advance to determine how many
+ * bytes are currently buffered in the Printer interface's data receive endpoint bank, and thus how many repeated calls to this
+ * function which are guaranteed to succeed.
+ *
+ * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or
+ * the call will fail.
+ *
+ * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state.
+ *
+ * \return Next received byte from the host, or a negative value if no data received.
+ */
+ int16_t PRNT_Device_ReceiveByte(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Flushes any data waiting to be sent, ensuring that the send buffer is cleared.
+ *
+ * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or
+ * the call will fail.
+ *
+ * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state.
+ *
+ * \return A value from the \ref Endpoint_WaitUntilReady_ErrorCodes_t enum.
+ */
+ uint8_t PRNT_Device_Flush(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ #if defined(FDEV_SETUP_STREAM) || defined(__DOXYGEN__)
+ /** Creates a standard character stream for the given Printer Device instance so that it can be used with all the regular
+ * functions in the standard <stdio.h> library that accept a \c FILE stream as a destination (e.g. \c fprintf()). The created
+ * stream is bidirectional and can be used for both input and output functions.
+ *
+ * Reading data from this stream is non-blocking, i.e. in most instances, complete strings cannot be read in by a single
+ * fetch, as the endpoint will not be ready at some point in the transmission, aborting the transfer. However, this may
+ * be used when the read data is processed byte-per-bye (via \c getc()) or when the user application will implement its own
+ * line buffering.
+ *
+ * \note The created stream can be given as \c stdout if desired to direct the standard output from all \c <stdio.h> functions
+ * to the given Printer interface.
+ * \n\n
+ *
+ * \note This function is not available on all microcontroller architectures.
+ *
+ * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state.
+ * \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed.
+ */
+ void PRNT_Device_CreateStream(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo,
+ FILE* const Stream) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+
+ /** Identical to \ref PRNT_Device_CreateStream(), except that reads are blocking until the calling stream function terminates
+ * the transfer. While blocking, the USB and Printer service tasks are called repeatedly to maintain USB communications.
+ *
+ * \note This function is not available on all microcontroller architectures.
+ *
+ * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class configuration and state.
+ * \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed.
+ */
+ void PRNT_Device_CreateBlockingStream(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo,
+ FILE* const Stream) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Function Prototypes: */
+ #if defined(__INCLUDE_FROM_PRINTER_DEVICE_C)
+ #if defined(FDEV_SETUP_STREAM)
+ static int PRNT_Device_putchar(char c,
+ FILE* Stream) ATTR_NON_NULL_PTR_ARG(2);
+ static int PRNT_Device_getchar(FILE* Stream) ATTR_NON_NULL_PTR_ARG(1);
+ static int PRNT_Device_getchar_Blocking(FILE* Stream) ATTR_NON_NULL_PTR_ARG(1);
+ #endif
+
+ void PRNT_Device_Event_Stub(void) ATTR_CONST;
+
+ void EVENT_PRNT_Device_SoftReset(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo)
+ ATTR_WEAK ATTR_NON_NULL_PTR_ARG(1) ATTR_ALIAS(PRNT_Device_Event_Stub);
+
+ #endif
+
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.c
new file mode 100644
index 000000000..6ee73c5bb
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.c
@@ -0,0 +1,508 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../../Core/USBMode.h"
+
+#if defined(USB_CAN_BE_DEVICE)
+
+#define __INCLUDE_FROM_RNDIS_DRIVER
+#define __INCLUDE_FROM_RNDIS_DEVICE_C
+#include "RNDISClassDevice.h"
+
+static const uint32_t PROGMEM AdapterSupportedOIDList[] =
+ {
+ CPU_TO_LE32(OID_GEN_SUPPORTED_LIST),
+ CPU_TO_LE32(OID_GEN_PHYSICAL_MEDIUM),
+ CPU_TO_LE32(OID_GEN_HARDWARE_STATUS),
+ CPU_TO_LE32(OID_GEN_MEDIA_SUPPORTED),
+ CPU_TO_LE32(OID_GEN_MEDIA_IN_USE),
+ CPU_TO_LE32(OID_GEN_MAXIMUM_FRAME_SIZE),
+ CPU_TO_LE32(OID_GEN_MAXIMUM_TOTAL_SIZE),
+ CPU_TO_LE32(OID_GEN_LINK_SPEED),
+ CPU_TO_LE32(OID_GEN_TRANSMIT_BLOCK_SIZE),
+ CPU_TO_LE32(OID_GEN_RECEIVE_BLOCK_SIZE),
+ CPU_TO_LE32(OID_GEN_VENDOR_ID),
+ CPU_TO_LE32(OID_GEN_VENDOR_DESCRIPTION),
+ CPU_TO_LE32(OID_GEN_CURRENT_PACKET_FILTER),
+ CPU_TO_LE32(OID_GEN_MAXIMUM_TOTAL_SIZE),
+ CPU_TO_LE32(OID_GEN_MEDIA_CONNECT_STATUS),
+ CPU_TO_LE32(OID_GEN_XMIT_OK),
+ CPU_TO_LE32(OID_GEN_RCV_OK),
+ CPU_TO_LE32(OID_GEN_XMIT_ERROR),
+ CPU_TO_LE32(OID_GEN_RCV_ERROR),
+ CPU_TO_LE32(OID_GEN_RCV_NO_BUFFER),
+ CPU_TO_LE32(OID_802_3_PERMANENT_ADDRESS),
+ CPU_TO_LE32(OID_802_3_CURRENT_ADDRESS),
+ CPU_TO_LE32(OID_802_3_MULTICAST_LIST),
+ CPU_TO_LE32(OID_802_3_MAXIMUM_LIST_SIZE),
+ CPU_TO_LE32(OID_802_3_RCV_ERROR_ALIGNMENT),
+ CPU_TO_LE32(OID_802_3_XMIT_ONE_COLLISION),
+ CPU_TO_LE32(OID_802_3_XMIT_MORE_COLLISIONS),
+ };
+
+void RNDIS_Device_ProcessControlRequest(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
+{
+ if (!(Endpoint_IsSETUPReceived()))
+ return;
+
+ if (USB_ControlRequest.wIndex != RNDISInterfaceInfo->Config.ControlInterfaceNumber)
+ return;
+
+ switch (USB_ControlRequest.bRequest)
+ {
+ case RNDIS_REQ_SendEncapsulatedCommand:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+ Endpoint_Read_Control_Stream_LE(RNDISInterfaceInfo->Config.MessageBuffer, USB_ControlRequest.wLength);
+ Endpoint_ClearIN();
+
+ RNDIS_Device_ProcessRNDISControlMessage(RNDISInterfaceInfo);
+ }
+
+ break;
+ case RNDIS_REQ_GetEncapsulatedResponse:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)RNDISInterfaceInfo->Config.MessageBuffer;
+
+ if (!(MessageHeader->MessageLength))
+ {
+ RNDISInterfaceInfo->Config.MessageBuffer[0] = 0;
+ MessageHeader->MessageLength = CPU_TO_LE32(1);
+ }
+
+ Endpoint_ClearSETUP();
+ Endpoint_Write_Control_Stream_LE(RNDISInterfaceInfo->Config.MessageBuffer, le32_to_cpu(MessageHeader->MessageLength));
+ Endpoint_ClearOUT();
+
+ MessageHeader->MessageLength = CPU_TO_LE32(0);
+ }
+
+ break;
+ }
+}
+
+bool RNDIS_Device_ConfigureEndpoints(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
+{
+ memset(&RNDISInterfaceInfo->State, 0x00, sizeof(RNDISInterfaceInfo->State));
+
+ RNDISInterfaceInfo->Config.DataINEndpoint.Type = EP_TYPE_BULK;
+ RNDISInterfaceInfo->Config.DataOUTEndpoint.Type = EP_TYPE_BULK;
+ RNDISInterfaceInfo->Config.NotificationEndpoint.Type = EP_TYPE_INTERRUPT;
+
+ if (RNDISInterfaceInfo->Config.MessageBuffer == NULL)
+ return false;
+
+ if (RNDISInterfaceInfo->Config.MessageBufferLength < RNDIS_DEVICE_MIN_MESSAGE_BUFFER_LENGTH)
+ return false;
+
+ if (!(Endpoint_ConfigureEndpointTable(&RNDISInterfaceInfo->Config.DataINEndpoint, 1)))
+ return false;
+
+ if (!(Endpoint_ConfigureEndpointTable(&RNDISInterfaceInfo->Config.DataOUTEndpoint, 1)))
+ return false;
+
+ if (!(Endpoint_ConfigureEndpointTable(&RNDISInterfaceInfo->Config.NotificationEndpoint, 1)))
+ return false;
+
+ return true;
+}
+
+void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
+{
+ if (USB_DeviceState != DEVICE_STATE_Configured)
+ return;
+
+ Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.NotificationEndpoint.Address);
+
+ if (Endpoint_IsINReady() && RNDISInterfaceInfo->State.ResponseReady)
+ {
+ USB_Request_Header_t Notification = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
+ .bRequest = RNDIS_NOTIF_ResponseAvailable,
+ .wValue = CPU_TO_LE16(0),
+ .wIndex = CPU_TO_LE16(0),
+ .wLength = CPU_TO_LE16(0),
+ };
+
+ Endpoint_Write_Stream_LE(&Notification, sizeof(USB_Request_Header_t), NULL);
+
+ Endpoint_ClearIN();
+
+ RNDISInterfaceInfo->State.ResponseReady = false;
+ }
+}
+
+void RNDIS_Device_ProcessRNDISControlMessage(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
+{
+ /* Note: Only a single buffer is used for both the received message and its response to save SRAM. Because of
+ this, response bytes should be filled in order so that they do not clobber unread data in the buffer. */
+
+ RNDIS_Message_Header_t* MessageHeader = (RNDIS_Message_Header_t*)RNDISInterfaceInfo->Config.MessageBuffer;
+
+ switch (le32_to_cpu(MessageHeader->MessageType))
+ {
+ case REMOTE_NDIS_INITIALIZE_MSG:
+ RNDISInterfaceInfo->State.ResponseReady = true;
+
+ RNDIS_Initialize_Message_t* INITIALIZE_Message =
+ (RNDIS_Initialize_Message_t*)RNDISInterfaceInfo->Config.MessageBuffer;
+ RNDIS_Initialize_Complete_t* INITIALIZE_Response =
+ (RNDIS_Initialize_Complete_t*)RNDISInterfaceInfo->Config.MessageBuffer;
+
+ INITIALIZE_Response->MessageType = CPU_TO_LE32(REMOTE_NDIS_INITIALIZE_CMPLT);
+ INITIALIZE_Response->MessageLength = CPU_TO_LE32(sizeof(RNDIS_Initialize_Complete_t));
+ INITIALIZE_Response->RequestId = INITIALIZE_Message->RequestId;
+ INITIALIZE_Response->Status = CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS);
+
+ INITIALIZE_Response->MajorVersion = CPU_TO_LE32(REMOTE_NDIS_VERSION_MAJOR);
+ INITIALIZE_Response->MinorVersion = CPU_TO_LE32(REMOTE_NDIS_VERSION_MINOR);
+ INITIALIZE_Response->DeviceFlags = CPU_TO_LE32(REMOTE_NDIS_DF_CONNECTIONLESS);
+ INITIALIZE_Response->Medium = CPU_TO_LE32(REMOTE_NDIS_MEDIUM_802_3);
+ INITIALIZE_Response->MaxPacketsPerTransfer = CPU_TO_LE32(1);
+ INITIALIZE_Response->MaxTransferSize = CPU_TO_LE32(sizeof(RNDIS_Packet_Message_t) + ETHERNET_FRAME_SIZE_MAX);
+ INITIALIZE_Response->PacketAlignmentFactor = CPU_TO_LE32(0);
+ INITIALIZE_Response->AFListOffset = CPU_TO_LE32(0);
+ INITIALIZE_Response->AFListSize = CPU_TO_LE32(0);
+
+ RNDISInterfaceInfo->State.CurrRNDISState = RNDIS_Initialized;
+ break;
+ case REMOTE_NDIS_HALT_MSG:
+ RNDISInterfaceInfo->State.ResponseReady = false;
+
+ MessageHeader->MessageLength = CPU_TO_LE32(0);
+
+ RNDISInterfaceInfo->State.CurrRNDISState = RNDIS_Uninitialized;
+ break;
+ case REMOTE_NDIS_QUERY_MSG:
+ RNDISInterfaceInfo->State.ResponseReady = true;
+
+ RNDIS_Query_Message_t* QUERY_Message = (RNDIS_Query_Message_t*)RNDISInterfaceInfo->Config.MessageBuffer;
+ RNDIS_Query_Complete_t* QUERY_Response = (RNDIS_Query_Complete_t*)RNDISInterfaceInfo->Config.MessageBuffer;
+ uint32_t Query_Oid = CPU_TO_LE32(QUERY_Message->Oid);
+
+ void* QueryData = &RNDISInterfaceInfo->Config.MessageBuffer[sizeof(RNDIS_Message_Header_t) +
+ le32_to_cpu(QUERY_Message->InformationBufferOffset)];
+ void* ResponseData = &RNDISInterfaceInfo->Config.MessageBuffer[sizeof(RNDIS_Query_Complete_t)];
+ uint16_t ResponseSize;
+
+ QUERY_Response->MessageType = CPU_TO_LE32(REMOTE_NDIS_QUERY_CMPLT);
+
+ if (RNDIS_Device_ProcessNDISQuery(RNDISInterfaceInfo, Query_Oid, QueryData, le32_to_cpu(QUERY_Message->InformationBufferLength),
+ ResponseData, &ResponseSize))
+ {
+ QUERY_Response->Status = CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS);
+ QUERY_Response->MessageLength = cpu_to_le32(sizeof(RNDIS_Query_Complete_t) + ResponseSize);
+
+ QUERY_Response->InformationBufferLength = CPU_TO_LE32(ResponseSize);
+ QUERY_Response->InformationBufferOffset = CPU_TO_LE32(sizeof(RNDIS_Query_Complete_t) - sizeof(RNDIS_Message_Header_t));
+ }
+ else
+ {
+ QUERY_Response->Status = CPU_TO_LE32(REMOTE_NDIS_STATUS_NOT_SUPPORTED);
+ QUERY_Response->MessageLength = CPU_TO_LE32(sizeof(RNDIS_Query_Complete_t));
+
+ QUERY_Response->InformationBufferLength = CPU_TO_LE32(0);
+ QUERY_Response->InformationBufferOffset = CPU_TO_LE32(0);
+ }
+
+ break;
+ case REMOTE_NDIS_SET_MSG:
+ RNDISInterfaceInfo->State.ResponseReady = true;
+
+ RNDIS_Set_Message_t* SET_Message = (RNDIS_Set_Message_t*)RNDISInterfaceInfo->Config.MessageBuffer;
+ RNDIS_Set_Complete_t* SET_Response = (RNDIS_Set_Complete_t*)RNDISInterfaceInfo->Config.MessageBuffer;
+ uint32_t SET_Oid = le32_to_cpu(SET_Message->Oid);
+
+ SET_Response->MessageType = CPU_TO_LE32(REMOTE_NDIS_SET_CMPLT);
+ SET_Response->MessageLength = CPU_TO_LE32(sizeof(RNDIS_Set_Complete_t));
+ SET_Response->RequestId = SET_Message->RequestId;
+
+ void* SetData = &RNDISInterfaceInfo->Config.MessageBuffer[sizeof(RNDIS_Message_Header_t) +
+ le32_to_cpu(SET_Message->InformationBufferOffset)];
+
+ SET_Response->Status = RNDIS_Device_ProcessNDISSet(RNDISInterfaceInfo, SET_Oid, SetData,
+ le32_to_cpu(SET_Message->InformationBufferLength)) ?
+ REMOTE_NDIS_STATUS_SUCCESS : REMOTE_NDIS_STATUS_NOT_SUPPORTED;
+ break;
+ case REMOTE_NDIS_RESET_MSG:
+ RNDISInterfaceInfo->State.ResponseReady = true;
+
+ RNDIS_Reset_Complete_t* RESET_Response = (RNDIS_Reset_Complete_t*)RNDISInterfaceInfo->Config.MessageBuffer;
+
+ RESET_Response->MessageType = CPU_TO_LE32(REMOTE_NDIS_RESET_CMPLT);
+ RESET_Response->MessageLength = CPU_TO_LE32(sizeof(RNDIS_Reset_Complete_t));
+ RESET_Response->Status = CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS);
+ RESET_Response->AddressingReset = CPU_TO_LE32(0);
+
+ break;
+ case REMOTE_NDIS_KEEPALIVE_MSG:
+ RNDISInterfaceInfo->State.ResponseReady = true;
+
+ RNDIS_KeepAlive_Message_t* KEEPALIVE_Message =
+ (RNDIS_KeepAlive_Message_t*)RNDISInterfaceInfo->Config.MessageBuffer;
+ RNDIS_KeepAlive_Complete_t* KEEPALIVE_Response =
+ (RNDIS_KeepAlive_Complete_t*)RNDISInterfaceInfo->Config.MessageBuffer;
+
+ KEEPALIVE_Response->MessageType = CPU_TO_LE32(REMOTE_NDIS_KEEPALIVE_CMPLT);
+ KEEPALIVE_Response->MessageLength = CPU_TO_LE32(sizeof(RNDIS_KeepAlive_Complete_t));
+ KEEPALIVE_Response->RequestId = KEEPALIVE_Message->RequestId;
+ KEEPALIVE_Response->Status = CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS);
+
+ break;
+ }
+}
+
+static bool RNDIS_Device_ProcessNDISQuery(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
+ const uint32_t OId,
+ void* const QueryData,
+ const uint16_t QuerySize,
+ void* ResponseData,
+ uint16_t* const ResponseSize)
+{
+ (void)QueryData;
+ (void)QuerySize;
+
+ switch (OId)
+ {
+ case OID_GEN_SUPPORTED_LIST:
+ *ResponseSize = sizeof(AdapterSupportedOIDList);
+
+ memcpy_P(ResponseData, AdapterSupportedOIDList, sizeof(AdapterSupportedOIDList));
+
+ return true;
+ case OID_GEN_PHYSICAL_MEDIUM:
+ *ResponseSize = sizeof(uint32_t);
+
+ /* Indicate that the device is a true ethernet link */
+ *((uint32_t*)ResponseData) = CPU_TO_LE32(0);
+
+ return true;
+ case OID_GEN_HARDWARE_STATUS:
+ *ResponseSize = sizeof(uint32_t);
+
+ *((uint32_t*)ResponseData) = CPU_TO_LE32(NDIS_HardwareStatus_Ready);
+
+ return true;
+ case OID_GEN_MEDIA_SUPPORTED:
+ case OID_GEN_MEDIA_IN_USE:
+ *ResponseSize = sizeof(uint32_t);
+
+ *((uint32_t*)ResponseData) = CPU_TO_LE32(REMOTE_NDIS_MEDIUM_802_3);
+
+ return true;
+ case OID_GEN_VENDOR_ID:
+ *ResponseSize = sizeof(uint32_t);
+
+ /* Vendor ID 0x0xFFFFFF is reserved for vendors who have not purchased a NDIS VID */
+ *((uint32_t*)ResponseData) = CPU_TO_LE32(0x00FFFFFF);
+
+ return true;
+ case OID_GEN_MAXIMUM_FRAME_SIZE:
+ case OID_GEN_TRANSMIT_BLOCK_SIZE:
+ case OID_GEN_RECEIVE_BLOCK_SIZE:
+ *ResponseSize = sizeof(uint32_t);
+
+ *((uint32_t*)ResponseData) = CPU_TO_LE32(ETHERNET_FRAME_SIZE_MAX);
+
+ return true;
+ case OID_GEN_VENDOR_DESCRIPTION:
+ *ResponseSize = (strlen(RNDISInterfaceInfo->Config.AdapterVendorDescription) + 1);
+
+ memcpy(ResponseData, RNDISInterfaceInfo->Config.AdapterVendorDescription, *ResponseSize);
+
+ return true;
+ case OID_GEN_MEDIA_CONNECT_STATUS:
+ *ResponseSize = sizeof(uint32_t);
+
+ *((uint32_t*)ResponseData) = CPU_TO_LE32(REMOTE_NDIS_MEDIA_STATE_CONNECTED);
+
+ return true;
+ case OID_GEN_LINK_SPEED:
+ *ResponseSize = sizeof(uint32_t);
+
+ /* Indicate 10Mb/s link speed */
+ *((uint32_t*)ResponseData) = CPU_TO_LE32(100000);
+
+ return true;
+ case OID_802_3_PERMANENT_ADDRESS:
+ case OID_802_3_CURRENT_ADDRESS:
+ *ResponseSize = sizeof(MAC_Address_t);
+
+ memcpy(ResponseData, &RNDISInterfaceInfo->Config.AdapterMACAddress, sizeof(MAC_Address_t));
+
+ return true;
+ case OID_802_3_MAXIMUM_LIST_SIZE:
+ *ResponseSize = sizeof(uint32_t);
+
+ /* Indicate only one multicast address supported */
+ *((uint32_t*)ResponseData) = CPU_TO_LE32(1);
+
+ return true;
+ case OID_GEN_CURRENT_PACKET_FILTER:
+ *ResponseSize = sizeof(uint32_t);
+
+ *((uint32_t*)ResponseData) = cpu_to_le32(RNDISInterfaceInfo->State.CurrPacketFilter);
+
+ return true;
+ case OID_GEN_XMIT_OK:
+ case OID_GEN_RCV_OK:
+ case OID_GEN_XMIT_ERROR:
+ case OID_GEN_RCV_ERROR:
+ case OID_GEN_RCV_NO_BUFFER:
+ case OID_802_3_RCV_ERROR_ALIGNMENT:
+ case OID_802_3_XMIT_ONE_COLLISION:
+ case OID_802_3_XMIT_MORE_COLLISIONS:
+ *ResponseSize = sizeof(uint32_t);
+
+ /* Unused statistic OIDs - always return 0 for each */
+ *((uint32_t*)ResponseData) = CPU_TO_LE32(0);
+
+ return true;
+ case OID_GEN_MAXIMUM_TOTAL_SIZE:
+ *ResponseSize = sizeof(uint32_t);
+
+ /* Indicate maximum overall buffer (Ethernet frame and RNDIS header) the adapter can handle */
+ *((uint32_t*)ResponseData) = CPU_TO_LE32(RNDISInterfaceInfo->Config.MessageBufferLength + ETHERNET_FRAME_SIZE_MAX);
+
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool RNDIS_Device_ProcessNDISSet(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
+ const uint32_t OId,
+ const void* SetData,
+ const uint16_t SetSize)
+{
+ (void)SetSize;
+
+ switch (OId)
+ {
+ case OID_GEN_CURRENT_PACKET_FILTER:
+ RNDISInterfaceInfo->State.CurrPacketFilter = le32_to_cpu(*((uint32_t*)SetData));
+ RNDISInterfaceInfo->State.CurrRNDISState = (RNDISInterfaceInfo->State.CurrPacketFilter) ? RNDIS_Data_Initialized : RNDIS_Initialized;
+
+ return true;
+ case OID_802_3_MULTICAST_LIST:
+ /* Do nothing - throw away the value from the host as it is unused */
+
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool RNDIS_Device_IsPacketReceived(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
+{
+ if ((USB_DeviceState != DEVICE_STATE_Configured) ||
+ (RNDISInterfaceInfo->State.CurrRNDISState != RNDIS_Data_Initialized))
+ {
+ return false;
+ }
+
+ Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataOUTEndpoint.Address);
+ return Endpoint_IsOUTReceived();
+}
+
+uint8_t RNDIS_Device_ReadPacket(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
+ void* Buffer,
+ uint16_t* const PacketLength)
+{
+ if ((USB_DeviceState != DEVICE_STATE_Configured) ||
+ (RNDISInterfaceInfo->State.CurrRNDISState != RNDIS_Data_Initialized))
+ {
+ return ENDPOINT_RWSTREAM_DeviceDisconnected;
+ }
+
+ Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataOUTEndpoint.Address);
+
+ *PacketLength = 0;
+
+ if (!(Endpoint_IsOUTReceived()))
+ return ENDPOINT_RWSTREAM_NoError;
+
+ RNDIS_Packet_Message_t RNDISPacketHeader;
+ Endpoint_Read_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NULL);
+
+ if (le32_to_cpu(RNDISPacketHeader.DataLength) > ETHERNET_FRAME_SIZE_MAX)
+ {
+ Endpoint_StallTransaction();
+
+ return RNDIS_ERROR_LOGICAL_CMD_FAILED;
+ }
+
+ *PacketLength = (uint16_t)le32_to_cpu(RNDISPacketHeader.DataLength);
+
+ Endpoint_Read_Stream_LE(Buffer, *PacketLength, NULL);
+ Endpoint_ClearOUT();
+
+ return ENDPOINT_RWSTREAM_NoError;
+}
+
+uint8_t RNDIS_Device_SendPacket(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
+ void* Buffer,
+ const uint16_t PacketLength)
+{
+ uint8_t ErrorCode;
+
+ if ((USB_DeviceState != DEVICE_STATE_Configured) ||
+ (RNDISInterfaceInfo->State.CurrRNDISState != RNDIS_Data_Initialized))
+ {
+ return ENDPOINT_RWSTREAM_DeviceDisconnected;
+ }
+
+ Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataINEndpoint.Address);
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
+ return ErrorCode;
+
+ RNDIS_Packet_Message_t RNDISPacketHeader;
+
+ memset(&RNDISPacketHeader, 0, sizeof(RNDIS_Packet_Message_t));
+
+ RNDISPacketHeader.MessageType = CPU_TO_LE32(REMOTE_NDIS_PACKET_MSG);
+ RNDISPacketHeader.MessageLength = cpu_to_le32(sizeof(RNDIS_Packet_Message_t) + PacketLength);
+ RNDISPacketHeader.DataOffset = CPU_TO_LE32(sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t));
+ RNDISPacketHeader.DataLength = cpu_to_le32(PacketLength);
+
+ Endpoint_Write_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NULL);
+ Endpoint_Write_Stream_LE(Buffer, PacketLength, NULL);
+ Endpoint_ClearIN();
+
+ return ENDPOINT_RWSTREAM_NoError;
+}
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.h
new file mode 100644
index 000000000..2821d7deb
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.h
@@ -0,0 +1,207 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Device mode driver for the library USB RNDIS Class driver.
+ *
+ * Device mode driver for the library USB RNDIS Class driver.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB module driver
+ * dispatch header located in LUFA/Drivers/USB.h.
+ */
+
+/** \ingroup Group_USBClassRNDIS
+ * \defgroup Group_USBClassRNDISDevice RNDIS Class Device Mode Driver
+ *
+ * \section Sec_USBClassRNDISDevice_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Drivers/USB/Class/Device/RNDISClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ *
+ * \section Sec_USBClassRNDISDevice_ModDescription Module Description
+ * Device Mode USB Class driver framework interface, for the RNDIS USB Class driver.
+ *
+ * @{
+ */
+
+#ifndef _RNDIS_CLASS_DEVICE_H_
+#define _RNDIS_CLASS_DEVICE_H_
+
+ /* Includes: */
+ #include "../../USB.h"
+ #include "../Common/RNDISClassCommon.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_RNDIS_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Type Defines: */
+ /** \brief RNDIS Class Device Mode Configuration and State Structure.
+ *
+ * Class state structure. An instance of this structure should be made for each RNDIS interface
+ * within the user application, and passed to each of the RNDIS class driver functions as the
+ * \c RNDISInterfaceInfo parameter. This stores each RNDIS interface's configuration and state information.
+ */
+ typedef struct
+ {
+ struct
+ {
+ uint8_t ControlInterfaceNumber; /**< Interface number of the RNDIS control interface within the device. */
+
+ USB_Endpoint_Table_t DataINEndpoint; /**< Data IN endpoint configuration table. */
+ USB_Endpoint_Table_t DataOUTEndpoint; /**< Data OUT endpoint configuration table. */
+ USB_Endpoint_Table_t NotificationEndpoint; /**< Notification IN Endpoint configuration table. */
+
+ char* AdapterVendorDescription; /**< String description of the adapter vendor. */
+ MAC_Address_t AdapterMACAddress; /**< MAC address of the adapter. */
+
+ uint8_t* MessageBuffer; /**< Buffer where RNDIS messages can be stored by the internal driver. This
+ * should be at least 132 bytes in length for minimal functionality. */
+ uint16_t MessageBufferLength; /**< Length in bytes of the \ref MessageBuffer RNDIS buffer. */
+ } Config; /**< Config data for the USB class interface within the device. All elements in this section
+ * <b>must</b> be set or the interface will fail to enumerate and operate correctly.
+ */
+ struct
+ {
+ bool ResponseReady; /**< Internal flag indicating if a RNDIS message is waiting to be returned to the host. */
+ uint8_t CurrRNDISState; /**< Current RNDIS state of the adapter, a value from the \ref RNDIS_States_t enum. */
+ uint32_t CurrPacketFilter; /**< Current packet filter mode, used internally by the class driver. */
+ } State; /**< State data for the USB class interface within the device. All elements in this section
+ * are reset to their defaults when the interface is enumerated.
+ */
+ } USB_ClassInfo_RNDIS_Device_t;
+
+ /* Function Prototypes: */
+ /** Configures the endpoints of a given RNDIS interface, ready for use. This should be linked to the library
+ * \ref EVENT_USB_Device_ConfigurationChanged() event so that the endpoints are configured when the configuration
+ * containing the given RNDIS interface is selected.
+ *
+ * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing a RNDIS Class configuration and state.
+ *
+ * \return Boolean \c true if the endpoints were successfully configured, \c false otherwise.
+ */
+ bool RNDIS_Device_ConfigureEndpoints(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Processes incoming control requests from the host, that are directed to the given RNDIS class interface. This should be
+ * linked to the library \ref EVENT_USB_Device_ControlRequest() event.
+ *
+ * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing a RNDIS Class configuration and state.
+ */
+ void RNDIS_Device_ProcessControlRequest(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** General management task for a given RNDIS class interface, required for the correct operation of the interface. This should
+ * be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
+ *
+ * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing a RNDIS Class configuration and state.
+ */
+ void RNDIS_Device_USBTask(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Determines if a packet is currently waiting for the device to read in and process.
+ *
+ * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class configuration and state.
+ *
+ * \return Boolean \c true if a packet is waiting to be read in by the host, \c false otherwise.
+ */
+ bool RNDIS_Device_IsPacketReceived(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Retrieves the next pending packet from the device, discarding the remainder of the RNDIS packet header to leave
+ * only the packet contents for processing by the device in the nominated buffer.
+ *
+ * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class configuration and state.
+ * \param[out] Buffer Pointer to a buffer where the packer data is to be written to.
+ * \param[out] PacketLength Pointer to where the length in bytes of the read packet is to be stored.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t RNDIS_Device_ReadPacket(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
+ void* Buffer,
+ uint16_t* const PacketLength) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Sends the given packet to the attached RNDIS device, after adding a RNDIS packet message header.
+ *
+ * \pre This function must only be called when the Device state machine is in the \ref DEVICE_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class configuration and state.
+ * \param[in] Buffer Pointer to a buffer where the packer data is to be read from.
+ * \param[in] PacketLength Length in bytes of the packet to send.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t RNDIS_Device_SendPacket(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
+ void* Buffer,
+ const uint16_t PacketLength) ATTR_NON_NULL_PTR_ARG(1);
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define RNDIS_DEVICE_MIN_MESSAGE_BUFFER_LENGTH sizeof(AdapterSupportedOIDList) + sizeof(RNDIS_Query_Complete_t)
+
+ /* Function Prototypes: */
+ #if defined(__INCLUDE_FROM_RNDIS_DEVICE_C)
+ static void RNDIS_Device_ProcessRNDISControlMessage(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo)
+ ATTR_NON_NULL_PTR_ARG(1);
+ static bool RNDIS_Device_ProcessNDISQuery(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
+ const uint32_t OId,
+ void* const QueryData,
+ const uint16_t QuerySize,
+ void* ResponseData,
+ uint16_t* const ResponseSize) ATTR_NON_NULL_PTR_ARG(1)
+ ATTR_NON_NULL_PTR_ARG(5) ATTR_NON_NULL_PTR_ARG(6);
+ static bool RNDIS_Device_ProcessNDISSet(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
+ const uint32_t OId,
+ const void* SetData,
+ const uint16_t SetSize) ATTR_NON_NULL_PTR_ARG(1)
+ ATTR_NON_NULL_PTR_ARG(3);
+ #endif
+
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/HIDClass.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/HIDClass.h
new file mode 100644
index 000000000..d2eea7532
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/HIDClass.h
@@ -0,0 +1,82 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Master include file for the library USB HID Class driver.
+ *
+ * Master include file for the library USB HID Class driver, for both host and device modes, where available.
+ *
+ * This file should be included in all user projects making use of this optional class driver, instead of
+ * including any headers in the USB/ClassDriver/Device, USB/ClassDriver/Host or USB/ClassDriver/Common subdirectories.
+ */
+
+/** \ingroup Group_USBClassDrivers
+ * \defgroup Group_USBClassHID HID Class Driver
+ * \brief USB class driver for the USB-IF Human Interface Device (HID) class standard.
+ *
+ * \section Sec_USBClassHID_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Drivers/USB/Class/Device/HIDClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ * - LUFA/Drivers/USB/Class/Host/HIDClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ * - LUFA/Drivers/USB/Class/Host/HIDParser.c <i>(Makefile source module name: LUFA_SRC_USB)</i>
+ *
+ * \section Sec_USBClassHID_ModDescription Module Description
+ * HID Class Driver module. This module contains an internal implementation of the USB HID Class, for both Device
+ * and Host USB modes. User applications can use this class driver instead of implementing the HID class manually
+ * via the low-level LUFA APIs.
+ *
+ * This module is designed to simplify the user code by exposing only the required interface needed to interface with
+ * Hosts or Devices using the USB HID Class.
+ *
+ * @{
+ */
+
+#ifndef _HID_CLASS_H_
+#define _HID_CLASS_H_
+
+ /* Macros: */
+ #define __INCLUDE_FROM_USB_DRIVER
+ #define __INCLUDE_FROM_HID_DRIVER
+
+ /* Includes: */
+ #include "../Core/USBMode.h"
+
+ #if defined(USB_CAN_BE_DEVICE)
+ #include "Device/HIDClassDevice.h"
+ #endif
+
+ #if defined(USB_CAN_BE_HOST)
+ #include "Host/HIDClassHost.h"
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/AndroidAccessoryClassHost.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/AndroidAccessoryClassHost.c
new file mode 100644
index 000000000..ac8d5dc5c
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/AndroidAccessoryClassHost.c
@@ -0,0 +1,422 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../../Core/USBMode.h"
+
+#if defined(USB_CAN_BE_HOST)
+
+#define __INCLUDE_FROM_AOA_DRIVER
+#define __INCLUDE_FROM_ANDROIDACCESSORY_HOST_C
+#include "AndroidAccessoryClassHost.h"
+
+bool AOA_Host_ValidateAccessoryDevice(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
+ const USB_Descriptor_Device_t* const DeviceDescriptor,
+ bool* const NeedModeSwitch)
+{
+ (void)AOAInterfaceInfo;
+
+ if (DeviceDescriptor->Header.Type != DTYPE_Device)
+ return false;
+
+ *NeedModeSwitch = ((DeviceDescriptor->ProductID != ANDROID_ACCESSORY_PRODUCT_ID) &&
+ (DeviceDescriptor->ProductID != ANDROID_ACCESSORY_ADB_PRODUCT_ID));
+
+ return true;
+}
+
+uint8_t AOA_Host_ConfigurePipes(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
+ uint16_t ConfigDescriptorSize,
+ void* ConfigDescriptorData)
+{
+ USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
+ USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
+ USB_Descriptor_Interface_t* AOAInterface = NULL;
+
+ memset(&AOAInterfaceInfo->State, 0x00, sizeof(AOAInterfaceInfo->State));
+
+ if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
+ return AOA_ENUMERROR_InvalidConfigDescriptor;
+
+ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+ DCOMP_AOA_Host_NextAndroidAccessoryInterface) != DESCRIPTOR_SEARCH_COMP_Found)
+ {
+ return AOA_ENUMERROR_NoCompatibleInterfaceFound;
+ }
+
+ AOAInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
+
+ while (!(DataINEndpoint) || !(DataOUTEndpoint))
+ {
+ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+ DCOMP_AOA_Host_NextInterfaceBulkEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
+ {
+ return AOA_ENUMERROR_NoCompatibleInterfaceFound;
+ }
+
+ USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
+
+ if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN)
+ DataINEndpoint = EndpointData;
+ else
+ DataOUTEndpoint = EndpointData;
+ }
+
+ AOAInterfaceInfo->Config.DataINPipe.Size = le16_to_cpu(DataINEndpoint->EndpointSize);
+ AOAInterfaceInfo->Config.DataINPipe.EndpointAddress = DataINEndpoint->EndpointAddress;
+ AOAInterfaceInfo->Config.DataINPipe.Type = EP_TYPE_BULK;
+
+ AOAInterfaceInfo->Config.DataOUTPipe.Size = le16_to_cpu(DataOUTEndpoint->EndpointSize);
+ AOAInterfaceInfo->Config.DataOUTPipe.EndpointAddress = DataOUTEndpoint->EndpointAddress;
+ AOAInterfaceInfo->Config.DataOUTPipe.Type = EP_TYPE_BULK;
+
+ if (!(Pipe_ConfigurePipeTable(&AOAInterfaceInfo->Config.DataINPipe, 1)))
+ return AOA_ENUMERROR_PipeConfigurationFailed;
+
+ if (!(Pipe_ConfigurePipeTable(&AOAInterfaceInfo->Config.DataOUTPipe, 1)))
+ return AOA_ENUMERROR_PipeConfigurationFailed;
+
+ AOAInterfaceInfo->State.IsActive = true;
+ AOAInterfaceInfo->State.InterfaceNumber = AOAInterface->InterfaceNumber;
+
+ return AOA_ENUMERROR_NoError;
+}
+
+static uint8_t DCOMP_AOA_Host_NextAndroidAccessoryInterface(void* const CurrentDescriptor)
+{
+ USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
+
+ if (Header->Type == DTYPE_Interface)
+ {
+ USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
+
+ if ((Interface->Class == AOA_CSCP_AOADataClass) &&
+ (Interface->SubClass == AOA_CSCP_AOADataSubclass) &&
+ (Interface->Protocol == AOA_CSCP_AOADataProtocol))
+ {
+ return DESCRIPTOR_SEARCH_Found;
+ }
+ }
+
+ return DESCRIPTOR_SEARCH_NotFound;
+}
+
+static uint8_t DCOMP_AOA_Host_NextInterfaceBulkEndpoint(void* const CurrentDescriptor)
+{
+ USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
+
+ if (Header->Type == DTYPE_Endpoint)
+ {
+ USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
+
+ uint8_t EndpointType = (Endpoint->Attributes & EP_TYPE_MASK);
+
+ if ((EndpointType == EP_TYPE_BULK) && (!(Pipe_IsEndpointBound(Endpoint->EndpointAddress))))
+ return DESCRIPTOR_SEARCH_Found;
+ }
+ else if (Header->Type == DTYPE_Interface)
+ {
+ return DESCRIPTOR_SEARCH_Fail;
+ }
+
+ return DESCRIPTOR_SEARCH_NotFound;
+}
+
+void AOA_Host_USBTask(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(AOAInterfaceInfo->State.IsActive))
+ return;
+
+ #if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
+ AOA_Host_Flush(AOAInterfaceInfo);
+ #endif
+}
+
+uint8_t AOA_Host_StartAccessoryMode(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo)
+{
+ uint8_t ErrorCode;
+
+ uint16_t AccessoryProtocol;
+ if ((ErrorCode = AOA_Host_GetAccessoryProtocol(&AccessoryProtocol)) != HOST_WAITERROR_Successful)
+ return ErrorCode;
+
+ if ((AccessoryProtocol != CPU_TO_LE16(AOA_PROTOCOL_AccessoryV1)) && (AccessoryProtocol != CPU_TO_LE16(AOA_PROTOCOL_AccessoryV2)))
+ return AOA_ERROR_LOGICAL_CMD_FAILED;
+
+ for (uint8_t PropertyIndex = 0; PropertyIndex < AOA_STRING_TOTAL_STRINGS; PropertyIndex++)
+ {
+ if ((ErrorCode = AOA_Host_SendPropertyString(AOAInterfaceInfo, PropertyIndex)) != HOST_WAITERROR_Successful)
+ return ErrorCode;
+ }
+
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR | REQREC_DEVICE),
+ .bRequest = AOA_REQ_StartAccessoryMode,
+ .wValue = 0,
+ .wIndex = 0,
+ .wLength = 0,
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+ return USB_Host_SendControlRequest(NULL);
+}
+
+static uint8_t AOA_Host_GetAccessoryProtocol(uint16_t* const Protocol)
+{
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_VENDOR | REQREC_DEVICE),
+ .bRequest = AOA_REQ_GetAccessoryProtocol,
+ .wValue = 0,
+ .wIndex = 0,
+ .wLength = sizeof(uint16_t),
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+ return USB_Host_SendControlRequest(Protocol);
+}
+
+static uint8_t AOA_Host_SendPropertyString(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
+ const uint8_t StringIndex)
+{
+ const char* String = AOAInterfaceInfo->Config.PropertyStrings[StringIndex];
+
+ if (String == NULL)
+ String = "";
+
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_VENDOR | REQREC_DEVICE),
+ .bRequest = AOA_REQ_SendString,
+ .wValue = 0,
+ .wIndex = StringIndex,
+ .wLength = (strlen(String) + 1),
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+ return USB_Host_SendControlRequest((char*)String);
+}
+
+uint8_t AOA_Host_SendData(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
+ const void* const Buffer,
+ const uint16_t Length)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(AOAInterfaceInfo->State.IsActive))
+ return PIPE_READYWAIT_DeviceDisconnected;
+
+ uint8_t ErrorCode;
+
+ Pipe_SelectPipe(AOAInterfaceInfo->Config.DataOUTPipe.Address);
+
+ Pipe_Unfreeze();
+ ErrorCode = Pipe_Write_Stream_LE(Buffer, Length, NULL);
+ Pipe_Freeze();
+
+ return ErrorCode;
+}
+
+uint8_t AOA_Host_SendString(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
+ const char* const String)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(AOAInterfaceInfo->State.IsActive))
+ return PIPE_READYWAIT_DeviceDisconnected;
+
+ uint8_t ErrorCode;
+
+ Pipe_SelectPipe(AOAInterfaceInfo->Config.DataOUTPipe.Address);
+
+ Pipe_Unfreeze();
+ ErrorCode = Pipe_Write_Stream_LE(String, strlen(String), NULL);
+ Pipe_Freeze();
+
+ return ErrorCode;
+}
+
+uint8_t AOA_Host_SendByte(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
+ const uint8_t Data)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(AOAInterfaceInfo->State.IsActive))
+ return PIPE_READYWAIT_DeviceDisconnected;
+
+ uint8_t ErrorCode;
+
+ Pipe_SelectPipe(AOAInterfaceInfo->Config.DataOUTPipe.Address);
+ Pipe_Unfreeze();
+
+ if (!(Pipe_IsReadWriteAllowed()))
+ {
+ Pipe_ClearOUT();
+
+ if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
+ return ErrorCode;
+ }
+
+ Pipe_Write_8(Data);
+ Pipe_Freeze();
+
+ return PIPE_READYWAIT_NoError;
+}
+
+uint16_t AOA_Host_BytesReceived(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(AOAInterfaceInfo->State.IsActive))
+ return 0;
+
+ Pipe_SelectPipe(AOAInterfaceInfo->Config.DataINPipe.Address);
+ Pipe_Unfreeze();
+
+ if (Pipe_IsINReceived())
+ {
+ if (!(Pipe_BytesInPipe()))
+ {
+ Pipe_ClearIN();
+ Pipe_Freeze();
+ return 0;
+ }
+ else
+ {
+ Pipe_Freeze();
+ return Pipe_BytesInPipe();
+ }
+ }
+ else
+ {
+ Pipe_Freeze();
+
+ return 0;
+ }
+}
+
+int16_t AOA_Host_ReceiveByte(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(AOAInterfaceInfo->State.IsActive))
+ return -1;
+
+ int16_t ReceivedByte = -1;
+
+ Pipe_SelectPipe(AOAInterfaceInfo->Config.DataINPipe.Address);
+ Pipe_Unfreeze();
+
+ if (Pipe_IsINReceived())
+ {
+ if (Pipe_BytesInPipe())
+ ReceivedByte = Pipe_Read_8();
+
+ if (!(Pipe_BytesInPipe()))
+ Pipe_ClearIN();
+ }
+
+ Pipe_Freeze();
+
+ return ReceivedByte;
+}
+
+uint8_t AOA_Host_Flush(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(AOAInterfaceInfo->State.IsActive))
+ return PIPE_READYWAIT_DeviceDisconnected;
+
+ uint8_t ErrorCode;
+
+ Pipe_SelectPipe(AOAInterfaceInfo->Config.DataOUTPipe.Address);
+ Pipe_Unfreeze();
+
+ if (!(Pipe_BytesInPipe()))
+ return PIPE_READYWAIT_NoError;
+
+ bool BankFull = !(Pipe_IsReadWriteAllowed());
+
+ Pipe_ClearOUT();
+
+ if (BankFull)
+ {
+ if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
+ return ErrorCode;
+
+ Pipe_ClearOUT();
+ }
+
+ Pipe_Freeze();
+
+ return PIPE_READYWAIT_NoError;
+}
+
+#if defined(FDEV_SETUP_STREAM)
+void AOA_Host_CreateStream(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
+ FILE* const Stream)
+{
+ *Stream = (FILE)FDEV_SETUP_STREAM(AOA_Host_putchar, AOA_Host_getchar, _FDEV_SETUP_RW);
+ fdev_set_udata(Stream, AOAInterfaceInfo);
+}
+
+void AOA_Host_CreateBlockingStream(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
+ FILE* const Stream)
+{
+ *Stream = (FILE)FDEV_SETUP_STREAM(AOA_Host_putchar, AOA_Host_getchar_Blocking, _FDEV_SETUP_RW);
+ fdev_set_udata(Stream, AOAInterfaceInfo);
+}
+
+static int AOA_Host_putchar(char c,
+ FILE* Stream)
+{
+ return AOA_Host_SendByte((USB_ClassInfo_AOA_Host_t*)fdev_get_udata(Stream), c) ? _FDEV_ERR : 0;
+}
+
+static int AOA_Host_getchar(FILE* Stream)
+{
+ int16_t ReceivedByte = AOA_Host_ReceiveByte((USB_ClassInfo_AOA_Host_t*)fdev_get_udata(Stream));
+
+ if (ReceivedByte < 0)
+ return _FDEV_EOF;
+
+ return ReceivedByte;
+}
+
+static int AOA_Host_getchar_Blocking(FILE* Stream)
+{
+ int16_t ReceivedByte;
+
+ while ((ReceivedByte = AOA_Host_ReceiveByte((USB_ClassInfo_AOA_Host_t*)fdev_get_udata(Stream))) < 0)
+ {
+ if (USB_HostState == HOST_STATE_Unattached)
+ return _FDEV_EOF;
+
+ AOA_Host_USBTask((USB_ClassInfo_AOA_Host_t*)fdev_get_udata(Stream));
+ USB_USBTask();
+ }
+
+ return ReceivedByte;
+}
+#endif
+
+#endif
+
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/AndroidAccessoryClassHost.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/AndroidAccessoryClassHost.h
new file mode 100644
index 000000000..0476f2e02
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/AndroidAccessoryClassHost.h
@@ -0,0 +1,314 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Host mode driver for the library USB Android Open Accessory Class driver.
+ *
+ * Host mode driver for the library USB Android Open Accessory Class driver.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB module driver
+ * dispatch header located in LUFA/Drivers/USB.h.
+ */
+
+/** \ingroup Group_USBClassAOA
+ * \defgroup Group_USBClassAndroidAccessoryHost Android Open Accessory Class Host Mode Driver
+ *
+ * \section Sec_USBClassAndroidAccessoryHost_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Drivers/USB/Class/Host/AndroidAccessoryClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ *
+ * \section Sec_USBClassAndroidAccessoryHost_ModDescription Module Description
+ * Host Mode USB Class driver framework interface, for the Android Open Accessory USB Class driver.
+ *
+ * @{
+ */
+
+#ifndef __AOA_CLASS_HOST_H__
+#define __AOA_CLASS_HOST_H__
+
+ /* Includes: */
+ #include "../../USB.h"
+ #include "../Common/AndroidAccessoryClassCommon.h"
+
+ #include <stdio.h>
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_AOA_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Error code for some Android Open Accessory Host functions, indicating a logical (and not hardware) error. */
+ #define AOA_ERROR_LOGICAL_CMD_FAILED 0x80
+
+ /* Type Defines: */
+ /** \brief Android Open Accessory Class Host Mode Configuration and State Structure.
+ *
+ * Class state structure. An instance of this structure should be made within the user application,
+ * and passed to each of the Android Open Accessory class driver functions as the \c AOAInterfaceInfo
+ * parameter. This stores each Android Open Accessory interface's configuration and state information.
+ */
+ typedef struct
+ {
+ struct
+ {
+ USB_Pipe_Table_t DataINPipe; /**< Data IN Pipe configuration table. */
+ USB_Pipe_Table_t DataOUTPipe; /**< Data OUT Pipe configuration table. */
+
+ char* PropertyStrings[AOA_STRING_TOTAL_STRINGS]; /**< Android Accessory property strings, sent to identify the accessory when the
+ * Android device is switched into Open Accessory mode. */
+ } Config; /**< Config data for the USB class interface within the device. All elements in this section
+ * <b>must</b> be set or the interface will fail to enumerate and operate correctly.
+ */
+ struct
+ {
+ bool IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
+ * after \ref AOA_Host_ConfigurePipes() is called and the Host state machine is in the
+ * Configured state.
+ */
+ uint8_t InterfaceNumber; /**< Interface index of the AOA interface within the attached device. */
+ } State; /**< State data for the USB class interface within the device. All elements in this section
+ * <b>may</b> be set to initial values, but may also be ignored to default to sane values when
+ * the interface is enumerated.
+ */
+ } USB_ClassInfo_AOA_Host_t;
+
+ /* Enums: */
+ /** Enum for the possible error codes returned by the \ref AOA_Host_ConfigurePipes() function. */
+ enum AOA_Host_EnumerationFailure_ErrorCodes_t
+ {
+ AOA_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */
+ AOA_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */
+ AOA_ENUMERROR_NoCompatibleInterfaceFound = 2, /**< A compatible Android Open Accessory interface was not found in the device's Configuration Descriptor. */
+ AOA_ENUMERROR_PipeConfigurationFailed = 3, /**< One or more pipes for the specified interface could not be configured correctly. */
+ };
+
+ /* Function Prototypes: */
+ /** General management task for a given Android Open Accessory host class interface, required for the correct operation of the interface.
+ * This should be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
+ *
+ * \param[in,out] AOAInterfaceInfo Pointer to a structure containing an Android Open Accessory Class host configuration and state.
+ */
+ void AOA_Host_USBTask(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Validates a device descriptor, to check if the device is a valid Android device, and if it is currently in Android Open Accessory mode.
+ *
+ * \param[in,out] AOAInterfaceInfo Pointer to a structure containing an AOA Class host configuration and state.
+ * \param[in] DeviceDescriptor Pointer a buffer containing the attached device's Device Descriptor.
+ * \param[out] NeedModeSwitch Pointer to a boolean where the mode switch requirement of the attached device is to be stored.
+ *
+ * \return Boolean \c true if the attached device is a valid Android device, \c false otherwise.
+ */
+ bool AOA_Host_ValidateAccessoryDevice(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
+ const USB_Descriptor_Device_t* const DeviceDescriptor,
+ bool* const NeedModeSwitch) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2) ATTR_NON_NULL_PTR_ARG(3);
+
+ /** Host interface configuration routine, to configure a given Android Open Accessory host interface instance using the Configuration
+ * Descriptor read from an attached USB device. This function automatically updates the given Android Open Accessory Host instance's
+ * state values and configures the pipes required to communicate with the interface if it is found within the device. This should be
+ * called once after the stack has enumerated the attached device, while the host state machine is in the Addressed state.
+ *
+ * \param[in,out] AOAInterfaceInfo Pointer to a structure containing an AOA Class host configuration and state.
+ * \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor.
+ * \param[in] ConfigDescriptorData Pointer to a buffer containing the attached device's Configuration Descriptor.
+ *
+ * \return A value from the \ref AOA_Host_EnumerationFailure_ErrorCodes_t enum.
+ */
+ uint8_t AOA_Host_ConfigurePipes(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
+ uint16_t ConfigDescriptorSize,
+ void* ConfigDescriptorData) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
+
+ /** Starts Accessory Mode in the attached Android device. This function will validate the device's Android Open Accessory protocol
+ * version, send the configured property strings, and request a switch to Android Open Accessory mode.
+ *
+ * \param[in,out] AOAInterfaceInfo Pointer to a structure containing an AOA Class host configuration and state.
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum, or \ref AOA_ERROR_LOGICAL_CMD_FAILED if a logical error occurred..
+ */
+ uint8_t AOA_Host_StartAccessoryMode(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Sends a given data buffer to the attached USB device, if connected. If a device is not connected when the function is
+ * called, the data will be discarded. Bytes will be queued for transmission to the device until either the pipe bank
+ * becomes full, or the \ref AOA_Host_Flush() function is called to flush the pending data to the device. This allows for
+ * multiple bytes to be packed into a single pipe packet, increasing data throughput.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] AOAInterfaceInfo Pointer to a structure containing a AOA Class host configuration and state.
+ * \param[in] Buffer Pointer to a buffer containing the data to send to the device.
+ * \param[in] Length Length of the data to send to the device.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t AOA_Host_SendData(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
+ const void* const Buffer,
+ const uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Sends a given null-terminated string to the attached USB device, if connected. If a device is not connected when the
+ * function is called, the string is discarded. Bytes will be queued for transmission to the device until either the pipe
+ * bank becomes full, or the \ref AOA_Host_Flush() function is called to flush the pending data to the device. This allows
+ * for multiple bytes to be packed into a single pipe packet, increasing data throughput.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] AOAInterfaceInfo Pointer to a structure containing a AOA Class host configuration and state.
+ * \param[in] String Pointer to the null terminated string to send to the device.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t AOA_Host_SendString(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
+ const char* const String) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+
+ /** Sends a given byte to the attached USB device, if connected. If a device is not connected when the function is called, the
+ * byte is discarded. Bytes will be queued for transmission to the device until either the pipe bank becomes full, or the
+ * \ref AOA_Host_Flush() function is called to flush the pending data to the host. This allows for multiple bytes to be
+ * packed into a single pipe packet, increasing data throughput.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] AOAInterfaceInfo Pointer to a structure containing a AOA Class host configuration and state.
+ * \param[in] Data Byte of data to send to the device.
+ *
+ * \return A value from the \ref Pipe_WaitUntilReady_ErrorCodes_t enum.
+ */
+ uint8_t AOA_Host_SendByte(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
+ const uint8_t Data) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Determines the number of bytes received by the AOA interface from the device, waiting to be read. This indicates the number
+ * of bytes in the IN pipe bank only, and thus the number of calls to \ref AOA_Host_ReceiveByte() which are guaranteed to succeed
+ * immediately. If multiple bytes are to be received, they should be buffered by the user application, as the pipe bank will not be
+ * released back to the USB controller until all bytes are read.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] AOAInterfaceInfo Pointer to a structure containing a AOA Class host configuration and state.
+ *
+ * \return Total number of buffered bytes received from the device.
+ */
+ uint16_t AOA_Host_BytesReceived(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Reads a byte of data from the device. If no data is waiting to be read of if a USB device is not connected, the function
+ * returns a negative value. The \ref AOA_Host_BytesReceived() function may be queried in advance to determine how many bytes
+ * are currently buffered in the AOA interface's data receive pipe.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] AOAInterfaceInfo Pointer to a structure containing a AOA Class host configuration and state.
+ *
+ * \return Next received byte from the device, or a negative value if no data received.
+ */
+ int16_t AOA_Host_ReceiveByte(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Flushes any data waiting to be sent, ensuring that the send buffer is cleared.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] AOAInterfaceInfo Pointer to a structure containing a AOA Class host configuration and state.
+ *
+ * \return A value from the \ref Pipe_WaitUntilReady_ErrorCodes_t enum.
+ */
+ uint8_t AOA_Host_Flush(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Creates a standard character stream for the given AOA Device instance so that it can be used with all the regular
+ * functions in the standard \c <stdio.h> library that accept a \c FILE stream as a destination (e.g. \c fprintf). The created
+ * stream is bidirectional and can be used for both input and output functions.
+ *
+ * Reading data from this stream is non-blocking, i.e. in most instances, complete strings cannot be read in by a single
+ * fetch, as the endpoint will not be ready at some point in the transmission, aborting the transfer. However, this may
+ * be used when the read data is processed byte-per-bye (via \c getc()) or when the user application will implement its own
+ * line buffering.
+ *
+ * \note The created stream can be given as \c stdout if desired to direct the standard output from all \c <stdio.h> functions
+ * to the given AOA interface.
+ * \n\n
+ *
+ * \note This function is not available on all microcontroller architectures.
+ *
+ * \param[in,out] AOAInterfaceInfo Pointer to a structure containing a AOA Class configuration and state.
+ * \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed.
+ */
+ void AOA_Host_CreateStream(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
+ FILE* const Stream) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+
+ /** Identical to \ref AOA_Host_CreateStream(), except that reads are blocking until the calling stream function terminates
+ * the transfer. While blocking, the USB and AOA service tasks are called repeatedly to maintain USB communications.
+ *
+ * \note This function is not available on all microcontroller architectures.
+ *
+ * \param[in,out] AOAInterfaceInfo Pointer to a structure containing a AOA Class configuration and state.
+ * \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed.
+ */
+ void AOA_Host_CreateBlockingStream(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
+ FILE* const Stream) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Function Prototypes: */
+ #if defined(__INCLUDE_FROM_ANDROIDACCESSORY_HOST_C)
+ #if defined(FDEV_SETUP_STREAM)
+ static int AOA_Host_putchar(char c,
+ FILE* Stream) ATTR_NON_NULL_PTR_ARG(2);
+ static int AOA_Host_getchar(FILE* Stream) ATTR_NON_NULL_PTR_ARG(1);
+ static int AOA_Host_getchar_Blocking(FILE* Stream) ATTR_NON_NULL_PTR_ARG(1);
+ #endif
+
+ static uint8_t AOA_Host_GetAccessoryProtocol(uint16_t* const Protocol) ATTR_NON_NULL_PTR_ARG(1);
+ static uint8_t AOA_Host_SendPropertyString(USB_ClassInfo_AOA_Host_t* const AOAInterfaceInfo,
+ const uint8_t StringIndex) ATTR_NON_NULL_PTR_ARG(1);
+
+ static uint8_t DCOMP_AOA_Host_NextAndroidAccessoryInterface(void* const CurrentDescriptor)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ static uint8_t DCOMP_AOA_Host_NextInterfaceBulkEndpoint(void* const CurrentDescriptor)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ #endif
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/AudioClassHost.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/AudioClassHost.c
new file mode 100644
index 000000000..3b5bceb6a
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/AudioClassHost.c
@@ -0,0 +1,223 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../../Core/USBMode.h"
+
+#if defined(USB_CAN_BE_HOST)
+
+#define __INCLUDE_FROM_AUDIO_DRIVER
+#define __INCLUDE_FROM_AUDIO_HOST_C
+#include "AudioClassHost.h"
+
+uint8_t Audio_Host_ConfigurePipes(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo,
+ uint16_t ConfigDescriptorSize,
+ void* ConfigDescriptorData)
+{
+ USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
+ USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
+ USB_Descriptor_Interface_t* AudioControlInterface = NULL;
+ USB_Descriptor_Interface_t* AudioStreamingInterface = NULL;
+
+ memset(&AudioInterfaceInfo->State, 0x00, sizeof(AudioInterfaceInfo->State));
+
+ if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
+ return AUDIO_ENUMERROR_InvalidConfigDescriptor;
+
+ while ((AudioInterfaceInfo->Config.DataINPipe.Address && !(DataINEndpoint)) ||
+ (AudioInterfaceInfo->Config.DataOUTPipe.Address && !(DataOUTEndpoint)))
+ {
+ if (!(AudioControlInterface) ||
+ USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+ DCOMP_Audio_Host_NextAudioInterfaceDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
+ {
+ if (!(AudioControlInterface) ||
+ USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+ DCOMP_Audio_Host_NextAudioStreamInterface) != DESCRIPTOR_SEARCH_COMP_Found)
+ {
+ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+ DCOMP_Audio_Host_NextAudioControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
+ {
+ return AUDIO_ENUMERROR_NoCompatibleInterfaceFound;
+ }
+
+ AudioControlInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
+
+ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+ DCOMP_Audio_Host_NextAudioStreamInterface) != DESCRIPTOR_SEARCH_COMP_Found)
+ {
+ return AUDIO_ENUMERROR_NoCompatibleInterfaceFound;
+ }
+ }
+
+ AudioStreamingInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
+
+ DataINEndpoint = NULL;
+ DataOUTEndpoint = NULL;
+
+ continue;
+ }
+
+ USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
+
+ if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN)
+ DataINEndpoint = EndpointData;
+ else
+ DataOUTEndpoint = EndpointData;
+ }
+
+ AudioInterfaceInfo->Config.DataINPipe.Size = le16_to_cpu(DataINEndpoint->EndpointSize);
+ AudioInterfaceInfo->Config.DataINPipe.EndpointAddress = DataINEndpoint->EndpointAddress;
+ AudioInterfaceInfo->Config.DataINPipe.Type = EP_TYPE_ISOCHRONOUS;
+ AudioInterfaceInfo->Config.DataINPipe.Banks = 2;
+
+ AudioInterfaceInfo->Config.DataOUTPipe.Size = le16_to_cpu(DataOUTEndpoint->EndpointSize);
+ AudioInterfaceInfo->Config.DataOUTPipe.EndpointAddress = DataOUTEndpoint->EndpointAddress;
+ AudioInterfaceInfo->Config.DataOUTPipe.Type = EP_TYPE_ISOCHRONOUS;
+ AudioInterfaceInfo->Config.DataOUTPipe.Banks = 2;
+
+ if (!(Pipe_ConfigurePipeTable(&AudioInterfaceInfo->Config.DataINPipe, 1)))
+ return AUDIO_ENUMERROR_PipeConfigurationFailed;
+
+ if (!(Pipe_ConfigurePipeTable(&AudioInterfaceInfo->Config.DataOUTPipe, 1)))
+ return AUDIO_ENUMERROR_PipeConfigurationFailed;
+
+ AudioInterfaceInfo->State.ControlInterfaceNumber = AudioControlInterface->InterfaceNumber;
+ AudioInterfaceInfo->State.StreamingInterfaceNumber = AudioStreamingInterface->InterfaceNumber;
+ AudioInterfaceInfo->State.EnabledStreamingAltIndex = AudioStreamingInterface->AlternateSetting;
+ AudioInterfaceInfo->State.IsActive = true;
+
+ return AUDIO_ENUMERROR_NoError;
+}
+
+static uint8_t DCOMP_Audio_Host_NextAudioControlInterface(void* CurrentDescriptor)
+{
+ USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
+
+ if (Header->Type == DTYPE_Interface)
+ {
+ USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
+
+ if ((Interface->Class == AUDIO_CSCP_AudioClass) &&
+ (Interface->SubClass == AUDIO_CSCP_ControlSubclass) &&
+ (Interface->Protocol == AUDIO_CSCP_ControlProtocol))
+ {
+ return DESCRIPTOR_SEARCH_Found;
+ }
+ }
+
+ return DESCRIPTOR_SEARCH_NotFound;
+}
+
+static uint8_t DCOMP_Audio_Host_NextAudioStreamInterface(void* CurrentDescriptor)
+{
+ USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
+
+ if (Header->Type == DTYPE_Interface)
+ {
+ USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
+
+ if ((Interface->Class == AUDIO_CSCP_AudioClass) &&
+ (Interface->SubClass == AUDIO_CSCP_AudioStreamingSubclass) &&
+ (Interface->Protocol == AUDIO_CSCP_StreamingProtocol))
+ {
+ return DESCRIPTOR_SEARCH_Found;
+ }
+ }
+
+ return DESCRIPTOR_SEARCH_NotFound;
+}
+
+static uint8_t DCOMP_Audio_Host_NextAudioInterfaceDataEndpoint(void* CurrentDescriptor)
+{
+ USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
+
+ if (Header->Type == DTYPE_Endpoint)
+ {
+ USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
+
+ if ((Endpoint->Attributes & EP_TYPE_MASK) == EP_TYPE_ISOCHRONOUS)
+ return DESCRIPTOR_SEARCH_Found;
+ }
+ else if (Header->Type == DTYPE_Interface)
+ {
+ return DESCRIPTOR_SEARCH_Fail;
+ }
+
+ return DESCRIPTOR_SEARCH_NotFound;
+}
+
+uint8_t Audio_Host_StartStopStreaming(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo,
+ const bool EnableStreaming)
+{
+ if (!(AudioInterfaceInfo->State.IsActive))
+ return HOST_SENDCONTROL_DeviceDisconnected;
+
+ return USB_Host_SetInterfaceAltSetting(AudioInterfaceInfo->State.StreamingInterfaceNumber,
+ EnableStreaming ? AudioInterfaceInfo->State.EnabledStreamingAltIndex : 0);
+}
+
+uint8_t Audio_Host_GetSetEndpointProperty(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo,
+ const uint8_t DataPipeIndex,
+ const uint8_t EndpointProperty,
+ const uint8_t EndpointControl,
+ const uint16_t DataLength,
+ void* const Data)
+{
+ if (!(AudioInterfaceInfo->State.IsActive))
+ return HOST_SENDCONTROL_DeviceDisconnected;
+
+ uint8_t RequestType;
+ uint8_t EndpointAddress;
+
+ if (EndpointProperty & 0x80)
+ RequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_ENDPOINT);
+ else
+ RequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_ENDPOINT);
+
+ Pipe_SelectPipe(DataPipeIndex);
+ EndpointAddress = Pipe_GetBoundEndpointAddress();
+
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = RequestType,
+ .bRequest = EndpointProperty,
+ .wValue = ((uint16_t)EndpointControl << 8),
+ .wIndex = EndpointAddress,
+ .wLength = DataLength,
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+
+ return USB_Host_SendControlRequest(Data);
+}
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/AudioClassHost.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/AudioClassHost.h
new file mode 100644
index 000000000..b00bb5fcd
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/AudioClassHost.h
@@ -0,0 +1,411 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Host mode driver for the library USB Audio 1.0 Class driver.
+ *
+ * Host mode driver for the library USB Audio 1.0 Class driver.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB module driver
+ * dispatch header located in LUFA/Drivers/USB.h.
+ */
+
+/** \ingroup Group_USBClassAudio
+ * \defgroup Group_USBClassAudioHost Audio 1.0 Class Host Mode Driver
+ *
+ * \section Sec_USBClassAudioHost_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Drivers/USB/Class/Host/AudioClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ *
+ * \section Sec_USBClassAudioHost_ModDescription Module Description
+ * Host Mode USB Class driver framework interface, for the Audio 1.0 USB Class driver.
+ *
+ * @{
+ */
+
+#ifndef __AUDIO_CLASS_HOST_H__
+#define __AUDIO_CLASS_HOST_H__
+
+ /* Includes: */
+ #include "../../USB.h"
+ #include "../Common/AudioClassCommon.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_AUDIO_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Type Defines: */
+ /** \brief Audio Class Host Mode Configuration and State Structure.
+ *
+ * Class state structure. An instance of this structure should be made within the user application,
+ * and passed to each of the Audio class driver functions as the \c AudioInterfaceInfo parameter. This
+ * stores each Audio interface's configuration and state information.
+ */
+ typedef struct
+ {
+ struct
+ {
+ USB_Pipe_Table_t DataINPipe; /**< Data IN Pipe configuration table. */
+ USB_Pipe_Table_t DataOUTPipe; /**< Data OUT Pipe configuration table. */
+ } Config; /**< Config data for the USB class interface within the device. All elements in this section
+ * <b>must</b> be set or the interface will fail to enumerate and operate correctly.
+ */
+ struct
+ {
+ bool IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
+ * after \ref Audio_Host_ConfigurePipes() is called and the Host state machine is in the
+ * Configured state.
+ */
+ uint8_t ControlInterfaceNumber; /**< Interface index of the Audio Control interface within the attached device. */
+ uint8_t StreamingInterfaceNumber; /**< Interface index of the Audio Streaming interface within the attached device. */
+
+ uint8_t EnabledStreamingAltIndex; /**< Alternative setting index of the Audio Streaming interface when the stream is enabled. */
+ } State; /**< State data for the USB class interface within the device. All elements in this section
+ * <b>may</b> be set to initial values, but may also be ignored to default to sane values when
+ * the interface is enumerated.
+ */
+ } USB_ClassInfo_Audio_Host_t;
+
+ /* Enums: */
+ /** Enum for the possible error codes returned by the \ref Audio_Host_ConfigurePipes() function. */
+ enum AUDIO_Host_EnumerationFailure_ErrorCodes_t
+ {
+ AUDIO_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */
+ AUDIO_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */
+ AUDIO_ENUMERROR_NoCompatibleInterfaceFound = 2, /**< A compatible AUDIO interface was not found in the device's Configuration Descriptor. */
+ AUDIO_ENUMERROR_PipeConfigurationFailed = 3, /**< One or more pipes for the specified interface could not be configured correctly. */
+ };
+
+ /* Function Prototypes: */
+ /** Host interface configuration routine, to configure a given Audio host interface instance using the Configuration
+ * Descriptor read from an attached USB device. This function automatically updates the given Audio Host instance's
+ * state values and configures the pipes required to communicate with the interface if it is found within the
+ * device. This should be called once after the stack has enumerated the attached device, while the host state
+ * machine is in the Addressed state.
+ *
+ * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class host configuration and state.
+ * \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor.
+ * \param[in] ConfigDescriptorData Pointer to a buffer containing the attached device's Configuration Descriptor.
+ *
+ * \return A value from the \ref AUDIO_Host_EnumerationFailure_ErrorCodes_t enum.
+ */
+ uint8_t Audio_Host_ConfigurePipes(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo,
+ uint16_t ConfigDescriptorSize,
+ void* ConfigDescriptorData) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
+
+ /** Starts or stops the audio streaming for the given configured Audio Host interface, allowing for audio samples to be
+ * send and/or received.
+ *
+ * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class host configuration and state.
+ * \param[in] EnableStreaming Boolean true to enable streaming of the specified interface, \c false to disable
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum.
+ */
+ uint8_t Audio_Host_StartStopStreaming(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo,
+ const bool EnableStreaming) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Gets or sets the specified property of a streaming audio class endpoint that is bound to a pipe in the given
+ * class instance.
+ *
+ * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class host configuration and state.
+ * \param[in] DataPipeIndex Index of the data pipe whose bound endpoint is to be altered.
+ * \param[in] EndpointProperty Property of the endpoint to get or set, a value from \ref Audio_ClassRequests_t.
+ * \param[in] EndpointControl Parameter of the endpoint to get or set, a value from \ref Audio_EndpointControls_t.
+ * \param[in,out] DataLength For SET operations, the length of the parameter data to set. For GET operations, the maximum
+ * length of the retrieved data.
+ * \param[in,out] Data Pointer to a location where the parameter data is stored for SET operations, or where
+ * the retrieved data is to be stored for GET operations.
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum.
+ */
+ uint8_t Audio_Host_GetSetEndpointProperty(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo,
+ const uint8_t DataPipeIndex,
+ const uint8_t EndpointProperty,
+ const uint8_t EndpointControl,
+ const uint16_t DataLength,
+ void* const Data) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(6);
+
+ /* Inline Functions: */
+ /** General management task for a given Audio host class interface, required for the correct operation of
+ * the interface. This should be called frequently in the main program loop, before the master USB management task
+ * \ref USB_USBTask().
+ *
+ * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class host configuration and state.
+ */
+ static inline void Audio_Host_USBTask(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo)
+ ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
+ static inline void Audio_Host_USBTask(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo)
+ {
+ (void)AudioInterfaceInfo;
+ }
+
+ /** Determines if the given audio interface is ready for a sample to be read from it, and selects the streaming
+ * IN pipe ready for reading.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or
+ * the call will fail.
+ *
+ * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state.
+ *
+ * \return Boolean \c true if the given Audio interface has a sample to be read, \c false otherwise.
+ */
+ static inline bool Audio_Host_IsSampleReceived(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo)
+ ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
+ static inline bool Audio_Host_IsSampleReceived(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo)
+ {
+ if ((USB_HostState != HOST_STATE_Configured) || !(AudioInterfaceInfo->State.IsActive))
+ return false;
+
+ bool SampleReceived = false;
+
+ Pipe_SelectPipe(AudioInterfaceInfo->Config.DataINPipe.Address);
+ Pipe_Unfreeze();
+ SampleReceived = Pipe_IsINReceived();
+ Pipe_Freeze();
+
+ return SampleReceived;
+ }
+
+ /** Determines if the given audio interface is ready to accept the next sample to be written to it, and selects
+ * the streaming OUT pipe ready for writing.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or
+ * the call will fail.
+ *
+ * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state.
+ *
+ * \return Boolean \c true if the given Audio interface is ready to accept the next sample, \c false otherwise.
+ */
+ static inline bool Audio_Host_IsReadyForNextSample(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo)
+ ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
+ static inline bool Audio_Host_IsReadyForNextSample(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo)
+ {
+ if ((USB_HostState != HOST_STATE_Configured) || !(AudioInterfaceInfo->State.IsActive))
+ return false;
+
+ Pipe_SelectPipe(AudioInterfaceInfo->Config.DataOUTPipe.Address);
+ return Pipe_IsOUTReady();
+ }
+
+ /** Reads the next 8-bit audio sample from the current audio interface.
+ *
+ * \pre This should be preceded immediately by a call to the \ref Audio_Host_IsSampleReceived() function to ensure
+ * that the correct pipe is selected and ready for data.
+ *
+ * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state.
+ *
+ * \return Signed 8-bit audio sample from the audio interface.
+ */
+ static inline int8_t Audio_Host_ReadSample8(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo)
+ ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
+ static inline int8_t Audio_Host_ReadSample8(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo)
+ {
+ int8_t Sample;
+
+ (void)AudioInterfaceInfo;
+
+ Sample = Pipe_Read_8();
+
+ if (!(Pipe_BytesInPipe()))
+ {
+ Pipe_Unfreeze();
+ Pipe_ClearIN();
+ Pipe_Freeze();
+ }
+
+ return Sample;
+ }
+
+ /** Reads the next 16-bit audio sample from the current audio interface.
+ *
+ * \pre This should be preceded immediately by a call to the \ref Audio_Host_IsSampleReceived() function to ensure
+ * that the correct pipe is selected and ready for data.
+ *
+ * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state.
+ *
+ * \return Signed 16-bit audio sample from the audio interface.
+ */
+ static inline int16_t Audio_Host_ReadSample16(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo)
+ ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
+ static inline int16_t Audio_Host_ReadSample16(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo)
+ {
+ int16_t Sample;
+
+ (void)AudioInterfaceInfo;
+
+ Sample = (int16_t)Pipe_Read_16_LE();
+
+ if (!(Pipe_BytesInPipe()))
+ {
+ Pipe_Unfreeze();
+ Pipe_ClearIN();
+ Pipe_Freeze();
+ }
+
+ return Sample;
+ }
+
+ /** Reads the next 24-bit audio sample from the current audio interface.
+ *
+ * \pre This should be preceded immediately by a call to the \ref Audio_Host_IsSampleReceived() function to ensure
+ * that the correct pipe is selected and ready for data.
+ *
+ * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state.
+ *
+ * \return Signed 24-bit audio sample from the audio interface.
+ */
+ static inline int32_t Audio_Host_ReadSample24(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo)
+ ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
+ static inline int32_t Audio_Host_ReadSample24(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo)
+ {
+ int32_t Sample;
+
+ (void)AudioInterfaceInfo;
+
+ Sample = (((uint32_t)Pipe_Read_8() << 16) | Pipe_Read_16_LE());
+
+ if (!(Pipe_BytesInPipe()))
+ {
+ Pipe_Unfreeze();
+ Pipe_ClearIN();
+ Pipe_Freeze();
+ }
+
+ return Sample;
+ }
+
+ /** Writes the next 8-bit audio sample to the current audio interface.
+ *
+ * \pre This should be preceded immediately by a call to the \ref Audio_Host_IsReadyForNextSample() function to
+ * ensure that the correct pipe is selected and ready for data.
+ *
+ * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state.
+ * \param[in] Sample Signed 8-bit audio sample.
+ */
+ static inline void Audio_Host_WriteSample8(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo,
+ const int8_t Sample) ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
+ static inline void Audio_Host_WriteSample8(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo,
+ const int8_t Sample)
+ {
+ (void)AudioInterfaceInfo;
+
+ Pipe_Write_8(Sample);
+
+ if (!(Pipe_IsReadWriteAllowed()))
+ {
+ Pipe_Unfreeze();
+ Pipe_ClearOUT();
+ Pipe_WaitUntilReady();
+ Pipe_Freeze();
+ }
+ }
+
+ /** Writes the next 16-bit audio sample to the current audio interface.
+ *
+ * \pre This should be preceded immediately by a call to the \ref Audio_Host_IsReadyForNextSample() function to
+ * ensure that the correct pipe is selected and ready for data.
+ *
+ * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state.
+ * \param[in] Sample Signed 16-bit audio sample.
+ */
+ static inline void Audio_Host_WriteSample16(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo,
+ const int16_t Sample) ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
+ static inline void Audio_Host_WriteSample16(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo,
+ const int16_t Sample)
+ {
+ (void)AudioInterfaceInfo;
+
+ Pipe_Write_16_LE(Sample);
+
+ if (!(Pipe_IsReadWriteAllowed()))
+ {
+ Pipe_Unfreeze();
+ Pipe_ClearOUT();
+ Pipe_WaitUntilReady();
+ Pipe_Freeze();
+ }
+ }
+
+ /** Writes the next 24-bit audio sample to the current audio interface.
+ *
+ * \pre This should be preceded immediately by a call to the \ref Audio_Host_IsReadyForNextSample() function to
+ * ensure that the correct pipe is selected and ready for data.
+ *
+ * \param[in,out] AudioInterfaceInfo Pointer to a structure containing an Audio Class configuration and state.
+ * \param[in] Sample Signed 24-bit audio sample.
+ */
+ static inline void Audio_Host_WriteSample24(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo,
+ const int32_t Sample) ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
+ static inline void Audio_Host_WriteSample24(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo,
+ const int32_t Sample)
+ {
+ (void)AudioInterfaceInfo;
+
+ Pipe_Write_16_LE(Sample);
+ Pipe_Write_8(Sample >> 16);
+
+ if (!(Pipe_IsReadWriteAllowed()))
+ {
+ Pipe_Unfreeze();
+ Pipe_ClearOUT();
+ Pipe_WaitUntilReady();
+ Pipe_Freeze();
+ }
+ }
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Function Prototypes: */
+ #if defined(__INCLUDE_FROM_AUDIO_HOST_C)
+ static uint8_t DCOMP_Audio_Host_NextAudioControlInterface(void* CurrentDescriptor)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ static uint8_t DCOMP_Audio_Host_NextAudioStreamInterface(void* CurrentDescriptor)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ static uint8_t DCOMP_Audio_Host_NextAudioInterfaceDataEndpoint(void* CurrentDescriptor)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ #endif
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/CDCClassHost.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/CDCClassHost.c
new file mode 100644
index 000000000..b32a237cc
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/CDCClassHost.c
@@ -0,0 +1,477 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../../Core/USBMode.h"
+
+#if defined(USB_CAN_BE_HOST)
+
+#define __INCLUDE_FROM_CDC_DRIVER
+#define __INCLUDE_FROM_CDC_HOST_C
+#include "CDCClassHost.h"
+
+uint8_t CDC_Host_ConfigurePipes(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
+ uint16_t ConfigDescriptorSize,
+ void* ConfigDescriptorData)
+{
+ USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
+ USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
+ USB_Descriptor_Endpoint_t* NotificationEndpoint = NULL;
+ USB_Descriptor_Interface_t* CDCControlInterface = NULL;
+
+ memset(&CDCInterfaceInfo->State, 0x00, sizeof(CDCInterfaceInfo->State));
+
+ if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
+ return CDC_ENUMERROR_InvalidConfigDescriptor;
+
+ while (!(DataINEndpoint) || !(DataOUTEndpoint) || !(NotificationEndpoint))
+ {
+ if (!(CDCControlInterface) ||
+ USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+ DCOMP_CDC_Host_NextCDCInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
+ {
+ if (NotificationEndpoint)
+ {
+ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+ DCOMP_CDC_Host_NextCDCDataInterface) != DESCRIPTOR_SEARCH_COMP_Found)
+ {
+ return CDC_ENUMERROR_NoCompatibleInterfaceFound;
+ }
+
+ DataINEndpoint = NULL;
+ DataOUTEndpoint = NULL;
+ }
+ else
+ {
+ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+ DCOMP_CDC_Host_NextCDCControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
+ {
+ return CDC_ENUMERROR_NoCompatibleInterfaceFound;
+ }
+
+ CDCControlInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
+
+ NotificationEndpoint = NULL;
+ }
+
+ continue;
+ }
+
+ USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
+
+ if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN)
+ {
+ if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT)
+ NotificationEndpoint = EndpointData;
+ else
+ DataINEndpoint = EndpointData;
+ }
+ else
+ {
+ DataOUTEndpoint = EndpointData;
+ }
+ }
+
+ CDCInterfaceInfo->Config.DataINPipe.Size = le16_to_cpu(DataINEndpoint->EndpointSize);
+ CDCInterfaceInfo->Config.DataINPipe.EndpointAddress = DataINEndpoint->EndpointAddress;
+ CDCInterfaceInfo->Config.DataINPipe.Type = EP_TYPE_BULK;
+
+ CDCInterfaceInfo->Config.DataOUTPipe.Size = le16_to_cpu(DataOUTEndpoint->EndpointSize);
+ CDCInterfaceInfo->Config.DataOUTPipe.EndpointAddress = DataOUTEndpoint->EndpointAddress;
+ CDCInterfaceInfo->Config.DataOUTPipe.Type = EP_TYPE_BULK;
+
+ CDCInterfaceInfo->Config.NotificationPipe.Size = le16_to_cpu(NotificationEndpoint->EndpointSize);
+ CDCInterfaceInfo->Config.NotificationPipe.EndpointAddress = NotificationEndpoint->EndpointAddress;
+ CDCInterfaceInfo->Config.NotificationPipe.Type = EP_TYPE_INTERRUPT;
+
+ if (!(Pipe_ConfigurePipeTable(&CDCInterfaceInfo->Config.DataINPipe, 1)))
+ return CDC_ENUMERROR_PipeConfigurationFailed;
+
+ if (!(Pipe_ConfigurePipeTable(&CDCInterfaceInfo->Config.DataOUTPipe, 1)))
+ return CDC_ENUMERROR_PipeConfigurationFailed;
+
+ if (!(Pipe_ConfigurePipeTable(&CDCInterfaceInfo->Config.NotificationPipe, 1)))
+ return CDC_ENUMERROR_PipeConfigurationFailed;
+
+ CDCInterfaceInfo->State.ControlInterfaceNumber = CDCControlInterface->InterfaceNumber;
+ CDCInterfaceInfo->State.ControlLineStates.HostToDevice = (CDC_CONTROL_LINE_OUT_RTS | CDC_CONTROL_LINE_OUT_DTR);
+ CDCInterfaceInfo->State.ControlLineStates.DeviceToHost = (CDC_CONTROL_LINE_IN_DCD | CDC_CONTROL_LINE_IN_DSR);
+ CDCInterfaceInfo->State.IsActive = true;
+
+ return CDC_ENUMERROR_NoError;
+}
+
+static uint8_t DCOMP_CDC_Host_NextCDCControlInterface(void* const CurrentDescriptor)
+{
+ USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
+
+ if (Header->Type == DTYPE_Interface)
+ {
+ USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
+
+ if ((Interface->Class == CDC_CSCP_CDCClass) &&
+ (Interface->SubClass == CDC_CSCP_ACMSubclass) &&
+ (Interface->Protocol == CDC_CSCP_ATCommandProtocol))
+ {
+ return DESCRIPTOR_SEARCH_Found;
+ }
+ }
+
+ return DESCRIPTOR_SEARCH_NotFound;
+}
+
+static uint8_t DCOMP_CDC_Host_NextCDCDataInterface(void* const CurrentDescriptor)
+{
+ USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
+
+ if (Header->Type == DTYPE_Interface)
+ {
+ USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
+
+ if ((Interface->Class == CDC_CSCP_CDCDataClass) &&
+ (Interface->SubClass == CDC_CSCP_NoDataSubclass) &&
+ (Interface->Protocol == CDC_CSCP_NoDataProtocol))
+ {
+ return DESCRIPTOR_SEARCH_Found;
+ }
+ }
+
+ return DESCRIPTOR_SEARCH_NotFound;
+}
+
+static uint8_t DCOMP_CDC_Host_NextCDCInterfaceEndpoint(void* const CurrentDescriptor)
+{
+ USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
+
+ if (Header->Type == DTYPE_Endpoint)
+ {
+ USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
+
+ uint8_t EndpointType = (Endpoint->Attributes & EP_TYPE_MASK);
+
+ if (((EndpointType == EP_TYPE_BULK) || (EndpointType == EP_TYPE_INTERRUPT)) &&
+ !(Pipe_IsEndpointBound(Endpoint->EndpointAddress)))
+ {
+ return DESCRIPTOR_SEARCH_Found;
+ }
+ }
+ else if (Header->Type == DTYPE_Interface)
+ {
+ return DESCRIPTOR_SEARCH_Fail;
+ }
+
+ return DESCRIPTOR_SEARCH_NotFound;
+}
+
+void CDC_Host_USBTask(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
+ return;
+
+ Pipe_SelectPipe(CDCInterfaceInfo->Config.NotificationPipe.Address);
+ Pipe_Unfreeze();
+
+ if (Pipe_IsINReceived())
+ {
+ USB_Request_Header_t Notification;
+ Pipe_Read_Stream_LE(&Notification, sizeof(USB_Request_Header_t), NULL);
+
+ if ((Notification.bRequest == CDC_NOTIF_SerialState) &&
+ (Notification.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)))
+ {
+ Pipe_Read_Stream_LE(&CDCInterfaceInfo->State.ControlLineStates.DeviceToHost,
+ sizeof(CDCInterfaceInfo->State.ControlLineStates.DeviceToHost),
+ NULL);
+
+ Pipe_ClearIN();
+
+ EVENT_CDC_Host_ControLineStateChanged(CDCInterfaceInfo);
+ }
+ else
+ {
+ Pipe_ClearIN();
+ }
+ }
+
+ Pipe_Freeze();
+
+ #if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
+ CDC_Host_Flush(CDCInterfaceInfo);
+ #endif
+}
+
+uint8_t CDC_Host_SetLineEncoding(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
+{
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
+ .bRequest = CDC_REQ_SetLineEncoding,
+ .wValue = 0,
+ .wIndex = CDCInterfaceInfo->State.ControlInterfaceNumber,
+ .wLength = sizeof(CDCInterfaceInfo->State.LineEncoding),
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+
+ return USB_Host_SendControlRequest(&CDCInterfaceInfo->State.LineEncoding);
+}
+
+uint8_t CDC_Host_SendControlLineStateChange(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
+{
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
+ .bRequest = CDC_REQ_SetControlLineState,
+ .wValue = CDCInterfaceInfo->State.ControlLineStates.HostToDevice,
+ .wIndex = CDCInterfaceInfo->State.ControlInterfaceNumber,
+ .wLength = 0,
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+
+ return USB_Host_SendControlRequest(NULL);
+}
+
+uint8_t CDC_Host_SendBreak(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
+ const uint8_t Duration)
+{
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
+ .bRequest = CDC_REQ_SendBreak,
+ .wValue = Duration,
+ .wIndex = CDCInterfaceInfo->State.ControlInterfaceNumber,
+ .wLength = 0,
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+
+ return USB_Host_SendControlRequest(NULL);
+}
+
+uint8_t CDC_Host_SendData(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
+ const void* const Buffer,
+ const uint16_t Length)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
+ return PIPE_READYWAIT_DeviceDisconnected;
+
+ uint8_t ErrorCode;
+
+ Pipe_SelectPipe(CDCInterfaceInfo->Config.DataOUTPipe.Address);
+
+ Pipe_Unfreeze();
+ ErrorCode = Pipe_Write_Stream_LE(Buffer, Length, NULL);
+ Pipe_Freeze();
+
+ return ErrorCode;
+}
+
+uint8_t CDC_Host_SendString(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
+ const char* const String)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
+ return PIPE_READYWAIT_DeviceDisconnected;
+
+ uint8_t ErrorCode;
+
+ Pipe_SelectPipe(CDCInterfaceInfo->Config.DataOUTPipe.Address);
+
+ Pipe_Unfreeze();
+ ErrorCode = Pipe_Write_Stream_LE(String, strlen(String), NULL);
+ Pipe_Freeze();
+
+ return ErrorCode;
+}
+
+uint8_t CDC_Host_SendByte(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
+ const uint8_t Data)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
+ return PIPE_READYWAIT_DeviceDisconnected;
+
+ uint8_t ErrorCode;
+
+ Pipe_SelectPipe(CDCInterfaceInfo->Config.DataOUTPipe.Address);
+ Pipe_Unfreeze();
+
+ if (!(Pipe_IsReadWriteAllowed()))
+ {
+ Pipe_ClearOUT();
+
+ if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
+ return ErrorCode;
+ }
+
+ Pipe_Write_8(Data);
+ Pipe_Freeze();
+
+ return PIPE_READYWAIT_NoError;
+}
+
+uint16_t CDC_Host_BytesReceived(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
+ return 0;
+
+ Pipe_SelectPipe(CDCInterfaceInfo->Config.DataINPipe.Address);
+ Pipe_Unfreeze();
+
+ if (Pipe_IsINReceived())
+ {
+ if (!(Pipe_BytesInPipe()))
+ {
+ Pipe_ClearIN();
+ Pipe_Freeze();
+ return 0;
+ }
+ else
+ {
+ Pipe_Freeze();
+ return Pipe_BytesInPipe();
+ }
+ }
+ else
+ {
+ Pipe_Freeze();
+
+ return 0;
+ }
+}
+
+int16_t CDC_Host_ReceiveByte(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
+ return -1;
+
+ int16_t ReceivedByte = -1;
+
+ Pipe_SelectPipe(CDCInterfaceInfo->Config.DataINPipe.Address);
+ Pipe_Unfreeze();
+
+ if (Pipe_IsINReceived())
+ {
+ if (Pipe_BytesInPipe())
+ ReceivedByte = Pipe_Read_8();
+
+ if (!(Pipe_BytesInPipe()))
+ Pipe_ClearIN();
+ }
+
+ Pipe_Freeze();
+
+ return ReceivedByte;
+}
+
+uint8_t CDC_Host_Flush(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(CDCInterfaceInfo->State.IsActive))
+ return PIPE_READYWAIT_DeviceDisconnected;
+
+ uint8_t ErrorCode;
+
+ Pipe_SelectPipe(CDCInterfaceInfo->Config.DataOUTPipe.Address);
+ Pipe_Unfreeze();
+
+ if (!(Pipe_BytesInPipe()))
+ return PIPE_READYWAIT_NoError;
+
+ bool BankFull = !(Pipe_IsReadWriteAllowed());
+
+ Pipe_ClearOUT();
+
+ if (BankFull)
+ {
+ if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
+ return ErrorCode;
+
+ Pipe_ClearOUT();
+ }
+
+ Pipe_Freeze();
+
+ return PIPE_READYWAIT_NoError;
+}
+
+#if defined(FDEV_SETUP_STREAM)
+void CDC_Host_CreateStream(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
+ FILE* const Stream)
+{
+ *Stream = (FILE)FDEV_SETUP_STREAM(CDC_Host_putchar, CDC_Host_getchar, _FDEV_SETUP_RW);
+ fdev_set_udata(Stream, CDCInterfaceInfo);
+}
+
+void CDC_Host_CreateBlockingStream(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
+ FILE* const Stream)
+{
+ *Stream = (FILE)FDEV_SETUP_STREAM(CDC_Host_putchar, CDC_Host_getchar_Blocking, _FDEV_SETUP_RW);
+ fdev_set_udata(Stream, CDCInterfaceInfo);
+}
+
+static int CDC_Host_putchar(char c,
+ FILE* Stream)
+{
+ return CDC_Host_SendByte((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream), c) ? _FDEV_ERR : 0;
+}
+
+static int CDC_Host_getchar(FILE* Stream)
+{
+ int16_t ReceivedByte = CDC_Host_ReceiveByte((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream));
+
+ if (ReceivedByte < 0)
+ return _FDEV_EOF;
+
+ return ReceivedByte;
+}
+
+static int CDC_Host_getchar_Blocking(FILE* Stream)
+{
+ int16_t ReceivedByte;
+
+ while ((ReceivedByte = CDC_Host_ReceiveByte((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream))) < 0)
+ {
+ if (USB_HostState == HOST_STATE_Unattached)
+ return _FDEV_EOF;
+
+ CDC_Host_USBTask((USB_ClassInfo_CDC_Host_t*)fdev_get_udata(Stream));
+ USB_USBTask();
+ }
+
+ return ReceivedByte;
+}
+#endif
+
+void CDC_Host_Event_Stub(void)
+{
+
+}
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/CDCClassHost.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/CDCClassHost.h
new file mode 100644
index 000000000..aeee23e50
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/CDCClassHost.h
@@ -0,0 +1,351 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Host mode driver for the library USB CDC Class driver.
+ *
+ * Host mode driver for the library USB CDC Class driver.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB module driver
+ * dispatch header located in LUFA/Drivers/USB.h.
+ */
+
+/** \ingroup Group_USBClassCDC
+ * \defgroup Group_USBClassCDCHost CDC Class Host Mode Driver
+ *
+ * \section Sec_USBClassCDCHost_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Drivers/USB/Class/Host/CDCClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ *
+ * \section Sec_USBClassCDCHost_ModDescription Module Description
+ * Host Mode USB Class driver framework interface, for the CDC USB Class driver.
+ *
+ * @{
+ */
+
+#ifndef __CDC_CLASS_HOST_H__
+#define __CDC_CLASS_HOST_H__
+
+ /* Includes: */
+ #include "../../USB.h"
+ #include "../Common/CDCClassCommon.h"
+
+ #include <stdio.h>
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_CDC_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Type Defines: */
+ /** \brief CDC Class Host Mode Configuration and State Structure.
+ *
+ * Class state structure. An instance of this structure should be made within the user application,
+ * and passed to each of the CDC class driver functions as the \c CDCInterfaceInfo parameter. This
+ * stores each CDC interface's configuration and state information.
+ */
+ typedef struct
+ {
+ struct
+ {
+ USB_Pipe_Table_t DataINPipe; /**< Data IN Pipe configuration table. */
+ USB_Pipe_Table_t DataOUTPipe; /**< Data OUT Pipe configuration table. */
+ USB_Pipe_Table_t NotificationPipe; /**< Notification IN Pipe configuration table. */
+ } Config; /**< Config data for the USB class interface within the device. All elements in this section
+ * <b>must</b> be set or the interface will fail to enumerate and operate correctly.
+ */
+ struct
+ {
+ bool IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
+ * after \ref CDC_Host_ConfigurePipes() is called and the Host state machine is in the
+ * Configured state.
+ */
+ uint8_t ControlInterfaceNumber; /**< Interface index of the CDC-ACM control interface within the attached device. */
+
+ struct
+ {
+ uint16_t HostToDevice; /**< Control line states from the host to device, as a set of \c CDC_CONTROL_LINE_OUT_*
+ * masks - to notify the device of changes to these values, call the
+ * \ref CDC_Host_SendControlLineStateChange() function.
+ */
+ uint16_t DeviceToHost; /**< Control line states from the device to host, as a set of \c CDC_CONTROL_LINE_IN_*
+ * masks. This value is updated each time \ref CDC_Host_USBTask() is called.
+ */
+ } ControlLineStates; /**< Current states of the virtual serial port's control lines between the device and host. */
+
+ CDC_LineEncoding_t LineEncoding; /**< Line encoding used in the virtual serial port, for the device's information.
+ * This is generally only used if the virtual serial port data is to be
+ * reconstructed on a physical UART. When set by the host application, the
+ * \ref CDC_Host_SetLineEncoding() function must be called to push the changes
+ * to the device.
+ */
+ } State; /**< State data for the USB class interface within the device. All elements in this section
+ * <b>may</b> be set to initial values, but may also be ignored to default to sane values when
+ * the interface is enumerated.
+ */
+ } USB_ClassInfo_CDC_Host_t;
+
+ /* Enums: */
+ /** Enum for the possible error codes returned by the \ref CDC_Host_ConfigurePipes() function. */
+ enum CDC_Host_EnumerationFailure_ErrorCodes_t
+ {
+ CDC_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */
+ CDC_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */
+ CDC_ENUMERROR_NoCompatibleInterfaceFound = 2, /**< A compatible CDC interface was not found in the device's Configuration Descriptor. */
+ CDC_ENUMERROR_PipeConfigurationFailed = 3, /**< One or more pipes for the specified interface could not be configured correctly. */
+ };
+
+ /* Function Prototypes: */
+ /** General management task for a given CDC host class interface, required for the correct operation of the interface. This should
+ * be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
+ *
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing an CDC Class host configuration and state.
+ */
+ void CDC_Host_USBTask(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Host interface configuration routine, to configure a given CDC host interface instance using the Configuration
+ * Descriptor read from an attached USB device. This function automatically updates the given CDC Host instance's
+ * state values and configures the pipes required to communicate with the interface if it is found within the device.
+ * This should be called once after the stack has enumerated the attached device, while the host state machine is in
+ * the Addressed state.
+ *
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing an CDC Class host configuration and state.
+ * \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor.
+ * \param[in] ConfigDescriptorData Pointer to a buffer containing the attached device's Configuration Descriptor.
+ *
+ * \return A value from the \ref CDC_Host_EnumerationFailure_ErrorCodes_t enum.
+ */
+ uint8_t CDC_Host_ConfigurePipes(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
+ uint16_t ConfigDescriptorSize,
+ void* ConfigDescriptorData) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
+
+ /** Sets the line encoding for the attached device's virtual serial port. This should be called when the \c LineEncoding
+ * values of the interface have been changed to push the new settings to the USB device.
+ *
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state.
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum.
+ */
+ uint8_t CDC_Host_SetLineEncoding(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Sends a Serial Control Line State Change notification to the device. This should be called when the virtual serial
+ * control lines (DTR, RTS, etc.) have changed states. Line states persist until they are cleared via a second
+ * notification. This should be called each time the CDC class driver's \c ControlLineStates.HostToDevice value is updated
+ * to push the new states to the USB device.
+ *
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state.
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum.
+ */
+ uint8_t CDC_Host_SendControlLineStateChange(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Sends a Send Break request to the device. This is generally used to separate data or to indicate a special condition
+ * to the receiving device.
+ *
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state.
+ * \param[in] Duration Duration of the break, in milliseconds.
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum.
+ */
+ uint8_t CDC_Host_SendBreak(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
+ const uint8_t Duration) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Sends a given data buffer to the attached USB device, if connected. If a device is not connected when the function is
+ * called, the data will be discarded. Bytes will be queued for transmission to the device until either the pipe bank
+ * becomes full, or the \ref CDC_Host_Flush() function is called to flush the pending data to the device. This allows for
+ * multiple bytes to be packed into a single pipe packet, increasing data throughput.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state.
+ * \param[in] Buffer Pointer to a buffer containing the data to send to the device.
+ * \param[in] Length Length of the data to send to the device.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t CDC_Host_SendData(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
+ const void* const Buffer,
+ const uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Sends a given null-terminated string to the attached USB device, if connected. If a device is not connected when the
+ * function is called, the string is discarded. Bytes will be queued for transmission to the device until either the pipe
+ * bank becomes full, or the \ref CDC_Host_Flush() function is called to flush the pending data to the device. This allows
+ * for multiple bytes to be packed into a single pipe packet, increasing data throughput.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state.
+ * \param[in] String Pointer to the null terminated string to send to the device.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t CDC_Host_SendString(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
+ const char* const String) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+
+ /** Sends a given byte to the attached USB device, if connected. If a device is not connected when the function is called, the
+ * byte is discarded. Bytes will be queued for transmission to the device until either the pipe bank becomes full, or the
+ * \ref CDC_Host_Flush() function is called to flush the pending data to the host. This allows for multiple bytes to be
+ * packed into a single pipe packet, increasing data throughput.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state.
+ * \param[in] Data Byte of data to send to the device.
+ *
+ * \return A value from the \ref Pipe_WaitUntilReady_ErrorCodes_t enum.
+ */
+ uint8_t CDC_Host_SendByte(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
+ const uint8_t Data) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Determines the number of bytes received by the CDC interface from the device, waiting to be read. This indicates the number
+ * of bytes in the IN pipe bank only, and thus the number of calls to \ref CDC_Host_ReceiveByte() which are guaranteed to succeed
+ * immediately. If multiple bytes are to be received, they should be buffered by the user application, as the pipe bank will not be
+ * released back to the USB controller until all bytes are read.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state.
+ *
+ * \return Total number of buffered bytes received from the device.
+ */
+ uint16_t CDC_Host_BytesReceived(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Reads a byte of data from the device. If no data is waiting to be read of if a USB device is not connected, the function
+ * returns a negative value. The \ref CDC_Host_BytesReceived() function may be queried in advance to determine how many bytes
+ * are currently buffered in the CDC interface's data receive pipe.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state.
+ *
+ * \return Next received byte from the device, or a negative value if no data received.
+ */
+ int16_t CDC_Host_ReceiveByte(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Flushes any data waiting to be sent, ensuring that the send buffer is cleared.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state.
+ *
+ * \return A value from the \ref Pipe_WaitUntilReady_ErrorCodes_t enum.
+ */
+ uint8_t CDC_Host_Flush(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ #if defined(FDEV_SETUP_STREAM) || defined(__DOXYGEN__)
+ /** Creates a standard character stream for the given CDC Device instance so that it can be used with all the regular
+ * functions in the standard \c <stdio.h> library that accept a \c FILE stream as a destination (e.g. \c fprintf). The created
+ * stream is bidirectional and can be used for both input and output functions.
+ *
+ * Reading data from this stream is non-blocking, i.e. in most instances, complete strings cannot be read in by a single
+ * fetch, as the endpoint will not be ready at some point in the transmission, aborting the transfer. However, this may
+ * be used when the read data is processed byte-per-bye (via \c getc()) or when the user application will implement its own
+ * line buffering.
+ *
+ * \note The created stream can be given as \c stdout if desired to direct the standard output from all \c <stdio.h> functions
+ * to the given CDC interface.
+ * \n\n
+ *
+ * \note This function is not available on all microcontroller architectures.
+ *
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state.
+ * \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed.
+ */
+ void CDC_Host_CreateStream(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
+ FILE* const Stream) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+
+ /** Identical to \ref CDC_Host_CreateStream(), except that reads are blocking until the calling stream function terminates
+ * the transfer. While blocking, the USB and CDC service tasks are called repeatedly to maintain USB communications.
+ *
+ * \note This function is not available on all microcontroller architectures.
+ *
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class configuration and state.
+ * \param[in,out] Stream Pointer to a FILE structure where the created stream should be placed.
+ */
+ void CDC_Host_CreateBlockingStream(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo,
+ FILE* const Stream) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+ #endif
+
+ /** CDC class driver event for a control line state change on a CDC host interface. This event fires each time the device notifies
+ * the host of a control line state change (containing the virtual serial control line states, such as DCD) and may be hooked in the
+ * user program by declaring a handler function with the same name and parameters listed here. The new control line states
+ * are available in the \c ControlLineStates.DeviceToHost value inside the CDC host interface structure passed as a parameter, set as
+ * a mask of \c CDC_CONTROL_LINE_IN_* masks.
+ *
+ * \param[in,out] CDCInterfaceInfo Pointer to a structure containing a CDC Class host configuration and state.
+ */
+ void EVENT_CDC_Host_ControLineStateChanged(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Function Prototypes: */
+ #if defined(__INCLUDE_FROM_CDC_HOST_C)
+ #if defined(FDEV_SETUP_STREAM)
+ static int CDC_Host_putchar(char c,
+ FILE* Stream) ATTR_NON_NULL_PTR_ARG(2);
+ static int CDC_Host_getchar(FILE* Stream) ATTR_NON_NULL_PTR_ARG(1);
+ static int CDC_Host_getchar_Blocking(FILE* Stream) ATTR_NON_NULL_PTR_ARG(1);
+ #endif
+
+ void CDC_Host_Event_Stub(void) ATTR_CONST;
+
+ void EVENT_CDC_Host_ControLineStateChanged(USB_ClassInfo_CDC_Host_t* const CDCInterfaceInfo)
+ ATTR_WEAK ATTR_NON_NULL_PTR_ARG(1) ATTR_ALIAS(CDC_Host_Event_Stub);
+
+ static uint8_t DCOMP_CDC_Host_NextCDCControlInterface(void* const CurrentDescriptor)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ static uint8_t DCOMP_CDC_Host_NextCDCDataInterface(void* const CurrentDescriptor)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ static uint8_t DCOMP_CDC_Host_NextCDCInterfaceEndpoint(void* const CurrentDescriptor)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ #endif
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/HIDClassHost.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/HIDClassHost.c
new file mode 100644
index 000000000..b43435dcb
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/HIDClassHost.c
@@ -0,0 +1,399 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../../Core/USBMode.h"
+
+#if defined(USB_CAN_BE_HOST)
+
+#define __INCLUDE_FROM_HID_DRIVER
+#define __INCLUDE_FROM_HID_HOST_C
+#include "HIDClassHost.h"
+
+uint8_t HID_Host_ConfigurePipes(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
+ uint16_t ConfigDescriptorSize,
+ void* ConfigDescriptorData)
+{
+ USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
+ USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
+ USB_Descriptor_Interface_t* HIDInterface = NULL;
+ USB_HID_Descriptor_HID_t* HIDDescriptor = NULL;
+
+ memset(&HIDInterfaceInfo->State, 0x00, sizeof(HIDInterfaceInfo->State));
+
+ if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
+ return HID_ENUMERROR_InvalidConfigDescriptor;
+
+ while (!(DataINEndpoint) || !(DataOUTEndpoint))
+ {
+ if (!(HIDInterface) ||
+ USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+ DCOMP_HID_Host_NextHIDInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
+ {
+ if (DataINEndpoint)
+ break;
+
+ do
+ {
+ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+ DCOMP_HID_Host_NextHIDInterface) != DESCRIPTOR_SEARCH_COMP_Found)
+ {
+ return HID_ENUMERROR_NoCompatibleInterfaceFound;
+ }
+
+ HIDInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
+ } while (HIDInterfaceInfo->Config.HIDInterfaceProtocol &&
+ (HIDInterface->Protocol != HIDInterfaceInfo->Config.HIDInterfaceProtocol));
+
+ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+ DCOMP_HID_Host_NextHIDDescriptor) != DESCRIPTOR_SEARCH_COMP_Found)
+ {
+ return HID_ENUMERROR_NoCompatibleInterfaceFound;
+ }
+
+ HIDDescriptor = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_HID_Descriptor_HID_t);
+
+ DataINEndpoint = NULL;
+ DataOUTEndpoint = NULL;
+
+ continue;
+ }
+
+ USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
+
+ if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN)
+ DataINEndpoint = EndpointData;
+ else
+ DataOUTEndpoint = EndpointData;
+ }
+
+ HIDInterfaceInfo->Config.DataINPipe.Size = le16_to_cpu(DataINEndpoint->EndpointSize);
+ HIDInterfaceInfo->Config.DataINPipe.EndpointAddress = DataINEndpoint->EndpointAddress;
+ HIDInterfaceInfo->Config.DataINPipe.Type = EP_TYPE_INTERRUPT;
+
+ if (!(Pipe_ConfigurePipeTable(&HIDInterfaceInfo->Config.DataINPipe, 1)))
+ return HID_ENUMERROR_PipeConfigurationFailed;
+
+ if (DataOUTEndpoint)
+ {
+ HIDInterfaceInfo->Config.DataOUTPipe.Size = le16_to_cpu(DataOUTEndpoint->EndpointSize);
+ HIDInterfaceInfo->Config.DataOUTPipe.EndpointAddress = DataOUTEndpoint->EndpointAddress;
+ HIDInterfaceInfo->Config.DataOUTPipe.Type = EP_TYPE_INTERRUPT;
+
+ if (!(Pipe_ConfigurePipeTable(&HIDInterfaceInfo->Config.DataOUTPipe, 1)))
+ return HID_ENUMERROR_PipeConfigurationFailed;
+ }
+
+ HIDInterfaceInfo->State.InterfaceNumber = HIDInterface->InterfaceNumber;
+ HIDInterfaceInfo->State.HIDReportSize = LE16_TO_CPU(HIDDescriptor->HIDReportLength);
+ HIDInterfaceInfo->State.SupportsBootProtocol = (HIDInterface->SubClass != HID_CSCP_NonBootProtocol);
+ HIDInterfaceInfo->State.LargestReportSize = 8;
+ HIDInterfaceInfo->State.IsActive = true;
+
+ return HID_ENUMERROR_NoError;
+}
+
+static uint8_t DCOMP_HID_Host_NextHIDInterface(void* const CurrentDescriptor)
+{
+ USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
+
+ if (Header->Type == DTYPE_Interface)
+ {
+ USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
+
+ if (Interface->Class == HID_CSCP_HIDClass)
+ return DESCRIPTOR_SEARCH_Found;
+ }
+
+ return DESCRIPTOR_SEARCH_NotFound;
+}
+
+static uint8_t DCOMP_HID_Host_NextHIDDescriptor(void* const CurrentDescriptor)
+{
+ USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
+
+ if (Header->Type == HID_DTYPE_HID)
+ return DESCRIPTOR_SEARCH_Found;
+ else if (Header->Type == DTYPE_Interface)
+ return DESCRIPTOR_SEARCH_Fail;
+ else
+ return DESCRIPTOR_SEARCH_NotFound;
+}
+
+static uint8_t DCOMP_HID_Host_NextHIDInterfaceEndpoint(void* const CurrentDescriptor)
+{
+ USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
+
+ if (Header->Type == DTYPE_Endpoint)
+ {
+ USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
+
+ if (!(Pipe_IsEndpointBound(Endpoint->EndpointAddress)))
+ return DESCRIPTOR_SEARCH_Found;
+ }
+ else if (Header->Type == DTYPE_Interface)
+ {
+ return DESCRIPTOR_SEARCH_Fail;
+ }
+
+ return DESCRIPTOR_SEARCH_NotFound;
+}
+
+#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
+uint8_t HID_Host_ReceiveReportByID(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
+ const uint8_t ReportID,
+ void* Buffer)
+{
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
+ .bRequest = HID_REQ_SetReport,
+ .wValue = ((HID_REPORT_ITEM_In + 1) << 8) | ReportID,
+ .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
+ .wLength = USB_GetHIDReportSize(HIDInterfaceInfo->Config.HIDParserData, ReportID, HID_REPORT_ITEM_In),
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+
+ return USB_Host_SendControlRequest(Buffer);
+}
+#endif
+
+uint8_t HID_Host_ReceiveReport(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
+ void* Buffer)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
+ return PIPE_READYWAIT_DeviceDisconnected;
+
+ uint8_t ErrorCode;
+
+ Pipe_SelectPipe(HIDInterfaceInfo->Config.DataINPipe.Address);
+ Pipe_Unfreeze();
+
+ uint16_t ReportSize;
+ uint8_t* BufferPos = Buffer;
+
+#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
+ if (!(HIDInterfaceInfo->State.UsingBootProtocol))
+ {
+ uint8_t ReportID = 0;
+
+ if (HIDInterfaceInfo->Config.HIDParserData->UsingReportIDs)
+ {
+ ReportID = Pipe_Read_8();
+ *(BufferPos++) = ReportID;
+ }
+
+ ReportSize = USB_GetHIDReportSize(HIDInterfaceInfo->Config.HIDParserData, ReportID, HID_REPORT_ITEM_In);
+ }
+ else
+#endif
+ {
+ ReportSize = Pipe_BytesInPipe();
+ }
+
+ if ((ErrorCode = Pipe_Read_Stream_LE(BufferPos, ReportSize, NULL)) != PIPE_RWSTREAM_NoError)
+ return ErrorCode;
+
+ Pipe_ClearIN();
+ Pipe_Freeze();
+
+ return PIPE_RWSTREAM_NoError;
+}
+
+uint8_t HID_Host_SendReportByID(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
+#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
+ const uint8_t ReportID,
+#endif
+ const uint8_t ReportType,
+ void* Buffer,
+ const uint16_t ReportSize)
+{
+#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
+ if ((USB_HostState != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
+ return PIPE_RWSTREAM_NoError;
+
+ if (HIDInterfaceInfo->State.DeviceUsesOUTPipe && (ReportType == HID_REPORT_ITEM_Out))
+ {
+ uint8_t ErrorCode;
+
+ Pipe_SelectPipe(HIDInterfaceInfo->Config.DataOUTPipe.Address);
+ Pipe_Unfreeze();
+
+ if (ReportID)
+ Pipe_Write_Stream_LE(&ReportID, sizeof(ReportID), NULL);
+
+ if ((ErrorCode = Pipe_Write_Stream_LE(Buffer, ReportSize, NULL)) != PIPE_RWSTREAM_NoError)
+ return ErrorCode;
+
+ Pipe_ClearOUT();
+ Pipe_Freeze();
+
+ return PIPE_RWSTREAM_NoError;
+ }
+ else
+#endif
+ {
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
+ .bRequest = HID_REQ_SetReport,
+#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
+ .wValue = ((ReportType + 1) << 8) | ReportID,
+#else
+ .wValue = ((ReportType + 1) << 8),
+#endif
+ .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
+ .wLength = ReportSize,
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+
+ return USB_Host_SendControlRequest(Buffer);
+ }
+}
+
+bool HID_Host_IsReportReceived(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
+ return false;
+
+ bool ReportReceived;
+
+ Pipe_SelectPipe(HIDInterfaceInfo->Config.DataINPipe.Address);
+ Pipe_Unfreeze();
+
+ ReportReceived = Pipe_IsINReceived();
+
+ Pipe_Freeze();
+
+ return ReportReceived;
+}
+
+uint8_t HID_Host_SetBootProtocol(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
+{
+ uint8_t ErrorCode;
+
+ if (!(HIDInterfaceInfo->State.SupportsBootProtocol))
+ return HID_ERROR_LOGICAL;
+
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
+ .bRequest = HID_REQ_SetProtocol,
+ .wValue = 0,
+ .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
+ .wLength = 0,
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+
+ if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
+ return ErrorCode;
+
+ HIDInterfaceInfo->State.LargestReportSize = 8;
+ HIDInterfaceInfo->State.UsingBootProtocol = true;
+
+ return HOST_SENDCONTROL_Successful;
+}
+
+uint8_t HID_Host_SetIdlePeriod(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
+ const uint16_t MS)
+{
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
+ .bRequest = HID_REQ_SetIdle,
+ .wValue = ((MS << 6) & 0xFF00),
+ .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
+ .wLength = 0,
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+
+ return USB_Host_SendControlRequest(NULL);
+}
+
+#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
+uint8_t HID_Host_SetReportProtocol(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
+{
+ uint8_t ErrorCode;
+
+ uint8_t HIDReportData[HIDInterfaceInfo->State.HIDReportSize];
+
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_INTERFACE),
+ .bRequest = REQ_GetDescriptor,
+ .wValue = (HID_DTYPE_Report << 8),
+ .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
+ .wLength = HIDInterfaceInfo->State.HIDReportSize,
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+
+ if ((ErrorCode = USB_Host_SendControlRequest(HIDReportData)) != HOST_SENDCONTROL_Successful)
+ return ErrorCode;
+
+ if (HIDInterfaceInfo->State.UsingBootProtocol)
+ {
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
+ .bRequest = HID_REQ_SetProtocol,
+ .wValue = 1,
+ .wIndex = HIDInterfaceInfo->State.InterfaceNumber,
+ .wLength = 0,
+ };
+
+ if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
+ return ErrorCode;
+
+ HIDInterfaceInfo->State.UsingBootProtocol = false;
+ }
+
+ if (HIDInterfaceInfo->Config.HIDParserData == NULL)
+ return HID_ERROR_LOGICAL;
+
+ if ((ErrorCode = USB_ProcessHIDReport(HIDReportData, HIDInterfaceInfo->State.HIDReportSize,
+ HIDInterfaceInfo->Config.HIDParserData)) != HID_PARSE_Successful)
+ {
+ return HID_ERROR_LOGICAL | ErrorCode;
+ }
+
+ uint16_t LargestReportSizeBits = HIDInterfaceInfo->Config.HIDParserData->LargestReportSizeBits;
+ HIDInterfaceInfo->State.LargestReportSize = (LargestReportSizeBits >> 3) + ((LargestReportSizeBits & 0x07) != 0);
+
+ return 0;
+}
+#endif
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/HIDClassHost.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/HIDClassHost.h
new file mode 100644
index 000000000..703b698df
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/HIDClassHost.h
@@ -0,0 +1,313 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Host mode driver for the library USB HID Class driver.
+ *
+ * Host mode driver for the library USB HID Class driver.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB module driver
+ * dispatch header located in LUFA/Drivers/USB.h.
+ */
+
+/** \ingroup Group_USBClassHID
+ * \defgroup Group_USBClassHIDHost HID Class Host Mode Driver
+ *
+ * \section Sec_USBClassHIDHost_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Drivers/USB/Class/Host/HIDClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ *
+ * \section Sec_USBClassHIDHost_ModDescription Module Description
+ * Host Mode USB Class driver framework interface, for the HID USB Class driver.
+ *
+ * @{
+ */
+
+#ifndef __HID_CLASS_HOST_H__
+#define __HID_CLASS_HOST_H__
+
+ /* Includes: */
+ #include "../../USB.h"
+ #include "../Common/HIDClassCommon.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_HID_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Error code for some HID Host functions, indicating a logical (and not hardware) error. */
+ #define HID_ERROR_LOGICAL 0x80
+
+ /* Type Defines: */
+ /** \brief HID Class Host Mode Configuration and State Structure.
+ *
+ * Class state structure. An instance of this structure should be made within the user application,
+ * and passed to each of the HID class driver functions as the \c HIDInterfaceInfo parameter. This
+ * stores each HID interface's configuration and state information.
+ */
+ typedef struct
+ {
+ struct
+ {
+ USB_Pipe_Table_t DataINPipe; /**< Data IN Pipe configuration table. */
+ USB_Pipe_Table_t DataOUTPipe; /**< Data OUT Pipe configuration table. */
+
+ uint8_t HIDInterfaceProtocol; /**< HID interface protocol value to match against if a specific
+ * boot subclass protocol is required, a protocol value from the
+ * \ref HID_Descriptor_ClassSubclassProtocol_t enum.
+ */
+ #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
+ HID_ReportInfo_t* HIDParserData; /**< HID parser data to store the parsed HID report data, when boot protocol
+ * is not used.
+ *
+ * \note When the \c HID_HOST_BOOT_PROTOCOL_ONLY compile time token is defined,
+ * this field is unavailable.
+ */
+ #endif
+ } Config; /**< Config data for the USB class interface within the device. All elements in this section
+ * <b>must</b> be set or the interface will fail to enumerate and operate correctly.
+ */
+ struct
+ {
+ bool IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
+ * after \ref HID_Host_ConfigurePipes() is called and the Host state machine is in the
+ * Configured state.
+ */
+ uint8_t InterfaceNumber; /**< Interface index of the HID interface within the attached device. */
+
+ bool SupportsBootProtocol; /**< Indicates if the current interface instance supports the HID Boot
+ * Protocol when enabled via \ref HID_Host_SetBootProtocol().
+ */
+ bool DeviceUsesOUTPipe; /**< Indicates if the current interface instance uses a separate OUT data pipe for
+ * OUT reports, or if OUT reports are sent via the control pipe instead.
+ */
+ bool UsingBootProtocol; /**< Indicates that the interface is currently initialized in Boot Protocol mode */
+ uint16_t HIDReportSize; /**< Size in bytes of the HID report descriptor in the device. */
+
+ uint8_t LargestReportSize; /**< Largest report the device will send, in bytes. */
+ } State; /**< State data for the USB class interface within the device. All elements in this section
+ * <b>may</b> be set to initial values, but may also be ignored to default to sane values when
+ * the interface is enumerated.
+ */
+ } USB_ClassInfo_HID_Host_t;
+
+ /* Enums: */
+ /** Enum for the possible error codes returned by the \ref HID_Host_ConfigurePipes() function. */
+ enum HID_Host_EnumerationFailure_ErrorCodes_t
+ {
+ HID_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */
+ HID_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */
+ HID_ENUMERROR_NoCompatibleInterfaceFound = 2, /**< A compatible HID interface was not found in the device's Configuration Descriptor. */
+ HID_ENUMERROR_PipeConfigurationFailed = 3, /**< One or more pipes for the specified interface could not be configured correctly. */
+ };
+
+ /* Function Prototypes: */
+ /** Host interface configuration routine, to configure a given HID host interface instance using the Configuration
+ * Descriptor read from an attached USB device. This function automatically updates the given HID Host instance's
+ * state values and configures the pipes required to communicate with the interface if it is found within the
+ * device. This should be called once after the stack has enumerated the attached device, while the host state
+ * machine is in the Addressed state.
+ *
+ * \attention Once the device pipes are configured, the HID device's reporting protocol <b>must</b> be set via a call
+ * to either the \ref HID_Host_SetBootProtocol() or \ref HID_Host_SetReportProtocol() function.
+ *
+ * \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state.
+ * \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor.
+ * \param[in] ConfigDescriptorData Pointer to a buffer containing the attached device's Configuration Descriptor.
+ *
+ * \return A value from the \ref HID_Host_EnumerationFailure_ErrorCodes_t enum.
+ */
+ uint8_t HID_Host_ConfigurePipes(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
+ uint16_t ConfigDescriptorSize,
+ void* ConfigDescriptorData) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
+
+
+ /** Receives a HID IN report from the attached HID device, when a report has been received on the HID IN Data pipe.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \attention The destination buffer should be large enough to accommodate the largest report that the attached device
+ * can generate.
+ *
+ * \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state.
+ * \param[in] Buffer Buffer to store the received report into.
+ *
+ * \return An error code from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t HID_Host_ReceiveReport(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
+ void* Buffer) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+
+ #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
+ /** Receives a HID IN report from the attached device, by the report ID.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \note When the \c HID_HOST_BOOT_PROTOCOL_ONLY compile time token is defined, this method is unavailable.
+ *
+ * \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state.
+ * \param[in] ReportID Report ID of the received report if ControlRequest is false, set by the to the Report ID to fetch.
+ * \param[in] Buffer Buffer to store the received report into.
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum.
+ */
+ uint8_t HID_Host_ReceiveReportByID(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
+ const uint8_t ReportID,
+ void* Buffer) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
+ #endif
+
+ /** Sends an OUT or FEATURE report to the currently attached HID device, using the device's OUT pipe if available,
+ * or the device's Control pipe if not.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \note When the \c HID_HOST_BOOT_PROTOCOL_ONLY compile time token is defined, the ReportID parameter is removed
+ * from the parameter list of this function.
+ *
+ * \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state.
+ * \param[in] ReportID Report ID of the report to send to the device, or 0 if the device does not use report IDs.
+ * \param[in] ReportType Type of report to issue to the device, either \ref HID_REPORT_ITEM_Out or \ref HID_REPORT_ITEM_Feature.
+ * \param[in] Buffer Buffer containing the report to send to the attached device.
+ * \param[in] ReportSize Report size in bytes to send to the attached device.
+ *
+ * \return An error code from the \ref USB_Host_SendControlErrorCodes_t enum if the DeviceUsesOUTPipe flag is set in
+ * the interface's state structure, a value from the \ref Pipe_Stream_RW_ErrorCodes_t enum otherwise.
+ */
+ uint8_t HID_Host_SendReportByID(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
+ #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
+ const uint8_t ReportID,
+ #endif
+ const uint8_t ReportType,
+ void* Buffer,
+ const uint16_t ReportSize) ATTR_NON_NULL_PTR_ARG(1)
+ #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
+ ATTR_NON_NULL_PTR_ARG(4);
+ #else
+ ATTR_NON_NULL_PTR_ARG(3);
+ #endif
+
+ /** Determines if a HID IN report has been received from the attached device on the data IN pipe.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state.
+ *
+ * \return Boolean \c true if a report has been received, \c false otherwise.
+ */
+ bool HID_Host_IsReportReceived(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Switches the attached HID device's reporting protocol over to the Boot Report protocol mode, on supported devices.
+ *
+ * \note When the \c HID_HOST_BOOT_PROTOCOL_ONLY compile time token is defined, this method must still be called
+ * to explicitly place the attached device into boot protocol mode before use.
+ *
+ * \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state.
+ *
+ * \return \ref HID_ERROR_LOGICAL if the device does not support Boot Protocol mode, a value from the
+ * \ref USB_Host_SendControlErrorCodes_t enum otherwise.
+ */
+ uint8_t HID_Host_SetBootProtocol(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Sets the idle period for the attached HID device to the specified interval. The HID idle period determines the rate
+ * at which the device should send a report, when no state changes have occurred; i.e. on HID keyboards, this sets the
+ * hardware key repeat interval.
+ *
+ * \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state.
+ * \param[in] MS Idle period as a multiple of four milliseconds, zero to disable hardware repeats
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum.
+ */
+ uint8_t HID_Host_SetIdlePeriod(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
+ const uint16_t MS) ATTR_NON_NULL_PTR_ARG(1);
+
+ #if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
+ /** Switches the attached HID device's reporting protocol over to the standard Report protocol mode. This also retrieves
+ * and parses the device's HID report descriptor, so that the size of each report can be determined in advance.
+ *
+ * \attention Whether this function is used or not, the \ref CALLBACK_HIDParser_FilterHIDReportItem() callback from the HID
+ * Report Parser this function references <b>must</b> be implemented in the user code.
+ *
+ * \note When the \c HID_HOST_BOOT_PROTOCOL_ONLY compile time token is defined, this method is unavailable.
+ *
+ * \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state.
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum if an error occurs while retrieving the HID
+ * Report descriptor or the setting of the Report protocol, \ref HID_ERROR_LOGICAL if the HID interface does
+ * not have a valid \ref HID_ReportInfo_t structure set in its configuration, a mask of \ref HID_ERROR_LOGICAL
+ * and a value from the \ref HID_Parse_ErrorCodes_t otherwise.
+ */
+ uint8_t HID_Host_SetReportProtocol(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+ #endif
+
+ /* Inline Functions: */
+ /** General management task for a given Human Interface Class host class interface, required for the correct operation of
+ * the interface. This should be called frequently in the main program loop, before the master USB management task
+ * \ref USB_USBTask().
+ *
+ * \param[in,out] HIDInterfaceInfo Pointer to a structure containing a HID Class host configuration and state.
+ */
+ static inline void HID_Host_USBTask(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+ static inline void HID_Host_USBTask(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
+ {
+ (void)HIDInterfaceInfo;
+ }
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Function Prototypes: */
+ #if defined(__INCLUDE_FROM_HID_HOST_C)
+ static uint8_t DCOMP_HID_Host_NextHIDInterface(void* const CurrentDescriptor)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ static uint8_t DCOMP_HID_Host_NextHIDDescriptor(void* const CurrentDescriptor)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ static uint8_t DCOMP_HID_Host_NextHIDInterfaceEndpoint(void* const CurrentDescriptor)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ #endif
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/MIDIClassHost.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/MIDIClassHost.c
new file mode 100644
index 000000000..8b898cba5
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/MIDIClassHost.c
@@ -0,0 +1,231 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../../Core/USBMode.h"
+
+#if defined(USB_CAN_BE_HOST)
+
+#define __INCLUDE_FROM_MIDI_DRIVER
+#define __INCLUDE_FROM_MIDI_HOST_C
+#include "MIDIClassHost.h"
+
+uint8_t MIDI_Host_ConfigurePipes(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo,
+ uint16_t ConfigDescriptorSize,
+ void* ConfigDescriptorData)
+{
+ USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
+ USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
+ USB_Descriptor_Interface_t* MIDIInterface = NULL;
+
+ memset(&MIDIInterfaceInfo->State, 0x00, sizeof(MIDIInterfaceInfo->State));
+
+ if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
+ return MIDI_ENUMERROR_InvalidConfigDescriptor;
+
+ while (!(DataINEndpoint) || !(DataOUTEndpoint))
+ {
+ if (!(MIDIInterface) ||
+ USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+ DCOMP_MIDI_Host_NextMIDIStreamingDataEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
+ {
+ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+ DCOMP_MIDI_Host_NextMIDIStreamingInterface) != DESCRIPTOR_SEARCH_COMP_Found)
+ {
+ return MIDI_ENUMERROR_NoCompatibleInterfaceFound;
+ }
+
+ MIDIInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
+
+ DataINEndpoint = NULL;
+ DataOUTEndpoint = NULL;
+
+ continue;
+ }
+
+ USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
+
+ if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN)
+ DataINEndpoint = EndpointData;
+ else
+ DataOUTEndpoint = EndpointData;
+ }
+
+ MIDIInterfaceInfo->Config.DataINPipe.Size = le16_to_cpu(DataINEndpoint->EndpointSize);
+ MIDIInterfaceInfo->Config.DataINPipe.EndpointAddress = DataINEndpoint->EndpointAddress;
+ MIDIInterfaceInfo->Config.DataINPipe.Type = EP_TYPE_BULK;
+
+ MIDIInterfaceInfo->Config.DataOUTPipe.Size = le16_to_cpu(DataOUTEndpoint->EndpointSize);
+ MIDIInterfaceInfo->Config.DataOUTPipe.EndpointAddress = DataOUTEndpoint->EndpointAddress;
+ MIDIInterfaceInfo->Config.DataOUTPipe.Type = EP_TYPE_BULK;
+
+ if (!(Pipe_ConfigurePipeTable(&MIDIInterfaceInfo->Config.DataINPipe, 1)))
+ return MIDI_ENUMERROR_PipeConfigurationFailed;
+
+ if (!(Pipe_ConfigurePipeTable(&MIDIInterfaceInfo->Config.DataOUTPipe, 1)))
+ return MIDI_ENUMERROR_PipeConfigurationFailed;
+
+ MIDIInterfaceInfo->State.InterfaceNumber = MIDIInterface->InterfaceNumber;
+ MIDIInterfaceInfo->State.IsActive = true;
+
+ return MIDI_ENUMERROR_NoError;
+}
+
+static uint8_t DCOMP_MIDI_Host_NextMIDIStreamingInterface(void* const CurrentDescriptor)
+{
+ USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
+
+ if (Header->Type == DTYPE_Interface)
+ {
+ USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
+
+ if ((Interface->Class == AUDIO_CSCP_AudioClass) &&
+ (Interface->SubClass == AUDIO_CSCP_MIDIStreamingSubclass) &&
+ (Interface->Protocol == AUDIO_CSCP_StreamingProtocol))
+ {
+ return DESCRIPTOR_SEARCH_Found;
+ }
+ }
+
+ return DESCRIPTOR_SEARCH_NotFound;
+}
+
+static uint8_t DCOMP_MIDI_Host_NextMIDIStreamingDataEndpoint(void* const CurrentDescriptor)
+{
+ USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
+
+ if (Header->Type == DTYPE_Endpoint)
+ {
+ USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
+
+ uint8_t EndpointType = (Endpoint->Attributes & EP_TYPE_MASK);
+
+ if ((EndpointType == EP_TYPE_BULK) && !(Pipe_IsEndpointBound(Endpoint->EndpointAddress)))
+ return DESCRIPTOR_SEARCH_Found;
+ }
+ else if (Header->Type == DTYPE_Interface)
+ {
+ return DESCRIPTOR_SEARCH_Fail;
+ }
+
+ return DESCRIPTOR_SEARCH_NotFound;
+}
+
+void MIDI_Host_USBTask(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(MIDIInterfaceInfo->State.IsActive))
+ return;
+
+ #if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
+ MIDI_Host_Flush(MIDIInterfaceInfo);
+ #endif
+}
+
+uint8_t MIDI_Host_Flush(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(MIDIInterfaceInfo->State.IsActive))
+ return PIPE_RWSTREAM_DeviceDisconnected;
+
+ uint8_t ErrorCode;
+
+ Pipe_SelectPipe(MIDIInterfaceInfo->Config.DataOUTPipe.Address);
+ Pipe_Unfreeze();
+
+ if (Pipe_BytesInPipe())
+ {
+ Pipe_ClearOUT();
+
+ if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
+ {
+ Pipe_Freeze();
+ return ErrorCode;
+ }
+ }
+
+ Pipe_Freeze();
+
+ return PIPE_READYWAIT_NoError;
+}
+
+uint8_t MIDI_Host_SendEventPacket(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo,
+ MIDI_EventPacket_t* const Event)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(MIDIInterfaceInfo->State.IsActive))
+ return HOST_SENDCONTROL_DeviceDisconnected;
+
+ uint8_t ErrorCode;
+
+ Pipe_SelectPipe(MIDIInterfaceInfo->Config.DataOUTPipe.Address);
+ Pipe_Unfreeze();
+
+ if ((ErrorCode = Pipe_Write_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NULL)) != PIPE_RWSTREAM_NoError)
+ {
+ Pipe_Freeze();
+ return ErrorCode;
+ }
+
+ if (!(Pipe_IsReadWriteAllowed()))
+ Pipe_ClearOUT();
+
+ Pipe_Freeze();
+
+ return PIPE_RWSTREAM_NoError;
+}
+
+bool MIDI_Host_ReceiveEventPacket(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo,
+ MIDI_EventPacket_t* const Event)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(MIDIInterfaceInfo->State.IsActive))
+ return HOST_SENDCONTROL_DeviceDisconnected;
+
+ bool DataReady = false;
+
+ Pipe_SelectPipe(MIDIInterfaceInfo->Config.DataINPipe.Address);
+ Pipe_Unfreeze();
+
+ if (Pipe_IsINReceived())
+ {
+ if (Pipe_BytesInPipe())
+ {
+ Pipe_Read_Stream_LE(Event, sizeof(MIDI_EventPacket_t), NULL);
+ DataReady = true;
+ }
+
+ if (!(Pipe_BytesInPipe()))
+ Pipe_ClearIN();
+ }
+
+ Pipe_Freeze();
+
+ return DataReady;
+}
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/MIDIClassHost.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/MIDIClassHost.h
new file mode 100644
index 000000000..7624f8ed9
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/MIDIClassHost.h
@@ -0,0 +1,190 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Host mode driver for the library USB MIDI Class driver.
+ *
+ * Host mode driver for the library USB MIDI Class driver.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB module driver
+ * dispatch header located in LUFA/Drivers/USB.h.
+ */
+
+/** \ingroup Group_USBClassMIDI
+ * \defgroup Group_USBClassMIDIHost MIDI Class Host Mode Driver
+ *
+ * \section Sec_USBClassMIDIHost_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Drivers/USB/Class/Host/MIDIClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ *
+ * \section Sec_USBClassMIDIHost_ModDescription Module Description
+ * Host Mode USB Class driver framework interface, for the MIDI USB Class driver.
+ *
+ * @{
+ */
+
+#ifndef __MIDI_CLASS_HOST_H__
+#define __MIDI_CLASS_HOST_H__
+
+ /* Includes: */
+ #include "../../USB.h"
+ #include "../Common/MIDIClassCommon.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_MIDI_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Type Defines: */
+ /** \brief MIDI Class Host Mode Configuration and State Structure.
+ *
+ * Class state structure. An instance of this structure should be made within the user application,
+ * and passed to each of the MIDI class driver functions as the \c MIDIInterfaceInfo parameter. This
+ * stores each MIDI interface's configuration and state information.
+ */
+ typedef struct
+ {
+ struct
+ {
+ USB_Pipe_Table_t DataINPipe; /**< Data IN Pipe configuration table. */
+ USB_Pipe_Table_t DataOUTPipe; /**< Data OUT Pipe configuration table. */
+ } Config; /**< Config data for the USB class interface within the device. All elements in this section
+ * <b>must</b> be set or the interface will fail to enumerate and operate correctly.
+ */
+ struct
+ {
+ bool IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
+ * after \ref MIDI_Host_ConfigurePipes() is called and the Host state machine is in the
+ * Configured state.
+ */
+ uint8_t InterfaceNumber; /**< Interface index of the MIDI interface within the attached device. */
+ } State; /**< State data for the USB class interface within the device. All elements in this section
+ * <b>may</b> be set to initial values, but may also be ignored to default to sane values when
+ * the interface is enumerated.
+ */
+ } USB_ClassInfo_MIDI_Host_t;
+
+ /* Enums: */
+ /** Enum for the possible error codes returned by the \ref MIDI_Host_ConfigurePipes() function. */
+ enum MIDI_Host_EnumerationFailure_ErrorCodes_t
+ {
+ MIDI_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */
+ MIDI_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */
+ MIDI_ENUMERROR_NoCompatibleInterfaceFound = 2, /**< A compatible MIDI interface was not found in the device's Configuration Descriptor. */
+ MIDI_ENUMERROR_PipeConfigurationFailed = 3, /**< One or more pipes for the specified interface could not be configured correctly. */
+ };
+
+ /* Function Prototypes: */
+ /** Host interface configuration routine, to configure a given MIDI host interface instance using the Configuration
+ * Descriptor read from an attached USB device. This function automatically updates the given MIDI Host instance's
+ * state values and configures the pipes required to communicate with the interface if it is found within the device.
+ * This should be called once after the stack has enumerated the attached device, while the host state machine is in
+ * the Addressed state.
+ *
+ * \param[in,out] MIDIInterfaceInfo Pointer to a structure containing an MIDI Class host configuration and state.
+ * \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor.
+ * \param[in] ConfigDescriptorData Pointer to a buffer containing the attached device's Configuration Descriptor.
+ *
+ * \return A value from the \ref MIDI_Host_EnumerationFailure_ErrorCodes_t enum.
+ */
+ uint8_t MIDI_Host_ConfigurePipes(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo,
+ uint16_t ConfigDescriptorSize,
+ void* ConfigDescriptorData) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
+
+ /** General management task for a given MIDI host class interface, required for the correct operation of the interface. This should
+ * be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
+ *
+ * \param[in,out] MIDIInterfaceInfo Pointer to a structure containing an MIDI Class host configuration and state.
+ */
+ void MIDI_Host_USBTask(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Sends a MIDI event packet to the device. If no device is connected, the event packet is discarded.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state.
+ * \param[in] Event Pointer to a populated USB_MIDI_EventPacket_t structure containing the MIDI event to send.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t MIDI_Host_SendEventPacket(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo,
+ MIDI_EventPacket_t* const Event) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+
+ /** Flushes the MIDI send buffer, sending any queued MIDI events to the device. This should be called to override the
+ * \ref MIDI_Host_SendEventPacket() function's packing behavior, to flush queued events. Events are queued into the
+ * pipe bank until either the pipe bank is full, or \ref MIDI_Host_Flush() is called. This allows for multiple MIDI
+ * events to be packed into a single pipe packet, increasing data throughput.
+ *
+ * \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state.
+ *
+ * \return A value from the \ref Pipe_WaitUntilReady_ErrorCodes_t enum.
+ */
+ uint8_t MIDI_Host_Flush(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Receives a MIDI event packet from the device.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] MIDIInterfaceInfo Pointer to a structure containing a MIDI Class configuration and state.
+ * \param[out] Event Pointer to a USB_MIDI_EventPacket_t structure where the received MIDI event is to be placed.
+ *
+ * \return Boolean \c true if a MIDI event packet was received, \c false otherwise.
+ */
+ bool MIDI_Host_ReceiveEventPacket(USB_ClassInfo_MIDI_Host_t* const MIDIInterfaceInfo,
+ MIDI_EventPacket_t* const Event) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Function Prototypes: */
+ #if defined(__INCLUDE_FROM_MIDI_HOST_C)
+ static uint8_t DCOMP_MIDI_Host_NextMIDIStreamingInterface(void* const CurrentDescriptor)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ static uint8_t DCOMP_MIDI_Host_NextMIDIStreamingDataEndpoint(void* const CurrentDescriptor)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ #endif
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/MassStorageClassHost.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/MassStorageClassHost.c
new file mode 100644
index 000000000..ac448a55b
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/MassStorageClassHost.c
@@ -0,0 +1,579 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../../Core/USBMode.h"
+
+#if defined(USB_CAN_BE_HOST)
+
+#define __INCLUDE_FROM_MS_DRIVER
+#define __INCLUDE_FROM_MASSSTORAGE_HOST_C
+#include "MassStorageClassHost.h"
+
+uint8_t MS_Host_ConfigurePipes(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
+ uint16_t ConfigDescriptorSize,
+ void* ConfigDescriptorData)
+{
+ USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
+ USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
+ USB_Descriptor_Interface_t* MassStorageInterface = NULL;
+
+ memset(&MSInterfaceInfo->State, 0x00, sizeof(MSInterfaceInfo->State));
+
+ if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
+ return MS_ENUMERROR_InvalidConfigDescriptor;
+
+ while (!(DataINEndpoint) || !(DataOUTEndpoint))
+ {
+ if (!(MassStorageInterface) ||
+ USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+ DCOMP_MS_Host_NextMSInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
+ {
+ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+ DCOMP_MS_Host_NextMSInterface) != DESCRIPTOR_SEARCH_COMP_Found)
+ {
+ return MS_ENUMERROR_NoCompatibleInterfaceFound;
+ }
+
+ MassStorageInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
+
+ DataINEndpoint = NULL;
+ DataOUTEndpoint = NULL;
+
+ continue;
+ }
+
+ USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
+
+ if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN)
+ DataINEndpoint = EndpointData;
+ else
+ DataOUTEndpoint = EndpointData;
+ }
+
+ MSInterfaceInfo->Config.DataINPipe.Size = le16_to_cpu(DataINEndpoint->EndpointSize);
+ MSInterfaceInfo->Config.DataINPipe.EndpointAddress = DataINEndpoint->EndpointAddress;
+ MSInterfaceInfo->Config.DataINPipe.Type = EP_TYPE_BULK;
+
+ MSInterfaceInfo->Config.DataOUTPipe.Size = le16_to_cpu(DataOUTEndpoint->EndpointSize);
+ MSInterfaceInfo->Config.DataOUTPipe.EndpointAddress = DataOUTEndpoint->EndpointAddress;
+ MSInterfaceInfo->Config.DataOUTPipe.Type = EP_TYPE_BULK;
+
+ if (!(Pipe_ConfigurePipeTable(&MSInterfaceInfo->Config.DataINPipe, 1)))
+ return MS_ENUMERROR_PipeConfigurationFailed;
+
+ if (!(Pipe_ConfigurePipeTable(&MSInterfaceInfo->Config.DataOUTPipe, 1)))
+ return MS_ENUMERROR_PipeConfigurationFailed;
+
+ MSInterfaceInfo->State.InterfaceNumber = MassStorageInterface->InterfaceNumber;
+ MSInterfaceInfo->State.IsActive = true;
+
+ return MS_ENUMERROR_NoError;
+}
+
+static uint8_t DCOMP_MS_Host_NextMSInterface(void* const CurrentDescriptor)
+{
+ USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
+
+ if (Header->Type == DTYPE_Interface)
+ {
+ USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
+
+ if ((Interface->Class == MS_CSCP_MassStorageClass) &&
+ (Interface->SubClass == MS_CSCP_SCSITransparentSubclass) &&
+ (Interface->Protocol == MS_CSCP_BulkOnlyTransportProtocol))
+ {
+ return DESCRIPTOR_SEARCH_Found;
+ }
+ }
+
+ return DESCRIPTOR_SEARCH_NotFound;
+}
+
+static uint8_t DCOMP_MS_Host_NextMSInterfaceEndpoint(void* const CurrentDescriptor)
+{
+ USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
+
+ if (Header->Type == DTYPE_Endpoint)
+ {
+ USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
+
+ uint8_t EndpointType = (Endpoint->Attributes & EP_TYPE_MASK);
+
+ if ((EndpointType == EP_TYPE_BULK) && (!(Pipe_IsEndpointBound(Endpoint->EndpointAddress))))
+ {
+ return DESCRIPTOR_SEARCH_Found;
+ }
+ }
+ else if (Header->Type == DTYPE_Interface)
+ {
+ return DESCRIPTOR_SEARCH_Fail;
+ }
+
+ return DESCRIPTOR_SEARCH_NotFound;
+}
+
+static uint8_t MS_Host_SendCommand(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
+ MS_CommandBlockWrapper_t* const SCSICommandBlock,
+ const void* const BufferPtr)
+{
+ uint8_t ErrorCode = PIPE_RWSTREAM_NoError;
+
+ if (++MSInterfaceInfo->State.TransactionTag == 0xFFFFFFFF)
+ MSInterfaceInfo->State.TransactionTag = 1;
+
+ SCSICommandBlock->Signature = CPU_TO_LE32(MS_CBW_SIGNATURE);
+ SCSICommandBlock->Tag = cpu_to_le32(MSInterfaceInfo->State.TransactionTag);
+
+ Pipe_SelectPipe(MSInterfaceInfo->Config.DataOUTPipe.Address);
+ Pipe_Unfreeze();
+
+ if ((ErrorCode = Pipe_Write_Stream_LE(SCSICommandBlock, sizeof(MS_CommandBlockWrapper_t),
+ NULL)) != PIPE_RWSTREAM_NoError)
+ {
+ return ErrorCode;
+ }
+
+ Pipe_ClearOUT();
+ Pipe_WaitUntilReady();
+
+ Pipe_Freeze();
+
+ if (BufferPtr != NULL)
+ {
+ ErrorCode = MS_Host_SendReceiveData(MSInterfaceInfo, SCSICommandBlock, (void*)BufferPtr);
+
+ if ((ErrorCode != PIPE_RWSTREAM_NoError) && (ErrorCode != PIPE_RWSTREAM_PipeStalled))
+ {
+ Pipe_Freeze();
+ return ErrorCode;
+ }
+ }
+
+ MS_CommandStatusWrapper_t SCSIStatusBlock;
+ return MS_Host_GetReturnedStatus(MSInterfaceInfo, &SCSIStatusBlock);
+}
+
+static uint8_t MS_Host_WaitForDataReceived(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo)
+{
+ uint16_t TimeoutMSRem = MS_COMMAND_DATA_TIMEOUT_MS;
+ uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber();
+
+ Pipe_SelectPipe(MSInterfaceInfo->Config.DataINPipe.Address);
+ Pipe_Unfreeze();
+
+ while (!(Pipe_IsINReceived()))
+ {
+ uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber();
+
+ if (CurrentFrameNumber != PreviousFrameNumber)
+ {
+ PreviousFrameNumber = CurrentFrameNumber;
+
+ if (!(TimeoutMSRem--))
+ return PIPE_RWSTREAM_Timeout;
+ }
+
+ Pipe_Freeze();
+ Pipe_SelectPipe(MSInterfaceInfo->Config.DataOUTPipe.Address);
+ Pipe_Unfreeze();
+
+ if (Pipe_IsStalled())
+ {
+ USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress());
+ return PIPE_RWSTREAM_PipeStalled;
+ }
+
+ Pipe_Freeze();
+ Pipe_SelectPipe(MSInterfaceInfo->Config.DataINPipe.Address);
+ Pipe_Unfreeze();
+
+ if (Pipe_IsStalled())
+ {
+ USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress());
+ return PIPE_RWSTREAM_PipeStalled;
+ }
+
+ if (USB_HostState == HOST_STATE_Unattached)
+ return PIPE_RWSTREAM_DeviceDisconnected;
+ };
+
+ Pipe_SelectPipe(MSInterfaceInfo->Config.DataINPipe.Address);
+ Pipe_Freeze();
+
+ Pipe_SelectPipe(MSInterfaceInfo->Config.DataOUTPipe.Address);
+ Pipe_Freeze();
+
+ return PIPE_RWSTREAM_NoError;
+}
+
+static uint8_t MS_Host_SendReceiveData(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
+ MS_CommandBlockWrapper_t* const SCSICommandBlock,
+ void* BufferPtr)
+{
+ uint8_t ErrorCode = PIPE_RWSTREAM_NoError;
+ uint16_t BytesRem = le32_to_cpu(SCSICommandBlock->DataTransferLength);
+
+ if (SCSICommandBlock->Flags & MS_COMMAND_DIR_DATA_IN)
+ {
+ if ((ErrorCode = MS_Host_WaitForDataReceived(MSInterfaceInfo)) != PIPE_RWSTREAM_NoError)
+ {
+ Pipe_Freeze();
+ return ErrorCode;
+ }
+
+ Pipe_SelectPipe(MSInterfaceInfo->Config.DataINPipe.Address);
+ Pipe_Unfreeze();
+
+ if ((ErrorCode = Pipe_Read_Stream_LE(BufferPtr, BytesRem, NULL)) != PIPE_RWSTREAM_NoError)
+ return ErrorCode;
+
+ Pipe_ClearIN();
+ }
+ else
+ {
+ Pipe_SelectPipe(MSInterfaceInfo->Config.DataOUTPipe.Address);
+ Pipe_Unfreeze();
+
+ if ((ErrorCode = Pipe_Write_Stream_LE(BufferPtr, BytesRem, NULL)) != PIPE_RWSTREAM_NoError)
+ return ErrorCode;
+
+ Pipe_ClearOUT();
+
+ while (!(Pipe_IsOUTReady()))
+ {
+ if (USB_HostState == HOST_STATE_Unattached)
+ return PIPE_RWSTREAM_DeviceDisconnected;
+ }
+ }
+
+ Pipe_Freeze();
+
+ return ErrorCode;
+}
+
+static uint8_t MS_Host_GetReturnedStatus(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
+ MS_CommandStatusWrapper_t* const SCSICommandStatus)
+{
+ uint8_t ErrorCode = PIPE_RWSTREAM_NoError;
+
+ if ((ErrorCode = MS_Host_WaitForDataReceived(MSInterfaceInfo)) != PIPE_RWSTREAM_NoError)
+ return ErrorCode;
+
+ Pipe_SelectPipe(MSInterfaceInfo->Config.DataINPipe.Address);
+ Pipe_Unfreeze();
+
+ if ((ErrorCode = Pipe_Read_Stream_LE(SCSICommandStatus, sizeof(MS_CommandStatusWrapper_t),
+ NULL)) != PIPE_RWSTREAM_NoError)
+ {
+ return ErrorCode;
+ }
+
+ Pipe_ClearIN();
+ Pipe_Freeze();
+
+ if (SCSICommandStatus->Status != MS_SCSI_COMMAND_Pass)
+ ErrorCode = MS_ERROR_LOGICAL_CMD_FAILED;
+
+ return ErrorCode;
+}
+
+uint8_t MS_Host_ResetMSInterface(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo)
+{
+ uint8_t ErrorCode;
+
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
+ .bRequest = MS_REQ_MassStorageReset,
+ .wValue = 0,
+ .wIndex = MSInterfaceInfo->State.InterfaceNumber,
+ .wLength = 0,
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+
+ if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
+ return ErrorCode;
+
+ Pipe_SelectPipe(MSInterfaceInfo->Config.DataINPipe.Address);
+
+ if ((ErrorCode = USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress())) != HOST_SENDCONTROL_Successful)
+ return ErrorCode;
+
+ Pipe_SelectPipe(MSInterfaceInfo->Config.DataOUTPipe.Address);
+
+ if ((ErrorCode = USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress())) != HOST_SENDCONTROL_Successful)
+ return ErrorCode;
+
+ return HOST_SENDCONTROL_Successful;
+}
+
+uint8_t MS_Host_GetMaxLUN(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
+ uint8_t* const MaxLUNIndex)
+{
+ uint8_t ErrorCode;
+
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
+ .bRequest = MS_REQ_GetMaxLUN,
+ .wValue = 0,
+ .wIndex = MSInterfaceInfo->State.InterfaceNumber,
+ .wLength = 1,
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+
+ if ((ErrorCode = USB_Host_SendControlRequest(MaxLUNIndex)) == HOST_SENDCONTROL_SetupStalled)
+ {
+ *MaxLUNIndex = 0;
+ ErrorCode = HOST_SENDCONTROL_Successful;
+ }
+
+ return ErrorCode;
+}
+
+uint8_t MS_Host_GetInquiryData(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
+ const uint8_t LUNIndex,
+ SCSI_Inquiry_Response_t* const InquiryData)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(MSInterfaceInfo->State.IsActive))
+ return HOST_SENDCONTROL_DeviceDisconnected;
+
+ MS_CommandBlockWrapper_t SCSICommandBlock = (MS_CommandBlockWrapper_t)
+ {
+ .DataTransferLength = CPU_TO_LE32(sizeof(SCSI_Inquiry_Response_t)),
+ .Flags = MS_COMMAND_DIR_DATA_IN,
+ .LUN = LUNIndex,
+ .SCSICommandLength = 6,
+ .SCSICommandData =
+ {
+ SCSI_CMD_INQUIRY,
+ 0x00, // Reserved
+ 0x00, // Reserved
+ 0x00, // Reserved
+ sizeof(SCSI_Inquiry_Response_t), // Allocation Length
+ 0x00 // Unused (control)
+ }
+ };
+
+ return MS_Host_SendCommand(MSInterfaceInfo, &SCSICommandBlock, InquiryData);
+}
+
+uint8_t MS_Host_TestUnitReady(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
+ const uint8_t LUNIndex)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(MSInterfaceInfo->State.IsActive))
+ return HOST_SENDCONTROL_DeviceDisconnected;
+
+ MS_CommandBlockWrapper_t SCSICommandBlock = (MS_CommandBlockWrapper_t)
+ {
+ .DataTransferLength = CPU_TO_LE32(0),
+ .Flags = MS_COMMAND_DIR_DATA_IN,
+ .LUN = LUNIndex,
+ .SCSICommandLength = 6,
+ .SCSICommandData =
+ {
+ SCSI_CMD_TEST_UNIT_READY,
+ 0x00, // Reserved
+ 0x00, // Reserved
+ 0x00, // Reserved
+ 0x00, // Reserved
+ 0x00 // Unused (control)
+ }
+ };
+
+ return MS_Host_SendCommand(MSInterfaceInfo, &SCSICommandBlock, NULL);
+}
+
+uint8_t MS_Host_ReadDeviceCapacity(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
+ const uint8_t LUNIndex,
+ SCSI_Capacity_t* const DeviceCapacity)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(MSInterfaceInfo->State.IsActive))
+ return HOST_SENDCONTROL_DeviceDisconnected;
+
+ uint8_t ErrorCode;
+
+ MS_CommandBlockWrapper_t SCSICommandBlock = (MS_CommandBlockWrapper_t)
+ {
+ .DataTransferLength = CPU_TO_LE32(sizeof(SCSI_Capacity_t)),
+ .Flags = MS_COMMAND_DIR_DATA_IN,
+ .LUN = LUNIndex,
+ .SCSICommandLength = 10,
+ .SCSICommandData =
+ {
+ SCSI_CMD_READ_CAPACITY_10,
+ 0x00, // Reserved
+ 0x00, // MSB of Logical block address
+ 0x00,
+ 0x00,
+ 0x00, // LSB of Logical block address
+ 0x00, // Reserved
+ 0x00, // Reserved
+ 0x00, // Partial Medium Indicator
+ 0x00 // Unused (control)
+ }
+ };
+
+ if ((ErrorCode = MS_Host_SendCommand(MSInterfaceInfo, &SCSICommandBlock, DeviceCapacity)) != PIPE_RWSTREAM_NoError)
+ return ErrorCode;
+
+ DeviceCapacity->Blocks = BE32_TO_CPU(DeviceCapacity->Blocks);
+ DeviceCapacity->BlockSize = BE32_TO_CPU(DeviceCapacity->BlockSize);
+
+ return PIPE_RWSTREAM_NoError;
+}
+
+uint8_t MS_Host_RequestSense(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
+ const uint8_t LUNIndex,
+ SCSI_Request_Sense_Response_t* const SenseData)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(MSInterfaceInfo->State.IsActive))
+ return HOST_SENDCONTROL_DeviceDisconnected;
+
+ MS_CommandBlockWrapper_t SCSICommandBlock = (MS_CommandBlockWrapper_t)
+ {
+ .DataTransferLength = CPU_TO_LE32(sizeof(SCSI_Request_Sense_Response_t)),
+ .Flags = MS_COMMAND_DIR_DATA_IN,
+ .LUN = LUNIndex,
+ .SCSICommandLength = 6,
+ .SCSICommandData =
+ {
+ SCSI_CMD_REQUEST_SENSE,
+ 0x00, // Reserved
+ 0x00, // Reserved
+ 0x00, // Reserved
+ sizeof(SCSI_Request_Sense_Response_t), // Allocation Length
+ 0x00 // Unused (control)
+ }
+ };
+
+ return MS_Host_SendCommand(MSInterfaceInfo, &SCSICommandBlock, SenseData);
+}
+
+uint8_t MS_Host_PreventAllowMediumRemoval(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
+ const uint8_t LUNIndex,
+ const bool PreventRemoval)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(MSInterfaceInfo->State.IsActive))
+ return HOST_SENDCONTROL_DeviceDisconnected;
+
+ MS_CommandBlockWrapper_t SCSICommandBlock = (MS_CommandBlockWrapper_t)
+ {
+ .DataTransferLength = CPU_TO_LE32(0),
+ .Flags = MS_COMMAND_DIR_DATA_OUT,
+ .LUN = LUNIndex,
+ .SCSICommandLength = 6,
+ .SCSICommandData =
+ {
+ SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL,
+ 0x00, // Reserved
+ 0x00, // Reserved
+ PreventRemoval, // Prevent flag
+ 0x00, // Reserved
+ 0x00 // Unused (control)
+ }
+ };
+
+ return MS_Host_SendCommand(MSInterfaceInfo, &SCSICommandBlock, NULL);
+}
+
+uint8_t MS_Host_ReadDeviceBlocks(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
+ const uint8_t LUNIndex,
+ const uint32_t BlockAddress,
+ const uint8_t Blocks,
+ const uint16_t BlockSize,
+ void* BlockBuffer)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(MSInterfaceInfo->State.IsActive))
+ return HOST_SENDCONTROL_DeviceDisconnected;
+
+ MS_CommandBlockWrapper_t SCSICommandBlock = (MS_CommandBlockWrapper_t)
+ {
+ .DataTransferLength = cpu_to_le32((uint32_t)Blocks * BlockSize),
+ .Flags = MS_COMMAND_DIR_DATA_IN,
+ .LUN = LUNIndex,
+ .SCSICommandLength = 10,
+ .SCSICommandData =
+ {
+ SCSI_CMD_READ_10,
+ 0x00, // Unused (control bits, all off)
+ (BlockAddress >> 24), // MSB of Block Address
+ (BlockAddress >> 16),
+ (BlockAddress >> 8),
+ (BlockAddress & 0xFF), // LSB of Block Address
+ 0x00, // Reserved
+ 0x00, // MSB of Total Blocks to Read
+ Blocks, // LSB of Total Blocks to Read
+ 0x00 // Unused (control)
+ }
+ };
+
+ return MS_Host_SendCommand(MSInterfaceInfo, &SCSICommandBlock, BlockBuffer);
+}
+
+uint8_t MS_Host_WriteDeviceBlocks(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
+ const uint8_t LUNIndex,
+ const uint32_t BlockAddress,
+ const uint8_t Blocks,
+ const uint16_t BlockSize,
+ const void* BlockBuffer)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(MSInterfaceInfo->State.IsActive))
+ return HOST_SENDCONTROL_DeviceDisconnected;
+
+ MS_CommandBlockWrapper_t SCSICommandBlock = (MS_CommandBlockWrapper_t)
+ {
+ .DataTransferLength = cpu_to_le32((uint32_t)Blocks * BlockSize),
+ .Flags = MS_COMMAND_DIR_DATA_OUT,
+ .LUN = LUNIndex,
+ .SCSICommandLength = 10,
+ .SCSICommandData =
+ {
+ SCSI_CMD_WRITE_10,
+ 0x00, // Unused (control bits, all off)
+ (BlockAddress >> 24), // MSB of Block Address
+ (BlockAddress >> 16),
+ (BlockAddress >> 8),
+ (BlockAddress & 0xFF), // LSB of Block Address
+ 0x00, // Reserved
+ 0x00, // MSB of Total Blocks to Write
+ Blocks, // LSB of Total Blocks to Write
+ 0x00 // Unused (control)
+ }
+ };
+
+ return MS_Host_SendCommand(MSInterfaceInfo, &SCSICommandBlock, BlockBuffer);
+}
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/MassStorageClassHost.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/MassStorageClassHost.h
new file mode 100644
index 000000000..6e558073b
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/MassStorageClassHost.h
@@ -0,0 +1,335 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Host mode driver for the library USB Mass Storage Class driver.
+ *
+ * Host mode driver for the library USB Mass Storage Class driver.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB module driver
+ * dispatch header located in LUFA/Drivers/USB.h.
+ */
+
+/** \ingroup Group_USBClassMS
+ * \defgroup Group_USBClassMassStorageHost Mass Storage Class Host Mode Driver
+ *
+ * \section Sec_USBClassMassStorageHost_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Drivers/USB/Class/Host/MassStorageClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ *
+ * \section Sec_USBClassMassStorageHost_ModDescription Module Description
+ * Host Mode USB Class driver framework interface, for the Mass Storage USB Class driver.
+ *
+ * @{
+ */
+
+#ifndef __MS_CLASS_HOST_H__
+#define __MS_CLASS_HOST_H__
+
+ /* Includes: */
+ #include "../../USB.h"
+ #include "../Common/MassStorageClassCommon.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_MS_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Error code for some Mass Storage Host functions, indicating a logical (and not hardware) error. */
+ #define MS_ERROR_LOGICAL_CMD_FAILED 0x80
+
+ /* Type Defines: */
+ /** \brief Mass Storage Class Host Mode Configuration and State Structure.
+ *
+ * Class state structure. An instance of this structure should be made within the user application,
+ * and passed to each of the Mass Storage class driver functions as the \c MSInterfaceInfo parameter. This
+ * stores each Mass Storage interface's configuration and state information.
+ */
+ typedef struct
+ {
+ struct
+ {
+ USB_Pipe_Table_t DataINPipe; /**< Data IN Pipe configuration table. */
+ USB_Pipe_Table_t DataOUTPipe; /**< Data OUT Pipe configuration table. */
+ } Config; /**< Config data for the USB class interface within the device. All elements in this section
+ * <b>must</b> be set or the interface will fail to enumerate and operate correctly.
+ */
+ struct
+ {
+ bool IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
+ * after \ref MS_Host_ConfigurePipes() is called and the Host state machine is in the
+ * Configured state.
+ */
+ uint8_t InterfaceNumber; /**< Interface index of the Mass Storage interface within the attached device. */
+
+ uint32_t TransactionTag; /**< Current transaction tag for data synchronizing of packets. */
+ } State; /**< State data for the USB class interface within the device. All elements in this section
+ * <b>may</b> be set to initial values, but may also be ignored to default to sane values when
+ * the interface is enumerated.
+ */
+ } USB_ClassInfo_MS_Host_t;
+
+ /** \brief SCSI Device LUN Capacity Structure.
+ *
+ * SCSI capacity structure, to hold the total capacity of the device in both the number
+ * of blocks in the current LUN, and the size of each block. This structure is filled by
+ * the device when the \ref MS_Host_ReadDeviceCapacity() function is called.
+ */
+ typedef struct
+ {
+ uint32_t Blocks; /**< Number of blocks in the addressed LUN of the device. */
+ uint32_t BlockSize; /**< Number of bytes in each block in the addressed LUN. */
+ } SCSI_Capacity_t;
+
+ /* Enums: */
+ /** Enum for the possible error codes returned by the \ref MS_Host_ConfigurePipes() function. */
+ enum MS_Host_EnumerationFailure_ErrorCodes_t
+ {
+ MS_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */
+ MS_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */
+ MS_ENUMERROR_NoCompatibleInterfaceFound = 2, /**< A compatible Mass Storage interface was not found in the device's Configuration Descriptor. */
+ MS_ENUMERROR_PipeConfigurationFailed = 3, /**< One or more pipes for the specified interface could not be configured correctly. */
+ };
+
+ /* Function Prototypes: */
+ /** Host interface configuration routine, to configure a given Mass Storage host interface instance using the
+ * Configuration Descriptor read from an attached USB device. This function automatically updates the given Mass
+ * Storage Host instance's state values and configures the pipes required to communicate with the interface if it
+ * is found within the device. This should be called once after the stack has enumerated the attached device, while
+ * the host state machine is in the Addressed state.
+ *
+ * \param[in,out] MSInterfaceInfo Pointer to a structure containing an MS Class host configuration and state.
+ * \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor.
+ * \param[in] DeviceConfigDescriptor Pointer to a buffer containing the attached device's Configuration Descriptor.
+ *
+ * \return A value from the \ref MS_Host_EnumerationFailure_ErrorCodes_t enum.
+ */
+ uint8_t MS_Host_ConfigurePipes(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
+ uint16_t ConfigDescriptorSize,
+ void* DeviceConfigDescriptor) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
+
+ /** Sends a MASS STORAGE RESET control request to the attached device, resetting the Mass Storage Interface
+ * and readying it for the next Mass Storage command. This should be called after a failed SCSI request to
+ * ensure the attached Mass Storage device is ready to receive the next command.
+ *
+ * \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state.
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum.
+ */
+ uint8_t MS_Host_ResetMSInterface(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Sends a GET MAX LUN control request to the attached device, retrieving the index of the highest LUN (Logical
+ * UNit, a logical drive) in the device. This value can then be used in the other functions of the Mass Storage
+ * Host mode Class driver to address a specific LUN within the device.
+ *
+ * \note Some devices do not support this request, and will STALL it when issued. To get around this,
+ * on unsupported devices the max LUN index will be reported as zero and no error will be returned
+ * if the device STALLs the request.
+ *
+ * \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state.
+ * \param[out] MaxLUNIndex Pointer to a location where the highest LUN index value should be stored.
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum.
+ */
+ uint8_t MS_Host_GetMaxLUN(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
+ uint8_t* const MaxLUNIndex) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+
+ /** Retrieves the Mass Storage device's inquiry data for the specified LUN, indicating the device characteristics and
+ * properties.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state.
+ * \param[in] LUNIndex LUN index within the device the command is being issued to.
+ * \param[out] InquiryData Location where the read inquiry data should be stored.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or \ref MS_ERROR_LOGICAL_CMD_FAILED.
+ */
+ uint8_t MS_Host_GetInquiryData(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
+ const uint8_t LUNIndex,
+ SCSI_Inquiry_Response_t* const InquiryData) ATTR_NON_NULL_PTR_ARG(1)
+ ATTR_NON_NULL_PTR_ARG(3);
+
+ /** Sends a TEST UNIT READY command to the device, to determine if it is ready to accept other SCSI commands.
+ *
+ * \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state.
+ * \param[in] LUNIndex LUN index within the device the command is being issued to.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or \ref MS_ERROR_LOGICAL_CMD_FAILED if not ready.
+ */
+ uint8_t MS_Host_TestUnitReady(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
+ const uint8_t LUNIndex) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Retrieves the total capacity of the attached USB Mass Storage device, in blocks, and block size.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state.
+ * \param[in] LUNIndex LUN index within the device the command is being issued to.
+ * \param[out] DeviceCapacity Pointer to the location where the capacity information should be stored.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or \ref MS_ERROR_LOGICAL_CMD_FAILED if not ready.
+ */
+ uint8_t MS_Host_ReadDeviceCapacity(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
+ const uint8_t LUNIndex,
+ SCSI_Capacity_t* const DeviceCapacity) ATTR_NON_NULL_PTR_ARG(1)
+ ATTR_NON_NULL_PTR_ARG(3);
+
+ /** Retrieves the device sense data, indicating the current device state and error codes for the previously
+ * issued command.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state.
+ * \param[in] LUNIndex LUN index within the device the command is being issued to.
+ * \param[out] SenseData Pointer to the location where the sense information should be stored.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or \ref MS_ERROR_LOGICAL_CMD_FAILED if not ready.
+ */
+ uint8_t MS_Host_RequestSense(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
+ const uint8_t LUNIndex,
+ SCSI_Request_Sense_Response_t* const SenseData) ATTR_NON_NULL_PTR_ARG(1)
+ ATTR_NON_NULL_PTR_ARG(3);
+
+ /** Issues a PREVENT MEDIUM REMOVAL command, to logically (or, depending on the type of device, physically) lock
+ * the device from removal so that blocks of data on the medium can be read or altered.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state.
+ * \param[in] LUNIndex LUN index within the device the command is being issued to.
+ * \param[in] PreventRemoval Boolean \c true if the device should be locked from removal, \c false otherwise.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or \ref MS_ERROR_LOGICAL_CMD_FAILED if not ready.
+ */
+ uint8_t MS_Host_PreventAllowMediumRemoval(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
+ const uint8_t LUNIndex,
+ const bool PreventRemoval) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Reads blocks of data from the attached Mass Storage device's medium.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state.
+ * \param[in] LUNIndex LUN index within the device the command is being issued to.
+ * \param[in] BlockAddress Starting block address within the device to read from.
+ * \param[in] Blocks Total number of blocks to read.
+ * \param[in] BlockSize Size in bytes of each block within the device.
+ * \param[out] BlockBuffer Pointer to where the read data from the device should be stored.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or \ref MS_ERROR_LOGICAL_CMD_FAILED if not ready.
+ */
+ uint8_t MS_Host_ReadDeviceBlocks(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
+ const uint8_t LUNIndex,
+ const uint32_t BlockAddress,
+ const uint8_t Blocks,
+ const uint16_t BlockSize,
+ void* BlockBuffer) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(6);
+
+ /** Writes blocks of data to the attached Mass Storage device's medium.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] MSInterfaceInfo Pointer to a structure containing a MS Class host configuration and state.
+ * \param[in] LUNIndex LUN index within the device the command is being issued to.
+ * \param[in] BlockAddress Starting block address within the device to write to.
+ * \param[in] Blocks Total number of blocks to read.
+ * \param[in] BlockSize Size in bytes of each block within the device.
+ * \param[in] BlockBuffer Pointer to where the data to write should be sourced from.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or \ref MS_ERROR_LOGICAL_CMD_FAILED if not ready.
+ */
+ uint8_t MS_Host_WriteDeviceBlocks(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
+ const uint8_t LUNIndex,
+ const uint32_t BlockAddress,
+ const uint8_t Blocks,
+ const uint16_t BlockSize,
+ const void* BlockBuffer) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(6);
+
+ /* Inline Functions: */
+ /** General management task for a given Mass Storage host class interface, required for the correct operation of
+ * the interface. This should be called frequently in the main program loop, before the master USB management task
+ * \ref USB_USBTask().
+ *
+ * \param[in,out] MSInterfaceInfo Pointer to a structure containing an Mass Storage Class host configuration and state.
+ */
+ static inline void MS_Host_USBTask(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
+ static inline void MS_Host_USBTask(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo)
+ {
+ (void)MSInterfaceInfo;
+ }
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define MS_COMMAND_DATA_TIMEOUT_MS 10000
+
+ /* Function Prototypes: */
+ #if defined(__INCLUDE_FROM_MASSSTORAGE_HOST_C)
+ static uint8_t MS_Host_SendCommand(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
+ MS_CommandBlockWrapper_t* const SCSICommandBlock,
+ const void* const BufferPtr) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+ static uint8_t MS_Host_WaitForDataReceived(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+ static uint8_t MS_Host_SendReceiveData(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
+ MS_CommandBlockWrapper_t* const SCSICommandBlock,
+ void* BufferPtr) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+ static uint8_t MS_Host_GetReturnedStatus(USB_ClassInfo_MS_Host_t* const MSInterfaceInfo,
+ MS_CommandStatusWrapper_t* const SCSICommandStatus)
+ ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+
+ static uint8_t DCOMP_MS_Host_NextMSInterface(void* const CurrentDescriptor)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ static uint8_t DCOMP_MS_Host_NextMSInterfaceEndpoint(void* const CurrentDescriptor)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ #endif
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/PrinterClassHost.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/PrinterClassHost.c
new file mode 100644
index 000000000..fd32e1c28
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/PrinterClassHost.c
@@ -0,0 +1,400 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../../Core/USBMode.h"
+
+#if defined(USB_CAN_BE_HOST)
+
+#define __INCLUDE_FROM_PRINTER_DRIVER
+#define __INCLUDE_FROM_PRINTER_HOST_C
+#include "PrinterClassHost.h"
+
+uint8_t PRNT_Host_ConfigurePipes(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
+ uint16_t ConfigDescriptorSize,
+ void* ConfigDescriptorData)
+{
+ USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
+ USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
+ USB_Descriptor_Interface_t* PrinterInterface = NULL;
+
+ memset(&PRNTInterfaceInfo->State, 0x00, sizeof(PRNTInterfaceInfo->State));
+
+ if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
+ return PRNT_ENUMERROR_InvalidConfigDescriptor;
+
+ while (!(DataINEndpoint) || !(DataOUTEndpoint))
+ {
+ if (!(PrinterInterface) ||
+ USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+ DCOMP_PRNT_Host_NextPRNTInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
+ {
+ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+ DCOMP_PRNT_Host_NextPRNTInterface) != DESCRIPTOR_SEARCH_COMP_Found)
+ {
+ return PRNT_ENUMERROR_NoCompatibleInterfaceFound;
+ }
+
+ PrinterInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
+
+ DataINEndpoint = NULL;
+ DataOUTEndpoint = NULL;
+
+ continue;
+ }
+
+ USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
+
+ if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN)
+ DataINEndpoint = EndpointData;
+ else
+ DataOUTEndpoint = EndpointData;
+ }
+
+ PRNTInterfaceInfo->Config.DataINPipe.Size = le16_to_cpu(DataINEndpoint->EndpointSize);
+ PRNTInterfaceInfo->Config.DataINPipe.EndpointAddress = DataINEndpoint->EndpointAddress;
+ PRNTInterfaceInfo->Config.DataINPipe.Type = EP_TYPE_BULK;
+
+ PRNTInterfaceInfo->Config.DataOUTPipe.Size = le16_to_cpu(DataOUTEndpoint->EndpointSize);
+ PRNTInterfaceInfo->Config.DataOUTPipe.EndpointAddress = DataOUTEndpoint->EndpointAddress;
+ PRNTInterfaceInfo->Config.DataOUTPipe.Type = EP_TYPE_BULK;
+
+ if (!(Pipe_ConfigurePipeTable(&PRNTInterfaceInfo->Config.DataINPipe, 1)))
+ return PRNT_ENUMERROR_PipeConfigurationFailed;
+
+ if (!(Pipe_ConfigurePipeTable(&PRNTInterfaceInfo->Config.DataOUTPipe, 1)))
+ return PRNT_ENUMERROR_PipeConfigurationFailed;
+
+ PRNTInterfaceInfo->State.InterfaceNumber = PrinterInterface->InterfaceNumber;
+ PRNTInterfaceInfo->State.AlternateSetting = PrinterInterface->AlternateSetting;
+ PRNTInterfaceInfo->State.IsActive = true;
+
+ return PRNT_ENUMERROR_NoError;
+}
+
+static uint8_t DCOMP_PRNT_Host_NextPRNTInterface(void* CurrentDescriptor)
+{
+ USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
+
+ if (Header->Type == DTYPE_Interface)
+ {
+ USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
+
+ if ((Interface->Class == PRNT_CSCP_PrinterClass) &&
+ (Interface->SubClass == PRNT_CSCP_PrinterSubclass) &&
+ (Interface->Protocol == PRNT_CSCP_BidirectionalProtocol))
+ {
+ return DESCRIPTOR_SEARCH_Found;
+ }
+ }
+
+ return DESCRIPTOR_SEARCH_NotFound;
+}
+
+static uint8_t DCOMP_PRNT_Host_NextPRNTInterfaceEndpoint(void* CurrentDescriptor)
+{
+ USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
+
+ if (Header->Type == DTYPE_Endpoint)
+ {
+ USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
+
+ uint8_t EndpointType = (Endpoint->Attributes & EP_TYPE_MASK);
+
+ if (EndpointType == EP_TYPE_BULK)
+ return DESCRIPTOR_SEARCH_Found;
+ }
+ else if (Header->Type == DTYPE_Interface)
+ {
+ return DESCRIPTOR_SEARCH_Fail;
+ }
+
+ return DESCRIPTOR_SEARCH_NotFound;
+}
+
+void PRNT_Host_USBTask(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
+ return;
+
+ #if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
+ PRNT_Host_Flush(PRNTInterfaceInfo);
+ #endif
+}
+
+uint8_t PRNT_Host_SetBidirectionalMode(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
+{
+ if (PRNTInterfaceInfo->State.AlternateSetting)
+ {
+ uint8_t ErrorCode;
+
+ if ((ErrorCode = USB_Host_SetInterfaceAltSetting(PRNTInterfaceInfo->State.InterfaceNumber,
+ PRNTInterfaceInfo->State.AlternateSetting)) != HOST_SENDCONTROL_Successful)
+ {
+ return ErrorCode;
+ }
+ }
+
+ return HOST_SENDCONTROL_Successful;
+}
+
+uint8_t PRNT_Host_GetPortStatus(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
+ uint8_t* const PortStatus)
+{
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
+ .bRequest = PRNT_REQ_GetPortStatus,
+ .wValue = 0,
+ .wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
+ .wLength = sizeof(uint8_t),
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+ return USB_Host_SendControlRequest(PortStatus);
+}
+
+uint8_t PRNT_Host_SoftReset(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
+{
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
+ .bRequest = PRNT_REQ_SoftReset,
+ .wValue = 0,
+ .wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
+ .wLength = 0,
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+ return USB_Host_SendControlRequest(NULL);
+}
+
+uint8_t PRNT_Host_Flush(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
+ return PIPE_READYWAIT_DeviceDisconnected;
+
+ uint8_t ErrorCode;
+
+ Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipe.Address);
+ Pipe_Unfreeze();
+
+ if (!(Pipe_BytesInPipe()))
+ return PIPE_READYWAIT_NoError;
+
+ bool BankFull = !(Pipe_IsReadWriteAllowed());
+
+ Pipe_ClearOUT();
+
+ if (BankFull)
+ {
+ if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
+ return ErrorCode;
+
+ Pipe_ClearOUT();
+ }
+
+ Pipe_Freeze();
+
+ return PIPE_READYWAIT_NoError;
+}
+
+uint8_t PRNT_Host_SendByte(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
+ const uint8_t Data)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
+ return PIPE_READYWAIT_DeviceDisconnected;
+
+ uint8_t ErrorCode;
+
+ Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipe.Address);
+ Pipe_Unfreeze();
+
+ if (!(Pipe_IsReadWriteAllowed()))
+ {
+ Pipe_ClearOUT();
+
+ if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
+ return ErrorCode;
+ }
+
+ Pipe_Write_8(Data);
+ Pipe_Freeze();
+
+ return PIPE_READYWAIT_NoError;
+}
+
+uint8_t PRNT_Host_SendString(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
+ const char* const String)
+{
+ uint8_t ErrorCode;
+
+ if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
+ return PIPE_RWSTREAM_DeviceDisconnected;
+
+ Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipe.Address);
+ Pipe_Unfreeze();
+
+ if ((ErrorCode = Pipe_Write_Stream_LE(String, strlen(String), NULL)) != PIPE_RWSTREAM_NoError)
+ return ErrorCode;
+
+ Pipe_ClearOUT();
+
+ ErrorCode = Pipe_WaitUntilReady();
+
+ Pipe_Freeze();
+
+ return ErrorCode;
+}
+
+uint8_t PRNT_Host_SendData(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
+ const void* Buffer,
+ const uint16_t Length)
+{
+ uint8_t ErrorCode;
+
+ if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
+ return PIPE_RWSTREAM_DeviceDisconnected;
+
+ Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipe.Address);
+ Pipe_Unfreeze();
+
+ if ((ErrorCode = Pipe_Write_Stream_LE(Buffer, Length, NULL)) != PIPE_RWSTREAM_NoError)
+ return ErrorCode;
+
+ Pipe_ClearOUT();
+
+ ErrorCode = Pipe_WaitUntilReady();
+
+ Pipe_Freeze();
+
+ return ErrorCode;
+}
+
+uint16_t PRNT_Host_BytesReceived(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
+ return 0;
+
+ Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataINPipe.Address);
+ Pipe_Unfreeze();
+
+ if (Pipe_IsINReceived())
+ {
+ if (!(Pipe_BytesInPipe()))
+ {
+ Pipe_ClearIN();
+ Pipe_Freeze();
+ return 0;
+ }
+ else
+ {
+ Pipe_Freeze();
+ return Pipe_BytesInPipe();
+ }
+ }
+ else
+ {
+ Pipe_Freeze();
+
+ return 0;
+ }
+}
+
+int16_t PRNT_Host_ReceiveByte(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
+ return PIPE_RWSTREAM_DeviceDisconnected;
+
+ int16_t ReceivedByte = -1;
+
+ Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataINPipe.Address);
+ Pipe_Unfreeze();
+
+ if (Pipe_IsINReceived())
+ {
+ if (Pipe_BytesInPipe())
+ ReceivedByte = Pipe_Read_8();
+
+ if (!(Pipe_BytesInPipe()))
+ Pipe_ClearIN();
+ }
+
+ Pipe_Freeze();
+
+ return ReceivedByte;
+}
+
+uint8_t PRNT_Host_GetDeviceID(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
+ char* const DeviceIDString,
+ const uint16_t BufferSize)
+{
+ uint8_t ErrorCode;
+ uint16_t DeviceIDStringLength = 0;
+
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
+ .bRequest = PRNT_REQ_GetDeviceID,
+ .wValue = 0,
+ .wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
+ .wLength = sizeof(DeviceIDStringLength),
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+
+ if ((ErrorCode = USB_Host_SendControlRequest(&DeviceIDStringLength)) != HOST_SENDCONTROL_Successful)
+ return ErrorCode;
+
+ if (!(DeviceIDStringLength))
+ {
+ DeviceIDString[0] = 0x00;
+ return HOST_SENDCONTROL_Successful;
+ }
+
+ DeviceIDStringLength = be16_to_cpu(DeviceIDStringLength);
+
+ if (DeviceIDStringLength > BufferSize)
+ DeviceIDStringLength = BufferSize;
+
+ USB_ControlRequest.wLength = DeviceIDStringLength;
+
+ if ((ErrorCode = USB_Host_SendControlRequest(DeviceIDString)) != HOST_SENDCONTROL_Successful)
+ return ErrorCode;
+
+ memmove(&DeviceIDString[0], &DeviceIDString[2], DeviceIDStringLength - 2);
+
+ DeviceIDString[DeviceIDStringLength - 2] = 0x00;
+
+ return HOST_SENDCONTROL_Successful;
+}
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/PrinterClassHost.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/PrinterClassHost.h
new file mode 100644
index 000000000..8089aa592
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/PrinterClassHost.h
@@ -0,0 +1,285 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Host mode driver for the library USB Printer Class driver.
+ *
+ * Host mode driver for the library USB Printer Class driver.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB module driver
+ * dispatch header located in LUFA/Drivers/USB.h.
+ */
+
+/** \ingroup Group_USBClassPrinter
+ * \defgroup Group_USBClassPrinterHost Printer Class Host Mode Driver
+ *
+ * \section Sec_USBClassPrinterHost_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Drivers/USB/Class/Host/PrinterClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ *
+ * \section Sec_USBClassPrinterHost_ModDescription Module Description
+ * Host Mode USB Class driver framework interface, for the Printer USB Class driver.
+ *
+ * @{
+ */
+
+#ifndef __PRINTER_CLASS_HOST_H__
+#define __PRINTER_CLASS_HOST_H__
+
+ /* Includes: */
+ #include "../../USB.h"
+ #include "../Common/PrinterClassCommon.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_PRINTER_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Type Defines: */
+ /** \brief Printer Class Host Mode Configuration and State Structure.
+ *
+ * Class state structure. An instance of this structure should be made within the user application,
+ * and passed to each of the Printer class driver functions as the \c PRNTInterfaceInfo parameter. This
+ * stores each Printer interface's configuration and state information.
+ */
+ typedef struct
+ {
+ struct
+ {
+ USB_Pipe_Table_t DataINPipe; /**< Data IN Pipe configuration table. */
+ USB_Pipe_Table_t DataOUTPipe; /**< Data OUT Pipe configuration table. */
+ } Config; /**< Config data for the USB class interface within the device. All elements in this section
+ * <b>must</b> be set or the interface will fail to enumerate and operate correctly.
+ */
+ struct
+ {
+ bool IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
+ * after \ref PRNT_Host_ConfigurePipes() is called and the Host state machine is in the
+ * Configured state.
+ */
+ uint8_t InterfaceNumber; /**< Interface index of the Printer interface within the attached device. */
+ uint8_t AlternateSetting; /**< Alternate setting within the Printer Interface in the attached device. */
+ } State; /**< State data for the USB class interface within the device. All elements in this section
+ * <b>may</b> be set to initial values, but may also be ignored to default to sane values when
+ * the interface is enumerated.
+ */
+ } USB_ClassInfo_PRNT_Host_t;
+
+ /* Enums: */
+ /** Enum for the possible error codes returned by the \ref PRNT_Host_ConfigurePipes() function. */
+ enum PRNT_Host_EnumerationFailure_ErrorCodes_t
+ {
+ PRNT_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */
+ PRNT_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */
+ PRNT_ENUMERROR_NoCompatibleInterfaceFound = 2, /**< A compatible Printer interface was not found in the device's Configuration Descriptor. */
+ PRNT_ENUMERROR_PipeConfigurationFailed = 3, /**< One or more pipes for the specified interface could not be configured correctly. */
+ };
+
+ /* Function Prototypes: */
+ /** Host interface configuration routine, to configure a given Printer host interface instance using the
+ * Configuration Descriptor read from an attached USB device. This function automatically updates the given Printer
+ * instance's state values and configures the pipes required to communicate with the interface if it is found within
+ * the device. This should be called once after the stack has enumerated the attached device, while the host state
+ * machine is in the Addressed state.
+ *
+ * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state.
+ * \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor.
+ * \param[in] ConfigDescriptorData Pointer to a buffer containing the attached device's Configuration Descriptor.
+ *
+ * \return A value from the \ref PRNT_Host_EnumerationFailure_ErrorCodes_t enum.
+ */
+ uint8_t PRNT_Host_ConfigurePipes(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
+ uint16_t ConfigDescriptorSize,
+ void* ConfigDescriptorData) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
+
+ /** General management task for a given Printer host class interface, required for the correct operation of
+ * the interface. This should be called frequently in the main program loop, before the master USB management task
+ * \ref USB_USBTask().
+ *
+ * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state.
+ */
+ void PRNT_Host_USBTask(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Configures the printer to enable Bidirectional mode, if it is not already in this mode. This should be called
+ * once the connected device's configuration has been set, to ensure the printer is ready to accept commands.
+ *
+ * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state.
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum.
+ */
+ uint8_t PRNT_Host_SetBidirectionalMode(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Retrieves the status of the virtual Printer port's inbound status lines. The result can then be masked against the
+ * \c PRNT_PORTSTATUS_* macros to determine the printer port's status.
+ *
+ * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state.
+ * \param[out] PortStatus Location where the retrieved port status should be stored.
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum.
+ */
+ uint8_t PRNT_Host_GetPortStatus(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
+ uint8_t* const PortStatus)
+ ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+
+ /** Soft-resets the attached printer, readying it for new commands.
+ *
+ * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state.
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum.
+ */
+ uint8_t PRNT_Host_SoftReset(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Flushes any data waiting to be sent, ensuring that the send buffer is cleared.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state.
+ *
+ * \return A value from the \ref Pipe_WaitUntilReady_ErrorCodes_t enum.
+ */
+ uint8_t PRNT_Host_Flush(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Sends the given null terminated string to the attached printer's input endpoint.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state.
+ * \param[in] String Pointer to a null terminated string to send.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t PRNT_Host_SendString(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
+ const char* const String) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+
+ /** Sends the given raw data stream to the attached printer's input endpoint. This should contain commands that the
+ * printer is able to understand - for example, PCL data. Not all printers accept all printer languages; see
+ * \ref PRNT_Host_GetDeviceID() for details on determining acceptable languages for an attached printer.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state.
+ * \param[in] Buffer Pointer to a buffer containing the raw command stream to send to the printer.
+ * \param[in] Length Size in bytes of the command stream to be sent.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t PRNT_Host_SendData(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
+ const void* Buffer,
+ const uint16_t Length) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+
+ /** Sends a given byte to the attached USB device, if connected. If a device is not connected when the function is called, the
+ * byte is discarded. Bytes will be queued for transmission to the device until either the pipe bank becomes full, or the
+ * \ref PRNT_Host_Flush() function is called to flush the pending data to the host. This allows for multiple bytes to be
+ * packed into a single pipe packet, increasing data throughput.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state.
+ * \param[in] Data Byte of data to send to the device.
+ *
+ * \return A value from the \ref Pipe_WaitUntilReady_ErrorCodes_t enum.
+ */
+ uint8_t PRNT_Host_SendByte(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
+ const uint8_t Data) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Determines the number of bytes received by the printer interface from the device, waiting to be read. This indicates the number
+ * of bytes in the IN pipe bank only, and thus the number of calls to \ref PRNT_Host_ReceiveByte() which are guaranteed to succeed
+ * immediately. If multiple bytes are to be received, they should be buffered by the user application, as the pipe bank will not be
+ * released back to the USB controller until all bytes are read.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state.
+ *
+ * \return Total number of buffered bytes received from the device.
+ */
+ uint16_t PRNT_Host_BytesReceived(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Reads a byte of data from the device. If no data is waiting to be read of if a USB device is not connected, the function
+ * returns a negative value. The \ref PRNT_Host_BytesReceived() function may be queried in advance to determine how many bytes
+ * are currently buffered in the Printer interface's data receive pipe.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state.
+ *
+ * \return Next received byte from the device, or a negative value if no data received.
+ */
+ int16_t PRNT_Host_ReceiveByte(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Retrieves the attached printer device's ID string, formatted according to IEEE 1284. This string is sent as a
+ * Unicode string from the device and is automatically converted to an ASCII encoded C string by this function, thus
+ * the maximum reportable string length is two less than the size given (to accommodate the Unicode string length
+ * bytes which are removed).
+ *
+ * This string, when supported, contains the model, manufacturer and acceptable printer languages for the attached device.
+ *
+ * \param[in,out] PRNTInterfaceInfo Pointer to a structure containing a Printer Class host configuration and state.
+ * \param[out] DeviceIDString Pointer to a buffer where the Device ID string should be stored, in ASCII format.
+ * \param[in] BufferSize Size in bytes of the buffer allocated for the Device ID string.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t PRNT_Host_GetDeviceID(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
+ char* const DeviceIDString,
+ const uint16_t BufferSize) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Function Prototypes: */
+ #if defined(__INCLUDE_FROM_PRINTER_HOST_C)
+ static uint8_t DCOMP_PRNT_Host_NextPRNTInterface(void* const CurrentDescriptor)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ static uint8_t DCOMP_PRNT_Host_NextPRNTInterfaceEndpoint(void* const CurrentDescriptor)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ #endif
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/RNDISClassHost.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/RNDISClassHost.c
new file mode 100644
index 000000000..3ed51c8d9
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/RNDISClassHost.c
@@ -0,0 +1,476 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../../Core/USBMode.h"
+
+#if defined(USB_CAN_BE_HOST)
+
+#define __INCLUDE_FROM_RNDIS_DRIVER
+#define __INCLUDE_FROM_RNDIS_HOST_C
+#include "RNDISClassHost.h"
+
+uint8_t RNDIS_Host_ConfigurePipes(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
+ uint16_t ConfigDescriptorSize,
+ void* ConfigDescriptorData)
+{
+ USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
+ USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
+ USB_Descriptor_Endpoint_t* NotificationEndpoint = NULL;
+ USB_Descriptor_Interface_t* RNDISControlInterface = NULL;
+
+ memset(&RNDISInterfaceInfo->State, 0x00, sizeof(RNDISInterfaceInfo->State));
+
+ if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
+ return RNDIS_ENUMERROR_InvalidConfigDescriptor;
+
+ RNDISControlInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
+
+ while (!(DataINEndpoint) || !(DataOUTEndpoint) || !(NotificationEndpoint))
+ {
+ if (!(RNDISControlInterface) ||
+ USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+ DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
+ {
+ if (NotificationEndpoint)
+ {
+ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+ DCOMP_RNDIS_Host_NextRNDISDataInterface) != DESCRIPTOR_SEARCH_COMP_Found)
+ {
+ return RNDIS_ENUMERROR_NoCompatibleInterfaceFound;
+ }
+
+ DataINEndpoint = NULL;
+ DataOUTEndpoint = NULL;
+ }
+ else
+ {
+ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+ DCOMP_RNDIS_Host_NextRNDISControlInterface) != DESCRIPTOR_SEARCH_COMP_Found)
+ {
+ return RNDIS_ENUMERROR_NoCompatibleInterfaceFound;
+ }
+
+ RNDISControlInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
+
+ NotificationEndpoint = NULL;
+ }
+
+ continue;
+ }
+
+ USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
+
+ if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN)
+ {
+ if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT)
+ NotificationEndpoint = EndpointData;
+ else
+ DataINEndpoint = EndpointData;
+ }
+ else
+ {
+ DataOUTEndpoint = EndpointData;
+ }
+ }
+
+ RNDISInterfaceInfo->Config.DataINPipe.Size = le16_to_cpu(DataINEndpoint->EndpointSize);
+ RNDISInterfaceInfo->Config.DataINPipe.EndpointAddress = DataINEndpoint->EndpointAddress;
+ RNDISInterfaceInfo->Config.DataINPipe.Type = EP_TYPE_BULK;
+
+ RNDISInterfaceInfo->Config.DataOUTPipe.Size = le16_to_cpu(DataOUTEndpoint->EndpointSize);
+ RNDISInterfaceInfo->Config.DataOUTPipe.EndpointAddress = DataOUTEndpoint->EndpointAddress;
+ RNDISInterfaceInfo->Config.DataOUTPipe.Type = EP_TYPE_BULK;
+
+ RNDISInterfaceInfo->Config.NotificationPipe.Size = le16_to_cpu(NotificationEndpoint->EndpointSize);
+ RNDISInterfaceInfo->Config.NotificationPipe.EndpointAddress = NotificationEndpoint->EndpointAddress;
+ RNDISInterfaceInfo->Config.NotificationPipe.Type = EP_TYPE_INTERRUPT;
+
+ if (!(Pipe_ConfigurePipeTable(&RNDISInterfaceInfo->Config.DataINPipe, 1)))
+ return RNDIS_ENUMERROR_PipeConfigurationFailed;
+
+ if (!(Pipe_ConfigurePipeTable(&RNDISInterfaceInfo->Config.DataOUTPipe, 1)))
+ return RNDIS_ENUMERROR_PipeConfigurationFailed;
+
+ if (!(Pipe_ConfigurePipeTable(&RNDISInterfaceInfo->Config.NotificationPipe, 1)))
+ return RNDIS_ENUMERROR_PipeConfigurationFailed;
+
+ RNDISInterfaceInfo->State.ControlInterfaceNumber = RNDISControlInterface->InterfaceNumber;
+ RNDISInterfaceInfo->State.IsActive = true;
+
+ return RNDIS_ENUMERROR_NoError;
+}
+
+static uint8_t DCOMP_RNDIS_Host_NextRNDISControlInterface(void* const CurrentDescriptor)
+{
+ USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
+
+ if (Header->Type == DTYPE_Interface)
+ {
+ USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
+
+ if ((Interface->Class == CDC_CSCP_CDCClass) &&
+ (Interface->SubClass == CDC_CSCP_ACMSubclass) &&
+ (Interface->Protocol == CDC_CSCP_VendorSpecificProtocol))
+ {
+ return DESCRIPTOR_SEARCH_Found;
+ }
+ }
+
+ return DESCRIPTOR_SEARCH_NotFound;
+}
+
+static uint8_t DCOMP_RNDIS_Host_NextRNDISDataInterface(void* const CurrentDescriptor)
+{
+ USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
+
+ if (Header->Type == DTYPE_Interface)
+ {
+ USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor,
+ USB_Descriptor_Interface_t);
+
+ if ((Interface->Class == CDC_CSCP_CDCDataClass) &&
+ (Interface->SubClass == CDC_CSCP_NoDataSubclass) &&
+ (Interface->Protocol == CDC_CSCP_NoDataProtocol))
+ {
+ return DESCRIPTOR_SEARCH_Found;
+ }
+ }
+
+ return DESCRIPTOR_SEARCH_NotFound;
+}
+
+static uint8_t DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint(void* const CurrentDescriptor)
+{
+ USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
+
+ if (Header->Type == DTYPE_Endpoint)
+ {
+ USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
+
+ uint8_t EndpointType = (Endpoint->Attributes & EP_TYPE_MASK);
+
+ if (((EndpointType == EP_TYPE_BULK) || (EndpointType == EP_TYPE_INTERRUPT)) &&
+ !(Pipe_IsEndpointBound(Endpoint->EndpointAddress)))
+ {
+ return DESCRIPTOR_SEARCH_Found;
+ }
+ }
+ else if (Header->Type == DTYPE_Interface)
+ {
+ return DESCRIPTOR_SEARCH_Fail;
+ }
+
+ return DESCRIPTOR_SEARCH_NotFound;
+}
+
+static uint8_t RNDIS_SendEncapsulatedCommand(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
+ void* Buffer,
+ const uint16_t Length)
+{
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
+ .bRequest = RNDIS_REQ_SendEncapsulatedCommand,
+ .wValue = 0,
+ .wIndex = RNDISInterfaceInfo->State.ControlInterfaceNumber,
+ .wLength = Length,
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+
+ return USB_Host_SendControlRequest(Buffer);
+}
+
+static uint8_t RNDIS_GetEncapsulatedResponse(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
+ void* Buffer,
+ const uint16_t Length)
+{
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
+ .bRequest = RNDIS_REQ_GetEncapsulatedResponse,
+ .wValue = 0,
+ .wIndex = RNDISInterfaceInfo->State.ControlInterfaceNumber,
+ .wLength = Length,
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+
+ return USB_Host_SendControlRequest(Buffer);
+}
+
+uint8_t RNDIS_Host_SendKeepAlive(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
+{
+ uint8_t ErrorCode;
+
+ RNDIS_KeepAlive_Message_t KeepAliveMessage;
+ RNDIS_KeepAlive_Complete_t KeepAliveMessageResponse;
+
+ KeepAliveMessage.MessageType = CPU_TO_LE32(REMOTE_NDIS_KEEPALIVE_MSG);
+ KeepAliveMessage.MessageLength = CPU_TO_LE32(sizeof(RNDIS_KeepAlive_Message_t));
+ KeepAliveMessage.RequestId = cpu_to_le32(RNDISInterfaceInfo->State.RequestID++);
+
+ if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &KeepAliveMessage,
+ sizeof(RNDIS_KeepAlive_Message_t))) != HOST_SENDCONTROL_Successful)
+ {
+ return ErrorCode;
+ }
+
+ if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &KeepAliveMessageResponse,
+ sizeof(RNDIS_KeepAlive_Complete_t))) != HOST_SENDCONTROL_Successful)
+ {
+ return ErrorCode;
+ }
+
+ return HOST_SENDCONTROL_Successful;
+}
+
+uint8_t RNDIS_Host_InitializeDevice(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
+{
+ uint8_t ErrorCode;
+
+ RNDIS_Initialize_Message_t InitMessage;
+ RNDIS_Initialize_Complete_t InitMessageResponse;
+
+ InitMessage.MessageType = CPU_TO_LE32(REMOTE_NDIS_INITIALIZE_MSG);
+ InitMessage.MessageLength = CPU_TO_LE32(sizeof(RNDIS_Initialize_Message_t));
+ InitMessage.RequestId = cpu_to_le32(RNDISInterfaceInfo->State.RequestID++);
+
+ InitMessage.MajorVersion = CPU_TO_LE32(REMOTE_NDIS_VERSION_MAJOR);
+ InitMessage.MinorVersion = CPU_TO_LE32(REMOTE_NDIS_VERSION_MINOR);
+ InitMessage.MaxTransferSize = cpu_to_le32(RNDISInterfaceInfo->Config.HostMaxPacketSize);
+
+ if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &InitMessage,
+ sizeof(RNDIS_Initialize_Message_t))) != HOST_SENDCONTROL_Successful)
+ {
+ return ErrorCode;
+ }
+
+ if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &InitMessageResponse,
+ sizeof(RNDIS_Initialize_Complete_t))) != HOST_SENDCONTROL_Successful)
+ {
+ return ErrorCode;
+ }
+
+ if (InitMessageResponse.Status != CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS))
+ return RNDIS_ERROR_LOGICAL_CMD_FAILED;
+
+ RNDISInterfaceInfo->State.DeviceMaxPacketSize = le32_to_cpu(InitMessageResponse.MaxTransferSize);
+
+ return HOST_SENDCONTROL_Successful;
+}
+
+uint8_t RNDIS_Host_SetRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
+ const uint32_t Oid,
+ void* Buffer,
+ const uint16_t Length)
+{
+ uint8_t ErrorCode;
+
+ struct
+ {
+ RNDIS_Set_Message_t SetMessage;
+ uint8_t ContiguousBuffer[Length];
+ } SetMessageData;
+
+ RNDIS_Set_Complete_t SetMessageResponse;
+
+ SetMessageData.SetMessage.MessageType = CPU_TO_LE32(REMOTE_NDIS_SET_MSG);
+ SetMessageData.SetMessage.MessageLength = cpu_to_le32(sizeof(RNDIS_Set_Message_t) + Length);
+ SetMessageData.SetMessage.RequestId = cpu_to_le32(RNDISInterfaceInfo->State.RequestID++);
+
+ SetMessageData.SetMessage.Oid = cpu_to_le32(Oid);
+ SetMessageData.SetMessage.InformationBufferLength = cpu_to_le32(Length);
+ SetMessageData.SetMessage.InformationBufferOffset = CPU_TO_LE32(sizeof(RNDIS_Set_Message_t) - sizeof(RNDIS_Message_Header_t));
+ SetMessageData.SetMessage.DeviceVcHandle = CPU_TO_LE32(0);
+
+ memcpy(&SetMessageData.ContiguousBuffer, Buffer, Length);
+
+ if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &SetMessageData,
+ (sizeof(RNDIS_Set_Message_t) + Length))) != HOST_SENDCONTROL_Successful)
+ {
+ return ErrorCode;
+ }
+
+ if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &SetMessageResponse,
+ sizeof(RNDIS_Set_Complete_t))) != HOST_SENDCONTROL_Successful)
+ {
+ return ErrorCode;
+ }
+
+ if (SetMessageResponse.Status != CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS))
+ return RNDIS_ERROR_LOGICAL_CMD_FAILED;
+
+ return HOST_SENDCONTROL_Successful;
+}
+
+uint8_t RNDIS_Host_QueryRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
+ const uint32_t Oid,
+ void* Buffer,
+ const uint16_t MaxLength)
+{
+ uint8_t ErrorCode;
+
+ RNDIS_Query_Message_t QueryMessage;
+
+ struct
+ {
+ RNDIS_Query_Complete_t QueryMessageResponse;
+ uint8_t ContiguousBuffer[MaxLength];
+ } QueryMessageResponseData;
+
+ QueryMessage.MessageType = CPU_TO_LE32(REMOTE_NDIS_QUERY_MSG);
+ QueryMessage.MessageLength = CPU_TO_LE32(sizeof(RNDIS_Query_Message_t));
+ QueryMessage.RequestId = cpu_to_le32(RNDISInterfaceInfo->State.RequestID++);
+
+ QueryMessage.Oid = cpu_to_le32(Oid);
+ QueryMessage.InformationBufferLength = CPU_TO_LE32(0);
+ QueryMessage.InformationBufferOffset = CPU_TO_LE32(0);
+ QueryMessage.DeviceVcHandle = CPU_TO_LE32(0);
+
+ if ((ErrorCode = RNDIS_SendEncapsulatedCommand(RNDISInterfaceInfo, &QueryMessage,
+ sizeof(RNDIS_Query_Message_t))) != HOST_SENDCONTROL_Successful)
+ {
+ return ErrorCode;
+ }
+
+ if ((ErrorCode = RNDIS_GetEncapsulatedResponse(RNDISInterfaceInfo, &QueryMessageResponseData,
+ sizeof(QueryMessageResponseData))) != HOST_SENDCONTROL_Successful)
+ {
+ return ErrorCode;
+ }
+
+ if (QueryMessageResponseData.QueryMessageResponse.Status != CPU_TO_LE32(REMOTE_NDIS_STATUS_SUCCESS))
+ return RNDIS_ERROR_LOGICAL_CMD_FAILED;
+
+ memcpy(Buffer, &QueryMessageResponseData.ContiguousBuffer, MaxLength);
+
+ return HOST_SENDCONTROL_Successful;
+}
+
+bool RNDIS_Host_IsPacketReceived(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
+{
+ bool PacketWaiting;
+
+ if ((USB_HostState != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
+ return false;
+
+ Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataINPipe.Address);
+
+ Pipe_Unfreeze();
+ PacketWaiting = Pipe_IsINReceived();
+ Pipe_Freeze();
+
+ return PacketWaiting;
+}
+
+uint8_t RNDIS_Host_ReadPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
+ void* Buffer,
+ uint16_t* const PacketLength)
+{
+ uint8_t ErrorCode;
+
+ if ((USB_HostState != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
+ return PIPE_READYWAIT_DeviceDisconnected;
+
+ Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataINPipe.Address);
+ Pipe_Unfreeze();
+
+ if (!(Pipe_IsReadWriteAllowed()))
+ {
+ if (Pipe_IsINReceived())
+ Pipe_ClearIN();
+
+ *PacketLength = 0;
+ Pipe_Freeze();
+ return PIPE_RWSTREAM_NoError;
+ }
+
+ RNDIS_Packet_Message_t DeviceMessage;
+
+ if ((ErrorCode = Pipe_Read_Stream_LE(&DeviceMessage, sizeof(RNDIS_Packet_Message_t),
+ NULL)) != PIPE_RWSTREAM_NoError)
+ {
+ return ErrorCode;
+ }
+
+ *PacketLength = (uint16_t)le32_to_cpu(DeviceMessage.DataLength);
+
+ Pipe_Discard_Stream(le32_to_cpu(DeviceMessage.DataOffset) -
+ (sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t)),
+ NULL);
+
+ Pipe_Read_Stream_LE(Buffer, *PacketLength, NULL);
+
+ if (!(Pipe_BytesInPipe()))
+ Pipe_ClearIN();
+
+ Pipe_Freeze();
+
+ return PIPE_RWSTREAM_NoError;
+}
+
+uint8_t RNDIS_Host_SendPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
+ void* Buffer,
+ const uint16_t PacketLength)
+{
+ uint8_t ErrorCode;
+
+ if ((USB_HostState != HOST_STATE_Configured) || !(RNDISInterfaceInfo->State.IsActive))
+ return PIPE_READYWAIT_DeviceDisconnected;
+
+ RNDIS_Packet_Message_t DeviceMessage;
+
+ memset(&DeviceMessage, 0, sizeof(RNDIS_Packet_Message_t));
+ DeviceMessage.MessageType = CPU_TO_LE32(REMOTE_NDIS_PACKET_MSG);
+ DeviceMessage.MessageLength = CPU_TO_LE32(sizeof(RNDIS_Packet_Message_t) + PacketLength);
+ DeviceMessage.DataOffset = CPU_TO_LE32(sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t));
+ DeviceMessage.DataLength = cpu_to_le32(PacketLength);
+
+ Pipe_SelectPipe(RNDISInterfaceInfo->Config.DataOUTPipe.Address);
+ Pipe_Unfreeze();
+
+ if ((ErrorCode = Pipe_Write_Stream_LE(&DeviceMessage, sizeof(RNDIS_Packet_Message_t),
+ NULL)) != PIPE_RWSTREAM_NoError)
+ {
+ return ErrorCode;
+ }
+
+ Pipe_Write_Stream_LE(Buffer, PacketLength, NULL);
+ Pipe_ClearOUT();
+
+ Pipe_Freeze();
+
+ return PIPE_RWSTREAM_NoError;
+}
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/RNDISClassHost.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/RNDISClassHost.h
new file mode 100644
index 000000000..79334b41b
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/RNDISClassHost.h
@@ -0,0 +1,270 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Host mode driver for the library USB RNDIS Class driver.
+ *
+ * Host mode driver for the library USB RNDIS Class driver.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB module driver
+ * dispatch header located in LUFA/Drivers/USB.h.
+ */
+
+/** \ingroup Group_USBClassRNDIS
+ * \defgroup Group_USBClassRNDISHost RNDIS Class Host Mode Driver
+ *
+ * \section Sec_USBClassRNDISHost_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Drivers/USB/Class/Host/RNDISClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ *
+ * \section Sec_USBClassRNDISHost_ModDescription Module Description
+ * Host Mode USB Class driver framework interface, for the Microsoft RNDIS Ethernet
+ * USB Class driver.
+ *
+ * @{
+ */
+
+#ifndef __RNDIS_CLASS_HOST_H__
+#define __RNDIS_CLASS_HOST_H__
+
+ /* Includes: */
+ #include "../../USB.h"
+ #include "../Common/RNDISClassCommon.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_RNDIS_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Type Defines: */
+ /** \brief RNDIS Class Host Mode Configuration and State Structure.
+ *
+ * Class state structure. An instance of this structure should be made within the user application,
+ * and passed to each of the RNDIS class driver functions as the \c RNDISInterfaceInfo parameter. This
+ * stores each RNDIS interface's configuration and state information.
+ */
+ typedef struct
+ {
+ struct
+ {
+ USB_Pipe_Table_t DataINPipe; /**< Data IN Pipe configuration table. */
+ USB_Pipe_Table_t DataOUTPipe; /**< Data OUT Pipe configuration table. */
+ USB_Pipe_Table_t NotificationPipe; /**< Notification IN Pipe configuration table. */
+
+ uint32_t HostMaxPacketSize; /**< Maximum size of a packet which can be buffered by the host. */
+ } Config; /**< Config data for the USB class interface within the device. All elements in this section
+ * <b>must</b> be set or the interface will fail to enumerate and operate correctly.
+ */
+ struct
+ {
+ bool IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
+ * after \ref RNDIS_Host_ConfigurePipes() is called and the Host state machine is in the
+ * Configured state.
+ */
+ uint8_t ControlInterfaceNumber; /**< Interface index of the RNDIS control interface within the attached device. */
+
+ uint32_t DeviceMaxPacketSize; /**< Maximum size of a packet which can be buffered by the attached RNDIS device. */
+
+ uint32_t RequestID; /**< Request ID counter to give a unique ID for each command/response pair. */
+ } State; /**< State data for the USB class interface within the device. All elements in this section
+ * <b>may</b> be set to initial values, but may also be ignored to default to sane values when
+ * the interface is enumerated.
+ */
+ } USB_ClassInfo_RNDIS_Host_t;
+
+ /* Enums: */
+ /** Enum for the possible error codes returned by the \ref RNDIS_Host_ConfigurePipes() function. */
+ enum RNDIS_Host_EnumerationFailure_ErrorCodes_t
+ {
+ RNDIS_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */
+ RNDIS_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */
+ RNDIS_ENUMERROR_NoCompatibleInterfaceFound = 2, /**< A compatible RNDIS interface was not found in the device's Configuration Descriptor. */
+ RNDIS_ENUMERROR_PipeConfigurationFailed = 3, /**< One or more pipes for the specified interface could not be configured correctly. */
+ };
+
+ /* Function Prototypes: */
+ /** Host interface configuration routine, to configure a given RNDIS host interface instance using the Configuration
+ * Descriptor read from an attached USB device. This function automatically updates the given RNDIS Host instance's
+ * state values and configures the pipes required to communicate with the interface if it is found within the device.
+ * This should be called once after the stack has enumerated the attached device, while the host state machine is in
+ * the Addressed state.
+ *
+ * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state.
+ * \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor.
+ * \param[in] ConfigDescriptorData Pointer to a buffer containing the attached device's Configuration Descriptor.
+ *
+ * \return A value from the \ref RNDIS_Host_EnumerationFailure_ErrorCodes_t enum.
+ */
+ uint8_t RNDIS_Host_ConfigurePipes(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
+ uint16_t ConfigDescriptorSize,
+ void* ConfigDescriptorData) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
+
+ /** Sends a RNDIS KEEPALIVE command to the device, to ensure that it does not enter standby mode after periods
+ * of long inactivity.
+ *
+ * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state.
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum or \ref RNDIS_ERROR_LOGICAL_CMD_FAILED if the device returned a
+ * logical command failure.
+ */
+ uint8_t RNDIS_Host_SendKeepAlive(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Initializes the attached RNDIS device's RNDIS interface. This should be called after the device's pipes have been
+ * configured via the call to \ref RNDIS_Host_ConfigurePipes().
+ *
+ * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state.
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum or \ref RNDIS_ERROR_LOGICAL_CMD_FAILED if the
+ * device returned a logical command failure.
+ */
+ uint8_t RNDIS_Host_InitializeDevice(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Sets a given RNDIS property of an attached RNDIS device.
+ *
+ * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state.
+ * \param[in] Oid OID number of the parameter to set.
+ * \param[in] Buffer Pointer to where the property data is to be sourced from.
+ * \param[in] Length Length in bytes of the property data to sent to the device.
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum or \ref RNDIS_ERROR_LOGICAL_CMD_FAILED if the
+ * device returned a logical command failure.
+ */
+ uint8_t RNDIS_Host_SetRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
+ const uint32_t Oid,
+ void* Buffer,
+ const uint16_t Length) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
+
+ /** Gets a given RNDIS property of an attached RNDIS device.
+ *
+ * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state.
+ * \param[in] Oid OID number of the parameter to get.
+ * \param[in] Buffer Pointer to where the property data is to be written to.
+ * \param[in] MaxLength Length in bytes of the destination buffer size.
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum or \ref RNDIS_ERROR_LOGICAL_CMD_FAILED if the
+ * device returned a logical command failure.
+ */
+ uint8_t RNDIS_Host_QueryRNDISProperty(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
+ const uint32_t Oid,
+ void* Buffer,
+ const uint16_t MaxLength) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
+
+ /** Determines if a packet is currently waiting for the host to read in and process.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state.
+ *
+ * \return Boolean \c true if a packet is waiting to be read in by the host, \c false otherwise.
+ */
+ bool RNDIS_Host_IsPacketReceived(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Retrieves the next pending packet from the device, discarding the remainder of the RNDIS packet header to leave
+ * only the packet contents for processing by the host in the nominated buffer.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state.
+ * \param[out] Buffer Pointer to a buffer where the packer data is to be written to.
+ * \param[out] PacketLength Pointer to where the length in bytes of the read packet is to be stored.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t RNDIS_Host_ReadPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
+ void* Buffer,
+ uint16_t* const PacketLength) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2)
+ ATTR_NON_NULL_PTR_ARG(3);
+
+ /** Sends the given packet to the attached RNDIS device, after adding a RNDIS packet message header.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state.
+ * \param[in] Buffer Pointer to a buffer where the packer data is to be read from.
+ * \param[in] PacketLength Length in bytes of the packet to send.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t RNDIS_Host_SendPacket(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
+ void* Buffer,
+ const uint16_t PacketLength) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+
+ /* Inline Functions: */
+ /** General management task for a given RNDIS host class interface, required for the correct operation of the interface. This should
+ * be called frequently in the main program loop, before the master USB management task \ref USB_USBTask().
+ *
+ * \param[in,out] RNDISInterfaceInfo Pointer to a structure containing an RNDIS Class host configuration and state.
+ */
+ static inline void RNDIS_Host_USBTask(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
+ static inline void RNDIS_Host_USBTask(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo)
+ {
+ (void)RNDISInterfaceInfo;
+ }
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Function Prototypes: */
+ #if defined(__INCLUDE_FROM_RNDIS_HOST_C)
+ static uint8_t RNDIS_SendEncapsulatedCommand(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
+ void* Buffer,
+ const uint16_t Length) ATTR_NON_NULL_PTR_ARG(1)
+ ATTR_NON_NULL_PTR_ARG(2);
+ static uint8_t RNDIS_GetEncapsulatedResponse(USB_ClassInfo_RNDIS_Host_t* const RNDISInterfaceInfo,
+ void* Buffer,
+ const uint16_t Length) ATTR_NON_NULL_PTR_ARG(1)
+ ATTR_NON_NULL_PTR_ARG(2);
+
+ static uint8_t DCOMP_RNDIS_Host_NextRNDISControlInterface(void* const CurrentDescriptor)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ static uint8_t DCOMP_RNDIS_Host_NextRNDISDataInterface(void* const CurrentDescriptor)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ static uint8_t DCOMP_RNDIS_Host_NextRNDISInterfaceEndpoint(void* const CurrentDescriptor)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ #endif
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/StillImageClassHost.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/StillImageClassHost.c
new file mode 100644
index 000000000..24a6308f5
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/StillImageClassHost.c
@@ -0,0 +1,436 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../../Core/USBMode.h"
+
+#if defined(USB_CAN_BE_HOST)
+
+#define __INCLUDE_FROM_SI_DRIVER
+#define __INCLUDE_FROM_STILLIMAGE_HOST_C
+#include "StillImageClassHost.h"
+
+uint8_t SI_Host_ConfigurePipes(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
+ uint16_t ConfigDescriptorSize,
+ void* ConfigDescriptorData)
+{
+ USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
+ USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
+ USB_Descriptor_Endpoint_t* EventsEndpoint = NULL;
+ USB_Descriptor_Interface_t* StillImageInterface = NULL;
+
+ memset(&SIInterfaceInfo->State, 0x00, sizeof(SIInterfaceInfo->State));
+
+ if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
+ return SI_ENUMERROR_InvalidConfigDescriptor;
+
+ while (!(DataINEndpoint) || !(DataOUTEndpoint) || !(EventsEndpoint))
+ {
+ if (!(StillImageInterface) ||
+ USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+ DCOMP_SI_Host_NextSIInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
+ {
+ if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
+ DCOMP_SI_Host_NextSIInterface) != DESCRIPTOR_SEARCH_COMP_Found)
+ {
+ return SI_ENUMERROR_NoCompatibleInterfaceFound;
+ }
+
+ StillImageInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
+
+ DataINEndpoint = NULL;
+ DataOUTEndpoint = NULL;
+ EventsEndpoint = NULL;
+
+ continue;
+ }
+
+ USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
+
+ if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN)
+ {
+ if ((EndpointData->Attributes & EP_TYPE_MASK) == EP_TYPE_INTERRUPT)
+ EventsEndpoint = EndpointData;
+ else
+ DataINEndpoint = EndpointData;
+ }
+ else
+ {
+ DataOUTEndpoint = EndpointData;
+ }
+ }
+
+ SIInterfaceInfo->Config.DataINPipe.Size = le16_to_cpu(DataINEndpoint->EndpointSize);
+ SIInterfaceInfo->Config.DataINPipe.EndpointAddress = DataINEndpoint->EndpointAddress;
+ SIInterfaceInfo->Config.DataINPipe.Type = EP_TYPE_BULK;
+
+ SIInterfaceInfo->Config.DataOUTPipe.Size = le16_to_cpu(DataOUTEndpoint->EndpointSize);
+ SIInterfaceInfo->Config.DataOUTPipe.EndpointAddress = DataOUTEndpoint->EndpointAddress;
+ SIInterfaceInfo->Config.DataOUTPipe.Type = EP_TYPE_BULK;
+
+ SIInterfaceInfo->Config.EventsPipe.Size = le16_to_cpu(EventsEndpoint->EndpointSize);
+ SIInterfaceInfo->Config.EventsPipe.EndpointAddress = EventsEndpoint->EndpointAddress;
+ SIInterfaceInfo->Config.EventsPipe.Type = EP_TYPE_INTERRUPT;
+
+ if (!(Pipe_ConfigurePipeTable(&SIInterfaceInfo->Config.DataINPipe, 1)))
+ return SI_ENUMERROR_PipeConfigurationFailed;
+
+ if (!(Pipe_ConfigurePipeTable(&SIInterfaceInfo->Config.DataOUTPipe, 1)))
+ return SI_ENUMERROR_PipeConfigurationFailed;
+
+ if (!(Pipe_ConfigurePipeTable(&SIInterfaceInfo->Config.EventsPipe, 1)))
+ return SI_ENUMERROR_PipeConfigurationFailed;
+
+ SIInterfaceInfo->State.InterfaceNumber = StillImageInterface->InterfaceNumber;
+ SIInterfaceInfo->State.IsActive = true;
+
+ return SI_ENUMERROR_NoError;
+}
+
+uint8_t DCOMP_SI_Host_NextSIInterface(void* const CurrentDescriptor)
+{
+ USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
+
+ if (Header->Type == DTYPE_Interface)
+ {
+ USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
+
+ if ((Interface->Class == SI_CSCP_StillImageClass) &&
+ (Interface->SubClass == SI_CSCP_StillImageSubclass) &&
+ (Interface->Protocol == SI_CSCP_BulkOnlyProtocol))
+ {
+ return DESCRIPTOR_SEARCH_Found;
+ }
+ }
+
+ return DESCRIPTOR_SEARCH_NotFound;
+}
+
+uint8_t DCOMP_SI_Host_NextSIInterfaceEndpoint(void* const CurrentDescriptor)
+{
+ USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
+
+ if (Header->Type == DTYPE_Endpoint)
+ {
+ USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
+
+ uint8_t EndpointType = (Endpoint->Attributes & EP_TYPE_MASK);
+
+ if (((EndpointType == EP_TYPE_BULK) || (EndpointType == EP_TYPE_INTERRUPT)) &&
+ (!(Pipe_IsEndpointBound(Endpoint->EndpointAddress))))
+ {
+ return DESCRIPTOR_SEARCH_Found;
+ }
+ }
+ else if (Header->Type == DTYPE_Interface)
+ {
+ return DESCRIPTOR_SEARCH_Fail;
+ }
+
+ return DESCRIPTOR_SEARCH_NotFound;
+}
+
+uint8_t SI_Host_SendBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
+ PIMA_Container_t* const PIMAHeader)
+{
+ uint8_t ErrorCode;
+
+ if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
+ return PIPE_RWSTREAM_DeviceDisconnected;
+
+ if (SIInterfaceInfo->State.IsSessionOpen)
+ PIMAHeader->TransactionID = cpu_to_le32(SIInterfaceInfo->State.TransactionID++);
+
+ Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipe.Address);
+ Pipe_Unfreeze();
+
+ if ((ErrorCode = Pipe_Write_Stream_LE(PIMAHeader, PIMA_COMMAND_SIZE(0), NULL)) != PIPE_RWSTREAM_NoError)
+ return ErrorCode;
+
+ uint8_t ParamBytes = (PIMAHeader->DataLength - PIMA_COMMAND_SIZE(0));
+
+ if (ParamBytes)
+ {
+ if ((ErrorCode = Pipe_Write_Stream_LE(&PIMAHeader->Params, ParamBytes, NULL)) != PIPE_RWSTREAM_NoError)
+ return ErrorCode;
+ }
+
+ Pipe_ClearOUT();
+ Pipe_Freeze();
+
+ return PIPE_RWSTREAM_NoError;
+}
+
+uint8_t SI_Host_ReceiveBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
+ PIMA_Container_t* const PIMAHeader)
+{
+ uint16_t TimeoutMSRem = SI_COMMAND_DATA_TIMEOUT_MS;
+ uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber();
+
+ if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
+ return PIPE_RWSTREAM_DeviceDisconnected;
+
+ Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipe.Address);
+ Pipe_Unfreeze();
+
+ while (!(Pipe_IsINReceived()))
+ {
+ uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber();
+
+ if (CurrentFrameNumber != PreviousFrameNumber)
+ {
+ PreviousFrameNumber = CurrentFrameNumber;
+
+ if (!(TimeoutMSRem--))
+ return PIPE_RWSTREAM_Timeout;
+ }
+
+ Pipe_Freeze();
+ Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipe.Address);
+ Pipe_Unfreeze();
+
+ if (Pipe_IsStalled())
+ {
+ USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress());
+ return PIPE_RWSTREAM_PipeStalled;
+ }
+
+ Pipe_Freeze();
+ Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipe.Address);
+ Pipe_Unfreeze();
+
+ if (Pipe_IsStalled())
+ {
+ USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress());
+ return PIPE_RWSTREAM_PipeStalled;
+ }
+
+ if (USB_HostState == HOST_STATE_Unattached)
+ return PIPE_RWSTREAM_DeviceDisconnected;
+ }
+
+ Pipe_Read_Stream_LE(PIMAHeader, PIMA_COMMAND_SIZE(0), NULL);
+
+ if (PIMAHeader->Type == CPU_TO_LE16(PIMA_CONTAINER_ResponseBlock))
+ {
+ uint8_t ParamBytes = (PIMAHeader->DataLength - PIMA_COMMAND_SIZE(0));
+
+ if (ParamBytes)
+ Pipe_Read_Stream_LE(&PIMAHeader->Params, ParamBytes, NULL);
+
+ Pipe_ClearIN();
+ }
+
+ Pipe_Freeze();
+
+ return PIPE_RWSTREAM_NoError;
+}
+
+uint8_t SI_Host_SendData(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
+ const void* Buffer,
+ const uint16_t Bytes)
+{
+ uint8_t ErrorCode;
+
+ if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
+ return PIPE_RWSTREAM_DeviceDisconnected;
+
+ Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipe.Address);
+ Pipe_Unfreeze();
+
+ ErrorCode = Pipe_Write_Stream_LE(Buffer, Bytes, NULL);
+
+ Pipe_ClearOUT();
+ Pipe_Freeze();
+
+ return ErrorCode;
+}
+
+uint8_t SI_Host_ReadData(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
+ void* Buffer,
+ const uint16_t Bytes)
+{
+ uint8_t ErrorCode;
+
+ if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
+ return PIPE_RWSTREAM_DeviceDisconnected;
+
+ Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipe.Address);
+ Pipe_Unfreeze();
+
+ ErrorCode = Pipe_Read_Stream_LE(Buffer, Bytes, NULL);
+
+ Pipe_Freeze();
+
+ return ErrorCode;
+}
+
+bool SI_Host_IsEventReceived(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
+{
+ bool IsEventReceived = false;
+
+ if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
+ return false;
+
+ Pipe_SelectPipe(SIInterfaceInfo->Config.EventsPipe.Address);
+ Pipe_Unfreeze();
+
+ if (Pipe_IsINReceived())
+ IsEventReceived = true;
+
+ Pipe_Freeze();
+
+ return IsEventReceived;
+}
+
+uint8_t SI_Host_ReceiveEventHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
+ PIMA_Container_t* const PIMAHeader)
+{
+ uint8_t ErrorCode;
+
+ if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
+ return PIPE_RWSTREAM_DeviceDisconnected;
+
+ Pipe_SelectPipe(SIInterfaceInfo->Config.EventsPipe.Address);
+ Pipe_Unfreeze();
+
+ ErrorCode = Pipe_Read_Stream_LE(PIMAHeader, sizeof(PIMA_Container_t), NULL);
+
+ Pipe_ClearIN();
+ Pipe_Freeze();
+
+ return ErrorCode;
+}
+
+uint8_t SI_Host_OpenSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
+ return PIPE_RWSTREAM_DeviceDisconnected;
+
+ uint8_t ErrorCode;
+
+ SIInterfaceInfo->State.TransactionID = 0;
+ SIInterfaceInfo->State.IsSessionOpen = false;
+
+ PIMA_Container_t PIMABlock = (PIMA_Container_t)
+ {
+ .DataLength = CPU_TO_LE32(PIMA_COMMAND_SIZE(1)),
+ .Type = CPU_TO_LE16(PIMA_CONTAINER_CommandBlock),
+ .Code = CPU_TO_LE16(0x1002),
+ .Params = {CPU_TO_LE32(1)},
+ };
+
+ if ((ErrorCode = SI_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
+ return ErrorCode;
+
+ if ((ErrorCode = SI_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
+ return ErrorCode;
+
+ if ((PIMABlock.Type != CPU_TO_LE16(PIMA_CONTAINER_ResponseBlock)) || (PIMABlock.Code != CPU_TO_LE16(0x2001)))
+ return SI_ERROR_LOGICAL_CMD_FAILED;
+
+ SIInterfaceInfo->State.IsSessionOpen = true;
+
+ return PIPE_RWSTREAM_NoError;
+}
+
+uint8_t SI_Host_CloseSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
+ return PIPE_RWSTREAM_DeviceDisconnected;
+
+ uint8_t ErrorCode;
+
+ PIMA_Container_t PIMABlock = (PIMA_Container_t)
+ {
+ .DataLength = CPU_TO_LE32(PIMA_COMMAND_SIZE(1)),
+ .Type = CPU_TO_LE16(PIMA_CONTAINER_CommandBlock),
+ .Code = CPU_TO_LE16(0x1003),
+ .Params = {CPU_TO_LE32(1)},
+ };
+
+ if ((ErrorCode = SI_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
+ return ErrorCode;
+
+ if ((ErrorCode = SI_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
+ return ErrorCode;
+
+ SIInterfaceInfo->State.IsSessionOpen = false;
+
+ if ((PIMABlock.Type != CPU_TO_LE16(PIMA_CONTAINER_ResponseBlock)) || (PIMABlock.Code != CPU_TO_LE16(0x2001)))
+ return SI_ERROR_LOGICAL_CMD_FAILED;
+
+ return PIPE_RWSTREAM_NoError;
+}
+
+uint8_t SI_Host_SendCommand(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
+ const uint16_t Operation,
+ const uint8_t TotalParams,
+ uint32_t* const Params)
+{
+ if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
+ return PIPE_RWSTREAM_DeviceDisconnected;
+
+ uint8_t ErrorCode;
+
+ PIMA_Container_t PIMABlock = (PIMA_Container_t)
+ {
+ .DataLength = cpu_to_le32(PIMA_COMMAND_SIZE(TotalParams)),
+ .Type = CPU_TO_LE16(PIMA_CONTAINER_CommandBlock),
+ .Code = cpu_to_le16(Operation),
+ };
+
+ memcpy(&PIMABlock.Params, Params, sizeof(uint32_t) * TotalParams);
+
+ if ((ErrorCode = SI_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
+ return ErrorCode;
+
+ return PIPE_RWSTREAM_NoError;
+}
+
+uint8_t SI_Host_ReceiveResponse(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
+{
+ uint8_t ErrorCode;
+ PIMA_Container_t PIMABlock;
+
+ if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
+ return PIPE_RWSTREAM_DeviceDisconnected;
+
+ if ((ErrorCode = SI_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
+ return ErrorCode;
+
+ if ((PIMABlock.Type != CPU_TO_LE16(PIMA_CONTAINER_ResponseBlock)) || (PIMABlock.Code != CPU_TO_LE16(0x2001)))
+ return SI_ERROR_LOGICAL_CMD_FAILED;
+
+ return PIPE_RWSTREAM_NoError;
+}
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/StillImageClassHost.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/StillImageClassHost.h
new file mode 100644
index 000000000..f9f41adb6
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/StillImageClassHost.h
@@ -0,0 +1,317 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Host mode driver for the library USB Still Image Class driver.
+ *
+ * Host mode driver for the library USB Still Image Class driver.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB module driver
+ * dispatch header located in LUFA/Drivers/USB.h.
+ */
+
+/** \ingroup Group_USBClassSI
+ * \defgroup Group_USBClassStillImageHost Still Image Class Host Mode Driver
+ *
+ * \section Sec_USBClassStillImageHost_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Drivers/USB/Class/Host/StillImageClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ *
+ * \section Sec_USBClassStillImageHost_ModDescription Module Description
+ * Host Mode USB Class driver framework interface, for the Still Image USB Class driver.
+ *
+ * @{
+ */
+
+#ifndef __SI_CLASS_HOST_H__
+#define __SI_CLASS_HOST_H__
+
+ /* Includes: */
+ #include "../../USB.h"
+ #include "../Common/StillImageClassCommon.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_SI_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Error code for some Still Image Host functions, indicating a logical (and not hardware) error. */
+ #define SI_ERROR_LOGICAL_CMD_FAILED 0x80
+
+ /* Type Defines: */
+ /** \brief Still Image Class Host Mode Configuration and State Structure.
+ *
+ * Class state structure. An instance of this structure should be made within the user application,
+ * and passed to each of the Still Image class driver functions as the \c SIInterfaceInfo parameter. This
+ * stores each Still Image interface's configuration and state information.
+ */
+ typedef struct
+ {
+ struct
+ {
+ USB_Pipe_Table_t DataINPipe; /**< Data IN Pipe configuration table. */
+ USB_Pipe_Table_t DataOUTPipe; /**< Data OUT Pipe configuration table. */
+ USB_Pipe_Table_t EventsPipe; /**< Event notification IN Pipe configuration table. */
+ } Config; /**< Config data for the USB class interface within the device. All elements in this section
+ * <b>must</b> be set or the interface will fail to enumerate and operate correctly.
+ */
+ struct
+ {
+ bool IsActive; /**< Indicates if the current interface instance is connected to an attached device, valid
+ * after \ref SI_Host_ConfigurePipes() is called and the Host state machine is in the
+ * Configured state.
+ */
+ uint8_t InterfaceNumber; /**< Interface index of the Still Image interface within the attached device. */
+
+ bool IsSessionOpen; /**< Indicates if a PIMA session is currently open with the attached device. */
+ uint32_t TransactionID; /**< Transaction ID for the next transaction to send to the device. */
+ } State; /**< State data for the USB class interface within the device. All elements in this section
+ * <b>may</b> be set to initial values, but may also be ignored to default to sane values when
+ * the interface is enumerated.
+ */
+ } USB_ClassInfo_SI_Host_t;
+
+ /* Enums: */
+ /** Enum for the possible error codes returned by the \ref SI_Host_ConfigurePipes() function. */
+ enum SI_Host_EnumerationFailure_ErrorCodes_t
+ {
+ SI_ENUMERROR_NoError = 0, /**< Configuration Descriptor was processed successfully. */
+ SI_ENUMERROR_InvalidConfigDescriptor = 1, /**< The device returned an invalid Configuration Descriptor. */
+ SI_ENUMERROR_NoCompatibleInterfaceFound = 2, /**< A compatible Still Image interface was not found in the device's
+ * Configuration Descriptor.
+ */
+ SI_ENUMERROR_PipeConfigurationFailed = 3, /**< One or more pipes for the specified interface could not be configured correctly. */
+ };
+
+ /* Function Prototypes: */
+ /** Host interface configuration routine, to configure a given Still Image host interface instance using the
+ * Configuration Descriptor read from an attached USB device. This function automatically updates the given Still
+ * Image Host instance's state values and configures the pipes required to communicate with the interface if it is
+ * found within the device. This should be called once after the stack has enumerated the attached device, while
+ * the host state machine is in the Addressed state.
+ *
+ * \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state.
+ * \param[in] ConfigDescriptorSize Length of the attached device's Configuration Descriptor.
+ * \param[in] ConfigDescriptorData Pointer to a buffer containing the attached device's Configuration Descriptor.
+ *
+ * \return A value from the \ref SI_Host_EnumerationFailure_ErrorCodes_t enum.
+ */
+ uint8_t SI_Host_ConfigurePipes(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
+ uint16_t ConfigDescriptorSize,
+ void* ConfigDescriptorData) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(3);
+
+ /** Opens a new PIMA session with the attached device. This should be used before any session-orientated PIMA commands
+ * are issued to the device. Only one session can be open at the one time.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum, or \ref SI_ERROR_LOGICAL_CMD_FAILED if the device
+ * returned a logical command failure.
+ */
+ uint8_t SI_Host_OpenSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Closes an already opened PIMA session with the attached device. This should be used after all session-orientated
+ * PIMA commands have been issued to the device.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum, or \ref SI_ERROR_LOGICAL_CMD_FAILED if the device
+ * returned a logical command failure.
+ */
+ uint8_t SI_Host_CloseSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Sends a raw PIMA block header to the device, filling out the transaction ID automatically. This can be used to send
+ * arbitrary PIMA blocks to the device with or without parameters.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state.
+ * \param[in] PIMAHeader Pointer to a PIMA container structure that is to be sent.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t SI_Host_SendBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
+ PIMA_Container_t* const PIMAHeader) ATTR_NON_NULL_PTR_ARG(1)
+ ATTR_NON_NULL_PTR_ARG(2);
+
+ /** Receives a raw PIMA block header from the device. This can be used to receive arbitrary PIMA blocks from the device with
+ * or without parameters.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state.
+ * \param[out] PIMAHeader Pointer to a PIMA container structure where the received block is to be stored.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t SI_Host_ReceiveBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
+ PIMA_Container_t* const PIMAHeader) ATTR_NON_NULL_PTR_ARG(1)
+ ATTR_NON_NULL_PTR_ARG(2);
+
+ /** Sends a given PIMA command to the attached device, filling out the PIMA command header's Transaction ID automatically.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state.
+ * \param[in] Operation PIMA operation code to issue to the device.
+ * \param[in] TotalParams Total number of 32-bit parameters to send to the device in the issued command block.
+ * \param[in] Params Pointer to an array of 32-bit values containing the parameters to send in the command block.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum, or \ref SI_ERROR_LOGICAL_CMD_FAILED if the device
+ * returned a logical command failure.
+ */
+ uint8_t SI_Host_SendCommand(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
+ const uint16_t Operation,
+ const uint8_t TotalParams,
+ uint32_t* const Params) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Receives and checks a response block from the attached Still Image device, once a command has been issued and all data
+ * associated with the command has been transferred.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum, or \ref SI_ERROR_LOGICAL_CMD_FAILED if the device
+ * returned a logical command failure.
+ */
+ uint8_t SI_Host_ReceiveResponse(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Indicates if the device has issued a PIMA event block to the host via the asynchronous events pipe.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state.
+ *
+ * \return Boolean \c true if an event is waiting to be read, \c false otherwise.
+ */
+ bool SI_Host_IsEventReceived(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Receives an asynchronous event block from the device via the asynchronous events pipe.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state.
+ * \param[out] PIMAHeader Pointer to a PIMA container structure where the event should be stored.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum, or \ref SI_ERROR_LOGICAL_CMD_FAILED if the device
+ * returned a logical command failure.
+ */
+ uint8_t SI_Host_ReceiveEventHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
+ PIMA_Container_t* const PIMAHeader) ATTR_NON_NULL_PTR_ARG(1)
+ ATTR_NON_NULL_PTR_ARG(2);
+
+ /** Sends arbitrary data to the attached device, for use in the data phase of PIMA commands which require data
+ * transfer beyond the regular PIMA command block parameters.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state.
+ * \param[in] Buffer Pointer to a buffer where the data to send has been stored.
+ * \param[in] Bytes Length in bytes of the data in the buffer to send to the attached device.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t SI_Host_SendData(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
+ const void* Buffer,
+ const uint16_t Bytes) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+
+ /** Receives arbitrary data from the attached device, for use in the data phase of PIMA commands which require data
+ * transfer beyond the regular PIMA command block parameters.
+ *
+ * \pre This function must only be called when the Host state machine is in the \ref HOST_STATE_Configured state or the
+ * call will fail.
+ *
+ * \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state.
+ * \param[out] Buffer Pointer to a buffer where the received data is to be stored.
+ * \param[in] Bytes Length in bytes of the data to read.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t SI_Host_ReadData(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
+ void* Buffer,
+ const uint16_t Bytes) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+
+ /* Inline Functions: */
+ /** General management task for a given Still Image host class interface, required for the correct operation of the
+ * interface. This should be called frequently in the main program loop, before the master USB management task
+ * \ref USB_USBTask().
+ *
+ * \param[in,out] SIInterfaceInfo Pointer to a structure containing a Still Image Class host configuration and state.
+ */
+ static inline void SI_Host_USBTask(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo) ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
+ static inline void SI_Host_USBTask(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
+ {
+ (void)SIInterfaceInfo;
+ }
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define SI_COMMAND_DATA_TIMEOUT_MS 10000
+
+ /* Function Prototypes: */
+ #if defined(__INCLUDE_FROM_STILLIMAGE_HOST_C)
+ static uint8_t DCOMP_SI_Host_NextSIInterface(void* const CurrentDescriptor)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ static uint8_t DCOMP_SI_Host_NextSIInterfaceEndpoint(void* const CurrentDescriptor)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(1);
+ #endif
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/MIDIClass.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/MIDIClass.h
new file mode 100644
index 000000000..7e6ba1c5b
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/MIDIClass.h
@@ -0,0 +1,84 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Master include file for the library USB MIDI Class driver.
+ *
+ * Master include file for the library USB MIDI Class driver, for both host and device modes, where available.
+ *
+ * This file should be included in all user projects making use of this optional class driver, instead of
+ * including any headers in the USB/ClassDriver/Device, USB/ClassDriver/Host or USB/ClassDriver/Common subdirectories.
+ */
+
+/** \ingroup Group_USBClassDrivers
+ * \defgroup Group_USBClassMIDI MIDI Class Driver
+ * \brief USB class driver for the USB-IF MIDI class standard.
+ *
+ * \section Sec_USBClassMIDI_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Drivers/USB/Class/Device/MIDIClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ * - LUFA/Drivers/USB/Class/Host/MIDIClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ *
+ * \section Sec_USBClassMIDI_ModDescription Module Description
+ * MIDI Class Driver module. This module contains an internal implementation of the USB MIDI Class, for both Device
+ * and Host USB modes. User applications can use this class driver instead of implementing the MIDI class manually
+ * via the low-level LUFA APIs.
+ *
+ * This module is designed to simplify the user code by exposing only the required interface needed to interface with
+ * Hosts or Devices using the USB MIDI Class.
+ *
+ * \note The USB MIDI class is actually a special case of the regular Audio class, thus this module depends on
+ * structure definitions from the \ref Group_USBClassAudioDevice class driver module.
+ *
+ * @{
+ */
+
+#ifndef _MIDI_CLASS_H_
+#define _MIDI_CLASS_H_
+
+ /* Macros: */
+ #define __INCLUDE_FROM_USB_DRIVER
+ #define __INCLUDE_FROM_MIDI_DRIVER
+
+ /* Includes: */
+ #include "../Core/USBMode.h"
+
+ #if defined(USB_CAN_BE_DEVICE)
+ #include "Device/MIDIClassDevice.h"
+ #endif
+
+ #if defined(USB_CAN_BE_HOST)
+ #include "Host/MIDIClassHost.h"
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/MassStorageClass.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/MassStorageClass.h
new file mode 100644
index 000000000..79a052163
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/MassStorageClass.h
@@ -0,0 +1,81 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Master include file for the library USB Mass Storage Class driver.
+ *
+ * Master include file for the library USB Mass Storage Class driver, for both host and device modes, where available.
+ *
+ * This file should be included in all user projects making use of this optional class driver, instead of
+ * including any headers in the USB/ClassDriver/Device, USB/ClassDriver/Host or USB/ClassDriver/Common subdirectories.
+ */
+
+/** \ingroup Group_USBClassDrivers
+ * \defgroup Group_USBClassMS Mass Storage Class Driver
+ * \brief USB class driver for the USB-IF Bulk-Only Transport Mass Storage class standard.
+ *
+ * \section Sec_USBClassMS_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ * - LUFA/Drivers/USB/Class/Host/MassStorageClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ *
+ * \section Sec_USBClassMS_ModDescription Module Description
+ * Mass Storage Class Driver module. This module contains an internal implementation of the USB Mass Storage Class, for both
+ * Device and Host USB modes. User applications can use this class driver instead of implementing the Mass Storage class
+ * manually via the low-level LUFA APIs.
+ *
+ * This module is designed to simplify the user code by exposing only the required interface needed to interface with
+ * Hosts or Devices using the USB Mass Storage Class.
+ *
+ * @{
+ */
+
+#ifndef _MS_CLASS_H_
+#define _MS_CLASS_H_
+
+ /* Macros: */
+ #define __INCLUDE_FROM_USB_DRIVER
+ #define __INCLUDE_FROM_MS_DRIVER
+
+ /* Includes: */
+ #include "../Core/USBMode.h"
+
+ #if defined(USB_CAN_BE_DEVICE)
+ #include "Device/MassStorageClassDevice.h"
+ #endif
+
+ #if defined(USB_CAN_BE_HOST)
+ #include "Host/MassStorageClassHost.h"
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/PrinterClass.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/PrinterClass.h
new file mode 100644
index 000000000..91121b5d0
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/PrinterClass.h
@@ -0,0 +1,83 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Master include file for the library USB Printer Class driver.
+ *
+ * Master include file for the library USB Printer Class driver, for both host and device modes, where available.
+ *
+ * This file should be included in all user projects making use of this optional class driver, instead of
+ * including any headers in the USB/ClassDriver/Device, USB/ClassDriver/Host or USB/ClassDriver/Common subdirectories.
+ */
+
+/** \ingroup Group_USBClassDrivers
+ * \defgroup Group_USBClassPrinter Printer Class Driver
+ * \brief USB class driver for the USB-IF Printer class standard.
+ *
+ * \section Sec_USBClassPrinter_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Drivers/USB/Class/Host/PrinterClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ * - LUFA/Drivers/USB/Class/Host/PrinterClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ *
+ * \section Sec_USBClassPrinter_ModDescription Module Description
+ * Printer Class Driver module. This module contains an internal implementation of the USB Printer Class, for the base
+ * USB Printer transport layer for USB Host mode only. Note that printers are free to implement whatever printer language
+ * they choose on top of this (e.g. Postscript), and so this driver exposes low level data transport functions only rather
+ * than high level raster or text functions. User applications can use this class driver instead of implementing the Printer
+ * class manually via the low-level LUFA APIs.
+ *
+ * This module is designed to simplify the user code by exposing only the required interface needed to interface with
+ * Devices using the USB Printer Class.
+ *
+ * @{
+ */
+
+#ifndef _PRINTER_CLASS_H_
+#define _PRINTER_CLASS_H_
+
+ /* Macros: */
+ #define __INCLUDE_FROM_USB_DRIVER
+ #define __INCLUDE_FROM_PRINTER_DRIVER
+
+ /* Includes: */
+ #include "../Core/USBMode.h"
+
+ #if defined(USB_CAN_BE_DEVICE)
+ #include "Device/PrinterClassDevice.h"
+ #endif
+
+ #if defined(USB_CAN_BE_HOST)
+ #include "Host/PrinterClassHost.h"
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/RNDISClass.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/RNDISClass.h
new file mode 100644
index 000000000..1555f0d23
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/RNDISClass.h
@@ -0,0 +1,81 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Master include file for the library USB RNDIS Class driver.
+ *
+ * Master include file for the library USB RNDIS Class driver, for both host and device modes, where available.
+ *
+ * This file should be included in all user projects making use of this optional class driver, instead of
+ * including any headers in the USB/ClassDriver/Device, USB/ClassDriver/Host or USB/ClassDriver/Common subdirectories.
+ */
+
+/** \ingroup Group_USBClassDrivers
+ * \defgroup Group_USBClassRNDIS RNDIS (Networking) Class Driver
+ * \brief USB class driver for the Microsoft Remote Network Driver Interface Specification (RNDIS) class standard.
+ *
+ * \section Sec_USBClassRNDIS_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Drivers/USB/Class/Device/RNDISClassDevice.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ * - LUFA/Drivers/USB/Class/Host/RNDISClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ *
+ * \section Sec_USBClassRNDIS_ModDescription Module Description
+ * RNDIS Class Driver module. This module contains an internal implementation of the Microsoft USB RNDIS Networking
+ * Class, for both Device and Host USB modes. User applications can use this class driver instead of implementing the
+ * RNDIS class manually via the low-level LUFA APIs.
+ *
+ * This module is designed to simplify the user code by exposing only the required interface needed to interface with
+ * Hosts using the USB RNDIS Class.
+ *
+ * @{
+ */
+
+#ifndef _RNDIS_CLASS_H_
+#define _RNDIS_CLASS_H_
+
+ /* Macros: */
+ #define __INCLUDE_FROM_USB_DRIVER
+ #define __INCLUDE_FROM_RNDIS_DRIVER
+
+ /* Includes: */
+ #include "../Core/USBMode.h"
+
+ #if defined(USB_CAN_BE_DEVICE)
+ #include "Device/RNDISClassDevice.h"
+ #endif
+
+ #if defined(USB_CAN_BE_HOST)
+ #include "Host/RNDISClassHost.h"
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/StillImageClass.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/StillImageClass.h
new file mode 100644
index 000000000..f2ec37b03
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/StillImageClass.h
@@ -0,0 +1,76 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Master include file for the library USB Still Image Class driver.
+ *
+ * Master include file for the library USB Still Image Class driver, for both host and device modes, where available.
+ *
+ * This file should be included in all user projects making use of this optional class driver, instead of
+ * including any headers in the USB/ClassDriver/Device, USB/ClassDriver/Host or USB/ClassDriver/Common subdirectories.
+ */
+
+/** \ingroup Group_USBClassDrivers
+ * \defgroup Group_USBClassSI Still Image Class Driver
+ * \brief USB class driver for the USB-IF Still Image (PIMA-compliant) class standard.
+ *
+ * \section Sec_USBClassSI_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Drivers/USB/Class/Host/StillImageClassHost.c <i>(Makefile source module name: LUFA_SRC_USBCLASS)</i>
+ *
+ * \section Sec_USBClassSI_ModDescription Module Description
+ * Still Image Class Driver module. This module contains an internal implementation of the USB Still Image Class,
+ * for USB Host mode only. User applications can use this class driver instead of implementing the Still Image class
+ * manually via the low-level LUFA APIs.
+ *
+ * This module is designed to simplify the user code by exposing only the required interface needed to interface with
+ * Devices using the USB Still Image Class.
+ *
+ * @{
+ */
+
+#ifndef _SI_CLASS_H_
+#define _SI_CLASS_H_
+
+ /* Macros: */
+ #define __INCLUDE_FROM_USB_DRIVER
+ #define __INCLUDE_FROM_SI_DRIVER
+
+ /* Includes: */
+ #include "../Core/USBMode.h"
+
+ #if defined(USB_CAN_BE_HOST)
+ #include "Host/StillImageClassHost.h"
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Device_AVR8.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Device_AVR8.c
new file mode 100644
index 000000000..d23e7b846
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Device_AVR8.c
@@ -0,0 +1,57 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "../../../../Common/Common.h"
+#if (ARCH == ARCH_AVR8)
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../USBMode.h"
+
+#if defined(USB_CAN_BE_DEVICE)
+
+#include "../Device.h"
+
+void USB_Device_SendRemoteWakeup(void)
+{
+ if (!(USB_Options & USB_OPT_MANUAL_PLL))
+ {
+ USB_PLL_On();
+ while (!(USB_PLL_IsReady()));
+ }
+
+ USB_CLK_Unfreeze();
+
+ UDCON |= (1 << RMWKUP);
+ while (UDCON & (1 << RMWKUP));
+}
+
+#endif
+
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Device_AVR8.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Device_AVR8.h
new file mode 100644
index 000000000..5efffe7b8
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Device_AVR8.h
@@ -0,0 +1,269 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief USB Device definitions for the AVR8 microcontrollers.
+ * \copydetails Group_Device_AVR8
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_Device
+ * \defgroup Group_Device_AVR8 Device Management (AVR8)
+ * \brief USB Device definitions for the AVR8 microcontrollers.
+ *
+ * Architecture specific USB Device definitions for the Atmel 8-bit AVR microcontrollers.
+ *
+ * @{
+ */
+
+#ifndef __USBDEVICE_AVR8_H__
+#define __USBDEVICE_AVR8_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../USBController.h"
+ #include "../StdDescriptors.h"
+ #include "../USBInterrupt.h"
+ #include "../Endpoint.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ #if (defined(USE_RAM_DESCRIPTORS) && defined(USE_EEPROM_DESCRIPTORS))
+ #error USE_RAM_DESCRIPTORS and USE_EEPROM_DESCRIPTORS are mutually exclusive.
+ #endif
+
+ #if (defined(USE_FLASH_DESCRIPTORS) && defined(USE_EEPROM_DESCRIPTORS))
+ #error USE_FLASH_DESCRIPTORS and USE_EEPROM_DESCRIPTORS are mutually exclusive.
+ #endif
+
+ #if (defined(USE_FLASH_DESCRIPTORS) && defined(USE_RAM_DESCRIPTORS))
+ #error USE_FLASH_DESCRIPTORS and USE_RAM_DESCRIPTORS are mutually exclusive.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** \name USB Device Mode Option Masks */
+ //@{
+ #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) || defined(__DOXYGEN__)
+ /** Mask for the Options parameter of the \ref USB_Init() function. This indicates that the
+ * USB interface should be initialized in low speed (1.5Mb/s) mode.
+ *
+ * \note Low Speed mode is not available on all USB AVR models.
+ * \n
+ *
+ * \note Restrictions apply on the number, size and type of endpoints which can be used
+ * when running in low speed mode - please refer to the USB 2.0 specification.
+ */
+ #define USB_DEVICE_OPT_LOWSPEED (1 << 0)
+ #endif
+
+ /** Mask for the Options parameter of the \ref USB_Init() function. This indicates that the
+ * USB interface should be initialized in full speed (12Mb/s) mode.
+ */
+ #define USB_DEVICE_OPT_FULLSPEED (0 << 0)
+ //@}
+
+ #if (!defined(NO_INTERNAL_SERIAL) && \
+ (defined(USB_SERIES_7_AVR) || defined(USB_SERIES_6_AVR) || \
+ defined(USB_SERIES_4_AVR) || defined(USB_SERIES_2_AVR) || \
+ defined(__DOXYGEN__)))
+ /** String descriptor index for the device's unique serial number string descriptor within the device.
+ * This unique serial number is used by the host to associate resources to the device (such as drivers or COM port
+ * number allocations) to a device regardless of the port it is plugged in to on the host. Some microcontrollers contain
+ * a unique serial number internally, and setting the device descriptors serial number string index to this value
+ * will cause it to use the internal serial number.
+ *
+ * On unsupported devices, this will evaluate to \ref NO_DESCRIPTOR and so will force the host to create a pseudo-serial
+ * number for the device.
+ */
+ #define USE_INTERNAL_SERIAL 0xDC
+
+ /** Length of the device's unique internal serial number, in bits, if present on the selected microcontroller
+ * model.
+ */
+ #define INTERNAL_SERIAL_LENGTH_BITS 80
+
+ /** Start address of the internal serial number, in the appropriate address space, if present on the selected microcontroller
+ * model.
+ */
+ #define INTERNAL_SERIAL_START_ADDRESS 0x0E
+ #else
+ #define USE_INTERNAL_SERIAL NO_DESCRIPTOR
+
+ #define INTERNAL_SERIAL_LENGTH_BITS 0
+ #define INTERNAL_SERIAL_START_ADDRESS 0
+ #endif
+
+ /* Function Prototypes: */
+ /** Sends a Remote Wakeup request to the host. This signals to the host that the device should
+ * be taken out of suspended mode, and communications should resume.
+ *
+ * Typically, this is implemented so that HID devices (mice, keyboards, etc.) can wake up the
+ * host computer when the host has suspended all USB devices to enter a low power state.
+ *
+ * \attention This function should only be used if the device has indicated to the host that it
+ * supports the Remote Wakeup feature in the device descriptors, and should only be
+ * issued if the host is currently allowing remote wakeup events from the device (i.e.,
+ * the \ref USB_Device_RemoteWakeupEnabled flag is set). When the \c NO_DEVICE_REMOTE_WAKEUP
+ * compile time option is used, this function is unavailable.
+ * \n\n
+ *
+ * \attention The USB clock must be running for this function to operate. If the stack is initialized with
+ * the \ref USB_OPT_MANUAL_PLL option enabled, the user must ensure that the PLL is running
+ * before attempting to call this function.
+ *
+ * \see \ref Group_StdDescriptors for more information on the RMWAKEUP feature and device descriptors.
+ */
+ void USB_Device_SendRemoteWakeup(void);
+
+ /* Inline Functions: */
+ /** Returns the current USB frame number, when in device mode. Every millisecond the USB bus is active (i.e. enumerated to a host)
+ * the frame number is incremented by one.
+ *
+ * \return Current USB frame number from the USB controller.
+ */
+ static inline uint16_t USB_Device_GetFrameNumber(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline uint16_t USB_Device_GetFrameNumber(void)
+ {
+ return UDFNUM;
+ }
+
+ #if !defined(NO_SOF_EVENTS)
+ /** Enables the device mode Start Of Frame events. When enabled, this causes the
+ * \ref EVENT_USB_Device_StartOfFrame() event to fire once per millisecond, synchronized to the USB bus,
+ * at the start of each USB frame when enumerated in device mode.
+ *
+ * \note This function is not available when the \c NO_SOF_EVENTS compile time token is defined.
+ */
+ static inline void USB_Device_EnableSOFEvents(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Device_EnableSOFEvents(void)
+ {
+ USB_INT_Enable(USB_INT_SOFI);
+ }
+
+ /** Disables the device mode Start Of Frame events. When disabled, this stops the firing of the
+ * \ref EVENT_USB_Device_StartOfFrame() event when enumerated in device mode.
+ *
+ * \note This function is not available when the \c NO_SOF_EVENTS compile time token is defined.
+ */
+ static inline void USB_Device_DisableSOFEvents(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Device_DisableSOFEvents(void)
+ {
+ USB_INT_Disable(USB_INT_SOFI);
+ }
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Inline Functions: */
+ #if defined(USB_DEVICE_OPT_LOWSPEED)
+ static inline void USB_Device_SetLowSpeed(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Device_SetLowSpeed(void)
+ {
+ UDCON |= (1 << LSM);
+ }
+
+ static inline void USB_Device_SetFullSpeed(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Device_SetFullSpeed(void)
+ {
+ UDCON &= ~(1 << LSM);
+ }
+ #endif
+
+ static inline void USB_Device_SetDeviceAddress(const uint8_t Address) ATTR_ALWAYS_INLINE;
+ static inline void USB_Device_SetDeviceAddress(const uint8_t Address)
+ {
+ UDADDR = (UDADDR & (1 << ADDEN)) | (Address & 0x7F);
+ }
+
+ static inline void USB_Device_EnableDeviceAddress(const uint8_t Address) ATTR_ALWAYS_INLINE;
+ static inline void USB_Device_EnableDeviceAddress(const uint8_t Address)
+ {
+ (void)Address;
+
+ UDADDR |= (1 << ADDEN);
+ }
+
+ static inline bool USB_Device_IsAddressSet(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline bool USB_Device_IsAddressSet(void)
+ {
+ return (UDADDR & (1 << ADDEN));
+ }
+
+ #if (USE_INTERNAL_SERIAL != NO_DESCRIPTOR)
+ static inline void USB_Device_GetSerialString(uint16_t* const UnicodeString) ATTR_NON_NULL_PTR_ARG(1);
+ static inline void USB_Device_GetSerialString(uint16_t* const UnicodeString)
+ {
+ uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask();
+ GlobalInterruptDisable();
+
+ uint8_t SigReadAddress = INTERNAL_SERIAL_START_ADDRESS;
+
+ for (uint8_t SerialCharNum = 0; SerialCharNum < (INTERNAL_SERIAL_LENGTH_BITS / 4); SerialCharNum++)
+ {
+ uint8_t SerialByte = boot_signature_byte_get(SigReadAddress);
+
+ if (SerialCharNum & 0x01)
+ {
+ SerialByte >>= 4;
+ SigReadAddress++;
+ }
+
+ SerialByte &= 0x0F;
+
+ UnicodeString[SerialCharNum] = cpu_to_le16((SerialByte >= 10) ?
+ (('A' - 10) + SerialByte) : ('0' + SerialByte));
+ }
+
+ SetGlobalInterruptMask(CurrentGlobalInt);
+ }
+ #endif
+
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/EndpointStream_AVR8.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/EndpointStream_AVR8.c
new file mode 100644
index 000000000..5782824cc
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/EndpointStream_AVR8.c
@@ -0,0 +1,275 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "../../../../Common/Common.h"
+#if (ARCH == ARCH_AVR8)
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../USBMode.h"
+
+#if defined(USB_CAN_BE_DEVICE)
+
+#include "EndpointStream_AVR8.h"
+
+#if !defined(CONTROL_ONLY_DEVICE)
+uint8_t Endpoint_Discard_Stream(uint16_t Length,
+ uint16_t* const BytesProcessed)
+{
+ uint8_t ErrorCode;
+ uint16_t BytesInTransfer = 0;
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()))
+ return ErrorCode;
+
+ if (BytesProcessed != NULL)
+ Length -= *BytesProcessed;
+
+ while (Length)
+ {
+ if (!(Endpoint_IsReadWriteAllowed()))
+ {
+ Endpoint_ClearOUT();
+
+ if (BytesProcessed != NULL)
+ {
+ *BytesProcessed += BytesInTransfer;
+ return ENDPOINT_RWSTREAM_IncompleteTransfer;
+ }
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()))
+ return ErrorCode;
+ }
+ else
+ {
+ Endpoint_Discard_8();
+
+ Length--;
+ BytesInTransfer++;
+ }
+ }
+
+ return ENDPOINT_RWSTREAM_NoError;
+}
+
+uint8_t Endpoint_Null_Stream(uint16_t Length,
+ uint16_t* const BytesProcessed)
+{
+ uint8_t ErrorCode;
+ uint16_t BytesInTransfer = 0;
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()))
+ return ErrorCode;
+
+ if (BytesProcessed != NULL)
+ Length -= *BytesProcessed;
+
+ while (Length)
+ {
+ if (!(Endpoint_IsReadWriteAllowed()))
+ {
+ Endpoint_ClearIN();
+
+ if (BytesProcessed != NULL)
+ {
+ *BytesProcessed += BytesInTransfer;
+ return ENDPOINT_RWSTREAM_IncompleteTransfer;
+ }
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()))
+ return ErrorCode;
+ }
+ else
+ {
+ Endpoint_Write_8(0);
+
+ Length--;
+ BytesInTransfer++;
+ }
+ }
+
+ return ENDPOINT_RWSTREAM_NoError;
+}
+
+/* The following abuses the C preprocessor in order to copy-paste common code with slight alterations,
+ * so that the code needs to be written once. It is a crude form of templating to reduce code maintenance. */
+
+#define TEMPLATE_FUNC_NAME Endpoint_Write_Stream_LE
+#define TEMPLATE_BUFFER_TYPE const void*
+#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearIN()
+#define TEMPLATE_BUFFER_OFFSET(Length) 0
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(*BufferPtr)
+#include "Template/Template_Endpoint_RW.c"
+
+#define TEMPLATE_FUNC_NAME Endpoint_Write_Stream_BE
+#define TEMPLATE_BUFFER_TYPE const void*
+#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearIN()
+#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(*BufferPtr)
+#include "Template/Template_Endpoint_RW.c"
+
+#define TEMPLATE_FUNC_NAME Endpoint_Read_Stream_LE
+#define TEMPLATE_BUFFER_TYPE void*
+#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearOUT()
+#define TEMPLATE_BUFFER_OFFSET(Length) 0
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) *BufferPtr = Endpoint_Read_8()
+#include "Template/Template_Endpoint_RW.c"
+
+#define TEMPLATE_FUNC_NAME Endpoint_Read_Stream_BE
+#define TEMPLATE_BUFFER_TYPE void*
+#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearOUT()
+#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) *BufferPtr = Endpoint_Read_8()
+#include "Template/Template_Endpoint_RW.c"
+
+#if defined(ARCH_HAS_FLASH_ADDRESS_SPACE)
+ #define TEMPLATE_FUNC_NAME Endpoint_Write_PStream_LE
+ #define TEMPLATE_BUFFER_TYPE const void*
+ #define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearIN()
+ #define TEMPLATE_BUFFER_OFFSET(Length) 0
+ #define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
+ #define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(pgm_read_byte(BufferPtr))
+ #include "Template/Template_Endpoint_RW.c"
+
+ #define TEMPLATE_FUNC_NAME Endpoint_Write_PStream_BE
+ #define TEMPLATE_BUFFER_TYPE const void*
+ #define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearIN()
+ #define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+ #define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
+ #define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(pgm_read_byte(BufferPtr))
+ #include "Template/Template_Endpoint_RW.c"
+#endif
+
+#if defined(ARCH_HAS_EEPROM_ADDRESS_SPACE)
+ #define TEMPLATE_FUNC_NAME Endpoint_Write_EStream_LE
+ #define TEMPLATE_BUFFER_TYPE const void*
+ #define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearIN()
+ #define TEMPLATE_BUFFER_OFFSET(Length) 0
+ #define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
+ #define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(eeprom_read_byte(BufferPtr))
+ #include "Template/Template_Endpoint_RW.c"
+
+ #define TEMPLATE_FUNC_NAME Endpoint_Write_EStream_BE
+ #define TEMPLATE_BUFFER_TYPE const void*
+ #define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearIN()
+ #define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+ #define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
+ #define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(eeprom_read_byte(BufferPtr))
+ #include "Template/Template_Endpoint_RW.c"
+
+ #define TEMPLATE_FUNC_NAME Endpoint_Read_EStream_LE
+ #define TEMPLATE_BUFFER_TYPE void*
+ #define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearOUT()
+ #define TEMPLATE_BUFFER_OFFSET(Length) 0
+ #define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
+ #define TEMPLATE_TRANSFER_BYTE(BufferPtr) eeprom_update_byte(BufferPtr, Endpoint_Read_8())
+ #include "Template/Template_Endpoint_RW.c"
+
+ #define TEMPLATE_FUNC_NAME Endpoint_Read_EStream_BE
+ #define TEMPLATE_BUFFER_TYPE void*
+ #define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearOUT()
+ #define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+ #define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
+ #define TEMPLATE_TRANSFER_BYTE(BufferPtr) eeprom_update_byte(BufferPtr, Endpoint_Read_8())
+ #include "Template/Template_Endpoint_RW.c"
+#endif
+
+#endif
+
+#define TEMPLATE_FUNC_NAME Endpoint_Write_Control_Stream_LE
+#define TEMPLATE_BUFFER_OFFSET(Length) 0
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(*BufferPtr)
+#include "Template/Template_Endpoint_Control_W.c"
+
+#define TEMPLATE_FUNC_NAME Endpoint_Write_Control_Stream_BE
+#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(*BufferPtr)
+#include "Template/Template_Endpoint_Control_W.c"
+
+#define TEMPLATE_FUNC_NAME Endpoint_Read_Control_Stream_LE
+#define TEMPLATE_BUFFER_OFFSET(Length) 0
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) *BufferPtr = Endpoint_Read_8()
+#include "Template/Template_Endpoint_Control_R.c"
+
+#define TEMPLATE_FUNC_NAME Endpoint_Read_Control_Stream_BE
+#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) *BufferPtr = Endpoint_Read_8()
+#include "Template/Template_Endpoint_Control_R.c"
+
+#if defined(ARCH_HAS_FLASH_ADDRESS_SPACE)
+ #define TEMPLATE_FUNC_NAME Endpoint_Write_Control_PStream_LE
+ #define TEMPLATE_BUFFER_OFFSET(Length) 0
+ #define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
+ #define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(pgm_read_byte(BufferPtr))
+ #include "Template/Template_Endpoint_Control_W.c"
+
+ #define TEMPLATE_FUNC_NAME Endpoint_Write_Control_PStream_BE
+ #define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+ #define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
+ #define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(pgm_read_byte(BufferPtr))
+ #include "Template/Template_Endpoint_Control_W.c"
+#endif
+
+#if defined(ARCH_HAS_EEPROM_ADDRESS_SPACE)
+ #define TEMPLATE_FUNC_NAME Endpoint_Write_Control_EStream_LE
+ #define TEMPLATE_BUFFER_OFFSET(Length) 0
+ #define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
+ #define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(eeprom_read_byte(BufferPtr))
+ #include "Template/Template_Endpoint_Control_W.c"
+
+ #define TEMPLATE_FUNC_NAME Endpoint_Write_Control_EStream_BE
+ #define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+ #define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
+ #define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(eeprom_read_byte(BufferPtr))
+ #include "Template/Template_Endpoint_Control_W.c"
+
+ #define TEMPLATE_FUNC_NAME Endpoint_Read_Control_EStream_LE
+ #define TEMPLATE_BUFFER_OFFSET(Length) 0
+ #define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
+ #define TEMPLATE_TRANSFER_BYTE(BufferPtr) eeprom_update_byte(BufferPtr, Endpoint_Read_8())
+ #include "Template/Template_Endpoint_Control_R.c"
+
+ #define TEMPLATE_FUNC_NAME Endpoint_Read_Control_EStream_BE
+ #define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+ #define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
+ #define TEMPLATE_TRANSFER_BYTE(BufferPtr) eeprom_update_byte(BufferPtr, Endpoint_Read_8())
+ #include "Template/Template_Endpoint_Control_R.c"
+#endif
+
+#endif
+
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/EndpointStream_AVR8.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/EndpointStream_AVR8.h
new file mode 100644
index 000000000..203278976
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/EndpointStream_AVR8.h
@@ -0,0 +1,658 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Endpoint data stream transmission and reception management for the AVR8 microcontrollers.
+ * \copydetails Group_EndpointStreamRW_AVR8
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_EndpointStreamRW
+ * \defgroup Group_EndpointStreamRW_AVR8 Read/Write of Multi-Byte Streams (AVR8)
+ * \brief Endpoint data stream transmission and reception management for the Atmel AVR8 architecture.
+ *
+ * Functions, macros, variables, enums and types related to data reading and writing of data streams from
+ * and to endpoints.
+ *
+ * @{
+ */
+
+#ifndef __ENDPOINT_STREAM_AVR8_H__
+#define __ENDPOINT_STREAM_AVR8_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../USBMode.h"
+ #include "../USBTask.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Function Prototypes: */
+ /** \name Stream functions for null data */
+ //@{
+
+ /** Reads and discards the given number of bytes from the currently selected endpoint's bank,
+ * discarding fully read packets from the host as needed. The last packet is not automatically
+ * discarded once the remaining bytes has been read; the user is responsible for manually
+ * discarding the last packet from the host via the \ref Endpoint_ClearOUT() macro.
+ *
+ * If the BytesProcessed parameter is \c NULL, the entire stream transfer is attempted at once,
+ * failing or succeeding as a single unit. If the BytesProcessed parameter points to a valid
+ * storage location, the transfer will instead be performed as a series of chunks. Each time
+ * the endpoint bank becomes empty while there is still data to process (and after the current
+ * packet has been acknowledged) the BytesProcessed location will be updated with the total number
+ * of bytes processed in the stream, and the function will exit with an error code of
+ * \ref ENDPOINT_RWSTREAM_IncompleteTransfer. This allows for any abort checking to be performed
+ * in the user code - to continue the transfer, call the function again with identical parameters
+ * and it will resume until the BytesProcessed value reaches the total transfer length.
+ *
+ * <b>Single Stream Transfer Example:</b>
+ * \code
+ * uint8_t ErrorCode;
+ *
+ * if ((ErrorCode = Endpoint_Discard_Stream(512, NULL)) != ENDPOINT_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * <b>Partial Stream Transfers Example:</b>
+ * \code
+ * uint8_t ErrorCode;
+ * uint16_t BytesProcessed;
+ *
+ * BytesProcessed = 0;
+ * while ((ErrorCode = Endpoint_Discard_Stream(512, &BytesProcessed)) == ENDPOINT_RWSTREAM_IncompleteTransfer)
+ * {
+ * // Stream not yet complete - do other actions here, abort if required
+ * }
+ *
+ * if (ErrorCode != ENDPOINT_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * \note This routine should not be used on CONTROL type endpoints.
+ *
+ * \param[in] Length Number of bytes to discard via the currently selected endpoint.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
+ * transaction should be updated, \c NULL if the entire stream should be read at once.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Discard_Stream(uint16_t Length,
+ uint16_t* const BytesProcessed);
+
+ /** Writes a given number of zeroed bytes to the currently selected endpoint's bank, sending
+ * full packets to the host as needed. The last packet is not automatically sent once the
+ * remaining bytes have been written; the user is responsible for manually sending the last
+ * packet to the host via the \ref Endpoint_ClearIN() macro.
+ *
+ * If the BytesProcessed parameter is \c NULL, the entire stream transfer is attempted at once,
+ * failing or succeeding as a single unit. If the BytesProcessed parameter points to a valid
+ * storage location, the transfer will instead be performed as a series of chunks. Each time
+ * the endpoint bank becomes full while there is still data to process (and after the current
+ * packet transmission has been initiated) the BytesProcessed location will be updated with the
+ * total number of bytes processed in the stream, and the function will exit with an error code of
+ * \ref ENDPOINT_RWSTREAM_IncompleteTransfer. This allows for any abort checking to be performed
+ * in the user code - to continue the transfer, call the function again with identical parameters
+ * and it will resume until the BytesProcessed value reaches the total transfer length.
+ *
+ * <b>Single Stream Transfer Example:</b>
+ * \code
+ * uint8_t ErrorCode;
+ *
+ * if ((ErrorCode = Endpoint_Null_Stream(512, NULL)) != ENDPOINT_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * <b>Partial Stream Transfers Example:</b>
+ * \code
+ * uint8_t ErrorCode;
+ * uint16_t BytesProcessed;
+ *
+ * BytesProcessed = 0;
+ * while ((ErrorCode = Endpoint_Null_Stream(512, &BytesProcessed)) == ENDPOINT_RWSTREAM_IncompleteTransfer)
+ * {
+ * // Stream not yet complete - do other actions here, abort if required
+ * }
+ *
+ * if (ErrorCode != ENDPOINT_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * \note This routine should not be used on CONTROL type endpoints.
+ *
+ * \param[in] Length Number of zero bytes to send via the currently selected endpoint.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
+ * transaction should be updated, \c NULL if the entire stream should be read at once.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Null_Stream(uint16_t Length,
+ uint16_t* const BytesProcessed);
+
+ //@}
+
+ /** \name Stream functions for RAM source/destination data */
+ //@{
+
+ /** Writes the given number of bytes to the endpoint from the given buffer in little endian,
+ * sending full packets to the host as needed. The last packet filled is not automatically sent;
+ * the user is responsible for manually sending the last written packet to the host via the
+ * \ref Endpoint_ClearIN() macro.
+ *
+ * If the BytesProcessed parameter is \c NULL, the entire stream transfer is attempted at once,
+ * failing or succeeding as a single unit. If the BytesProcessed parameter points to a valid
+ * storage location, the transfer will instead be performed as a series of chunks. Each time
+ * the endpoint bank becomes full while there is still data to process (and after the current
+ * packet transmission has been initiated) the BytesProcessed location will be updated with the
+ * total number of bytes processed in the stream, and the function will exit with an error code of
+ * \ref ENDPOINT_RWSTREAM_IncompleteTransfer. This allows for any abort checking to be performed
+ * in the user code - to continue the transfer, call the function again with identical parameters
+ * and it will resume until the BytesProcessed value reaches the total transfer length.
+ *
+ * <b>Single Stream Transfer Example:</b>
+ * \code
+ * uint8_t DataStream[512];
+ * uint8_t ErrorCode;
+ *
+ * if ((ErrorCode = Endpoint_Write_Stream_LE(DataStream, sizeof(DataStream),
+ * NULL)) != ENDPOINT_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * <b>Partial Stream Transfers Example:</b>
+ * \code
+ * uint8_t DataStream[512];
+ * uint8_t ErrorCode;
+ * uint16_t BytesProcessed;
+ *
+ * BytesProcessed = 0;
+ * while ((ErrorCode = Endpoint_Write_Stream_LE(DataStream, sizeof(DataStream),
+ * &BytesProcessed)) == ENDPOINT_RWSTREAM_IncompleteTransfer)
+ * {
+ * // Stream not yet complete - do other actions here, abort if required
+ * }
+ *
+ * if (ErrorCode != ENDPOINT_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * \note This routine should not be used on CONTROL type endpoints.
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
+ * transaction should be updated, \c NULL if the entire stream should be written at once.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_Stream_LE(const void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Writes the given number of bytes to the endpoint from the given buffer in big endian,
+ * sending full packets to the host as needed. The last packet filled is not automatically sent;
+ * the user is responsible for manually sending the last written packet to the host via the
+ * \ref Endpoint_ClearIN() macro.
+ *
+ * \note This routine should not be used on CONTROL type endpoints.
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
+ * transaction should be updated, \c NULL if the entire stream should be written at once.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_Stream_BE(const void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Reads the given number of bytes from the endpoint from the given buffer in little endian,
+ * discarding fully read packets from the host as needed. The last packet is not automatically
+ * discarded once the remaining bytes has been read; the user is responsible for manually
+ * discarding the last packet from the host via the \ref Endpoint_ClearOUT() macro.
+ *
+ * If the BytesProcessed parameter is \c NULL, the entire stream transfer is attempted at once,
+ * failing or succeeding as a single unit. If the BytesProcessed parameter points to a valid
+ * storage location, the transfer will instead be performed as a series of chunks. Each time
+ * the endpoint bank becomes empty while there is still data to process (and after the current
+ * packet has been acknowledged) the BytesProcessed location will be updated with the total number
+ * of bytes processed in the stream, and the function will exit with an error code of
+ * \ref ENDPOINT_RWSTREAM_IncompleteTransfer. This allows for any abort checking to be performed
+ * in the user code - to continue the transfer, call the function again with identical parameters
+ * and it will resume until the BytesProcessed value reaches the total transfer length.
+ *
+ * <b>Single Stream Transfer Example:</b>
+ * \code
+ * uint8_t DataStream[512];
+ * uint8_t ErrorCode;
+ *
+ * if ((ErrorCode = Endpoint_Read_Stream_LE(DataStream, sizeof(DataStream),
+ * NULL)) != ENDPOINT_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * <b>Partial Stream Transfers Example:</b>
+ * \code
+ * uint8_t DataStream[512];
+ * uint8_t ErrorCode;
+ * uint16_t BytesProcessed;
+ *
+ * BytesProcessed = 0;
+ * while ((ErrorCode = Endpoint_Read_Stream_LE(DataStream, sizeof(DataStream),
+ * &BytesProcessed)) == ENDPOINT_RWSTREAM_IncompleteTransfer)
+ * {
+ * // Stream not yet complete - do other actions here, abort if required
+ * }
+ *
+ * if (ErrorCode != ENDPOINT_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * \note This routine should not be used on CONTROL type endpoints.
+ *
+ * \param[out] Buffer Pointer to the destination data buffer to write to.
+ * \param[in] Length Number of bytes to send via the currently selected endpoint.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
+ * transaction should be updated, \c NULL if the entire stream should be read at once.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Read_Stream_LE(void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Reads the given number of bytes from the endpoint from the given buffer in big endian,
+ * discarding fully read packets from the host as needed. The last packet is not automatically
+ * discarded once the remaining bytes has been read; the user is responsible for manually
+ * discarding the last packet from the host via the \ref Endpoint_ClearOUT() macro.
+ *
+ * \note This routine should not be used on CONTROL type endpoints.
+ *
+ * \param[out] Buffer Pointer to the destination data buffer to write to.
+ * \param[in] Length Number of bytes to send via the currently selected endpoint.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
+ * transaction should be updated, \c NULL if the entire stream should be read at once.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Read_Stream_BE(void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Writes the given number of bytes to the CONTROL type endpoint from the given buffer in little endian,
+ * sending full packets to the host as needed. The host OUT acknowledgement is not automatically cleared
+ * in both failure and success states; the user is responsible for manually clearing the status OUT packet
+ * to finalize the transfer's status stage via the \ref Endpoint_ClearOUT() macro.
+ *
+ * \note This function automatically sends the last packet in the data stage of the transaction; when the
+ * function returns, the user is responsible for clearing the <b>status</b> stage of the transaction.
+ * Note that the status stage packet is sent or received in the opposite direction of the data flow.
+ * \n\n
+ *
+ * \note This routine should only be used on CONTROL type endpoints.
+ *
+ * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
+ * together; i.e. the entire stream data must be read or written at the one time.
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
+ *
+ * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_Control_Stream_LE(const void* const Buffer,
+ uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Writes the given number of bytes to the CONTROL type endpoint from the given buffer in big endian,
+ * sending full packets to the host as needed. The host OUT acknowledgement is not automatically cleared
+ * in both failure and success states; the user is responsible for manually clearing the status OUT packet
+ * to finalize the transfer's status stage via the \ref Endpoint_ClearOUT() macro.
+ *
+ * \note This function automatically sends the last packet in the data stage of the transaction; when the
+ * function returns, the user is responsible for clearing the <b>status</b> stage of the transaction.
+ * Note that the status stage packet is sent or received in the opposite direction of the data flow.
+ * \n\n
+ *
+ * \note This routine should only be used on CONTROL type endpoints.
+ *
+ * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
+ * together; i.e. the entire stream data must be read or written at the one time.
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
+ *
+ * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_Control_Stream_BE(const void* const Buffer,
+ uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Reads the given number of bytes from the CONTROL endpoint from the given buffer in little endian,
+ * discarding fully read packets from the host as needed. The device IN acknowledgement is not
+ * automatically sent after success or failure states; the user is responsible for manually sending the
+ * status IN packet to finalize the transfer's status stage via the \ref Endpoint_ClearIN() macro.
+ *
+ * \note This function automatically sends the last packet in the data stage of the transaction; when the
+ * function returns, the user is responsible for clearing the <b>status</b> stage of the transaction.
+ * Note that the status stage packet is sent or received in the opposite direction of the data flow.
+ * \n\n
+ *
+ * \note This routine should only be used on CONTROL type endpoints.
+ *
+ * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
+ * together; i.e. the entire stream data must be read or written at the one time.
+ *
+ * \param[out] Buffer Pointer to the destination data buffer to write to.
+ * \param[in] Length Number of bytes to send via the currently selected endpoint.
+ *
+ * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Read_Control_Stream_LE(void* const Buffer,
+ uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Reads the given number of bytes from the CONTROL endpoint from the given buffer in big endian,
+ * discarding fully read packets from the host as needed. The device IN acknowledgement is not
+ * automatically sent after success or failure states; the user is responsible for manually sending the
+ * status IN packet to finalize the transfer's status stage via the \ref Endpoint_ClearIN() macro.
+ *
+ * \note This function automatically sends the last packet in the data stage of the transaction; when the
+ * function returns, the user is responsible for clearing the <b>status</b> stage of the transaction.
+ * Note that the status stage packet is sent or received in the opposite direction of the data flow.
+ * \n\n
+ *
+ * \note This routine should only be used on CONTROL type endpoints.
+ *
+ * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
+ * together; i.e. the entire stream data must be read or written at the one time.
+ *
+ * \param[out] Buffer Pointer to the destination data buffer to write to.
+ * \param[in] Length Number of bytes to send via the currently selected endpoint.
+ *
+ * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Read_Control_Stream_BE(void* const Buffer,
+ uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+ //@}
+
+ /** \name Stream functions for EEPROM source/destination data */
+ //@{
+
+ /** EEPROM buffer source version of \ref Endpoint_Write_Stream_LE().
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
+ * transaction should be updated, \c NULL if the entire stream should be written at once.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_EStream_LE(const void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** EEPROM buffer source version of \ref Endpoint_Write_Stream_BE().
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
+ * transaction should be updated, \c NULL if the entire stream should be written at once.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_EStream_BE(const void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** EEPROM buffer destination version of \ref Endpoint_Read_Stream_LE().
+ *
+ * \param[out] Buffer Pointer to the destination data buffer to write to, located in EEPROM memory space.
+ * \param[in] Length Number of bytes to send via the currently selected endpoint.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
+ * transaction should be updated, \c NULL if the entire stream should be read at once.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Read_EStream_LE(void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** EEPROM buffer destination version of \ref Endpoint_Read_Stream_BE().
+ *
+ * \param[out] Buffer Pointer to the destination data buffer to write to, located in EEPROM memory space.
+ * \param[in] Length Number of bytes to send via the currently selected endpoint.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
+ * transaction should be updated, \c NULL if the entire stream should be read at once.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Read_EStream_BE(void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** EEPROM buffer source version of Endpoint_Write_Control_Stream_LE.
+ *
+ * \note This function automatically sends the last packet in the data stage of the transaction; when the
+ * function returns, the user is responsible for clearing the <b>status</b> stage of the transaction.
+ * Note that the status stage packet is sent or received in the opposite direction of the data flow.
+ * \n\n
+ *
+ * \note This routine should only be used on CONTROL type endpoints.
+ * \n\n
+ *
+ * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
+ * together; i.e. the entire stream data must be read or written at the one time.
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
+ *
+ * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_Control_EStream_LE(const void* const Buffer,
+ uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** EEPROM buffer source version of \ref Endpoint_Write_Control_Stream_BE().
+ *
+ * \note This function automatically sends the last packet in the data stage of the transaction; when the
+ * function returns, the user is responsible for clearing the <b>status</b> stage of the transaction.
+ * Note that the status stage packet is sent or received in the opposite direction of the data flow.
+ * \n\n
+ *
+ * \note This routine should only be used on CONTROL type endpoints.
+ * \n\n
+ *
+ * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
+ * together; i.e. the entire stream data must be read or written at the one time.
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
+ *
+ * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_Control_EStream_BE(const void* const Buffer,
+ uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** EEPROM buffer source version of \ref Endpoint_Read_Control_Stream_LE().
+ *
+ * \note This function automatically sends the last packet in the data stage of the transaction; when the
+ * function returns, the user is responsible for clearing the <b>status</b> stage of the transaction.
+ * Note that the status stage packet is sent or received in the opposite direction of the data flow.
+ * \n\n
+ *
+ * \note This routine should only be used on CONTROL type endpoints.
+ * \n\n
+ *
+ * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
+ * together; i.e. the entire stream data must be read or written at the one time.
+ *
+ * \param[out] Buffer Pointer to the destination data buffer to write to.
+ * \param[in] Length Number of bytes to send via the currently selected endpoint.
+ *
+ * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Read_Control_EStream_LE(void* const Buffer,
+ uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** EEPROM buffer source version of \ref Endpoint_Read_Control_Stream_BE().
+ *
+ * \note This function automatically sends the last packet in the data stage of the transaction; when the
+ * function returns, the user is responsible for clearing the <b>status</b> stage of the transaction.
+ * Note that the status stage packet is sent or received in the opposite direction of the data flow.
+ * \n\n
+ *
+ * \note This routine should only be used on CONTROL type endpoints.
+ * \n\n
+ *
+ * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
+ * together; i.e. the entire stream data must be read or written at the one time.
+ *
+ * \param[out] Buffer Pointer to the destination data buffer to write to.
+ * \param[in] Length Number of bytes to send via the currently selected endpoint.
+ *
+ * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Read_Control_EStream_BE(void* const Buffer,
+ uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+ //@}
+
+ /** \name Stream functions for PROGMEM source/destination data */
+ //@{
+
+ /** FLASH buffer source version of \ref Endpoint_Write_Stream_LE().
+ *
+ * \pre The FLASH data must be located in the first 64KB of FLASH for this function to work correctly.
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
+ * transaction should be updated, \c NULL if the entire stream should be written at once.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_PStream_LE(const void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** FLASH buffer source version of \ref Endpoint_Write_Stream_BE().
+ *
+ * \pre The FLASH data must be located in the first 64KB of FLASH for this function to work correctly.
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
+ * transaction should be updated, \c NULL if the entire stream should be written at once.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_PStream_BE(const void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** FLASH buffer source version of \ref Endpoint_Write_Control_Stream_LE().
+ *
+ * \pre The FLASH data must be located in the first 64KB of FLASH for this function to work correctly.
+ *
+ * \note This function automatically sends the last packet in the data stage of the transaction; when the
+ * function returns, the user is responsible for clearing the <b>status</b> stage of the transaction.
+ * Note that the status stage packet is sent or received in the opposite direction of the data flow.
+ * \n\n
+ *
+ * \note This routine should only be used on CONTROL type endpoints.
+ * \n\n
+ *
+ * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
+ * together; i.e. the entire stream data must be read or written at the one time.
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
+ *
+ * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_Control_PStream_LE(const void* const Buffer,
+ uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** FLASH buffer source version of \ref Endpoint_Write_Control_Stream_BE().
+ *
+ * \pre The FLASH data must be located in the first 64KB of FLASH for this function to work correctly.
+ *
+ * \note This function automatically sends the last packet in the data stage of the transaction; when the
+ * function returns, the user is responsible for clearing the <b>status</b> stage of the transaction.
+ * Note that the status stage packet is sent or received in the opposite direction of the data flow.
+ * \n\n
+ *
+ * \note This routine should only be used on CONTROL type endpoints.
+ * \n\n
+ *
+ * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
+ * together; i.e. the entire stream data must be read or written at the one time.
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
+ *
+ * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_Control_PStream_BE(const void* const Buffer,
+ uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+ //@}
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.c
new file mode 100644
index 000000000..f5d20341b
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.c
@@ -0,0 +1,201 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "../../../../Common/Common.h"
+#if (ARCH == ARCH_AVR8)
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../USBMode.h"
+
+#if defined(USB_CAN_BE_DEVICE)
+
+#include "../Endpoint.h"
+
+#if !defined(FIXED_CONTROL_ENDPOINT_SIZE)
+uint8_t USB_Device_ControlEndpointSize = ENDPOINT_CONTROLEP_DEFAULT_SIZE;
+#endif
+
+bool Endpoint_ConfigureEndpointTable(const USB_Endpoint_Table_t* const Table,
+ const uint8_t Entries)
+{
+ for (uint8_t i = 0; i < Entries; i++)
+ {
+ if (!(Table[i].Address))
+ continue;
+
+ if (!(Endpoint_ConfigureEndpoint(Table[i].Address, Table[i].Type, Table[i].Size, Table[i].Banks)))
+ return false;
+ }
+
+ return true;
+}
+
+bool Endpoint_ConfigureEndpoint_Prv(const uint8_t Number,
+ const uint8_t UECFG0XData,
+ const uint8_t UECFG1XData)
+{
+#if defined(CONTROL_ONLY_DEVICE) || defined(ORDERED_EP_CONFIG)
+ Endpoint_SelectEndpoint(Number);
+ Endpoint_EnableEndpoint();
+
+ UECFG1X = 0;
+ UECFG0X = UECFG0XData;
+ UECFG1X = UECFG1XData;
+
+ return Endpoint_IsConfigured();
+#else
+ for (uint8_t EPNum = Number; EPNum < ENDPOINT_TOTAL_ENDPOINTS; EPNum++)
+ {
+ uint8_t UECFG0XTemp;
+ uint8_t UECFG1XTemp;
+ uint8_t UEIENXTemp;
+
+ Endpoint_SelectEndpoint(EPNum);
+
+ if (EPNum == Number)
+ {
+ UECFG0XTemp = UECFG0XData;
+ UECFG1XTemp = UECFG1XData;
+ UEIENXTemp = 0;
+ }
+ else
+ {
+ UECFG0XTemp = UECFG0X;
+ UECFG1XTemp = UECFG1X;
+ UEIENXTemp = UEIENX;
+ }
+
+ if (!(UECFG1XTemp & (1 << ALLOC)))
+ continue;
+
+ Endpoint_DisableEndpoint();
+ UECFG1X &= ~(1 << ALLOC);
+
+ Endpoint_EnableEndpoint();
+ UECFG0X = UECFG0XTemp;
+ UECFG1X = UECFG1XTemp;
+ UEIENX = UEIENXTemp;
+
+ if (!(Endpoint_IsConfigured()))
+ return false;
+ }
+
+ Endpoint_SelectEndpoint(Number);
+ return true;
+#endif
+}
+
+void Endpoint_ClearEndpoints(void)
+{
+ UEINT = 0;
+
+ for (uint8_t EPNum = 0; EPNum < ENDPOINT_TOTAL_ENDPOINTS; EPNum++)
+ {
+ Endpoint_SelectEndpoint(EPNum);
+ UEIENX = 0;
+ UEINTX = 0;
+ UECFG1X = 0;
+ Endpoint_DisableEndpoint();
+ }
+}
+
+void Endpoint_ClearStatusStage(void)
+{
+ if (USB_ControlRequest.bmRequestType & REQDIR_DEVICETOHOST)
+ {
+ while (!(Endpoint_IsOUTReceived()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+
+ Endpoint_ClearOUT();
+ }
+ else
+ {
+ while (!(Endpoint_IsINReady()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+
+ Endpoint_ClearIN();
+ }
+}
+
+#if !defined(CONTROL_ONLY_DEVICE)
+uint8_t Endpoint_WaitUntilReady(void)
+{
+ #if (USB_STREAM_TIMEOUT_MS < 0xFF)
+ uint8_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
+ #else
+ uint16_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
+ #endif
+
+ uint16_t PreviousFrameNumber = USB_Device_GetFrameNumber();
+
+ for (;;)
+ {
+ if (Endpoint_GetEndpointDirection() == ENDPOINT_DIR_IN)
+ {
+ if (Endpoint_IsINReady())
+ return ENDPOINT_READYWAIT_NoError;
+ }
+ else
+ {
+ if (Endpoint_IsOUTReceived())
+ return ENDPOINT_READYWAIT_NoError;
+ }
+
+ uint8_t USB_DeviceState_LCL = USB_DeviceState;
+
+ if (USB_DeviceState_LCL == DEVICE_STATE_Unattached)
+ return ENDPOINT_READYWAIT_DeviceDisconnected;
+ else if (USB_DeviceState_LCL == DEVICE_STATE_Suspended)
+ return ENDPOINT_READYWAIT_BusSuspended;
+ else if (Endpoint_IsStalled())
+ return ENDPOINT_READYWAIT_EndpointStalled;
+
+ uint16_t CurrentFrameNumber = USB_Device_GetFrameNumber();
+
+ if (CurrentFrameNumber != PreviousFrameNumber)
+ {
+ PreviousFrameNumber = CurrentFrameNumber;
+
+ if (!(TimeoutMSRem--))
+ return ENDPOINT_READYWAIT_Timeout;
+ }
+ }
+}
+#endif
+
+#endif
+
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.h
new file mode 100644
index 000000000..1632d93cf
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.h
@@ -0,0 +1,819 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief USB Endpoint definitions for the AVR8 microcontrollers.
+ * \copydetails Group_EndpointManagement_AVR8
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_EndpointRW
+ * \defgroup Group_EndpointRW_AVR8 Endpoint Data Reading and Writing (AVR8)
+ * \brief Endpoint data read/write definitions for the Atmel AVR8 architecture.
+ *
+ * Functions, macros, variables, enums and types related to data reading and writing from and to endpoints.
+ */
+
+/** \ingroup Group_EndpointPrimitiveRW
+ * \defgroup Group_EndpointPrimitiveRW_AVR8 Read/Write of Primitive Data Types (AVR8)
+ * \brief Endpoint primitive read/write definitions for the Atmel AVR8 architecture.
+ *
+ * Functions, macros, variables, enums and types related to data reading and writing of primitive data types
+ * from and to endpoints.
+ */
+
+/** \ingroup Group_EndpointPacketManagement
+ * \defgroup Group_EndpointPacketManagement_AVR8 Endpoint Packet Management (AVR8)
+ * \brief Endpoint packet management definitions for the Atmel AVR8 architecture.
+ *
+ * Functions, macros, variables, enums and types related to packet management of endpoints.
+ */
+
+/** \ingroup Group_EndpointManagement
+ * \defgroup Group_EndpointManagement_AVR8 Endpoint Management (AVR8)
+ * \brief Endpoint management definitions for the Atmel AVR8 architecture.
+ *
+ * Functions, macros and enums related to endpoint management when in USB Device mode. This
+ * module contains the endpoint management macros, as well as endpoint interrupt and data
+ * send/receive functions for various data types.
+ *
+ * @{
+ */
+
+#ifndef __ENDPOINT_AVR8_H__
+#define __ENDPOINT_AVR8_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../USBTask.h"
+ #include "../USBInterrupt.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Inline Functions: */
+ static inline uint8_t Endpoint_BytesToEPSizeMask(const uint16_t Bytes) ATTR_WARN_UNUSED_RESULT ATTR_CONST
+ ATTR_ALWAYS_INLINE;
+ static inline uint8_t Endpoint_BytesToEPSizeMask(const uint16_t Bytes)
+ {
+ uint8_t MaskVal = 0;
+ uint16_t CheckBytes = 8;
+
+ while (CheckBytes < Bytes)
+ {
+ MaskVal++;
+ CheckBytes <<= 1;
+ }
+
+ return (MaskVal << EPSIZE0);
+ }
+
+ /* Function Prototypes: */
+ void Endpoint_ClearEndpoints(void);
+ bool Endpoint_ConfigureEndpoint_Prv(const uint8_t Number,
+ const uint8_t UECFG0XData,
+ const uint8_t UECFG1XData);
+
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ #if (!defined(FIXED_CONTROL_ENDPOINT_SIZE) || defined(__DOXYGEN__))
+ /** Default size of the default control endpoint's bank, until altered by the control endpoint bank size
+ * value in the device descriptor. Not available if the \c FIXED_CONTROL_ENDPOINT_SIZE token is defined.
+ */
+ #define ENDPOINT_CONTROLEP_DEFAULT_SIZE 8
+ #endif
+
+ #if !defined(CONTROL_ONLY_DEVICE) || defined(__DOXYGEN__)
+ #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) || defined(__DOXYGEN__)
+ /** Total number of endpoints (including the default control endpoint at address 0) which may
+ * be used in the device. Different USB AVR models support different amounts of endpoints,
+ * this value reflects the maximum number of endpoints for the currently selected AVR model.
+ */
+ #define ENDPOINT_TOTAL_ENDPOINTS 7
+ #else
+ #define ENDPOINT_TOTAL_ENDPOINTS 5
+ #endif
+ #else
+ #define ENDPOINT_TOTAL_ENDPOINTS 1
+ #endif
+
+ /* Enums: */
+ /** Enum for the possible error return codes of the \ref Endpoint_WaitUntilReady() function.
+ *
+ * \ingroup Group_EndpointRW_AVR8
+ */
+ enum Endpoint_WaitUntilReady_ErrorCodes_t
+ {
+ ENDPOINT_READYWAIT_NoError = 0, /**< Endpoint is ready for next packet, no error. */
+ ENDPOINT_READYWAIT_EndpointStalled = 1, /**< The endpoint was stalled during the stream
+ * transfer by the host or device.
+ */
+ ENDPOINT_READYWAIT_DeviceDisconnected = 2, /**< Device was disconnected from the host while
+ * waiting for the endpoint to become ready.
+ */
+ ENDPOINT_READYWAIT_BusSuspended = 3, /**< The USB bus has been suspended by the host and
+ * no USB endpoint traffic can occur until the bus
+ * has resumed.
+ */
+ ENDPOINT_READYWAIT_Timeout = 4, /**< The host failed to accept or send the next packet
+ * within the software timeout period set by the
+ * \ref USB_STREAM_TIMEOUT_MS macro.
+ */
+ };
+
+ /* Inline Functions: */
+ /** Configures the specified endpoint address with the given endpoint type, bank size and number of hardware
+ * banks. Once configured, the endpoint may be read from or written to, depending on its direction.
+ *
+ * \param[in] Address Endpoint address to configure.
+ *
+ * \param[in] Type Type of endpoint to configure, a \c EP_TYPE_* mask. Not all endpoint types
+ * are available on Low Speed USB devices - refer to the USB 2.0 specification.
+ *
+ * \param[in] Size Size of the endpoint's bank, where packets are stored before they are transmitted
+ * to the USB host, or after they have been received from the USB host (depending on
+ * the endpoint's data direction). The bank size must indicate the maximum packet size
+ * that the endpoint can handle.
+ *
+ * \param[in] Banks Number of banks to use for the endpoint being configured.
+ *
+ * \attention When the \c ORDERED_EP_CONFIG compile time option is used, Endpoints <b>must</b> be configured in
+ * ascending order, or bank corruption will occur.
+ *
+ * \note Different endpoints may have different maximum packet sizes based on the endpoint's index - please
+ * refer to the chosen microcontroller model's datasheet to determine the maximum bank size for each endpoint.
+ * \n\n
+ *
+ * \note The default control endpoint should not be manually configured by the user application, as
+ * it is automatically configured by the library internally.
+ * \n\n
+ *
+ * \note This routine will automatically select the specified endpoint upon success. Upon failure, the endpoint
+ * which failed to reconfigure correctly will be selected.
+ *
+ * \return Boolean \c true if the configuration succeeded, \c false otherwise.
+ */
+ static inline bool Endpoint_ConfigureEndpoint(const uint8_t Address,
+ const uint8_t Type,
+ const uint16_t Size,
+ const uint8_t Banks) ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_ConfigureEndpoint(const uint8_t Address,
+ const uint8_t Type,
+ const uint16_t Size,
+ const uint8_t Banks)
+ {
+ uint8_t Number = (Address & ENDPOINT_EPNUM_MASK);
+
+ if (Number >= ENDPOINT_TOTAL_ENDPOINTS)
+ return false;
+
+ return Endpoint_ConfigureEndpoint_Prv(Number,
+ ((Type << EPTYPE0) | ((Address & ENDPOINT_DIR_IN) ? (1 << EPDIR) : 0)),
+ ((1 << ALLOC) | ((Banks > 1) ? (1 << EPBK0) : 0) | Endpoint_BytesToEPSizeMask(Size)));
+ }
+
+ /** Indicates the number of bytes currently stored in the current endpoint's selected bank.
+ *
+ * \ingroup Group_EndpointRW_AVR8
+ *
+ * \return Total number of bytes in the currently selected Endpoint's FIFO buffer.
+ */
+ static inline uint16_t Endpoint_BytesInEndpoint(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint16_t Endpoint_BytesInEndpoint(void)
+ {
+ #if (defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR))
+ return UEBCX;
+ #elif defined(USB_SERIES_4_AVR)
+ return (((uint16_t)UEBCHX << 8) | UEBCLX);
+ #elif defined(USB_SERIES_2_AVR)
+ return UEBCLX;
+ #endif
+ }
+
+ /** Determines the currently selected endpoint's direction.
+ *
+ * \return The currently selected endpoint's direction, as a \c ENDPOINT_DIR_* mask.
+ */
+ static inline uint8_t Endpoint_GetEndpointDirection(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Endpoint_GetEndpointDirection(void)
+ {
+ return (UECFG0X & (1 << EPDIR)) ? ENDPOINT_DIR_IN : ENDPOINT_DIR_OUT;
+ }
+
+ /** Get the endpoint address of the currently selected endpoint. This is typically used to save
+ * the currently selected endpoint so that it can be restored after another endpoint has been
+ * manipulated.
+ *
+ * \return Index of the currently selected endpoint.
+ */
+ static inline uint8_t Endpoint_GetCurrentEndpoint(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Endpoint_GetCurrentEndpoint(void)
+ {
+ #if !defined(CONTROL_ONLY_DEVICE)
+ return ((UENUM & ENDPOINT_EPNUM_MASK) | Endpoint_GetEndpointDirection());
+ #else
+ return ENDPOINT_CONTROLEP;
+ #endif
+ }
+
+ /** Selects the given endpoint address.
+ *
+ * Any endpoint operations which do not require the endpoint address to be indicated will operate on
+ * the currently selected endpoint.
+ *
+ * \param[in] Address Endpoint address to select.
+ */
+ static inline void Endpoint_SelectEndpoint(const uint8_t Address) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_SelectEndpoint(const uint8_t Address)
+ {
+ #if !defined(CONTROL_ONLY_DEVICE)
+ UENUM = (Address & ENDPOINT_EPNUM_MASK);
+ #endif
+ }
+
+ /** Resets the endpoint bank FIFO. This clears all the endpoint banks and resets the USB controller's
+ * data In and Out pointers to the bank's contents.
+ *
+ * \param[in] Address Endpoint address whose FIFO buffers are to be reset.
+ */
+ static inline void Endpoint_ResetEndpoint(const uint8_t Address) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_ResetEndpoint(const uint8_t Address)
+ {
+ UERST = (1 << (Address & ENDPOINT_EPNUM_MASK));
+ UERST = 0;
+ }
+
+ /** Enables the currently selected endpoint so that data can be sent and received through it to
+ * and from a host.
+ *
+ * \note Endpoints must first be configured properly via \ref Endpoint_ConfigureEndpoint().
+ */
+ static inline void Endpoint_EnableEndpoint(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_EnableEndpoint(void)
+ {
+ UECONX |= (1 << EPEN);
+ }
+
+ /** Disables the currently selected endpoint so that data cannot be sent and received through it
+ * to and from a host.
+ */
+ static inline void Endpoint_DisableEndpoint(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_DisableEndpoint(void)
+ {
+ UECONX &= ~(1 << EPEN);
+ }
+
+ /** Determines if the currently selected endpoint is enabled, but not necessarily configured.
+ *
+ * \return Boolean \c true if the currently selected endpoint is enabled, \c false otherwise.
+ */
+ static inline bool Endpoint_IsEnabled(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_IsEnabled(void)
+ {
+ return ((UECONX & (1 << EPEN)) ? true : false);
+ }
+
+ /** Retrieves the number of busy banks in the currently selected endpoint, which have been queued for
+ * transmission via the \ref Endpoint_ClearIN() command, or are awaiting acknowledgment via the
+ * \ref Endpoint_ClearOUT() command.
+ *
+ * \ingroup Group_EndpointPacketManagement_AVR8
+ *
+ * \return Total number of busy banks in the selected endpoint.
+ */
+ static inline uint8_t Endpoint_GetBusyBanks(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Endpoint_GetBusyBanks(void)
+ {
+ return (UESTA0X & (0x03 << NBUSYBK0));
+ }
+
+ /** Aborts all pending IN transactions on the currently selected endpoint, once the bank
+ * has been queued for transmission to the host via \ref Endpoint_ClearIN(). This function
+ * will terminate all queued transactions, resetting the endpoint banks ready for a new
+ * packet.
+ *
+ * \ingroup Group_EndpointPacketManagement_AVR8
+ */
+ static inline void Endpoint_AbortPendingIN(void)
+ {
+ while (Endpoint_GetBusyBanks() != 0)
+ {
+ UEINTX |= (1 << RXOUTI);
+ while (UEINTX & (1 << RXOUTI));
+ }
+ }
+
+ /** Determines if the currently selected endpoint may be read from (if data is waiting in the endpoint
+ * bank and the endpoint is an OUT direction, or if the bank is not yet full if the endpoint is an IN
+ * direction). This function will return false if an error has occurred in the endpoint, if the endpoint
+ * is an OUT direction and no packet (or an empty packet) has been received, or if the endpoint is an IN
+ * direction and the endpoint bank is full.
+ *
+ * \ingroup Group_EndpointPacketManagement_AVR8
+ *
+ * \return Boolean \c true if the currently selected endpoint may be read from or written to, depending
+ * on its direction.
+ */
+ static inline bool Endpoint_IsReadWriteAllowed(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_IsReadWriteAllowed(void)
+ {
+ return ((UEINTX & (1 << RWAL)) ? true : false);
+ }
+
+ /** Determines if the currently selected endpoint is configured.
+ *
+ * \return Boolean \c true if the currently selected endpoint has been configured, \c false otherwise.
+ */
+ static inline bool Endpoint_IsConfigured(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_IsConfigured(void)
+ {
+ return ((UESTA0X & (1 << CFGOK)) ? true : false);
+ }
+
+ /** Returns a mask indicating which INTERRUPT type endpoints have interrupted - i.e. their
+ * interrupt duration has elapsed. Which endpoints have interrupted can be determined by
+ * masking the return value against <tt>(1 << <i>{Endpoint Number}</i>)</tt>.
+ *
+ * \return Mask whose bits indicate which endpoints have interrupted.
+ */
+ static inline uint8_t Endpoint_GetEndpointInterrupts(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Endpoint_GetEndpointInterrupts(void)
+ {
+ return UEINT;
+ }
+
+ /** Determines if the specified endpoint number has interrupted (valid only for INTERRUPT type
+ * endpoints).
+ *
+ * \param[in] Address Address of the endpoint whose interrupt flag should be tested.
+ *
+ * \return Boolean \c true if the specified endpoint has interrupted, \c false otherwise.
+ */
+ static inline bool Endpoint_HasEndpointInterrupted(const uint8_t Address) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_HasEndpointInterrupted(const uint8_t Address)
+ {
+ return ((Endpoint_GetEndpointInterrupts() & (1 << (Address & ENDPOINT_EPNUM_MASK))) ? true : false);
+ }
+
+ /** Determines if the selected IN endpoint is ready for a new packet to be sent to the host.
+ *
+ * \ingroup Group_EndpointPacketManagement_AVR8
+ *
+ * \return Boolean \c true if the current endpoint is ready for an IN packet, \c false otherwise.
+ */
+ static inline bool Endpoint_IsINReady(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_IsINReady(void)
+ {
+ return ((UEINTX & (1 << TXINI)) ? true : false);
+ }
+
+ /** Determines if the selected OUT endpoint has received new packet from the host.
+ *
+ * \ingroup Group_EndpointPacketManagement_AVR8
+ *
+ * \return Boolean \c true if current endpoint is has received an OUT packet, \c false otherwise.
+ */
+ static inline bool Endpoint_IsOUTReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_IsOUTReceived(void)
+ {
+ return ((UEINTX & (1 << RXOUTI)) ? true : false);
+ }
+
+ /** Determines if the current CONTROL type endpoint has received a SETUP packet.
+ *
+ * \ingroup Group_EndpointPacketManagement_AVR8
+ *
+ * \return Boolean \c true if the selected endpoint has received a SETUP packet, \c false otherwise.
+ */
+ static inline bool Endpoint_IsSETUPReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_IsSETUPReceived(void)
+ {
+ return ((UEINTX & (1 << RXSTPI)) ? true : false);
+ }
+
+ /** Clears a received SETUP packet on the currently selected CONTROL type endpoint, freeing up the
+ * endpoint for the next packet.
+ *
+ * \ingroup Group_EndpointPacketManagement_AVR8
+ *
+ * \note This is not applicable for non CONTROL type endpoints.
+ */
+ static inline void Endpoint_ClearSETUP(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_ClearSETUP(void)
+ {
+ UEINTX &= ~(1 << RXSTPI);
+ }
+
+ /** Sends an IN packet to the host on the currently selected endpoint, freeing up the endpoint for the
+ * next packet and switching to the alternative endpoint bank if double banked.
+ *
+ * \ingroup Group_EndpointPacketManagement_AVR8
+ */
+ static inline void Endpoint_ClearIN(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_ClearIN(void)
+ {
+ #if !defined(CONTROL_ONLY_DEVICE)
+ UEINTX &= ~((1 << TXINI) | (1 << FIFOCON));
+ #else
+ UEINTX &= ~(1 << TXINI);
+ #endif
+ }
+
+ /** Acknowledges an OUT packet to the host on the currently selected endpoint, freeing up the endpoint
+ * for the next packet and switching to the alternative endpoint bank if double banked.
+ *
+ * \ingroup Group_EndpointPacketManagement_AVR8
+ */
+ static inline void Endpoint_ClearOUT(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_ClearOUT(void)
+ {
+ #if !defined(CONTROL_ONLY_DEVICE)
+ UEINTX &= ~((1 << RXOUTI) | (1 << FIFOCON));
+ #else
+ UEINTX &= ~(1 << RXOUTI);
+ #endif
+ }
+
+ /** Stalls the current endpoint, indicating to the host that a logical problem occurred with the
+ * indicated endpoint and that the current transfer sequence should be aborted. This provides a
+ * way for devices to indicate invalid commands to the host so that the current transfer can be
+ * aborted and the host can begin its own recovery sequence.
+ *
+ * The currently selected endpoint remains stalled until either the \ref Endpoint_ClearStall() macro
+ * is called, or the host issues a CLEAR FEATURE request to the device for the currently selected
+ * endpoint.
+ *
+ * \ingroup Group_EndpointPacketManagement_AVR8
+ */
+ static inline void Endpoint_StallTransaction(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_StallTransaction(void)
+ {
+ UECONX |= (1 << STALLRQ);
+ }
+
+ /** Clears the STALL condition on the currently selected endpoint.
+ *
+ * \ingroup Group_EndpointPacketManagement_AVR8
+ */
+ static inline void Endpoint_ClearStall(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_ClearStall(void)
+ {
+ UECONX |= (1 << STALLRQC);
+ }
+
+ /** Determines if the currently selected endpoint is stalled, \c false otherwise.
+ *
+ * \ingroup Group_EndpointPacketManagement_AVR8
+ *
+ * \return Boolean \c true if the currently selected endpoint is stalled, \c false otherwise.
+ */
+ static inline bool Endpoint_IsStalled(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_IsStalled(void)
+ {
+ return ((UECONX & (1 << STALLRQ)) ? true : false);
+ }
+
+ /** Resets the data toggle of the currently selected endpoint. */
+ static inline void Endpoint_ResetDataToggle(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_ResetDataToggle(void)
+ {
+ UECONX |= (1 << RSTDT);
+ }
+
+ /** Sets the direction of the currently selected endpoint.
+ *
+ * \param[in] DirectionMask New endpoint direction, as a \c ENDPOINT_DIR_* mask.
+ */
+ static inline void Endpoint_SetEndpointDirection(const uint8_t DirectionMask) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_SetEndpointDirection(const uint8_t DirectionMask)
+ {
+ UECFG0X = ((UECFG0X & ~(1 << EPDIR)) | (DirectionMask ? (1 << EPDIR) : 0));
+ }
+
+ /** Reads one byte from the currently selected endpoint's bank, for OUT direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_AVR8
+ *
+ * \return Next byte in the currently selected endpoint's FIFO buffer.
+ */
+ static inline uint8_t Endpoint_Read_8(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Endpoint_Read_8(void)
+ {
+ return UEDATX;
+ }
+
+ /** Writes one byte to the currently selected endpoint's bank, for IN direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_AVR8
+ *
+ * \param[in] Data Data to write into the the currently selected endpoint's FIFO buffer.
+ */
+ static inline void Endpoint_Write_8(const uint8_t Data) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_Write_8(const uint8_t Data)
+ {
+ UEDATX = Data;
+ }
+
+ /** Discards one byte from the currently selected endpoint's bank, for OUT direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_AVR8
+ */
+ static inline void Endpoint_Discard_8(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_Discard_8(void)
+ {
+ uint8_t Dummy;
+
+ Dummy = UEDATX;
+
+ (void)Dummy;
+ }
+
+ /** Reads two bytes from the currently selected endpoint's bank in little endian format, for OUT
+ * direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_AVR8
+ *
+ * \return Next two bytes in the currently selected endpoint's FIFO buffer.
+ */
+ static inline uint16_t Endpoint_Read_16_LE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint16_t Endpoint_Read_16_LE(void)
+ {
+ union
+ {
+ uint16_t Value;
+ uint8_t Bytes[2];
+ } Data;
+
+ Data.Bytes[0] = UEDATX;
+ Data.Bytes[1] = UEDATX;
+
+ return Data.Value;
+ }
+
+ /** Reads two bytes from the currently selected endpoint's bank in big endian format, for OUT
+ * direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_AVR8
+ *
+ * \return Next two bytes in the currently selected endpoint's FIFO buffer.
+ */
+ static inline uint16_t Endpoint_Read_16_BE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint16_t Endpoint_Read_16_BE(void)
+ {
+ union
+ {
+ uint16_t Value;
+ uint8_t Bytes[2];
+ } Data;
+
+ Data.Bytes[1] = UEDATX;
+ Data.Bytes[0] = UEDATX;
+
+ return Data.Value;
+ }
+
+ /** Writes two bytes to the currently selected endpoint's bank in little endian format, for IN
+ * direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_AVR8
+ *
+ * \param[in] Data Data to write to the currently selected endpoint's FIFO buffer.
+ */
+ static inline void Endpoint_Write_16_LE(const uint16_t Data) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_Write_16_LE(const uint16_t Data)
+ {
+ UEDATX = (Data & 0xFF);
+ UEDATX = (Data >> 8);
+ }
+
+ /** Writes two bytes to the currently selected endpoint's bank in big endian format, for IN
+ * direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_AVR8
+ *
+ * \param[in] Data Data to write to the currently selected endpoint's FIFO buffer.
+ */
+ static inline void Endpoint_Write_16_BE(const uint16_t Data) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_Write_16_BE(const uint16_t Data)
+ {
+ UEDATX = (Data >> 8);
+ UEDATX = (Data & 0xFF);
+ }
+
+ /** Discards two bytes from the currently selected endpoint's bank, for OUT direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_AVR8
+ */
+ static inline void Endpoint_Discard_16(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_Discard_16(void)
+ {
+ uint8_t Dummy;
+
+ Dummy = UEDATX;
+ Dummy = UEDATX;
+
+ (void)Dummy;
+ }
+
+ /** Reads four bytes from the currently selected endpoint's bank in little endian format, for OUT
+ * direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_AVR8
+ *
+ * \return Next four bytes in the currently selected endpoint's FIFO buffer.
+ */
+ static inline uint32_t Endpoint_Read_32_LE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint32_t Endpoint_Read_32_LE(void)
+ {
+ union
+ {
+ uint32_t Value;
+ uint8_t Bytes[4];
+ } Data;
+
+ Data.Bytes[0] = UEDATX;
+ Data.Bytes[1] = UEDATX;
+ Data.Bytes[2] = UEDATX;
+ Data.Bytes[3] = UEDATX;
+
+ return Data.Value;
+ }
+
+ /** Reads four bytes from the currently selected endpoint's bank in big endian format, for OUT
+ * direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_AVR8
+ *
+ * \return Next four bytes in the currently selected endpoint's FIFO buffer.
+ */
+ static inline uint32_t Endpoint_Read_32_BE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint32_t Endpoint_Read_32_BE(void)
+ {
+ union
+ {
+ uint32_t Value;
+ uint8_t Bytes[4];
+ } Data;
+
+ Data.Bytes[3] = UEDATX;
+ Data.Bytes[2] = UEDATX;
+ Data.Bytes[1] = UEDATX;
+ Data.Bytes[0] = UEDATX;
+
+ return Data.Value;
+ }
+
+ /** Writes four bytes to the currently selected endpoint's bank in little endian format, for IN
+ * direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_AVR8
+ *
+ * \param[in] Data Data to write to the currently selected endpoint's FIFO buffer.
+ */
+ static inline void Endpoint_Write_32_LE(const uint32_t Data) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_Write_32_LE(const uint32_t Data)
+ {
+ UEDATX = (Data & 0xFF);
+ UEDATX = (Data >> 8);
+ UEDATX = (Data >> 16);
+ UEDATX = (Data >> 24);
+ }
+
+ /** Writes four bytes to the currently selected endpoint's bank in big endian format, for IN
+ * direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_AVR8
+ *
+ * \param[in] Data Data to write to the currently selected endpoint's FIFO buffer.
+ */
+ static inline void Endpoint_Write_32_BE(const uint32_t Data) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_Write_32_BE(const uint32_t Data)
+ {
+ UEDATX = (Data >> 24);
+ UEDATX = (Data >> 16);
+ UEDATX = (Data >> 8);
+ UEDATX = (Data & 0xFF);
+ }
+
+ /** Discards four bytes from the currently selected endpoint's bank, for OUT direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_AVR8
+ */
+ static inline void Endpoint_Discard_32(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_Discard_32(void)
+ {
+ uint8_t Dummy;
+
+ Dummy = UEDATX;
+ Dummy = UEDATX;
+ Dummy = UEDATX;
+ Dummy = UEDATX;
+
+ (void)Dummy;
+ }
+
+ /* External Variables: */
+ /** Global indicating the maximum packet size of the default control endpoint located at address
+ * 0 in the device. This value is set to the value indicated in the device descriptor in the user
+ * project once the USB interface is initialized into device mode.
+ *
+ * If space is an issue, it is possible to fix this to a static value by defining the control
+ * endpoint size in the \c FIXED_CONTROL_ENDPOINT_SIZE token passed to the compiler in the makefile
+ * via the -D switch. When a fixed control endpoint size is used, the size is no longer dynamically
+ * read from the descriptors at runtime and instead fixed to the given value. When used, it is
+ * important that the descriptor control endpoint size value matches the size given as the
+ * \c FIXED_CONTROL_ENDPOINT_SIZE token - it is recommended that the \c FIXED_CONTROL_ENDPOINT_SIZE token
+ * be used in the device descriptors to ensure this.
+ *
+ * \attention This variable should be treated as read-only in the user application, and never manually
+ * changed in value.
+ */
+ #if (!defined(FIXED_CONTROL_ENDPOINT_SIZE) || defined(__DOXYGEN__))
+ extern uint8_t USB_Device_ControlEndpointSize;
+ #else
+ #define USB_Device_ControlEndpointSize FIXED_CONTROL_ENDPOINT_SIZE
+ #endif
+
+ /* Function Prototypes: */
+ /** Configures a table of endpoint descriptions, in sequence. This function can be used to configure multiple
+ * endpoints at the same time.
+ *
+ * \note Endpoints with a zero address will be ignored, thus this function cannot be used to configure the
+ * control endpoint.
+ *
+ * \param[in] Table Pointer to a table of endpoint descriptions.
+ * \param[in] Entries Number of entries in the endpoint table to configure.
+ *
+ * \return Boolean \c true if all endpoints configured successfully, \c false otherwise.
+ */
+ bool Endpoint_ConfigureEndpointTable(const USB_Endpoint_Table_t* const Table,
+ const uint8_t Entries);
+
+ /** Completes the status stage of a control transfer on a CONTROL type endpoint automatically,
+ * with respect to the data direction. This is a convenience function which can be used to
+ * simplify user control request handling.
+ *
+ * \note This routine should not be called on non CONTROL type endpoints.
+ */
+ void Endpoint_ClearStatusStage(void);
+
+ /** Spin-loops until the currently selected non-control endpoint is ready for the next packet of data
+ * to be read or written to it.
+ *
+ * \note This routine should not be called on CONTROL type endpoints.
+ *
+ * \ingroup Group_EndpointRW_AVR8
+ *
+ * \return A value from the \ref Endpoint_WaitUntilReady_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_WaitUntilReady(void);
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Host_AVR8.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Host_AVR8.c
new file mode 100644
index 000000000..4e38c75a6
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Host_AVR8.c
@@ -0,0 +1,297 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "../../../../Common/Common.h"
+#if (ARCH == ARCH_AVR8)
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../USBMode.h"
+
+#if defined(USB_CAN_BE_HOST)
+
+#define __INCLUDE_FROM_HOST_C
+#include "../Host.h"
+
+void USB_Host_ProcessNextHostState(void)
+{
+ uint8_t ErrorCode = HOST_ENUMERROR_NoError;
+ uint8_t SubErrorCode = HOST_ENUMERROR_NoError;
+
+ static uint16_t WaitMSRemaining;
+ static uint8_t PostWaitState;
+
+ switch (USB_HostState)
+ {
+ case HOST_STATE_WaitForDevice:
+ if (WaitMSRemaining)
+ {
+ if ((SubErrorCode = USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful)
+ {
+ USB_HostState = PostWaitState;
+ ErrorCode = HOST_ENUMERROR_WaitStage;
+ break;
+ }
+
+ if (!(--WaitMSRemaining))
+ USB_HostState = PostWaitState;
+ }
+
+ break;
+ case HOST_STATE_Powered:
+ WaitMSRemaining = HOST_DEVICE_SETTLE_DELAY_MS;
+
+ USB_HostState = HOST_STATE_Powered_WaitForDeviceSettle;
+ break;
+ case HOST_STATE_Powered_WaitForDeviceSettle:
+ if (WaitMSRemaining--)
+ {
+ Delay_MS(1);
+ break;
+ }
+ else
+ {
+ USB_Host_VBUS_Manual_Off();
+
+ USB_OTGPAD_On();
+ USB_Host_VBUS_Auto_Enable();
+ USB_Host_VBUS_Auto_On();
+
+ #if defined(NO_AUTO_VBUS_MANAGEMENT)
+ USB_Host_VBUS_Manual_Enable();
+ USB_Host_VBUS_Manual_On();
+ #endif
+
+ USB_HostState = HOST_STATE_Powered_WaitForConnect;
+ }
+
+ break;
+ case HOST_STATE_Powered_WaitForConnect:
+ if (USB_INT_HasOccurred(USB_INT_DCONNI))
+ {
+ USB_INT_Clear(USB_INT_DCONNI);
+ USB_INT_Clear(USB_INT_DDISCI);
+
+ USB_INT_Clear(USB_INT_VBERRI);
+ USB_INT_Enable(USB_INT_VBERRI);
+
+ USB_Host_ResumeBus();
+ Pipe_ClearPipes();
+
+ HOST_TASK_NONBLOCK_WAIT(100, HOST_STATE_Powered_DoReset);
+ }
+
+ break;
+ case HOST_STATE_Powered_DoReset:
+ USB_Host_ResetDevice();
+
+ HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Powered_ConfigPipe);
+ break;
+ case HOST_STATE_Powered_ConfigPipe:
+ if (!(Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL, ENDPOINT_CONTROLEP, PIPE_CONTROLPIPE_DEFAULT_SIZE, 1)))
+ {
+ ErrorCode = HOST_ENUMERROR_PipeConfigError;
+ SubErrorCode = 0;
+ break;
+ }
+
+ USB_HostState = HOST_STATE_Default;
+ break;
+ case HOST_STATE_Default:
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE),
+ .bRequest = REQ_GetDescriptor,
+ .wValue = (DTYPE_Device << 8),
+ .wIndex = 0,
+ .wLength = 8,
+ };
+
+ uint8_t DataBuffer[8];
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+ if ((SubErrorCode = USB_Host_SendControlRequest(DataBuffer)) != HOST_SENDCONTROL_Successful)
+ {
+ ErrorCode = HOST_ENUMERROR_ControlError;
+ break;
+ }
+
+ USB_Host_ControlPipeSize = DataBuffer[offsetof(USB_Descriptor_Device_t, Endpoint0Size)];
+
+ USB_Host_ResetDevice();
+
+ HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Default_PostReset);
+ break;
+ case HOST_STATE_Default_PostReset:
+ if (!(Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL, ENDPOINT_CONTROLEP, USB_Host_ControlPipeSize, 1)))
+ {
+ ErrorCode = HOST_ENUMERROR_PipeConfigError;
+ SubErrorCode = 0;
+ break;
+ }
+
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE),
+ .bRequest = REQ_SetAddress,
+ .wValue = USB_HOST_DEVICEADDRESS,
+ .wIndex = 0,
+ .wLength = 0,
+ };
+
+ if ((SubErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
+ {
+ ErrorCode = HOST_ENUMERROR_ControlError;
+ break;
+ }
+
+ HOST_TASK_NONBLOCK_WAIT(100, HOST_STATE_Default_PostAddressSet);
+ break;
+ case HOST_STATE_Default_PostAddressSet:
+ USB_Host_SetDeviceAddress(USB_HOST_DEVICEADDRESS);
+
+ USB_HostState = HOST_STATE_Addressed;
+
+ EVENT_USB_Host_DeviceEnumerationComplete();
+ break;
+
+ default:
+ break;
+ }
+
+ if ((ErrorCode != HOST_ENUMERROR_NoError) && (USB_HostState != HOST_STATE_Unattached))
+ {
+ EVENT_USB_Host_DeviceEnumerationFailed(ErrorCode, SubErrorCode);
+
+ USB_Host_VBUS_Auto_Off();
+
+ EVENT_USB_Host_DeviceUnattached();
+
+ USB_ResetInterface();
+ }
+}
+
+uint8_t USB_Host_WaitMS(uint8_t MS)
+{
+ bool BusSuspended = USB_Host_IsBusSuspended();
+ uint8_t ErrorCode = HOST_WAITERROR_Successful;
+ bool HSOFIEnabled = USB_INT_IsEnabled(USB_INT_HSOFI);
+
+ USB_INT_Disable(USB_INT_HSOFI);
+ USB_INT_Clear(USB_INT_HSOFI);
+
+ USB_Host_ResumeBus();
+
+ while (MS)
+ {
+ if (USB_INT_HasOccurred(USB_INT_HSOFI))
+ {
+ USB_INT_Clear(USB_INT_HSOFI);
+ MS--;
+ }
+
+ if ((USB_HostState == HOST_STATE_Unattached) || (USB_CurrentMode != USB_MODE_Host))
+ {
+ ErrorCode = HOST_WAITERROR_DeviceDisconnect;
+
+ break;
+ }
+
+ if (Pipe_IsError())
+ {
+ Pipe_ClearError();
+ ErrorCode = HOST_WAITERROR_PipeError;
+
+ break;
+ }
+
+ if (Pipe_IsStalled())
+ {
+ Pipe_ClearStall();
+ ErrorCode = HOST_WAITERROR_SetupStalled;
+
+ break;
+ }
+ }
+
+ if (BusSuspended)
+ USB_Host_SuspendBus();
+
+ if (HSOFIEnabled)
+ USB_INT_Enable(USB_INT_HSOFI);
+
+ return ErrorCode;
+}
+
+static void USB_Host_ResetDevice(void)
+{
+ bool BusSuspended = USB_Host_IsBusSuspended();
+
+ USB_INT_Disable(USB_INT_DDISCI);
+
+ USB_Host_ResetBus();
+ while (!(USB_Host_IsBusResetComplete()));
+ USB_Host_ResumeBus();
+
+ USB_Host_ConfigurationNumber = 0;
+
+ bool HSOFIEnabled = USB_INT_IsEnabled(USB_INT_HSOFI);
+
+ USB_INT_Disable(USB_INT_HSOFI);
+ USB_INT_Clear(USB_INT_HSOFI);
+
+ for (uint8_t MSRem = 10; MSRem != 0; MSRem--)
+ {
+ /* Workaround for powerless-pull-up devices. After a USB bus reset,
+ all disconnection interrupts are suppressed while a USB frame is
+ looked for - if it is found within 10ms, the device is still
+ present. */
+
+ if (USB_INT_HasOccurred(USB_INT_HSOFI))
+ {
+ USB_INT_Clear(USB_INT_HSOFI);
+ USB_INT_Clear(USB_INT_DDISCI);
+ break;
+ }
+
+ Delay_MS(1);
+ }
+
+ if (HSOFIEnabled)
+ USB_INT_Enable(USB_INT_HSOFI);
+
+ if (BusSuspended)
+ USB_Host_SuspendBus();
+
+ USB_INT_Enable(USB_INT_DDISCI);
+}
+
+#endif
+
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Host_AVR8.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Host_AVR8.h
new file mode 100644
index 000000000..f0ffa5a54
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Host_AVR8.h
@@ -0,0 +1,372 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief USB Host definitions for the AVR8 microcontrollers.
+ * \copydetails Group_Host_AVR8
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_Host
+ * \defgroup Group_Host_AVR8 Host Management (AVR8)
+ * \brief USB Host definitions for the AVR8 microcontrollers.
+ *
+ * Architecture specific USB Host definitions for the Atmel 8-bit AVR microcontrollers.
+ *
+ * @{
+ */
+
+#ifndef __USBHOST_AVR8_H__
+#define __USBHOST_AVR8_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../StdDescriptors.h"
+ #include "../Pipe.h"
+ #include "../USBInterrupt.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ #if defined(INVERTED_VBUS_ENABLE_LINE) && !defined(NO_AUTO_VBUS_MANAGEMENT)
+ #error The INVERTED_VBUS_ENABLE_LINE compile option requires NO_AUTO_VBUS_MANAGEMENT for the AVR8 architecture.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the fixed USB device address which any attached device is enumerated to when in
+ * host mode. As only one USB device may be attached to the AVR in host mode at any one time
+ * and that the address used is not important (other than the fact that it is non-zero), a
+ * fixed value is specified by the library.
+ */
+ #define USB_HOST_DEVICEADDRESS 1
+
+ #if !defined(HOST_DEVICE_SETTLE_DELAY_MS) || defined(__DOXYGEN__)
+ /** Constant for the delay in milliseconds after a device is connected before the library
+ * will start the enumeration process. Some devices require a delay of up to 5 seconds
+ * after connection before the enumeration process can start or incorrect operation will
+ * occur.
+ *
+ * The default delay value may be overridden in the user project makefile by defining the
+ * \c HOST_DEVICE_SETTLE_DELAY_MS token to the required delay in milliseconds, and passed to the
+ * compiler using the -D switch.
+ */
+ #define HOST_DEVICE_SETTLE_DELAY_MS 1000
+ #endif
+
+ /** Enum for the error codes for the \ref EVENT_USB_Host_HostError() event.
+ *
+ * \see \ref Group_Events for more information on this event.
+ */
+ enum USB_Host_ErrorCodes_t
+ {
+ HOST_ERROR_VBusVoltageDip = 0, /**< VBUS voltage dipped to an unacceptable level. This
+ * error may be the result of an attached device drawing
+ * too much current from the VBUS line, or due to the
+ * AVR's power source being unable to supply sufficient
+ * current.
+ */
+ };
+
+ /** Enum for the error codes for the \ref EVENT_USB_Host_DeviceEnumerationFailed() event.
+ *
+ * \see \ref Group_Events for more information on this event.
+ */
+ enum USB_Host_EnumerationErrorCodes_t
+ {
+ HOST_ENUMERROR_NoError = 0, /**< No error occurred. Used internally, this is not a valid
+ * ErrorCode parameter value for the \ref EVENT_USB_Host_DeviceEnumerationFailed()
+ * event.
+ */
+ HOST_ENUMERROR_WaitStage = 1, /**< One of the delays between enumeration steps failed
+ * to complete successfully, due to a timeout or other
+ * error.
+ */
+ HOST_ENUMERROR_NoDeviceDetected = 2, /**< No device was detected, despite the USB data lines
+ * indicating the attachment of a device.
+ */
+ HOST_ENUMERROR_ControlError = 3, /**< One of the enumeration control requests failed to
+ * complete successfully.
+ */
+ HOST_ENUMERROR_PipeConfigError = 4, /**< The default control pipe (address 0) failed to
+ * configure correctly.
+ */
+ };
+
+ /* Inline Functions: */
+ /** Returns the current USB frame number, when in host mode. Every millisecond the USB bus is active (i.e. not suspended)
+ * the frame number is incremented by one.
+ *
+ * \return Current USB frame number from the USB controller.
+ */
+ static inline uint16_t USB_Host_GetFrameNumber(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint16_t USB_Host_GetFrameNumber(void)
+ {
+ return UHFNUM;
+ }
+
+ #if !defined(NO_SOF_EVENTS)
+ /** Enables the host mode Start Of Frame events. When enabled, this causes the
+ * \ref EVENT_USB_Host_StartOfFrame() event to fire once per millisecond, synchronized to the USB bus,
+ * at the start of each USB frame when a device is enumerated while in host mode.
+ *
+ * \note This function is not available when the \c NO_SOF_EVENTS compile time token is defined.
+ */
+ static inline void USB_Host_EnableSOFEvents(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_EnableSOFEvents(void)
+ {
+ USB_INT_Enable(USB_INT_HSOFI);
+ }
+
+ /** Disables the host mode Start Of Frame events. When disabled, this stops the firing of the
+ * \ref EVENT_USB_Host_StartOfFrame() event when enumerated in host mode.
+ *
+ * \note This function is not available when the \c NO_SOF_EVENTS compile time token is defined.
+ */
+ static inline void USB_Host_DisableSOFEvents(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_DisableSOFEvents(void)
+ {
+ USB_INT_Disable(USB_INT_HSOFI);
+ }
+ #endif
+
+ /** Resets the USB bus, including the endpoints in any attached device and pipes on the AVR host.
+ * USB bus resets leave the default control pipe configured (if already configured).
+ *
+ * If the USB bus has been suspended prior to issuing a bus reset, the attached device will be
+ * woken up automatically and the bus resumed after the reset has been correctly issued.
+ */
+ static inline void USB_Host_ResetBus(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_ResetBus(void)
+ {
+ UHCON |= (1 << RESET);
+ }
+
+ /** Determines if a previously issued bus reset (via the \ref USB_Host_ResetBus() macro) has
+ * completed.
+ *
+ * \return Boolean \c true if no bus reset is currently being sent, \c false otherwise.
+ */
+ static inline bool USB_Host_IsBusResetComplete(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool USB_Host_IsBusResetComplete(void)
+ {
+ return ((UHCON & (1 << RESET)) ? false : true);
+ }
+
+ /** Resumes USB communications with an attached and enumerated device, by resuming the transmission
+ * of the 1MS Start Of Frame messages to the device. When resumed, USB communications between the
+ * host and attached device may occur.
+ */
+ static inline void USB_Host_ResumeBus(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_ResumeBus(void)
+ {
+ UHCON |= (1 << SOFEN);
+ }
+
+ /** Suspends the USB bus, preventing any communications from occurring between the host and attached
+ * device until the bus has been resumed. This stops the transmission of the 1MS Start Of Frame
+ * messages to the device.
+ *
+ * \attention While the USB bus is suspended, all USB interrupt sources are also disabled; this means that
+ * some events (such as device disconnections) will not fire until the bus is resumed.
+ */
+ static inline void USB_Host_SuspendBus(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_SuspendBus(void)
+ {
+ UHCON &= ~(1 << SOFEN);
+ }
+
+ /** Determines if the USB bus has been suspended via the use of the \ref USB_Host_SuspendBus() macro,
+ * false otherwise. While suspended, no USB communications can occur until the bus is resumed,
+ * except for the Remote Wakeup event from the device if supported.
+ *
+ * \return Boolean \c true if the bus is currently suspended, \c false otherwise.
+ */
+ static inline bool USB_Host_IsBusSuspended(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool USB_Host_IsBusSuspended(void)
+ {
+ return ((UHCON & (1 << SOFEN)) ? false : true);
+ }
+
+ /** Determines if the attached device is currently enumerated in Full Speed mode (12Mb/s), or
+ * false if the attached device is enumerated in Low Speed mode (1.5Mb/s).
+ *
+ * \return Boolean \c true if the attached device is enumerated in Full Speed mode, \c false otherwise.
+ */
+ static inline bool USB_Host_IsDeviceFullSpeed(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool USB_Host_IsDeviceFullSpeed(void)
+ {
+ return ((USBSTA & (1 << SPEED)) ? true : false);
+ }
+
+ /** Determines if the attached device is currently issuing a Remote Wakeup request, requesting
+ * that the host resume the USB bus and wake up the device, \c false otherwise.
+ *
+ * \return Boolean \c true if the attached device has sent a Remote Wakeup request, \c false otherwise.
+ */
+ static inline bool USB_Host_IsRemoteWakeupSent(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool USB_Host_IsRemoteWakeupSent(void)
+ {
+ return ((UHINT & (1 << RXRSMI)) ? true : false);
+ }
+
+ /** Clears the flag indicating that a Remote Wakeup request has been issued by an attached device. */
+ static inline void USB_Host_ClearRemoteWakeupSent(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_ClearRemoteWakeupSent(void)
+ {
+ UHINT &= ~(1 << RXRSMI);
+ }
+
+ /** Accepts a Remote Wakeup request from an attached device. This must be issued in response to
+ * a device's Remote Wakeup request within 2ms for the request to be accepted and the bus to
+ * be resumed.
+ */
+ static inline void USB_Host_ResumeFromWakeupRequest(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_ResumeFromWakeupRequest(void)
+ {
+ UHCON |= (1 << RESUME);
+ }
+
+ /** Determines if a resume from Remote Wakeup request is currently being sent to an attached
+ * device.
+ *
+ * \return Boolean \c true if no resume request is currently being sent, \c false otherwise.
+ */
+ static inline bool USB_Host_IsResumeFromWakeupRequestSent(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool USB_Host_IsResumeFromWakeupRequestSent(void)
+ {
+ return ((UHCON & (1 << RESUME)) ? false : true);
+ }
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ static inline void USB_Host_HostMode_On(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_HostMode_On(void)
+ {
+ USBCON |= (1 << HOST);
+ }
+
+ static inline void USB_Host_HostMode_Off(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_HostMode_Off(void)
+ {
+ USBCON &= ~(1 << HOST);
+ }
+
+ static inline void USB_Host_VBUS_Auto_Enable(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_VBUS_Auto_Enable(void)
+ {
+ OTGCON &= ~(1 << VBUSHWC);
+ UHWCON |= (1 << UVCONE);
+ }
+
+ static inline void USB_Host_VBUS_Manual_Enable(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_VBUS_Manual_Enable(void)
+ {
+ OTGCON |= (1 << VBUSHWC);
+ UHWCON &= ~(1 << UVCONE);
+
+ DDRE |= (1 << 7);
+ }
+
+ static inline void USB_Host_VBUS_Auto_On(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_VBUS_Auto_On(void)
+ {
+ OTGCON |= (1 << VBUSREQ);
+ }
+
+ static inline void USB_Host_VBUS_Manual_On(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_VBUS_Manual_On(void)
+ {
+ #if defined(INVERTED_VBUS_ENABLE_LINE)
+ PORTE &= ~(1 << 7);
+ #else
+ PORTE |= (1 << 7);
+ #endif
+ }
+
+ static inline void USB_Host_VBUS_Auto_Off(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_VBUS_Auto_Off(void)
+ {
+ OTGCON |= (1 << VBUSRQC);
+ }
+
+ static inline void USB_Host_VBUS_Manual_Off(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_VBUS_Manual_Off(void)
+ {
+ #if defined(INVERTED_VBUS_ENABLE_LINE)
+ PORTE |= (1 << 7);
+ #else
+ PORTE &= ~(1 << 7);
+ #endif
+ }
+
+ static inline void USB_Host_SetDeviceAddress(const uint8_t Address) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_SetDeviceAddress(const uint8_t Address)
+ {
+ UHADDR = (Address & 0x7F);
+ }
+
+ /* Enums: */
+ enum USB_Host_WaitMSErrorCodes_t
+ {
+ HOST_WAITERROR_Successful = 0,
+ HOST_WAITERROR_DeviceDisconnect = 1,
+ HOST_WAITERROR_PipeError = 2,
+ HOST_WAITERROR_SetupStalled = 3,
+ };
+
+ /* Function Prototypes: */
+ void USB_Host_ProcessNextHostState(void);
+ uint8_t USB_Host_WaitMS(uint8_t MS);
+
+ #if defined(__INCLUDE_FROM_HOST_C)
+ static void USB_Host_ResetDevice(void);
+ #endif
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/OTG_AVR8.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/OTG_AVR8.h
new file mode 100644
index 000000000..c2e849627
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/OTG_AVR8.h
@@ -0,0 +1,159 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief USB OTG definitions for the AVR8 microcontrollers.
+ * \copydetails Group_OTG_AVR8
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_OTG
+ * \defgroup Group_OTG_AVR8 USB On The Go (OTG) Management (AVR8)
+ * \brief USB OTG definitions for the AVR8 microcontrollers.
+ *
+ * Architecture specific USB OTG definitions for the Atmel 8-bit AVR microcontrollers.
+ *
+ * @{
+ */
+
+#ifndef __USBOTG_AVR8_H__
+#define __USBOTG_AVR8_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Mask for the VBUS pulsing method of SRP, supported by some OTG devices.
+ *
+ * \see \ref USB_OTG_Device_InitiateSRP().
+ */
+ #define USB_OTG_SRP_VBUS (1 << SRPSEL)
+
+ /** Mask for the Data + pulsing method of SRP, supported by some OTG devices.
+ *
+ * \see \ref USB_OTG_Device_InitiateSRP().
+ */
+ #define USB_OTG_STP_DATA 0
+
+ /* Inline Functions: */
+ /** Initiate a Host Negotiation Protocol request. This indicates to the other connected device
+ * that the device wishes to change device/host roles.
+ */
+ static inline void USB_OTG_Device_RequestHNP(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_OTG_Device_RequestHNP(void)
+ {
+ OTGCON |= (1 << HNPREQ);
+ }
+
+ /** Cancel a Host Negotiation Protocol request. This stops a pending HNP request to the other
+ * connected device.
+ */
+ static inline void USB_OTG_Device_CancelHNPRequest(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_OTG_Device_CancelHNPRequest(void)
+ {
+ OTGCON &= ~(1 << HNPREQ);
+ }
+
+ /** Determines if the device is currently sending a HNP to an attached host.
+ *
+ * \return Boolean \c true if currently sending a HNP to the other connected device, \c false otherwise
+ */
+ static inline bool USB_OTG_Device_IsSendingHNP(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool USB_OTG_Device_IsSendingHNP(void)
+ {
+ return ((OTGCON & (1 << HNPREQ)) ? true : false);
+ }
+
+ /** Initiates a Session Request Protocol request. Most OTG devices turn off VBUS when the USB
+ * interface is not in use, to conserve power. Sending a SRP to a USB OTG device running in
+ * host mode indicates that VBUS should be applied and a session started.
+ *
+ * There are two different methods of sending a SRP - either pulses on the VBUS line, or by
+ * pulsing the Data + line via the internal pull-up resistor.
+ *
+ * \param[in] SRPTypeMask Mask indicating the type of SRP to use, either \ref USB_OTG_SRP_VBUS or
+ * \ref USB_OTG_STP_DATA.
+ */
+ static inline void USB_OTG_Device_InitiateSRP(const uint8_t SRPTypeMask) ATTR_ALWAYS_INLINE;
+ static inline void USB_OTG_Device_InitiateSRP(const uint8_t SRPTypeMask)
+ {
+ OTGCON = ((OTGCON & ~(1 << SRPSEL)) | (SRPTypeMask | (1 << SRPREQ)));
+ }
+
+ /** Accepts a HNP from a connected device, indicating that both devices should exchange
+ * device/host roles.
+ */
+ static inline void USB_OTG_Host_AcceptHNP(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_OTG_Host_AcceptHNP(void)
+ {
+ OTGCON |= (1 << HNPREQ);
+ }
+
+ /** Rejects a HNP from a connected device, indicating that both devices should remain in their
+ * current device/host roles.
+ */
+ static inline void USB_OTG_Host_RejectHNP(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_OTG_Host_RejectHNP(void)
+ {
+ OTGCON &= ~(1 << HNPREQ);
+ }
+
+ /** Indicates if the connected device is currently sending a HNP request.
+ *
+ * \return Boolean \c true if a HNP is currently being issued by the connected device, \c false otherwise.
+ */
+ static inline bool USB_OTG_Host_IsHNPReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool USB_OTG_Host_IsHNPReceived(void)
+ {
+ return ((OTGCON & (1 << HNPREQ)) ? true : false);
+ }
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/PipeStream_AVR8.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/PipeStream_AVR8.c
new file mode 100644
index 000000000..47169b3fe
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/PipeStream_AVR8.c
@@ -0,0 +1,221 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "../../../../Common/Common.h"
+#if (ARCH == ARCH_AVR8)
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../USBMode.h"
+
+#if defined(USB_CAN_BE_HOST)
+
+#include "PipeStream_AVR8.h"
+
+uint8_t Pipe_Discard_Stream(uint16_t Length,
+ uint16_t* const BytesProcessed)
+{
+ uint8_t ErrorCode;
+ uint16_t BytesInTransfer = 0;
+
+ Pipe_SetPipeToken(PIPE_TOKEN_IN);
+
+ if ((ErrorCode = Pipe_WaitUntilReady()))
+ return ErrorCode;
+
+ if (BytesProcessed != NULL)
+ Length -= *BytesProcessed;
+
+ while (Length)
+ {
+ if (!(Pipe_IsReadWriteAllowed()))
+ {
+ Pipe_ClearIN();
+
+ if (BytesProcessed != NULL)
+ {
+ *BytesProcessed += BytesInTransfer;
+ return PIPE_RWSTREAM_IncompleteTransfer;
+ }
+
+ if ((ErrorCode = Pipe_WaitUntilReady()))
+ return ErrorCode;
+ }
+ else
+ {
+ Pipe_Discard_8();
+
+ Length--;
+ BytesInTransfer++;
+ }
+ }
+
+ return PIPE_RWSTREAM_NoError;
+}
+
+uint8_t Pipe_Null_Stream(uint16_t Length,
+ uint16_t* const BytesProcessed)
+{
+ uint8_t ErrorCode;
+ uint16_t BytesInTransfer = 0;
+
+ Pipe_SetPipeToken(PIPE_TOKEN_OUT);
+
+ if ((ErrorCode = Pipe_WaitUntilReady()))
+ return ErrorCode;
+
+ if (BytesProcessed != NULL)
+ Length -= *BytesProcessed;
+
+ while (Length)
+ {
+ if (!(Pipe_IsReadWriteAllowed()))
+ {
+ Pipe_ClearOUT();
+
+ if (BytesProcessed != NULL)
+ {
+ *BytesProcessed += BytesInTransfer;
+ return PIPE_RWSTREAM_IncompleteTransfer;
+ }
+
+ USB_USBTask();
+
+ if ((ErrorCode = Pipe_WaitUntilReady()))
+ return ErrorCode;
+ }
+ else
+ {
+ Pipe_Write_8(0);
+
+ Length--;
+ BytesInTransfer++;
+ }
+ }
+
+ return PIPE_RWSTREAM_NoError;
+}
+
+/* The following abuses the C preprocessor in order to copy-paste common code with slight alterations,
+ * so that the code needs to be written once. It is a crude form of templating to reduce code maintenance. */
+
+#define TEMPLATE_FUNC_NAME Pipe_Write_Stream_LE
+#define TEMPLATE_BUFFER_TYPE const void*
+#define TEMPLATE_TOKEN PIPE_TOKEN_OUT
+#define TEMPLATE_CLEAR_PIPE() Pipe_ClearOUT()
+#define TEMPLATE_BUFFER_OFFSET(Length) 0
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) DataStream += Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Pipe_Write_8(*BufferPtr)
+#include "Template/Template_Pipe_RW.c"
+
+#define TEMPLATE_FUNC_NAME Pipe_Write_Stream_BE
+#define TEMPLATE_BUFFER_TYPE const void*
+#define TEMPLATE_TOKEN PIPE_TOKEN_OUT
+#define TEMPLATE_CLEAR_PIPE() Pipe_ClearOUT()
+#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) DataStream -= Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Pipe_Write_8(*BufferPtr)
+#include "Template/Template_Pipe_RW.c"
+
+#define TEMPLATE_FUNC_NAME Pipe_Read_Stream_LE
+#define TEMPLATE_BUFFER_TYPE void*
+#define TEMPLATE_TOKEN PIPE_TOKEN_IN
+#define TEMPLATE_CLEAR_PIPE() Pipe_ClearIN()
+#define TEMPLATE_BUFFER_OFFSET(Length) 0
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) DataStream += Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) *BufferPtr = Pipe_Read_8()
+#include "Template/Template_Pipe_RW.c"
+
+#define TEMPLATE_FUNC_NAME Pipe_Read_Stream_BE
+#define TEMPLATE_BUFFER_TYPE void*
+#define TEMPLATE_TOKEN PIPE_TOKEN_IN
+#define TEMPLATE_CLEAR_PIPE() Pipe_ClearIN()
+#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) DataStream -= Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) *BufferPtr = Pipe_Read_8()
+#include "Template/Template_Pipe_RW.c"
+
+#define TEMPLATE_FUNC_NAME Pipe_Write_PStream_LE
+#define TEMPLATE_BUFFER_TYPE const void*
+#define TEMPLATE_TOKEN PIPE_TOKEN_OUT
+#define TEMPLATE_CLEAR_PIPE() Pipe_ClearOUT()
+#define TEMPLATE_BUFFER_OFFSET(Length) 0
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) DataStream += Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Pipe_Write_8(pgm_read_byte(BufferPtr))
+#include "Template/Template_Pipe_RW.c"
+
+#define TEMPLATE_FUNC_NAME Pipe_Write_PStream_BE
+#define TEMPLATE_BUFFER_TYPE const void*
+#define TEMPLATE_TOKEN PIPE_TOKEN_OUT
+#define TEMPLATE_CLEAR_PIPE() Pipe_ClearOUT()
+#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) DataStream -= Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Pipe_Write_8(pgm_read_byte(BufferPtr))
+#include "Template/Template_Pipe_RW.c"
+
+#define TEMPLATE_FUNC_NAME Pipe_Write_EStream_LE
+#define TEMPLATE_BUFFER_TYPE const void*
+#define TEMPLATE_TOKEN PIPE_TOKEN_OUT
+#define TEMPLATE_CLEAR_PIPE() Pipe_ClearOUT()
+#define TEMPLATE_BUFFER_OFFSET(Length) 0
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) DataStream += Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Pipe_Write_8(eeprom_read_byte(BufferPtr))
+#include "Template/Template_Pipe_RW.c"
+
+#define TEMPLATE_FUNC_NAME Pipe_Write_EStream_BE
+#define TEMPLATE_BUFFER_TYPE const void*
+#define TEMPLATE_TOKEN PIPE_TOKEN_OUT
+#define TEMPLATE_CLEAR_PIPE() Pipe_ClearOUT()
+#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) DataStream -= Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Pipe_Write_8(eeprom_read_byte(BufferPtr))
+#include "Template/Template_Pipe_RW.c"
+
+#define TEMPLATE_FUNC_NAME Pipe_Read_EStream_LE
+#define TEMPLATE_BUFFER_TYPE void*
+#define TEMPLATE_TOKEN PIPE_TOKEN_IN
+#define TEMPLATE_CLEAR_PIPE() Pipe_ClearIN()
+#define TEMPLATE_BUFFER_OFFSET(Length) 0
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) DataStream += Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) eeprom_update_byte(BufferPtr, Pipe_Read_8())
+#include "Template/Template_Pipe_RW.c"
+
+#define TEMPLATE_FUNC_NAME Pipe_Read_EStream_BE
+#define TEMPLATE_BUFFER_TYPE void*
+#define TEMPLATE_TOKEN PIPE_TOKEN_IN
+#define TEMPLATE_CLEAR_PIPE() Pipe_ClearIN()
+#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) DataStream -= Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) eeprom_update_byte(BufferPtr, Pipe_Read_8())
+#include "Template/Template_Pipe_RW.c"
+
+#endif
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/PipeStream_AVR8.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/PipeStream_AVR8.h
new file mode 100644
index 000000000..264dab54e
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/PipeStream_AVR8.h
@@ -0,0 +1,442 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Pipe data stream transmission and reception management for the AVR8 microcontrollers
+ * \copydetails Group_PipeStreamRW_AVR8
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_PipeStreamRW
+ * \defgroup Group_PipeStreamRW_AVR8 Read/Write of Multi-Byte Streams (AVR8)
+ * \brief Pipe data stream transmission and reception management for the Atmel AVR8 architecture.
+ *
+ * Functions, macros, variables, enums and types related to data reading and writing of data streams from
+ * and to pipes.
+ *
+ * @{
+ */
+
+#ifndef __PIPE_STREAM_AVR8_H__
+#define __PIPE_STREAM_AVR8_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../USBMode.h"
+ #include "../USBTask.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Function Prototypes: */
+ /** \name Stream functions for null data */
+ //@{
+
+ /** Reads and discards the given number of bytes from the pipe, discarding fully read packets from the host
+ * as needed. The last packet is not automatically discarded once the remaining bytes has been read; the
+ * user is responsible for manually discarding the last packet from the device via the \ref Pipe_ClearIN() macro.
+ *
+ * If the BytesProcessed parameter is \c NULL, the entire stream transfer is attempted at once, failing or
+ * succeeding as a single unit. If the BytesProcessed parameter points to a valid storage location, the transfer
+ * will instead be performed as a series of chunks. Each time the pipe bank becomes empty while there is still data
+ * to process (and after the current packet has been acknowledged) the BytesProcessed location will be updated with
+ * the total number of bytes processed in the stream, and the function will exit with an error code of
+ * \ref PIPE_RWSTREAM_IncompleteTransfer. This allows for any abort checking to be performed in the user code - to
+ * continue the transfer, call the function again with identical parameters and it will resume until the BytesProcessed
+ * value reaches the total transfer length.
+ *
+ * <b>Single Stream Transfer Example:</b>
+ * \code
+ * uint8_t ErrorCode;
+ *
+ * if ((ErrorCode = Pipe_Discard_Stream(512, NULL)) != PIPE_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * <b>Partial Stream Transfers Example:</b>
+ * \code
+ * uint8_t ErrorCode;
+ * uint16_t BytesProcessed;
+ *
+ * BytesProcessed = 0;
+ * while ((ErrorCode = Pipe_Discard_Stream(512, &BytesProcessed)) == PIPE_RWSTREAM_IncompleteTransfer)
+ * {
+ * // Stream not yet complete - do other actions here, abort if required
+ * }
+ *
+ * if (ErrorCode != PIPE_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * \note The pipe token is set automatically, thus this can be used on bi-directional pipes directly without
+ * having to explicitly change the data direction with a call to \ref Pipe_SetPipeToken().
+ *
+ * \param[in] Length Number of bytes to discard via the currently selected pipe.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes already processed should
+ * updated, \c NULL if the entire stream should be processed at once.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Pipe_Discard_Stream(uint16_t Length,
+ uint16_t* const BytesProcessed);
+
+ /** Writes a given number of zeroed bytes to the pipe, sending full pipe packets from the host to the device
+ * as needed. The last packet is not automatically sent once the remaining bytes has been written; the
+ * user is responsible for manually discarding the last packet from the device via the \ref Pipe_ClearOUT() macro.
+ *
+ * If the BytesProcessed parameter is \c NULL, the entire stream transfer is attempted at once, failing or
+ * succeeding as a single unit. If the BytesProcessed parameter points to a valid storage location, the transfer
+ * will instead be performed as a series of chunks. Each time the pipe bank becomes full while there is still data
+ * to process (and after the current packet transmission has been initiated) the BytesProcessed location will be
+ * updated with the total number of bytes processed in the stream, and the function will exit with an error code of
+ * \ref PIPE_RWSTREAM_IncompleteTransfer. This allows for any abort checking to be performed in the user code - to
+ * continue the transfer, call the function again with identical parameters and it will resume until the BytesProcessed
+ * value reaches the total transfer length.
+ *
+ * <b>Single Stream Transfer Example:</b>
+ * \code
+ * uint8_t ErrorCode;
+ *
+ * if ((ErrorCode = Pipe_Null_Stream(512, NULL)) != PIPE_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * <b>Partial Stream Transfers Example:</b>
+ * \code
+ * uint8_t ErrorCode;
+ * uint16_t BytesProcessed;
+ *
+ * BytesProcessed = 0;
+ * while ((ErrorCode = Pipe_Null_Stream(512, &BytesProcessed)) == PIPE_RWSTREAM_IncompleteTransfer)
+ * {
+ * // Stream not yet complete - do other actions here, abort if required
+ * }
+ *
+ * if (ErrorCode != PIPE_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * \note The pipe token is set automatically, thus this can be used on bi-directional pipes directly without
+ * having to explicitly change the data direction with a call to \ref Pipe_SetPipeToken().
+ *
+ * \param[in] Length Number of zero bytes to write via the currently selected pipe.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes already processed should
+ * updated, \c NULL if the entire stream should be processed at once.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Pipe_Null_Stream(uint16_t Length,
+ uint16_t* const BytesProcessed);
+
+ //@}
+
+ /** \name Stream functions for RAM source/destination data */
+ //@{
+
+ /** Writes the given number of bytes to the pipe from the given buffer in little endian,
+ * sending full packets to the device as needed. The last packet filled is not automatically sent;
+ * the user is responsible for manually sending the last written packet to the host via the
+ * \ref Pipe_ClearOUT() macro. Between each USB packet, the given stream callback function is
+ * executed repeatedly until the next packet is ready, allowing for early aborts of stream transfers.
+ *
+ * If the BytesProcessed parameter is \c NULL, the entire stream transfer is attempted at once,
+ * failing or succeeding as a single unit. If the BytesProcessed parameter points to a valid
+ * storage location, the transfer will instead be performed as a series of chunks. Each time
+ * the pipe bank becomes full while there is still data to process (and after the current
+ * packet transmission has been initiated) the BytesProcessed location will be updated with the
+ * total number of bytes processed in the stream, and the function will exit with an error code of
+ * \ref PIPE_RWSTREAM_IncompleteTransfer. This allows for any abort checking to be performed
+ * in the user code - to continue the transfer, call the function again with identical parameters
+ * and it will resume until the BytesProcessed value reaches the total transfer length.
+ *
+ * <b>Single Stream Transfer Example:</b>
+ * \code
+ * uint8_t DataStream[512];
+ * uint8_t ErrorCode;
+ *
+ * if ((ErrorCode = Pipe_Write_Stream_LE(DataStream, sizeof(DataStream),
+ * NULL)) != PIPE_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * <b>Partial Stream Transfers Example:</b>
+ * \code
+ * uint8_t DataStream[512];
+ * uint8_t ErrorCode;
+ * uint16_t BytesProcessed;
+ *
+ * BytesProcessed = 0;
+ * while ((ErrorCode = Pipe_Write_Stream_LE(DataStream, sizeof(DataStream),
+ * &BytesProcessed)) == PIPE_RWSTREAM_IncompleteTransfer)
+ * {
+ * // Stream not yet complete - do other actions here, abort if required
+ * }
+ *
+ * if (ErrorCode != PIPE_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * \note The pipe token is set automatically, thus this can be used on bi-directional pipes directly without
+ * having to explicitly change the data direction with a call to \ref Pipe_SetPipeToken().
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected pipe into the buffer.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes already processed should
+ * updated, \c NULL if the entire stream should be written at once.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Pipe_Write_Stream_LE(const void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Writes the given number of bytes to the pipe from the given buffer in big endian,
+ * sending full packets to the device as needed. The last packet filled is not automatically sent;
+ * the user is responsible for manually sending the last written packet to the host via the
+ * \ref Pipe_ClearOUT() macro. Between each USB packet, the given stream callback function is
+ * executed repeatedly until the next packet is ready, allowing for early aborts of stream transfers.
+ *
+ * \note The pipe token is set automatically, thus this can be used on bi-directional pipes directly without
+ * having to explicitly change the data direction with a call to \ref Pipe_SetPipeToken().
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected pipe into the buffer.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes already processed should
+ * updated, \c NULL if the entire stream should be written at once.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Pipe_Write_Stream_BE(const void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Reads the given number of bytes from the pipe into the given buffer in little endian,
+ * sending full packets to the device as needed. The last packet filled is not automatically sent;
+ * the user is responsible for manually sending the last written packet to the host via the
+ * \ref Pipe_ClearIN() macro. Between each USB packet, the given stream callback function is
+ * executed repeatedly until the next packet is ready, allowing for early aborts of stream transfers.
+ *
+ * If the BytesProcessed parameter is \c NULL, the entire stream transfer is attempted at once,
+ * failing or succeeding as a single unit. If the BytesProcessed parameter points to a valid
+ * storage location, the transfer will instead be performed as a series of chunks. Each time
+ * the pipe bank becomes empty while there is still data to process (and after the current
+ * packet has been acknowledged) the BytesProcessed location will be updated with the total number
+ * of bytes processed in the stream, and the function will exit with an error code of
+ * \ref PIPE_RWSTREAM_IncompleteTransfer. This allows for any abort checking to be performed
+ * in the user code - to continue the transfer, call the function again with identical parameters
+ * and it will resume until the BytesProcessed value reaches the total transfer length.
+ *
+ * <b>Single Stream Transfer Example:</b>
+ * \code
+ * uint8_t DataStream[512];
+ * uint8_t ErrorCode;
+ *
+ * if ((ErrorCode = Pipe_Read_Stream_LE(DataStream, sizeof(DataStream),
+ * NULL)) != PIPE_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * <b>Partial Stream Transfers Example:</b>
+ * \code
+ * uint8_t DataStream[512];
+ * uint8_t ErrorCode;
+ * uint16_t BytesProcessed;
+ *
+ * BytesProcessed = 0;
+ * while ((ErrorCode = Pipe_Read_Stream_LE(DataStream, sizeof(DataStream),
+ * &BytesProcessed)) == PIPE_RWSTREAM_IncompleteTransfer)
+ * {
+ * // Stream not yet complete - do other actions here, abort if required
+ * }
+ *
+ * if (ErrorCode != PIPE_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * \note The pipe token is set automatically, thus this can be used on bi-directional pipes directly without
+ * having to explicitly change the data direction with a call to \ref Pipe_SetPipeToken().
+ *
+ * \param[out] Buffer Pointer to the source data buffer to write to.
+ * \param[in] Length Number of bytes to read for the currently selected pipe to read from.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes already processed should
+ * updated, \c NULL if the entire stream should be read at once.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Pipe_Read_Stream_LE(void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Reads the given number of bytes from the pipe into the given buffer in big endian,
+ * sending full packets to the device as needed. The last packet filled is not automatically sent;
+ * the user is responsible for manually sending the last written packet to the host via the
+ * \ref Pipe_ClearIN() macro. Between each USB packet, the given stream callback function is
+ * executed repeatedly until the next packet is ready, allowing for early aborts of stream transfers.
+ *
+ * \note The pipe token is set automatically, thus this can be used on bi-directional pipes directly without
+ * having to explicitly change the data direction with a call to \ref Pipe_SetPipeToken().
+ *
+ * \param[out] Buffer Pointer to the source data buffer to write to.
+ * \param[in] Length Number of bytes to read for the currently selected pipe to read from.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes already processed should
+ * updated, \c NULL if the entire stream should be read at once.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Pipe_Read_Stream_BE(void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+ //@}
+
+ /** \name Stream functions for EEPROM source/destination data */
+ //@{
+
+ /** EEPROM buffer source version of \ref Pipe_Write_Stream_LE().
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected pipe into the buffer.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes already processed should
+ * updated, \c NULL if the entire stream should be written at once.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Pipe_Write_EStream_LE(const void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** EEPROM buffer source version of \ref Pipe_Write_Stream_BE().
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected pipe into the buffer.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes already processed should
+ * updated, \c NULL if the entire stream should be written at once.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Pipe_Write_EStream_BE(const void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** EEPROM buffer source version of \ref Pipe_Read_Stream_LE().
+ *
+ * \param[out] Buffer Pointer to the source data buffer to write to.
+ * \param[in] Length Number of bytes to read for the currently selected pipe to read from.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes already processed should
+ * updated, \c NULL if the entire stream should be read at once.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Pipe_Read_EStream_LE(void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** EEPROM buffer source version of \ref Pipe_Read_Stream_BE().
+ *
+ * \param[out] Buffer Pointer to the source data buffer to write to.
+ * \param[in] Length Number of bytes to read for the currently selected pipe to read from.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes already processed should
+ * updated, \c NULL if the entire stream should be read at once.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Pipe_Read_EStream_BE(void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+ //@}
+
+ /** \name Stream functions for PROGMEM source/destination data */
+ //@{
+
+ /** FLASH buffer source version of \ref Pipe_Write_Stream_LE().
+ *
+ * \pre The FLASH data must be located in the first 64KB of FLASH for this function to work correctly.
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected pipe into the buffer.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes already processed should
+ * updated, \c NULL if the entire stream should be written at once.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Pipe_Write_PStream_LE(const void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** FLASH buffer source version of \ref Pipe_Write_Stream_BE().
+ *
+ * \pre The FLASH data must be located in the first 64KB of FLASH for this function to work correctly.
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected pipe into the buffer.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes already processed should
+ * updated, \c NULL if the entire stream should be written at once.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Pipe_Write_PStream_BE(const void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+ //@}
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.c
new file mode 100644
index 000000000..fc99ae416
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.c
@@ -0,0 +1,210 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "../../../../Common/Common.h"
+#if (ARCH == ARCH_AVR8)
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../USBMode.h"
+
+#if defined(USB_CAN_BE_HOST)
+
+#include "../Pipe.h"
+
+uint8_t USB_Host_ControlPipeSize = PIPE_CONTROLPIPE_DEFAULT_SIZE;
+
+bool Pipe_ConfigurePipeTable(const USB_Pipe_Table_t* const Table,
+ const uint8_t Entries)
+{
+ for (uint8_t i = 0; i < Entries; i++)
+ {
+ if (!(Table[i].Address))
+ continue;
+
+ if (!(Pipe_ConfigurePipe(Table[i].Address, Table[i].Type, Table[i].EndpointAddress, Table[i].Size, Table[i].Banks)))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool Pipe_ConfigurePipe(const uint8_t Address,
+ const uint8_t Type,
+ const uint8_t EndpointAddress,
+ const uint16_t Size,
+ const uint8_t Banks)
+{
+ uint8_t Number = (Address & PIPE_EPNUM_MASK);
+ uint8_t Token = (Address & PIPE_DIR_IN) ? PIPE_TOKEN_IN : PIPE_TOKEN_OUT;
+
+ if (Number >= PIPE_TOTAL_PIPES)
+ return false;
+
+ if (Type == EP_TYPE_CONTROL)
+ Token = PIPE_TOKEN_SETUP;
+
+#if defined(ORDERED_EP_CONFIG)
+ Pipe_SelectPipe(Number);
+ Pipe_EnablePipe();
+
+ UPCFG1X = 0;
+
+ UPCFG0X = ((Type << EPTYPE0) | Token | ((EndpointAddress & PIPE_EPNUM_MASK) << PEPNUM0));
+ UPCFG1X = ((1 << ALLOC) | ((Banks > 1) ? (1 << EPBK0) : 0) | Pipe_BytesToEPSizeMask(Size));
+
+ Pipe_SetInfiniteINRequests();
+
+ return Pipe_IsConfigured();
+#else
+ for (uint8_t PNum = Number; PNum < PIPE_TOTAL_PIPES; PNum++)
+ {
+ uint8_t UPCFG0XTemp;
+ uint8_t UPCFG1XTemp;
+ uint8_t UPCFG2XTemp;
+ uint8_t UPIENXTemp;
+
+ Pipe_SelectPipe(PNum);
+
+ if (PNum == Number)
+ {
+ UPCFG0XTemp = ((Type << EPTYPE0) | Token | ((EndpointAddress & PIPE_EPNUM_MASK) << PEPNUM0));
+ UPCFG1XTemp = ((1 << ALLOC) | ((Banks > 1) ? (1 << EPBK0) : 0) | Pipe_BytesToEPSizeMask(Size));
+ UPCFG2XTemp = 0;
+ UPIENXTemp = 0;
+ }
+ else
+ {
+ UPCFG0XTemp = UPCFG0X;
+ UPCFG1XTemp = UPCFG1X;
+ UPCFG2XTemp = UPCFG2X;
+ UPIENXTemp = UPIENX;
+ }
+
+ if (!(UPCFG1XTemp & (1 << ALLOC)))
+ continue;
+
+ Pipe_DisablePipe();
+ UPCFG1X &= ~(1 << ALLOC);
+
+ Pipe_EnablePipe();
+ UPCFG0X = UPCFG0XTemp;
+ UPCFG1X = UPCFG1XTemp;
+ UPCFG2X = UPCFG2XTemp;
+ UPIENX = UPIENXTemp;
+
+ Pipe_SetInfiniteINRequests();
+
+ if (!(Pipe_IsConfigured()))
+ return false;
+ }
+
+ Pipe_SelectPipe(Number);
+ return true;
+#endif
+}
+
+void Pipe_ClearPipes(void)
+{
+ UPINT = 0;
+
+ for (uint8_t PNum = 0; PNum < PIPE_TOTAL_PIPES; PNum++)
+ {
+ Pipe_SelectPipe(PNum);
+ UPIENX = 0;
+ UPINTX = 0;
+ UPCFG1X = 0;
+ Pipe_DisablePipe();
+ }
+}
+
+bool Pipe_IsEndpointBound(const uint8_t EndpointAddress)
+{
+ uint8_t PrevPipeNumber = Pipe_GetCurrentPipe();
+
+ for (uint8_t PNum = 0; PNum < PIPE_TOTAL_PIPES; PNum++)
+ {
+ Pipe_SelectPipe(PNum);
+
+ if (!(Pipe_IsConfigured()))
+ continue;
+
+ if (Pipe_GetBoundEndpointAddress() == EndpointAddress)
+ return true;
+ }
+
+ Pipe_SelectPipe(PrevPipeNumber);
+ return false;
+}
+
+uint8_t Pipe_WaitUntilReady(void)
+{
+ #if (USB_STREAM_TIMEOUT_MS < 0xFF)
+ uint8_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
+ #else
+ uint16_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
+ #endif
+
+ uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber();
+
+ for (;;)
+ {
+ if (Pipe_GetPipeToken() == PIPE_TOKEN_IN)
+ {
+ if (Pipe_IsINReceived())
+ return PIPE_READYWAIT_NoError;
+ }
+ else
+ {
+ if (Pipe_IsOUTReady())
+ return PIPE_READYWAIT_NoError;
+ }
+
+ if (Pipe_IsStalled())
+ return PIPE_READYWAIT_PipeStalled;
+ else if (USB_HostState == HOST_STATE_Unattached)
+ return PIPE_READYWAIT_DeviceDisconnected;
+
+ uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber();
+
+ if (CurrentFrameNumber != PreviousFrameNumber)
+ {
+ PreviousFrameNumber = CurrentFrameNumber;
+
+ if (!(TimeoutMSRem--))
+ return PIPE_READYWAIT_Timeout;
+ }
+ }
+}
+
+#endif
+
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.h
new file mode 100644
index 000000000..bac324ffc
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.h
@@ -0,0 +1,922 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief USB Pipe definitions for the AVR8 microcontrollers.
+ * \copydetails Group_PipeManagement_AVR8
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_PipeRW
+ * \defgroup Group_PipeRW_AVR8 Pipe Data Reading and Writing (AVR8)
+ * \brief Pipe data read/write definitions for the Atmel AVR8 architecture.
+ *
+ * Functions, macros, variables, enums and types related to data reading and writing from and to pipes.
+ */
+
+/** \ingroup Group_PipePrimitiveRW
+ * \defgroup Group_PipePrimitiveRW_AVR8 Read/Write of Primitive Data Types (AVR8)
+ * \brief Pipe primitive data read/write definitions for the Atmel AVR8 architecture.
+ *
+ * Functions, macros, variables, enums and types related to data reading and writing of primitive data types
+ * from and to pipes.
+ */
+
+/** \ingroup Group_PipePacketManagement
+ * \defgroup Group_PipePacketManagement_AVR8 Pipe Packet Management (AVR8)
+ * \brief Pipe packet management definitions for the Atmel AVR8 architecture.
+ *
+ * Functions, macros, variables, enums and types related to packet management of pipes.
+ */
+
+/** \ingroup Group_PipeControlReq
+ * \defgroup Group_PipeControlReq_AVR8 Pipe Control Request Management (AVR8)
+ * \brief Pipe control request management definitions for the Atmel AVR8 architecture.
+ *
+ * Module for host mode request processing. This module allows for the transmission of standard, class and
+ * vendor control requests to the default control endpoint of an attached device while in host mode.
+ *
+ * \see Chapter 9 of the USB 2.0 specification.
+ */
+
+/** \ingroup Group_PipeManagement
+ * \defgroup Group_PipeManagement_AVR8 Pipe Management (AVR8)
+ * \brief Pipe management definitions for the Atmel AVR8 architecture.
+ *
+ * This module contains functions, macros and enums related to pipe management when in USB Host mode. This
+ * module contains the pipe management macros, as well as pipe interrupt and data send/receive functions
+ * for various data types.
+ *
+ * @{
+ */
+
+#ifndef __PIPE_AVR8_H__
+#define __PIPE_AVR8_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../USBTask.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** \name Pipe Error Flag Masks */
+ //@{
+ /** Mask for \ref Pipe_GetErrorFlags(), indicating that an overflow error occurred in the pipe on the received data. */
+ #define PIPE_ERRORFLAG_OVERFLOW (1 << 6)
+
+ /** Mask for \ref Pipe_GetErrorFlags(), indicating that an underflow error occurred in the pipe on the received data. */
+ #define PIPE_ERRORFLAG_UNDERFLOW (1 << 5)
+
+ /** Mask for \ref Pipe_GetErrorFlags(), indicating that a CRC error occurred in the pipe on the received data. */
+ #define PIPE_ERRORFLAG_CRC16 (1 << 4)
+
+ /** Mask for \ref Pipe_GetErrorFlags(), indicating that a hardware timeout error occurred in the pipe. */
+ #define PIPE_ERRORFLAG_TIMEOUT (1 << 3)
+
+ /** Mask for \ref Pipe_GetErrorFlags(), indicating that a hardware PID error occurred in the pipe. */
+ #define PIPE_ERRORFLAG_PID (1 << 2)
+
+ /** Mask for \ref Pipe_GetErrorFlags(), indicating that a hardware data PID error occurred in the pipe. */
+ #define PIPE_ERRORFLAG_DATAPID (1 << 1)
+
+ /** Mask for \ref Pipe_GetErrorFlags(), indicating that a hardware data toggle error occurred in the pipe. */
+ #define PIPE_ERRORFLAG_DATATGL (1 << 0)
+ //@}
+
+ /** \name Pipe Token Masks */
+ //@{
+ /** Token mask for \ref Pipe_SetPipeToken() and \ref Pipe_GetPipeToken(). This sets the pipe as a SETUP token (for CONTROL type pipes),
+ * which will trigger a control request on the attached device when data is written to the pipe.
+ */
+ #define PIPE_TOKEN_SETUP (0 << PTOKEN0)
+
+ /** Token mask for \ref Pipe_SetPipeToken() and \ref Pipe_GetPipeToken(). This sets the pipe as a IN token (for non-CONTROL type pipes),
+ * indicating that the pipe data will flow from device to host.
+ */
+ #define PIPE_TOKEN_IN (1 << PTOKEN0)
+
+ /** Token mask for \ref Pipe_SetPipeToken() and \ref Pipe_GetPipeToken(). This sets the pipe as a OUT token (for non-CONTROL type pipes),
+ * indicating that the pipe data will flow from host to device.
+ */
+ #define PIPE_TOKEN_OUT (2 << PTOKEN0)
+ //@}
+
+ /** Default size of the default control pipe's bank, until altered by the Endpoint0Size value
+ * in the device descriptor of the attached device.
+ */
+ #define PIPE_CONTROLPIPE_DEFAULT_SIZE 64
+
+ /** Total number of pipes (including the default control pipe at address 0) which may be used in
+ * the device. Different USB AVR models support different amounts of pipes, this value reflects
+ * the maximum number of pipes for the currently selected AVR model.
+ */
+ #define PIPE_TOTAL_PIPES 7
+
+ /** Size in bytes of the largest pipe bank size possible in the device. Not all banks on each AVR
+ * model supports the largest bank size possible on the device; different pipe numbers support
+ * different maximum bank sizes. This value reflects the largest possible bank of any pipe on the
+ * currently selected USB AVR model.
+ */
+ #define PIPE_MAX_SIZE 256
+
+ /* Enums: */
+ /** Enum for the possible error return codes of the \ref Pipe_WaitUntilReady() function.
+ *
+ * \ingroup Group_PipeRW_AVR8
+ */
+ enum Pipe_WaitUntilReady_ErrorCodes_t
+ {
+ PIPE_READYWAIT_NoError = 0, /**< Pipe ready for next packet, no error. */
+ PIPE_READYWAIT_PipeStalled = 1, /**< The device stalled the pipe while waiting. */
+ PIPE_READYWAIT_DeviceDisconnected = 2, /**< Device was disconnected from the host while waiting. */
+ PIPE_READYWAIT_Timeout = 3, /**< The device failed to accept or send the next packet
+ * within the software timeout period set by the
+ * \ref USB_STREAM_TIMEOUT_MS macro.
+ */
+ };
+
+ /* Inline Functions: */
+ /** Indicates the number of bytes currently stored in the current pipes's selected bank.
+ *
+ * \ingroup Group_PipeRW_AVR8
+ *
+ * \return Total number of bytes in the currently selected pipe's FIFO buffer.
+ */
+ static inline uint16_t Pipe_BytesInPipe(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint16_t Pipe_BytesInPipe(void)
+ {
+ return UPBCX;
+ }
+
+ /** Determines the currently selected pipe's direction.
+ *
+ * \return The currently selected pipe's direction, as a \c PIPE_DIR_* mask.
+ */
+ static inline uint8_t Pipe_GetPipeDirection(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Pipe_GetPipeDirection(void)
+ {
+ return (UPCFG0X & (1 << EPDIR)) ? PIPE_DIR_IN : PIPE_DIR_OUT;
+ }
+
+ /** Returns the pipe address of the currently selected pipe. This is typically used to save the
+ * currently selected pipe address so that it can be restored after another pipe has been manipulated.
+ *
+ * \return Index of the currently selected pipe.
+ */
+ static inline uint8_t Pipe_GetCurrentPipe(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Pipe_GetCurrentPipe(void)
+ {
+ return ((UPNUM & PIPE_PIPENUM_MASK) | Pipe_GetPipeDirection());
+ }
+
+ /** Selects the given pipe address. Any pipe operations which do not require the pipe address to be
+ * indicated will operate on the currently selected pipe.
+ *
+ * \param[in] Address Address of the pipe to select.
+ */
+ static inline void Pipe_SelectPipe(const uint8_t Address) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_SelectPipe(const uint8_t Address)
+ {
+ UPNUM = (Address & PIPE_PIPENUM_MASK);
+ }
+
+ /** Resets the desired pipe, including the pipe banks and flags.
+ *
+ * \param[in] Address Address of the pipe to reset.
+ */
+ static inline void Pipe_ResetPipe(const uint8_t Address) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_ResetPipe(const uint8_t Address)
+ {
+ UPRST = (1 << (Address & PIPE_PIPENUM_MASK));
+ UPRST = 0;
+ }
+
+ /** Enables the currently selected pipe so that data can be sent and received through it to and from
+ * an attached device.
+ *
+ * \pre The currently selected pipe must first be configured properly via \ref Pipe_ConfigurePipe().
+ */
+ static inline void Pipe_EnablePipe(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_EnablePipe(void)
+ {
+ UPCONX |= (1 << PEN);
+ }
+
+ /** Disables the currently selected pipe so that data cannot be sent and received through it to and
+ * from an attached device.
+ */
+ static inline void Pipe_DisablePipe(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_DisablePipe(void)
+ {
+ UPCONX &= ~(1 << PEN);
+ }
+
+ /** Determines if the currently selected pipe is enabled, but not necessarily configured.
+ *
+ * \return Boolean \c true if the currently selected pipe is enabled, \c false otherwise.
+ */
+ static inline bool Pipe_IsEnabled(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsEnabled(void)
+ {
+ return ((UPCONX & (1 << PEN)) ? true : false);
+ }
+
+ /** Gets the current pipe token, indicating the pipe's data direction and type.
+ *
+ * \return The current pipe token, as a \c PIPE_TOKEN_* mask.
+ */
+ static inline uint8_t Pipe_GetPipeToken(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Pipe_GetPipeToken(void)
+ {
+ return (UPCFG0X & (0x03 << PTOKEN0));
+ }
+
+ /** Sets the token for the currently selected pipe to one of the tokens specified by the \c PIPE_TOKEN_*
+ * masks. This can be used on CONTROL type pipes, to allow for bidirectional transfer of data during
+ * control requests, or on regular pipes to allow for half-duplex bidirectional data transfer to devices
+ * which have two endpoints of opposite direction sharing the same endpoint address within the device.
+ *
+ * \param[in] Token New pipe token to set the selected pipe to, as a \c PIPE_TOKEN_* mask.
+ */
+ static inline void Pipe_SetPipeToken(const uint8_t Token) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_SetPipeToken(const uint8_t Token)
+ {
+ UPCFG0X = ((UPCFG0X & ~(0x03 << PTOKEN0)) | Token);
+ }
+
+ /** Configures the currently selected pipe to allow for an unlimited number of IN requests. */
+ static inline void Pipe_SetInfiniteINRequests(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_SetInfiniteINRequests(void)
+ {
+ UPCONX |= (1 << INMODE);
+ }
+
+ /** Configures the currently selected pipe to only allow the specified number of IN requests to be
+ * accepted by the pipe before it is automatically frozen.
+ *
+ * \param[in] TotalINRequests Total number of IN requests that the pipe may receive before freezing.
+ */
+ static inline void Pipe_SetFiniteINRequests(const uint8_t TotalINRequests) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_SetFiniteINRequests(const uint8_t TotalINRequests)
+ {
+ UPCONX &= ~(1 << INMODE);
+ UPINRQX = TotalINRequests;
+ }
+
+ /** Determines if the currently selected pipe is configured.
+ *
+ * \return Boolean \c true if the selected pipe is configured, \c false otherwise.
+ */
+ static inline bool Pipe_IsConfigured(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsConfigured(void)
+ {
+ return ((UPSTAX & (1 << CFGOK)) ? true : false);
+ }
+
+ /** Retrieves the endpoint address of the endpoint within the attached device that the currently selected
+ * pipe is bound to.
+ *
+ * \return Endpoint address the currently selected pipe is bound to.
+ */
+ static inline uint8_t Pipe_GetBoundEndpointAddress(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Pipe_GetBoundEndpointAddress(void)
+ {
+ uint8_t UPCFG0X_Temp = UPCFG0X;
+
+ return (((UPCFG0X_Temp >> PEPNUM0) & PIPE_EPNUM_MASK) |
+ ((UPCFG0X_Temp & (1 << PTOKEN1)) ? ENDPOINT_DIR_IN : ENDPOINT_DIR_OUT));
+ }
+
+ /** Sets the period between interrupts for an INTERRUPT type pipe to a specified number of milliseconds.
+ *
+ * \param[in] Milliseconds Number of milliseconds between each pipe poll.
+ */
+ static inline void Pipe_SetInterruptPeriod(const uint8_t Milliseconds) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_SetInterruptPeriod(const uint8_t Milliseconds)
+ {
+ UPCFG2X = Milliseconds;
+ }
+
+ /** Returns a mask indicating which pipe's interrupt periods have elapsed, indicating that the pipe should
+ * be serviced.
+ *
+ * \return Mask whose bits indicate which pipes have interrupted.
+ */
+ static inline uint8_t Pipe_GetPipeInterrupts(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Pipe_GetPipeInterrupts(void)
+ {
+ return UPINT;
+ }
+
+ /** Determines if the specified pipe address has interrupted (valid only for INTERRUPT type
+ * pipes).
+ *
+ * \param[in] Address Address of the pipe whose interrupt flag should be tested.
+ *
+ * \return Boolean \c true if the specified pipe has interrupted, \c false otherwise.
+ */
+ static inline bool Pipe_HasPipeInterrupted(const uint8_t Address) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_HasPipeInterrupted(const uint8_t Address)
+ {
+ return ((UPINT & (1 << (Address & PIPE_PIPENUM_MASK))) ? true : false);
+ }
+
+ /** Unfreezes the selected pipe, allowing it to communicate with an attached device. */
+ static inline void Pipe_Unfreeze(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_Unfreeze(void)
+ {
+ UPCONX &= ~(1 << PFREEZE);
+ }
+
+ /** Freezes the selected pipe, preventing it from communicating with an attached device. */
+ static inline void Pipe_Freeze(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_Freeze(void)
+ {
+ UPCONX |= (1 << PFREEZE);
+ }
+
+ /** Determines if the currently selected pipe is frozen, and not able to accept data.
+ *
+ * \return Boolean \c true if the currently selected pipe is frozen, \c false otherwise.
+ */
+ static inline bool Pipe_IsFrozen(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsFrozen(void)
+ {
+ return ((UPCONX & (1 << PFREEZE)) ? true : false);
+ }
+
+ /** Clears the error flags for the currently selected pipe. */
+ static inline void Pipe_ClearError(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_ClearError(void)
+ {
+ UPERRX = 0;
+ UPINTX &= ~(1 << PERRI);
+ }
+
+ /** Determines if the master pipe error flag is set for the currently selected pipe, indicating that
+ * some sort of hardware error has occurred on the pipe.
+ *
+ * \see \ref Pipe_GetErrorFlags() macro for information on retrieving the exact error flag.
+ *
+ * \return Boolean \c true if an error has occurred on the selected pipe, \c false otherwise.
+ */
+ static inline bool Pipe_IsError(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsError(void)
+ {
+ return ((UPINTX & (1 << PERRI)) ? true : false);
+ }
+
+ /** Gets a mask of the hardware error flags which have occurred on the currently selected pipe. This
+ * value can then be masked against the \c PIPE_ERRORFLAG_* masks to determine what error has occurred.
+ *
+ * \return Mask comprising of \c PIPE_ERRORFLAG_* bits indicating what error has occurred on the selected pipe.
+ */
+ static inline uint8_t Pipe_GetErrorFlags(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Pipe_GetErrorFlags(void)
+ {
+ return ((UPERRX & (PIPE_ERRORFLAG_CRC16 | PIPE_ERRORFLAG_TIMEOUT |
+ PIPE_ERRORFLAG_PID | PIPE_ERRORFLAG_DATAPID |
+ PIPE_ERRORFLAG_DATATGL)) |
+ (UPSTAX & (PIPE_ERRORFLAG_OVERFLOW | PIPE_ERRORFLAG_UNDERFLOW)));
+ }
+
+ /** Retrieves the number of busy banks in the currently selected pipe, which have been queued for
+ * transmission via the \ref Pipe_ClearOUT() command, or are awaiting acknowledgement via the
+ * \ref Pipe_ClearIN() command.
+ *
+ * \ingroup Group_PipePacketManagement_AVR8
+ *
+ * \return Total number of busy banks in the selected pipe.
+ */
+ static inline uint8_t Pipe_GetBusyBanks(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Pipe_GetBusyBanks(void)
+ {
+ return (UPSTAX & (0x03 << NBUSYBK0));
+ }
+
+ /** Determines if the currently selected pipe may be read from (if data is waiting in the pipe
+ * bank and the pipe is an IN direction, or if the bank is not yet full if the pipe is an OUT
+ * direction). This function will return false if an error has occurred in the pipe, or if the pipe
+ * is an IN direction and no packet (or an empty packet) has been received, or if the pipe is an OUT
+ * direction and the pipe bank is full.
+ *
+ * \note This function is not valid on CONTROL type pipes.
+ *
+ * \ingroup Group_PipePacketManagement_AVR8
+ *
+ * \return Boolean \c true if the currently selected pipe may be read from or written to, depending
+ * on its direction.
+ */
+ static inline bool Pipe_IsReadWriteAllowed(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsReadWriteAllowed(void)
+ {
+ return ((UPINTX & (1 << RWAL)) ? true : false);
+ }
+
+ /** Determines if a packet has been received on the currently selected IN pipe from the attached device.
+ *
+ * \ingroup Group_PipePacketManagement_AVR8
+ *
+ * \return Boolean \c true if the current pipe has received an IN packet, \c false otherwise.
+ */
+ static inline bool Pipe_IsINReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsINReceived(void)
+ {
+ return ((UPINTX & (1 << RXINI)) ? true : false);
+ }
+
+ /** Determines if the currently selected OUT pipe is ready to send an OUT packet to the attached device.
+ *
+ * \ingroup Group_PipePacketManagement_AVR8
+ *
+ * \return Boolean \c true if the current pipe is ready for an OUT packet, \c false otherwise.
+ */
+ static inline bool Pipe_IsOUTReady(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsOUTReady(void)
+ {
+ return ((UPINTX & (1 << TXOUTI)) ? true : false);
+ }
+
+ /** Determines if no SETUP request is currently being sent to the attached device on the selected
+ * CONTROL type pipe.
+ *
+ * \ingroup Group_PipePacketManagement_AVR8
+ *
+ * \return Boolean \c true if the current pipe is ready for a SETUP packet, \c false otherwise.
+ */
+ static inline bool Pipe_IsSETUPSent(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsSETUPSent(void)
+ {
+ return ((UPINTX & (1 << TXSTPI)) ? true : false);
+ }
+
+ /** Sends the currently selected CONTROL type pipe's contents to the device as a SETUP packet.
+ *
+ * \ingroup Group_PipePacketManagement_AVR8
+ */
+ static inline void Pipe_ClearSETUP(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_ClearSETUP(void)
+ {
+ UPINTX &= ~((1 << TXSTPI) | (1 << FIFOCON));
+ }
+
+ /** Acknowledges the reception of a setup IN request from the attached device on the currently selected
+ * pipe, freeing the bank ready for the next packet.
+ *
+ * \ingroup Group_PipePacketManagement_AVR8
+ */
+ static inline void Pipe_ClearIN(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_ClearIN(void)
+ {
+ UPINTX &= ~((1 << RXINI) | (1 << FIFOCON));
+ }
+
+ /** Sends the currently selected pipe's contents to the device as an OUT packet on the selected pipe, freeing
+ * the bank ready for the next packet.
+ *
+ * \ingroup Group_PipePacketManagement_AVR8
+ */
+ static inline void Pipe_ClearOUT(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_ClearOUT(void)
+ {
+ UPINTX &= ~((1 << TXOUTI) | (1 << FIFOCON));
+ }
+
+ /** Determines if the device sent a NAK (Negative Acknowledge) in response to the last sent packet on
+ * the currently selected pipe. This occurs when the host sends a packet to the device, but the device
+ * is not currently ready to handle the packet (i.e. its endpoint banks are full). Once a NAK has been
+ * received, it must be cleared using \ref Pipe_ClearNAKReceived() before the previous (or any other) packet
+ * can be re-sent.
+ *
+ * \ingroup Group_PipePacketManagement_AVR8
+ *
+ * \return Boolean \c true if an NAK has been received on the current pipe, \c false otherwise.
+ */
+ static inline bool Pipe_IsNAKReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsNAKReceived(void)
+ {
+ return ((UPINTX & (1 << NAKEDI)) ? true : false);
+ }
+
+ /** Clears the NAK condition on the currently selected pipe.
+ *
+ * \ingroup Group_PipePacketManagement_AVR8
+ *
+ * \see \ref Pipe_IsNAKReceived() for more details.
+ */
+ static inline void Pipe_ClearNAKReceived(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_ClearNAKReceived(void)
+ {
+ UPINTX &= ~(1 << NAKEDI);
+ }
+
+ /** Determines if the currently selected pipe has had the STALL condition set by the attached device.
+ *
+ * \ingroup Group_PipePacketManagement_AVR8
+ *
+ * \return Boolean \c true if the current pipe has been stalled by the attached device, \c false otherwise.
+ */
+ static inline bool Pipe_IsStalled(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsStalled(void)
+ {
+ return ((UPINTX & (1 << RXSTALLI)) ? true : false);
+ }
+
+ /** Clears the STALL condition detection flag on the currently selected pipe, but does not clear the
+ * STALL condition itself (this must be done via a ClearFeature control request to the device).
+ *
+ * \ingroup Group_PipePacketManagement_AVR8
+ */
+ static inline void Pipe_ClearStall(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_ClearStall(void)
+ {
+ UPINTX &= ~(1 << RXSTALLI);
+ }
+
+ /** Reads one byte from the currently selected pipe's bank, for OUT direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW_AVR8
+ *
+ * \return Next byte in the currently selected pipe's FIFO buffer.
+ */
+ static inline uint8_t Pipe_Read_8(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Pipe_Read_8(void)
+ {
+ return UPDATX;
+ }
+
+ /** Writes one byte to the currently selected pipe's bank, for IN direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW_AVR8
+ *
+ * \param[in] Data Data to write into the the currently selected pipe's FIFO buffer.
+ */
+ static inline void Pipe_Write_8(const uint8_t Data) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_Write_8(const uint8_t Data)
+ {
+ UPDATX = Data;
+ }
+
+ /** Discards one byte from the currently selected pipe's bank, for OUT direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW_AVR8
+ */
+ static inline void Pipe_Discard_8(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_Discard_8(void)
+ {
+ uint8_t Dummy;
+
+ Dummy = UPDATX;
+
+ (void)Dummy;
+ }
+
+ /** Reads two bytes from the currently selected pipe's bank in little endian format, for OUT
+ * direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW_AVR8
+ *
+ * \return Next two bytes in the currently selected pipe's FIFO buffer.
+ */
+ static inline uint16_t Pipe_Read_16_LE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint16_t Pipe_Read_16_LE(void)
+ {
+ union
+ {
+ uint16_t Value;
+ uint8_t Bytes[2];
+ } Data;
+
+ Data.Bytes[0] = UPDATX;
+ Data.Bytes[1] = UPDATX;
+
+ return Data.Value;
+ }
+
+ /** Reads two bytes from the currently selected pipe's bank in big endian format, for OUT
+ * direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW_AVR8
+ *
+ * \return Next two bytes in the currently selected pipe's FIFO buffer.
+ */
+ static inline uint16_t Pipe_Read_16_BE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint16_t Pipe_Read_16_BE(void)
+ {
+ union
+ {
+ uint16_t Value;
+ uint8_t Bytes[2];
+ } Data;
+
+ Data.Bytes[1] = UPDATX;
+ Data.Bytes[0] = UPDATX;
+
+ return Data.Value;
+ }
+
+ /** Writes two bytes to the currently selected pipe's bank in little endian format, for IN
+ * direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW_AVR8
+ *
+ * \param[in] Data Data to write to the currently selected pipe's FIFO buffer.
+ */
+ static inline void Pipe_Write_16_LE(const uint16_t Data) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_Write_16_LE(const uint16_t Data)
+ {
+ UPDATX = (Data & 0xFF);
+ UPDATX = (Data >> 8);
+ }
+
+ /** Writes two bytes to the currently selected pipe's bank in big endian format, for IN
+ * direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW_AVR8
+ *
+ * \param[in] Data Data to write to the currently selected pipe's FIFO buffer.
+ */
+ static inline void Pipe_Write_16_BE(const uint16_t Data) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_Write_16_BE(const uint16_t Data)
+ {
+ UPDATX = (Data >> 8);
+ UPDATX = (Data & 0xFF);
+ }
+
+ /** Discards two bytes from the currently selected pipe's bank, for OUT direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW_AVR8
+ */
+ static inline void Pipe_Discard_16(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_Discard_16(void)
+ {
+ uint8_t Dummy;
+
+ Dummy = UPDATX;
+ Dummy = UPDATX;
+
+ (void)Dummy;
+ }
+
+ /** Reads four bytes from the currently selected pipe's bank in little endian format, for OUT
+ * direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW_AVR8
+ *
+ * \return Next four bytes in the currently selected pipe's FIFO buffer.
+ */
+ static inline uint32_t Pipe_Read_32_LE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint32_t Pipe_Read_32_LE(void)
+ {
+ union
+ {
+ uint32_t Value;
+ uint8_t Bytes[4];
+ } Data;
+
+ Data.Bytes[0] = UPDATX;
+ Data.Bytes[1] = UPDATX;
+ Data.Bytes[2] = UPDATX;
+ Data.Bytes[3] = UPDATX;
+
+ return Data.Value;
+ }
+
+ /** Reads four bytes from the currently selected pipe's bank in big endian format, for OUT
+ * direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW_AVR8
+ *
+ * \return Next four bytes in the currently selected pipe's FIFO buffer.
+ */
+ static inline uint32_t Pipe_Read_32_BE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint32_t Pipe_Read_32_BE(void)
+ {
+ union
+ {
+ uint32_t DWord;
+ uint8_t Bytes[4];
+ } Data;
+
+ Data.Bytes[3] = UPDATX;
+ Data.Bytes[2] = UPDATX;
+ Data.Bytes[1] = UPDATX;
+ Data.Bytes[0] = UPDATX;
+
+ return Data.DWord;
+ }
+
+ /** Writes four bytes to the currently selected pipe's bank in little endian format, for IN
+ * direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW_AVR8
+ *
+ * \param[in] Data Data to write to the currently selected pipe's FIFO buffer.
+ */
+ static inline void Pipe_Write_32_LE(const uint32_t Data) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_Write_32_LE(const uint32_t Data)
+ {
+ UPDATX = (Data & 0xFF);
+ UPDATX = (Data >> 8);
+ UPDATX = (Data >> 16);
+ UPDATX = (Data >> 24);
+ }
+
+ /** Writes four bytes to the currently selected pipe's bank in big endian format, for IN
+ * direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW_AVR8
+ *
+ * \param[in] Data Data to write to the currently selected pipe's FIFO buffer.
+ */
+ static inline void Pipe_Write_32_BE(const uint32_t Data) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_Write_32_BE(const uint32_t Data)
+ {
+ UPDATX = (Data >> 24);
+ UPDATX = (Data >> 16);
+ UPDATX = (Data >> 8);
+ UPDATX = (Data & 0xFF);
+ }
+
+ /** Discards four bytes from the currently selected pipe's bank, for OUT direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW_AVR8
+ */
+ static inline void Pipe_Discard_32(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_Discard_32(void)
+ {
+ uint8_t Dummy;
+
+ Dummy = UPDATX;
+ Dummy = UPDATX;
+ Dummy = UPDATX;
+ Dummy = UPDATX;
+
+ (void)Dummy;
+ }
+
+ /* External Variables: */
+ /** Global indicating the maximum packet size of the default control pipe located at address
+ * 0 in the device. This value is set to the value indicated in the attached device's device
+ * descriptor once the USB interface is initialized into host mode and a device is attached
+ * to the USB bus.
+ *
+ * \attention This variable should be treated as read-only in the user application, and never manually
+ * changed in value.
+ */
+ extern uint8_t USB_Host_ControlPipeSize;
+
+ /* Function Prototypes: */
+ /** Configures a table of pipe descriptions, in sequence. This function can be used to configure multiple
+ * pipes at the same time.
+ *
+ * \note Pipe with a zero address will be ignored, thus this function cannot be used to configure the
+ * control pipe.
+ *
+ * \param[in] Table Pointer to a table of pipe descriptions.
+ * \param[in] Entries Number of entries in the pipe table to configure.
+ *
+ * \return Boolean \c true if all pipes configured successfully, \c false otherwise.
+ */
+ bool Pipe_ConfigurePipeTable(const USB_Pipe_Table_t* const Table,
+ const uint8_t Entries);
+
+ /** Configures the specified pipe address with the given pipe type, endpoint address within the attached device,
+ * bank size and number of hardware banks.
+ *
+ * A newly configured pipe is frozen by default, and must be unfrozen before use via the \ref Pipe_Unfreeze()
+ * before being used. Pipes should be kept frozen unless waiting for data from a device while in IN mode, or
+ * sending data to the device in OUT mode. IN type pipes are also automatically configured to accept infinite
+ * numbers of IN requests without automatic freezing - this can be overridden by a call to
+ * \ref Pipe_SetFiniteINRequests().
+ *
+ * \param[in] Address Pipe address to configure.
+ *
+ * \param[in] Type Type of pipe to configure, an \c EP_TYPE_* mask. Not all pipe types are available on Low
+ * Speed USB devices - refer to the USB 2.0 specification.
+ *
+ * \param[in] EndpointAddress Endpoint address within the attached device that the pipe should interface to.
+ *
+ * \param[in] Size Size of the pipe's bank, where packets are stored before they are transmitted to
+ * the USB device, or after they have been received from the USB device (depending on
+ * the pipe's data direction). The bank size must indicate the maximum packet size that
+ * the pipe can handle.
+ *
+ * \param[in] Banks Number of banks to use for the pipe being configured.
+ *
+ * \attention When the \c ORDERED_EP_CONFIG compile time option is used, Pipes <b>must</b> be configured in ascending order,
+ * or bank corruption will occur.
+ *
+ * \note Certain microcontroller model's pipes may have different maximum packet sizes based on the pipe's
+ * index - refer to the chosen microcontroller's datasheet to determine the maximum bank size for each pipe.
+ * \n\n
+ *
+ * \note The default control pipe should not be manually configured by the user application, as it is
+ * automatically configured by the library internally.
+ * \n\n
+ *
+ * \note This routine will automatically select the specified pipe upon success. Upon failure, the pipe which
+ * failed to reconfigure correctly will be selected.
+ *
+ * \return Boolean \c true if the configuration succeeded, \c false otherwise.
+ */
+ bool Pipe_ConfigurePipe(const uint8_t Address,
+ const uint8_t Type,
+ const uint8_t EndpointAddress,
+ const uint16_t Size,
+ const uint8_t Banks);
+
+ /** Spin-loops until the currently selected non-control pipe is ready for the next packet of data to be read
+ * or written to it, aborting in the case of an error condition (such as a timeout or device disconnect).
+ *
+ * \ingroup Group_PipeRW_AVR8
+ *
+ * \return A value from the \ref Pipe_WaitUntilReady_ErrorCodes_t enum.
+ */
+ uint8_t Pipe_WaitUntilReady(void);
+
+ /** Determines if a pipe has been bound to the given device endpoint address. If a pipe which is bound to the given
+ * endpoint is found, it is automatically selected.
+ *
+ * \param[in] EndpointAddress Address and direction mask of the endpoint within the attached device to check.
+ *
+ * \return Boolean \c true if a pipe bound to the given endpoint address of the specified direction is found,
+ * \c false otherwise.
+ */
+ bool Pipe_IsEndpointBound(const uint8_t EndpointAddress) ATTR_WARN_UNUSED_RESULT;
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #if !defined(ENDPOINT_CONTROLEP)
+ #define ENDPOINT_CONTROLEP 0
+ #endif
+
+ /* Inline Functions: */
+ static inline uint8_t Pipe_BytesToEPSizeMask(const uint16_t Bytes) ATTR_WARN_UNUSED_RESULT ATTR_CONST ATTR_ALWAYS_INLINE;
+ static inline uint8_t Pipe_BytesToEPSizeMask(const uint16_t Bytes)
+ {
+ uint8_t MaskVal = 0;
+ uint16_t CheckBytes = 8;
+
+ while ((CheckBytes < Bytes) && (CheckBytes < PIPE_MAX_SIZE))
+ {
+ MaskVal++;
+ CheckBytes <<= 1;
+ }
+
+ return (MaskVal << EPSIZE0);
+ }
+
+ /* Function Prototypes: */
+ void Pipe_ClearPipes(void);
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_Control_R.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_Control_R.c
new file mode 100644
index 000000000..59c620ae5
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_Control_R.c
@@ -0,0 +1,84 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#if defined(TEMPLATE_FUNC_NAME)
+
+uint8_t TEMPLATE_FUNC_NAME (void* const Buffer,
+ uint16_t Length)
+{
+ uint8_t* DataStream = ((uint8_t*)Buffer + TEMPLATE_BUFFER_OFFSET(Length));
+
+ if (!(Length))
+ Endpoint_ClearOUT();
+
+ while (Length)
+ {
+ uint8_t USB_DeviceState_LCL = USB_DeviceState;
+
+ if (USB_DeviceState_LCL == DEVICE_STATE_Unattached)
+ return ENDPOINT_RWCSTREAM_DeviceDisconnected;
+ else if (USB_DeviceState_LCL == DEVICE_STATE_Suspended)
+ return ENDPOINT_RWCSTREAM_BusSuspended;
+ else if (Endpoint_IsSETUPReceived())
+ return ENDPOINT_RWCSTREAM_HostAborted;
+
+ if (Endpoint_IsOUTReceived())
+ {
+ while (Length && Endpoint_BytesInEndpoint())
+ {
+ TEMPLATE_TRANSFER_BYTE(DataStream);
+ TEMPLATE_BUFFER_MOVE(DataStream, 1);
+ Length--;
+ }
+
+ Endpoint_ClearOUT();
+ }
+ }
+
+ while (!(Endpoint_IsINReady()))
+ {
+ uint8_t USB_DeviceState_LCL = USB_DeviceState;
+
+ if (USB_DeviceState_LCL == DEVICE_STATE_Unattached)
+ return ENDPOINT_RWCSTREAM_DeviceDisconnected;
+ else if (USB_DeviceState_LCL == DEVICE_STATE_Suspended)
+ return ENDPOINT_RWCSTREAM_BusSuspended;
+ }
+
+ return ENDPOINT_RWCSTREAM_NoError;
+}
+
+#undef TEMPLATE_BUFFER_OFFSET
+#undef TEMPLATE_BUFFER_MOVE
+#undef TEMPLATE_FUNC_NAME
+#undef TEMPLATE_TRANSFER_BYTE
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_Control_W.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_Control_W.c
new file mode 100644
index 000000000..98887009c
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_Control_W.c
@@ -0,0 +1,95 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#if defined(TEMPLATE_FUNC_NAME)
+
+uint8_t TEMPLATE_FUNC_NAME (const void* const Buffer,
+ uint16_t Length)
+{
+ uint8_t* DataStream = ((uint8_t*)Buffer + TEMPLATE_BUFFER_OFFSET(Length));
+ bool LastPacketFull = false;
+
+ if (Length > USB_ControlRequest.wLength)
+ Length = USB_ControlRequest.wLength;
+ else if (!(Length))
+ Endpoint_ClearIN();
+
+ while (Length || LastPacketFull)
+ {
+ uint8_t USB_DeviceState_LCL = USB_DeviceState;
+
+ if (USB_DeviceState_LCL == DEVICE_STATE_Unattached)
+ return ENDPOINT_RWCSTREAM_DeviceDisconnected;
+ else if (USB_DeviceState_LCL == DEVICE_STATE_Suspended)
+ return ENDPOINT_RWCSTREAM_BusSuspended;
+ else if (Endpoint_IsSETUPReceived())
+ return ENDPOINT_RWCSTREAM_HostAborted;
+ else if (Endpoint_IsOUTReceived())
+ break;
+
+ if (Endpoint_IsINReady())
+ {
+ uint16_t BytesInEndpoint = Endpoint_BytesInEndpoint();
+
+ while (Length && (BytesInEndpoint < USB_Device_ControlEndpointSize))
+ {
+ TEMPLATE_TRANSFER_BYTE(DataStream);
+ TEMPLATE_BUFFER_MOVE(DataStream, 1);
+ Length--;
+ BytesInEndpoint++;
+ }
+
+ LastPacketFull = (BytesInEndpoint == USB_Device_ControlEndpointSize);
+ Endpoint_ClearIN();
+ }
+ }
+
+ while (!(Endpoint_IsOUTReceived()))
+ {
+ uint8_t USB_DeviceState_LCL = USB_DeviceState;
+
+ if (USB_DeviceState_LCL == DEVICE_STATE_Unattached)
+ return ENDPOINT_RWCSTREAM_DeviceDisconnected;
+ else if (USB_DeviceState_LCL == DEVICE_STATE_Suspended)
+ return ENDPOINT_RWCSTREAM_BusSuspended;
+ else if (Endpoint_IsSETUPReceived())
+ return ENDPOINT_RWCSTREAM_HostAborted;
+ }
+
+ return ENDPOINT_RWCSTREAM_NoError;
+}
+
+#undef TEMPLATE_BUFFER_OFFSET
+#undef TEMPLATE_BUFFER_MOVE
+#undef TEMPLATE_FUNC_NAME
+#undef TEMPLATE_TRANSFER_BYTE
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_RW.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_RW.c
new file mode 100644
index 000000000..d51afdfb1
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_RW.c
@@ -0,0 +1,89 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#if defined(TEMPLATE_FUNC_NAME)
+
+uint8_t TEMPLATE_FUNC_NAME (TEMPLATE_BUFFER_TYPE const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed)
+{
+ uint8_t* DataStream = ((uint8_t*)Buffer + TEMPLATE_BUFFER_OFFSET(Length));
+ uint16_t BytesInTransfer = 0;
+ uint8_t ErrorCode;
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()))
+ return ErrorCode;
+
+ if (BytesProcessed != NULL)
+ {
+ Length -= *BytesProcessed;
+ TEMPLATE_BUFFER_MOVE(DataStream, *BytesProcessed);
+ }
+
+ while (Length)
+ {
+ if (!(Endpoint_IsReadWriteAllowed()))
+ {
+ TEMPLATE_CLEAR_ENDPOINT();
+
+ #if !defined(INTERRUPT_CONTROL_ENDPOINT)
+ USB_USBTask();
+ #endif
+
+ if (BytesProcessed != NULL)
+ {
+ *BytesProcessed += BytesInTransfer;
+ return ENDPOINT_RWSTREAM_IncompleteTransfer;
+ }
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()))
+ return ErrorCode;
+ }
+ else
+ {
+ TEMPLATE_TRANSFER_BYTE(DataStream);
+ TEMPLATE_BUFFER_MOVE(DataStream, 1);
+ Length--;
+ BytesInTransfer++;
+ }
+ }
+
+ return ENDPOINT_RWSTREAM_NoError;
+}
+
+#undef TEMPLATE_FUNC_NAME
+#undef TEMPLATE_BUFFER_TYPE
+#undef TEMPLATE_TRANSFER_BYTE
+#undef TEMPLATE_CLEAR_ENDPOINT
+#undef TEMPLATE_BUFFER_OFFSET
+#undef TEMPLATE_BUFFER_MOVE
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Template/Template_Pipe_RW.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Template/Template_Pipe_RW.c
new file mode 100644
index 000000000..2685c9b9d
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Template/Template_Pipe_RW.c
@@ -0,0 +1,88 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#if defined(TEMPLATE_FUNC_NAME)
+
+uint8_t TEMPLATE_FUNC_NAME (TEMPLATE_BUFFER_TYPE const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed)
+{
+ uint8_t* DataStream = ((uint8_t*)Buffer + TEMPLATE_BUFFER_OFFSET(Length));
+ uint16_t BytesInTransfer = 0;
+ uint8_t ErrorCode;
+
+ Pipe_SetPipeToken(TEMPLATE_TOKEN);
+
+ if ((ErrorCode = Pipe_WaitUntilReady()))
+ return ErrorCode;
+
+ if (BytesProcessed != NULL)
+ {
+ Length -= *BytesProcessed;
+ TEMPLATE_BUFFER_MOVE(DataStream, *BytesProcessed);
+ }
+
+ while (Length)
+ {
+ if (!(Pipe_IsReadWriteAllowed()))
+ {
+ TEMPLATE_CLEAR_PIPE();
+
+ if (BytesProcessed != NULL)
+ {
+ *BytesProcessed += BytesInTransfer;
+ return PIPE_RWSTREAM_IncompleteTransfer;
+ }
+
+ if ((ErrorCode = Pipe_WaitUntilReady()))
+ return ErrorCode;
+ }
+ else
+ {
+ TEMPLATE_TRANSFER_BYTE(DataStream);
+ TEMPLATE_BUFFER_MOVE(DataStream, 1);
+ Length--;
+ BytesInTransfer++;
+ }
+ }
+
+ return PIPE_RWSTREAM_NoError;
+}
+
+#undef TEMPLATE_FUNC_NAME
+#undef TEMPLATE_BUFFER_TYPE
+#undef TEMPLATE_TOKEN
+#undef TEMPLATE_TRANSFER_BYTE
+#undef TEMPLATE_CLEAR_PIPE
+#undef TEMPLATE_BUFFER_OFFSET
+#undef TEMPLATE_BUFFER_MOVE
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/USBController_AVR8.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/USBController_AVR8.c
new file mode 100644
index 000000000..71c5f916d
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/USBController_AVR8.c
@@ -0,0 +1,273 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "../../../../Common/Common.h"
+#if (ARCH == ARCH_AVR8)
+
+#define __INCLUDE_FROM_USB_DRIVER
+#define __INCLUDE_FROM_USB_CONTROLLER_C
+#include "../USBController.h"
+
+#if defined(USB_CAN_BE_BOTH)
+volatile uint8_t USB_CurrentMode = USB_MODE_None;
+#endif
+
+#if !defined(USE_STATIC_OPTIONS)
+volatile uint8_t USB_Options;
+#endif
+
+void USB_Init(
+ #if defined(USB_CAN_BE_BOTH)
+ const uint8_t Mode
+ #endif
+
+ #if (defined(USB_CAN_BE_BOTH) && !defined(USE_STATIC_OPTIONS))
+ ,
+ #elif (!defined(USB_CAN_BE_BOTH) && defined(USE_STATIC_OPTIONS))
+ void
+ #endif
+
+ #if !defined(USE_STATIC_OPTIONS)
+ const uint8_t Options
+ #endif
+ )
+{
+ #if !defined(USE_STATIC_OPTIONS)
+ USB_Options = Options;
+ #endif
+
+ #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
+ /* Workaround for AVR8 bootloaders that fail to turn off the OTG pad before running
+ * the loaded application. This causes VBUS detection to fail unless we first force
+ * it off to reset it. */
+ USB_OTGPAD_Off();
+ #endif
+
+ if (!(USB_Options & USB_OPT_REG_DISABLED))
+ USB_REG_On();
+ else
+ USB_REG_Off();
+
+ if (!(USB_Options & USB_OPT_MANUAL_PLL))
+ {
+ #if defined(USB_SERIES_4_AVR)
+ PLLFRQ = (1 << PDIV2);
+ #endif
+ }
+
+ #if defined(USB_CAN_BE_BOTH)
+ if (Mode == USB_MODE_UID)
+ {
+ UHWCON |= (1 << UIDE);
+ USB_INT_Enable(USB_INT_IDTI);
+ USB_CurrentMode = USB_GetUSBModeFromUID();
+ }
+ else
+ {
+ UHWCON &= ~(1 << UIDE);
+ USB_CurrentMode = Mode;
+ }
+ #endif
+
+ USB_IsInitialized = true;
+
+ USB_ResetInterface();
+}
+
+void USB_Disable(void)
+{
+ USB_INT_DisableAllInterrupts();
+ USB_INT_ClearAllInterrupts();
+
+ USB_Detach();
+ USB_Controller_Disable();
+
+ if (!(USB_Options & USB_OPT_MANUAL_PLL))
+ USB_PLL_Off();
+
+ if (!(USB_Options & USB_OPT_REG_KEEP_ENABLED))
+ USB_REG_Off();
+
+ #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
+ USB_OTGPAD_Off();
+ #endif
+
+ #if defined(USB_CAN_BE_BOTH)
+ USB_CurrentMode = USB_MODE_None;
+ #endif
+
+ USB_IsInitialized = false;
+}
+
+void USB_ResetInterface(void)
+{
+ #if defined(USB_CAN_BE_BOTH)
+ bool UIDModeSelectEnabled = ((UHWCON & (1 << UIDE)) != 0);
+ #endif
+
+ USB_INT_DisableAllInterrupts();
+ USB_INT_ClearAllInterrupts();
+
+ USB_Controller_Reset();
+
+ #if defined(USB_CAN_BE_BOTH)
+ if (UIDModeSelectEnabled)
+ USB_INT_Enable(USB_INT_IDTI);
+ #endif
+
+ USB_CLK_Unfreeze();
+
+ if (USB_CurrentMode == USB_MODE_Device)
+ {
+ #if defined(USB_CAN_BE_DEVICE)
+ #if (defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR))
+ UHWCON |= (1 << UIMOD);
+ #endif
+
+ if (!(USB_Options & USB_OPT_MANUAL_PLL))
+ {
+ #if defined(USB_SERIES_2_AVR)
+ USB_PLL_On();
+ while (!(USB_PLL_IsReady()));
+ #else
+ USB_PLL_Off();
+ #endif
+ }
+
+ USB_Init_Device();
+ #endif
+ }
+ else if (USB_CurrentMode == USB_MODE_Host)
+ {
+ #if defined(USB_CAN_BE_HOST)
+ UHWCON &= ~(1 << UIMOD);
+
+ if (!(USB_Options & USB_OPT_MANUAL_PLL))
+ {
+ #if defined(USB_CAN_BE_HOST)
+ USB_PLL_On();
+ while (!(USB_PLL_IsReady()));
+ #endif
+ }
+
+ USB_Init_Host();
+ #endif
+ }
+
+ #if (defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR))
+ USB_OTGPAD_On();
+ #endif
+}
+
+#if defined(USB_CAN_BE_DEVICE)
+static void USB_Init_Device(void)
+{
+ USB_DeviceState = DEVICE_STATE_Unattached;
+ USB_Device_ConfigurationNumber = 0;
+
+ #if !defined(NO_DEVICE_REMOTE_WAKEUP)
+ USB_Device_RemoteWakeupEnabled = false;
+ #endif
+
+ #if !defined(NO_DEVICE_SELF_POWER)
+ USB_Device_CurrentlySelfPowered = false;
+ #endif
+
+ #if !defined(FIXED_CONTROL_ENDPOINT_SIZE)
+ USB_Descriptor_Device_t* DeviceDescriptorPtr;
+
+ #if defined(ARCH_HAS_MULTI_ADDRESS_SPACE) && \
+ !(defined(USE_FLASH_DESCRIPTORS) || defined(USE_EEPROM_DESCRIPTORS) || defined(USE_RAM_DESCRIPTORS))
+ uint8_t DescriptorAddressSpace;
+
+ if (CALLBACK_USB_GetDescriptor((DTYPE_Device << 8), 0, (void*)&DeviceDescriptorPtr, &DescriptorAddressSpace) != NO_DESCRIPTOR)
+ {
+ if (DescriptorAddressSpace == MEMSPACE_FLASH)
+ USB_Device_ControlEndpointSize = pgm_read_byte(&DeviceDescriptorPtr->Endpoint0Size);
+ else if (DescriptorAddressSpace == MEMSPACE_EEPROM)
+ USB_Device_ControlEndpointSize = eeprom_read_byte(&DeviceDescriptorPtr->Endpoint0Size);
+ else
+ USB_Device_ControlEndpointSize = DeviceDescriptorPtr->Endpoint0Size;
+ }
+ #else
+ if (CALLBACK_USB_GetDescriptor((DTYPE_Device << 8), 0, (void*)&DeviceDescriptorPtr) != NO_DESCRIPTOR)
+ {
+ #if defined(USE_RAM_DESCRIPTORS)
+ USB_Device_ControlEndpointSize = DeviceDescriptorPtr->Endpoint0Size;
+ #elif defined(USE_EEPROM_DESCRIPTORS)
+ USB_Device_ControlEndpointSize = eeprom_read_byte(&DeviceDescriptorPtr->Endpoint0Size);
+ #else
+ USB_Device_ControlEndpointSize = pgm_read_byte(&DeviceDescriptorPtr->Endpoint0Size);
+ #endif
+ }
+ #endif
+ #endif
+
+ #if (defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR))
+ if (USB_Options & USB_DEVICE_OPT_LOWSPEED)
+ USB_Device_SetLowSpeed();
+ else
+ USB_Device_SetFullSpeed();
+
+ USB_INT_Enable(USB_INT_VBUSTI);
+ #endif
+
+ Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL,
+ USB_Device_ControlEndpointSize, 1);
+
+ USB_INT_Clear(USB_INT_SUSPI);
+ USB_INT_Enable(USB_INT_SUSPI);
+ USB_INT_Enable(USB_INT_EORSTI);
+
+ USB_Attach();
+}
+#endif
+
+#if defined(USB_CAN_BE_HOST)
+static void USB_Init_Host(void)
+{
+ USB_HostState = HOST_STATE_Unattached;
+ USB_Host_ConfigurationNumber = 0;
+ USB_Host_ControlPipeSize = PIPE_CONTROLPIPE_DEFAULT_SIZE;
+
+ USB_Host_HostMode_On();
+
+ USB_Host_VBUS_Auto_Off();
+ USB_Host_VBUS_Manual_Enable();
+ USB_Host_VBUS_Manual_On();
+
+ USB_INT_Enable(USB_INT_SRPI);
+ USB_INT_Enable(USB_INT_BCERRI);
+
+ USB_Attach();
+}
+#endif
+
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/USBController_AVR8.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/USBController_AVR8.h
new file mode 100644
index 000000000..de34f42a1
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/USBController_AVR8.h
@@ -0,0 +1,432 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief USB Controller definitions for the AVR8 microcontrollers.
+ * \copydetails Group_USBManagement_AVR8
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_USBManagement
+ * \defgroup Group_USBManagement_AVR8 USB Interface Management (AVR8)
+ * \brief USB Controller definitions for the AVR8 microcontrollers.
+ *
+ * Functions, macros, variables, enums and types related to the setup and management of the USB interface.
+ *
+ * @{
+ */
+
+#ifndef __USBCONTROLLER_AVR8_H__
+#define __USBCONTROLLER_AVR8_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../USBMode.h"
+ #include "../Events.h"
+ #include "../USBTask.h"
+ #include "../USBInterrupt.h"
+
+ #if defined(USB_CAN_BE_HOST) || defined(__DOXYGEN__)
+ #include "../Host.h"
+ #include "../OTG.h"
+ #include "../Pipe.h"
+ #include "../HostStandardReq.h"
+ #include "../PipeStream.h"
+ #endif
+
+ #if defined(USB_CAN_BE_DEVICE) || defined(__DOXYGEN__)
+ #include "../Device.h"
+ #include "../Endpoint.h"
+ #include "../DeviceStandardReq.h"
+ #include "../EndpointStream.h"
+ #endif
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks and Defines: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ #if !defined(F_USB)
+ #error F_USB is not defined. You must define F_USB to the frequency of the unprescaled USB controller clock in your project makefile.
+ #endif
+
+ #if (F_USB == 8000000)
+ #if (defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || \
+ defined(__AVR_ATmega8U2__) || defined(__AVR_ATmega16U2__) || \
+ defined(__AVR_ATmega32U2__))
+ #define USB_PLL_PSC 0
+ #elif (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
+ #define USB_PLL_PSC 0
+ #elif (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__))
+ #define USB_PLL_PSC ((1 << PLLP1) | (1 << PLLP0))
+ #elif (defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1287__))
+ #define USB_PLL_PSC ((1 << PLLP1) | (1 << PLLP0))
+ #endif
+ #elif (F_USB == 16000000)
+ #if (defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || \
+ defined(__AVR_ATmega8U2__) || defined(__AVR_ATmega16U2__) || \
+ defined(__AVR_ATmega32U2__))
+ #define USB_PLL_PSC (1 << PLLP0)
+ #elif (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
+ #define USB_PLL_PSC (1 << PINDIV)
+ #elif (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__))
+ #define USB_PLL_PSC ((1 << PLLP2) | (1 << PLLP1))
+ #elif (defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__))
+ #define USB_PLL_PSC ((1 << PLLP2) | (1 << PLLP0))
+ #endif
+ #endif
+
+ #if !defined(USB_PLL_PSC)
+ #error No PLL prescale value available for chosen F_USB value and AVR model.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** \name USB Controller Option Masks */
+ //@{
+ /** Regulator disable option mask for \ref USB_Init(). This indicates that the internal 3.3V USB data pad
+ * regulator should be disabled and the AVR's VCC level used for the data pads.
+ *
+ * \note See USB AVR data sheet for more information on the internal pad regulator.
+ */
+ #define USB_OPT_REG_DISABLED (1 << 1)
+
+ /** Regulator enable option mask for \ref USB_Init(). This indicates that the internal 3.3V USB data pad
+ * regulator should be enabled to regulate the data pin voltages from the VBUS level down to a level within
+ * the range allowable by the USB standard.
+ *
+ * \note See USB AVR data sheet for more information on the internal pad regulator.
+ */
+ #define USB_OPT_REG_ENABLED (0 << 1)
+
+ /** Option mask for \ref USB_Init() to keep regulator enabled at all times. Indicates that \ref USB_Disable()
+ * should not disable the regulator as it would otherwise. Has no effect if regulator is disabled using
+ * \ref USB_OPT_REG_DISABLED.
+ *
+ * \note See USB AVR data sheet for more information on the internal pad regulator.
+ */
+ #define USB_OPT_REG_KEEP_ENABLED (1 << 3)
+
+ /** Manual PLL control option mask for \ref USB_Init(). This indicates to the library that the user application
+ * will take full responsibility for controlling the AVR's PLL (used to generate the high frequency clock
+ * that the USB controller requires) and ensuring that it is locked at the correct frequency for USB operations.
+ */
+ #define USB_OPT_MANUAL_PLL (1 << 2)
+
+ /** Automatic PLL control option mask for \ref USB_Init(). This indicates to the library that the library should
+ * take full responsibility for controlling the AVR's PLL (used to generate the high frequency clock
+ * that the USB controller requires) and ensuring that it is locked at the correct frequency for USB operations.
+ */
+ #define USB_OPT_AUTO_PLL (0 << 2)
+ //@}
+
+ #if !defined(USB_STREAM_TIMEOUT_MS) || defined(__DOXYGEN__)
+ /** Constant for the maximum software timeout period of the USB data stream transfer functions
+ * (both control and standard) when in either device or host mode. If the next packet of a stream
+ * is not received or acknowledged within this time period, the stream function will fail.
+ *
+ * This value may be overridden in the user project makefile as the value of the
+ * \ref USB_STREAM_TIMEOUT_MS token, and passed to the compiler using the -D switch.
+ */
+ #define USB_STREAM_TIMEOUT_MS 100
+ #endif
+
+ /* Inline Functions: */
+ #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) || defined(__DOXYGEN__)
+ /** Determines if the VBUS line is currently high (i.e. the USB host is supplying power).
+ *
+ * \note This function is not available on some AVR models which do not support hardware VBUS monitoring.
+ *
+ * \return Boolean \c true if the VBUS line is currently detecting power from a host, \c false otherwise.
+ */
+ static inline bool USB_VBUS_GetStatus(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool USB_VBUS_GetStatus(void)
+ {
+ return ((USBSTA & (1 << VBUS)) ? true : false);
+ }
+ #endif
+
+ /** Detaches the device from the USB bus. This has the effect of removing the device from any
+ * attached host, ceasing USB communications. If no host is present, this prevents any host from
+ * enumerating the device once attached until \ref USB_Attach() is called.
+ */
+ static inline void USB_Detach(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Detach(void)
+ {
+ UDCON |= (1 << DETACH);
+ }
+
+ /** Attaches the device to the USB bus. This announces the device's presence to any attached
+ * USB host, starting the enumeration process. If no host is present, attaching the device
+ * will allow for enumeration once a host is connected to the device.
+ *
+ * This is inexplicably also required for proper operation while in host mode, to enable the
+ * attachment of a device to the host. This is despite the bit being located in the device-mode
+ * register and despite the datasheet making no mention of its requirement in host mode.
+ */
+ static inline void USB_Attach(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Attach(void)
+ {
+ UDCON &= ~(1 << DETACH);
+ }
+
+ /* Function Prototypes: */
+ /** Main function to initialize and start the USB interface. Once active, the USB interface will
+ * allow for device connection to a host when in device mode, or for device enumeration while in
+ * host mode.
+ *
+ * As the USB library relies on interrupts for the device and host mode enumeration processes,
+ * the user must enable global interrupts before or shortly after this function is called. In
+ * device mode, interrupts must be enabled within 500ms of this function being called to ensure
+ * that the host does not time out whilst enumerating the device. In host mode, interrupts may be
+ * enabled at the application's leisure however enumeration will not begin of an attached device
+ * until after this has occurred.
+ *
+ * Calling this function when the USB interface is already initialized will cause a complete USB
+ * interface reset and re-enumeration.
+ *
+ * \param[in] Mode Mask indicating what mode the USB interface is to be initialized to, a value
+ * from the \ref USB_Modes_t enum.
+ * \note This parameter does not exist on devices with only one supported USB
+ * mode (device or host).
+ *
+ * \param[in] Options Mask indicating the options which should be used when initializing the USB
+ * interface to control the USB interface's behavior. This should be comprised of
+ * a \c USB_OPT_REG_* mask to control the regulator, a \c USB_OPT_*_PLL mask to control the
+ * PLL, and a \c USB_DEVICE_OPT_* mask (when the device mode is enabled) to set the device
+ * mode speed.
+ *
+ * \note To reduce the FLASH requirements of the library if only device or host mode is required,
+ * the mode can be statically set in the project makefile by defining the token \c USB_DEVICE_ONLY
+ * (for device mode) or \c USB_HOST_ONLY (for host mode), passing the token to the compiler
+ * via the -D switch. If the mode is statically set, this parameter does not exist in the
+ * function prototype.
+ * \n\n
+ *
+ * \note To reduce the FLASH requirements of the library if only fixed settings are required,
+ * the options may be set statically in the same manner as the mode (see the Mode parameter of
+ * this function). To statically set the USB options, pass in the \c USE_STATIC_OPTIONS token,
+ * defined to the appropriate options masks. When the options are statically set, this
+ * parameter does not exist in the function prototype.
+ * \n\n
+ *
+ * \note The mode parameter does not exist on devices where only one mode is possible, such as USB
+ * AVR models which only implement the USB device mode in hardware.
+ *
+ * \see \ref Group_Device for the \c USB_DEVICE_OPT_* masks.
+ */
+ void USB_Init(
+ #if defined(USB_CAN_BE_BOTH) || defined(__DOXYGEN__)
+ const uint8_t Mode
+ #endif
+
+ #if (defined(USB_CAN_BE_BOTH) && !defined(USE_STATIC_OPTIONS)) || defined(__DOXYGEN__)
+ ,
+ #elif (!defined(USB_CAN_BE_BOTH) && defined(USE_STATIC_OPTIONS))
+ void
+ #endif
+
+ #if !defined(USE_STATIC_OPTIONS) || defined(__DOXYGEN__)
+ const uint8_t Options
+ #endif
+ );
+
+ /** Shuts down the USB interface. This turns off the USB interface after deallocating all USB FIFO
+ * memory, endpoints and pipes. When turned off, no USB functionality can be used until the interface
+ * is restarted with the \ref USB_Init() function.
+ */
+ void USB_Disable(void);
+
+ /** Resets the interface, when already initialized. This will re-enumerate the device if already connected
+ * to a host, or re-enumerate an already attached device when in host mode.
+ */
+ void USB_ResetInterface(void);
+
+ /* Global Variables: */
+ #if defined(USB_CAN_BE_BOTH) || defined(__DOXYGEN__)
+ /** Indicates the mode that the USB interface is currently initialized to, a value from the
+ * \ref USB_Modes_t enum.
+ *
+ * \attention This variable should be treated as read-only in the user application, and never manually
+ * changed in value.
+ *
+ * \note When the controller is initialized into UID auto-detection mode, this variable will hold the
+ * currently selected USB mode (i.e. \ref USB_MODE_Device or \ref USB_MODE_Host). If the controller
+ * is fixed into a specific mode (either through the \c USB_DEVICE_ONLY or \c USB_HOST_ONLY compile time
+ * options, or a limitation of the USB controller in the chosen device model) this will evaluate to
+ * a constant of the appropriate value and will never evaluate to \ref USB_MODE_None even when the
+ * USB interface is not initialized.
+ */
+ extern volatile uint8_t USB_CurrentMode;
+ #elif defined(USB_CAN_BE_HOST)
+ #define USB_CurrentMode USB_MODE_Host
+ #elif defined(USB_CAN_BE_DEVICE)
+ #define USB_CurrentMode USB_MODE_Device
+ #endif
+
+ #if !defined(USE_STATIC_OPTIONS) || defined(__DOXYGEN__)
+ /** Indicates the current USB options that the USB interface was initialized with when \ref USB_Init()
+ * was called. This value will be one of the \c USB_MODE_* masks defined elsewhere in this module.
+ *
+ * \attention This variable should be treated as read-only in the user application, and never manually
+ * changed in value.
+ */
+ extern volatile uint8_t USB_Options;
+ #elif defined(USE_STATIC_OPTIONS)
+ #define USB_Options USE_STATIC_OPTIONS
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Function Prototypes: */
+ #if defined(__INCLUDE_FROM_USB_CONTROLLER_C)
+ #if defined(USB_CAN_BE_DEVICE)
+ static void USB_Init_Device(void);
+ #endif
+
+ #if defined(USB_CAN_BE_HOST)
+ static void USB_Init_Host(void);
+ #endif
+ #endif
+
+ /* Inline Functions: */
+ static inline void USB_PLL_On(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_PLL_On(void)
+ {
+ PLLCSR = USB_PLL_PSC;
+ PLLCSR = (USB_PLL_PSC | (1 << PLLE));
+ }
+
+ static inline void USB_PLL_Off(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_PLL_Off(void)
+ {
+ PLLCSR = 0;
+ }
+
+ static inline bool USB_PLL_IsReady(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool USB_PLL_IsReady(void)
+ {
+ return ((PLLCSR & (1 << PLOCK)) ? true : false);
+ }
+
+ static inline void USB_REG_On(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_REG_On(void)
+ {
+ #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
+ UHWCON |= (1 << UVREGE);
+ #else
+ REGCR &= ~(1 << REGDIS);
+ #endif
+ }
+
+ static inline void USB_REG_Off(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_REG_Off(void)
+ {
+ #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
+ UHWCON &= ~(1 << UVREGE);
+ #else
+ REGCR |= (1 << REGDIS);
+ #endif
+ }
+
+ #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
+ static inline void USB_OTGPAD_On(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_OTGPAD_On(void)
+ {
+ USBCON |= (1 << OTGPADE);
+ }
+
+ static inline void USB_OTGPAD_Off(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_OTGPAD_Off(void)
+ {
+ USBCON &= ~(1 << OTGPADE);
+ }
+ #endif
+
+ static inline void USB_CLK_Freeze(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_CLK_Freeze(void)
+ {
+ USBCON |= (1 << FRZCLK);
+ }
+
+ static inline void USB_CLK_Unfreeze(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_CLK_Unfreeze(void)
+ {
+ USBCON &= ~(1 << FRZCLK);
+ }
+
+ static inline void USB_Controller_Enable(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Controller_Enable(void)
+ {
+ USBCON |= (1 << USBE);
+ }
+
+ static inline void USB_Controller_Disable(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Controller_Disable(void)
+ {
+ USBCON &= ~(1 << USBE);
+ }
+
+ static inline void USB_Controller_Reset(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Controller_Reset(void)
+ {
+ USBCON &= ~(1 << USBE);
+ USBCON |= (1 << USBE);
+ }
+
+ #if defined(USB_CAN_BE_BOTH)
+ static inline uint8_t USB_GetUSBModeFromUID(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t USB_GetUSBModeFromUID(void)
+ {
+ if (USBSTA & (1 << ID))
+ return USB_MODE_Device;
+ else
+ return USB_MODE_Host;
+ }
+ #endif
+
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/USBInterrupt_AVR8.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/USBInterrupt_AVR8.c
new file mode 100644
index 000000000..7efaea65a
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/USBInterrupt_AVR8.c
@@ -0,0 +1,279 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "../../../../Common/Common.h"
+#if (ARCH == ARCH_AVR8)
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../USBInterrupt.h"
+
+void USB_INT_DisableAllInterrupts(void)
+{
+ #if defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
+ USBCON &= ~((1 << VBUSTE) | (1 << IDTE));
+ #elif defined(USB_SERIES_4_AVR)
+ USBCON &= ~(1 << VBUSTE);
+ #endif
+
+ #if defined(USB_CAN_BE_BOTH)
+ OTGIEN = 0;
+ #endif
+
+ #if defined(USB_CAN_BE_HOST)
+ UHIEN = 0;
+ #endif
+
+ #if defined(USB_CAN_BE_DEVICE)
+ UDIEN = 0;
+ #endif
+}
+
+void USB_INT_ClearAllInterrupts(void)
+{
+ #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
+ USBINT = 0;
+ #endif
+
+ #if defined(USB_CAN_BE_BOTH)
+ OTGINT = 0;
+ #endif
+
+ #if defined(USB_CAN_BE_HOST)
+ UHINT = 0;
+ #endif
+
+ #if defined(USB_CAN_BE_DEVICE)
+ UDINT = 0;
+ #endif
+}
+
+ISR(USB_GEN_vect, ISR_BLOCK)
+{
+ #if defined(USB_CAN_BE_DEVICE)
+ #if !defined(NO_SOF_EVENTS)
+ if (USB_INT_HasOccurred(USB_INT_SOFI) && USB_INT_IsEnabled(USB_INT_SOFI))
+ {
+ USB_INT_Clear(USB_INT_SOFI);
+
+ EVENT_USB_Device_StartOfFrame();
+ }
+ #endif
+
+ #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
+ if (USB_INT_HasOccurred(USB_INT_VBUSTI) && USB_INT_IsEnabled(USB_INT_VBUSTI))
+ {
+ USB_INT_Clear(USB_INT_VBUSTI);
+
+ if (USB_VBUS_GetStatus())
+ {
+ if (!(USB_Options & USB_OPT_MANUAL_PLL))
+ {
+ USB_PLL_On();
+ while (!(USB_PLL_IsReady()));
+ }
+
+ USB_DeviceState = DEVICE_STATE_Powered;
+ EVENT_USB_Device_Connect();
+ }
+ else
+ {
+ if (!(USB_Options & USB_OPT_MANUAL_PLL))
+ USB_PLL_Off();
+
+ USB_DeviceState = DEVICE_STATE_Unattached;
+ EVENT_USB_Device_Disconnect();
+ }
+ }
+ #endif
+
+ if (USB_INT_HasOccurred(USB_INT_SUSPI) && USB_INT_IsEnabled(USB_INT_SUSPI))
+ {
+ USB_INT_Disable(USB_INT_SUSPI);
+ USB_INT_Enable(USB_INT_WAKEUPI);
+
+ USB_CLK_Freeze();
+
+ if (!(USB_Options & USB_OPT_MANUAL_PLL))
+ USB_PLL_Off();
+
+ #if defined(USB_SERIES_2_AVR) && !defined(NO_LIMITED_CONTROLLER_CONNECT)
+ USB_DeviceState = DEVICE_STATE_Unattached;
+ EVENT_USB_Device_Disconnect();
+ #else
+ USB_DeviceState = DEVICE_STATE_Suspended;
+ EVENT_USB_Device_Suspend();
+ #endif
+ }
+
+ if (USB_INT_HasOccurred(USB_INT_WAKEUPI) && USB_INT_IsEnabled(USB_INT_WAKEUPI))
+ {
+ if (!(USB_Options & USB_OPT_MANUAL_PLL))
+ {
+ USB_PLL_On();
+ while (!(USB_PLL_IsReady()));
+ }
+
+ USB_CLK_Unfreeze();
+
+ USB_INT_Clear(USB_INT_WAKEUPI);
+
+ USB_INT_Disable(USB_INT_WAKEUPI);
+ USB_INT_Enable(USB_INT_SUSPI);
+
+ if (USB_Device_ConfigurationNumber)
+ USB_DeviceState = DEVICE_STATE_Configured;
+ else
+ USB_DeviceState = (USB_Device_IsAddressSet()) ? DEVICE_STATE_Addressed : DEVICE_STATE_Powered;
+
+ #if defined(USB_SERIES_2_AVR) && !defined(NO_LIMITED_CONTROLLER_CONNECT)
+ EVENT_USB_Device_Connect();
+ #else
+ EVENT_USB_Device_WakeUp();
+ #endif
+ }
+
+ if (USB_INT_HasOccurred(USB_INT_EORSTI) && USB_INT_IsEnabled(USB_INT_EORSTI))
+ {
+ USB_INT_Clear(USB_INT_EORSTI);
+
+ USB_DeviceState = DEVICE_STATE_Default;
+ USB_Device_ConfigurationNumber = 0;
+
+ USB_INT_Clear(USB_INT_SUSPI);
+ USB_INT_Disable(USB_INT_SUSPI);
+ USB_INT_Enable(USB_INT_WAKEUPI);
+
+ Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL,
+ USB_Device_ControlEndpointSize, 1);
+
+ #if defined(INTERRUPT_CONTROL_ENDPOINT)
+ USB_INT_Enable(USB_INT_RXSTPI);
+ #endif
+
+ EVENT_USB_Device_Reset();
+ }
+ #endif
+
+ #if defined(USB_CAN_BE_HOST)
+ #if !defined(NO_SOF_EVENTS)
+ if (USB_INT_HasOccurred(USB_INT_HSOFI) && USB_INT_IsEnabled(USB_INT_HSOFI))
+ {
+ USB_INT_Clear(USB_INT_HSOFI);
+
+ EVENT_USB_Host_StartOfFrame();
+ }
+ #endif
+
+ if (USB_INT_HasOccurred(USB_INT_DDISCI) && USB_INT_IsEnabled(USB_INT_DDISCI))
+ {
+ USB_INT_Clear(USB_INT_DDISCI);
+ USB_INT_Clear(USB_INT_DCONNI);
+ USB_INT_Disable(USB_INT_DDISCI);
+
+ EVENT_USB_Host_DeviceUnattached();
+
+ USB_ResetInterface();
+ }
+
+ if (USB_INT_HasOccurred(USB_INT_VBERRI) && USB_INT_IsEnabled(USB_INT_VBERRI))
+ {
+ USB_INT_Clear(USB_INT_VBERRI);
+
+ USB_Host_VBUS_Manual_Off();
+ USB_Host_VBUS_Auto_Off();
+
+ EVENT_USB_Host_HostError(HOST_ERROR_VBusVoltageDip);
+ EVENT_USB_Host_DeviceUnattached();
+
+ USB_HostState = HOST_STATE_Unattached;
+ }
+
+ if (USB_INT_HasOccurred(USB_INT_SRPI) && USB_INT_IsEnabled(USB_INT_SRPI))
+ {
+ USB_INT_Clear(USB_INT_SRPI);
+ USB_INT_Disable(USB_INT_SRPI);
+
+ EVENT_USB_Host_DeviceAttached();
+
+ USB_INT_Enable(USB_INT_DDISCI);
+
+ USB_HostState = HOST_STATE_Powered;
+ }
+
+ if (USB_INT_HasOccurred(USB_INT_BCERRI) && USB_INT_IsEnabled(USB_INT_BCERRI))
+ {
+ USB_INT_Clear(USB_INT_BCERRI);
+
+ EVENT_USB_Host_DeviceEnumerationFailed(HOST_ENUMERROR_NoDeviceDetected, 0);
+ EVENT_USB_Host_DeviceUnattached();
+
+ USB_ResetInterface();
+ }
+ #endif
+
+ #if defined(USB_CAN_BE_BOTH)
+ if (USB_INT_HasOccurred(USB_INT_IDTI) && USB_INT_IsEnabled(USB_INT_IDTI))
+ {
+ USB_INT_Clear(USB_INT_IDTI);
+
+ if (USB_DeviceState != DEVICE_STATE_Unattached)
+ EVENT_USB_Device_Disconnect();
+
+ if (USB_HostState != HOST_STATE_Unattached)
+ EVENT_USB_Host_DeviceUnattached();
+
+ USB_CurrentMode = USB_GetUSBModeFromUID();
+ USB_ResetInterface();
+
+ EVENT_USB_UIDChange();
+ }
+ #endif
+}
+
+#if defined(INTERRUPT_CONTROL_ENDPOINT) && defined(USB_CAN_BE_DEVICE)
+ISR(USB_COM_vect, ISR_BLOCK)
+{
+ uint8_t PrevSelectedEndpoint = Endpoint_GetCurrentEndpoint();
+
+ Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);
+ USB_INT_Disable(USB_INT_RXSTPI);
+
+ GlobalInterruptEnable();
+
+ USB_Device_ProcessControlRequest();
+
+ Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);
+ USB_INT_Enable(USB_INT_RXSTPI);
+ Endpoint_SelectEndpoint(PrevSelectedEndpoint);
+}
+#endif
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/USBInterrupt_AVR8.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/USBInterrupt_AVR8.h
new file mode 100644
index 000000000..e6f5ff994
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/USBInterrupt_AVR8.h
@@ -0,0 +1,375 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief USB Controller Interrupt definitions for the AVR8 microcontrollers.
+ *
+ * This file contains definitions required for the correct handling of low level USB service routine interrupts
+ * from the USB controller.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+#ifndef __USBINTERRUPT_AVR8_H__
+#define __USBINTERRUPT_AVR8_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Enums: */
+ enum USB_Interrupts_t
+ {
+ #if (defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) || defined(__DOXYGEN__))
+ USB_INT_VBUSTI = 0,
+ #endif
+ #if (defined(USB_CAN_BE_BOTH) || defined(__DOXYGEN__))
+ USB_INT_IDTI = 1,
+ #endif
+ #if (defined(USB_CAN_BE_DEVICE) || defined(__DOXYGEN__))
+ USB_INT_WAKEUPI = 2,
+ USB_INT_SUSPI = 3,
+ USB_INT_EORSTI = 4,
+ USB_INT_SOFI = 5,
+ USB_INT_RXSTPI = 6,
+ #endif
+ #if (defined(USB_CAN_BE_HOST) || defined(__DOXYGEN__))
+ USB_INT_HSOFI = 7,
+ USB_INT_DCONNI = 8,
+ USB_INT_DDISCI = 9,
+ USB_INT_RSTI = 10,
+ USB_INT_BCERRI = 11,
+ USB_INT_VBERRI = 12,
+ USB_INT_SRPI = 13,
+ #endif
+ };
+
+ /* Inline Functions: */
+ static inline void USB_INT_Enable(const uint8_t Interrupt) ATTR_ALWAYS_INLINE;
+ static inline void USB_INT_Enable(const uint8_t Interrupt)
+ {
+ switch (Interrupt)
+ {
+ #if (defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR))
+ case USB_INT_VBUSTI:
+ USBCON |= (1 << VBUSTE);
+ break;
+ #endif
+ #if defined(USB_CAN_BE_BOTH)
+ case USB_INT_IDTI:
+ USBCON |= (1 << IDTE);
+ break;
+ #endif
+ #if defined(USB_CAN_BE_DEVICE)
+ case USB_INT_WAKEUPI:
+ UDIEN |= (1 << WAKEUPE);
+ break;
+ case USB_INT_SUSPI:
+ UDIEN |= (1 << SUSPE);
+ break;
+ case USB_INT_EORSTI:
+ UDIEN |= (1 << EORSTE);
+ break;
+ case USB_INT_SOFI:
+ UDIEN |= (1 << SOFE);
+ break;
+ case USB_INT_RXSTPI:
+ UEIENX |= (1 << RXSTPE);
+ break;
+ #endif
+ #if defined(USB_CAN_BE_HOST)
+ case USB_INT_HSOFI:
+ UHIEN |= (1 << HSOFE);
+ break;
+ case USB_INT_DCONNI:
+ UHIEN |= (1 << DCONNE);
+ break;
+ case USB_INT_DDISCI:
+ UHIEN |= (1 << DDISCE);
+ break;
+ case USB_INT_RSTI:
+ UHIEN |= (1 << RSTE);
+ break;
+ case USB_INT_BCERRI:
+ OTGIEN |= (1 << BCERRE);
+ break;
+ case USB_INT_VBERRI:
+ OTGIEN |= (1 << VBERRE);
+ break;
+ case USB_INT_SRPI:
+ OTGIEN |= (1 << SRPE);
+ break;
+ #endif
+ default:
+ break;
+ }
+ }
+
+ static inline void USB_INT_Disable(const uint8_t Interrupt) ATTR_ALWAYS_INLINE;
+ static inline void USB_INT_Disable(const uint8_t Interrupt)
+ {
+ switch (Interrupt)
+ {
+ #if (defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR))
+ case USB_INT_VBUSTI:
+ USBCON &= ~(1 << VBUSTE);
+ break;
+ #endif
+ #if defined(USB_CAN_BE_BOTH)
+ case USB_INT_IDTI:
+ USBCON &= ~(1 << IDTE);
+ break;
+ #endif
+ #if defined(USB_CAN_BE_DEVICE)
+ case USB_INT_WAKEUPI:
+ UDIEN &= ~(1 << WAKEUPE);
+ break;
+ case USB_INT_SUSPI:
+ UDIEN &= ~(1 << SUSPE);
+ break;
+ case USB_INT_EORSTI:
+ UDIEN &= ~(1 << EORSTE);
+ break;
+ case USB_INT_SOFI:
+ UDIEN &= ~(1 << SOFE);
+ break;
+ case USB_INT_RXSTPI:
+ UEIENX &= ~(1 << RXSTPE);
+ break;
+ #endif
+ #if defined(USB_CAN_BE_HOST)
+ case USB_INT_HSOFI:
+ UHIEN &= ~(1 << HSOFE);
+ break;
+ case USB_INT_DCONNI:
+ UHIEN &= ~(1 << DCONNE);
+ break;
+ case USB_INT_DDISCI:
+ UHIEN &= ~(1 << DDISCE);
+ break;
+ case USB_INT_RSTI:
+ UHIEN &= ~(1 << RSTE);
+ break;
+ case USB_INT_BCERRI:
+ OTGIEN &= ~(1 << BCERRE);
+ break;
+ case USB_INT_VBERRI:
+ OTGIEN &= ~(1 << VBERRE);
+ break;
+ case USB_INT_SRPI:
+ OTGIEN &= ~(1 << SRPE);
+ break;
+ #endif
+ default:
+ break;
+ }
+ }
+
+ static inline void USB_INT_Clear(const uint8_t Interrupt) ATTR_ALWAYS_INLINE;
+ static inline void USB_INT_Clear(const uint8_t Interrupt)
+ {
+ switch (Interrupt)
+ {
+ #if (defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR))
+ case USB_INT_VBUSTI:
+ USBINT &= ~(1 << VBUSTI);
+ break;
+ #endif
+ #if defined(USB_CAN_BE_BOTH)
+ case USB_INT_IDTI:
+ USBINT &= ~(1 << IDTI);
+ break;
+ #endif
+ #if defined(USB_CAN_BE_DEVICE)
+ case USB_INT_WAKEUPI:
+ UDINT &= ~(1 << WAKEUPI);
+ break;
+ case USB_INT_SUSPI:
+ UDINT &= ~(1 << SUSPI);
+ break;
+ case USB_INT_EORSTI:
+ UDINT &= ~(1 << EORSTI);
+ break;
+ case USB_INT_SOFI:
+ UDINT &= ~(1 << SOFI);
+ break;
+ case USB_INT_RXSTPI:
+ UEINTX &= ~(1 << RXSTPI);
+ break;
+ #endif
+ #if defined(USB_CAN_BE_HOST)
+ case USB_INT_HSOFI:
+ UHINT &= ~(1 << HSOFI);
+ break;
+ case USB_INT_DCONNI:
+ UHINT &= ~(1 << DCONNI);
+ break;
+ case USB_INT_DDISCI:
+ UHINT &= ~(1 << DDISCI);
+ break;
+ case USB_INT_RSTI:
+ UHINT &= ~(1 << RSTI);
+ break;
+ case USB_INT_BCERRI:
+ OTGINT &= ~(1 << BCERRI);
+ break;
+ case USB_INT_VBERRI:
+ OTGINT &= ~(1 << VBERRI);
+ break;
+ case USB_INT_SRPI:
+ OTGINT &= ~(1 << SRPI);
+ break;
+ #endif
+ default:
+ break;
+ }
+ }
+
+ static inline bool USB_INT_IsEnabled(const uint8_t Interrupt) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline bool USB_INT_IsEnabled(const uint8_t Interrupt)
+ {
+ switch (Interrupt)
+ {
+ #if (defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR))
+ case USB_INT_VBUSTI:
+ return (USBCON & (1 << VBUSTE));
+ #endif
+ #if defined(USB_CAN_BE_BOTH)
+ case USB_INT_IDTI:
+ return (USBCON & (1 << IDTE));
+ #endif
+ #if defined(USB_CAN_BE_DEVICE)
+ case USB_INT_WAKEUPI:
+ return (UDIEN & (1 << WAKEUPE));
+ case USB_INT_SUSPI:
+ return (UDIEN & (1 << SUSPE));
+ case USB_INT_EORSTI:
+ return (UDIEN & (1 << EORSTE));
+ case USB_INT_SOFI:
+ return (UDIEN & (1 << SOFE));
+ case USB_INT_RXSTPI:
+ return (UEIENX & (1 << RXSTPE));
+ #endif
+ #if defined(USB_CAN_BE_HOST)
+ case USB_INT_HSOFI:
+ return (UHIEN & (1 << HSOFE));
+ case USB_INT_DCONNI:
+ return (UHIEN & (1 << DCONNE));
+ case USB_INT_DDISCI:
+ return (UHIEN & (1 << DDISCE));
+ case USB_INT_RSTI:
+ return (UHIEN & (1 << RSTE));
+ case USB_INT_BCERRI:
+ return (OTGIEN & (1 << BCERRE));
+ case USB_INT_VBERRI:
+ return (OTGIEN & (1 << VBERRE));
+ case USB_INT_SRPI:
+ return (OTGIEN & (1 << SRPE));
+ #endif
+ default:
+ return false;
+ }
+ }
+
+ static inline bool USB_INT_HasOccurred(const uint8_t Interrupt) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline bool USB_INT_HasOccurred(const uint8_t Interrupt)
+ {
+ switch (Interrupt)
+ {
+ #if (defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR))
+ case USB_INT_VBUSTI:
+ return (USBINT & (1 << VBUSTI));
+ #endif
+ #if defined(USB_CAN_BE_BOTH)
+ case USB_INT_IDTI:
+ return (USBINT & (1 << IDTI));
+ #endif
+ #if defined(USB_CAN_BE_DEVICE)
+ case USB_INT_WAKEUPI:
+ return (UDINT & (1 << WAKEUPI));
+ case USB_INT_SUSPI:
+ return (UDINT & (1 << SUSPI));
+ case USB_INT_EORSTI:
+ return (UDINT & (1 << EORSTI));
+ case USB_INT_SOFI:
+ return (UDINT & (1 << SOFI));
+ case USB_INT_RXSTPI:
+ return (UEINTX & (1 << RXSTPI));
+ #endif
+ #if defined(USB_CAN_BE_HOST)
+ case USB_INT_HSOFI:
+ return (UHINT & (1 << HSOFI));
+ case USB_INT_DCONNI:
+ return (UHINT & (1 << DCONNI));
+ case USB_INT_DDISCI:
+ return (UHINT & (1 << DDISCI));
+ case USB_INT_RSTI:
+ return (UHINT & (1 << RSTI));
+ case USB_INT_BCERRI:
+ return (OTGINT & (1 << BCERRI));
+ case USB_INT_VBERRI:
+ return (OTGINT & (1 << VBERRI));
+ case USB_INT_SRPI:
+ return (OTGINT & (1 << SRPI));
+ #endif
+ default:
+ return false;
+ }
+ }
+
+ /* Includes: */
+ #include "../USBMode.h"
+ #include "../Events.h"
+ #include "../USBController.h"
+
+ /* Function Prototypes: */
+ void USB_INT_ClearAllInterrupts(void);
+ void USB_INT_DisableAllInterrupts(void);
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/ConfigDescriptors.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/ConfigDescriptors.c
new file mode 100644
index 000000000..da6812a32
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/ConfigDescriptors.c
@@ -0,0 +1,146 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "ConfigDescriptors.h"
+
+#if defined(USB_CAN_BE_HOST)
+uint8_t USB_Host_GetDeviceConfigDescriptor(const uint8_t ConfigNumber,
+ uint16_t* const ConfigSizePtr,
+ void* const BufferPtr,
+ const uint16_t BufferSize)
+{
+ uint8_t ErrorCode;
+ uint8_t ConfigHeader[sizeof(USB_Descriptor_Configuration_Header_t)];
+
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE),
+ .bRequest = REQ_GetDescriptor,
+ .wValue = ((DTYPE_Configuration << 8) | (ConfigNumber - 1)),
+ .wIndex = 0,
+ .wLength = sizeof(USB_Descriptor_Configuration_Header_t),
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+
+ if ((ErrorCode = USB_Host_SendControlRequest(ConfigHeader)) != HOST_SENDCONTROL_Successful)
+ return ErrorCode;
+
+ *ConfigSizePtr = le16_to_cpu(DESCRIPTOR_PCAST(ConfigHeader, USB_Descriptor_Configuration_Header_t)->TotalConfigurationSize);
+
+ if (*ConfigSizePtr > BufferSize)
+ return HOST_GETCONFIG_BuffOverflow;
+
+ USB_ControlRequest.wLength = *ConfigSizePtr;
+
+ if ((ErrorCode = USB_Host_SendControlRequest(BufferPtr)) != HOST_SENDCONTROL_Successful)
+ return ErrorCode;
+
+ if (DESCRIPTOR_TYPE(BufferPtr) != DTYPE_Configuration)
+ return HOST_GETCONFIG_InvalidData;
+
+ return HOST_GETCONFIG_Successful;
+}
+#endif
+
+void USB_GetNextDescriptorOfType(uint16_t* const BytesRem,
+ void** const CurrConfigLoc,
+ const uint8_t Type)
+{
+ while (*BytesRem)
+ {
+ USB_GetNextDescriptor(BytesRem, CurrConfigLoc);
+
+ if (DESCRIPTOR_TYPE(*CurrConfigLoc) == Type)
+ return;
+ }
+}
+
+void USB_GetNextDescriptorOfTypeBefore(uint16_t* const BytesRem,
+ void** const CurrConfigLoc,
+ const uint8_t Type,
+ const uint8_t BeforeType)
+{
+ while (*BytesRem)
+ {
+ USB_GetNextDescriptor(BytesRem, CurrConfigLoc);
+
+ if (DESCRIPTOR_TYPE(*CurrConfigLoc) == Type)
+ {
+ return;
+ }
+ else if (DESCRIPTOR_TYPE(*CurrConfigLoc) == BeforeType)
+ {
+ *BytesRem = 0;
+ return;
+ }
+ }
+}
+
+void USB_GetNextDescriptorOfTypeAfter(uint16_t* const BytesRem,
+ void** const CurrConfigLoc,
+ const uint8_t Type,
+ const uint8_t AfterType)
+{
+ USB_GetNextDescriptorOfType(BytesRem, CurrConfigLoc, AfterType);
+
+ if (*BytesRem)
+ USB_GetNextDescriptorOfType(BytesRem, CurrConfigLoc, Type);
+}
+
+uint8_t USB_GetNextDescriptorComp(uint16_t* const BytesRem,
+ void** const CurrConfigLoc,
+ ConfigComparatorPtr_t const ComparatorRoutine)
+{
+ uint8_t ErrorCode;
+
+ while (*BytesRem)
+ {
+ uint8_t* PrevDescLoc = *CurrConfigLoc;
+ uint16_t PrevBytesRem = *BytesRem;
+
+ USB_GetNextDescriptor(BytesRem, CurrConfigLoc);
+
+ if ((ErrorCode = ComparatorRoutine(*CurrConfigLoc)) != DESCRIPTOR_SEARCH_NotFound)
+ {
+ if (ErrorCode == DESCRIPTOR_SEARCH_Fail)
+ {
+ *CurrConfigLoc = PrevDescLoc;
+ *BytesRem = PrevBytesRem;
+ }
+
+ return ErrorCode;
+ }
+ }
+
+ return DESCRIPTOR_SEARCH_COMP_EndOfDescriptor;
+}
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/ConfigDescriptors.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/ConfigDescriptors.h
new file mode 100644
index 000000000..b4a9788c2
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/ConfigDescriptors.h
@@ -0,0 +1,287 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief USB Configuration Descriptor definitions.
+ * \copydetails Group_ConfigDescriptorParser
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_StdDescriptors
+ * \defgroup Group_ConfigDescriptorParser Configuration Descriptor Parser
+ * \brief USB Configuration Descriptor definitions.
+ *
+ * This section of the library gives a friendly API which can be used in host applications to easily
+ * parse an attached device's configuration descriptor so that endpoint, interface and other descriptor
+ * data can be extracted and used as needed.
+ *
+ * @{
+ */
+
+#ifndef __CONFIGDESCRIPTORS_H__
+#define __CONFIGDESCRIPTORS_H__
+
+ /* Includes: */
+ #include "../../../Common/Common.h"
+ #include "USBMode.h"
+ #include "HostStandardReq.h"
+ #include "StdDescriptors.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Casts a pointer to a descriptor inside the configuration descriptor into a pointer to the given
+ * descriptor type.
+ *
+ * Usage Example:
+ * \code
+ * uint8_t* CurrDescriptor = &ConfigDescriptor[0]; // Pointing to the configuration header
+ * USB_Descriptor_Configuration_Header_t* ConfigHeaderPtr = DESCRIPTOR_PCAST(CurrDescriptor,
+ * USB_Descriptor_Configuration_Header_t);
+ *
+ * // Can now access elements of the configuration header struct using the -> indirection operator
+ * \endcode
+ */
+ #define DESCRIPTOR_PCAST(DescriptorPtr, Type) ((Type*)(DescriptorPtr))
+
+ /** Casts a pointer to a descriptor inside the configuration descriptor into the given descriptor
+ * type (as an actual struct instance rather than a pointer to a struct).
+ *
+ * Usage Example:
+ * \code
+ * uint8_t* CurrDescriptor = &ConfigDescriptor[0]; // Pointing to the configuration header
+ * USB_Descriptor_Configuration_Header_t ConfigHeader = DESCRIPTOR_CAST(CurrDescriptor,
+ * USB_Descriptor_Configuration_Header_t);
+ *
+ * // Can now access elements of the configuration header struct using the . operator
+ * \endcode
+ */
+ #define DESCRIPTOR_CAST(DescriptorPtr, Type) (*DESCRIPTOR_PCAST(DescriptorPtr, Type))
+
+ /** Returns the descriptor's type, expressed as the 8-bit type value in the header of the descriptor.
+ * This value's meaning depends on the descriptor's placement in the descriptor, but standard type
+ * values can be accessed in the \ref USB_DescriptorTypes_t enum.
+ */
+ #define DESCRIPTOR_TYPE(DescriptorPtr) DESCRIPTOR_PCAST(DescriptorPtr, USB_Descriptor_Header_t)->Type
+
+ /** Returns the descriptor's size, expressed as the 8-bit value indicating the number of bytes. */
+ #define DESCRIPTOR_SIZE(DescriptorPtr) DESCRIPTOR_PCAST(DescriptorPtr, USB_Descriptor_Header_t)->Size
+
+ /* Type Defines: */
+ /** Type define for a Configuration Descriptor comparator function (function taking a pointer to an array
+ * of type void, returning a uint8_t value).
+ *
+ * \see \ref USB_GetNextDescriptorComp function for more details.
+ */
+ typedef uint8_t (* ConfigComparatorPtr_t)(void*);
+
+ /* Enums: */
+ /** Enum for the possible return codes of the \ref USB_Host_GetDeviceConfigDescriptor() function. */
+ enum USB_Host_GetConfigDescriptor_ErrorCodes_t
+ {
+ HOST_GETCONFIG_Successful = 0, /**< No error occurred while retrieving the configuration descriptor. */
+ HOST_GETCONFIG_DeviceDisconnect = 1, /**< The attached device was disconnected while retrieving the configuration
+ * descriptor.
+ */
+ HOST_GETCONFIG_PipeError = 2, /**< An error occurred in the pipe while sending the request. */
+ HOST_GETCONFIG_SetupStalled = 3, /**< The attached device stalled the request to retrieve the configuration
+ * descriptor.
+ */
+ HOST_GETCONFIG_SoftwareTimeOut = 4, /**< The request or data transfer timed out. */
+ HOST_GETCONFIG_BuffOverflow = 5, /**< The device's configuration descriptor is too large to fit into the allocated
+ * buffer.
+ */
+ HOST_GETCONFIG_InvalidData = 6, /**< The device returned invalid configuration descriptor data. */
+ };
+
+ /** Enum for return values of a descriptor comparator function. */
+ enum DSearch_Return_ErrorCodes_t
+ {
+ DESCRIPTOR_SEARCH_Found = 0, /**< Current descriptor matches comparator criteria. */
+ DESCRIPTOR_SEARCH_Fail = 1, /**< No further descriptor could possibly match criteria, fail the search. */
+ DESCRIPTOR_SEARCH_NotFound = 2, /**< Current descriptor does not match comparator criteria. */
+ };
+
+ /** Enum for return values of \ref USB_GetNextDescriptorComp(). */
+ enum DSearch_Comp_Return_ErrorCodes_t
+ {
+ DESCRIPTOR_SEARCH_COMP_Found = 0, /**< Configuration descriptor now points to descriptor which matches
+ * search criteria of the given comparator function. */
+ DESCRIPTOR_SEARCH_COMP_Fail = 1, /**< Comparator function returned \ref DESCRIPTOR_SEARCH_Fail. */
+ DESCRIPTOR_SEARCH_COMP_EndOfDescriptor = 2, /**< End of configuration descriptor reached before match found. */
+ };
+
+ /* Function Prototypes: */
+ /** Retrieves the configuration descriptor data from an attached device via a standard request into a buffer,
+ * including validity and size checking to prevent a buffer overflow.
+ *
+ * \param[in] ConfigNumber Device configuration descriptor number to fetch from the device (usually set to 1 for
+ * single configuration devices).
+ * \param[in,out] ConfigSizePtr Pointer to a location for storing the retrieved configuration descriptor size.
+ * \param[out] BufferPtr Pointer to the buffer for storing the configuration descriptor data.
+ * \param[out] BufferSize Size of the allocated buffer where the configuration descriptor is to be stored.
+ *
+ * \return A value from the \ref USB_Host_GetConfigDescriptor_ErrorCodes_t enum.
+ */
+ uint8_t USB_Host_GetDeviceConfigDescriptor(const uint8_t ConfigNumber,
+ uint16_t* const ConfigSizePtr,
+ void* const BufferPtr,
+ const uint16_t BufferSize) ATTR_NON_NULL_PTR_ARG(2) ATTR_NON_NULL_PTR_ARG(3);
+
+ /** Skips to the next sub-descriptor inside the configuration descriptor of the specified type value.
+ * The bytes remaining value is automatically decremented.
+ *
+ * \param[in,out] BytesRem Pointer to the number of bytes remaining of the configuration descriptor.
+ * \param[in,out] CurrConfigLoc Pointer to the current descriptor inside the configuration descriptor.
+ * \param[in] Type Descriptor type value to search for.
+ */
+ void USB_GetNextDescriptorOfType(uint16_t* const BytesRem,
+ void** const CurrConfigLoc,
+ const uint8_t Type)
+ ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+
+ /** Skips to the next sub-descriptor inside the configuration descriptor of the specified type value,
+ * which must come before a descriptor of the second given type value. If the BeforeType type
+ * descriptor is reached first, the number of bytes remaining to process is set to zero and the
+ * function exits. The bytes remaining value is automatically decremented.
+ *
+ * \param[in,out] BytesRem Pointer to the number of bytes remaining of the configuration descriptor.
+ * \param[in,out] CurrConfigLoc Pointer to the current descriptor inside the configuration descriptor.
+ * \param[in] Type Descriptor type value to search for.
+ * \param[in] BeforeType Descriptor type value which must not be reached before the given Type descriptor.
+ */
+ void USB_GetNextDescriptorOfTypeBefore(uint16_t* const BytesRem,
+ void** const CurrConfigLoc,
+ const uint8_t Type,
+ const uint8_t BeforeType)
+ ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+
+ /** Skips to the next sub-descriptor inside the configuration descriptor of the specified type value,
+ * which must come after a descriptor of the second given type value. The bytes remaining value is
+ * automatically decremented.
+ *
+ * \param[in,out] BytesRem Pointer to the number of bytes remaining of the configuration descriptor.
+ * \param[in,out] CurrConfigLoc Pointer to the current descriptor inside the configuration descriptor.
+ * \param[in] Type Descriptor type value to search for.
+ * \param[in] AfterType Descriptor type value which must be reached before the given Type descriptor.
+ */
+ void USB_GetNextDescriptorOfTypeAfter(uint16_t* const BytesRem,
+ void** const CurrConfigLoc,
+ const uint8_t Type,
+ const uint8_t AfterType)
+ ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+
+ /** Searches for the next descriptor in the given configuration descriptor using a pre-made comparator
+ * function. The routine updates the position and remaining configuration descriptor bytes values
+ * automatically. If a comparator routine fails a search, the descriptor pointer is retreated back
+ * so that the next descriptor search invocation will start from the descriptor which first caused the
+ * original search to fail. This behavior allows for one comparator to be used immediately after another
+ * has failed, starting the second search from the descriptor which failed the first.
+ *
+ * Comparator functions should be standard functions which accept a pointer to the header of the current
+ * descriptor inside the configuration descriptor which is being compared, and should return a value from
+ * the \ref DSearch_Return_ErrorCodes_t enum as a uint8_t value.
+ *
+ * \note This function is available in USB Host mode only.
+ *
+ * \param[in,out] BytesRem Pointer to an int storing the remaining bytes in the configuration descriptor.
+ * \param[in,out] CurrConfigLoc Pointer to the current position in the configuration descriptor.
+ * \param[in] ComparatorRoutine Name of the comparator search function to use on the configuration descriptor.
+ *
+ * \return Value of one of the members of the \ref DSearch_Comp_Return_ErrorCodes_t enum.
+ *
+ * Usage Example:
+ * \code
+ * uint8_t EndpointSearcher(void* CurrentDescriptor); // Comparator Prototype
+ *
+ * uint8_t EndpointSearcher(void* CurrentDescriptor)
+ * {
+ * if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint)
+ * return DESCRIPTOR_SEARCH_Found;
+ * else
+ * return DESCRIPTOR_SEARCH_NotFound;
+ * }
+ *
+ * //...
+ *
+ * // After retrieving configuration descriptor:
+ * if (USB_Host_GetNextDescriptorComp(&BytesRemaining, &CurrentConfigLoc, EndpointSearcher) ==
+ * Descriptor_Search_Comp_Found)
+ * {
+ * // Do something with the endpoint descriptor
+ * }
+ * \endcode
+ */
+ uint8_t USB_GetNextDescriptorComp(uint16_t* const BytesRem,
+ void** const CurrConfigLoc,
+ ConfigComparatorPtr_t const ComparatorRoutine) ATTR_NON_NULL_PTR_ARG(1)
+ ATTR_NON_NULL_PTR_ARG(2) ATTR_NON_NULL_PTR_ARG(3);
+
+ /* Inline Functions: */
+ /** Skips over the current sub-descriptor inside the configuration descriptor, so that the pointer then
+ points to the next sub-descriptor. The bytes remaining value is automatically decremented.
+ *
+ * \param[in,out] BytesRem Pointer to the number of bytes remaining of the configuration descriptor.
+ * \param[in,out] CurrConfigLoc Pointer to the current descriptor inside the configuration descriptor.
+ */
+ static inline void USB_GetNextDescriptor(uint16_t* const BytesRem,
+ void** CurrConfigLoc) ATTR_NON_NULL_PTR_ARG(1) ATTR_NON_NULL_PTR_ARG(2);
+ static inline void USB_GetNextDescriptor(uint16_t* const BytesRem,
+ void** CurrConfigLoc)
+ {
+ uint16_t CurrDescriptorSize = DESCRIPTOR_CAST(*CurrConfigLoc, USB_Descriptor_Header_t).Size;
+
+ if (*BytesRem < CurrDescriptorSize)
+ CurrDescriptorSize = *BytesRem;
+
+ *CurrConfigLoc = (void*)((uintptr_t)*CurrConfigLoc + CurrDescriptorSize);
+ *BytesRem -= CurrDescriptorSize;
+ }
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/Device.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/Device.h
new file mode 100644
index 000000000..10d739f56
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/Device.h
@@ -0,0 +1,159 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Common USB Device definitions for all architectures.
+ * \copydetails Group_Device
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_USB
+ * \defgroup Group_Device Device Management
+ * \brief USB Device management definitions for USB device mode.
+ *
+ * USB Device mode related definitions common to all architectures. This module contains definitions which
+ * are used when the USB controller is initialized in device mode.
+ *
+ * @{
+ */
+
+#ifndef __USBDEVICE_H__
+#define __USBDEVICE_H__
+
+ /* Includes: */
+ #include "../../../Common/Common.h"
+ #include "USBMode.h"
+ #include "StdDescriptors.h"
+ #include "USBInterrupt.h"
+ #include "Endpoint.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Enums: */
+ /** Enum for the various states of the USB Device state machine. Only some states are
+ * implemented in the LUFA library - other states are left to the user to implement.
+ *
+ * For information on each possible USB device state, refer to the USB 2.0 specification.
+ *
+ * \see \ref USB_DeviceState, which stores the current device state machine state.
+ */
+ enum USB_Device_States_t
+ {
+ DEVICE_STATE_Unattached = 0, /**< Internally implemented by the library. This state indicates
+ * that the device is not currently connected to a host.
+ */
+ DEVICE_STATE_Powered = 1, /**< Internally implemented by the library. This state indicates
+ * that the device is connected to a host, but enumeration has not
+ * yet begun.
+ */
+ DEVICE_STATE_Default = 2, /**< Internally implemented by the library. This state indicates
+ * that the device's USB bus has been reset by the host and it is
+ * now waiting for the host to begin the enumeration process.
+ */
+ DEVICE_STATE_Addressed = 3, /**< Internally implemented by the library. This state indicates
+ * that the device has been addressed by the USB Host, but is not
+ * yet configured.
+ */
+ DEVICE_STATE_Configured = 4, /**< May be implemented by the user project. This state indicates
+ * that the device has been enumerated by the host and is ready
+ * for USB communications to begin.
+ */
+ DEVICE_STATE_Suspended = 5, /**< May be implemented by the user project. This state indicates
+ * that the USB bus has been suspended by the host, and the device
+ * should power down to a minimal power level until the bus is
+ * resumed.
+ */
+ };
+
+ /* Function Prototypes: */
+ /** Function to retrieve a given descriptor's size and memory location from the given descriptor type value,
+ * index and language ID. This function MUST be overridden in the user application (added with full, identical
+ * prototype and name so that the library can call it to retrieve descriptor data.
+ *
+ * \param[in] wValue The type of the descriptor to retrieve in the upper byte, and the index in the
+ * lower byte (when more than one descriptor of the given type exists, such as the
+ * case of string descriptors). The type may be one of the standard types defined
+ * in the DescriptorTypes_t enum, or may be a class-specific descriptor type value.
+ * \param[in] wIndex The language ID of the string to return if the \c wValue type indicates
+ * \ref DTYPE_String, otherwise zero for standard descriptors, or as defined in a
+ * class-specific standards.
+ * \param[out] DescriptorAddress Pointer to the descriptor in memory. This should be set by the routine to
+ * the address of the descriptor.
+ * \param[out] DescriptorMemorySpace A value from the \ref USB_DescriptorMemorySpaces_t enum to indicate the memory
+ * space in which the descriptor is stored. This parameter does not exist when one
+ * of the \c USE_*_DESCRIPTORS compile time options is used, or on architectures which
+ * use a unified address space.
+ *
+ * \note By default, the library expects all descriptors to be located in flash memory via the \c PROGMEM attribute.
+ * If descriptors should be located in RAM or EEPROM instead (to speed up access in the case of RAM, or to
+ * allow the descriptors to be changed dynamically at runtime) either the \c USE_RAM_DESCRIPTORS or the
+ * \c USE_EEPROM_DESCRIPTORS tokens may be defined in the project makefile and passed to the compiler by the -D
+ * switch.
+ *
+ * \return Size in bytes of the descriptor if it exists, zero or \ref NO_DESCRIPTOR otherwise.
+ */
+ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+ const uint8_t wIndex,
+ const void** const DescriptorAddress
+ #if (defined(ARCH_HAS_MULTI_ADDRESS_SPACE) || defined(__DOXYGEN__)) && \
+ !(defined(USE_FLASH_DESCRIPTORS) || defined(USE_EEPROM_DESCRIPTORS) || defined(USE_RAM_DESCRIPTORS))
+ , uint8_t* const DescriptorMemorySpace
+ #endif
+ ) ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
+
+ /* Architecture Includes: */
+ #if (ARCH == ARCH_AVR8)
+ #include "AVR8/Device_AVR8.h"
+ #elif (ARCH == ARCH_UC3)
+ #include "UC3/Device_UC3.h"
+ #elif (ARCH == ARCH_XMEGA)
+ #include "XMEGA/Device_XMEGA.h"
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/DeviceStandardReq.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/DeviceStandardReq.c
new file mode 100644
index 000000000..adf615a9c
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/DeviceStandardReq.c
@@ -0,0 +1,380 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "USBMode.h"
+
+#if defined(USB_CAN_BE_DEVICE)
+
+#define __INCLUDE_FROM_DEVICESTDREQ_C
+#include "DeviceStandardReq.h"
+
+uint8_t USB_Device_ConfigurationNumber;
+
+#if !defined(NO_DEVICE_SELF_POWER)
+bool USB_Device_CurrentlySelfPowered;
+#endif
+
+#if !defined(NO_DEVICE_REMOTE_WAKEUP)
+bool USB_Device_RemoteWakeupEnabled;
+#endif
+
+void USB_Device_ProcessControlRequest(void)
+{
+ #if defined(ARCH_BIG_ENDIAN)
+ USB_ControlRequest.bmRequestType = Endpoint_Read_8();
+ USB_ControlRequest.bRequest = Endpoint_Read_8();
+ USB_ControlRequest.wValue = Endpoint_Read_16_LE();
+ USB_ControlRequest.wIndex = Endpoint_Read_16_LE();
+ USB_ControlRequest.wLength = Endpoint_Read_16_LE();
+ #else
+ uint8_t* RequestHeader = (uint8_t*)&USB_ControlRequest;
+
+ for (uint8_t RequestHeaderByte = 0; RequestHeaderByte < sizeof(USB_Request_Header_t); RequestHeaderByte++)
+ *(RequestHeader++) = Endpoint_Read_8();
+ #endif
+
+ EVENT_USB_Device_ControlRequest();
+
+ if (Endpoint_IsSETUPReceived())
+ {
+ uint8_t bmRequestType = USB_ControlRequest.bmRequestType;
+
+ switch (USB_ControlRequest.bRequest)
+ {
+ case REQ_GetStatus:
+ if ((bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE)) ||
+ (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_ENDPOINT)))
+ {
+ USB_Device_GetStatus();
+ }
+
+ break;
+ case REQ_ClearFeature:
+ case REQ_SetFeature:
+ if ((bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE)) ||
+ (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_ENDPOINT)))
+ {
+ USB_Device_ClearSetFeature();
+ }
+
+ break;
+ case REQ_SetAddress:
+ if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE))
+ USB_Device_SetAddress();
+
+ break;
+ case REQ_GetDescriptor:
+ if ((bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE)) ||
+ (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_INTERFACE)))
+ {
+ USB_Device_GetDescriptor();
+ }
+
+ break;
+ case REQ_GetConfiguration:
+ if (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE))
+ USB_Device_GetConfiguration();
+
+ break;
+ case REQ_SetConfiguration:
+ if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE))
+ USB_Device_SetConfiguration();
+
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (Endpoint_IsSETUPReceived())
+ {
+ Endpoint_ClearSETUP();
+ Endpoint_StallTransaction();
+ }
+}
+
+static void USB_Device_SetAddress(void)
+{
+ uint8_t DeviceAddress = (USB_ControlRequest.wValue & 0x7F);
+
+ USB_Device_SetDeviceAddress(DeviceAddress);
+
+ Endpoint_ClearSETUP();
+
+ Endpoint_ClearStatusStage();
+
+ while (!(Endpoint_IsINReady()));
+
+ USB_Device_EnableDeviceAddress(DeviceAddress);
+
+ USB_DeviceState = (DeviceAddress) ? DEVICE_STATE_Addressed : DEVICE_STATE_Default;
+}
+
+static void USB_Device_SetConfiguration(void)
+{
+ #if defined(FIXED_NUM_CONFIGURATIONS)
+ if ((uint8_t)USB_ControlRequest.wValue > FIXED_NUM_CONFIGURATIONS)
+ return;
+ #else
+ USB_Descriptor_Device_t* DevDescriptorPtr;
+
+ #if defined(ARCH_HAS_MULTI_ADDRESS_SPACE)
+ #if defined(USE_FLASH_DESCRIPTORS)
+ #define MemoryAddressSpace MEMSPACE_FLASH
+ #elif defined(USE_EEPROM_DESCRIPTORS)
+ #define MemoryAddressSpace MEMSPACE_EEPROM
+ #elif defined(USE_SRAM_DESCRIPTORS)
+ #define MemoryAddressSpace MEMSPACE_SRAM
+ #else
+ uint8_t MemoryAddressSpace;
+ #endif
+ #endif
+
+ if (CALLBACK_USB_GetDescriptor((DTYPE_Device << 8), 0, (void*)&DevDescriptorPtr
+ #if defined(ARCH_HAS_MULTI_ADDRESS_SPACE) && \
+ !(defined(USE_FLASH_DESCRIPTORS) || defined(USE_EEPROM_DESCRIPTORS) || defined(USE_RAM_DESCRIPTORS))
+ , &MemoryAddressSpace
+ #endif
+ ) == NO_DESCRIPTOR)
+ {
+ return;
+ }
+
+ #if defined(ARCH_HAS_MULTI_ADDRESS_SPACE)
+ if (MemoryAddressSpace == MEMSPACE_FLASH)
+ {
+ if (((uint8_t)USB_ControlRequest.wValue > pgm_read_byte(&DevDescriptorPtr->NumberOfConfigurations)))
+ return;
+ }
+ else if (MemoryAddressSpace == MEMSPACE_EEPROM)
+ {
+ if (((uint8_t)USB_ControlRequest.wValue > eeprom_read_byte(&DevDescriptorPtr->NumberOfConfigurations)))
+ return;
+ }
+ else
+ {
+ if ((uint8_t)USB_ControlRequest.wValue > DevDescriptorPtr->NumberOfConfigurations)
+ return;
+ }
+ #else
+ if ((uint8_t)USB_ControlRequest.wValue > DevDescriptorPtr->NumberOfConfigurations)
+ return;
+ #endif
+ #endif
+
+ Endpoint_ClearSETUP();
+
+ USB_Device_ConfigurationNumber = (uint8_t)USB_ControlRequest.wValue;
+
+ Endpoint_ClearStatusStage();
+
+ if (USB_Device_ConfigurationNumber)
+ USB_DeviceState = DEVICE_STATE_Configured;
+ else
+ USB_DeviceState = (USB_Device_IsAddressSet()) ? DEVICE_STATE_Configured : DEVICE_STATE_Powered;
+
+ EVENT_USB_Device_ConfigurationChanged();
+}
+
+static void USB_Device_GetConfiguration(void)
+{
+ Endpoint_ClearSETUP();
+
+ Endpoint_Write_8(USB_Device_ConfigurationNumber);
+ Endpoint_ClearIN();
+
+ Endpoint_ClearStatusStage();
+}
+
+#if !defined(NO_INTERNAL_SERIAL) && (USE_INTERNAL_SERIAL != NO_DESCRIPTOR)
+static void USB_Device_GetInternalSerialDescriptor(void)
+{
+ struct
+ {
+ USB_Descriptor_Header_t Header;
+ uint16_t UnicodeString[INTERNAL_SERIAL_LENGTH_BITS / 4];
+ } SignatureDescriptor;
+
+ SignatureDescriptor.Header.Type = DTYPE_String;
+ SignatureDescriptor.Header.Size = USB_STRING_LEN(INTERNAL_SERIAL_LENGTH_BITS / 4);
+
+ USB_Device_GetSerialString(SignatureDescriptor.UnicodeString);
+
+ Endpoint_ClearSETUP();
+
+ Endpoint_Write_Control_Stream_LE(&SignatureDescriptor, sizeof(SignatureDescriptor));
+ Endpoint_ClearOUT();
+}
+#endif
+
+static void USB_Device_GetDescriptor(void)
+{
+ const void* DescriptorPointer;
+ uint16_t DescriptorSize;
+
+ #if defined(ARCH_HAS_MULTI_ADDRESS_SPACE) && \
+ !(defined(USE_FLASH_DESCRIPTORS) || defined(USE_EEPROM_DESCRIPTORS) || defined(USE_RAM_DESCRIPTORS))
+ uint8_t DescriptorAddressSpace;
+ #endif
+
+ #if !defined(NO_INTERNAL_SERIAL) && (USE_INTERNAL_SERIAL != NO_DESCRIPTOR)
+ if (USB_ControlRequest.wValue == ((DTYPE_String << 8) | USE_INTERNAL_SERIAL))
+ {
+ USB_Device_GetInternalSerialDescriptor();
+ return;
+ }
+ #endif
+
+ if ((DescriptorSize = CALLBACK_USB_GetDescriptor(USB_ControlRequest.wValue, USB_ControlRequest.wIndex,
+ &DescriptorPointer
+ #if defined(ARCH_HAS_MULTI_ADDRESS_SPACE) && \
+ !(defined(USE_FLASH_DESCRIPTORS) || defined(USE_EEPROM_DESCRIPTORS) || defined(USE_RAM_DESCRIPTORS))
+ , &DescriptorAddressSpace
+ #endif
+ )) == NO_DESCRIPTOR)
+ {
+ return;
+ }
+
+ Endpoint_ClearSETUP();
+
+ #if defined(USE_RAM_DESCRIPTORS) || !defined(ARCH_HAS_MULTI_ADDRESS_SPACE)
+ Endpoint_Write_Control_Stream_LE(DescriptorPointer, DescriptorSize);
+ #elif defined(USE_EEPROM_DESCRIPTORS)
+ Endpoint_Write_Control_EStream_LE(DescriptorPointer, DescriptorSize);
+ #elif defined(USE_FLASH_DESCRIPTORS)
+ Endpoint_Write_Control_PStream_LE(DescriptorPointer, DescriptorSize);
+ #else
+ if (DescriptorAddressSpace == MEMSPACE_FLASH)
+ Endpoint_Write_Control_PStream_LE(DescriptorPointer, DescriptorSize);
+ else if (DescriptorAddressSpace == MEMSPACE_EEPROM)
+ Endpoint_Write_Control_EStream_LE(DescriptorPointer, DescriptorSize);
+ else
+ Endpoint_Write_Control_Stream_LE(DescriptorPointer, DescriptorSize);
+ #endif
+
+ Endpoint_ClearOUT();
+}
+
+static void USB_Device_GetStatus(void)
+{
+ uint8_t CurrentStatus = 0;
+
+ switch (USB_ControlRequest.bmRequestType)
+ {
+ case (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE):
+ #if !defined(NO_DEVICE_SELF_POWER)
+ if (USB_Device_CurrentlySelfPowered)
+ CurrentStatus |= FEATURE_SELFPOWERED_ENABLED;
+ #endif
+
+ #if !defined(NO_DEVICE_REMOTE_WAKEUP)
+ if (USB_Device_RemoteWakeupEnabled)
+ CurrentStatus |= FEATURE_REMOTE_WAKEUP_ENABLED;
+ #endif
+ break;
+ case (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_ENDPOINT):
+ #if !defined(CONTROL_ONLY_DEVICE)
+ Endpoint_SelectEndpoint((uint8_t)USB_ControlRequest.wIndex & ENDPOINT_EPNUM_MASK);
+
+ CurrentStatus = Endpoint_IsStalled();
+
+ Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);
+ #endif
+
+ break;
+ default:
+ return;
+ }
+
+ Endpoint_ClearSETUP();
+
+ Endpoint_Write_16_LE(CurrentStatus);
+ Endpoint_ClearIN();
+
+ Endpoint_ClearStatusStage();
+}
+
+static void USB_Device_ClearSetFeature(void)
+{
+ switch (USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_RECIPIENT)
+ {
+ #if !defined(NO_DEVICE_REMOTE_WAKEUP)
+ case REQREC_DEVICE:
+ if ((uint8_t)USB_ControlRequest.wValue == FEATURE_SEL_DeviceRemoteWakeup)
+ USB_Device_RemoteWakeupEnabled = (USB_ControlRequest.bRequest == REQ_SetFeature);
+ else
+ return;
+
+ break;
+ #endif
+ #if !defined(CONTROL_ONLY_DEVICE)
+ case REQREC_ENDPOINT:
+ if ((uint8_t)USB_ControlRequest.wValue == FEATURE_SEL_EndpointHalt)
+ {
+ uint8_t EndpointIndex = ((uint8_t)USB_ControlRequest.wIndex & ENDPOINT_EPNUM_MASK);
+
+ if (EndpointIndex == ENDPOINT_CONTROLEP)
+ return;
+
+ Endpoint_SelectEndpoint(EndpointIndex);
+
+ if (Endpoint_IsEnabled())
+ {
+ if (USB_ControlRequest.bRequest == REQ_SetFeature)
+ {
+ Endpoint_StallTransaction();
+ }
+ else
+ {
+ Endpoint_ClearStall();
+ Endpoint_ResetEndpoint(EndpointIndex);
+ Endpoint_ResetDataToggle();
+ }
+ }
+ }
+
+ break;
+ #endif
+ default:
+ return;
+ }
+
+ Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);
+
+ Endpoint_ClearSETUP();
+
+ Endpoint_ClearStatusStage();
+}
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/DeviceStandardReq.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/DeviceStandardReq.h
new file mode 100644
index 000000000..396e20554
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/DeviceStandardReq.h
@@ -0,0 +1,158 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief USB device standard request management.
+ *
+ * This file contains the function prototypes necessary for the processing of incoming standard control requests
+ * when the library is in USB device mode.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+#ifndef __DEVICESTDREQ_H__
+#define __DEVICESTDREQ_H__
+
+ /* Includes: */
+ #include "../../../Common/Common.h"
+ #include "USBMode.h"
+ #include "StdDescriptors.h"
+ #include "Events.h"
+ #include "StdRequestType.h"
+ #include "USBTask.h"
+ #include "USBController.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Enums: */
+ #if defined(ARCH_HAS_MULTI_ADDRESS_SPACE) || defined(__DOXYGEN__)
+ /** Enum for the possible descriptor memory spaces, for the \c MemoryAddressSpace parameter of the
+ * \ref CALLBACK_USB_GetDescriptor() function. This can be used when none of the \c USE_*_DESCRIPTORS
+ * compile time options are used, to indicate in which memory space the descriptor is stored.
+ *
+ * \ingroup Group_Device
+ */
+ enum USB_DescriptorMemorySpaces_t
+ {
+ #if defined(ARCH_HAS_FLASH_ADDRESS_SPACE) || defined(__DOXYGEN__)
+ MEMSPACE_FLASH = 0, /**< Indicates the requested descriptor is located in FLASH memory. */
+ #endif
+ #if defined(ARCH_HAS_EEPROM_ADDRESS_SPACE) || defined(__DOXYGEN__)
+ MEMSPACE_EEPROM = 1, /**< Indicates the requested descriptor is located in EEPROM memory. */
+ #endif
+ MEMSPACE_RAM = 2, /**< Indicates the requested descriptor is located in RAM memory. */
+ };
+ #endif
+
+ /* Global Variables: */
+ /** Indicates the currently set configuration number of the device. USB devices may have several
+ * different configurations which the host can select between; this indicates the currently selected
+ * value, or 0 if no configuration has been selected.
+ *
+ * \attention This variable should be treated as read-only in the user application, and never manually
+ * changed in value.
+ *
+ * \ingroup Group_Device
+ */
+ extern uint8_t USB_Device_ConfigurationNumber;
+
+ #if !defined(NO_DEVICE_REMOTE_WAKEUP)
+ /** Indicates if the host is currently allowing the device to issue remote wakeup events. If this
+ * flag is cleared, the device should not issue remote wakeup events to the host.
+ *
+ * \attention This variable should be treated as read-only in the user application, and never manually
+ * changed in value.
+ *
+ * \note To reduce FLASH usage of the compiled applications where Remote Wakeup is not supported,
+ * this global and the underlying management code can be disabled by defining the
+ * \c NO_DEVICE_REMOTE_WAKEUP token in the project makefile and passing it to the compiler via
+ * the -D switch.
+ *
+ * \ingroup Group_Device
+ */
+ extern bool USB_Device_RemoteWakeupEnabled;
+ #endif
+
+ #if !defined(NO_DEVICE_SELF_POWER)
+ /** Indicates if the device is currently being powered by its own power supply, rather than being
+ * powered by the host's USB supply. This flag should remain cleared if the device does not
+ * support self powered mode, as indicated in the device descriptors.
+ *
+ * \ingroup Group_Device
+ */
+ extern bool USB_Device_CurrentlySelfPowered;
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ #if defined(USE_RAM_DESCRIPTORS) && defined(USE_EEPROM_DESCRIPTORS)
+ #error USE_RAM_DESCRIPTORS and USE_EEPROM_DESCRIPTORS are mutually exclusive.
+ #elif defined(USE_RAM_DESCRIPTORS) && defined(USE_FLASH_DESCRIPTORS)
+ #error USE_RAM_DESCRIPTORS and USE_FLASH_DESCRIPTORS are mutually exclusive.
+ #elif defined(USE_FLASH_DESCRIPTORS) && defined(USE_EEPROM_DESCRIPTORS)
+ #error USE_FLASH_DESCRIPTORS and USE_EEPROM_DESCRIPTORS are mutually exclusive.
+ #elif defined(USE_FLASH_DESCRIPTORS) && defined(USE_EEPROM_DESCRIPTORS) && defined(USE_RAM_DESCRIPTORS)
+ #error Only one of the USE_*_DESCRIPTORS modes should be selected.
+ #endif
+
+ /* Function Prototypes: */
+ void USB_Device_ProcessControlRequest(void);
+
+ #if defined(__INCLUDE_FROM_DEVICESTDREQ_C)
+ static void USB_Device_SetAddress(void);
+ static void USB_Device_SetConfiguration(void);
+ static void USB_Device_GetConfiguration(void);
+ static void USB_Device_GetDescriptor(void);
+ static void USB_Device_GetStatus(void);
+ static void USB_Device_ClearSetFeature(void);
+
+ #if !defined(NO_INTERNAL_SERIAL) && (USE_INTERNAL_SERIAL != NO_DESCRIPTOR)
+ static void USB_Device_GetInternalSerialDescriptor(void);
+ #endif
+ #endif
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/Endpoint.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/Endpoint.h
new file mode 100644
index 000000000..bf41376f4
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/Endpoint.h
@@ -0,0 +1,130 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief USB Endpoint definitions for all architectures.
+ * \copydetails Group_EndpointManagement
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_EndpointManagement
+ * \defgroup Group_EndpointRW Endpoint Data Reading and Writing
+ * \brief Endpoint data read/write definitions.
+ *
+ * Functions, macros, variables, enums and types related to data reading and writing from and to endpoints.
+ */
+
+/** \ingroup Group_EndpointRW
+ * \defgroup Group_EndpointPrimitiveRW Read/Write of Primitive Data Types
+ * \brief Endpoint data primitive read/write definitions.
+ *
+ * Functions, macros, variables, enums and types related to data reading and writing of primitive data types
+ * from and to endpoints.
+ */
+
+/** \ingroup Group_EndpointManagement
+ * \defgroup Group_EndpointPacketManagement Endpoint Packet Management
+ * \brief USB Endpoint package management definitions.
+ *
+ * Functions, macros, variables, enums and types related to packet management of endpoints.
+ */
+
+/** \ingroup Group_USB
+ * \defgroup Group_EndpointManagement Endpoint Management
+ * \brief Endpoint management definitions.
+ *
+ * Functions, macros and enums related to endpoint management when in USB Device mode. This
+ * module contains the endpoint management macros, as well as endpoint interrupt and data
+ * send/receive functions for various data types.
+ *
+ * @{
+ */
+
+#ifndef __ENDPOINT_H__
+#define __ENDPOINT_H__
+
+ /* Includes: */
+ #include "../../../Common/Common.h"
+ #include "USBMode.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Type Defines: */
+ /** Type define for a endpoint table entry, used to configure endpoints in groups via
+ * \ref Endpoint_ConfigureEndpointTable().
+ */
+ typedef struct
+ {
+ uint8_t Address; /**< Address of the endpoint to configure, or zero if the table entry is to be unused. */
+ uint16_t Size; /**< Size of the endpoint bank, in bytes. */
+ uint8_t Type; /**< Type of the endpoint, a \c EP_TYPE_* mask. */
+ uint8_t Banks; /**< Number of hardware banks to use for the endpoint. */
+ } USB_Endpoint_Table_t;
+
+ /* Macros: */
+ /** Endpoint number mask, for masking against endpoint addresses to retrieve the endpoint's
+ * numerical address in the device.
+ */
+ #define ENDPOINT_EPNUM_MASK 0x0F
+
+ /** Endpoint address for the default control endpoint, which always resides in address 0. This is
+ * defined for convenience to give more readable code when used with the endpoint macros.
+ */
+ #define ENDPOINT_CONTROLEP 0
+
+ /* Architecture Includes: */
+ #if (ARCH == ARCH_AVR8)
+ #include "AVR8/Endpoint_AVR8.h"
+ #elif (ARCH == ARCH_UC3)
+ #include "UC3/Endpoint_UC3.h"
+ #elif (ARCH == ARCH_XMEGA)
+ #include "XMEGA/Endpoint_XMEGA.h"
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/EndpointStream.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/EndpointStream.h
new file mode 100644
index 000000000..5675c323c
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/EndpointStream.h
@@ -0,0 +1,124 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Endpoint data stream transmission and reception management.
+ * \copydetails Group_EndpointStreamRW
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_EndpointRW
+ * \defgroup Group_EndpointStreamRW Read/Write of Multi-Byte Streams
+ * \brief Endpoint data stream transmission and reception management.
+ *
+ * Functions, macros, variables, enums and types related to data reading and writing of data streams from
+ * and to endpoints.
+ *
+ * @{
+ */
+
+#ifndef __ENDPOINT_STREAM_H__
+#define __ENDPOINT_STREAM_H__
+
+ /* Includes: */
+ #include "../../../Common/Common.h"
+ #include "USBMode.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Enums: */
+ /** Enum for the possible error return codes of the \c Endpoint_*_Stream_* functions. */
+ enum Endpoint_Stream_RW_ErrorCodes_t
+ {
+ ENDPOINT_RWSTREAM_NoError = 0, /**< Command completed successfully, no error. */
+ ENDPOINT_RWSTREAM_EndpointStalled = 1, /**< The endpoint was stalled during the stream
+ * transfer by the host or device.
+ */
+ ENDPOINT_RWSTREAM_DeviceDisconnected = 2, /**< Device was disconnected from the host during
+ * the transfer.
+ */
+ ENDPOINT_RWSTREAM_BusSuspended = 3, /**< The USB bus has been suspended by the host and
+ * no USB endpoint traffic can occur until the bus
+ * has resumed.
+ */
+ ENDPOINT_RWSTREAM_Timeout = 4, /**< The host failed to accept or send the next packet
+ * within the software timeout period set by the
+ * \ref USB_STREAM_TIMEOUT_MS macro.
+ */
+ ENDPOINT_RWSTREAM_IncompleteTransfer = 5, /**< Indicates that the endpoint bank became full or empty before
+ * the complete contents of the current stream could be
+ * transferred. The endpoint stream function should be called
+ * again to process the next chunk of data in the transfer.
+ */
+ };
+
+ /** Enum for the possible error return codes of the \c Endpoint_*_Control_Stream_* functions. */
+ enum Endpoint_ControlStream_RW_ErrorCodes_t
+ {
+ ENDPOINT_RWCSTREAM_NoError = 0, /**< Command completed successfully, no error. */
+ ENDPOINT_RWCSTREAM_HostAborted = 1, /**< The aborted the transfer prematurely. */
+ ENDPOINT_RWCSTREAM_DeviceDisconnected = 2, /**< Device was disconnected from the host during
+ * the transfer.
+ */
+ ENDPOINT_RWCSTREAM_BusSuspended = 3, /**< The USB bus has been suspended by the host and
+ * no USB endpoint traffic can occur until the bus
+ * has resumed.
+ */
+ };
+
+ /* Architecture Includes: */
+ #if (ARCH == ARCH_AVR8)
+ #include "AVR8/EndpointStream_AVR8.h"
+ #elif (ARCH == ARCH_UC3)
+ #include "UC3/EndpointStream_UC3.h"
+ #elif (ARCH == ARCH_XMEGA)
+ #include "XMEGA/EndpointStream_XMEGA.h"
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/Events.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/Events.c
new file mode 100644
index 000000000..a63b002fe
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/Events.c
@@ -0,0 +1,39 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#define __INCLUDE_FROM_EVENTS_C
+#define __INCLUDE_FROM_USB_DRIVER
+#include "Events.h"
+
+void USB_Event_Stub(void)
+{
+
+}
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/Events.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/Events.h
new file mode 100644
index 000000000..9c85112fb
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/Events.h
@@ -0,0 +1,372 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief USB Event management definitions.
+ * \copydetails Group_Events
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_USB
+ * \defgroup Group_Events USB Events
+ * \brief USB Event management definitions.
+ *
+ * This module contains macros and functions relating to the management of library events, which are small
+ * pieces of code similar to ISRs which are run when a given condition is met. Each event can be fired from
+ * multiple places in the user or library code, which may or may not be inside an ISR, thus each handler
+ * should be written to be as small and fast as possible to prevent possible problems.
+ *
+ * Events can be hooked by the user application by declaring a handler function with the same name and parameters
+ * listed here. If an event with no user-associated handler is fired within the library, it by default maps to an
+ * internal empty stub function.
+ *
+ * Each event must only have one associated event handler, but can be raised by multiple sources by calling the
+ * event handler function (with any required event parameters).
+ *
+ * @{
+ */
+
+#ifndef __USBEVENTS_H__
+#define __USBEVENTS_H__
+
+ /* Includes: */
+ #include "../../../Common/Common.h"
+ #include "USBMode.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Pseudo-Functions for Doxygen: */
+ #if !defined(__INCLUDE_FROM_EVENTS_C) || defined(__DOXYGEN__)
+ /** Event for USB mode pin level change. This event fires when the USB interface is set to dual role
+ * mode, and the UID pin level has changed to indicate a new mode (device or host). This event fires
+ * before the mode is switched to the newly indicated mode but after the \ref EVENT_USB_Device_Disconnect
+ * event has fired (if disconnected before the role change).
+ *
+ * \note This event only exists on microcontrollers that support dual role USB modes.
+ * \n\n
+ *
+ * \note This event does not exist if the \c USB_DEVICE_ONLY or \c USB_HOST_ONLY tokens have been supplied
+ * to the compiler (see \ref Group_USBManagement documentation).
+ */
+ void EVENT_USB_UIDChange(void);
+
+ /** Event for USB host error. This event fires when a hardware fault has occurred whilst the USB
+ * interface is in host mode.
+ *
+ * \param[in] ErrorCode Error code indicating the failure reason, a value in \ref USB_Host_ErrorCodes_t.
+ *
+ * \note This event only exists on microcontrollers that supports USB host mode.
+ * \n\n
+ *
+ * \note This event does not exist if the \c USB_DEVICE_ONLY token is supplied to the compiler (see
+ * \ref Group_USBManagement documentation).
+ */
+ void EVENT_USB_Host_HostError(const uint8_t ErrorCode);
+
+ /** Event for USB device attachment. This event fires when a the USB interface is in host mode, and
+ * a USB device has been connected to the USB interface. This is interrupt driven, thus fires before
+ * the standard \ref EVENT_USB_Device_Connect() event and so can be used to programmatically start the USB
+ * management task to reduce CPU consumption.
+ *
+ * \note This event only exists on microcontrollers that supports USB host mode.
+ * \n\n
+ *
+ * \note This event does not exist if the \c USB_DEVICE_ONLY token is supplied to the compiler (see
+ * \ref Group_USBManagement documentation).
+ *
+ * \see \ref USB_USBTask() for more information on the USB management task and reducing CPU usage.
+ */
+ void EVENT_USB_Host_DeviceAttached(void);
+
+ /** Event for USB device removal. This event fires when a the USB interface is in host mode, and
+ * a USB device has been removed the USB interface whether or not it has been enumerated. This
+ * can be used to programmatically stop the USB management task to reduce CPU consumption.
+ *
+ * \note This event only exists on microcontrollers that supports USB host mode.
+ * \n\n
+ *
+ * \note This event does not exist if the \c USB_DEVICE_ONLY token is supplied to the compiler (see
+ * \ref Group_USBManagement documentation).
+ *
+ * \see \ref USB_USBTask() for more information on the USB management task and reducing CPU usage.
+ */
+ void EVENT_USB_Host_DeviceUnattached(void);
+
+ /** Event for USB device enumeration failure. This event fires when a the USB interface is
+ * in host mode, and an attached USB device has failed to enumerate completely.
+ *
+ * \param[in] ErrorCode Error code indicating the failure reason, a value in
+ * \ref USB_Host_EnumerationErrorCodes_t.
+ *
+ * \param[in] SubErrorCode Sub error code indicating the reason for failure - for example, if the
+ * ErrorCode parameter indicates a control error, this will give the error
+ * code returned by the \ref USB_Host_SendControlRequest() function.
+ *
+ * \note This event only exists on microcontrollers that supports USB host mode.
+ * \n\n
+ *
+ * \note This event does not exist if the \c USB_DEVICE_ONLY token is supplied to the compiler (see
+ * \ref Group_USBManagement documentation).
+ */
+ void EVENT_USB_Host_DeviceEnumerationFailed(const uint8_t ErrorCode,
+ const uint8_t SubErrorCode);
+
+ /** Event for USB device enumeration completion. This event fires when a the USB interface is
+ * in host mode and an attached USB device has been completely enumerated and is ready to be
+ * controlled by the user application.
+ *
+ * This event is time-critical; exceeding OS-specific delays within this event handler (typically of around
+ * 1 second) when a transaction is waiting to be processed by the device will prevent break communications
+ * and cause the host to reset the USB bus.
+ *
+ * \note This event only exists on microcontrollers that supports USB host mode.
+ * \n\n
+ *
+ * \note This event does not exist if the \c USB_DEVICE_ONLY token is supplied to the compiler (see
+ * \ref Group_USBManagement documentation).
+ */
+ void EVENT_USB_Host_DeviceEnumerationComplete(void);
+
+ /** Event for USB Start Of Frame detection, when enabled. This event fires at the start of each USB
+ * frame, once per millisecond, and is synchronized to the USB bus. This can be used as an accurate
+ * millisecond timer source when the USB bus is not suspended while in host mode.
+ *
+ * This event is time-critical; it is run once per millisecond and thus long handlers will significantly
+ * degrade device performance. This event should only be enabled when needed to reduce device wake-ups.
+ *
+ * \note This event is not normally active - it must be manually enabled and disabled via the
+ * \ref USB_Host_EnableSOFEvents() and \ref USB_Host_DisableSOFEvents() commands after enumeration of
+ * a USB device.
+ * \n\n
+ *
+ * \note This event does not exist if the \c USB_DEVICE_ONLY token is supplied to the compiler (see
+ * \ref Group_USBManagement documentation).
+ */
+ void EVENT_USB_Host_StartOfFrame(void);
+
+ /** Event for USB device connection. This event fires when the microcontroller is in USB Device mode
+ * and the device is connected to a USB host, beginning the enumeration process measured by a rising
+ * level on the microcontroller's VBUS sense pin.
+ *
+ * This event is time-critical; exceeding OS-specific delays within this event handler (typically of around
+ * two seconds) will prevent the device from enumerating correctly.
+ *
+ * \attention This event may fire multiple times during device enumeration on the microcontrollers with limited USB controllers
+ * if \c NO_LIMITED_CONTROLLER_CONNECT is not defined.
+ *
+ * \note For the microcontrollers with limited USB controller functionality, VBUS sensing is not available.
+ * this means that the current connection state is derived from the bus suspension and wake up events by default,
+ * which is not always accurate (host may suspend the bus while still connected). If the actual connection state
+ * needs to be determined, VBUS should be routed to an external pin, and the auto-detect behavior turned off by
+ * passing the \c NO_LIMITED_CONTROLLER_CONNECT token to the compiler via the -D switch at compile time. The connection
+ * and disconnection events may be manually fired, and the \ref USB_DeviceState global changed manually.
+ * \n\n
+ *
+ * \see \ref Group_USBManagement for more information on the USB management task and reducing CPU usage.
+ */
+ void EVENT_USB_Device_Connect(void);
+
+ /** Event for USB device disconnection. This event fires when the microcontroller is in USB Device mode and the device is
+ * disconnected from a host, measured by a falling level on the microcontroller's VBUS sense pin.
+ *
+ * \attention This event may fire multiple times during device enumeration on the microcontrollers with limited USB controllers
+ * if \c NO_LIMITED_CONTROLLER_CONNECT is not defined.
+ *
+ * \note For the microcontrollers with limited USB controllers, VBUS sense is not available to the USB controller.
+ * this means that the current connection state is derived from the bus suspension and wake up events by default,
+ * which is not always accurate (host may suspend the bus while still connected). If the actual connection state
+ * needs to be determined, VBUS should be routed to an external pin, and the auto-detect behavior turned off by
+ * passing the \c NO_LIMITED_CONTROLLER_CONNECT token to the compiler via the -D switch at compile time. The connection
+ * and disconnection events may be manually fired, and the \ref USB_DeviceState global changed manually.
+ * \n\n
+ *
+ * \see \ref Group_USBManagement for more information on the USB management task and reducing CPU usage.
+ */
+ void EVENT_USB_Device_Disconnect(void);
+
+ /** Event for control requests. This event fires when a the USB host issues a control request
+ * to the mandatory device control endpoint (of address 0). This may either be a standard
+ * request that the library may have a handler code for internally, or a class specific request
+ * issued to the device which must be handled appropriately. If a request is not processed in the
+ * user application via this event, it will be passed to the library for processing internally
+ * if a suitable handler exists.
+ *
+ * This event is time-critical; each packet within the request transaction must be acknowledged or
+ * sent within 50ms or the host will abort the transfer.
+ *
+ * The library internally handles all standard control requests with the exceptions of SYNC FRAME,
+ * SET DESCRIPTOR and SET INTERFACE. These and all other non-standard control requests will be left
+ * for the user to process via this event if desired. If not handled in the user application or by
+ * the library internally, unknown requests are automatically STALLed.
+ *
+ * \note This event does not exist if the \c USB_HOST_ONLY token is supplied to the compiler (see
+ * \ref Group_USBManagement documentation).
+ * \n\n
+ *
+ * \note Requests should be handled in the same manner as described in the USB 2.0 Specification,
+ * or appropriate class specification. In all instances, the library has already read the
+ * request SETUP parameters into the \ref USB_ControlRequest structure which should then be used
+ * by the application to determine how to handle the issued request.
+ */
+ void EVENT_USB_Device_ControlRequest(void);
+
+ /** Event for USB configuration number changed. This event fires when a the USB host changes the
+ * selected configuration number while in device mode. This event should be hooked in device
+ * applications to create the endpoints and configure the device for the selected configuration.
+ *
+ * This event is time-critical; exceeding OS-specific delays within this event handler (typically of around
+ * one second) will prevent the device from enumerating correctly.
+ *
+ * This event fires after the value of \ref USB_Device_ConfigurationNumber has been changed.
+ *
+ * \note This event does not exist if the \c USB_HOST_ONLY token is supplied to the compiler (see
+ * \ref Group_USBManagement documentation).
+ */
+ void EVENT_USB_Device_ConfigurationChanged(void);
+
+ /** Event for USB suspend. This event fires when a the USB host suspends the device by halting its
+ * transmission of Start Of Frame pulses to the device. This is generally hooked in order to move
+ * the device over to a low power state until the host wakes up the device. If the USB interface is
+ * enumerated with the \ref USB_OPT_AUTO_PLL option set, the library will automatically suspend the
+ * USB PLL before the event is fired to save power.
+ *
+ * \note This event does not exist if the \c USB_HOST_ONLY token is supplied to the compiler (see
+ * \ref Group_USBManagement documentation).
+ * \n\n
+ *
+ * \note This event does not exist on the microcontrollers with limited USB VBUS sensing abilities
+ * when the \c NO_LIMITED_CONTROLLER_CONNECT compile time token is not set - see
+ * \ref EVENT_USB_Device_Disconnect.
+ *
+ * \see \ref EVENT_USB_Device_WakeUp() event for accompanying Wake Up event.
+ */
+ void EVENT_USB_Device_Suspend(void);
+
+ /** Event for USB wake up. This event fires when a the USB interface is suspended while in device
+ * mode, and the host wakes up the device by supplying Start Of Frame pulses. This is generally
+ * hooked to pull the user application out of a low power state and back into normal operating
+ * mode. If the USB interface is enumerated with the \ref USB_OPT_AUTO_PLL option set, the library
+ * will automatically restart the USB PLL before the event is fired.
+ *
+ * \note This event does not exist if the \c USB_HOST_ONLY token is supplied to the compiler (see
+ * \ref Group_USBManagement documentation).
+ * \n\n
+ *
+ * \note This event does not exist on the microcontrollers with limited USB VBUS sensing abilities
+ * when the \c NO_LIMITED_CONTROLLER_CONNECT compile time token is not set - see
+ * \ref EVENT_USB_Device_Disconnect.
+ *
+ * \see \ref EVENT_USB_Device_Suspend() event for accompanying Suspend event.
+ */
+ void EVENT_USB_Device_WakeUp(void);
+
+ /** Event for USB interface reset. This event fires when the USB interface is in device mode, and
+ * a the USB host requests that the device reset its interface. This event fires after the control
+ * endpoint has been automatically configured by the library.
+ *
+ * This event is time-critical; exceeding OS-specific delays within this event handler (typically of around
+ * two seconds) will prevent the device from enumerating correctly.
+ *
+ * \note This event does not exist if the \c USB_HOST_ONLY token is supplied to the compiler (see
+ * \ref Group_USBManagement documentation).
+ */
+ void EVENT_USB_Device_Reset(void);
+
+ /** Event for USB Start Of Frame detection, when enabled. This event fires at the start of each USB
+ * frame, once per millisecond, and is synchronized to the USB bus. This can be used as an accurate
+ * millisecond timer source when the USB bus is enumerated in device mode to a USB host.
+ *
+ * This event is time-critical; it is run once per millisecond and thus long handlers will significantly
+ * degrade device performance. This event should only be enabled when needed to reduce device wake-ups.
+ *
+ * \pre This event is not normally active - it must be manually enabled and disabled via the
+ * \ref USB_Device_EnableSOFEvents() and \ref USB_Device_DisableSOFEvents() commands after enumeration.
+ * \n\n
+ *
+ * \note This event does not exist if the \c USB_HOST_ONLY token is supplied to the compiler (see
+ * \ref Group_USBManagement documentation).
+ */
+ void EVENT_USB_Device_StartOfFrame(void);
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Function Prototypes: */
+ #if defined(__INCLUDE_FROM_EVENTS_C)
+ void USB_Event_Stub(void) ATTR_CONST;
+
+ #if defined(USB_CAN_BE_BOTH)
+ void EVENT_USB_UIDChange(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
+ #endif
+
+ #if defined(USB_CAN_BE_HOST)
+ void EVENT_USB_Host_HostError(const uint8_t ErrorCode) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
+ void EVENT_USB_Host_DeviceAttached(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
+ void EVENT_USB_Host_DeviceUnattached(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
+ void EVENT_USB_Host_DeviceEnumerationComplete(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
+ void EVENT_USB_Host_DeviceEnumerationFailed(const uint8_t ErrorCode,
+ const uint8_t SubErrorCode)
+ ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
+ void EVENT_USB_Host_StartOfFrame(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
+ #endif
+
+ #if defined(USB_CAN_BE_DEVICE)
+ void EVENT_USB_Device_Connect(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
+ void EVENT_USB_Device_Disconnect(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
+ void EVENT_USB_Device_ControlRequest(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
+ void EVENT_USB_Device_ConfigurationChanged(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
+ void EVENT_USB_Device_Suspend(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
+ void EVENT_USB_Device_WakeUp(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
+ void EVENT_USB_Device_Reset(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
+ void EVENT_USB_Device_StartOfFrame(void) ATTR_WEAK ATTR_ALIAS(USB_Event_Stub);
+ #endif
+ #endif
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/Host.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/Host.h
new file mode 100644
index 000000000..6146cc5ae
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/Host.h
@@ -0,0 +1,139 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Common USB Host definitions for all architectures.
+ * \copydetails Group_Host
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_USB
+ * \defgroup Group_Host Host Management
+ * \brief USB Host management definitions for USB host mode.
+ *
+ * USB Host mode related macros and enums. This module contains macros and enums which are used when
+ * the USB controller is initialized in host mode.
+ *
+ * @{
+ */
+
+#ifndef __USBHOST_H__
+#define __USBHOST_H__
+
+ /* Includes: */
+ #include "../../../Common/Common.h"
+ #include "USBMode.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Enums: */
+ /** Enum for the various states of the USB Host state machine.
+ *
+ * For information on each possible USB host state, refer to the USB 2.0 specification.
+ * Several of the USB host states are broken up further into multiple smaller sub-states,
+ * so that they can be internally implemented inside the library in an efficient manner.
+ *
+ * \see \ref USB_HostState, which stores the current host state machine state.
+ */
+ enum USB_Host_States_t
+ {
+ HOST_STATE_WaitForDevice = 0, /**< This state indicates that the stack is waiting for an interval
+ * to elapse before continuing with the next step of the device
+ * enumeration process.
+ */
+ HOST_STATE_Unattached = 1, /**< This state indicates that the host state machine is waiting for
+ * a device to be attached so that it can start the enumeration process.
+ */
+ HOST_STATE_Powered = 2, /**< This state indicates that a device has been attached, and the
+ * library's internals are being configured to begin the enumeration
+ * process.
+ */
+ HOST_STATE_Powered_WaitForDeviceSettle = 3, /**< This state indicates that the stack is waiting for the initial
+ * settling period to elapse before beginning the enumeration process.
+ */
+ HOST_STATE_Powered_WaitForConnect = 4, /**< This state indicates that the stack is waiting for a connection event
+ * from the USB controller to indicate a valid USB device has been attached
+ * to the bus and is ready to be enumerated.
+ */
+ HOST_STATE_Powered_DoReset = 5, /**< This state indicates that a valid USB device has been attached, and that
+ * it will now be reset to ensure it is ready for enumeration.
+ */
+ HOST_STATE_Powered_ConfigPipe = 6, /**< This state indicates that the attached device is currently powered and
+ * reset, and that the control pipe is now being configured by the stack.
+ */
+ HOST_STATE_Default = 7, /**< This state indicates that the stack is currently retrieving the control
+ * endpoint's size from the device, so that the control pipe can be altered
+ * to match.
+ */
+ HOST_STATE_Default_PostReset = 8, /**< This state indicates that the control pipe is being reconfigured to match
+ * the retrieved control endpoint size from the device, and the device's USB
+ * bus address is being set.
+ */
+ HOST_STATE_Default_PostAddressSet = 9, /**< This state indicates that the device's address has now been set, and the
+ * stack is has now completed the device enumeration process. This state causes
+ * the stack to change the current USB device address to that set for the
+ * connected device, before progressing to the \ref HOST_STATE_Addressed state
+ * ready for use in the user application.
+ */
+ HOST_STATE_Addressed = 10, /**< Indicates that the device has been enumerated and addressed, and is now waiting
+ * for the user application to configure the device ready for use.
+ */
+ HOST_STATE_Configured = 11, /**< Indicates that the device has been configured into a valid device configuration,
+ * ready for general use by the user application.
+ */
+ };
+
+ /* Architecture Includes: */
+ #if (ARCH == ARCH_AVR8)
+ #include "AVR8/Host_AVR8.h"
+ #elif (ARCH == ARCH_UC3)
+ #include "UC3/Host_UC3.h"
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/HostStandardReq.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/HostStandardReq.c
new file mode 100644
index 000000000..4a21ce73c
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/HostStandardReq.c
@@ -0,0 +1,322 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "USBMode.h"
+
+#if defined(USB_CAN_BE_HOST)
+
+#define __INCLUDE_FROM_HOSTSTDREQ_C
+#include "HostStandardReq.h"
+
+uint8_t USB_Host_ConfigurationNumber;
+
+static uint8_t USB_Host_SendControlRequest_PRV(void* const BufferPtr)
+{
+ uint8_t* DataStream = (uint8_t*)BufferPtr;
+ uint8_t ReturnStatus = HOST_SENDCONTROL_Successful;
+ uint16_t DataLen = USB_ControlRequest.wLength;
+
+ USB_Host_ResumeBus();
+
+ if ((ReturnStatus = USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful)
+ return ReturnStatus;
+
+ Pipe_SetPipeToken(PIPE_TOKEN_SETUP);
+ Pipe_ClearError();
+
+ Pipe_Unfreeze();
+
+ #if defined(ARCH_BIG_ENDIAN)
+ Pipe_Write_8(USB_ControlRequest.bmRequestType);
+ Pipe_Write_8(USB_ControlRequest.bRequest);
+ Pipe_Write_16_LE(USB_ControlRequest.wValue);
+ Pipe_Write_16_LE(USB_ControlRequest.wIndex);
+ Pipe_Write_16_LE(USB_ControlRequest.wLength);
+ #else
+ uint8_t* HeaderStream = (uint8_t*)&USB_ControlRequest;
+
+ for (uint8_t HeaderByte = 0; HeaderByte < sizeof(USB_Request_Header_t); HeaderByte++)
+ Pipe_Write_8(*(HeaderStream++));
+ #endif
+
+ Pipe_ClearSETUP();
+
+ if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_SetupSent)) != HOST_SENDCONTROL_Successful)
+ return ReturnStatus;
+
+ Pipe_Freeze();
+
+ if ((ReturnStatus = USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful)
+ return ReturnStatus;
+
+ if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_DIRECTION) == REQDIR_DEVICETOHOST)
+ {
+ Pipe_SetPipeToken(PIPE_TOKEN_IN);
+
+ if (DataStream != NULL)
+ {
+ while (DataLen)
+ {
+ Pipe_Unfreeze();
+
+ if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_InReceived)) != HOST_SENDCONTROL_Successful)
+ return ReturnStatus;
+
+ if (!(Pipe_BytesInPipe()))
+ DataLen = 0;
+
+ while (Pipe_BytesInPipe() && DataLen)
+ {
+ *(DataStream++) = Pipe_Read_8();
+ DataLen--;
+ }
+
+ Pipe_Freeze();
+ Pipe_ClearIN();
+ }
+ }
+
+ Pipe_SetPipeToken(PIPE_TOKEN_OUT);
+ Pipe_Unfreeze();
+
+ if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_OutReady)) != HOST_SENDCONTROL_Successful)
+ return ReturnStatus;
+
+ Pipe_ClearOUT();
+
+ if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_OutReady)) != HOST_SENDCONTROL_Successful)
+ return ReturnStatus;
+ }
+ else
+ {
+ if (DataStream != NULL)
+ {
+ Pipe_SetPipeToken(PIPE_TOKEN_OUT);
+ Pipe_Unfreeze();
+
+ while (DataLen)
+ {
+ if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_OutReady)) != HOST_SENDCONTROL_Successful)
+ return ReturnStatus;
+
+ while (DataLen && (Pipe_BytesInPipe() < USB_Host_ControlPipeSize))
+ {
+ Pipe_Write_8(*(DataStream++));
+ DataLen--;
+ }
+
+ Pipe_ClearOUT();
+ }
+
+ if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_OutReady)) != HOST_SENDCONTROL_Successful)
+ return ReturnStatus;
+
+ Pipe_Freeze();
+ }
+
+ Pipe_SetPipeToken(PIPE_TOKEN_IN);
+ Pipe_Unfreeze();
+
+ if ((ReturnStatus = USB_Host_WaitForIOS(USB_HOST_WAITFOR_InReceived)) != HOST_SENDCONTROL_Successful)
+ return ReturnStatus;
+
+ Pipe_ClearIN();
+ }
+
+ return ReturnStatus;
+}
+
+static uint8_t USB_Host_WaitForIOS(const uint8_t WaitType)
+{
+ #if (USB_HOST_TIMEOUT_MS < 0xFF)
+ uint8_t TimeoutCounter = USB_HOST_TIMEOUT_MS;
+ #else
+ uint16_t TimeoutCounter = USB_HOST_TIMEOUT_MS;
+ #endif
+
+ while (!(((WaitType == USB_HOST_WAITFOR_SetupSent) && Pipe_IsSETUPSent()) ||
+ ((WaitType == USB_HOST_WAITFOR_InReceived) && Pipe_IsINReceived()) ||
+ ((WaitType == USB_HOST_WAITFOR_OutReady) && Pipe_IsOUTReady())))
+ {
+ uint8_t ErrorCode;
+
+ if ((ErrorCode = USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful)
+ return ErrorCode;
+
+ if (!(TimeoutCounter--))
+ return HOST_SENDCONTROL_SoftwareTimeOut;
+ }
+
+ return HOST_SENDCONTROL_Successful;
+}
+
+uint8_t USB_Host_SendControlRequest(void* const BufferPtr)
+{
+ bool BusSuspended = USB_Host_IsBusSuspended();
+ uint8_t ReturnStatus = USB_Host_SendControlRequest_PRV(BufferPtr);
+
+ Pipe_Freeze();
+
+ if (BusSuspended)
+ USB_Host_SuspendBus();
+
+ Pipe_ResetPipe(PIPE_CONTROLPIPE);
+
+ return ReturnStatus;
+}
+
+uint8_t USB_Host_SetDeviceConfiguration(const uint8_t ConfigNumber)
+{
+ uint8_t ErrorCode;
+
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE),
+ .bRequest = REQ_SetConfiguration,
+ .wValue = ConfigNumber,
+ .wIndex = 0,
+ .wLength = 0,
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+
+ if ((ErrorCode = USB_Host_SendControlRequest(NULL)) == HOST_SENDCONTROL_Successful)
+ {
+ USB_Host_ConfigurationNumber = ConfigNumber;
+ USB_HostState = (ConfigNumber) ? HOST_STATE_Configured : HOST_STATE_Addressed;
+ }
+
+ return ErrorCode;
+}
+
+uint8_t USB_Host_GetDeviceConfiguration(uint8_t* const ConfigNumber)
+{
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE),
+ .bRequest = REQ_GetConfiguration,
+ .wValue = 0,
+ .wIndex = 0,
+ .wLength = sizeof(uint8_t),
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+
+ return USB_Host_SendControlRequest(ConfigNumber);
+}
+
+uint8_t USB_Host_GetDescriptor(const uint8_t Type,
+ const uint8_t Index,
+ void* const Buffer,
+ const uint8_t BufferLength)
+{
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE),
+ .bRequest = REQ_GetDescriptor,
+ .wValue = (((uint16_t)Type << 8) | Index),
+ .wIndex = 0,
+ .wLength = BufferLength,
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+
+ return USB_Host_SendControlRequest(Buffer);
+}
+
+uint8_t USB_Host_GetDeviceStatus(uint8_t* const FeatureStatus)
+{
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE),
+ .bRequest = REQ_GetStatus,
+ .wValue = 0,
+ .wIndex = 0,
+ .wLength = 0,
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+
+ return USB_Host_SendControlRequest(FeatureStatus);
+}
+
+uint8_t USB_Host_ClearEndpointStall(const uint8_t EndpointAddress)
+{
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_ENDPOINT),
+ .bRequest = REQ_ClearFeature,
+ .wValue = FEATURE_SEL_EndpointHalt,
+ .wIndex = EndpointAddress,
+ .wLength = 0,
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+
+ return USB_Host_SendControlRequest(NULL);
+}
+
+uint8_t USB_Host_SetInterfaceAltSetting(const uint8_t InterfaceIndex,
+ const uint8_t AltSetting)
+{
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_INTERFACE),
+ .bRequest = REQ_SetInterface,
+ .wValue = AltSetting,
+ .wIndex = InterfaceIndex,
+ .wLength = 0,
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+
+ return USB_Host_SendControlRequest(NULL);
+}
+
+uint8_t USB_Host_GetInterfaceAltSetting(const uint8_t InterfaceIndex,
+ uint8_t* const AltSetting)
+{
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_INTERFACE),
+ .bRequest = REQ_GetInterface,
+ .wValue = 0,
+ .wIndex = InterfaceIndex,
+ .wLength = sizeof(uint8_t),
+ };
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+
+ return USB_Host_SendControlRequest(AltSetting);
+}
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/HostStandardReq.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/HostStandardReq.h
new file mode 100644
index 000000000..bd67bcb9e
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/HostStandardReq.h
@@ -0,0 +1,292 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief USB host standard request management.
+ *
+ * This file contains the function prototypes necessary for the issuing of outgoing standard control requests
+ * when the library is in USB host mode.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+#ifndef __HOSTSTDREQ_H__
+#define __HOSTSTDREQ_H__
+
+ /* Includes: */
+ #include "../../../Common/Common.h"
+ #include "USBMode.h"
+ #include "StdRequestType.h"
+ #include "USBController.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ #if !defined(USB_HOST_TIMEOUT_MS) || defined(__DOXYGEN__)
+ /** Constant for the maximum software timeout period of sent USB control transactions to an attached
+ * device. If a device fails to respond to a sent control request within this period, the
+ * library will return a timeout error code.
+ *
+ * This value may be overridden in the user project makefile as the value of the
+ * \ref USB_HOST_TIMEOUT_MS token, and passed to the compiler using the -D switch.
+ */
+ #define USB_HOST_TIMEOUT_MS 1000
+ #endif
+
+ /* Enums: */
+ /** Enum for the \ref USB_Host_SendControlRequest() return code, indicating the reason for the error
+ * if the transfer of the request is unsuccessful.
+ *
+ * \ingroup Group_PipeControlReq
+ */
+ enum USB_Host_SendControlErrorCodes_t
+ {
+ HOST_SENDCONTROL_Successful = 0, /**< No error occurred in the request transfer. */
+ HOST_SENDCONTROL_DeviceDisconnected = 1, /**< The attached device was disconnected during the
+ * request transfer.
+ */
+ HOST_SENDCONTROL_PipeError = 2, /**< An error occurred in the pipe while sending the request. */
+ HOST_SENDCONTROL_SetupStalled = 3, /**< The attached device stalled the request, usually
+ * indicating that the request is unsupported on the device.
+ */
+ HOST_SENDCONTROL_SoftwareTimeOut = 4, /**< The request or data transfer timed out. */
+ };
+
+ /* Global Variables: */
+ /** Indicates the currently set configuration number of the attached device. This indicates the currently
+ * selected configuration value if one has been set successfully, or 0 if no configuration has been selected.
+ *
+ * To set a device configuration, call the \ref USB_Host_SetDeviceConfiguration() function.
+ *
+ * \attention This variable should be treated as read-only in the user application, and never manually
+ * changed in value.
+ *
+ * \ingroup Group_Host
+ */
+ extern uint8_t USB_Host_ConfigurationNumber;
+
+ /* Function Prototypes: */
+ /** Sends the request stored in the \ref USB_ControlRequest global structure to the attached device,
+ * and transfers the data stored in the buffer to the device, or from the device to the buffer
+ * as requested. The transfer is made on the currently selected pipe.
+ *
+ * \ingroup Group_PipeControlReq
+ *
+ * \param[in] BufferPtr Pointer to the start of the data buffer if the request has a data stage, or
+ * \c NULL if the request transfers no data to or from the device.
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
+ */
+ uint8_t USB_Host_SendControlRequest(void* const BufferPtr);
+
+ /** Sends a SET CONFIGURATION standard request to the attached device, with the given configuration index.
+ *
+ * This routine will automatically update the \ref USB_HostState and \ref USB_Host_ConfigurationNumber
+ * state variables according to the given function parameters and the result of the request.
+ *
+ * \note After this routine returns, the control pipe will be selected.
+ *
+ * \ingroup Group_PipeControlReq
+ *
+ * \param[in] ConfigNumber Configuration index to send to the device.
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
+ */
+ uint8_t USB_Host_SetDeviceConfiguration(const uint8_t ConfigNumber);
+
+ /** Sends a GET CONFIGURATION standard request to the attached device, to retrieve the currently selected
+ * device configuration index.
+ *
+ * \note After this routine returns, the control pipe will be selected.
+ *
+ * \ingroup Group_PipeControlReq
+ *
+ * \param[out] ConfigNumber Pointer to a location where the retrieved configuration index should be stored.
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
+ */
+ uint8_t USB_Host_GetDeviceConfiguration(uint8_t* const ConfigNumber) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Sends a GET DESCRIPTOR standard request to the attached device, requesting the descriptor of the
+ * specified type and index.
+ *
+ * \note After this routine returns, the control pipe will be selected.
+ *
+ * \ingroup Group_PipeControlReq
+ *
+ * \param[in] Type Type of descriptor to retrieve, a value from the \ref USB_DescriptorTypes_t enum.
+ * \param[in] Index Index of the descriptor to retrieve.
+ * \param[out] Buffer Pointer to the destination buffer where the retrieved string descriptor is to be stored.
+ * \param[in] BufferLength Maximum size of the string descriptor which can be stored into the buffer.
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
+ */
+ uint8_t USB_Host_GetDescriptor(const uint8_t Type,
+ const uint8_t Index,
+ void* const Buffer,
+ const uint8_t BufferLength) ATTR_NON_NULL_PTR_ARG(3);
+
+ /** Retrieves the current feature status of the attached device, via a GET STATUS standard request. The
+ * retrieved feature status can then be examined by masking the retrieved value with the various
+ * \c FEATURE_* masks for bus/self power information and remote wakeup support.
+ *
+ * \note After this routine returns, the control pipe will be selected.
+ *
+ * \ingroup Group_PipeControlReq
+ *
+ * \param[out] FeatureStatus Location where the retrieved feature status should be stored.
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
+ */
+ uint8_t USB_Host_GetDeviceStatus(uint8_t* const FeatureStatus) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Clears a stall condition on the given pipe, via a CLEAR FEATURE standard request to the attached device.
+ *
+ * \note After this routine returns, the control pipe will be selected.
+ *
+ * \ingroup Group_PipeControlReq
+ *
+ * \param[in] EndpointAddress Address of the endpoint to clear, including the endpoint's direction.
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
+ */
+ uint8_t USB_Host_ClearEndpointStall(const uint8_t EndpointAddress);
+
+ /** Selects a given alternative setting for the specified interface, via a SET INTERFACE standard request to
+ * the attached device.
+ *
+ * \note After this routine returns, the control pipe will be selected.
+ *
+ * \ingroup Group_PipeControlReq
+ *
+ * \param[in] InterfaceIndex Index of the interface whose alternative setting is to be altered.
+ * \param[in] AltSetting Index of the interface's alternative setting which is to be selected.
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
+ */
+ uint8_t USB_Host_SetInterfaceAltSetting(const uint8_t InterfaceIndex,
+ const uint8_t AltSetting);
+
+
+ /** Retrieves the current alternative setting for the specified interface, via a GET INTERFACE standard request to
+ * the attached device.
+ *
+ * \note After this routine returns, the control pipe will be selected.
+ *
+ * \ingroup Group_PipeControlReq
+ *
+ * \param[in] InterfaceIndex Index of the interface whose alternative setting is to be altered.
+ * \param[out] AltSetting Pointer to a location where the retrieved alternative setting value should be stored.
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
+ */
+ uint8_t USB_Host_GetInterfaceAltSetting(const uint8_t InterfaceIndex,
+ uint8_t* const AltSetting) ATTR_NON_NULL_PTR_ARG(2);
+
+ /* Inline Functions: */
+ /** Sends a GET DESCRIPTOR standard request to the attached device, requesting the device descriptor.
+ * This can be used to easily retrieve information about the device such as its VID, PID and power
+ * requirements. This is a convenience wrapper for \ref USB_Host_GetDescriptor().
+ *
+ * \note After this routine returns, the control pipe will be selected.
+ *
+ * \ingroup Group_PipeControlReq
+ *
+ * \param[out] DeviceDescriptorPtr Pointer to the destination device descriptor structure where
+ * the read data is to be stored.
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
+ */
+ static inline uint8_t USB_Host_GetDeviceDescriptor(USB_Descriptor_Device_t* const DeviceDescriptorPtr) ATTR_NON_NULL_PTR_ARG(1);
+ static inline uint8_t USB_Host_GetDeviceDescriptor(USB_Descriptor_Device_t* const DeviceDescriptorPtr)
+ {
+ return USB_Host_GetDescriptor(DTYPE_Device, 0, DeviceDescriptorPtr, sizeof(USB_Descriptor_Device_t));
+ }
+
+ /** Sends a GET DESCRIPTOR standard request to the attached device, requesting the string descriptor
+ * of the specified index. This can be used to easily retrieve string descriptors from the device by
+ * index, after the index is obtained from the Device or Configuration descriptors. This is a convenience
+ * wrapper for \ref USB_Host_GetDescriptor().
+ *
+ * \note After this routine returns, the control pipe will be selected.
+ *
+ * \ingroup Group_PipeControlReq
+ *
+ * \param[in] Index Index of the string descriptor to retrieve.
+ * \param[out] Buffer Pointer to the destination buffer where the retrieved string descriptor is
+ * to be stored.
+ * \param[in] BufferLength Maximum size of the string descriptor which can be stored into the buffer.
+ *
+ * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result.
+ */
+ static inline uint8_t USB_Host_GetDeviceStringDescriptor(const uint8_t Index,
+ void* const Buffer,
+ const uint8_t BufferLength) ATTR_NON_NULL_PTR_ARG(2);
+ static inline uint8_t USB_Host_GetDeviceStringDescriptor(const uint8_t Index,
+ void* const Buffer,
+ const uint8_t BufferLength)
+ {
+ return USB_Host_GetDescriptor(DTYPE_String, Index, Buffer, BufferLength);
+ }
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Enums: */
+ enum USB_WaitForTypes_t
+ {
+ USB_HOST_WAITFOR_SetupSent,
+ USB_HOST_WAITFOR_InReceived,
+ USB_HOST_WAITFOR_OutReady,
+ };
+
+ /* Function Prototypes: */
+ #if defined(__INCLUDE_FROM_HOSTSTDREQ_C)
+ static uint8_t USB_Host_SendControlRequest_PRV(void* const BufferPtr);
+ static uint8_t USB_Host_WaitForIOS(const uint8_t WaitType);
+ #endif
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/OTG.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/OTG.h
new file mode 100644
index 000000000..58d47bace
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/OTG.h
@@ -0,0 +1,80 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Common USB OTG definitions for all architectures.
+ * \copydetails Group_OTG
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_USB
+ * \defgroup Group_OTG USB On The Go (OTG) Management
+ * \brief USB OTG management definitions.
+ *
+ * This module contains macros for embedded USB hosts with dual role On The Go capabilities, for managing role
+ * exchange. OTG is a way for two USB dual role devices to talk to one another directly without fixed device/host
+ * roles.
+ *
+ * @{
+ */
+
+#ifndef __USBOTG_H__
+#define __USBOTG_H__
+
+ /* Includes: */
+ #include "../../../Common/Common.h"
+ #include "USBMode.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Architecture Includes: */
+ #if (ARCH == ARCH_AVR8)
+ #include "AVR8/OTG_AVR8.h"
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/Pipe.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/Pipe.h
new file mode 100644
index 000000000..ca3fdbe7a
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/Pipe.h
@@ -0,0 +1,144 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Common USB Pipe definitions for all architectures.
+ * \copydetails Group_PipeManagement
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_PipeManagement
+ * \defgroup Group_PipeRW Pipe Data Reading and Writing
+ * \brief Pipe data read/write definitions.
+ *
+ * Functions, macros, variables, enums and types related to data reading and writing from and to pipes.
+ */
+
+/** \ingroup Group_PipeRW
+ * \defgroup Group_PipePrimitiveRW Read/Write of Primitive Data Types
+ * \brief Pipe data primitive read/write definitions.
+ *
+ * Functions, macros, variables, enums and types related to data reading and writing of primitive data types
+ * from and to pipes.
+ */
+
+/** \ingroup Group_PipeManagement
+ * \defgroup Group_PipePacketManagement Pipe Packet Management
+ * \brief Pipe packet management definitions.
+ *
+ * Functions, macros, variables, enums and types related to packet management of pipes.
+ */
+
+/** \ingroup Group_PipeManagement
+ * \defgroup Group_PipeControlReq Pipe Control Request Management
+ * \brief Pipe control request definitions.
+ *
+ * Module for host mode request processing. This module allows for the transmission of standard, class and
+ * vendor control requests to the default control endpoint of an attached device while in host mode.
+ *
+ * \see Chapter 9 of the USB 2.0 specification.
+ */
+
+/** \ingroup Group_USB
+ * \defgroup Group_PipeManagement Pipe Management
+ * \brief Pipe management definitions.
+ *
+ * This module contains functions, macros and enums related to pipe management when in USB Host mode. This
+ * module contains the pipe management macros, as well as pipe interrupt and data send/receive functions
+ * for various data types.
+ *
+ * @{
+ */
+
+#ifndef __PIPE_H__
+#define __PIPE_H__
+
+ /* Includes: */
+ #include "../../../Common/Common.h"
+ #include "USBMode.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Type Defines: */
+ /** Type define for a pipe table entry, used to configure pipes in groups via
+ * \ref Pipe_ConfigurePipeTable().
+ */
+ typedef struct
+ {
+ uint8_t Address; /**< Address of the pipe to configure, or zero if the table entry is to be unused. */
+ uint16_t Size; /**< Size of the pipe bank, in bytes. */
+ uint8_t EndpointAddress; /**< Address of the endpoint in the connected device. */
+ uint8_t Type; /**< Type of the endpoint, a \c EP_TYPE_* mask. */
+ uint8_t Banks; /**< Number of hardware banks to use for the pipe. */
+ } USB_Pipe_Table_t;
+
+ /* Macros: */
+ /** Pipe address for the default control pipe, which always resides in address 0. This is
+ * defined for convenience to give more readable code when used with the pipe macros.
+ */
+ #define PIPE_CONTROLPIPE 0
+
+ /** Pipe number mask, for masking against pipe addresses to retrieve the pipe's numerical address
+ * in the device.
+ */
+ #define PIPE_PIPENUM_MASK 0x0F
+
+ /** Endpoint number mask, for masking against endpoint addresses to retrieve the endpoint's
+ * numerical address in the attached device.
+ */
+ #define PIPE_EPNUM_MASK 0x0F
+
+ /* Architecture Includes: */
+ #if (ARCH == ARCH_AVR8)
+ #include "AVR8/Pipe_AVR8.h"
+ #elif (ARCH == ARCH_UC3)
+ #include "UC3/Pipe_UC3.h"
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/PipeStream.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/PipeStream.h
new file mode 100644
index 000000000..239969687
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/PipeStream.h
@@ -0,0 +1,100 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Pipe data stream transmission and reception management.
+ * \copydetails Group_PipeStreamRW
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_PipeRW
+ * \defgroup Group_PipeStreamRW Read/Write of Multi-Byte Streams
+ * \brief Pipe data stream transmission and reception management.
+ *
+ * Functions, macros, variables, enums and types related to data reading and writing of data streams from
+ * and to pipes.
+ *
+ * @{
+ */
+
+#ifndef __PIPE_STREAM_H__
+#define __PIPE_STREAM_H__
+
+ /* Includes: */
+ #include "../../../Common/Common.h"
+ #include "USBMode.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Enums: */
+ /** Enum for the possible error return codes of the Pipe_*_Stream_* functions. */
+ enum Pipe_Stream_RW_ErrorCodes_t
+ {
+ PIPE_RWSTREAM_NoError = 0, /**< Command completed successfully, no error. */
+ PIPE_RWSTREAM_PipeStalled = 1, /**< The device stalled the pipe during the transfer. */
+ PIPE_RWSTREAM_DeviceDisconnected = 2, /**< Device was disconnected from the host during
+ * the transfer.
+ */
+ PIPE_RWSTREAM_Timeout = 3, /**< The device failed to accept or send the next packet
+ * within the software timeout period set by the
+ * \ref USB_STREAM_TIMEOUT_MS macro.
+ */
+ PIPE_RWSTREAM_IncompleteTransfer = 4, /**< Indicates that the pipe bank became full/empty before the
+ * complete contents of the stream could be transferred.
+ */
+ };
+
+ /* Architecture Includes: */
+ #if (ARCH == ARCH_AVR8)
+ #include "AVR8/PipeStream_AVR8.h"
+ #elif (ARCH == ARCH_UC3)
+ #include "UC3/PipeStream_UC3.h"
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/StdDescriptors.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/StdDescriptors.h
new file mode 100644
index 000000000..e0a1a37f4
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/StdDescriptors.h
@@ -0,0 +1,765 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Common standard USB Descriptor definitions for all architectures.
+ * \copydetails Group_StdDescriptors
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_USB
+ * \defgroup Group_StdDescriptors USB Descriptors
+ * \brief Standard USB Descriptor definitions.
+ *
+ * Standard USB device descriptor defines and retrieval routines, for USB devices. This module contains
+ * structures and macros for the easy creation of standard USB descriptors in USB device projects.
+ *
+ * @{
+ */
+
+#ifndef __USBDESCRIPTORS_H__
+#define __USBDESCRIPTORS_H__
+
+ /* Includes: */
+ #include "../../../Common/Common.h"
+ #include "USBMode.h"
+ #include "Events.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates that a given descriptor does not exist in the device. This can be used inside descriptors
+ * for string descriptor indexes, or may be use as a return value for GetDescriptor when the specified
+ * descriptor does not exist.
+ */
+ #define NO_DESCRIPTOR 0
+
+ /** Macro to calculate the power value for the configuration descriptor, from a given number of milliamperes.
+ *
+ * \param[in] mA Maximum number of milliamps the device consumes when the given configuration is selected.
+ */
+ #define USB_CONFIG_POWER_MA(mA) ((mA) >> 1)
+
+ /** Macro to calculate the Unicode length of a string with a given number of Unicode characters.
+ * Should be used in string descriptor's headers for giving the string descriptor's byte length.
+ *
+ * \param[in] UnicodeChars Number of Unicode characters in the string text.
+ */
+ #define USB_STRING_LEN(UnicodeChars) (sizeof(USB_Descriptor_Header_t) + ((UnicodeChars) << 1))
+
+ /** Convenience macro to easily create \ref USB_Descriptor_String_t instances from a wide character string.
+ *
+ * \note This macro is for little-endian systems only.
+ *
+ * \param[in] String String to initialize a USB String Descriptor structure with.
+ */
+ #define USB_STRING_DESCRIPTOR(String) { .Header = {.Size = sizeof(USB_Descriptor_Header_t) + (sizeof(String) - 2), .Type = DTYPE_String}, .UnicodeString = String }
+
+ /** Convenience macro to easily create \ref USB_Descriptor_String_t instances from an array of characters.
+ *
+ * \param[in] ... Characters to initialize a USB String Descriptor structure with.
+ */
+ #define USB_STRING_DESCRIPTOR_ARRAY(...) { .Header = {.Size = sizeof(USB_Descriptor_Header_t) + sizeof((uint16_t){__VA_ARGS__}), .Type = DTYPE_String}, .UnicodeString = {__VA_ARGS__} }
+
+ /** Macro to encode a given major/minor/revision version number into Binary Coded Decimal format for descriptor
+ * fields requiring BCD encoding, such as the USB version number in the standard device descriptor.
+ *
+ * \note This value is automatically converted into Little Endian, suitable for direct use inside device
+ * descriptors on all architectures without endianness conversion macros.
+ *
+ * \param[in] Major Major version number to encode.
+ * \param[in] Minor Minor version number to encode.
+ * \param[in] Revision Revision version number to encode.
+ */
+ #define VERSION_BCD(Major, Minor, Revision) \
+ CPU_TO_LE16( ((Major & 0xFF) << 8) | \
+ ((Minor & 0x0F) << 4) | \
+ (Revision & 0x0F) )
+
+ /** String language ID for the English language. Should be used in \ref USB_Descriptor_String_t descriptors
+ * to indicate that the English language is supported by the device in its string descriptors.
+ */
+ #define LANGUAGE_ID_ENG 0x0409
+
+ /** \name USB Configuration Descriptor Attribute Masks */
+ //@{
+ /** Mask for the reserved bit in the Configuration Descriptor's \c ConfigAttributes field, which must be set on all
+ * devices for historical purposes.
+ */
+ #define USB_CONFIG_ATTR_RESERVED 0x80
+
+ /** Can be masked with other configuration descriptor attributes for a \ref USB_Descriptor_Configuration_Header_t
+ * descriptor's \c ConfigAttributes value to indicate that the specified configuration can draw its power
+ * from the device's own power source.
+ */
+ #define USB_CONFIG_ATTR_SELFPOWERED 0x40
+
+ /** Can be masked with other configuration descriptor attributes for a \ref USB_Descriptor_Configuration_Header_t
+ * descriptor's \c ConfigAttributes value to indicate that the specified configuration supports the
+ * remote wakeup feature of the USB standard, allowing a suspended USB device to wake up the host upon
+ * request.
+ */
+ #define USB_CONFIG_ATTR_REMOTEWAKEUP 0x20
+ //@}
+
+ /** \name Endpoint Descriptor Attribute Masks */
+ //@{
+ /** Can be masked with other endpoint descriptor attributes for a \ref USB_Descriptor_Endpoint_t descriptor's
+ * \c Attributes value to indicate that the specified endpoint is not synchronized.
+ *
+ * \see The USB specification for more details on the possible Endpoint attributes.
+ */
+ #define ENDPOINT_ATTR_NO_SYNC (0 << 2)
+
+ /** Can be masked with other endpoint descriptor attributes for a \ref USB_Descriptor_Endpoint_t descriptor's
+ * \c Attributes value to indicate that the specified endpoint is asynchronous.
+ *
+ * \see The USB specification for more details on the possible Endpoint attributes.
+ */
+ #define ENDPOINT_ATTR_ASYNC (1 << 2)
+
+ /** Can be masked with other endpoint descriptor attributes for a \ref USB_Descriptor_Endpoint_t descriptor's
+ * \c Attributes value to indicate that the specified endpoint is adaptive.
+ *
+ * \see The USB specification for more details on the possible Endpoint attributes.
+ */
+ #define ENDPOINT_ATTR_ADAPTIVE (2 << 2)
+
+ /** Can be masked with other endpoint descriptor attributes for a \ref USB_Descriptor_Endpoint_t descriptor's
+ * \c Attributes value to indicate that the specified endpoint is synchronized.
+ *
+ * \see The USB specification for more details on the possible Endpoint attributes.
+ */
+ #define ENDPOINT_ATTR_SYNC (3 << 2)
+ //@}
+
+ /** \name Endpoint Descriptor Usage Masks */
+ //@{
+ /** Can be masked with other endpoint descriptor attributes for a \ref USB_Descriptor_Endpoint_t descriptor's
+ * \c Attributes value to indicate that the specified endpoint is used for data transfers.
+ *
+ * \see The USB specification for more details on the possible Endpoint usage attributes.
+ */
+ #define ENDPOINT_USAGE_DATA (0 << 4)
+
+ /** Can be masked with other endpoint descriptor attributes for a \ref USB_Descriptor_Endpoint_t descriptor's
+ * \c Attributes value to indicate that the specified endpoint is used for feedback.
+ *
+ * \see The USB specification for more details on the possible Endpoint usage attributes.
+ */
+ #define ENDPOINT_USAGE_FEEDBACK (1 << 4)
+
+ /** Can be masked with other endpoint descriptor attributes for a \ref USB_Descriptor_Endpoint_t descriptor's
+ * \c Attributes value to indicate that the specified endpoint is used for implicit feedback.
+ *
+ * \see The USB specification for more details on the possible Endpoint usage attributes.
+ */
+ #define ENDPOINT_USAGE_IMPLICIT_FEEDBACK (2 << 4)
+ //@}
+
+ /* Enums: */
+ /** Enum for the possible standard descriptor types, as given in each descriptor's header. */
+ enum USB_DescriptorTypes_t
+ {
+ DTYPE_Device = 0x01, /**< Indicates that the descriptor is a device descriptor. */
+ DTYPE_Configuration = 0x02, /**< Indicates that the descriptor is a configuration descriptor. */
+ DTYPE_String = 0x03, /**< Indicates that the descriptor is a string descriptor. */
+ DTYPE_Interface = 0x04, /**< Indicates that the descriptor is an interface descriptor. */
+ DTYPE_Endpoint = 0x05, /**< Indicates that the descriptor is an endpoint descriptor. */
+ DTYPE_DeviceQualifier = 0x06, /**< Indicates that the descriptor is a device qualifier descriptor. */
+ DTYPE_Other = 0x07, /**< Indicates that the descriptor is of other type. */
+ DTYPE_InterfacePower = 0x08, /**< Indicates that the descriptor is an interface power descriptor. */
+ DTYPE_InterfaceAssociation = 0x0B, /**< Indicates that the descriptor is an interface association descriptor. */
+ DTYPE_CSInterface = 0x24, /**< Indicates that the descriptor is a class specific interface descriptor. */
+ DTYPE_CSEndpoint = 0x25, /**< Indicates that the descriptor is a class specific endpoint descriptor. */
+ };
+
+ /** Enum for possible Class, Subclass and Protocol values of device and interface descriptors. */
+ enum USB_Descriptor_ClassSubclassProtocol_t
+ {
+ USB_CSCP_NoDeviceClass = 0x00, /**< Descriptor Class value indicating that the device does not belong
+ * to a particular class at the device level.
+ */
+ USB_CSCP_NoDeviceSubclass = 0x00, /**< Descriptor Subclass value indicating that the device does not belong
+ * to a particular subclass at the device level.
+ */
+ USB_CSCP_NoDeviceProtocol = 0x00, /**< Descriptor Protocol value indicating that the device does not belong
+ * to a particular protocol at the device level.
+ */
+ USB_CSCP_VendorSpecificClass = 0xFF, /**< Descriptor Class value indicating that the device/interface belongs
+ * to a vendor specific class.
+ */
+ USB_CSCP_VendorSpecificSubclass = 0xFF, /**< Descriptor Subclass value indicating that the device/interface belongs
+ * to a vendor specific subclass.
+ */
+ USB_CSCP_VendorSpecificProtocol = 0xFF, /**< Descriptor Protocol value indicating that the device/interface belongs
+ * to a vendor specific protocol.
+ */
+ USB_CSCP_IADDeviceClass = 0xEF, /**< Descriptor Class value indicating that the device belongs to the
+ * Interface Association Descriptor class.
+ */
+ USB_CSCP_IADDeviceSubclass = 0x02, /**< Descriptor Subclass value indicating that the device belongs to the
+ * Interface Association Descriptor subclass.
+ */
+ USB_CSCP_IADDeviceProtocol = 0x01, /**< Descriptor Protocol value indicating that the device belongs to the
+ * Interface Association Descriptor protocol.
+ */
+ };
+
+ /* Type Defines: */
+ /** \brief Standard USB Descriptor Header (LUFA naming conventions).
+ *
+ * Type define for all descriptors' standard header, indicating the descriptor's length and type. This structure
+ * uses LUFA-specific element names to make each element's purpose clearer.
+ *
+ * \see \ref USB_StdDescriptor_Header_t for the version of this type with standard element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint8_t Size; /**< Size of the descriptor, in bytes. */
+ uint8_t Type; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
+ * given by the specific class.
+ */
+ } ATTR_PACKED USB_Descriptor_Header_t;
+
+ /** \brief Standard USB Descriptor Header (USB-IF naming conventions).
+ *
+ * Type define for all descriptors' standard header, indicating the descriptor's length and type. This structure
+ * uses the relevant standard's given element names to ensure compatibility with the standard.
+ *
+ * \see \ref USB_Descriptor_Header_t for the version of this type with non-standard LUFA specific element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint8_t bLength; /**< Size of the descriptor, in bytes. */
+ uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
+ * given by the specific class.
+ */
+ } ATTR_PACKED USB_StdDescriptor_Header_t;
+
+ /** \brief Standard USB Device Descriptor (LUFA naming conventions).
+ *
+ * Type define for a standard Device Descriptor. This structure uses LUFA-specific element names to make each
+ * element's purpose clearer.
+ *
+ * \see \ref USB_StdDescriptor_Device_t for the version of this type with standard element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Header_t Header; /**< Descriptor header, including type and size. */
+
+ uint16_t USBSpecification; /**< BCD of the supported USB specification.
+ *
+ * \see \ref VERSION_BCD() utility macro.
+ */
+ uint8_t Class; /**< USB device class. */
+ uint8_t SubClass; /**< USB device subclass. */
+ uint8_t Protocol; /**< USB device protocol. */
+
+ uint8_t Endpoint0Size; /**< Size of the control (address 0) endpoint's bank in bytes. */
+
+ uint16_t VendorID; /**< Vendor ID for the USB product. */
+ uint16_t ProductID; /**< Unique product ID for the USB product. */
+ uint16_t ReleaseNumber; /**< Product release (version) number.
+ *
+ * \see \ref VERSION_BCD() utility macro.
+ */
+ uint8_t ManufacturerStrIndex; /**< String index for the manufacturer's name. The
+ * host will request this string via a separate
+ * control request for the string descriptor.
+ *
+ * \note If no string supplied, use \ref NO_DESCRIPTOR.
+ */
+ uint8_t ProductStrIndex; /**< String index for the product name/details.
+ *
+ * \see ManufacturerStrIndex structure entry.
+ */
+ uint8_t SerialNumStrIndex; /**< String index for the product's globally unique hexadecimal
+ * serial number, in uppercase Unicode ASCII.
+ *
+ * \note On some microcontroller models, there is an embedded serial number
+ * in the chip which can be used for the device serial number.
+ * To use this serial number, set this to \c USE_INTERNAL_SERIAL.
+ * On unsupported devices, this will evaluate to \ref NO_DESCRIPTOR
+ * and will cause the host to generate a pseudo-unique value for the
+ * device upon insertion.
+ *
+ * \see \c ManufacturerStrIndex structure entry.
+ */
+ uint8_t NumberOfConfigurations; /**< Total number of configurations supported by
+ * the device.
+ */
+ } ATTR_PACKED USB_Descriptor_Device_t;
+
+ /** \brief Standard USB Device Descriptor (USB-IF naming conventions).
+ *
+ * Type define for a standard Device Descriptor. This structure uses the relevant standard's given element names
+ * to ensure compatibility with the standard.
+ *
+ * \see \ref USB_Descriptor_Device_t for the version of this type with non-standard LUFA specific element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint8_t bLength; /**< Size of the descriptor, in bytes. */
+ uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
+ * given by the specific class.
+ */
+ uint16_t bcdUSB; /**< BCD of the supported USB specification.
+ *
+ * \see \ref VERSION_BCD() utility macro.
+ */
+ uint8_t bDeviceClass; /**< USB device class. */
+ uint8_t bDeviceSubClass; /**< USB device subclass. */
+ uint8_t bDeviceProtocol; /**< USB device protocol. */
+ uint8_t bMaxPacketSize0; /**< Size of the control (address 0) endpoint's bank in bytes. */
+ uint16_t idVendor; /**< Vendor ID for the USB product. */
+ uint16_t idProduct; /**< Unique product ID for the USB product. */
+ uint16_t bcdDevice; /**< Product release (version) number.
+ *
+ * \see \ref VERSION_BCD() utility macro.
+ */
+ uint8_t iManufacturer; /**< String index for the manufacturer's name. The
+ * host will request this string via a separate
+ * control request for the string descriptor.
+ *
+ * \note If no string supplied, use \ref NO_DESCRIPTOR.
+ */
+ uint8_t iProduct; /**< String index for the product name/details.
+ *
+ * \see ManufacturerStrIndex structure entry.
+ */
+ uint8_t iSerialNumber; /**< String index for the product's globally unique hexadecimal
+ * serial number, in uppercase Unicode ASCII.
+ *
+ * \note On some microcontroller models, there is an embedded serial number
+ * in the chip which can be used for the device serial number.
+ * To use this serial number, set this to \c USE_INTERNAL_SERIAL.
+ * On unsupported devices, this will evaluate to \ref NO_DESCRIPTOR
+ * and will cause the host to generate a pseudo-unique value for the
+ * device upon insertion.
+ *
+ * \see \c ManufacturerStrIndex structure entry.
+ */
+ uint8_t bNumConfigurations; /**< Total number of configurations supported by
+ * the device.
+ */
+ } ATTR_PACKED USB_StdDescriptor_Device_t;
+
+ /** \brief Standard USB Device Qualifier Descriptor (LUFA naming conventions).
+ *
+ * Type define for a standard Device Qualifier Descriptor. This structure uses LUFA-specific element names
+ * to make each element's purpose clearer.
+ *
+ * \see \ref USB_StdDescriptor_DeviceQualifier_t for the version of this type with standard element names.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Header_t Header; /**< Descriptor header, including type and size. */
+
+ uint16_t USBSpecification; /**< BCD of the supported USB specification.
+ *
+ * \see \ref VERSION_BCD() utility macro.
+ */
+ uint8_t Class; /**< USB device class. */
+ uint8_t SubClass; /**< USB device subclass. */
+ uint8_t Protocol; /**< USB device protocol. */
+
+ uint8_t Endpoint0Size; /**< Size of the control (address 0) endpoint's bank in bytes. */
+ uint8_t NumberOfConfigurations; /**< Total number of configurations supported by
+ * the device.
+ */
+ uint8_t Reserved; /**< Reserved for future use, must be 0. */
+ } ATTR_PACKED USB_Descriptor_DeviceQualifier_t;
+
+ /** \brief Standard USB Device Qualifier Descriptor (USB-IF naming conventions).
+ *
+ * Type define for a standard Device Qualifier Descriptor. This structure uses the relevant standard's given element names
+ * to ensure compatibility with the standard.
+ *
+ * \see \ref USB_Descriptor_DeviceQualifier_t for the version of this type with non-standard LUFA specific element names.
+ */
+ typedef struct
+ {
+ uint8_t bLength; /**< Size of the descriptor, in bytes. */
+ uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
+ * given by the specific class.
+ */
+ uint16_t bcdUSB; /**< BCD of the supported USB specification.
+ *
+ * \see \ref VERSION_BCD() utility macro.
+ */
+ uint8_t bDeviceClass; /**< USB device class. */
+ uint8_t bDeviceSubClass; /**< USB device subclass. */
+ uint8_t bDeviceProtocol; /**< USB device protocol. */
+ uint8_t bMaxPacketSize0; /**< Size of the control (address 0) endpoint's bank in bytes. */
+ uint8_t bNumConfigurations; /**< Total number of configurations supported by
+ * the device.
+ */
+ uint8_t bReserved; /**< Reserved for future use, must be 0. */
+ } ATTR_PACKED USB_StdDescriptor_DeviceQualifier_t;
+
+ /** \brief Standard USB Configuration Descriptor (LUFA naming conventions).
+ *
+ * Type define for a standard Configuration Descriptor header. This structure uses LUFA-specific element names
+ * to make each element's purpose clearer.
+ *
+ * \see \ref USB_StdDescriptor_Configuration_Header_t for the version of this type with standard element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Header_t Header; /**< Descriptor header, including type and size. */
+
+ uint16_t TotalConfigurationSize; /**< Size of the configuration descriptor header,
+ * and all sub descriptors inside the configuration.
+ */
+ uint8_t TotalInterfaces; /**< Total number of interfaces in the configuration. */
+
+ uint8_t ConfigurationNumber; /**< Configuration index of the current configuration. */
+ uint8_t ConfigurationStrIndex; /**< Index of a string descriptor describing the configuration. */
+
+ uint8_t ConfigAttributes; /**< Configuration attributes, comprised of a mask of \c USB_CONFIG_ATTR_* masks.
+ * On all devices, this should include USB_CONFIG_ATTR_RESERVED at a minimum.
+ */
+
+ uint8_t MaxPowerConsumption; /**< Maximum power consumption of the device while in the
+ * current configuration, calculated by the \ref USB_CONFIG_POWER_MA()
+ * macro.
+ */
+ } ATTR_PACKED USB_Descriptor_Configuration_Header_t;
+
+ /** \brief Standard USB Configuration Descriptor (USB-IF naming conventions).
+ *
+ * Type define for a standard Configuration Descriptor header. This structure uses the relevant standard's given element names
+ * to ensure compatibility with the standard.
+ *
+ * \see \ref USB_Descriptor_Device_t for the version of this type with non-standard LUFA specific element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint8_t bLength; /**< Size of the descriptor, in bytes. */
+ uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
+ * given by the specific class.
+ */
+ uint16_t wTotalLength; /**< Size of the configuration descriptor header,
+ * and all sub descriptors inside the configuration.
+ */
+ uint8_t bNumInterfaces; /**< Total number of interfaces in the configuration. */
+ uint8_t bConfigurationValue; /**< Configuration index of the current configuration. */
+ uint8_t iConfiguration; /**< Index of a string descriptor describing the configuration. */
+ uint8_t bmAttributes; /**< Configuration attributes, comprised of a mask of \c USB_CONFIG_ATTR_* masks.
+ * On all devices, this should include USB_CONFIG_ATTR_RESERVED at a minimum.
+ */
+ uint8_t bMaxPower; /**< Maximum power consumption of the device while in the
+ * current configuration, calculated by the \ref USB_CONFIG_POWER_MA()
+ * macro.
+ */
+ } ATTR_PACKED USB_StdDescriptor_Configuration_Header_t;
+
+ /** \brief Standard USB Interface Descriptor (LUFA naming conventions).
+ *
+ * Type define for a standard Interface Descriptor. This structure uses LUFA-specific element names
+ * to make each element's purpose clearer.
+ *
+ * \see \ref USB_StdDescriptor_Interface_t for the version of this type with standard element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Header_t Header; /**< Descriptor header, including type and size. */
+
+ uint8_t InterfaceNumber; /**< Index of the interface in the current configuration. */
+ uint8_t AlternateSetting; /**< Alternate setting for the interface number. The same
+ * interface number can have multiple alternate settings
+ * with different endpoint configurations, which can be
+ * selected by the host.
+ */
+ uint8_t TotalEndpoints; /**< Total number of endpoints in the interface. */
+
+ uint8_t Class; /**< Interface class ID. */
+ uint8_t SubClass; /**< Interface subclass ID. */
+ uint8_t Protocol; /**< Interface protocol ID. */
+
+ uint8_t InterfaceStrIndex; /**< Index of the string descriptor describing the interface. */
+ } ATTR_PACKED USB_Descriptor_Interface_t;
+
+ /** \brief Standard USB Interface Descriptor (USB-IF naming conventions).
+ *
+ * Type define for a standard Interface Descriptor. This structure uses the relevant standard's given element names
+ * to ensure compatibility with the standard.
+ *
+ * \see \ref USB_Descriptor_Interface_t for the version of this type with non-standard LUFA specific element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint8_t bLength; /**< Size of the descriptor, in bytes. */
+ uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
+ * given by the specific class.
+ */
+ uint8_t bInterfaceNumber; /**< Index of the interface in the current configuration. */
+ uint8_t bAlternateSetting; /**< Alternate setting for the interface number. The same
+ * interface number can have multiple alternate settings
+ * with different endpoint configurations, which can be
+ * selected by the host.
+ */
+ uint8_t bNumEndpoints; /**< Total number of endpoints in the interface. */
+ uint8_t bInterfaceClass; /**< Interface class ID. */
+ uint8_t bInterfaceSubClass; /**< Interface subclass ID. */
+ uint8_t bInterfaceProtocol; /**< Interface protocol ID. */
+ uint8_t iInterface; /**< Index of the string descriptor describing the
+ * interface.
+ */
+ } ATTR_PACKED USB_StdDescriptor_Interface_t;
+
+ /** \brief Standard USB Interface Association Descriptor (LUFA naming conventions).
+ *
+ * Type define for a standard Interface Association Descriptor. This structure uses LUFA-specific element names
+ * to make each element's purpose clearer.
+ *
+ * This descriptor has been added as a supplement to the USB2.0 standard, in the ECN located at
+ * <a>http://www.usb.org/developers/docs/InterfaceAssociationDescriptor_ecn.pdf</a>. It allows composite
+ * devices with multiple interfaces related to the same function to have the multiple interfaces bound
+ * together at the point of enumeration, loading one generic driver for all the interfaces in the single
+ * function. Read the ECN for more information.
+ *
+ * \see \ref USB_StdDescriptor_Interface_Association_t for the version of this type with standard element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Header_t Header; /**< Descriptor header, including type and size. */
+
+ uint8_t FirstInterfaceIndex; /**< Index of the first associated interface. */
+ uint8_t TotalInterfaces; /**< Total number of associated interfaces. */
+
+ uint8_t Class; /**< Interface class ID. */
+ uint8_t SubClass; /**< Interface subclass ID. */
+ uint8_t Protocol; /**< Interface protocol ID. */
+
+ uint8_t IADStrIndex; /**< Index of the string descriptor describing the
+ * interface association.
+ */
+ } ATTR_PACKED USB_Descriptor_Interface_Association_t;
+
+ /** \brief Standard USB Interface Association Descriptor (USB-IF naming conventions).
+ *
+ * Type define for a standard Interface Association Descriptor. This structure uses the relevant standard's given
+ * element names to ensure compatibility with the standard.
+ *
+ * This descriptor has been added as a supplement to the USB2.0 standard, in the ECN located at
+ * <a>http://www.usb.org/developers/docs/InterfaceAssociationDescriptor_ecn.pdf</a>. It allows composite
+ * devices with multiple interfaces related to the same function to have the multiple interfaces bound
+ * together at the point of enumeration, loading one generic driver for all the interfaces in the single
+ * function. Read the ECN for more information.
+ *
+ * \see \ref USB_Descriptor_Interface_Association_t for the version of this type with non-standard LUFA specific
+ * element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint8_t bLength; /**< Size of the descriptor, in bytes. */
+ uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
+ * given by the specific class.
+ */
+ uint8_t bFirstInterface; /**< Index of the first associated interface. */
+ uint8_t bInterfaceCount; /**< Total number of associated interfaces. */
+ uint8_t bFunctionClass; /**< Interface class ID. */
+ uint8_t bFunctionSubClass; /**< Interface subclass ID. */
+ uint8_t bFunctionProtocol; /**< Interface protocol ID. */
+ uint8_t iFunction; /**< Index of the string descriptor describing the
+ * interface association.
+ */
+ } ATTR_PACKED USB_StdDescriptor_Interface_Association_t;
+
+ /** \brief Standard USB Endpoint Descriptor (LUFA naming conventions).
+ *
+ * Type define for a standard Endpoint Descriptor. This structure uses LUFA-specific element names
+ * to make each element's purpose clearer.
+ *
+ * \see \ref USB_StdDescriptor_Endpoint_t for the version of this type with standard element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Header_t Header; /**< Descriptor header, including type and size. */
+
+ uint8_t EndpointAddress; /**< Logical address of the endpoint within the device for the current
+ * configuration, including direction mask.
+ */
+ uint8_t Attributes; /**< Endpoint attributes, comprised of a mask of the endpoint type (EP_TYPE_*)
+ * and attributes (ENDPOINT_ATTR_*) masks.
+ */
+ uint16_t EndpointSize; /**< Size of the endpoint bank, in bytes. This indicates the maximum packet
+ * size that the endpoint can receive at a time.
+ */
+ uint8_t PollingIntervalMS; /**< Polling interval in milliseconds for the endpoint if it is an INTERRUPT
+ * or ISOCHRONOUS type.
+ */
+ } ATTR_PACKED USB_Descriptor_Endpoint_t;
+
+ /** \brief Standard USB Endpoint Descriptor (USB-IF naming conventions).
+ *
+ * Type define for a standard Endpoint Descriptor. This structure uses the relevant standard's given
+ * element names to ensure compatibility with the standard.
+ *
+ * \see \ref USB_Descriptor_Endpoint_t for the version of this type with non-standard LUFA specific
+ * element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint8_t bLength; /**< Size of the descriptor, in bytes. */
+ uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a
+ * value given by the specific class.
+ */
+ uint8_t bEndpointAddress; /**< Logical address of the endpoint within the device for the current
+ * configuration, including direction mask.
+ */
+ uint8_t bmAttributes; /**< Endpoint attributes, comprised of a mask of the endpoint type (EP_TYPE_*)
+ * and attributes (ENDPOINT_ATTR_*) masks.
+ */
+ uint16_t wMaxPacketSize; /**< Size of the endpoint bank, in bytes. This indicates the maximum packet size
+ * that the endpoint can receive at a time.
+ */
+ uint8_t bInterval; /**< Polling interval in milliseconds for the endpoint if it is an INTERRUPT or
+ * ISOCHRONOUS type.
+ */
+ } ATTR_PACKED USB_StdDescriptor_Endpoint_t;
+
+ /** \brief Standard USB String Descriptor (LUFA naming conventions).
+ *
+ * Type define for a standard string descriptor. Unlike other standard descriptors, the length
+ * of the descriptor for placement in the descriptor header must be determined by the \ref USB_STRING_LEN()
+ * macro rather than by the size of the descriptor structure, as the length is not fixed.
+ *
+ * This structure should also be used for string index 0, which contains the supported language IDs for
+ * the device as an array.
+ *
+ * This structure uses LUFA-specific element names to make each element's purpose clearer.
+ *
+ * \see \ref USB_StdDescriptor_String_t for the version of this type with standard element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ USB_Descriptor_Header_t Header; /**< Descriptor header, including type and size. */
+
+ #if (((ARCH == ARCH_AVR8) || (ARCH == ARCH_XMEGA)) && !defined(__DOXYGEN__))
+ wchar_t UnicodeString[];
+ #else
+ uint16_t UnicodeString[]; /**< String data, as unicode characters (alternatively,
+ * string language IDs). If normal ASCII characters are
+ * to be used, they must be added as an array of characters
+ * rather than a normal C string so that they are widened to
+ * Unicode size.
+ *
+ * Under GCC, strings prefixed with the "L" character (before
+ * the opening string quotation mark) are considered to be
+ * Unicode strings, and may be used instead of an explicit
+ * array of ASCII characters on little endian devices with
+ * UTF-16-LE \c wchar_t encoding.
+ */
+ #endif
+ } ATTR_PACKED USB_Descriptor_String_t;
+
+ /** \brief Standard USB String Descriptor (USB-IF naming conventions).
+ *
+ * Type define for a standard string descriptor. Unlike other standard descriptors, the length
+ * of the descriptor for placement in the descriptor header must be determined by the \ref USB_STRING_LEN()
+ * macro rather than by the size of the descriptor structure, as the length is not fixed.
+ *
+ * This structure should also be used for string index 0, which contains the supported language IDs for
+ * the device as an array.
+ *
+ * This structure uses the relevant standard's given element names to ensure compatibility with the standard.
+ *
+ * \see \ref USB_Descriptor_String_t for the version of this type with with non-standard LUFA specific
+ * element names.
+ *
+ * \note Regardless of CPU architecture, these values should be stored as little endian.
+ */
+ typedef struct
+ {
+ uint8_t bLength; /**< Size of the descriptor, in bytes. */
+ uint8_t bDescriptorType; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t
+ * or a value given by the specific class.
+ */
+ uint16_t bString[]; /**< String data, as unicode characters (alternatively, string language IDs).
+ * If normal ASCII characters are to be used, they must be added as an array
+ * of characters rather than a normal C string so that they are widened to
+ * Unicode size.
+ *
+ * Under GCC, strings prefixed with the "L" character (before the opening string
+ * quotation mark) are considered to be Unicode strings, and may be used instead
+ * of an explicit array of ASCII characters.
+ */
+ } ATTR_PACKED USB_StdDescriptor_String_t;
+
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/StdRequestType.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/StdRequestType.h
new file mode 100644
index 000000000..b2506cd7d
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/StdRequestType.h
@@ -0,0 +1,258 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief USB control endpoint request definitions.
+ * \copydetails Group_StdRequest
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_USB
+ * \defgroup Group_StdRequest Standard USB Requests
+ * \brief USB control endpoint request definitions.
+ *
+ * This module contains definitions for the various control request parameters, so that the request
+ * details (such as data direction, request recipient, etc.) can be extracted via masking.
+ *
+ * @{
+ */
+
+#ifndef __STDREQTYPE_H__
+#define __STDREQTYPE_H__
+
+ /* Includes: */
+ #include "../../../Common/Common.h"
+ #include "USBMode.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Mask for the request type parameter, to indicate the direction of the request data (Host to Device
+ * or Device to Host). The result of this mask should then be compared to the request direction masks.
+ *
+ * \see \c REQDIR_* macros for masks indicating the request data direction.
+ */
+ #define CONTROL_REQTYPE_DIRECTION 0x80
+
+ /** Mask for the request type parameter, to indicate the type of request (Device, Class or Vendor
+ * Specific). The result of this mask should then be compared to the request type masks.
+ *
+ * \see \c REQTYPE_* macros for masks indicating the request type.
+ */
+ #define CONTROL_REQTYPE_TYPE 0x60
+
+ /** Mask for the request type parameter, to indicate the recipient of the request (Device, Interface
+ * Endpoint or Other). The result of this mask should then be compared to the request recipient
+ * masks.
+ *
+ * \see \c REQREC_* macros for masks indicating the request recipient.
+ */
+ #define CONTROL_REQTYPE_RECIPIENT 0x1F
+
+ /** \name Control Request Data Direction Masks */
+ //@{
+ /** Request data direction mask, indicating that the request data will flow from host to device.
+ *
+ * \see \ref CONTROL_REQTYPE_DIRECTION macro.
+ */
+ #define REQDIR_HOSTTODEVICE (0 << 7)
+
+ /** Request data direction mask, indicating that the request data will flow from device to host.
+ *
+ * \see \ref CONTROL_REQTYPE_DIRECTION macro.
+ */
+ #define REQDIR_DEVICETOHOST (1 << 7)
+ //@}
+
+ /** \name Control Request Type Masks */
+ //@{
+ /** Request type mask, indicating that the request is a standard request.
+ *
+ * \see \ref CONTROL_REQTYPE_TYPE macro.
+ */
+ #define REQTYPE_STANDARD (0 << 5)
+
+ /** Request type mask, indicating that the request is a class-specific request.
+ *
+ * \see \ref CONTROL_REQTYPE_TYPE macro.
+ */
+ #define REQTYPE_CLASS (1 << 5)
+
+ /** Request type mask, indicating that the request is a vendor specific request.
+ *
+ * \see \ref CONTROL_REQTYPE_TYPE macro.
+ */
+ #define REQTYPE_VENDOR (2 << 5)
+ //@}
+
+ /** \name Control Request Recipient Masks */
+ //@{
+ /** Request recipient mask, indicating that the request is to be issued to the device as a whole.
+ *
+ * \see \ref CONTROL_REQTYPE_RECIPIENT macro.
+ */
+ #define REQREC_DEVICE (0 << 0)
+
+ /** Request recipient mask, indicating that the request is to be issued to an interface in the
+ * currently selected configuration.
+ *
+ * \see \ref CONTROL_REQTYPE_RECIPIENT macro.
+ */
+ #define REQREC_INTERFACE (1 << 0)
+
+ /** Request recipient mask, indicating that the request is to be issued to an endpoint in the
+ * currently selected configuration.
+ *
+ * \see \ref CONTROL_REQTYPE_RECIPIENT macro.
+ */
+ #define REQREC_ENDPOINT (2 << 0)
+
+ /** Request recipient mask, indicating that the request is to be issued to an unspecified element
+ * in the currently selected configuration.
+ *
+ * \see \ref CONTROL_REQTYPE_RECIPIENT macro.
+ */
+ #define REQREC_OTHER (3 << 0)
+ //@}
+
+ /* Type Defines: */
+ /** \brief Standard USB Control Request
+ *
+ * Type define for a standard USB control request.
+ *
+ * \see The USB 2.0 specification for more information on standard control requests.
+ */
+ typedef struct
+ {
+ uint8_t bmRequestType; /**< Type of the request. */
+ uint8_t bRequest; /**< Request command code. */
+ uint16_t wValue; /**< wValue parameter of the request. */
+ uint16_t wIndex; /**< wIndex parameter of the request. */
+ uint16_t wLength; /**< Length of the data to transfer in bytes. */
+ } ATTR_PACKED USB_Request_Header_t;
+
+ /* Enums: */
+ /** Enumeration for the various standard request commands. These commands are applicable when the
+ * request type is \ref REQTYPE_STANDARD (with the exception of \ref REQ_GetDescriptor, which is always
+ * handled regardless of the request type value).
+ *
+ * \see Chapter 9 of the USB 2.0 Specification.
+ */
+ enum USB_Control_Request_t
+ {
+ REQ_GetStatus = 0, /**< Implemented in the library for device and endpoint recipients. Passed
+ * to the user application for other recipients via the
+ * \ref EVENT_USB_Device_ControlRequest() event when received in
+ * device mode. */
+ REQ_ClearFeature = 1, /**< Implemented in the library for device and endpoint recipients. Passed
+ * to the user application for other recipients via the
+ * \ref EVENT_USB_Device_ControlRequest() event when received in
+ * device mode. */
+ REQ_SetFeature = 3, /**< Implemented in the library for device and endpoint recipients. Passed
+ * to the user application for other recipients via the
+ * \ref EVENT_USB_Device_ControlRequest() event when received in
+ * device mode. */
+ REQ_SetAddress = 5, /**< Implemented in the library for the device recipient. Passed
+ * to the user application for other recipients via the
+ * \ref EVENT_USB_Device_ControlRequest() event when received in
+ * device mode. */
+ REQ_GetDescriptor = 6, /**< Implemented in the library for device and interface recipients. Passed to the
+ * user application for other recipients via the
+ * \ref EVENT_USB_Device_ControlRequest() event when received in
+ * device mode. */
+ REQ_SetDescriptor = 7, /**< Not implemented in the library, passed to the user application
+ * via the \ref EVENT_USB_Device_ControlRequest() event when received in
+ * device mode. */
+ REQ_GetConfiguration = 8, /**< Implemented in the library for the device recipient. Passed
+ * to the user application for other recipients via the
+ * \ref EVENT_USB_Device_ControlRequest() event when received in
+ * device mode. */
+ REQ_SetConfiguration = 9, /**< Implemented in the library for the device recipient. Passed
+ * to the user application for other recipients via the
+ * \ref EVENT_USB_Device_ControlRequest() event when received in
+ * device mode. */
+ REQ_GetInterface = 10, /**< Not implemented in the library, passed to the user application
+ * via the \ref EVENT_USB_Device_ControlRequest() event when received in
+ * device mode. */
+ REQ_SetInterface = 11, /**< Not implemented in the library, passed to the user application
+ * via the \ref EVENT_USB_Device_ControlRequest() event when received in
+ * device mode. */
+ REQ_SynchFrame = 12, /**< Not implemented in the library, passed to the user application
+ * via the \ref EVENT_USB_Device_ControlRequest() event when received in
+ * device mode. */
+ };
+
+ /** Feature Selector values for Set Feature and Clear Feature standard control requests directed to the device, interface
+ * and endpoint recipients.
+ */
+ enum USB_Feature_Selectors_t
+ {
+ FEATURE_SEL_EndpointHalt = 0x00, /**< Feature selector for Clear Feature or Set Feature commands. When
+ * used in a Set Feature or Clear Feature request this indicates that an
+ * endpoint (whose address is given elsewhere in the request) should have
+ * its stall condition changed.
+ */
+ FEATURE_SEL_DeviceRemoteWakeup = 0x01, /**< Feature selector for Device level Remote Wakeup enable set or clear.
+ * This feature can be controlled by the host on devices which indicate
+ * remote wakeup support in their descriptors to selectively disable or
+ * enable remote wakeup.
+ */
+ FEATURE_SEL_TestMode = 0x02, /**< Feature selector for Test Mode features, used to test the USB controller
+ * to check for incorrect operation.
+ */
+ };
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define FEATURE_SELFPOWERED_ENABLED (1 << 0)
+ #define FEATURE_REMOTE_WAKEUP_ENABLED (1 << 1)
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Device_UC3.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Device_UC3.c
new file mode 100644
index 000000000..6f6de3f5e
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Device_UC3.c
@@ -0,0 +1,51 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "../../../../Common/Common.h"
+#if (ARCH == ARCH_UC3)
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../USBMode.h"
+
+#if defined(USB_CAN_BE_DEVICE)
+
+#include "../Device.h"
+
+void USB_Device_SendRemoteWakeup(void)
+{
+ USB_CLK_Unfreeze();
+
+ AVR32_USBB.UDCON.rmwkup = true;
+ while (AVR32_USBB.UDCON.rmwkup);
+}
+
+#endif
+
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Device_UC3.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Device_UC3.h
new file mode 100644
index 000000000..5579ea0bc
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Device_UC3.h
@@ -0,0 +1,267 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief USB Device definitions for the AVR32 UC3 microcontrollers.
+ * \copydetails Group_Device_UC3
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_Device
+ * \defgroup Group_Device_UC3 Device Management (UC3)
+ * \brief USB Device definitions for the AVR32 UC3 microcontrollers.
+ *
+ * Architecture specific USB Device definitions for the Atmel 32-bit UC3 AVR microcontrollers.
+ *
+ * @{
+ */
+
+#ifndef __USBDEVICE_UC3_H__
+#define __USBDEVICE_UC3_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../USBController.h"
+ #include "../StdDescriptors.h"
+ #include "../USBInterrupt.h"
+ #include "../Endpoint.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** \name USB Device Mode Option Masks */
+ //@{
+ /** Mask for the Options parameter of the \ref USB_Init() function. This indicates that the
+ * USB interface should be initialized in low speed (1.5Mb/s) mode.
+ *
+ * \note Restrictions apply on the number, size and type of endpoints which can be used
+ * when running in low speed mode - please refer to the USB 2.0 specification.
+ */
+ #define USB_DEVICE_OPT_LOWSPEED (1 << 0)
+
+ /** Mask for the Options parameter of the \ref USB_Init() function. This indicates that the
+ * USB interface should be initialized in full speed (12Mb/s) mode.
+ */
+ #define USB_DEVICE_OPT_FULLSPEED (0 << 0)
+
+ #if defined(USB_SERIES_UC3A3_AVR32) || defined(USB_SERIES_UC3A4_AVR32) || defined(__DOXYGEN__)
+ /** Mask for the Options parameter of the \ref USB_Init() function. This indicates that the
+ * USB interface should be initialized in high speed (480Mb/s) mode.
+ */
+ #define USB_DEVICE_OPT_HIGHSPEED (1 << 1)
+ #endif
+ //@}
+
+ #if (!defined(NO_INTERNAL_SERIAL) && \
+ (defined(USB_SERIES_UC3A3_AVR32) || defined(USB_SERIES_UC3A4_AVR32) || \
+ defined(__DOXYGEN__)))
+ /** String descriptor index for the device's unique serial number string descriptor within the device.
+ * This unique serial number is used by the host to associate resources to the device (such as drivers or COM port
+ * number allocations) to a device regardless of the port it is plugged in to on the host. Some microcontrollers contain
+ * a unique serial number internally, and setting the device descriptors serial number string index to this value
+ * will cause it to use the internal serial number.
+ *
+ * On unsupported devices, this will evaluate to \ref NO_DESCRIPTOR and so will force the host to create a pseudo-serial
+ * number for the device.
+ */
+ #define USE_INTERNAL_SERIAL 0xDC
+
+ /** Length of the device's unique internal serial number, in bits, if present on the selected microcontroller
+ * model.
+ */
+ #define INTERNAL_SERIAL_LENGTH_BITS 120
+
+ /** Start address of the internal serial number, in the appropriate address space, if present on the selected microcontroller
+ * model.
+ */
+ #define INTERNAL_SERIAL_START_ADDRESS 0x80800204
+ #else
+ #define USE_INTERNAL_SERIAL NO_DESCRIPTOR
+
+ #define INTERNAL_SERIAL_LENGTH_BITS 0
+ #define INTERNAL_SERIAL_START_ADDRESS 0
+ #endif
+
+ /* Function Prototypes: */
+ /** Sends a Remote Wakeup request to the host. This signals to the host that the device should
+ * be taken out of suspended mode, and communications should resume.
+ *
+ * Typically, this is implemented so that HID devices (mice, keyboards, etc.) can wake up the
+ * host computer when the host has suspended all USB devices to enter a low power state.
+ *
+ * \note This function should only be used if the device has indicated to the host that it
+ * supports the Remote Wakeup feature in the device descriptors, and should only be
+ * issued if the host is currently allowing remote wakeup events from the device (i.e.,
+ * the \ref USB_Device_RemoteWakeupEnabled flag is set). When the \c NO_DEVICE_REMOTE_WAKEUP
+ * compile time option is used, this function is unavailable.
+ *
+ * \note The USB clock must be running for this function to operate. If the stack is initialized with
+ * the \ref USB_OPT_MANUAL_PLL option enabled, the user must ensure that the PLL is running
+ * before attempting to call this function.
+ *
+ * \see \ref Group_StdDescriptors for more information on the RMWAKEUP feature and device descriptors.
+ */
+ void USB_Device_SendRemoteWakeup(void);
+
+ /* Inline Functions: */
+ /** Returns the current USB frame number, when in device mode. Every millisecond the USB bus is active (i.e. enumerated to a host)
+ * the frame number is incremented by one.
+ *
+ * \return Current USB frame number from the USB controller.
+ */
+ static inline uint16_t USB_Device_GetFrameNumber(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline uint16_t USB_Device_GetFrameNumber(void)
+ {
+ return AVR32_USBB.UDFNUM.fnum;
+ }
+
+ #if !defined(NO_SOF_EVENTS)
+ /** Enables the device mode Start Of Frame events. When enabled, this causes the
+ * \ref EVENT_USB_Device_StartOfFrame() event to fire once per millisecond, synchronized to the USB bus,
+ * at the start of each USB frame when enumerated in device mode.
+ *
+ * \note Not available when the \c NO_SOF_EVENTS compile time token is defined.
+ */
+ static inline void USB_Device_EnableSOFEvents(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Device_EnableSOFEvents(void)
+ {
+ USB_INT_Enable(USB_INT_SOFI);
+ }
+
+ /** Disables the device mode Start Of Frame events. When disabled, this stops the firing of the
+ * \ref EVENT_USB_Device_StartOfFrame() event when enumerated in device mode.
+ *
+ * \note Not available when the \c NO_SOF_EVENTS compile time token is defined.
+ */
+ static inline void USB_Device_DisableSOFEvents(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Device_DisableSOFEvents(void)
+ {
+ USB_INT_Disable(USB_INT_SOFI);
+ }
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Inline Functions: */
+ static inline void USB_Device_SetLowSpeed(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Device_SetLowSpeed(void)
+ {
+ AVR32_USBB.UDCON.ls = true;
+ }
+
+ static inline void USB_Device_SetFullSpeed(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Device_SetFullSpeed(void)
+ {
+ AVR32_USBB.UDCON.ls = false;
+ #if defined(USB_DEVICE_OPT_HIGHSPEED)
+ AVR32_USBB.UDCON.spdconf = 3;
+ #endif
+ }
+
+ #if defined(USB_DEVICE_OPT_HIGHSPEED)
+ static inline void USB_Device_SetHighSpeed(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Device_SetHighSpeed(void)
+ {
+ AVR32_USBB.UDCON.ls = false;
+ AVR32_USBB.UDCON.spdconf = 0;
+ }
+ #endif
+
+ static inline void USB_Device_SetDeviceAddress(const uint8_t Address) ATTR_ALWAYS_INLINE;
+ static inline void USB_Device_SetDeviceAddress(const uint8_t Address)
+ {
+ AVR32_USBB.UDCON.uadd = Address;
+ }
+
+ static inline void USB_Device_EnableDeviceAddress(const uint8_t Address) ATTR_ALWAYS_INLINE;
+ static inline void USB_Device_EnableDeviceAddress(const uint8_t Address)
+ {
+ (void)Address;
+
+ AVR32_USBB.UDCON.adden = true;
+ }
+
+ static inline bool USB_Device_IsAddressSet(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline bool USB_Device_IsAddressSet(void)
+ {
+ return AVR32_USBB.UDCON.adden;
+ }
+
+ #if (USE_INTERNAL_SERIAL != NO_DESCRIPTOR)
+ static inline void USB_Device_GetSerialString(uint16_t* const UnicodeString) ATTR_NON_NULL_PTR_ARG(1);
+ static inline void USB_Device_GetSerialString(uint16_t* const UnicodeString)
+ {
+ uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask();
+ GlobalInterruptDisable();
+
+ uint8_t* SigReadAddress = (uint8_t*)INTERNAL_SERIAL_START_ADDRESS;
+
+ for (uint8_t SerialCharNum = 0; SerialCharNum < (INTERNAL_SERIAL_LENGTH_BITS / 4); SerialCharNum++)
+ {
+ uint8_t SerialByte = *SigReadAddress;
+
+ if (SerialCharNum & 0x01)
+ {
+ SerialByte >>= 4;
+ SigReadAddress++;
+ }
+
+ SerialByte &= 0x0F;
+
+ UnicodeString[SerialCharNum] = cpu_to_le16((SerialByte >= 10) ?
+ (('A' - 10) + SerialByte) : ('0' + SerialByte));
+ }
+
+ SetGlobalInterruptMask(CurrentGlobalInt);
+ }
+ #endif
+
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/EndpointStream_UC3.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/EndpointStream_UC3.c
new file mode 100644
index 000000000..6e9862927
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/EndpointStream_UC3.c
@@ -0,0 +1,235 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "../../../../Common/Common.h"
+#if (ARCH == ARCH_UC3)
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../USBMode.h"
+
+#if defined(USB_CAN_BE_DEVICE)
+
+#include "EndpointStream_UC3.h"
+
+#if !defined(CONTROL_ONLY_DEVICE)
+uint8_t Endpoint_Discard_Stream(uint16_t Length,
+ uint16_t* const BytesProcessed)
+{
+ uint8_t ErrorCode;
+ uint16_t BytesInTransfer = 0;
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()))
+ return ErrorCode;
+
+ if (BytesProcessed != NULL)
+ Length -= *BytesProcessed;
+
+ while (Length)
+ {
+ if (!(Endpoint_IsReadWriteAllowed()))
+ {
+ Endpoint_ClearOUT();
+
+ if (BytesProcessed != NULL)
+ {
+ *BytesProcessed += BytesInTransfer;
+ return ENDPOINT_RWSTREAM_IncompleteTransfer;
+ }
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()))
+ return ErrorCode;
+ }
+ else
+ {
+ Endpoint_Discard_8();
+
+ Length--;
+ BytesInTransfer++;
+ }
+ }
+
+ return ENDPOINT_RWSTREAM_NoError;
+}
+
+uint8_t Endpoint_Null_Stream(uint16_t Length,
+ uint16_t* const BytesProcessed)
+{
+ uint8_t ErrorCode;
+ uint16_t BytesInTransfer = 0;
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()))
+ return ErrorCode;
+
+ if (BytesProcessed != NULL)
+ Length -= *BytesProcessed;
+
+ while (Length)
+ {
+ if (!(Endpoint_IsReadWriteAllowed()))
+ {
+ Endpoint_ClearIN();
+
+ if (BytesProcessed != NULL)
+ {
+ *BytesProcessed += BytesInTransfer;
+ return ENDPOINT_RWSTREAM_IncompleteTransfer;
+ }
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()))
+ return ErrorCode;
+ }
+ else
+ {
+ Endpoint_Write_8(0);
+
+ Length--;
+ BytesInTransfer++;
+ }
+ }
+
+ return ENDPOINT_RWSTREAM_NoError;
+}
+
+/* The following abuses the C preprocessor in order to copy-paste common code with slight alterations,
+ * so that the code needs to be written once. It is a crude form of templating to reduce code maintenance. */
+
+#define TEMPLATE_FUNC_NAME Endpoint_Write_Stream_LE
+#define TEMPLATE_BUFFER_TYPE const void*
+#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearIN()
+#define TEMPLATE_BUFFER_OFFSET(Length) 0
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(*BufferPtr)
+#include "Template/Template_Endpoint_RW.c"
+
+#define TEMPLATE_FUNC_NAME Endpoint_Write_Stream_BE
+#define TEMPLATE_BUFFER_TYPE const void*
+#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearIN()
+#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(*BufferPtr)
+#include "Template/Template_Endpoint_RW.c"
+
+#define TEMPLATE_FUNC_NAME Endpoint_Read_Stream_LE
+#define TEMPLATE_BUFFER_TYPE void*
+#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearOUT()
+#define TEMPLATE_BUFFER_OFFSET(Length) 0
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) *BufferPtr = Endpoint_Read_8()
+#include "Template/Template_Endpoint_RW.c"
+
+#define TEMPLATE_FUNC_NAME Endpoint_Read_Stream_BE
+#define TEMPLATE_BUFFER_TYPE void*
+#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearOUT()
+#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) *BufferPtr = Endpoint_Read_8()
+#include "Template/Template_Endpoint_RW.c"
+
+#if defined(ARCH_HAS_FLASH_ADDRESS_SPACE)
+ #define TEMPLATE_FUNC_NAME Endpoint_Write_PStream_LE
+ #define TEMPLATE_BUFFER_TYPE const void*
+ #define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearIN()
+ #define TEMPLATE_BUFFER_OFFSET(Length) 0
+ #define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
+ #define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(pgm_read_byte(BufferPtr))
+ #include "Template/Template_Endpoint_RW.c"
+
+ #define TEMPLATE_FUNC_NAME Endpoint_Write_PStream_BE
+ #define TEMPLATE_BUFFER_TYPE const void*
+ #define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearIN()
+ #define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+ #define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
+ #define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(pgm_read_byte(BufferPtr))
+ #include "Template/Template_Endpoint_RW.c"
+#endif
+
+#if defined(ARCH_HAS_EEPROM_ADDRESS_SPACE)
+ #define TEMPLATE_FUNC_NAME Endpoint_Write_EStream_LE
+ #define TEMPLATE_BUFFER_TYPE const void*
+ #define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearIN()
+ #define TEMPLATE_BUFFER_OFFSET(Length) 0
+ #define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
+ #define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(eeprom_read_byte(BufferPtr))
+ #include "Template/Template_Endpoint_RW.c"
+
+ #define TEMPLATE_FUNC_NAME Endpoint_Write_EStream_BE
+ #define TEMPLATE_BUFFER_TYPE const void*
+ #define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearIN()
+ #define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+ #define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
+ #define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(eeprom_read_byte(BufferPtr))
+ #include "Template/Template_Endpoint_RW.c"
+
+ #define TEMPLATE_FUNC_NAME Endpoint_Read_EStream_LE
+ #define TEMPLATE_BUFFER_TYPE void*
+ #define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearOUT()
+ #define TEMPLATE_BUFFER_OFFSET(Length) 0
+ #define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
+ #define TEMPLATE_TRANSFER_BYTE(BufferPtr) eeprom_update_byte(BufferPtr, Endpoint_Read_8())
+ #include "Template/Template_Endpoint_RW.c"
+
+ #define TEMPLATE_FUNC_NAME Endpoint_Read_EStream_BE
+ #define TEMPLATE_BUFFER_TYPE void*
+ #define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearOUT()
+ #define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+ #define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
+ #define TEMPLATE_TRANSFER_BYTE(BufferPtr) eeprom_update_byte(BufferPtr, Endpoint_Read_8())
+ #include "Template/Template_Endpoint_RW.c"
+#endif
+
+#endif
+
+#define TEMPLATE_FUNC_NAME Endpoint_Write_Control_Stream_LE
+#define TEMPLATE_BUFFER_OFFSET(Length) 0
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(*BufferPtr)
+#include "Template/Template_Endpoint_Control_W.c"
+
+#define TEMPLATE_FUNC_NAME Endpoint_Write_Control_Stream_BE
+#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(*BufferPtr)
+#include "Template/Template_Endpoint_Control_W.c"
+
+#define TEMPLATE_FUNC_NAME Endpoint_Read_Control_Stream_LE
+#define TEMPLATE_BUFFER_OFFSET(Length) 0
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) *BufferPtr = Endpoint_Read_8()
+#include "Template/Template_Endpoint_Control_R.c"
+
+#define TEMPLATE_FUNC_NAME Endpoint_Read_Control_Stream_BE
+#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) *BufferPtr = Endpoint_Read_8()
+#include "Template/Template_Endpoint_Control_R.c"
+
+#endif
+
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/EndpointStream_UC3.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/EndpointStream_UC3.h
new file mode 100644
index 000000000..831c71407
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/EndpointStream_UC3.h
@@ -0,0 +1,438 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Endpoint data stream transmission and reception management for the AVR32 UC3 microcontrollers.
+ * \copydetails Group_EndpointStreamRW_UC3
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_EndpointStreamRW
+ * \defgroup Group_EndpointStreamRW_UC3 Read/Write of Multi-Byte Streams (UC3)
+ * \brief Endpoint data stream transmission and reception management for the Atmel AVR32 UC3 architecture.
+ *
+ * Functions, macros, variables, enums and types related to data reading and writing of data streams from
+ * and to endpoints.
+ *
+ * @{
+ */
+
+#ifndef __ENDPOINT_STREAM_UC3_H__
+#define __ENDPOINT_STREAM_UC3_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../USBMode.h"
+ #include "../USBTask.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Function Prototypes: */
+ /** \name Stream functions for null data */
+ //@{
+
+ /** Reads and discards the given number of bytes from the currently selected endpoint's bank,
+ * discarding fully read packets from the host as needed. The last packet is not automatically
+ * discarded once the remaining bytes has been read; the user is responsible for manually
+ * discarding the last packet from the host via the \ref Endpoint_ClearOUT() macro.
+ *
+ * If the BytesProcessed parameter is \c NULL, the entire stream transfer is attempted at once,
+ * failing or succeeding as a single unit. If the BytesProcessed parameter points to a valid
+ * storage location, the transfer will instead be performed as a series of chunks. Each time
+ * the endpoint bank becomes empty while there is still data to process (and after the current
+ * packet has been acknowledged) the BytesProcessed location will be updated with the total number
+ * of bytes processed in the stream, and the function will exit with an error code of
+ * \ref ENDPOINT_RWSTREAM_IncompleteTransfer. This allows for any abort checking to be performed
+ * in the user code - to continue the transfer, call the function again with identical parameters
+ * and it will resume until the BytesProcessed value reaches the total transfer length.
+ *
+ * <b>Single Stream Transfer Example:</b>
+ * \code
+ * uint8_t ErrorCode;
+ *
+ * if ((ErrorCode = Endpoint_Discard_Stream(512, NULL)) != ENDPOINT_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * <b>Partial Stream Transfers Example:</b>
+ * \code
+ * uint8_t ErrorCode;
+ * uint16_t BytesProcessed;
+ *
+ * BytesProcessed = 0;
+ * while ((ErrorCode = Endpoint_Discard_Stream(512, &BytesProcessed)) == ENDPOINT_RWSTREAM_IncompleteTransfer)
+ * {
+ * // Stream not yet complete - do other actions here, abort if required
+ * }
+ *
+ * if (ErrorCode != ENDPOINT_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * \note This routine should not be used on CONTROL type endpoints.
+ *
+ * \param[in] Length Number of bytes to discard via the currently selected endpoint.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
+ * transaction should be updated, \c NULL if the entire stream should be read at once.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Discard_Stream(uint16_t Length,
+ uint16_t* const BytesProcessed);
+
+ /** Writes a given number of zeroed bytes to the currently selected endpoint's bank, sending
+ * full packets to the host as needed. The last packet is not automatically sent once the
+ * remaining bytes have been written; the user is responsible for manually sending the last
+ * packet to the host via the \ref Endpoint_ClearIN() macro.
+ *
+ * If the BytesProcessed parameter is \c NULL, the entire stream transfer is attempted at once,
+ * failing or succeeding as a single unit. If the BytesProcessed parameter points to a valid
+ * storage location, the transfer will instead be performed as a series of chunks. Each time
+ * the endpoint bank becomes full while there is still data to process (and after the current
+ * packet transmission has been initiated) the BytesProcessed location will be updated with the
+ * total number of bytes processed in the stream, and the function will exit with an error code of
+ * \ref ENDPOINT_RWSTREAM_IncompleteTransfer. This allows for any abort checking to be performed
+ * in the user code - to continue the transfer, call the function again with identical parameters
+ * and it will resume until the BytesProcessed value reaches the total transfer length.
+ *
+ * <b>Single Stream Transfer Example:</b>
+ * \code
+ * uint8_t ErrorCode;
+ *
+ * if ((ErrorCode = Endpoint_Null_Stream(512, NULL)) != ENDPOINT_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * <b>Partial Stream Transfers Example:</b>
+ * \code
+ * uint8_t ErrorCode;
+ * uint16_t BytesProcessed;
+ *
+ * BytesProcessed = 0;
+ * while ((ErrorCode = Endpoint_Null_Stream(512, &BytesProcessed)) == ENDPOINT_RWSTREAM_IncompleteTransfer)
+ * {
+ * // Stream not yet complete - do other actions here, abort if required
+ * }
+ *
+ * if (ErrorCode != ENDPOINT_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * \note This routine should not be used on CONTROL type endpoints.
+ *
+ * \param[in] Length Number of zero bytes to send via the currently selected endpoint.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
+ * transaction should be updated, \c NULL if the entire stream should be read at once.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Null_Stream(uint16_t Length,
+ uint16_t* const BytesProcessed);
+
+ //@}
+
+ /** \name Stream functions for RAM source/destination data */
+ //@{
+
+ /** Writes the given number of bytes to the endpoint from the given buffer in little endian,
+ * sending full packets to the host as needed. The last packet filled is not automatically sent;
+ * the user is responsible for manually sending the last written packet to the host via the
+ * \ref Endpoint_ClearIN() macro.
+ *
+ * If the BytesProcessed parameter is \c NULL, the entire stream transfer is attempted at once,
+ * failing or succeeding as a single unit. If the BytesProcessed parameter points to a valid
+ * storage location, the transfer will instead be performed as a series of chunks. Each time
+ * the endpoint bank becomes full while there is still data to process (and after the current
+ * packet transmission has been initiated) the BytesProcessed location will be updated with the
+ * total number of bytes processed in the stream, and the function will exit with an error code of
+ * \ref ENDPOINT_RWSTREAM_IncompleteTransfer. This allows for any abort checking to be performed
+ * in the user code - to continue the transfer, call the function again with identical parameters
+ * and it will resume until the BytesProcessed value reaches the total transfer length.
+ *
+ * <b>Single Stream Transfer Example:</b>
+ * \code
+ * uint8_t DataStream[512];
+ * uint8_t ErrorCode;
+ *
+ * if ((ErrorCode = Endpoint_Write_Stream_LE(DataStream, sizeof(DataStream),
+ * NULL)) != ENDPOINT_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * <b>Partial Stream Transfers Example:</b>
+ * \code
+ * uint8_t DataStream[512];
+ * uint8_t ErrorCode;
+ * uint16_t BytesProcessed;
+ *
+ * BytesProcessed = 0;
+ * while ((ErrorCode = Endpoint_Write_Stream_LE(DataStream, sizeof(DataStream),
+ * &BytesProcessed)) == ENDPOINT_RWSTREAM_IncompleteTransfer)
+ * {
+ * // Stream not yet complete - do other actions here, abort if required
+ * }
+ *
+ * if (ErrorCode != ENDPOINT_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * \note This routine should not be used on CONTROL type endpoints.
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
+ * transaction should be updated, \c NULL if the entire stream should be written at once.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_Stream_LE(const void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Writes the given number of bytes to the endpoint from the given buffer in big endian,
+ * sending full packets to the host as needed. The last packet filled is not automatically sent;
+ * the user is responsible for manually sending the last written packet to the host via the
+ * \ref Endpoint_ClearIN() macro.
+ *
+ * \note This routine should not be used on CONTROL type endpoints.
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
+ * transaction should be updated, \c NULL if the entire stream should be written at once.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_Stream_BE(const void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Reads the given number of bytes from the endpoint from the given buffer in little endian,
+ * discarding fully read packets from the host as needed. The last packet is not automatically
+ * discarded once the remaining bytes has been read; the user is responsible for manually
+ * discarding the last packet from the host via the \ref Endpoint_ClearOUT() macro.
+ *
+ * If the BytesProcessed parameter is \c NULL, the entire stream transfer is attempted at once,
+ * failing or succeeding as a single unit. If the BytesProcessed parameter points to a valid
+ * storage location, the transfer will instead be performed as a series of chunks. Each time
+ * the endpoint bank becomes empty while there is still data to process (and after the current
+ * packet has been acknowledged) the BytesProcessed location will be updated with the total number
+ * of bytes processed in the stream, and the function will exit with an error code of
+ * \ref ENDPOINT_RWSTREAM_IncompleteTransfer. This allows for any abort checking to be performed
+ * in the user code - to continue the transfer, call the function again with identical parameters
+ * and it will resume until the BytesProcessed value reaches the total transfer length.
+ *
+ * <b>Single Stream Transfer Example:</b>
+ * \code
+ * uint8_t DataStream[512];
+ * uint8_t ErrorCode;
+ *
+ * if ((ErrorCode = Endpoint_Read_Stream_LE(DataStream, sizeof(DataStream),
+ * NULL)) != ENDPOINT_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * <b>Partial Stream Transfers Example:</b>
+ * \code
+ * uint8_t DataStream[512];
+ * uint8_t ErrorCode;
+ * uint16_t BytesProcessed;
+ *
+ * BytesProcessed = 0;
+ * while ((ErrorCode = Endpoint_Read_Stream_LE(DataStream, sizeof(DataStream),
+ * &BytesProcessed)) == ENDPOINT_RWSTREAM_IncompleteTransfer)
+ * {
+ * // Stream not yet complete - do other actions here, abort if required
+ * }
+ *
+ * if (ErrorCode != ENDPOINT_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * \note This routine should not be used on CONTROL type endpoints.
+ *
+ * \param[out] Buffer Pointer to the destination data buffer to write to.
+ * \param[in] Length Number of bytes to send via the currently selected endpoint.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
+ * transaction should be updated, \c NULL if the entire stream should be read at once.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Read_Stream_LE(void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Reads the given number of bytes from the endpoint from the given buffer in big endian,
+ * discarding fully read packets from the host as needed. The last packet is not automatically
+ * discarded once the remaining bytes has been read; the user is responsible for manually
+ * discarding the last packet from the host via the \ref Endpoint_ClearOUT() macro.
+ *
+ * \note This routine should not be used on CONTROL type endpoints.
+ *
+ * \param[out] Buffer Pointer to the destination data buffer to write to.
+ * \param[in] Length Number of bytes to send via the currently selected endpoint.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
+ * transaction should be updated, \c NULL if the entire stream should be read at once.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Read_Stream_BE(void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Writes the given number of bytes to the CONTROL type endpoint from the given buffer in little endian,
+ * sending full packets to the host as needed. The host OUT acknowledgement is not automatically cleared
+ * in both failure and success states; the user is responsible for manually clearing the status OUT packet
+ * to finalize the transfer's status stage via the \ref Endpoint_ClearOUT() macro.
+ *
+ * \note This function automatically sends the last packet in the data stage of the transaction; when the
+ * function returns, the user is responsible for clearing the <b>status</b> stage of the transaction.
+ * Note that the status stage packet is sent or received in the opposite direction of the data flow.
+ * \n\n
+ *
+ * \note This routine should only be used on CONTROL type endpoints.
+ *
+ * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
+ * together; i.e. the entire stream data must be read or written at the one time.
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
+ *
+ * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_Control_Stream_LE(const void* const Buffer,
+ uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Writes the given number of bytes to the CONTROL type endpoint from the given buffer in big endian,
+ * sending full packets to the host as needed. The host OUT acknowledgement is not automatically cleared
+ * in both failure and success states; the user is responsible for manually clearing the status OUT packet
+ * to finalize the transfer's status stage via the \ref Endpoint_ClearOUT() macro.
+ *
+ * \note This function automatically sends the last packet in the data stage of the transaction; when the
+ * function returns, the user is responsible for clearing the <b>status</b> stage of the transaction.
+ * Note that the status stage packet is sent or received in the opposite direction of the data flow.
+ * \n\n
+ *
+ * \note This routine should only be used on CONTROL type endpoints.
+ *
+ * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
+ * together; i.e. the entire stream data must be read or written at the one time.
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
+ *
+ * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_Control_Stream_BE(const void* const Buffer,
+ uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Reads the given number of bytes from the CONTROL endpoint from the given buffer in little endian,
+ * discarding fully read packets from the host as needed. The device IN acknowledgement is not
+ * automatically sent after success or failure states; the user is responsible for manually sending the
+ * status IN packet to finalize the transfer's status stage via the \ref Endpoint_ClearIN() macro.
+ *
+ * \note This function automatically sends the last packet in the data stage of the transaction; when the
+ * function returns, the user is responsible for clearing the <b>status</b> stage of the transaction.
+ * Note that the status stage packet is sent or received in the opposite direction of the data flow.
+ * \n\n
+ *
+ * \note This routine should only be used on CONTROL type endpoints.
+ *
+ * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
+ * together; i.e. the entire stream data must be read or written at the one time.
+ *
+ * \param[out] Buffer Pointer to the destination data buffer to write to.
+ * \param[in] Length Number of bytes to send via the currently selected endpoint.
+ *
+ * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Read_Control_Stream_LE(void* const Buffer,
+ uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Reads the given number of bytes from the CONTROL endpoint from the given buffer in big endian,
+ * discarding fully read packets from the host as needed. The device IN acknowledgement is not
+ * automatically sent after success or failure states; the user is responsible for manually sending the
+ * status IN packet to finalize the transfer's status stage via the \ref Endpoint_ClearIN() macro.
+ *
+ * \note This function automatically sends the last packet in the data stage of the transaction; when the
+ * function returns, the user is responsible for clearing the <b>status</b> stage of the transaction.
+ * Note that the status stage packet is sent or received in the opposite direction of the data flow.
+ * \n\n
+ *
+ * \note This routine should only be used on CONTROL type endpoints.
+ *
+ * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
+ * together; i.e. the entire stream data must be read or written at the one time.
+ *
+ * \param[out] Buffer Pointer to the destination data buffer to write to.
+ * \param[in] Length Number of bytes to send via the currently selected endpoint.
+ *
+ * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Read_Control_Stream_BE(void* const Buffer,
+ uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+ //@}
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.c
new file mode 100644
index 000000000..5dce488f2
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.c
@@ -0,0 +1,196 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "../../../../Common/Common.h"
+#if (ARCH == ARCH_UC3)
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../USBMode.h"
+
+#if defined(USB_CAN_BE_DEVICE)
+
+#include "../Endpoint.h"
+
+#if !defined(FIXED_CONTROL_ENDPOINT_SIZE)
+uint8_t USB_Device_ControlEndpointSize = ENDPOINT_CONTROLEP_DEFAULT_SIZE;
+#endif
+
+volatile uint32_t USB_Endpoint_SelectedEndpoint = ENDPOINT_CONTROLEP;
+volatile uint8_t* USB_Endpoint_FIFOPos[ENDPOINT_TOTAL_ENDPOINTS];
+
+bool Endpoint_ConfigureEndpointTable(const USB_Endpoint_Table_t* const Table,
+ const uint8_t Entries)
+{
+ for (uint8_t i = 0; i < Entries; i++)
+ {
+ if (!(Table[i].Address))
+ continue;
+
+ if (!(Endpoint_ConfigureEndpoint(Table[i].Address, Table[i].Type, Table[i].Size, Table[i].Banks)))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool Endpoint_ConfigureEndpoint_Prv(const uint8_t Number,
+ const uint32_t UECFG0Data)
+{
+ USB_Endpoint_FIFOPos[Number] = &AVR32_USBB_SLAVE[Number * ENDPOINT_HSB_ADDRESS_SPACE_SIZE];
+
+#if defined(CONTROL_ONLY_DEVICE) || defined(ORDERED_EP_CONFIG)
+ Endpoint_SelectEndpoint(Number);
+ Endpoint_EnableEndpoint();
+
+ (&AVR32_USBB.uecfg0)[Number] = 0;
+ (&AVR32_USBB.uecfg0)[Number] = UECFG0Data;
+
+ return Endpoint_IsConfigured();
+#else
+ for (uint8_t EPNum = Number; EPNum < ENDPOINT_TOTAL_ENDPOINTS; EPNum++)
+ {
+ uint32_t UECFG0Temp;
+
+ Endpoint_SelectEndpoint(EPNum);
+
+ if (EPNum == Number)
+ {
+ UECFG0Temp = UECFG0Data;
+ }
+ else
+ {
+ UECFG0Temp = (&AVR32_USBB.uecfg0)[EPNum];
+ }
+
+ if (!(UECFG0Temp & AVR32_USBB_ALLOC_MASK))
+ continue;
+
+ Endpoint_DisableEndpoint();
+ (&AVR32_USBB.uecfg0)[EPNum] &= ~AVR32_USBB_ALLOC_MASK;
+
+ Endpoint_EnableEndpoint();
+ (&AVR32_USBB.uecfg0)[EPNum] = UECFG0Temp;
+
+ if (!(Endpoint_IsConfigured()))
+ return false;
+ }
+
+ Endpoint_SelectEndpoint(Number);
+ return true;
+#endif
+}
+
+void Endpoint_ClearEndpoints(void)
+{
+ for (uint8_t EPNum = 0; EPNum < ENDPOINT_TOTAL_ENDPOINTS; EPNum++)
+ {
+ Endpoint_SelectEndpoint(EPNum);
+ (&AVR32_USBB.uecfg0)[EPNum] = 0;
+ (&AVR32_USBB.uecon0clr)[EPNum] = -1;
+ USB_Endpoint_FIFOPos[EPNum] = &AVR32_USBB_SLAVE[EPNum * 0x10000];
+ Endpoint_DisableEndpoint();
+ }
+}
+
+void Endpoint_ClearStatusStage(void)
+{
+ if (USB_ControlRequest.bmRequestType & REQDIR_DEVICETOHOST)
+ {
+ while (!(Endpoint_IsOUTReceived()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+
+ Endpoint_ClearOUT();
+ }
+ else
+ {
+ while (!(Endpoint_IsINReady()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+
+ Endpoint_ClearIN();
+ }
+}
+
+#if !defined(CONTROL_ONLY_DEVICE)
+uint8_t Endpoint_WaitUntilReady(void)
+{
+ #if (USB_STREAM_TIMEOUT_MS < 0xFF)
+ uint8_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
+ #else
+ uint16_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
+ #endif
+
+ uint16_t PreviousFrameNumber = USB_Device_GetFrameNumber();
+
+ for (;;)
+ {
+ if (Endpoint_GetEndpointDirection() == ENDPOINT_DIR_IN)
+ {
+ if (Endpoint_IsINReady())
+ return ENDPOINT_READYWAIT_NoError;
+ }
+ else
+ {
+ if (Endpoint_IsOUTReceived())
+ return ENDPOINT_READYWAIT_NoError;
+ }
+
+ uint8_t USB_DeviceState_LCL = USB_DeviceState;
+
+ if (USB_DeviceState_LCL == DEVICE_STATE_Unattached)
+ return ENDPOINT_READYWAIT_DeviceDisconnected;
+ else if (USB_DeviceState_LCL == DEVICE_STATE_Suspended)
+ return ENDPOINT_READYWAIT_BusSuspended;
+ else if (Endpoint_IsStalled())
+ return ENDPOINT_READYWAIT_EndpointStalled;
+
+ uint16_t CurrentFrameNumber = USB_Device_GetFrameNumber();
+
+ if (CurrentFrameNumber != PreviousFrameNumber)
+ {
+ PreviousFrameNumber = CurrentFrameNumber;
+
+ if (!(TimeoutMSRem--))
+ return ENDPOINT_READYWAIT_Timeout;
+ }
+ }
+}
+#endif
+
+#endif
+
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.h
new file mode 100644
index 000000000..cf35d2b60
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.h
@@ -0,0 +1,794 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief USB Endpoint definitions for the AVR32 UC3 microcontrollers.
+ * \copydetails Group_EndpointManagement_UC3
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_EndpointRW
+ * \defgroup Group_EndpointRW_UC3 Endpoint Data Reading and Writing (UC3)
+ * \brief Endpoint data read/write definitions for the Atmel AVR32 UC3 architecture.
+ *
+ * Functions, macros, variables, enums and types related to data reading and writing from and to endpoints.
+ */
+
+/** \ingroup Group_EndpointPrimitiveRW
+ * \defgroup Group_EndpointPrimitiveRW_UC3 Read/Write of Primitive Data Types (UC3)
+ * \brief Endpoint primitive read/write definitions for the Atmel AVR32 UC3 architecture.
+ *
+ * Functions, macros, variables, enums and types related to data reading and writing of primitive data types
+ * from and to endpoints.
+ */
+
+/** \ingroup Group_EndpointPacketManagement
+ * \defgroup Group_EndpointPacketManagement_UC3 Endpoint Packet Management (UC3)
+ * \brief Endpoint packet management definitions for the Atmel AVR32 UC3 architecture.
+ *
+ * Functions, macros, variables, enums and types related to packet management of endpoints.
+ */
+
+/** \ingroup Group_EndpointManagement
+ * \defgroup Group_EndpointManagement_UC3 Endpoint Management (UC3)
+ * \brief Endpoint management definitions for the Atmel AVR32 UC3 architecture.
+ *
+ * Functions, macros and enums related to endpoint management when in USB Device mode. This
+ * module contains the endpoint management macros, as well as endpoint interrupt and data
+ * send/receive functions for various data types.
+ *
+ * @{
+ */
+
+#ifndef __ENDPOINT_UC3_H__
+#define __ENDPOINT_UC3_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../USBTask.h"
+ #include "../USBInterrupt.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define ENDPOINT_HSB_ADDRESS_SPACE_SIZE (64 * 1024UL)
+
+ /* Inline Functions: */
+ static inline uint32_t Endpoint_BytesToEPSizeMask(const uint16_t Bytes) ATTR_WARN_UNUSED_RESULT ATTR_CONST
+ ATTR_ALWAYS_INLINE;
+ static inline uint32_t Endpoint_BytesToEPSizeMask(const uint16_t Bytes)
+ {
+ uint8_t MaskVal = 0;
+ uint16_t CheckBytes = 8;
+
+ while (CheckBytes < Bytes)
+ {
+ MaskVal++;
+ CheckBytes <<= 1;
+ }
+
+ return (MaskVal << AVR32_USBB_EPSIZE_OFFSET);
+ }
+
+ /* Function Prototypes: */
+ void Endpoint_ClearEndpoints(void);
+ bool Endpoint_ConfigureEndpoint_Prv(const uint8_t Number,
+ const uint32_t UECFGXData);
+
+ /* External Variables: */
+ extern volatile uint32_t USB_Endpoint_SelectedEndpoint;
+ extern volatile uint8_t* USB_Endpoint_FIFOPos[];
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ #if (!defined(FIXED_CONTROL_ENDPOINT_SIZE) || defined(__DOXYGEN__))
+ /** Default size of the default control endpoint's bank, until altered by the control endpoint bank size
+ * value in the device descriptor. Not available if the \c FIXED_CONTROL_ENDPOINT_SIZE token is defined.
+ */
+ #define ENDPOINT_CONTROLEP_DEFAULT_SIZE 8
+ #endif
+
+ #if !defined(CONTROL_ONLY_DEVICE) || defined(__DOXYGEN__)
+ #if defined(USB_SERIES_UC3A3_AVR32) || defined(USB_SERIES_UC3A4_AVR32)
+ #define ENDPOINT_TOTAL_ENDPOINTS 8
+ #else
+ /** Total number of endpoints (including the default control endpoint at address 0) which may
+ * be used in the device. Different AVR models support different amounts of endpoints,
+ * this value reflects the maximum number of endpoints for the currently selected AVR model.
+ */
+ #define ENDPOINT_TOTAL_ENDPOINTS 7
+ #endif
+ #else
+ #define ENDPOINT_TOTAL_ENDPOINTS 1
+ #endif
+
+ /* Enums: */
+ /** Enum for the possible error return codes of the \ref Endpoint_WaitUntilReady() function.
+ *
+ * \ingroup Group_EndpointRW_UC3
+ */
+ enum Endpoint_WaitUntilReady_ErrorCodes_t
+ {
+ ENDPOINT_READYWAIT_NoError = 0, /**< Endpoint is ready for next packet, no error. */
+ ENDPOINT_READYWAIT_EndpointStalled = 1, /**< The endpoint was stalled during the stream
+ * transfer by the host or device.
+ */
+ ENDPOINT_READYWAIT_DeviceDisconnected = 2, /**< Device was disconnected from the host while
+ * waiting for the endpoint to become ready.
+ */
+ ENDPOINT_READYWAIT_BusSuspended = 3, /**< The USB bus has been suspended by the host and
+ * no USB endpoint traffic can occur until the bus
+ * has resumed.
+ */
+ ENDPOINT_READYWAIT_Timeout = 4, /**< The host failed to accept or send the next packet
+ * within the software timeout period set by the
+ * \ref USB_STREAM_TIMEOUT_MS macro.
+ */
+ };
+
+ /* Inline Functions: */
+ /** Configures the specified endpoint address with the given endpoint type, bank size and number of hardware
+ * banks. Once configured, the endpoint may be read from or written to, depending on its direction.
+ *
+ * \param[in] Address Endpoint address to configure.
+ *
+ * \param[in] Type Type of endpoint to configure, a \c EP_TYPE_* mask. Not all endpoint types
+ * are available on Low Speed USB devices - refer to the USB 2.0 specification.
+ *
+ * \param[in] Size Size of the endpoint's bank, where packets are stored before they are transmitted
+ * to the USB host, or after they have been received from the USB host (depending on
+ * the endpoint's data direction). The bank size must indicate the maximum packet size
+ * that the endpoint can handle.
+ *
+ * \param[in] Banks Number of hardware banks to use for the endpoint being configured.
+ *
+ * \attention When the \c ORDERED_EP_CONFIG compile time option is used, Endpoints <b>must</b> be configured in
+ * ascending order, or bank corruption will occur.
+ *
+ * \note Different endpoints may have different maximum packet sizes based on the endpoint's index - refer to
+ * the chosen microcontroller model's datasheet to determine the maximum bank size for each endpoint.
+ * \n\n
+ *
+ * \note The default control endpoint should not be manually configured by the user application, as
+ * it is automatically configured by the library internally.
+ * \n\n
+ *
+ * \note This routine will automatically select the specified endpoint upon success. Upon failure, the endpoint
+ * which failed to reconfigure correctly will be selected.
+ *
+ * \return Boolean \c true if the configuration succeeded, \c false otherwise.
+ */
+ static inline bool Endpoint_ConfigureEndpoint(const uint8_t Address,
+ const uint8_t Type,
+ const uint16_t Size,
+ const uint8_t Banks) ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_ConfigureEndpoint(const uint8_t Address,
+ const uint8_t Type,
+ const uint16_t Size,
+ const uint8_t Banks)
+ {
+ uint8_t Number = (Address & ENDPOINT_EPNUM_MASK);
+
+ if (Number >= ENDPOINT_TOTAL_ENDPOINTS)
+ return false;
+
+ return Endpoint_ConfigureEndpoint_Prv(Number,
+ (AVR32_USBB_ALLOC_MASK |
+ ((uint32_t)Type << AVR32_USBB_EPTYPE_OFFSET) |
+ ((Address & ENDPOINT_DIR_IN) ? AVR32_USBB_UECFG0_EPDIR_MASK : 0) |
+ ((Banks > 1) ? AVR32_USBB_UECFG0_EPBK_SINGLE : AVR32_USBB_UECFG0_EPBK_DOUBLE) |
+ Endpoint_BytesToEPSizeMask(Size)));
+ }
+
+ /** Indicates the number of bytes currently stored in the current endpoint's selected bank.
+ *
+ * \ingroup Group_EndpointRW_UC3
+ *
+ * \return Total number of bytes in the currently selected Endpoint's FIFO buffer.
+ */
+ static inline uint16_t Endpoint_BytesInEndpoint(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint16_t Endpoint_BytesInEndpoint(void)
+ {
+ return (&AVR32_USBB.UESTA0)[USB_Endpoint_SelectedEndpoint].byct;
+ }
+
+ /** Determines the currently selected endpoint's direction.
+ *
+ * \return The currently selected endpoint's direction, as a \c ENDPOINT_DIR_* mask.
+ */
+ static inline uint32_t Endpoint_GetEndpointDirection(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint32_t Endpoint_GetEndpointDirection(void)
+ {
+ return ((&AVR32_USBB.UECFG0)[USB_Endpoint_SelectedEndpoint].epdir ? ENDPOINT_DIR_IN : ENDPOINT_DIR_OUT);
+ }
+
+ /** Get the endpoint address of the currently selected endpoint. This is typically used to save
+ * the currently selected endpoint so that it can be restored after another endpoint has been
+ * manipulated.
+ *
+ * \return Index of the currently selected endpoint.
+ */
+ static inline uint8_t Endpoint_GetCurrentEndpoint(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Endpoint_GetCurrentEndpoint(void)
+ {
+ return (USB_Endpoint_SelectedEndpoint | Endpoint_GetEndpointDirection());
+ }
+
+ /** Selects the given endpoint address.
+ *
+ * Any endpoint operations which do not require the endpoint address to be indicated will operate on
+ * the currently selected endpoint.
+ *
+ * \param[in] Address Endpoint address to select.
+ */
+ static inline void Endpoint_SelectEndpoint(const uint8_t Address) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_SelectEndpoint(const uint8_t Address)
+ {
+ USB_Endpoint_SelectedEndpoint = (Address & ENDPOINT_EPNUM_MASK);
+ }
+
+ /** Resets the endpoint bank FIFO. This clears all the endpoint banks and resets the USB controller's
+ * data In and Out pointers to the bank's contents.
+ *
+ * \param[in] Address Endpoint number whose FIFO buffers are to be reset.
+ */
+ static inline void Endpoint_ResetEndpoint(const uint8_t Address) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_ResetEndpoint(const uint8_t Address)
+ {
+ uint32_t EndpointNumber = (Address & ENDPOINT_EPNUM_MASK);
+
+ AVR32_USBB.uerst |= (AVR32_USBB_EPRST0_MASK << EndpointNumber);
+ AVR32_USBB.uerst &= ~(AVR32_USBB_EPRST0_MASK << EndpointNumber);
+ USB_Endpoint_FIFOPos[EndpointNumber] = &AVR32_USBB_SLAVE[EndpointNumber * ENDPOINT_HSB_ADDRESS_SPACE_SIZE];
+ }
+
+ /** Enables the currently selected endpoint so that data can be sent and received through it to
+ * and from a host.
+ *
+ * \note Endpoints must first be configured properly via \ref Endpoint_ConfigureEndpoint().
+ */
+ static inline void Endpoint_EnableEndpoint(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_EnableEndpoint(void)
+ {
+ AVR32_USBB.uerst |= (AVR32_USBB_EPEN0_MASK << USB_Endpoint_SelectedEndpoint);
+ }
+
+ /** Disables the currently selected endpoint so that data cannot be sent and received through it
+ * to and from a host.
+ */
+ static inline void Endpoint_DisableEndpoint(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_DisableEndpoint(void)
+ {
+ AVR32_USBB.uerst &= ~(AVR32_USBB_EPEN0_MASK << USB_Endpoint_SelectedEndpoint);
+ }
+
+ /** Determines if the currently selected endpoint is enabled, but not necessarily configured.
+ *
+ * \return Boolean \c true if the currently selected endpoint is enabled, \c false otherwise.
+ */
+ static inline bool Endpoint_IsEnabled(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_IsEnabled(void)
+ {
+ return ((AVR32_USBB.uerst & (AVR32_USBB_EPEN0_MASK << USB_Endpoint_SelectedEndpoint)) ? true : false);
+ }
+
+ /** Retrieves the number of busy banks in the currently selected endpoint, which have been queued for
+ * transmission via the \ref Endpoint_ClearIN() command, or are awaiting acknowledgement via the
+ * \ref Endpoint_ClearOUT() command.
+ *
+ * \ingroup Group_EndpointPacketManagement_UC3
+ *
+ * \return Total number of busy banks in the selected endpoint.
+ */
+ static inline uint8_t Endpoint_GetBusyBanks(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline uint8_t Endpoint_GetBusyBanks(void)
+ {
+ return (&AVR32_USBB.UESTA0)[USB_Endpoint_SelectedEndpoint].nbusybk;
+ }
+
+ /** Aborts all pending IN transactions on the currently selected endpoint, once the bank
+ * has been queued for transmission to the host via \ref Endpoint_ClearIN(). This function
+ * will terminate all queued transactions, resetting the endpoint banks ready for a new
+ * packet.
+ *
+ * \ingroup Group_EndpointPacketManagement_UC3
+ */
+ static inline void Endpoint_AbortPendingIN(void)
+ {
+ while (Endpoint_GetBusyBanks() != 0)
+ {
+ (&AVR32_USBB.UECON0SET)[USB_Endpoint_SelectedEndpoint].killbks = true;
+ while ((&AVR32_USBB.UECON0)[USB_Endpoint_SelectedEndpoint].killbk);
+ }
+ }
+
+ /** Determines if the currently selected endpoint may be read from (if data is waiting in the endpoint
+ * bank and the endpoint is an OUT direction, or if the bank is not yet full if the endpoint is an IN
+ * direction). This function will return false if an error has occurred in the endpoint, if the endpoint
+ * is an OUT direction and no packet (or an empty packet) has been received, or if the endpoint is an IN
+ * direction and the endpoint bank is full.
+ *
+ * \ingroup Group_EndpointPacketManagement_UC3
+ *
+ * \return Boolean \c true if the currently selected endpoint may be read from or written to, depending
+ * on its direction.
+ */
+ static inline bool Endpoint_IsReadWriteAllowed(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_IsReadWriteAllowed(void)
+ {
+ return (&AVR32_USBB.UESTA0)[USB_Endpoint_SelectedEndpoint].rwall;
+ }
+
+ /** Determines if the currently selected endpoint is configured.
+ *
+ * \return Boolean \c true if the currently selected endpoint has been configured, \c false otherwise.
+ */
+ static inline bool Endpoint_IsConfigured(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_IsConfigured(void)
+ {
+ return (&AVR32_USBB.UESTA0)[USB_Endpoint_SelectedEndpoint].cfgok;
+ }
+
+ /** Returns a mask indicating which INTERRUPT type endpoints have interrupted - i.e. their
+ * interrupt duration has elapsed. Which endpoints have interrupted can be determined by
+ * masking the return value against <tt>(1 << <i>{Endpoint Number}</i>)</tt>.
+ *
+ * \return Mask whose bits indicate which endpoints have interrupted.
+ */
+ static inline uint32_t Endpoint_GetEndpointInterrupts(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint32_t Endpoint_GetEndpointInterrupts(void)
+ {
+ return ((AVR32_USBB.udint & (AVR32_USBB_EP6INT_MASK | AVR32_USBB_EP5INT_MASK |
+ AVR32_USBB_EP4INT_MASK | AVR32_USBB_EP3INT_MASK |
+ AVR32_USBB_EP2INT_MASK | AVR32_USBB_EP1INT_MASK |
+ AVR32_USBB_EP0INT_MASK)) >> AVR32_USBB_EP0INT_OFFSET);
+ }
+
+ /** Determines if the specified endpoint number has interrupted (valid only for INTERRUPT type
+ * endpoints).
+ *
+ * \param[in] Address Address of the endpoint whose interrupt flag should be tested.
+ *
+ * \return Boolean \c true if the specified endpoint has interrupted, \c false otherwise.
+ */
+ static inline bool Endpoint_HasEndpointInterrupted(const uint8_t Address) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_HasEndpointInterrupted(const uint8_t Address)
+ {
+ return ((Endpoint_GetEndpointInterrupts() & (AVR32_USBB_EP0INT_MASK << (Address & ENDPOINT_EPNUM_MASK))) ? true : false);
+ }
+
+ /** Determines if the selected IN endpoint is ready for a new packet to be sent to the host.
+ *
+ * \ingroup Group_EndpointPacketManagement_UC3
+ *
+ * \return Boolean \c true if the current endpoint is ready for an IN packet, \c false otherwise.
+ */
+ static inline bool Endpoint_IsINReady(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_IsINReady(void)
+ {
+ return (&AVR32_USBB.UESTA0)[USB_Endpoint_SelectedEndpoint].txini;
+ }
+
+ /** Determines if the selected OUT endpoint has received new packet from the host.
+ *
+ * \ingroup Group_EndpointPacketManagement_UC3
+ *
+ * \return Boolean \c true if current endpoint is has received an OUT packet, \c false otherwise.
+ */
+ static inline bool Endpoint_IsOUTReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_IsOUTReceived(void)
+ {
+ return (&AVR32_USBB.UESTA0)[USB_Endpoint_SelectedEndpoint].rxouti;
+ }
+
+ /** Determines if the current CONTROL type endpoint has received a SETUP packet.
+ *
+ * \ingroup Group_EndpointPacketManagement_UC3
+ *
+ * \return Boolean \c true if the selected endpoint has received a SETUP packet, \c false otherwise.
+ */
+ static inline bool Endpoint_IsSETUPReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_IsSETUPReceived(void)
+ {
+ return (&AVR32_USBB.UESTA0)[USB_Endpoint_SelectedEndpoint].rxstpi;
+ }
+
+ /** Clears a received SETUP packet on the currently selected CONTROL type endpoint, freeing up the
+ * endpoint for the next packet.
+ *
+ * \ingroup Group_EndpointPacketManagement_UC3
+ *
+ * \note This is not applicable for non CONTROL type endpoints.
+ */
+ static inline void Endpoint_ClearSETUP(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_ClearSETUP(void)
+ {
+ (&AVR32_USBB.UESTA0CLR)[USB_Endpoint_SelectedEndpoint].rxstpic = true;
+ USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint] = &AVR32_USBB_SLAVE[USB_Endpoint_SelectedEndpoint * ENDPOINT_HSB_ADDRESS_SPACE_SIZE];
+ }
+
+ /** Sends an IN packet to the host on the currently selected endpoint, freeing up the endpoint for the
+ * next packet and switching to the alternative endpoint bank if double banked.
+ *
+ * \ingroup Group_EndpointPacketManagement_UC3
+ */
+ static inline void Endpoint_ClearIN(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_ClearIN(void)
+ {
+ (&AVR32_USBB.UESTA0CLR)[USB_Endpoint_SelectedEndpoint].txinic = true;
+ (&AVR32_USBB.UECON0CLR)[USB_Endpoint_SelectedEndpoint].fifoconc = true;
+ USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint] = &AVR32_USBB_SLAVE[USB_Endpoint_SelectedEndpoint * ENDPOINT_HSB_ADDRESS_SPACE_SIZE];
+ }
+
+ /** Acknowledges an OUT packet to the host on the currently selected endpoint, freeing up the endpoint
+ * for the next packet and switching to the alternative endpoint bank if double banked.
+ *
+ * \ingroup Group_EndpointPacketManagement_UC3
+ */
+ static inline void Endpoint_ClearOUT(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_ClearOUT(void)
+ {
+ (&AVR32_USBB.UESTA0CLR)[USB_Endpoint_SelectedEndpoint].rxoutic = true;
+ (&AVR32_USBB.UECON0CLR)[USB_Endpoint_SelectedEndpoint].fifoconc = true;
+ USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint] = &AVR32_USBB_SLAVE[USB_Endpoint_SelectedEndpoint * ENDPOINT_HSB_ADDRESS_SPACE_SIZE];
+ }
+
+ /** Stalls the current endpoint, indicating to the host that a logical problem occurred with the
+ * indicated endpoint and that the current transfer sequence should be aborted. This provides a
+ * way for devices to indicate invalid commands to the host so that the current transfer can be
+ * aborted and the host can begin its own recovery sequence.
+ *
+ * The currently selected endpoint remains stalled until either the \ref Endpoint_ClearStall() macro
+ * is called, or the host issues a CLEAR FEATURE request to the device for the currently selected
+ * endpoint.
+ *
+ * \ingroup Group_EndpointPacketManagement_UC3
+ */
+ static inline void Endpoint_StallTransaction(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_StallTransaction(void)
+ {
+ (&AVR32_USBB.UECON0SET)[USB_Endpoint_SelectedEndpoint].stallrqs = true;
+ }
+
+ /** Clears the STALL condition on the currently selected endpoint.
+ *
+ * \ingroup Group_EndpointPacketManagement_UC3
+ */
+ static inline void Endpoint_ClearStall(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_ClearStall(void)
+ {
+ (&AVR32_USBB.UECON0CLR)[USB_Endpoint_SelectedEndpoint].stallrqc = true;
+ }
+
+ /** Determines if the currently selected endpoint is stalled, \c false otherwise.
+ *
+ * \ingroup Group_EndpointPacketManagement_UC3
+ *
+ * \return Boolean \c true if the currently selected endpoint is stalled, \c false otherwise.
+ */
+ static inline bool Endpoint_IsStalled(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_IsStalled(void)
+ {
+ return (&AVR32_USBB.UECON0)[USB_Endpoint_SelectedEndpoint].stallrq;
+ }
+
+ /** Resets the data toggle of the currently selected endpoint. */
+ static inline void Endpoint_ResetDataToggle(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_ResetDataToggle(void)
+ {
+ (&AVR32_USBB.UECON0SET)[USB_Endpoint_SelectedEndpoint].rstdts = true;
+ }
+
+ /** Sets the direction of the currently selected endpoint.
+ *
+ * \param[in] DirectionMask New endpoint direction, as a \c ENDPOINT_DIR_* mask.
+ */
+ static inline void Endpoint_SetEndpointDirection(const uint32_t DirectionMask) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_SetEndpointDirection(const uint32_t DirectionMask)
+ {
+ (&AVR32_USBB.UECFG0)[USB_Endpoint_SelectedEndpoint].epdir = (DirectionMask == ENDPOINT_DIR_IN);
+ }
+
+ /** Reads one byte from the currently selected endpoint's bank, for OUT direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_UC3
+ *
+ * \return Next byte in the currently selected endpoint's FIFO buffer.
+ */
+ static inline uint8_t Endpoint_Read_8(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Endpoint_Read_8(void)
+ {
+ return *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
+ }
+
+ /** Writes one byte to the currently selected endpoint's bank, for IN direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_UC3
+ *
+ * \param[in] Data Data to write into the the currently selected endpoint's FIFO buffer.
+ */
+ static inline void Endpoint_Write_8(const uint8_t Data) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_Write_8(const uint8_t Data)
+ {
+ *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++) = Data;
+ }
+
+ /** Discards one byte from the currently selected endpoint's bank, for OUT direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_UC3
+ */
+ static inline void Endpoint_Discard_8(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_Discard_8(void)
+ {
+ uint8_t Dummy;
+
+ Dummy = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
+
+ (void)Dummy;
+ }
+
+ /** Reads two bytes from the currently selected endpoint's bank in little endian format, for OUT
+ * direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_UC3
+ *
+ * \return Next two bytes in the currently selected endpoint's FIFO buffer.
+ */
+ static inline uint16_t Endpoint_Read_16_LE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint16_t Endpoint_Read_16_LE(void)
+ {
+ uint16_t Byte0 = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
+ uint16_t Byte1 = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
+
+ return ((Byte1 << 8) | Byte0);
+ }
+
+ /** Reads two bytes from the currently selected endpoint's bank in big endian format, for OUT
+ * direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_UC3
+ *
+ * \return Next two bytes in the currently selected endpoint's FIFO buffer.
+ */
+ static inline uint16_t Endpoint_Read_16_BE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint16_t Endpoint_Read_16_BE(void)
+ {
+ uint16_t Byte0 = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
+ uint16_t Byte1 = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
+
+ return ((Byte0 << 8) | Byte1);
+ }
+
+ /** Writes two bytes to the currently selected endpoint's bank in little endian format, for IN
+ * direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_UC3
+ *
+ * \param[in] Data Data to write to the currently selected endpoint's FIFO buffer.
+ */
+ static inline void Endpoint_Write_16_LE(const uint16_t Data) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_Write_16_LE(const uint16_t Data)
+ {
+ *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++) = (Data & 0xFF);
+ *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++) = (Data >> 8);
+ }
+
+ /** Writes two bytes to the currently selected endpoint's bank in big endian format, for IN
+ * direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_UC3
+ *
+ * \param[in] Data Data to write to the currently selected endpoint's FIFO buffer.
+ */
+ static inline void Endpoint_Write_16_BE(const uint16_t Data) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_Write_16_BE(const uint16_t Data)
+ {
+ *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++) = (Data >> 8);
+ *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++) = (Data & 0xFF);
+ }
+
+ /** Discards two bytes from the currently selected endpoint's bank, for OUT direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_UC3
+ */
+ static inline void Endpoint_Discard_16(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_Discard_16(void)
+ {
+ uint8_t Dummy;
+
+ Dummy = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
+ Dummy = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
+
+ (void)Dummy;
+ }
+
+ /** Reads four bytes from the currently selected endpoint's bank in little endian format, for OUT
+ * direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_UC3
+ *
+ * \return Next four bytes in the currently selected endpoint's FIFO buffer.
+ */
+ static inline uint32_t Endpoint_Read_32_LE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint32_t Endpoint_Read_32_LE(void)
+ {
+ uint32_t Byte0 = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
+ uint32_t Byte1 = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
+ uint32_t Byte2 = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
+ uint32_t Byte3 = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
+
+ return ((Byte3 << 24) | (Byte2 << 16) | (Byte1 << 8) | Byte0);
+ }
+
+ /** Reads four bytes from the currently selected endpoint's bank in big endian format, for OUT
+ * direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_UC3
+ *
+ * \return Next four bytes in the currently selected endpoint's FIFO buffer.
+ */
+ static inline uint32_t Endpoint_Read_32_BE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint32_t Endpoint_Read_32_BE(void)
+ {
+ uint32_t Byte0 = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
+ uint32_t Byte1 = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
+ uint32_t Byte2 = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
+ uint32_t Byte3 = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
+
+ return ((Byte0 << 24) | (Byte1 << 16) | (Byte2 << 8) | Byte3);
+ }
+
+ /** Writes four bytes to the currently selected endpoint's bank in little endian format, for IN
+ * direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_UC3
+ *
+ * \param[in] Data Data to write to the currently selected endpoint's FIFO buffer.
+ */
+ static inline void Endpoint_Write_32_LE(const uint32_t Data) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_Write_32_LE(const uint32_t Data)
+ {
+ *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++) = (Data & 0xFF);
+ *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++) = (Data >> 8);
+ *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++) = (Data >> 16);
+ *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++) = (Data >> 24);
+ }
+
+ /** Writes four bytes to the currently selected endpoint's bank in big endian format, for IN
+ * direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_UC3
+ *
+ * \param[in] Data Data to write to the currently selected endpoint's FIFO buffer.
+ */
+ static inline void Endpoint_Write_32_BE(const uint32_t Data) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_Write_32_BE(const uint32_t Data)
+ {
+ *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++) = (Data >> 24);
+ *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++) = (Data >> 16);
+ *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++) = (Data >> 8);
+ *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++) = (Data & 0xFF);
+ }
+
+ /** Discards four bytes from the currently selected endpoint's bank, for OUT direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_UC3
+ */
+ static inline void Endpoint_Discard_32(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_Discard_32(void)
+ {
+ uint8_t Dummy;
+
+ Dummy = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
+ Dummy = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
+ Dummy = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
+ Dummy = *(USB_Endpoint_FIFOPos[USB_Endpoint_SelectedEndpoint]++);
+
+ (void)Dummy;
+ }
+
+ /* External Variables: */
+ /** Global indicating the maximum packet size of the default control endpoint located at address
+ * 0 in the device. This value is set to the value indicated in the device descriptor in the user
+ * project once the USB interface is initialized into device mode.
+ *
+ * If space is an issue, it is possible to fix this to a static value by defining the control
+ * endpoint size in the \c FIXED_CONTROL_ENDPOINT_SIZE token passed to the compiler in the makefile
+ * via the -D switch. When a fixed control endpoint size is used, the size is no longer dynamically
+ * read from the descriptors at runtime and instead fixed to the given value. When used, it is
+ * important that the descriptor control endpoint size value matches the size given as the
+ * \c FIXED_CONTROL_ENDPOINT_SIZE token - it is recommended that the \c FIXED_CONTROL_ENDPOINT_SIZE token
+ * be used in the device descriptors to ensure this.
+ *
+ * \attention This variable should be treated as read-only in the user application, and never manually
+ * changed in value.
+ */
+ #if (!defined(FIXED_CONTROL_ENDPOINT_SIZE) || defined(__DOXYGEN__))
+ extern uint8_t USB_Device_ControlEndpointSize;
+ #else
+ #define USB_Device_ControlEndpointSize FIXED_CONTROL_ENDPOINT_SIZE
+ #endif
+
+ /* Function Prototypes: */
+ /** Configures a table of endpoint descriptions, in sequence. This function can be used to configure multiple
+ * endpoints at the same time.
+ *
+ * \note Endpoints with a zero address will be ignored, thus this function cannot be used to configure the
+ * control endpoint.
+ *
+ * \param[in] Table Pointer to a table of endpoint descriptions.
+ * \param[in] Entries Number of entries in the endpoint table to configure.
+ *
+ * \return Boolean \c true if all endpoints configured successfully, \c false otherwise.
+ */
+ bool Endpoint_ConfigureEndpointTable(const USB_Endpoint_Table_t* const Table,
+ const uint8_t Entries);
+
+ /** Completes the status stage of a control transfer on a CONTROL type endpoint automatically,
+ * with respect to the data direction. This is a convenience function which can be used to
+ * simplify user control request handling.
+ *
+ * \note This routine should not be called on non CONTROL type endpoints.
+ */
+ void Endpoint_ClearStatusStage(void);
+
+ /** Spin-loops until the currently selected non-control endpoint is ready for the next packet of data
+ * to be read or written to it.
+ *
+ * \note This routine should not be called on CONTROL type endpoints.
+ *
+ * \ingroup Group_EndpointRW_UC3
+ *
+ * \return A value from the \ref Endpoint_WaitUntilReady_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_WaitUntilReady(void);
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Host_UC3.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Host_UC3.c
new file mode 100644
index 000000000..77807525f
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Host_UC3.c
@@ -0,0 +1,297 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "../../../../Common/Common.h"
+#if (ARCH == ARCH_UC3)
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../USBMode.h"
+
+#if defined(USB_CAN_BE_HOST)
+
+#define __INCLUDE_FROM_HOST_C
+#include "../Host.h"
+
+void USB_Host_ProcessNextHostState(void)
+{
+ uint8_t ErrorCode = HOST_ENUMERROR_NoError;
+ uint8_t SubErrorCode = HOST_ENUMERROR_NoError;
+
+ static uint16_t WaitMSRemaining;
+ static uint8_t PostWaitState;
+
+ switch (USB_HostState)
+ {
+ case HOST_STATE_WaitForDevice:
+ if (WaitMSRemaining)
+ {
+ if ((SubErrorCode = USB_Host_WaitMS(1)) != HOST_WAITERROR_Successful)
+ {
+ USB_HostState = PostWaitState;
+ ErrorCode = HOST_ENUMERROR_WaitStage;
+ break;
+ }
+
+ if (!(--WaitMSRemaining))
+ USB_HostState = PostWaitState;
+ }
+
+ break;
+ case HOST_STATE_Powered:
+ WaitMSRemaining = HOST_DEVICE_SETTLE_DELAY_MS;
+
+ USB_HostState = HOST_STATE_Powered_WaitForDeviceSettle;
+ break;
+ case HOST_STATE_Powered_WaitForDeviceSettle:
+ if (WaitMSRemaining--)
+ {
+ Delay_MS(1);
+ break;
+ }
+ else
+ {
+ USB_Host_VBUS_Manual_Off();
+
+ USB_OTGPAD_On();
+ USB_Host_VBUS_Auto_Enable();
+ USB_Host_VBUS_Auto_On();
+
+ #if defined(NO_AUTO_VBUS_MANAGEMENT)
+ USB_Host_VBUS_Manual_Enable();
+ USB_Host_VBUS_Manual_On();
+ #endif
+
+ USB_HostState = HOST_STATE_Powered_WaitForConnect;
+ }
+
+ break;
+ case HOST_STATE_Powered_WaitForConnect:
+ if (USB_INT_HasOccurred(USB_INT_DCONNI))
+ {
+ USB_INT_Clear(USB_INT_DCONNI);
+ USB_INT_Clear(USB_INT_DDISCI);
+
+ USB_INT_Clear(USB_INT_VBERRI);
+ USB_INT_Enable(USB_INT_VBERRI);
+
+ USB_Host_ResumeBus();
+ Pipe_ClearPipes();
+
+ HOST_TASK_NONBLOCK_WAIT(100, HOST_STATE_Powered_DoReset);
+ }
+
+ break;
+ case HOST_STATE_Powered_DoReset:
+ USB_Host_ResetDevice();
+
+ HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Powered_ConfigPipe);
+ break;
+ case HOST_STATE_Powered_ConfigPipe:
+ if (!(Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL, ENDPOINT_CONTROLEP, PIPE_CONTROLPIPE_DEFAULT_SIZE, 1)))
+ {
+ ErrorCode = HOST_ENUMERROR_PipeConfigError;
+ SubErrorCode = 0;
+ break;
+ }
+
+ USB_HostState = HOST_STATE_Default;
+ break;
+ case HOST_STATE_Default:
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE),
+ .bRequest = REQ_GetDescriptor,
+ .wValue = (DTYPE_Device << 8),
+ .wIndex = 0,
+ .wLength = 8,
+ };
+
+ uint8_t DataBuffer[8];
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+ if ((SubErrorCode = USB_Host_SendControlRequest(DataBuffer)) != HOST_SENDCONTROL_Successful)
+ {
+ ErrorCode = HOST_ENUMERROR_ControlError;
+ break;
+ }
+
+ USB_Host_ControlPipeSize = DataBuffer[offsetof(USB_Descriptor_Device_t, Endpoint0Size)];
+
+ USB_Host_ResetDevice();
+
+ HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Default_PostReset);
+ break;
+ case HOST_STATE_Default_PostReset:
+ if (!(Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL, ENDPOINT_CONTROLEP, USB_Host_ControlPipeSize, 1)))
+ {
+ ErrorCode = HOST_ENUMERROR_PipeConfigError;
+ SubErrorCode = 0;
+ break;
+ }
+
+ USB_ControlRequest = (USB_Request_Header_t)
+ {
+ .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_DEVICE),
+ .bRequest = REQ_SetAddress,
+ .wValue = USB_HOST_DEVICEADDRESS,
+ .wIndex = 0,
+ .wLength = 0,
+ };
+
+ if ((SubErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
+ {
+ ErrorCode = HOST_ENUMERROR_ControlError;
+ break;
+ }
+
+ HOST_TASK_NONBLOCK_WAIT(100, HOST_STATE_Default_PostAddressSet);
+ break;
+ case HOST_STATE_Default_PostAddressSet:
+ USB_Host_SetDeviceAddress(USB_HOST_DEVICEADDRESS);
+
+ USB_HostState = HOST_STATE_Addressed;
+
+ EVENT_USB_Host_DeviceEnumerationComplete();
+ break;
+
+ default:
+ break;
+ }
+
+ if ((ErrorCode != HOST_ENUMERROR_NoError) && (USB_HostState != HOST_STATE_Unattached))
+ {
+ EVENT_USB_Host_DeviceEnumerationFailed(ErrorCode, SubErrorCode);
+
+ USB_Host_VBUS_Auto_Off();
+
+ EVENT_USB_Host_DeviceUnattached();
+
+ USB_ResetInterface();
+ }
+}
+
+uint8_t USB_Host_WaitMS(uint8_t MS)
+{
+ bool BusSuspended = USB_Host_IsBusSuspended();
+ uint8_t ErrorCode = HOST_WAITERROR_Successful;
+ bool HSOFIEnabled = USB_INT_IsEnabled(USB_INT_HSOFI);
+
+ USB_INT_Disable(USB_INT_HSOFI);
+ USB_INT_Clear(USB_INT_HSOFI);
+
+ USB_Host_ResumeBus();
+
+ while (MS)
+ {
+ if (USB_INT_HasOccurred(USB_INT_HSOFI))
+ {
+ USB_INT_Clear(USB_INT_HSOFI);
+ MS--;
+ }
+
+ if ((USB_HostState == HOST_STATE_Unattached) || (USB_CurrentMode != USB_MODE_Host))
+ {
+ ErrorCode = HOST_WAITERROR_DeviceDisconnect;
+
+ break;
+ }
+
+ if (Pipe_IsError())
+ {
+ Pipe_ClearError();
+ ErrorCode = HOST_WAITERROR_PipeError;
+
+ break;
+ }
+
+ if (Pipe_IsStalled())
+ {
+ Pipe_ClearStall();
+ ErrorCode = HOST_WAITERROR_SetupStalled;
+
+ break;
+ }
+ }
+
+ if (BusSuspended)
+ USB_Host_SuspendBus();
+
+ if (HSOFIEnabled)
+ USB_INT_Enable(USB_INT_HSOFI);
+
+ return ErrorCode;
+}
+
+static void USB_Host_ResetDevice(void)
+{
+ bool BusSuspended = USB_Host_IsBusSuspended();
+
+ USB_INT_Disable(USB_INT_DDISCI);
+
+ USB_Host_ResetBus();
+ while (!(USB_Host_IsBusResetComplete()));
+ USB_Host_ResumeBus();
+
+ USB_Host_ConfigurationNumber = 0;
+
+ bool HSOFIEnabled = USB_INT_IsEnabled(USB_INT_HSOFI);
+
+ USB_INT_Disable(USB_INT_HSOFI);
+ USB_INT_Clear(USB_INT_HSOFI);
+
+ for (uint8_t MSRem = 10; MSRem != 0; MSRem--)
+ {
+ /* Workaround for powerless-pull-up devices. After a USB bus reset,
+ all disconnection interrupts are suppressed while a USB frame is
+ looked for - if it is found within 10ms, the device is still
+ present. */
+
+ if (USB_INT_HasOccurred(USB_INT_HSOFI))
+ {
+ USB_INT_Clear(USB_INT_HSOFI);
+ USB_INT_Clear(USB_INT_DDISCI);
+ break;
+ }
+
+ Delay_MS(1);
+ }
+
+ if (HSOFIEnabled)
+ USB_INT_Enable(USB_INT_HSOFI);
+
+ if (BusSuspended)
+ USB_Host_SuspendBus();
+
+ USB_INT_Enable(USB_INT_DDISCI);
+}
+
+#endif
+
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Host_UC3.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Host_UC3.h
new file mode 100644
index 000000000..eb803b073
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Host_UC3.h
@@ -0,0 +1,363 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief USB Host definitions for the AVR32 UC3B microcontrollers.
+ * \copydetails Group_Host_UC3B
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_Host
+ * \defgroup Group_Host_UC3B Host Management (UC3B)
+ * \brief USB Host definitions for the AVR32 UC3B microcontrollers.
+ *
+ * Architecture specific USB Host definitions for the Atmel 32-bit AVR UC3B microcontrollers.
+ *
+ * @{
+ */
+
+#ifndef __USBHOST_UC3B_H__
+#define __USBHOST_UC3B_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../StdDescriptors.h"
+ #include "../Pipe.h"
+ #include "../USBInterrupt.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the fixed USB device address which any attached device is enumerated to when in
+ * host mode. As only one USB device may be attached to the AVR in host mode at any one time
+ * and that the address used is not important (other than the fact that it is non-zero), a
+ * fixed value is specified by the library.
+ */
+ #define USB_HOST_DEVICEADDRESS 1
+
+ #if !defined(HOST_DEVICE_SETTLE_DELAY_MS) || defined(__DOXYGEN__)
+ /** Constant for the delay in milliseconds after a device is connected before the library
+ * will start the enumeration process. Some devices require a delay of up to 5 seconds
+ * after connection before the enumeration process can start or incorrect operation will
+ * occur.
+ *
+ * The default delay value may be overridden in the user project makefile by defining the
+ * \c HOST_DEVICE_SETTLE_DELAY_MS token to the required delay in milliseconds, and passed to the
+ * compiler using the -D switch.
+ */
+ #define HOST_DEVICE_SETTLE_DELAY_MS 1000
+ #endif
+
+ /* Enums: */
+ /** Enum for the error codes for the \ref EVENT_USB_Host_HostError() event.
+ *
+ * \see \ref Group_Events for more information on this event.
+ */
+ enum USB_Host_ErrorCodes_t
+ {
+ HOST_ERROR_VBusVoltageDip = 0, /**< VBUS voltage dipped to an unacceptable level. This
+ * error may be the result of an attached device drawing
+ * too much current from the VBUS line, or due to the
+ * AVR's power source being unable to supply sufficient
+ * current.
+ */
+ };
+
+ /** Enum for the error codes for the \ref EVENT_USB_Host_DeviceEnumerationFailed() event.
+ *
+ * \see \ref Group_Events for more information on this event.
+ */
+ enum USB_Host_EnumerationErrorCodes_t
+ {
+ HOST_ENUMERROR_NoError = 0, /**< No error occurred. Used internally, this is not a valid
+ * ErrorCode parameter value for the \ref EVENT_USB_Host_DeviceEnumerationFailed()
+ * event.
+ */
+ HOST_ENUMERROR_WaitStage = 1, /**< One of the delays between enumeration steps failed
+ * to complete successfully, due to a timeout or other
+ * error.
+ */
+ HOST_ENUMERROR_NoDeviceDetected = 2, /**< No device was detected, despite the USB data lines
+ * indicating the attachment of a device.
+ */
+ HOST_ENUMERROR_ControlError = 3, /**< One of the enumeration control requests failed to
+ * complete successfully.
+ */
+ HOST_ENUMERROR_PipeConfigError = 4, /**< The default control pipe (address 0) failed to
+ * configure correctly.
+ */
+ };
+
+ /* Inline Functions: */
+ /** Returns the current USB frame number, when in host mode. Every millisecond the USB bus is active (i.e. not suspended)
+ * the frame number is incremented by one.
+ *
+ * \return Current USB frame number from the USB controller.
+ */
+ static inline uint16_t USB_Host_GetFrameNumber(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint16_t USB_Host_GetFrameNumber(void)
+ {
+ return AVR32_USBB_UHFNUM;
+ }
+
+ #if !defined(NO_SOF_EVENTS)
+ /** Enables the host mode Start Of Frame events. When enabled, this causes the
+ * \ref EVENT_USB_Host_StartOfFrame() event to fire once per millisecond, synchronized to the USB bus,
+ * at the start of each USB frame when a device is enumerated while in host mode.
+ *
+ * \note This function is not available when the \c NO_SOF_EVENTS compile time token is defined.
+ */
+ static inline void USB_Host_EnableSOFEvents(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_EnableSOFEvents(void)
+ {
+ USB_INT_Enable(USB_INT_HSOFI);
+ }
+
+ /** Disables the host mode Start Of Frame events. When disabled, this stops the firing of the
+ * \ref EVENT_USB_Host_StartOfFrame() event when enumerated in host mode.
+ *
+ * \note This function is not available when the \c NO_SOF_EVENTS compile time token is defined.
+ */
+ static inline void USB_Host_DisableSOFEvents(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_DisableSOFEvents(void)
+ {
+ USB_INT_Disable(USB_INT_HSOFI);
+ }
+ #endif
+
+ /** Resets the USB bus, including the endpoints in any attached device and pipes on the AVR host.
+ * USB bus resets leave the default control pipe configured (if already configured).
+ *
+ * If the USB bus has been suspended prior to issuing a bus reset, the attached device will be
+ * woken up automatically and the bus resumed after the reset has been correctly issued.
+ */
+ static inline void USB_Host_ResetBus(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_ResetBus(void)
+ {
+ AVR32_USBB.UHCON.reset = true;
+ }
+
+ /** Determines if a previously issued bus reset (via the \ref USB_Host_ResetBus() macro) has
+ * completed.
+ *
+ * \return Boolean \c true if no bus reset is currently being sent, \c false otherwise.
+ */
+ static inline bool USB_Host_IsBusResetComplete(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool USB_Host_IsBusResetComplete(void)
+ {
+ return AVR32_USBB.UHCON.reset;
+ }
+
+ /** Resumes USB communications with an attached and enumerated device, by resuming the transmission
+ * of the 1MS Start Of Frame messages to the device. When resumed, USB communications between the
+ * host and attached device may occur.
+ */
+ static inline void USB_Host_ResumeBus(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_ResumeBus(void)
+ {
+ AVR32_USBB.UHCON.sofe = true;
+ }
+
+ /** Suspends the USB bus, preventing any communications from occurring between the host and attached
+ * device until the bus has been resumed. This stops the transmission of the 1MS Start Of Frame
+ * messages to the device.
+ *
+ * \note While the USB bus is suspended, all USB interrupt sources are also disabled; this means that
+ * some events (such as device disconnections) will not fire until the bus is resumed.
+ */
+ static inline void USB_Host_SuspendBus(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_SuspendBus(void)
+ {
+ AVR32_USBB.UHCON.sofe = false;
+ }
+
+ /** Determines if the USB bus has been suspended via the use of the \ref USB_Host_SuspendBus() macro,
+ * false otherwise. While suspended, no USB communications can occur until the bus is resumed,
+ * except for the Remote Wakeup event from the device if supported.
+ *
+ * \return Boolean \c true if the bus is currently suspended, \c false otherwise.
+ */
+ static inline bool USB_Host_IsBusSuspended(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool USB_Host_IsBusSuspended(void)
+ {
+ return AVR32_USBB.UHCON.sofe;
+ }
+
+ /** Determines if the attached device is currently enumerated in Full Speed mode (12Mb/s), or
+ * false if the attached device is enumerated in Low Speed mode (1.5Mb/s).
+ *
+ * \return Boolean \c true if the attached device is enumerated in Full Speed mode, \c false otherwise.
+ */
+ static inline bool USB_Host_IsDeviceFullSpeed(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool USB_Host_IsDeviceFullSpeed(void)
+ {
+ return (AVR32_USBB.USBSTA.speed == AVR32_USBB_SPEED_FULL);
+ }
+
+ /** Determines if the attached device is currently issuing a Remote Wakeup request, requesting
+ * that the host resume the USB bus and wake up the device, \c false otherwise.
+ *
+ * \return Boolean \c true if the attached device has sent a Remote Wakeup request, \c false otherwise.
+ */
+ static inline bool USB_Host_IsRemoteWakeupSent(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool USB_Host_IsRemoteWakeupSent(void)
+ {
+ return AVR32_USBB.UHINT.rxrsmi;
+ }
+
+ /** Clears the flag indicating that a Remote Wakeup request has been issued by an attached device. */
+ static inline void USB_Host_ClearRemoteWakeupSent(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_ClearRemoteWakeupSent(void)
+ {
+ AVR32_USBB.UHINTCLR.rxrsmic = true;
+ }
+
+ /** Accepts a Remote Wakeup request from an attached device. This must be issued in response to
+ * a device's Remote Wakeup request within 2ms for the request to be accepted and the bus to
+ * be resumed.
+ */
+ static inline void USB_Host_ResumeFromWakeupRequest(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_ResumeFromWakeupRequest(void)
+ {
+ AVR32_USBB.UHCON.resume = true;
+ }
+
+ /** Determines if a resume from Remote Wakeup request is currently being sent to an attached
+ * device.
+ *
+ * \return Boolean \c true if no resume request is currently being sent, \c false otherwise.
+ */
+ static inline bool USB_Host_IsResumeFromWakeupRequestSent(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool USB_Host_IsResumeFromWakeupRequestSent(void)
+ {
+ return AVR32_USBB.UHCON.resume;
+ }
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ static inline void USB_Host_HostMode_On(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_HostMode_On(void)
+ {
+ // Not required for UC3B
+ }
+
+ static inline void USB_Host_HostMode_Off(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_HostMode_Off(void)
+ {
+ // Not required for UC3B
+ }
+
+ static inline void USB_Host_VBUS_Auto_Enable(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_VBUS_Auto_Enable(void)
+ {
+ AVR32_USBB.USBCON.vbushwc = false;
+ }
+
+ static inline void USB_Host_VBUS_Manual_Enable(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_VBUS_Manual_Enable(void)
+ {
+ AVR32_USBB.USBCON.vbushwc = true;
+ }
+
+ static inline void USB_Host_VBUS_Auto_On(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_VBUS_Auto_On(void)
+ {
+ AVR32_USBB.USBSTASET.vbusrqs = true;
+ }
+
+ static inline void USB_Host_VBUS_Manual_On(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_VBUS_Manual_On(void)
+ {
+ AVR32_USBB.USBSTASET.vbusrqs = true;
+ }
+
+ static inline void USB_Host_VBUS_Auto_Off(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_VBUS_Auto_Off(void)
+ {
+ AVR32_USBB.USBSTACLR.vbusrqc = true;
+ }
+
+ static inline void USB_Host_VBUS_Manual_Off(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_VBUS_Manual_Off(void)
+ {
+ AVR32_USBB.USBSTACLR.vbusrqc = true;
+ }
+
+ static inline void USB_Host_SetDeviceAddress(const uint8_t Address) ATTR_ALWAYS_INLINE;
+ static inline void USB_Host_SetDeviceAddress(const uint8_t Address)
+ {
+ AVR32_USBB.UHADDR1.uhaddr_p0 = Address;
+ AVR32_USBB.UHADDR1.uhaddr_p1 = Address;
+ AVR32_USBB.UHADDR1.uhaddr_p2 = Address;
+ AVR32_USBB.UHADDR1.uhaddr_p3 = Address;
+ AVR32_USBB.UHADDR2.uhaddr_p4 = Address;
+ AVR32_USBB.UHADDR2.uhaddr_p5 = Address;
+ AVR32_USBB.UHADDR2.uhaddr_p6 = Address;
+ }
+
+ /* Enums: */
+ enum USB_Host_WaitMSErrorCodes_t
+ {
+ HOST_WAITERROR_Successful = 0,
+ HOST_WAITERROR_DeviceDisconnect = 1,
+ HOST_WAITERROR_PipeError = 2,
+ HOST_WAITERROR_SetupStalled = 3,
+ };
+
+ /* Function Prototypes: */
+ void USB_Host_ProcessNextHostState(void);
+ uint8_t USB_Host_WaitMS(uint8_t MS);
+
+ #if defined(__INCLUDE_FROM_HOST_C)
+ static void USB_Host_ResetDevice(void);
+ #endif
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/PipeStream_UC3.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/PipeStream_UC3.c
new file mode 100644
index 000000000..7dfe44858
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/PipeStream_UC3.c
@@ -0,0 +1,166 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "../../../../Common/Common.h"
+#if (ARCH == ARCH_UC3)
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../USBMode.h"
+
+#if defined(USB_CAN_BE_HOST)
+
+#include "PipeStream_UC3.h"
+
+uint8_t Pipe_Discard_Stream(uint16_t Length,
+ uint16_t* const BytesProcessed)
+{
+ uint8_t ErrorCode;
+ uint16_t BytesInTransfer = 0;
+
+ Pipe_SetPipeToken(PIPE_TOKEN_IN);
+
+ if ((ErrorCode = Pipe_WaitUntilReady()))
+ return ErrorCode;
+
+ if (BytesProcessed != NULL)
+ Length -= *BytesProcessed;
+
+ while (Length)
+ {
+ if (!(Pipe_IsReadWriteAllowed()))
+ {
+ Pipe_ClearIN();
+
+ if (BytesProcessed != NULL)
+ {
+ *BytesProcessed += BytesInTransfer;
+ return PIPE_RWSTREAM_IncompleteTransfer;
+ }
+
+ if ((ErrorCode = Pipe_WaitUntilReady()))
+ return ErrorCode;
+ }
+ else
+ {
+ Pipe_Discard_8();
+
+ Length--;
+ BytesInTransfer++;
+ }
+ }
+
+ return PIPE_RWSTREAM_NoError;
+}
+
+uint8_t Pipe_Null_Stream(uint16_t Length,
+ uint16_t* const BytesProcessed)
+{
+ uint8_t ErrorCode;
+ uint16_t BytesInTransfer = 0;
+
+ Pipe_SetPipeToken(PIPE_TOKEN_OUT);
+
+ if ((ErrorCode = Pipe_WaitUntilReady()))
+ return ErrorCode;
+
+ if (BytesProcessed != NULL)
+ Length -= *BytesProcessed;
+
+ while (Length)
+ {
+ if (!(Pipe_IsReadWriteAllowed()))
+ {
+ Pipe_ClearOUT();
+
+ if (BytesProcessed != NULL)
+ {
+ *BytesProcessed += BytesInTransfer;
+ return PIPE_RWSTREAM_IncompleteTransfer;
+ }
+
+ USB_USBTask();
+
+ if ((ErrorCode = Pipe_WaitUntilReady()))
+ return ErrorCode;
+ }
+ else
+ {
+ Pipe_Write_8(0);
+
+ Length--;
+ BytesInTransfer++;
+ }
+ }
+
+ return PIPE_RWSTREAM_NoError;
+}
+
+/* The following abuses the C preprocessor in order to copy-paste common code with slight alterations,
+ * so that the code needs to be written once. It is a crude form of templating to reduce code maintenance. */
+
+#define TEMPLATE_FUNC_NAME Pipe_Write_Stream_LE
+#define TEMPLATE_BUFFER_TYPE const void*
+#define TEMPLATE_TOKEN PIPE_TOKEN_OUT
+#define TEMPLATE_CLEAR_PIPE() Pipe_ClearOUT()
+#define TEMPLATE_BUFFER_OFFSET(Length) 0
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) DataStream += Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Pipe_Write_8(*BufferPtr)
+#include "Template/Template_Pipe_RW.c"
+
+#define TEMPLATE_FUNC_NAME Pipe_Write_Stream_BE
+#define TEMPLATE_BUFFER_TYPE const void*
+#define TEMPLATE_TOKEN PIPE_TOKEN_OUT
+#define TEMPLATE_CLEAR_PIPE() Pipe_ClearOUT()
+#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) DataStream -= Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Pipe_Write_8(*BufferPtr)
+#include "Template/Template_Pipe_RW.c"
+
+#define TEMPLATE_FUNC_NAME Pipe_Read_Stream_LE
+#define TEMPLATE_BUFFER_TYPE void*
+#define TEMPLATE_TOKEN PIPE_TOKEN_IN
+#define TEMPLATE_CLEAR_PIPE() Pipe_ClearIN()
+#define TEMPLATE_BUFFER_OFFSET(Length) 0
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) DataStream += Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) *BufferPtr = Pipe_Read_8()
+#include "Template/Template_Pipe_RW.c"
+
+#define TEMPLATE_FUNC_NAME Pipe_Read_Stream_BE
+#define TEMPLATE_BUFFER_TYPE void*
+#define TEMPLATE_TOKEN PIPE_TOKEN_IN
+#define TEMPLATE_CLEAR_PIPE() Pipe_ClearIN()
+#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) DataStream -= Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) *BufferPtr = Pipe_Read_8()
+#include "Template/Template_Pipe_RW.c"
+
+#endif
+
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/PipeStream_UC3.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/PipeStream_UC3.h
new file mode 100644
index 000000000..4dd79c975
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/PipeStream_UC3.h
@@ -0,0 +1,352 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Pipe data stream transmission and reception management for the AVR32 UC3 microcontrollers.
+ * \copydetails Group_PipeStreamRW_UC3
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_PipeStreamRW
+ * \defgroup Group_PipeStreamRW_UC3 Read/Write of Multi-Byte Streams (UC3)
+ * \brief Pipe data stream transmission and reception management for the Atmel AVR32 UC3 architecture.
+ *
+ * Functions, macros, variables, enums and types related to data reading and writing of data streams from
+ * and to pipes.
+ *
+ * @{
+ */
+
+#ifndef __PIPE_STREAM_UC3_H__
+#define __PIPE_STREAM_UC3_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../USBMode.h"
+ #include "../USBTask.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Function Prototypes: */
+ /** \name Stream functions for null data */
+ //@{
+
+ /** Reads and discards the given number of bytes from the pipe, discarding fully read packets from the host
+ * as needed. The last packet is not automatically discarded once the remaining bytes has been read; the
+ * user is responsible for manually discarding the last packet from the device via the \ref Pipe_ClearIN() macro.
+ *
+ * If the BytesProcessed parameter is \c NULL, the entire stream transfer is attempted at once, failing or
+ * succeeding as a single unit. If the BytesProcessed parameter points to a valid storage location, the transfer
+ * will instead be performed as a series of chunks. Each time the pipe bank becomes empty while there is still data
+ * to process (and after the current packet has been acknowledged) the BytesProcessed location will be updated with
+ * the total number of bytes processed in the stream, and the function will exit with an error code of
+ * \ref PIPE_RWSTREAM_IncompleteTransfer. This allows for any abort checking to be performed in the user code - to
+ * continue the transfer, call the function again with identical parameters and it will resume until the BytesProcessed
+ * value reaches the total transfer length.
+ *
+ * <b>Single Stream Transfer Example:</b>
+ * \code
+ * uint8_t ErrorCode;
+ *
+ * if ((ErrorCode = Pipe_Discard_Stream(512, NULL)) != PIPE_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * <b>Partial Stream Transfers Example:</b>
+ * \code
+ * uint8_t ErrorCode;
+ * uint16_t BytesProcessed;
+ *
+ * BytesProcessed = 0;
+ * while ((ErrorCode = Pipe_Discard_Stream(512, &BytesProcessed)) == PIPE_RWSTREAM_IncompleteTransfer)
+ * {
+ * // Stream not yet complete - do other actions here, abort if required
+ * }
+ *
+ * if (ErrorCode != PIPE_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * \note The pipe token is set automatically, thus this can be used on bi-directional pipes directly without
+ * having to explicitly change the data direction with a call to \ref Pipe_SetPipeToken().
+ *
+ * \param[in] Length Number of bytes to discard via the currently selected pipe.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes already processed should
+ * updated, \c NULL if the entire stream should be processed at once.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Pipe_Discard_Stream(uint16_t Length,
+ uint16_t* const BytesProcessed);
+
+ /** Writes a given number of zeroed bytes to the pipe, sending full pipe packets from the host to the device
+ * as needed. The last packet is not automatically sent once the remaining bytes has been written; the
+ * user is responsible for manually discarding the last packet from the device via the \ref Pipe_ClearOUT() macro.
+ *
+ * If the BytesProcessed parameter is \c NULL, the entire stream transfer is attempted at once, failing or
+ * succeeding as a single unit. If the BytesProcessed parameter points to a valid storage location, the transfer
+ * will instead be performed as a series of chunks. Each time the pipe bank becomes full while there is still data
+ * to process (and after the current packet transmission has been initiated) the BytesProcessed location will be
+ * updated with the total number of bytes processed in the stream, and the function will exit with an error code of
+ * \ref PIPE_RWSTREAM_IncompleteTransfer. This allows for any abort checking to be performed in the user code - to
+ * continue the transfer, call the function again with identical parameters and it will resume until the BytesProcessed
+ * value reaches the total transfer length.
+ *
+ * <b>Single Stream Transfer Example:</b>
+ * \code
+ * uint8_t ErrorCode;
+ *
+ * if ((ErrorCode = Pipe_Null_Stream(512, NULL)) != PIPE_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * <b>Partial Stream Transfers Example:</b>
+ * \code
+ * uint8_t ErrorCode;
+ * uint16_t BytesProcessed;
+ *
+ * BytesProcessed = 0;
+ * while ((ErrorCode = Pipe_Null_Stream(512, &BytesProcessed)) == PIPE_RWSTREAM_IncompleteTransfer)
+ * {
+ * // Stream not yet complete - do other actions here, abort if required
+ * }
+ *
+ * if (ErrorCode != PIPE_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * \note The pipe token is set automatically, thus this can be used on bi-directional pipes directly without
+ * having to explicitly change the data direction with a call to \ref Pipe_SetPipeToken().
+ *
+ * \param[in] Length Number of zero bytes to write via the currently selected pipe.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes already processed should
+ * updated, \c NULL if the entire stream should be processed at once.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Pipe_Null_Stream(uint16_t Length,
+ uint16_t* const BytesProcessed);
+
+ //@}
+
+ /** \name Stream functions for RAM source/destination data */
+ //@{
+
+ /** Writes the given number of bytes to the pipe from the given buffer in little endian,
+ * sending full packets to the device as needed. The last packet filled is not automatically sent;
+ * the user is responsible for manually sending the last written packet to the host via the
+ * \ref Pipe_ClearOUT() macro. Between each USB packet, the given stream callback function is
+ * executed repeatedly until the next packet is ready, allowing for early aborts of stream transfers.
+ *
+ * If the BytesProcessed parameter is \c NULL, the entire stream transfer is attempted at once,
+ * failing or succeeding as a single unit. If the BytesProcessed parameter points to a valid
+ * storage location, the transfer will instead be performed as a series of chunks. Each time
+ * the pipe bank becomes full while there is still data to process (and after the current
+ * packet transmission has been initiated) the BytesProcessed location will be updated with the
+ * total number of bytes processed in the stream, and the function will exit with an error code of
+ * \ref PIPE_RWSTREAM_IncompleteTransfer. This allows for any abort checking to be performed
+ * in the user code - to continue the transfer, call the function again with identical parameters
+ * and it will resume until the BytesProcessed value reaches the total transfer length.
+ *
+ * <b>Single Stream Transfer Example:</b>
+ * \code
+ * uint8_t DataStream[512];
+ * uint8_t ErrorCode;
+ *
+ * if ((ErrorCode = Pipe_Write_Stream_LE(DataStream, sizeof(DataStream),
+ * NULL)) != PIPE_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * <b>Partial Stream Transfers Example:</b>
+ * \code
+ * uint8_t DataStream[512];
+ * uint8_t ErrorCode;
+ * uint16_t BytesProcessed;
+ *
+ * BytesProcessed = 0;
+ * while ((ErrorCode = Pipe_Write_Stream_LE(DataStream, sizeof(DataStream),
+ * &BytesProcessed)) == PIPE_RWSTREAM_IncompleteTransfer)
+ * {
+ * // Stream not yet complete - do other actions here, abort if required
+ * }
+ *
+ * if (ErrorCode != PIPE_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * \note The pipe token is set automatically, thus this can be used on bi-directional pipes directly without
+ * having to explicitly change the data direction with a call to \ref Pipe_SetPipeToken().
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected pipe into the buffer.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes already processed should
+ * updated, \c NULL if the entire stream should be written at once.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Pipe_Write_Stream_LE(const void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Writes the given number of bytes to the pipe from the given buffer in big endian,
+ * sending full packets to the device as needed. The last packet filled is not automatically sent;
+ * the user is responsible for manually sending the last written packet to the host via the
+ * \ref Pipe_ClearOUT() macro. Between each USB packet, the given stream callback function is
+ * executed repeatedly until the next packet is ready, allowing for early aborts of stream transfers.
+ *
+ * \note The pipe token is set automatically, thus this can be used on bi-directional pipes directly without
+ * having to explicitly change the data direction with a call to \ref Pipe_SetPipeToken().
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected pipe into the buffer.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes already processed should
+ * updated, \c NULL if the entire stream should be written at once.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Pipe_Write_Stream_BE(const void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Reads the given number of bytes from the pipe into the given buffer in little endian,
+ * sending full packets to the device as needed. The last packet filled is not automatically sent;
+ * the user is responsible for manually sending the last written packet to the host via the
+ * \ref Pipe_ClearIN() macro. Between each USB packet, the given stream callback function is
+ * executed repeatedly until the next packet is ready, allowing for early aborts of stream transfers.
+ *
+ * If the BytesProcessed parameter is \c NULL, the entire stream transfer is attempted at once,
+ * failing or succeeding as a single unit. If the BytesProcessed parameter points to a valid
+ * storage location, the transfer will instead be performed as a series of chunks. Each time
+ * the pipe bank becomes empty while there is still data to process (and after the current
+ * packet has been acknowledged) the BytesProcessed location will be updated with the total number
+ * of bytes processed in the stream, and the function will exit with an error code of
+ * \ref PIPE_RWSTREAM_IncompleteTransfer. This allows for any abort checking to be performed
+ * in the user code - to continue the transfer, call the function again with identical parameters
+ * and it will resume until the BytesProcessed value reaches the total transfer length.
+ *
+ * <b>Single Stream Transfer Example:</b>
+ * \code
+ * uint8_t DataStream[512];
+ * uint8_t ErrorCode;
+ *
+ * if ((ErrorCode = Pipe_Read_Stream_LE(DataStream, sizeof(DataStream),
+ * NULL)) != PIPE_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * <b>Partial Stream Transfers Example:</b>
+ * \code
+ * uint8_t DataStream[512];
+ * uint8_t ErrorCode;
+ * uint16_t BytesProcessed;
+ *
+ * BytesProcessed = 0;
+ * while ((ErrorCode = Pipe_Read_Stream_LE(DataStream, sizeof(DataStream),
+ * &BytesProcessed)) == PIPE_RWSTREAM_IncompleteTransfer)
+ * {
+ * // Stream not yet complete - do other actions here, abort if required
+ * }
+ *
+ * if (ErrorCode != PIPE_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * \note The pipe token is set automatically, thus this can be used on bi-directional pipes directly without
+ * having to explicitly change the data direction with a call to \ref Pipe_SetPipeToken().
+ *
+ * \param[out] Buffer Pointer to the source data buffer to write to.
+ * \param[in] Length Number of bytes to read for the currently selected pipe to read from.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes already processed should
+ * updated, \c NULL if the entire stream should be read at once.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Pipe_Read_Stream_LE(void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Reads the given number of bytes from the pipe into the given buffer in big endian,
+ * sending full packets to the device as needed. The last packet filled is not automatically sent;
+ * the user is responsible for manually sending the last written packet to the host via the
+ * \ref Pipe_ClearIN() macro. Between each USB packet, the given stream callback function is
+ * executed repeatedly until the next packet is ready, allowing for early aborts of stream transfers.
+ *
+ * \note The pipe token is set automatically, thus this can be used on bi-directional pipes directly without
+ * having to explicitly change the data direction with a call to \ref Pipe_SetPipeToken().
+ *
+ * \param[out] Buffer Pointer to the source data buffer to write to.
+ * \param[in] Length Number of bytes to read for the currently selected pipe to read from.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes already processed should
+ * updated, \c NULL if the entire stream should be read at once.
+ *
+ * \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Pipe_Read_Stream_BE(void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+ //@}
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Pipe_UC3.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Pipe_UC3.c
new file mode 100644
index 000000000..a24c7b1d6
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Pipe_UC3.c
@@ -0,0 +1,209 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "../../../../Common/Common.h"
+#if (ARCH == ARCH_UC3)
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../USBMode.h"
+
+#if defined(USB_CAN_BE_HOST)
+
+#include "../Pipe.h"
+
+uint8_t USB_Host_ControlPipeSize = PIPE_CONTROLPIPE_DEFAULT_SIZE;
+
+volatile uint32_t USB_Pipe_SelectedPipe = PIPE_CONTROLPIPE;
+volatile uint8_t* USB_Pipe_FIFOPos[PIPE_TOTAL_PIPES];
+
+bool Pipe_ConfigurePipeTable(const USB_Pipe_Table_t* const Table,
+ const uint8_t Entries)
+{
+ for (uint8_t i = 0; i < Entries; i++)
+ {
+ if (!(Table[i].Address))
+ continue;
+
+ if (!(Pipe_ConfigurePipe(Table[i].Address, Table[i].Type, Table[i].EndpointAddress, Table[i].Size, Table[i].Banks)))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool Pipe_ConfigurePipe(const uint8_t Address,
+ const uint8_t Type,
+ const uint8_t EndpointAddress,
+ const uint16_t Size,
+ const uint8_t Banks)
+{
+ uint8_t Number = (Address & PIPE_EPNUM_MASK);
+ uint8_t Token = (Address & PIPE_DIR_IN) ? PIPE_TOKEN_IN : PIPE_TOKEN_OUT;
+
+ if (Number >= PIPE_TOTAL_PIPES)
+ return false;
+
+ if (Type == EP_TYPE_CONTROL)
+ Token = PIPE_TOKEN_SETUP;
+
+ USB_Pipe_FIFOPos[Number] = &AVR32_USBB_SLAVE[Number * PIPE_HSB_ADDRESS_SPACE_SIZE];
+
+#if defined(ORDERED_EP_CONFIG)
+ Pipe_SelectPipe(Number);
+ Pipe_EnablePipe();
+
+ (&AVR32_USBB.upcfg0)[Number] = 0;
+ (&AVR32_USBB.upcfg0)[Number] = (AVR32_USBB_ALLOC_MASK |
+ ((uint32_t)Type << AVR32_USBB_PTYPE_OFFSET) |
+ ((uint32_t)Token << AVR32_USBB_PTOKEN_OFFSET) |
+ ((Banks > 1) ? AVR32_USBB_PBK_MASK : 0) |
+ Pipe_BytesToEPSizeMask(Size) |
+ ((uint32_t)Number << AVR32_USBB_PEPNUM_OFFSET));
+
+ Pipe_SetInfiniteINRequests();
+
+ return Pipe_IsConfigured();
+#else
+ for (uint8_t PNum = Number; PNum < PIPE_TOTAL_PIPES; PNum++)
+ {
+ uint32_t UPCFG0Temp;
+
+ Pipe_SelectPipe(PNum);
+
+ if (PNum == Number)
+ {
+ UPCFG0Temp = (AVR32_USBB_ALLOC_MASK |
+ ((uint32_t)Type << AVR32_USBB_PTYPE_OFFSET) |
+ ((uint32_t)Token << AVR32_USBB_PTOKEN_OFFSET) |
+ ((Banks > 1) ? AVR32_USBB_PBK_MASK : 0) |
+ Pipe_BytesToEPSizeMask(Size) |
+ ((EndpointAddress & PIPE_EPNUM_MASK) << AVR32_USBB_PEPNUM_OFFSET));
+ }
+ else
+ {
+ UPCFG0Temp = (&AVR32_USBB.upcfg0)[PNum];
+ }
+
+ if (!(UPCFG0Temp & AVR32_USBB_ALLOC_MASK))
+ continue;
+
+ Pipe_DisablePipe();
+ (&AVR32_USBB.upcfg0)[PNum] &= ~AVR32_USBB_ALLOC_MASK;
+
+ Pipe_EnablePipe();
+ (&AVR32_USBB.upcfg0)[PNum] = UPCFG0Temp;
+
+ Pipe_SetInfiniteINRequests();
+
+ if (!(Pipe_IsConfigured()))
+ return false;
+ }
+
+ Pipe_SelectPipe(Number);
+ return true;
+#endif
+}
+
+void Pipe_ClearPipes(void)
+{
+ for (uint8_t PNum = 0; PNum < PIPE_TOTAL_PIPES; PNum++)
+ {
+ Pipe_SelectPipe(PNum);
+ (&AVR32_USBB.upcfg0)[PNum] = 0;
+ (&AVR32_USBB.upcon0clr)[PNum] = -1;
+ USB_Pipe_FIFOPos[PNum] = &AVR32_USBB_SLAVE[PNum * 0x10000];
+ Pipe_DisablePipe();
+ }
+}
+
+bool Pipe_IsEndpointBound(const uint8_t EndpointAddress)
+{
+ uint8_t PrevPipeNumber = Pipe_GetCurrentPipe();
+
+ for (uint8_t PNum = 0; PNum < PIPE_TOTAL_PIPES; PNum++)
+ {
+ Pipe_SelectPipe(PNum);
+
+ if (!(Pipe_IsConfigured()))
+ continue;
+
+ if (Pipe_GetBoundEndpointAddress() == EndpointAddress)
+ return true;
+ }
+
+ Pipe_SelectPipe(PrevPipeNumber);
+ return false;
+}
+
+uint8_t Pipe_WaitUntilReady(void)
+{
+ #if (USB_STREAM_TIMEOUT_MS < 0xFF)
+ uint8_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
+ #else
+ uint16_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
+ #endif
+
+ uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber();
+
+ for (;;)
+ {
+ if (Pipe_GetPipeToken() == PIPE_TOKEN_IN)
+ {
+ if (Pipe_IsINReceived())
+ return PIPE_READYWAIT_NoError;
+ }
+ else
+ {
+ if (Pipe_IsOUTReady())
+ return PIPE_READYWAIT_NoError;
+ }
+
+ if (Pipe_IsStalled())
+ return PIPE_READYWAIT_PipeStalled;
+ else if (USB_HostState == HOST_STATE_Unattached)
+ return PIPE_READYWAIT_DeviceDisconnected;
+
+ uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber();
+
+ if (CurrentFrameNumber != PreviousFrameNumber)
+ {
+ PreviousFrameNumber = CurrentFrameNumber;
+
+ if (!(TimeoutMSRem--))
+ return PIPE_READYWAIT_Timeout;
+ }
+ }
+}
+
+#endif
+
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Pipe_UC3.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Pipe_UC3.h
new file mode 100644
index 000000000..1a0ada8b7
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Pipe_UC3.h
@@ -0,0 +1,924 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief USB Pipe definitions for the AVR32 UC3 microcontrollers.
+ * \copydetails Group_PipeManagement_UC3
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_PipeRW
+ * \defgroup Group_PipeRW_UC3 Pipe Data Reading and Writing (UC3)
+ * \brief Pipe data read/write definitions for the Atmel AVR32 UC3 architecture.
+ *
+ * Functions, macros, variables, enums and types related to data reading and writing from and to pipes.
+ */
+
+/** \ingroup Group_PipePrimitiveRW
+ * \defgroup Group_PipePrimitiveRW_UC3 Read/Write of Primitive Data Types (UC3)
+ * \brief Pipe primitive data read/write definitions for the Atmel AVR32 UC3 architecture.
+ *
+ * Functions, macros, variables, enums and types related to data reading and writing of primitive data types
+ * from and to pipes.
+ */
+
+/** \ingroup Group_PipePacketManagement
+ * \defgroup Group_PipePacketManagement_UC3 Pipe Packet Management (UC3)
+ * \brief Pipe packet management definitions for the Atmel AVR32 UC3 architecture.
+ *
+ * Functions, macros, variables, enums and types related to packet management of pipes.
+ */
+
+/** \ingroup Group_PipeControlReq
+ * \defgroup Group_PipeControlReq_UC3 Pipe Control Request Management (UC3)
+ * \brief Pipe control request management definitions for the Atmel AVR32 UC3 architecture.
+ *
+ * Module for host mode request processing. This module allows for the transmission of standard, class and
+ * vendor control requests to the default control endpoint of an attached device while in host mode.
+ *
+ * \see Chapter 9 of the USB 2.0 specification.
+ */
+
+/** \ingroup Group_PipeManagement
+ * \defgroup Group_PipeManagement_UC3 Pipe Management (UC3)
+ * \brief Pipe management definitions for the Atmel AVR32 UC3 architecture.
+ *
+ * This module contains functions, macros and enums related to pipe management when in USB Host mode. This
+ * module contains the pipe management macros, as well as pipe interrupt and data send/receive functions
+ * for various data types.
+ *
+ * @{
+ */
+
+#ifndef __PIPE_UC3_H__
+#define __PIPE_UC3_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../USBTask.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #define PIPE_HSB_ADDRESS_SPACE_SIZE (64 * 1024UL)
+
+ /* External Variables: */
+ extern volatile uint32_t USB_Pipe_SelectedPipe;
+ extern volatile uint8_t* USB_Pipe_FIFOPos[];
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** \name Pipe Error Flag Masks */
+ //@{
+ /** Mask for \ref Pipe_GetErrorFlags(), indicating that an overflow error occurred in the pipe on the received data. */
+ #define PIPE_ERRORFLAG_OVERFLOW (AVR32_USBB_UPSTA0_OVERFI_MASK << 8)
+
+ /** Mask for \ref Pipe_GetErrorFlags(), indicating that a CRC error occurred in the pipe on the received data. */
+ #define PIPE_ERRORFLAG_CRC16 AVR32_USBB_UPERR0_CRC16_MASK
+
+ /** Mask for \ref Pipe_GetErrorFlags(), indicating that a hardware timeout error occurred in the pipe. */
+ #define PIPE_ERRORFLAG_TIMEOUT AVR32_USBB_UPERR0_TIMEOUT_MASK
+
+ /** Mask for \ref Pipe_GetErrorFlags(), indicating that a hardware PID error occurred in the pipe. */
+ #define PIPE_ERRORFLAG_PID AVR32_USBB_UPERR0_PID_MASK
+
+ /** Mask for \ref Pipe_GetErrorFlags(), indicating that a hardware data PID error occurred in the pipe. */
+ #define PIPE_ERRORFLAG_DATAPID AVR32_USBB_UPERR0_DATAPID_MASK
+
+ /** Mask for \ref Pipe_GetErrorFlags(), indicating that a hardware data toggle error occurred in the pipe. */
+ #define PIPE_ERRORFLAG_DATATGL AVR32_USBB_UPERR0_DATATGL_MASK
+ //@}
+
+ /** \name Pipe Token Masks */
+ //@{
+ /** Token mask for \ref Pipe_SetPipeToken() and \ref Pipe_GetPipeToken(). This sets the pipe as a SETUP token (for CONTROL type pipes),
+ * which will trigger a control request on the attached device when data is written to the pipe.
+ */
+ #define PIPE_TOKEN_SETUP AVR32_USBB_UPCFG0_PTOKEN_SETUP
+
+ /** Token mask for \ref Pipe_SetPipeToken() and \ref Pipe_GetPipeToken(). This sets the pipe as a IN token (for non-CONTROL type pipes),
+ * indicating that the pipe data will flow from device to host.
+ */
+ #define PIPE_TOKEN_IN AVR32_USBB_UPCFG0_PTOKEN_IN
+
+ /** Token mask for \ref Pipe_SetPipeToken() and \ref Pipe_GetPipeToken(). This sets the pipe as a OUT token (for non-CONTROL type pipes),
+ * indicating that the pipe data will flow from host to device.
+ */
+ #define PIPE_TOKEN_OUT AVR32_USBB_UPCFG0_PTOKEN_OUT
+ //@}
+
+ /** Default size of the default control pipe's bank, until altered by the Endpoint0Size value
+ * in the device descriptor of the attached device.
+ */
+ #define PIPE_CONTROLPIPE_DEFAULT_SIZE 64
+
+ #if defined(USB_SERIES_UC3A3_AVR32) || defined(USB_SERIES_UC3A4_AVR32) || defined(__DOXYGEN__)
+ /** Total number of pipes (including the default control pipe at address 0) which may be used in
+ * the device.
+ */
+ #define PIPE_TOTAL_PIPES 8
+ #else
+ #define PIPE_TOTAL_PIPES 7
+ #endif
+
+ /** Size in bytes of the largest pipe bank size possible in the device. Not all banks on each AVR
+ * model supports the largest bank size possible on the device; different pipe numbers support
+ * different maximum bank sizes. This value reflects the largest possible bank of any pipe on the
+ * currently selected UC3 AVR model.
+ */
+ #define PIPE_MAX_SIZE 256
+
+ /* Enums: */
+ /** Enum for the possible error return codes of the \ref Pipe_WaitUntilReady() function.
+ *
+ * \ingroup Group_PipeRW_UC3
+ */
+ enum Pipe_WaitUntilReady_ErrorCodes_t
+ {
+ PIPE_READYWAIT_NoError = 0, /**< Pipe ready for next packet, no error. */
+ PIPE_READYWAIT_PipeStalled = 1, /**< The device stalled the pipe while waiting. */
+ PIPE_READYWAIT_DeviceDisconnected = 2, /**< Device was disconnected from the host while waiting. */
+ PIPE_READYWAIT_Timeout = 3, /**< The device failed to accept or send the next packet
+ * within the software timeout period set by the
+ * \ref USB_STREAM_TIMEOUT_MS macro.
+ */
+ };
+
+ /* Inline Functions: */
+ /** Indicates the number of bytes currently stored in the current pipes's selected bank.
+ *
+ * \ingroup Group_PipeRW_UC3
+ *
+ * \return Total number of bytes in the currently selected pipe's FIFO buffer.
+ */
+ static inline uint16_t Pipe_BytesInPipe(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint16_t Pipe_BytesInPipe(void)
+ {
+ return (&AVR32_USBB.UPSTA0)[USB_Pipe_SelectedPipe].pbyct;
+ }
+
+ /** Determines the currently selected pipe's direction.
+ *
+ * \return The currently selected pipe's direction, as a \c PIPE_DIR_* mask.
+ */
+ static inline uint8_t Pipe_GetPipeDirection(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Pipe_GetPipeDirection(void)
+ {
+ return (((&AVR32_USBB.UPCFG0)[USB_Pipe_SelectedPipe].ptoken == PIPE_TOKEN_OUT) ? PIPE_DIR_OUT : PIPE_DIR_IN);
+ }
+
+ /** Returns the pipe address of the currently selected pipe. This is typically used to save the
+ * currently selected pipe number so that it can be restored after another pipe has been manipulated.
+ *
+ * \return Index of the currently selected pipe.
+ */
+ static inline uint8_t Pipe_GetCurrentPipe(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Pipe_GetCurrentPipe(void)
+ {
+ return (USB_Pipe_SelectedPipe | Pipe_GetPipeDirection());
+ }
+
+ /** Selects the given pipe address. Any pipe operations which do not require the pipe address to be
+ * indicated will operate on the currently selected pipe.
+ *
+ * \param[in] Address Address of the pipe to select.
+ */
+ static inline void Pipe_SelectPipe(const uint8_t Address) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_SelectPipe(const uint8_t Address)
+ {
+ USB_Pipe_SelectedPipe = (Address & PIPE_EPNUM_MASK);
+ }
+
+ /** Resets the desired pipe, including the pipe banks and flags.
+ *
+ * \param[in] Address Index of the pipe to reset.
+ */
+ static inline void Pipe_ResetPipe(const uint8_t Address) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_ResetPipe(const uint8_t Address)
+ {
+ uint32_t PipeNumber = (Address & PIPE_EPNUM_MASK);
+
+ AVR32_USBB.uprst |= (AVR32_USBB_PRST0_MASK << PipeNumber);
+ AVR32_USBB.uprst &= ~(AVR32_USBB_PRST0_MASK << PipeNumber);
+ USB_Pipe_FIFOPos[PipeNumber] = &AVR32_USBB_SLAVE[PipeNumber * PIPE_HSB_ADDRESS_SPACE_SIZE];
+ }
+
+ /** Enables the currently selected pipe so that data can be sent and received through it to and from
+ * an attached device.
+ *
+ * \pre The currently selected pipe must first be configured properly via \ref Pipe_ConfigurePipe().
+ */
+ static inline void Pipe_EnablePipe(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_EnablePipe(void)
+ {
+ AVR32_USBB.uprst |= (AVR32_USBB_PEN0_MASK << USB_Pipe_SelectedPipe);
+ }
+
+ /** Disables the currently selected pipe so that data cannot be sent and received through it to and
+ * from an attached device.
+ */
+ static inline void Pipe_DisablePipe(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_DisablePipe(void)
+ {
+ AVR32_USBB.uprst &= ~(AVR32_USBB_PEN0_MASK << USB_Pipe_SelectedPipe);
+ }
+
+ /** Determines if the currently selected pipe is enabled, but not necessarily configured.
+ *
+ * \return Boolean \c true if the currently selected pipe is enabled, \c false otherwise.
+ */
+ static inline bool Pipe_IsEnabled(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsEnabled(void)
+ {
+ return ((AVR32_USBB.uprst & (AVR32_USBB_PEN0_MASK << USB_Pipe_SelectedPipe)) ? true : false);
+ }
+
+ /** Gets the current pipe token, indicating the pipe's data direction and type.
+ *
+ * \return The current pipe token, as a \c PIPE_TOKEN_* mask.
+ */
+ static inline uint8_t Pipe_GetPipeToken(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Pipe_GetPipeToken(void)
+ {
+ return (&AVR32_USBB.UPCFG0)[USB_Pipe_SelectedPipe].ptoken;
+ }
+
+ /** Sets the token for the currently selected pipe to one of the tokens specified by the \c PIPE_TOKEN_*
+ * masks. This can be used on CONTROL type pipes, to allow for bidirectional transfer of data during
+ * control requests, or on regular pipes to allow for half-duplex bidirectional data transfer to devices
+ * which have two endpoints of opposite direction sharing the same endpoint address within the device.
+ *
+ * \param[in] Token New pipe token to set the selected pipe to, as a \c PIPE_TOKEN_* mask.
+ */
+ static inline void Pipe_SetPipeToken(const uint8_t Token) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_SetPipeToken(const uint8_t Token)
+ {
+ (&AVR32_USBB.UPCFG0)[USB_Pipe_SelectedPipe].ptoken = Token;
+ }
+
+ /** Configures the currently selected pipe to allow for an unlimited number of IN requests. */
+ static inline void Pipe_SetInfiniteINRequests(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_SetInfiniteINRequests(void)
+ {
+ (&AVR32_USBB.UPINRQ0)[USB_Pipe_SelectedPipe].inmode = true;
+ }
+
+ /** Configures the currently selected pipe to only allow the specified number of IN requests to be
+ * accepted by the pipe before it is automatically frozen.
+ *
+ * \param[in] TotalINRequests Total number of IN requests that the pipe may receive before freezing.
+ */
+ static inline void Pipe_SetFiniteINRequests(const uint8_t TotalINRequests) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_SetFiniteINRequests(const uint8_t TotalINRequests)
+ {
+ (&AVR32_USBB.UPINRQ0)[USB_Pipe_SelectedPipe].inmode = false;
+ (&AVR32_USBB.UPINRQ0)[USB_Pipe_SelectedPipe].inrq = TotalINRequests;
+ }
+
+ /** Determines if the currently selected pipe is configured.
+ *
+ * \return Boolean \c true if the selected pipe is configured, \c false otherwise.
+ */
+ static inline bool Pipe_IsConfigured(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsConfigured(void)
+ {
+ return (&AVR32_USBB.UPSTA0)[USB_Pipe_SelectedPipe].cfgok;
+ }
+
+ /** Retrieves the endpoint address of the endpoint within the attached device that the currently selected
+ * pipe is bound to.
+ *
+ * \return Endpoint address the currently selected pipe is bound to.
+ */
+ static inline uint8_t Pipe_GetBoundEndpointAddress(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Pipe_GetBoundEndpointAddress(void)
+ {
+ return ((&AVR32_USBB.UPCFG0)[USB_Pipe_SelectedPipe].pepnum |
+ ((Pipe_GetPipeToken() == PIPE_TOKEN_IN) ? PIPE_DIR_IN : PIPE_DIR_OUT));
+ }
+
+ /** Sets the period between interrupts for an INTERRUPT type pipe to a specified number of milliseconds.
+ *
+ * \param[in] Milliseconds Number of milliseconds between each pipe poll.
+ */
+ static inline void Pipe_SetInterruptPeriod(const uint8_t Milliseconds) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_SetInterruptPeriod(const uint8_t Milliseconds)
+ {
+ (&AVR32_USBB.UPCFG0)[USB_Pipe_SelectedPipe].intfrq = Milliseconds;
+ }
+
+ /** Returns a mask indicating which pipe's interrupt periods have elapsed, indicating that the pipe should
+ * be serviced.
+ *
+ * \return Mask whose bits indicate which pipes have interrupted.
+ */
+ static inline uint8_t Pipe_GetPipeInterrupts(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Pipe_GetPipeInterrupts(void)
+ {
+ return ((AVR32_USBB.uhint & (AVR32_USBB_P6INT_MASK | AVR32_USBB_P5INT_MASK |
+ AVR32_USBB_P4INT_MASK | AVR32_USBB_P3INT_MASK |
+ AVR32_USBB_P2INT_MASK | AVR32_USBB_P1INT_MASK |
+ AVR32_USBB_P0INT_MASK)) >> AVR32_USBB_P0INT_OFFSET);
+ }
+
+ /** Determines if the specified pipe address has interrupted (valid only for INTERRUPT type
+ * pipes).
+ *
+ * \param[in] Address Address of the pipe whose interrupt flag should be tested.
+ *
+ * \return Boolean \c true if the specified pipe has interrupted, \c false otherwise.
+ */
+ static inline bool Pipe_HasPipeInterrupted(const uint8_t Address) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_HasPipeInterrupted(const uint8_t Address)
+ {
+ return ((AVR32_USBB.uhint & (AVR32_USBB_P0INTES_MASK << (Address & PIPE_EPNUM_MASK))) ? true : false);
+ }
+
+ /** Unfreezes the selected pipe, allowing it to communicate with an attached device. */
+ static inline void Pipe_Unfreeze(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_Unfreeze(void)
+ {
+ (&AVR32_USBB.UPCON0CLR)[USB_Pipe_SelectedPipe].pfreezec = true;
+ }
+
+ /** Freezes the selected pipe, preventing it from communicating with an attached device. */
+ static inline void Pipe_Freeze(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_Freeze(void)
+ {
+ (&AVR32_USBB.UPCON0SET)[USB_Pipe_SelectedPipe].pfreezes = true;
+ }
+
+ /** Determines if the currently selected pipe is frozen, and not able to accept data.
+ *
+ * \return Boolean \c true if the currently selected pipe is frozen, \c false otherwise.
+ */
+ static inline bool Pipe_IsFrozen(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsFrozen(void)
+ {
+ return (((&AVR32_USBB.UPCON0)[USB_Pipe_SelectedPipe].pfreeze) ? true : false);
+ }
+
+ /** Clears the error flags for the currently selected pipe. */
+ static inline void Pipe_ClearError(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_ClearError(void)
+ {
+ (&AVR32_USBB.uperr0)[USB_Pipe_SelectedPipe] = 0;
+ (&AVR32_USBB.UPSTA0CLR)[USB_Pipe_SelectedPipe].overfic = true;
+ }
+
+ /** Determines if the master pipe error flag is set for the currently selected pipe, indicating that
+ * some sort of hardware error has occurred on the pipe.
+ *
+ * \see \ref Pipe_GetErrorFlags() macro for information on retrieving the exact error flag.
+ *
+ * \return Boolean \c true if an error has occurred on the selected pipe, \c false otherwise.
+ */
+ static inline bool Pipe_IsError(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsError(void)
+ {
+ return (((&AVR32_USBB.upsta0)[USB_Pipe_SelectedPipe] &
+ (AVR32_USBB_PERRI_MASK | AVR32_USBB_OVERFI_MASK)) ? true : false);
+ }
+
+ /** Gets a mask of the hardware error flags which have occurred on the currently selected pipe. This
+ * value can then be masked against the \c PIPE_ERRORFLAG_* masks to determine what error has occurred.
+ *
+ * \return Mask comprising of \c PIPE_ERRORFLAG_* bits indicating what error has occurred on the selected pipe.
+ */
+ static inline uint8_t Pipe_GetErrorFlags(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Pipe_GetErrorFlags(void)
+ {
+
+ return (((&AVR32_USBB.uperr0)[USB_Pipe_SelectedPipe] &
+ (PIPE_ERRORFLAG_CRC16 | PIPE_ERRORFLAG_TIMEOUT |
+ PIPE_ERRORFLAG_PID | PIPE_ERRORFLAG_DATAPID |
+ PIPE_ERRORFLAG_DATATGL)) |
+ (((&AVR32_USBB.upsta0)[USB_Pipe_SelectedPipe] << 8) &
+ PIPE_ERRORFLAG_OVERFLOW));
+ }
+
+ /** Retrieves the number of busy banks in the currently selected pipe, which have been queued for
+ * transmission via the \ref Pipe_ClearOUT() command, or are awaiting acknowledgement via the
+ * \ref Pipe_ClearIN() command.
+ *
+ * \ingroup Group_PipePacketManagement_UC3
+ *
+ * \return Total number of busy banks in the selected pipe.
+ */
+ static inline uint8_t Pipe_GetBusyBanks(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Pipe_GetBusyBanks(void)
+ {
+ return (&AVR32_USBB.UPSTA0)[USB_Pipe_SelectedPipe].nbusybk;
+ }
+
+ /** Determines if the currently selected pipe may be read from (if data is waiting in the pipe
+ * bank and the pipe is an IN direction, or if the bank is not yet full if the pipe is an OUT
+ * direction). This function will return false if an error has occurred in the pipe, or if the pipe
+ * is an IN direction and no packet (or an empty packet) has been received, or if the pipe is an OUT
+ * direction and the pipe bank is full.
+ *
+ * \note This function is not valid on CONTROL type pipes.
+ *
+ * \ingroup Group_PipePacketManagement_UC3
+ *
+ * \return Boolean \c true if the currently selected pipe may be read from or written to, depending
+ * on its direction.
+ */
+ static inline bool Pipe_IsReadWriteAllowed(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsReadWriteAllowed(void)
+ {
+ return (&AVR32_USBB.UPSTA0)[USB_Pipe_SelectedPipe].rwall;
+ }
+
+ /** Determines if a packet has been received on the currently selected IN pipe from the attached device.
+ *
+ * \ingroup Group_PipePacketManagement_UC3
+ *
+ * \return Boolean \c true if the current pipe has received an IN packet, \c false otherwise.
+ */
+ static inline bool Pipe_IsINReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsINReceived(void)
+ {
+ return (&AVR32_USBB.UPSTA0)[USB_Pipe_SelectedPipe].rxini;
+ }
+
+ /** Determines if the currently selected OUT pipe is ready to send an OUT packet to the attached device.
+ *
+ * \ingroup Group_PipePacketManagement_UC3
+ *
+ * \return Boolean \c true if the current pipe is ready for an OUT packet, \c false otherwise.
+ */
+ static inline bool Pipe_IsOUTReady(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsOUTReady(void)
+ {
+ return (&AVR32_USBB.UPSTA0)[USB_Pipe_SelectedPipe].txouti;
+ }
+
+ /** Determines if no SETUP request is currently being sent to the attached device on the selected
+ * CONTROL type pipe.
+ *
+ * \ingroup Group_PipePacketManagement_UC3
+ *
+ * \return Boolean \c true if the current pipe is ready for a SETUP packet, \c false otherwise.
+ */
+ static inline bool Pipe_IsSETUPSent(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsSETUPSent(void)
+ {
+ return (&AVR32_USBB.UPSTA0)[USB_Pipe_SelectedPipe].txstpi;
+ }
+
+ /** Sends the currently selected CONTROL type pipe's contents to the device as a SETUP packet.
+ *
+ * \ingroup Group_PipePacketManagement_UC3
+ */
+ static inline void Pipe_ClearSETUP(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_ClearSETUP(void)
+ {
+ (&AVR32_USBB.UPSTA0CLR)[USB_Pipe_SelectedPipe].txstpic = true;
+ (&AVR32_USBB.UPCON0CLR)[USB_Pipe_SelectedPipe].fifoconc = true;
+ USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe] = &AVR32_USBB_SLAVE[USB_Pipe_SelectedPipe * PIPE_HSB_ADDRESS_SPACE_SIZE];
+ }
+
+ /** Acknowledges the reception of a setup IN request from the attached device on the currently selected
+ * pipe, freeing the bank ready for the next packet.
+ *
+ * \ingroup Group_PipePacketManagement_UC3
+ */
+ static inline void Pipe_ClearIN(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_ClearIN(void)
+ {
+ (&AVR32_USBB.UPSTA0CLR)[USB_Pipe_SelectedPipe].rxinic = true;
+ (&AVR32_USBB.UPCON0CLR)[USB_Pipe_SelectedPipe].fifoconc = true;
+ USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe] = &AVR32_USBB_SLAVE[USB_Pipe_SelectedPipe * PIPE_HSB_ADDRESS_SPACE_SIZE];
+ }
+
+ /** Sends the currently selected pipe's contents to the device as an OUT packet on the selected pipe, freeing
+ * the bank ready for the next packet.
+ *
+ * \ingroup Group_PipePacketManagement_UC3
+ */
+ static inline void Pipe_ClearOUT(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_ClearOUT(void)
+ {
+ (&AVR32_USBB.UPSTA0CLR)[USB_Pipe_SelectedPipe].txoutic = true;
+ (&AVR32_USBB.UPCON0CLR)[USB_Pipe_SelectedPipe].fifoconc = true;
+ USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe] = &AVR32_USBB_SLAVE[USB_Pipe_SelectedPipe * PIPE_HSB_ADDRESS_SPACE_SIZE];
+ }
+
+ /** Determines if the device sent a NAK (Negative Acknowledge) in response to the last sent packet on
+ * the currently selected pipe. This occurs when the host sends a packet to the device, but the device
+ * is not currently ready to handle the packet (i.e. its endpoint banks are full). Once a NAK has been
+ * received, it must be cleared using \ref Pipe_ClearNAKReceived() before the previous (or any other) packet
+ * can be re-sent.
+ *
+ * \ingroup Group_PipePacketManagement_UC3
+ *
+ * \return Boolean \c true if an NAK has been received on the current pipe, \c false otherwise.
+ */
+ static inline bool Pipe_IsNAKReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsNAKReceived(void)
+ {
+ return (&AVR32_USBB.UPSTA0)[USB_Pipe_SelectedPipe].nakedi;
+ }
+
+ /** Clears the NAK condition on the currently selected pipe.
+ *
+ * \ingroup Group_PipePacketManagement_UC3
+ *
+ * \see \ref Pipe_IsNAKReceived() for more details.
+ */
+ static inline void Pipe_ClearNAKReceived(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_ClearNAKReceived(void)
+ {
+ (&AVR32_USBB.UPSTA0CLR)[USB_Pipe_SelectedPipe].nakedic = true;
+ }
+
+ /** Determines if the currently selected pipe has had the STALL condition set by the attached device.
+ *
+ * \ingroup Group_PipePacketManagement_UC3
+ *
+ * \return Boolean \c true if the current pipe has been stalled by the attached device, \c false otherwise.
+ */
+ static inline bool Pipe_IsStalled(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsStalled(void)
+ {
+ return (&AVR32_USBB.UPSTA0)[USB_Pipe_SelectedPipe].rxstalldi;
+ }
+
+ /** Clears the STALL condition detection flag on the currently selected pipe, but does not clear the
+ * STALL condition itself (this must be done via a ClearFeature control request to the device).
+ *
+ * \ingroup Group_PipePacketManagement_UC3
+ */
+ static inline void Pipe_ClearStall(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_ClearStall(void)
+ {
+ (&AVR32_USBB.UPSTA0CLR)[USB_Pipe_SelectedPipe].rxstalldic = true;
+ USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe] = &AVR32_USBB_SLAVE[USB_Pipe_SelectedPipe * PIPE_HSB_ADDRESS_SPACE_SIZE];
+ }
+
+ /** Reads one byte from the currently selected pipe's bank, for OUT direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW_UC3
+ *
+ * \return Next byte in the currently selected pipe's FIFO buffer.
+ */
+ static inline uint8_t Pipe_Read_8(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Pipe_Read_8(void)
+ {
+ return *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
+ }
+
+ /** Writes one byte to the currently selected pipe's bank, for IN direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW_UC3
+ *
+ * \param[in] Data Data to write into the the currently selected pipe's FIFO buffer.
+ */
+ static inline void Pipe_Write_8(const uint8_t Data) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_Write_8(const uint8_t Data)
+ {
+ *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++) = Data;
+ }
+
+ /** Discards one byte from the currently selected pipe's bank, for OUT direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW_UC3
+ */
+ static inline void Pipe_Discard_8(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_Discard_8(void)
+ {
+ uint8_t Dummy;
+
+ Dummy = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
+
+ (void)Dummy;
+ }
+
+ /** Reads two bytes from the currently selected pipe's bank in little endian format, for OUT
+ * direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW_UC3
+ *
+ * \return Next two bytes in the currently selected pipe's FIFO buffer.
+ */
+ static inline uint16_t Pipe_Read_16_LE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint16_t Pipe_Read_16_LE(void)
+ {
+ uint16_t Byte0 = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
+ uint16_t Byte1 = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
+
+ return ((Byte1 << 8) | Byte0);
+ }
+
+ /** Reads two bytes from the currently selected pipe's bank in big endian format, for OUT
+ * direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW_UC3
+ *
+ * \return Next two bytes in the currently selected pipe's FIFO buffer.
+ */
+ static inline uint16_t Pipe_Read_16_BE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint16_t Pipe_Read_16_BE(void)
+ {
+ uint16_t Byte0 = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
+ uint16_t Byte1 = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
+
+ return ((Byte0 << 8) | Byte1);
+ }
+
+ /** Writes two bytes to the currently selected pipe's bank in little endian format, for IN
+ * direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW_UC3
+ *
+ * \param[in] Data Data to write to the currently selected pipe's FIFO buffer.
+ */
+ static inline void Pipe_Write_16_LE(const uint16_t Data) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_Write_16_LE(const uint16_t Data)
+ {
+ *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++) = (Data & 0xFF);
+ *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++) = (Data >> 8);
+ }
+
+ /** Writes two bytes to the currently selected pipe's bank in big endian format, for IN
+ * direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW_UC3
+ *
+ * \param[in] Data Data to write to the currently selected pipe's FIFO buffer.
+ */
+ static inline void Pipe_Write_16_BE(const uint16_t Data) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_Write_16_BE(const uint16_t Data)
+ {
+ *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++) = (Data >> 8);
+ *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++) = (Data & 0xFF);
+ }
+
+ /** Discards two bytes from the currently selected pipe's bank, for OUT direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW_UC3
+ */
+ static inline void Pipe_Discard_16(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_Discard_16(void)
+ {
+ uint8_t Dummy;
+
+ Dummy = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
+ Dummy = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
+
+ (void)Dummy;
+ }
+
+ /** Reads four bytes from the currently selected pipe's bank in little endian format, for OUT
+ * direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW_UC3
+ *
+ * \return Next four bytes in the currently selected pipe's FIFO buffer.
+ */
+ static inline uint32_t Pipe_Read_32_LE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint32_t Pipe_Read_32_LE(void)
+ {
+ uint32_t Byte0 = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
+ uint32_t Byte1 = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
+ uint32_t Byte2 = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
+ uint32_t Byte3 = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
+
+ return ((Byte3 << 24) | (Byte2 << 16) | (Byte1 << 8) | Byte0);
+ }
+
+ /** Reads four bytes from the currently selected pipe's bank in big endian format, for OUT
+ * direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW_UC3
+ *
+ * \return Next four bytes in the currently selected pipe's FIFO buffer.
+ */
+ static inline uint32_t Pipe_Read_32_BE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint32_t Pipe_Read_32_BE(void)
+ {
+ uint32_t Byte0 = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
+ uint32_t Byte1 = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
+ uint32_t Byte2 = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
+ uint32_t Byte3 = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
+
+ return ((Byte0 << 24) | (Byte1 << 16) | (Byte2 << 8) | Byte3);
+ }
+
+ /** Writes four bytes to the currently selected pipe's bank in little endian format, for IN
+ * direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW_UC3
+ *
+ * \param[in] Data Data to write to the currently selected pipe's FIFO buffer.
+ */
+ static inline void Pipe_Write_32_LE(const uint32_t Data) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_Write_32_LE(const uint32_t Data)
+ {
+ *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++) = (Data & 0xFF);
+ *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++) = (Data >> 8);
+ *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++) = (Data >> 16);
+ *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++) = (Data >> 24);
+ }
+
+ /** Writes four bytes to the currently selected pipe's bank in big endian format, for IN
+ * direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW_UC3
+ *
+ * \param[in] Data Data to write to the currently selected pipe's FIFO buffer.
+ */
+ static inline void Pipe_Write_32_BE(const uint32_t Data) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_Write_32_BE(const uint32_t Data)
+ {
+ *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++) = (Data >> 24);
+ *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++) = (Data >> 16);
+ *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++) = (Data >> 8);
+ *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++) = (Data & 0xFF);
+ }
+
+ /** Discards four bytes from the currently selected pipe's bank, for OUT direction pipes.
+ *
+ * \ingroup Group_PipePrimitiveRW_UC3
+ */
+ static inline void Pipe_Discard_32(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_Discard_32(void)
+ {
+ uint8_t Dummy;
+
+ Dummy = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
+ Dummy = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
+ Dummy = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
+ Dummy = *(USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe]++);
+
+ (void)Dummy;
+ }
+
+ /* External Variables: */
+ /** Global indicating the maximum packet size of the default control pipe located at address
+ * 0 in the device. This value is set to the value indicated in the attached device's device
+ * descriptor once the USB interface is initialized into host mode and a device is attached
+ * to the USB bus.
+ *
+ * \attention This variable should be treated as read-only in the user application, and never manually
+ * changed in value.
+ */
+ extern uint8_t USB_Host_ControlPipeSize;
+
+ /* Function Prototypes: */
+ /** Configures a table of pipe descriptions, in sequence. This function can be used to configure multiple
+ * pipes at the same time.
+ *
+ * \note Pipe with a zero address will be ignored, thus this function cannot be used to configure the
+ * control pipe.
+ *
+ * \param[in] Table Pointer to a table of pipe descriptions.
+ * \param[in] Entries Number of entries in the pipe table to configure.
+ *
+ * \return Boolean \c true if all pipes configured successfully, \c false otherwise.
+ */
+ bool Pipe_ConfigurePipeTable(const USB_Pipe_Table_t* const Table,
+ const uint8_t Entries);
+
+ /** Configures the specified pipe address with the given pipe type, endpoint address within the attached device,
+ * bank size and number of hardware banks.
+ *
+ * A newly configured pipe is frozen by default, and must be unfrozen before use via the \ref Pipe_Unfreeze()
+ * before being used. Pipes should be kept frozen unless waiting for data from a device while in IN mode, or
+ * sending data to the device in OUT mode. IN type pipes are also automatically configured to accept infinite
+ * numbers of IN requests without automatic freezing - this can be overridden by a call to
+ * \ref Pipe_SetFiniteINRequests().
+ *
+ * \param[in] Address Pipe address to configure.
+ *
+ * \param[in] Type Type of pipe to configure, an \c EP_TYPE_* mask. Not all pipe types are available on Low
+ * Speed USB devices - refer to the USB 2.0 specification.
+ *
+ * \param[in] EndpointAddress Endpoint address within the attached device that the pipe should interface to.
+ *
+ * \param[in] Size Size of the pipe's bank, where packets are stored before they are transmitted to
+ * the USB device, or after they have been received from the USB device (depending on
+ * the pipe's data direction). The bank size must indicate the maximum packet size that
+ * the pipe can handle.
+ *
+ * \param[in] Banks Number of banks to use for the pipe being configured.
+ *
+ * \note When the \c ORDERED_EP_CONFIG compile time option is used, Pipes <b>must</b> be configured in ascending order,
+ * or bank corruption will occur.
+ * \n\n
+ *
+ * \note Certain microcontroller model's pipes may have different maximum packet sizes based on the pipe's
+ * index - refer to the chosen microcontroller's datasheet to determine the maximum bank size for each pipe.
+ * \n\n
+ *
+ * \note The default control pipe should not be manually configured by the user application, as it is
+ * automatically configured by the library internally.
+ * \n\n
+ *
+ * \note This routine will automatically select the specified pipe upon success. Upon failure, the pipe which
+ * failed to reconfigure correctly will be selected.
+ *
+ * \return Boolean \c true if the configuration succeeded, \c false otherwise.
+ */
+ bool Pipe_ConfigurePipe(const uint8_t Address,
+ const uint8_t Type,
+ const uint8_t EndpointAddress,
+ const uint16_t Size,
+ const uint8_t Banks);
+
+ /** Spin-loops until the currently selected non-control pipe is ready for the next packet of data to be read
+ * or written to it, aborting in the case of an error condition (such as a timeout or device disconnect).
+ *
+ * \ingroup Group_PipeRW_UC3
+ *
+ * \return A value from the \ref Pipe_WaitUntilReady_ErrorCodes_t enum.
+ */
+ uint8_t Pipe_WaitUntilReady(void);
+
+ /** Determines if a pipe has been bound to the given device endpoint address. If a pipe which is bound to the given
+ * endpoint is found, it is automatically selected.
+ *
+ * \param[in] EndpointAddress Address and direction mask of the endpoint within the attached device to check.
+ *
+ * \return Boolean \c true if a pipe bound to the given endpoint address of the specified direction is found,
+ * \c false otherwise.
+ */
+ bool Pipe_IsEndpointBound(const uint8_t EndpointAddress) ATTR_WARN_UNUSED_RESULT;
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #if !defined(ENDPOINT_CONTROLEP)
+ #define ENDPOINT_CONTROLEP 0
+ #endif
+
+ /* Inline Functions: */
+ static inline uint8_t Pipe_BytesToEPSizeMask(const uint16_t Bytes) ATTR_WARN_UNUSED_RESULT ATTR_CONST ATTR_ALWAYS_INLINE;
+ static inline uint8_t Pipe_BytesToEPSizeMask(const uint16_t Bytes)
+ {
+ uint8_t MaskVal = 0;
+ uint16_t CheckBytes = 8;
+
+ while ((CheckBytes < Bytes) && (CheckBytes < PIPE_MAX_SIZE))
+ {
+ MaskVal++;
+ CheckBytes <<= 1;
+ }
+
+ return (MaskVal << AVR32_USBB_PSIZE_OFFSET);
+ }
+
+ /* Function Prototypes: */
+ void Pipe_ClearPipes(void);
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_Control_R.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_Control_R.c
new file mode 100644
index 000000000..59c620ae5
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_Control_R.c
@@ -0,0 +1,84 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#if defined(TEMPLATE_FUNC_NAME)
+
+uint8_t TEMPLATE_FUNC_NAME (void* const Buffer,
+ uint16_t Length)
+{
+ uint8_t* DataStream = ((uint8_t*)Buffer + TEMPLATE_BUFFER_OFFSET(Length));
+
+ if (!(Length))
+ Endpoint_ClearOUT();
+
+ while (Length)
+ {
+ uint8_t USB_DeviceState_LCL = USB_DeviceState;
+
+ if (USB_DeviceState_LCL == DEVICE_STATE_Unattached)
+ return ENDPOINT_RWCSTREAM_DeviceDisconnected;
+ else if (USB_DeviceState_LCL == DEVICE_STATE_Suspended)
+ return ENDPOINT_RWCSTREAM_BusSuspended;
+ else if (Endpoint_IsSETUPReceived())
+ return ENDPOINT_RWCSTREAM_HostAborted;
+
+ if (Endpoint_IsOUTReceived())
+ {
+ while (Length && Endpoint_BytesInEndpoint())
+ {
+ TEMPLATE_TRANSFER_BYTE(DataStream);
+ TEMPLATE_BUFFER_MOVE(DataStream, 1);
+ Length--;
+ }
+
+ Endpoint_ClearOUT();
+ }
+ }
+
+ while (!(Endpoint_IsINReady()))
+ {
+ uint8_t USB_DeviceState_LCL = USB_DeviceState;
+
+ if (USB_DeviceState_LCL == DEVICE_STATE_Unattached)
+ return ENDPOINT_RWCSTREAM_DeviceDisconnected;
+ else if (USB_DeviceState_LCL == DEVICE_STATE_Suspended)
+ return ENDPOINT_RWCSTREAM_BusSuspended;
+ }
+
+ return ENDPOINT_RWCSTREAM_NoError;
+}
+
+#undef TEMPLATE_BUFFER_OFFSET
+#undef TEMPLATE_BUFFER_MOVE
+#undef TEMPLATE_FUNC_NAME
+#undef TEMPLATE_TRANSFER_BYTE
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_Control_W.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_Control_W.c
new file mode 100644
index 000000000..98887009c
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_Control_W.c
@@ -0,0 +1,95 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#if defined(TEMPLATE_FUNC_NAME)
+
+uint8_t TEMPLATE_FUNC_NAME (const void* const Buffer,
+ uint16_t Length)
+{
+ uint8_t* DataStream = ((uint8_t*)Buffer + TEMPLATE_BUFFER_OFFSET(Length));
+ bool LastPacketFull = false;
+
+ if (Length > USB_ControlRequest.wLength)
+ Length = USB_ControlRequest.wLength;
+ else if (!(Length))
+ Endpoint_ClearIN();
+
+ while (Length || LastPacketFull)
+ {
+ uint8_t USB_DeviceState_LCL = USB_DeviceState;
+
+ if (USB_DeviceState_LCL == DEVICE_STATE_Unattached)
+ return ENDPOINT_RWCSTREAM_DeviceDisconnected;
+ else if (USB_DeviceState_LCL == DEVICE_STATE_Suspended)
+ return ENDPOINT_RWCSTREAM_BusSuspended;
+ else if (Endpoint_IsSETUPReceived())
+ return ENDPOINT_RWCSTREAM_HostAborted;
+ else if (Endpoint_IsOUTReceived())
+ break;
+
+ if (Endpoint_IsINReady())
+ {
+ uint16_t BytesInEndpoint = Endpoint_BytesInEndpoint();
+
+ while (Length && (BytesInEndpoint < USB_Device_ControlEndpointSize))
+ {
+ TEMPLATE_TRANSFER_BYTE(DataStream);
+ TEMPLATE_BUFFER_MOVE(DataStream, 1);
+ Length--;
+ BytesInEndpoint++;
+ }
+
+ LastPacketFull = (BytesInEndpoint == USB_Device_ControlEndpointSize);
+ Endpoint_ClearIN();
+ }
+ }
+
+ while (!(Endpoint_IsOUTReceived()))
+ {
+ uint8_t USB_DeviceState_LCL = USB_DeviceState;
+
+ if (USB_DeviceState_LCL == DEVICE_STATE_Unattached)
+ return ENDPOINT_RWCSTREAM_DeviceDisconnected;
+ else if (USB_DeviceState_LCL == DEVICE_STATE_Suspended)
+ return ENDPOINT_RWCSTREAM_BusSuspended;
+ else if (Endpoint_IsSETUPReceived())
+ return ENDPOINT_RWCSTREAM_HostAborted;
+ }
+
+ return ENDPOINT_RWCSTREAM_NoError;
+}
+
+#undef TEMPLATE_BUFFER_OFFSET
+#undef TEMPLATE_BUFFER_MOVE
+#undef TEMPLATE_FUNC_NAME
+#undef TEMPLATE_TRANSFER_BYTE
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_RW.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_RW.c
new file mode 100644
index 000000000..d51afdfb1
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_RW.c
@@ -0,0 +1,89 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#if defined(TEMPLATE_FUNC_NAME)
+
+uint8_t TEMPLATE_FUNC_NAME (TEMPLATE_BUFFER_TYPE const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed)
+{
+ uint8_t* DataStream = ((uint8_t*)Buffer + TEMPLATE_BUFFER_OFFSET(Length));
+ uint16_t BytesInTransfer = 0;
+ uint8_t ErrorCode;
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()))
+ return ErrorCode;
+
+ if (BytesProcessed != NULL)
+ {
+ Length -= *BytesProcessed;
+ TEMPLATE_BUFFER_MOVE(DataStream, *BytesProcessed);
+ }
+
+ while (Length)
+ {
+ if (!(Endpoint_IsReadWriteAllowed()))
+ {
+ TEMPLATE_CLEAR_ENDPOINT();
+
+ #if !defined(INTERRUPT_CONTROL_ENDPOINT)
+ USB_USBTask();
+ #endif
+
+ if (BytesProcessed != NULL)
+ {
+ *BytesProcessed += BytesInTransfer;
+ return ENDPOINT_RWSTREAM_IncompleteTransfer;
+ }
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()))
+ return ErrorCode;
+ }
+ else
+ {
+ TEMPLATE_TRANSFER_BYTE(DataStream);
+ TEMPLATE_BUFFER_MOVE(DataStream, 1);
+ Length--;
+ BytesInTransfer++;
+ }
+ }
+
+ return ENDPOINT_RWSTREAM_NoError;
+}
+
+#undef TEMPLATE_FUNC_NAME
+#undef TEMPLATE_BUFFER_TYPE
+#undef TEMPLATE_TRANSFER_BYTE
+#undef TEMPLATE_CLEAR_ENDPOINT
+#undef TEMPLATE_BUFFER_OFFSET
+#undef TEMPLATE_BUFFER_MOVE
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Template/Template_Pipe_RW.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Template/Template_Pipe_RW.c
new file mode 100644
index 000000000..2685c9b9d
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/Template/Template_Pipe_RW.c
@@ -0,0 +1,88 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#if defined(TEMPLATE_FUNC_NAME)
+
+uint8_t TEMPLATE_FUNC_NAME (TEMPLATE_BUFFER_TYPE const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed)
+{
+ uint8_t* DataStream = ((uint8_t*)Buffer + TEMPLATE_BUFFER_OFFSET(Length));
+ uint16_t BytesInTransfer = 0;
+ uint8_t ErrorCode;
+
+ Pipe_SetPipeToken(TEMPLATE_TOKEN);
+
+ if ((ErrorCode = Pipe_WaitUntilReady()))
+ return ErrorCode;
+
+ if (BytesProcessed != NULL)
+ {
+ Length -= *BytesProcessed;
+ TEMPLATE_BUFFER_MOVE(DataStream, *BytesProcessed);
+ }
+
+ while (Length)
+ {
+ if (!(Pipe_IsReadWriteAllowed()))
+ {
+ TEMPLATE_CLEAR_PIPE();
+
+ if (BytesProcessed != NULL)
+ {
+ *BytesProcessed += BytesInTransfer;
+ return PIPE_RWSTREAM_IncompleteTransfer;
+ }
+
+ if ((ErrorCode = Pipe_WaitUntilReady()))
+ return ErrorCode;
+ }
+ else
+ {
+ TEMPLATE_TRANSFER_BYTE(DataStream);
+ TEMPLATE_BUFFER_MOVE(DataStream, 1);
+ Length--;
+ BytesInTransfer++;
+ }
+ }
+
+ return PIPE_RWSTREAM_NoError;
+}
+
+#undef TEMPLATE_FUNC_NAME
+#undef TEMPLATE_BUFFER_TYPE
+#undef TEMPLATE_TOKEN
+#undef TEMPLATE_TRANSFER_BYTE
+#undef TEMPLATE_CLEAR_PIPE
+#undef TEMPLATE_BUFFER_OFFSET
+#undef TEMPLATE_BUFFER_MOVE
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/USBController_UC3.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/USBController_UC3.c
new file mode 100644
index 000000000..fda0ddc39
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/USBController_UC3.c
@@ -0,0 +1,222 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "../../../../Common/Common.h"
+#if (ARCH == ARCH_UC3)
+
+#define __INCLUDE_FROM_USB_DRIVER
+#define __INCLUDE_FROM_USB_CONTROLLER_C
+#include "../USBController.h"
+
+#if defined(USB_CAN_BE_BOTH)
+volatile uint8_t USB_CurrentMode = USB_MODE_None;
+#endif
+
+#if !defined(USE_STATIC_OPTIONS)
+volatile uint8_t USB_Options;
+#endif
+
+void USB_Init(
+ #if defined(USB_CAN_BE_BOTH)
+ const uint8_t Mode
+ #endif
+
+ #if (defined(USB_CAN_BE_BOTH) && !defined(USE_STATIC_OPTIONS))
+ ,
+ #elif (!defined(USB_CAN_BE_BOTH) && defined(USE_STATIC_OPTIONS))
+ void
+ #endif
+
+ #if !defined(USE_STATIC_OPTIONS)
+ const uint8_t Options
+ #endif
+ )
+{
+ #if !defined(USE_STATIC_OPTIONS)
+ USB_Options = Options;
+ #endif
+
+ #if defined(USB_CAN_BE_BOTH)
+ if (Mode == USB_MODE_UID)
+ {
+ AVR32_USBB.USBCON.uide = true;
+ USB_INT_Enable(USB_INT_IDTI);
+ USB_CurrentMode = USB_GetUSBModeFromUID();
+ }
+ else
+ {
+ AVR32_USBB.USBCON.uide = false;
+ USB_CurrentMode = Mode;
+ }
+ #else
+ AVR32_USBB.USBCON.uide = false;
+ #endif
+
+ USB_IsInitialized = true;
+
+ USB_ResetInterface();
+}
+
+void USB_Disable(void)
+{
+ USB_INT_DisableAllInterrupts();
+ USB_INT_ClearAllInterrupts();
+
+ USB_Detach();
+ USB_Controller_Disable();
+
+ USB_OTGPAD_Off();
+
+ #if defined(USB_CAN_BE_BOTH)
+ USB_CurrentMode = USB_MODE_None;
+ #endif
+
+ AVR32_PM.GCCTRL[3].cen = false;
+
+ USB_IsInitialized = false;
+}
+
+void USB_ResetInterface(void)
+{
+ #if defined(USB_CAN_BE_BOTH)
+ bool UIDModeSelectEnabled = AVR32_USBB.USBCON.uide;
+ #endif
+
+ AVR32_PM.GCCTRL[AVR32_PM_GCLK_USBB].pllsel = !(USB_Options & USB_OPT_GCLK_SRC_OSC);
+ AVR32_PM.GCCTRL[AVR32_PM_GCLK_USBB].oscsel = !(USB_Options & USB_OPT_GCLK_CHANNEL_0);
+ AVR32_PM.GCCTRL[AVR32_PM_GCLK_USBB].diven = (F_USB != USB_CLOCK_REQUIRED_FREQ);
+ AVR32_PM.GCCTRL[AVR32_PM_GCLK_USBB].div = (F_USB == USB_CLOCK_REQUIRED_FREQ) ? 0 : (uint32_t)((F_USB / USB_CLOCK_REQUIRED_FREQ / 2) - 1);
+ AVR32_PM.GCCTRL[AVR32_PM_GCLK_USBB].cen = true;
+
+ USB_INT_DisableAllInterrupts();
+ USB_INT_ClearAllInterrupts();
+
+ USB_Controller_Reset();
+
+ #if defined(USB_CAN_BE_BOTH)
+ if (UIDModeSelectEnabled)
+ USB_INT_Enable(USB_INT_IDTI);
+ #endif
+
+ USB_CLK_Unfreeze();
+
+ if (USB_CurrentMode == USB_MODE_Device)
+ {
+ #if defined(USB_CAN_BE_DEVICE)
+ AVR32_USBB.USBCON.uimod = true;
+
+ USB_Init_Device();
+ #endif
+ }
+ else if (USB_CurrentMode == USB_MODE_Host)
+ {
+ #if defined(INVERTED_VBUS_ENABLE_LINE)
+ AVR32_USBB.USBCON.vbuspo = true;
+ #endif
+
+ #if defined(USB_CAN_BE_HOST)
+ AVR32_USBB.USBCON.uimod = false;
+
+ USB_Init_Host();
+ #endif
+ }
+
+ USB_OTGPAD_On();
+}
+
+#if defined(USB_CAN_BE_DEVICE)
+static void USB_Init_Device(void)
+{
+ USB_DeviceState = DEVICE_STATE_Unattached;
+ USB_Device_ConfigurationNumber = 0;
+
+ #if !defined(NO_DEVICE_REMOTE_WAKEUP)
+ USB_Device_RemoteWakeupEnabled = false;
+ #endif
+
+ #if !defined(NO_DEVICE_SELF_POWER)
+ USB_Device_CurrentlySelfPowered = false;
+ #endif
+
+ #if !defined(FIXED_CONTROL_ENDPOINT_SIZE)
+ USB_Descriptor_Device_t* DeviceDescriptorPtr;
+
+ if (CALLBACK_USB_GetDescriptor((DTYPE_Device << 8), 0, (void*)&DeviceDescriptorPtr) != NO_DESCRIPTOR)
+ USB_Device_ControlEndpointSize = DeviceDescriptorPtr->Endpoint0Size;
+ #endif
+
+ if (USB_Options & USB_DEVICE_OPT_LOWSPEED)
+ {
+ USB_Device_SetLowSpeed();
+ }
+ else
+ {
+ #if defined(USB_DEVICE_OPT_HIGHSPEED)
+ if (USB_Options & USB_DEVICE_OPT_HIGHSPEED)
+ USB_Device_SetHighSpeed();
+ else
+ USB_Device_SetFullSpeed();
+ #else
+ USB_Device_SetFullSpeed();
+ #endif
+ }
+
+ USB_INT_Enable(USB_INT_VBUSTI);
+
+ Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL,
+ USB_Device_ControlEndpointSize, 1);
+
+ USB_INT_Clear(USB_INT_SUSPI);
+ USB_INT_Enable(USB_INT_SUSPI);
+ USB_INT_Enable(USB_INT_EORSTI);
+
+ USB_Attach();
+}
+#endif
+
+#if defined(USB_CAN_BE_HOST)
+static void USB_Init_Host(void)
+{
+ USB_HostState = HOST_STATE_Unattached;
+ USB_Host_ConfigurationNumber = 0;
+ USB_Host_ControlPipeSize = PIPE_CONTROLPIPE_DEFAULT_SIZE;
+
+ USB_Host_HostMode_On();
+
+ USB_Host_VBUS_Auto_On();
+
+ USB_INT_Enable(USB_INT_DCONNI);
+ USB_INT_Enable(USB_INT_BCERRI);
+
+ USB_Attach();
+}
+#endif
+
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/USBController_UC3.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/USBController_UC3.h
new file mode 100644
index 000000000..2e824583a
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/USBController_UC3.h
@@ -0,0 +1,353 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief USB Controller definitions for the AVR32 UC3 microcontrollers.
+ * \copydetails Group_USBManagement_UC3
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_USBManagement
+ * \defgroup Group_USBManagement_UC3 USB Interface Management (UC3)
+ * \brief USB Controller definitions for the AVR32 UC3 microcontrollers.
+ *
+ * Functions, macros, variables, enums and types related to the setup and management of the USB interface.
+ *
+ * @{
+ */
+
+#ifndef __USBCONTROLLER_UC3_H__
+#define __USBCONTROLLER_UC3_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../USBMode.h"
+ #include "../Events.h"
+ #include "../USBTask.h"
+ #include "../USBInterrupt.h"
+
+ #if defined(USB_CAN_BE_HOST) || defined(__DOXYGEN__)
+ #include "../Host.h"
+ #include "../OTG.h"
+ #include "../Pipe.h"
+ #include "../HostStandardReq.h"
+ #include "../PipeStream.h"
+ #endif
+
+ #if defined(USB_CAN_BE_DEVICE) || defined(__DOXYGEN__)
+ #include "../Device.h"
+ #include "../Endpoint.h"
+ #include "../DeviceStandardReq.h"
+ #include "../EndpointStream.h"
+ #endif
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks and Defines: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ #if !defined(F_USB)
+ #error F_USB is not defined. You must define F_USB to the frequency of the clock input to the USB module.
+ #endif
+
+ #if (defined(USB_SERIES_UC3A3_AVR) || defined(USB_SERIES_UC3A4_AVR))
+ #if ((F_USB < 12000000) || (F_USB % 12000000))
+ #error Invalid F_USB specified. F_USB must be a multiple of 12MHz for UC3A3 and UC3A4 devices.
+ #endif
+ #else
+ #if ((F_USB < 48000000) || (F_USB % 48000000))
+ #error Invalid F_USB specified. F_USB must be a multiple of 48MHz for UC3A and UC3B devices.
+ #endif
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** \name USB Controller Option Masks */
+ //@{
+ /** Selects one of the system's main clock oscillators as the input clock to the USB Generic Clock source
+ * generation module. This indicates that an external oscillator should be used directly instead of an
+ * internal PLL clock source.
+ */
+ #define USB_OPT_GCLK_SRC_OSC (1 << 2)
+
+ /** Selects one of the system's PLL oscillators as the input clock to the USB Generic Clock source
+ * generation module. This indicates that one of the device's PLL outputs should be used instead of an
+ * external oscillator source.
+ */
+ #define USB_OPT_GCLK_SRC_PLL (0 << 2)
+
+ /** Selects PLL or External Oscillator 0 as the USB Generic Clock source module input clock. */
+ #define USB_OPT_GCLK_CHANNEL_0 (1 << 3)
+
+ /** Selects PLL or External Oscillator 1 as the USB Generic Clock source module input clock. */
+ #define USB_OPT_GCLK_CHANNEL_1 (0 << 3)
+ //@}
+
+ #if !defined(USB_STREAM_TIMEOUT_MS) || defined(__DOXYGEN__)
+ /** Constant for the maximum software timeout period of the USB data stream transfer functions
+ * (both control and standard) when in either device or host mode. If the next packet of a stream
+ * is not received or acknowledged within this time period, the stream function will fail.
+ *
+ * This value may be overridden in the user project makefile as the value of the
+ * \ref USB_STREAM_TIMEOUT_MS token, and passed to the compiler using the -D switch.
+ */
+ #define USB_STREAM_TIMEOUT_MS 100
+ #endif
+
+ /* Inline Functions: */
+ /** Determines if the VBUS line is currently high (i.e. the USB host is supplying power).
+ *
+ * \return Boolean \c true if the VBUS line is currently detecting power from a host, \c false otherwise.
+ */
+ static inline bool USB_VBUS_GetStatus(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool USB_VBUS_GetStatus(void)
+ {
+ return AVR32_USBB.USBSTA.vbus;
+ }
+
+ /** Detaches the device from the USB bus. This has the effect of removing the device from any
+ * attached host, ceasing USB communications. If no host is present, this prevents any host from
+ * enumerating the device once attached until \ref USB_Attach() is called.
+ */
+ static inline void USB_Detach(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Detach(void)
+ {
+ AVR32_USBB.UDCON.detach = true;
+ }
+
+ /** Attaches the device to the USB bus. This announces the device's presence to any attached
+ * USB host, starting the enumeration process. If no host is present, attaching the device
+ * will allow for enumeration once a host is connected to the device.
+ *
+ * This is inexplicably also required for proper operation while in host mode, to enable the
+ * attachment of a device to the host. This is despite the bit being located in the device-mode
+ * register and despite the datasheet making no mention of its requirement in host mode.
+ */
+ static inline void USB_Attach(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Attach(void)
+ {
+ AVR32_USBB.UDCON.detach = false;
+ }
+
+ /* Function Prototypes: */
+ /** Main function to initialize and start the USB interface. Once active, the USB interface will
+ * allow for device connection to a host when in device mode, or for device enumeration while in
+ * host mode.
+ *
+ * As the USB library relies on interrupts for the device and host mode enumeration processes,
+ * the user must enable global interrupts before or shortly after this function is called. In
+ * device mode, interrupts must be enabled within 500ms of this function being called to ensure
+ * that the host does not time out whilst enumerating the device. In host mode, interrupts may be
+ * enabled at the application's leisure however enumeration will not begin of an attached device
+ * until after this has occurred.
+ *
+ * Calling this function when the USB interface is already initialized will cause a complete USB
+ * interface reset and re-enumeration.
+ *
+ * \param[in] Mode Mask indicating what mode the USB interface is to be initialized to, a value
+ * from the \ref USB_Modes_t enum.
+ * \note This parameter does not exist on devices with only one supported USB
+ * mode (device or host).
+ *
+ * \param[in] Options Mask indicating the options which should be used when initializing the USB
+ * interface to control the USB interface's behavior. This should be comprised of
+ * a \c USB_OPT_REG_* mask to control the regulator, a \c USB_OPT_*_PLL mask to control the
+ * PLL, and a \c USB_DEVICE_OPT_* mask (when the device mode is enabled) to set the device
+ * mode speed.
+ *
+ * \note To reduce the FLASH requirements of the library if only device or host mode is required,
+ * the mode can be statically set in the project makefile by defining the token \c USB_DEVICE_ONLY
+ * (for device mode) or \c USB_HOST_ONLY (for host mode), passing the token to the compiler
+ * via the -D switch. If the mode is statically set, this parameter does not exist in the
+ * function prototype.
+ * \n\n
+ *
+ * \note To reduce the FLASH requirements of the library if only fixed settings are required,
+ * the options may be set statically in the same manner as the mode (see the Mode parameter of
+ * this function). To statically set the USB options, pass in the \c USE_STATIC_OPTIONS token,
+ * defined to the appropriate options masks. When the options are statically set, this
+ * parameter does not exist in the function prototype.
+ *
+ * \see \ref Group_Device for the \c USB_DEVICE_OPT_* masks.
+ */
+ void USB_Init(
+ #if defined(USB_CAN_BE_BOTH) || defined(__DOXYGEN__)
+ const uint8_t Mode
+ #endif
+
+ #if (defined(USB_CAN_BE_BOTH) && !defined(USE_STATIC_OPTIONS)) || defined(__DOXYGEN__)
+ ,
+ #elif (!defined(USB_CAN_BE_BOTH) && defined(USE_STATIC_OPTIONS))
+ void
+ #endif
+
+ #if !defined(USE_STATIC_OPTIONS) || defined(__DOXYGEN__)
+ const uint8_t Options
+ #endif
+ );
+
+ /** Shuts down the USB interface. This turns off the USB interface after deallocating all USB FIFO
+ * memory, endpoints and pipes. When turned off, no USB functionality can be used until the interface
+ * is restarted with the \ref USB_Init() function.
+ */
+ void USB_Disable(void);
+
+ /** Resets the interface, when already initialized. This will re-enumerate the device if already connected
+ * to a host, or re-enumerate an already attached device when in host mode.
+ */
+ void USB_ResetInterface(void);
+
+ /* Global Variables: */
+ #if defined(USB_CAN_BE_BOTH) || defined(__DOXYGEN__)
+ /** Indicates the mode that the USB interface is currently initialized to, a value from the
+ * \ref USB_Modes_t enum.
+ *
+ * \attention This variable should be treated as read-only in the user application, and never manually
+ * changed in value.
+ *
+ * \note When the controller is initialized into UID auto-detection mode, this variable will hold the
+ * currently selected USB mode (i.e. \ref USB_MODE_Device or \ref USB_MODE_Host). If the controller
+ * is fixed into a specific mode (either through the \c USB_DEVICE_ONLY or \c USB_HOST_ONLY compile time
+ * options, or a limitation of the USB controller in the chosen device model) this will evaluate to
+ * a constant of the appropriate value and will never evaluate to \ref USB_MODE_None even when the
+ * USB interface is not initialized.
+ */
+ extern volatile uint8_t USB_CurrentMode;
+ #elif defined(USB_CAN_BE_HOST)
+ #define USB_CurrentMode USB_MODE_Host
+ #elif defined(USB_CAN_BE_DEVICE)
+ #define USB_CurrentMode USB_MODE_Device
+ #endif
+
+ #if !defined(USE_STATIC_OPTIONS) || defined(__DOXYGEN__)
+ /** Indicates the current USB options that the USB interface was initialized with when \ref USB_Init()
+ * was called. This value will be one of the \c USB_MODE_* masks defined elsewhere in this module.
+ *
+ * \attention This variable should be treated as read-only in the user application, and never manually
+ * changed in value.
+ */
+ extern volatile uint8_t USB_Options;
+ #elif defined(USE_STATIC_OPTIONS)
+ #define USB_Options USE_STATIC_OPTIONS
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #if defined(USB_SERIES_UC3A3_AVR32) || defined(USB_SERIES_UC3A4_AVR32)
+ #define USB_CLOCK_REQUIRED_FREQ 12000000UL
+ #else
+ #define USB_CLOCK_REQUIRED_FREQ 48000000UL
+ #endif
+
+ /* Function Prototypes: */
+ #if defined(__INCLUDE_FROM_USB_CONTROLLER_C)
+ #if defined(USB_CAN_BE_DEVICE)
+ static void USB_Init_Device(void);
+ #endif
+
+ #if defined(USB_CAN_BE_HOST)
+ static void USB_Init_Host(void);
+ #endif
+ #endif
+
+ /* Inline Functions: */
+ static inline void USB_OTGPAD_On(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_OTGPAD_On(void)
+ {
+ AVR32_USBB.USBCON.otgpade = true;
+ }
+
+ static inline void USB_OTGPAD_Off(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_OTGPAD_Off(void)
+ {
+ AVR32_USBB.USBCON.otgpade = false;
+ }
+
+ static inline void USB_CLK_Freeze(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_CLK_Freeze(void)
+ {
+ AVR32_USBB.USBCON.frzclk = true;
+ }
+
+ static inline void USB_CLK_Unfreeze(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_CLK_Unfreeze(void)
+ {
+ AVR32_USBB.USBCON.frzclk = false;
+ }
+
+ static inline void USB_Controller_Enable(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Controller_Enable(void)
+ {
+ AVR32_USBB.USBCON.usbe = true;
+ }
+
+ static inline void USB_Controller_Disable(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Controller_Disable(void)
+ {
+ AVR32_USBB.USBCON.usbe = false;
+ }
+
+ static inline void USB_Controller_Reset(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Controller_Reset(void)
+ {
+ AVR32_USBB.USBCON.usbe = false;
+ AVR32_USBB.USBCON.usbe = true;
+ }
+
+ #if defined(USB_CAN_BE_BOTH)
+ static inline uint8_t USB_GetUSBModeFromUID(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t USB_GetUSBModeFromUID(void)
+ {
+ if (AVR32_USBB.USBSTA.id)
+ return USB_MODE_Device;
+ else
+ return USB_MODE_Host;
+ }
+ #endif
+
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/USBInterrupt_UC3.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/USBInterrupt_UC3.c
new file mode 100644
index 000000000..83ada8cc1
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/USBInterrupt_UC3.c
@@ -0,0 +1,228 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "../../../../Common/Common.h"
+#if (ARCH == ARCH_UC3)
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../USBInterrupt.h"
+
+void USB_INT_DisableAllInterrupts(void)
+{
+ AVR32_USBB.USBCON.vbuste = false;
+ AVR32_USBB.USBCON.idte = false;
+
+ AVR32_USBB.uhinteclr = -1;
+ AVR32_USBB.udinteclr = -1;
+}
+
+void USB_INT_ClearAllInterrupts(void)
+{
+ AVR32_USBB.USBSTACLR.vbustic = true;
+ AVR32_USBB.USBSTACLR.idtic = true;
+
+ AVR32_USBB.uhintclr = -1;
+ AVR32_USBB.udintclr = -1;
+}
+
+ISR(USB_GEN_vect)
+{
+ #if defined(USB_CAN_BE_DEVICE)
+ #if !defined(NO_SOF_EVENTS)
+ if (USB_INT_HasOccurred(USB_INT_SOFI) && USB_INT_IsEnabled(USB_INT_SOFI))
+ {
+ USB_INT_Clear(USB_INT_SOFI);
+
+ EVENT_USB_Device_StartOfFrame();
+ }
+ #endif
+
+ if (USB_INT_HasOccurred(USB_INT_VBUSTI) && USB_INT_IsEnabled(USB_INT_VBUSTI))
+ {
+ USB_INT_Clear(USB_INT_VBUSTI);
+
+ if (USB_VBUS_GetStatus())
+ {
+ USB_DeviceState = DEVICE_STATE_Powered;
+ EVENT_USB_Device_Connect();
+ }
+ else
+ {
+ USB_DeviceState = DEVICE_STATE_Unattached;
+ EVENT_USB_Device_Disconnect();
+ }
+ }
+
+ if (USB_INT_HasOccurred(USB_INT_SUSPI) && USB_INT_IsEnabled(USB_INT_SUSPI))
+ {
+ USB_INT_Disable(USB_INT_SUSPI);
+ USB_INT_Enable(USB_INT_WAKEUPI);
+
+ USB_CLK_Freeze();
+
+ USB_DeviceState = DEVICE_STATE_Suspended;
+ EVENT_USB_Device_Suspend();
+ }
+
+ if (USB_INT_HasOccurred(USB_INT_WAKEUPI) && USB_INT_IsEnabled(USB_INT_WAKEUPI))
+ {
+ USB_CLK_Unfreeze();
+
+ USB_INT_Clear(USB_INT_WAKEUPI);
+
+ USB_INT_Disable(USB_INT_WAKEUPI);
+ USB_INT_Enable(USB_INT_SUSPI);
+
+ if (USB_Device_ConfigurationNumber)
+ USB_DeviceState = DEVICE_STATE_Configured;
+ else
+ USB_DeviceState = (USB_Device_IsAddressSet()) ? DEVICE_STATE_Addressed : DEVICE_STATE_Powered;
+
+ EVENT_USB_Device_WakeUp();
+ }
+
+ if (USB_INT_HasOccurred(USB_INT_EORSTI) && USB_INT_IsEnabled(USB_INT_EORSTI))
+ {
+ USB_INT_Clear(USB_INT_EORSTI);
+
+ USB_DeviceState = DEVICE_STATE_Default;
+ USB_Device_ConfigurationNumber = 0;
+
+ USB_INT_Clear(USB_INT_SUSPI);
+ USB_INT_Disable(USB_INT_SUSPI);
+ USB_INT_Enable(USB_INT_WAKEUPI);
+
+ USB_Device_SetDeviceAddress(0);
+ Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL,
+ USB_Device_ControlEndpointSize, 1);
+
+ #if defined(INTERRUPT_CONTROL_ENDPOINT)
+ USB_INT_Enable(USB_INT_RXSTPI);
+ #endif
+
+ EVENT_USB_Device_Reset();
+ }
+ #endif
+
+ #if defined(USB_CAN_BE_HOST)
+ #if !defined(NO_SOF_EVENTS)
+ if (USB_INT_HasOccurred(USB_INT_HSOFI) && USB_INT_IsEnabled(USB_INT_HSOFI))
+ {
+ USB_INT_Clear(USB_INT_HSOFI);
+
+ EVENT_USB_Host_StartOfFrame();
+ }
+ #endif
+
+ if (USB_INT_HasOccurred(USB_INT_DDISCI) && USB_INT_IsEnabled(USB_INT_DDISCI))
+ {
+ USB_INT_Clear(USB_INT_DDISCI);
+ USB_INT_Clear(USB_INT_DCONNI);
+ USB_INT_Disable(USB_INT_DDISCI);
+
+ EVENT_USB_Host_DeviceUnattached();
+
+ USB_ResetInterface();
+ }
+
+ if (USB_INT_HasOccurred(USB_INT_VBERRI) && USB_INT_IsEnabled(USB_INT_VBERRI))
+ {
+ USB_INT_Clear(USB_INT_VBERRI);
+
+ USB_Host_VBUS_Manual_Off();
+ USB_Host_VBUS_Auto_Off();
+
+ EVENT_USB_Host_HostError(HOST_ERROR_VBusVoltageDip);
+ EVENT_USB_Host_DeviceUnattached();
+
+ USB_HostState = HOST_STATE_Unattached;
+ }
+
+ if (USB_INT_HasOccurred(USB_INT_DCONNI) && USB_INT_IsEnabled(USB_INT_DCONNI))
+ {
+ USB_INT_Clear(USB_INT_DCONNI);
+ USB_INT_Disable(USB_INT_DCONNI);
+
+ EVENT_USB_Host_DeviceAttached();
+
+ USB_INT_Enable(USB_INT_DDISCI);
+
+ USB_HostState = HOST_STATE_Powered;
+ }
+
+ if (USB_INT_HasOccurred(USB_INT_BCERRI) && USB_INT_IsEnabled(USB_INT_BCERRI))
+ {
+ USB_INT_Clear(USB_INT_BCERRI);
+
+ EVENT_USB_Host_DeviceEnumerationFailed(HOST_ENUMERROR_NoDeviceDetected, 0);
+ EVENT_USB_Host_DeviceUnattached();
+
+ USB_ResetInterface();
+ }
+ #endif
+
+ #if defined(USB_CAN_BE_BOTH)
+ if (USB_INT_HasOccurred(USB_INT_IDTI) && USB_INT_IsEnabled(USB_INT_IDTI))
+ {
+ USB_INT_Clear(USB_INT_IDTI);
+
+ if (USB_DeviceState != DEVICE_STATE_Unattached)
+ EVENT_USB_Device_Disconnect();
+
+ if (USB_HostState != HOST_STATE_Unattached)
+ EVENT_USB_Host_DeviceUnattached();
+
+ USB_CurrentMode = USB_GetUSBModeFromUID();
+ USB_ResetInterface();
+
+ EVENT_USB_UIDChange();
+ }
+ #endif
+}
+
+#if defined(INTERRUPT_CONTROL_ENDPOINT) && defined(USB_CAN_BE_DEVICE)
+ISR(USB_COM_vect)
+{
+ uint8_t PrevSelectedEndpoint = Endpoint_GetCurrentEndpoint();
+
+ Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);
+ USB_INT_Disable(USB_INT_RXSTPI);
+
+ GlobalInterruptEnable();
+
+ USB_Device_ProcessControlRequest();
+
+ Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);
+ USB_INT_Enable(USB_INT_RXSTPI);
+ Endpoint_SelectEndpoint(PrevSelectedEndpoint);
+}
+#endif
+
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/USBInterrupt_UC3.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/USBInterrupt_UC3.h
new file mode 100644
index 000000000..ddd5389c2
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/UC3/USBInterrupt_UC3.h
@@ -0,0 +1,376 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief USB Controller Interrupt definitions for the AVR32 UC3 microcontrollers.
+ *
+ * This file contains definitions required for the correct handling of low level USB service routine interrupts
+ * from the USB controller.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+#ifndef __USBINTERRUPT_UC3_H__
+#define __USBINTERRUPT_UC3_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* External Variables: */
+ extern volatile uint32_t USB_Endpoint_SelectedEndpoint;
+
+ /* Enums: */
+ enum USB_Interrupts_t
+ {
+ USB_INT_VBUSTI = 0,
+ #if (defined(USB_CAN_BE_BOTH) || defined(__DOXYGEN__))
+ USB_INT_IDTI = 1,
+ #endif
+ #if (defined(USB_CAN_BE_DEVICE) || defined(__DOXYGEN__))
+ USB_INT_WAKEUPI = 2,
+ USB_INT_SUSPI = 3,
+ USB_INT_EORSTI = 4,
+ USB_INT_SOFI = 5,
+ USB_INT_RXSTPI = 6,
+ #endif
+ #if (defined(USB_CAN_BE_HOST) || defined(__DOXYGEN__))
+ USB_INT_HSOFI = 7,
+ USB_INT_DCONNI = 8,
+ USB_INT_DDISCI = 9,
+ USB_INT_RSTI = 10,
+ USB_INT_BCERRI = 11,
+ USB_INT_VBERRI = 12,
+ #endif
+ };
+
+ /* Inline Functions: */
+ static inline void USB_INT_Enable(const uint8_t Interrupt) ATTR_ALWAYS_INLINE;
+ static inline void USB_INT_Enable(const uint8_t Interrupt)
+ {
+ switch (Interrupt)
+ {
+ case USB_INT_VBUSTI:
+ AVR32_USBB.USBCON.vbuste = true;
+ break;
+ #if defined(USB_CAN_BE_BOTH)
+ case USB_INT_IDTI:
+ AVR32_USBB.USBCON.idte = true;
+ break;
+ #endif
+ #if defined(USB_CAN_BE_DEVICE)
+ case USB_INT_WAKEUPI:
+ AVR32_USBB.UDINTESET.wakeupes = true;
+ break;
+ case USB_INT_SUSPI:
+ AVR32_USBB.UDINTESET.suspes = true;
+ break;
+ case USB_INT_EORSTI:
+ AVR32_USBB.UDINTESET.eorstes = true;
+ break;
+ case USB_INT_SOFI:
+ AVR32_USBB.UDINTESET.sofes = true;
+ break;
+ case USB_INT_RXSTPI:
+ (&AVR32_USBB.UECON0SET)[USB_Endpoint_SelectedEndpoint].rxstpes = true;
+ break;
+ #endif
+ #if defined(USB_CAN_BE_HOST)
+ case USB_INT_HSOFI:
+ AVR32_USBB.UHINTESET.hsofies = true;
+ break;
+ case USB_INT_DCONNI:
+ AVR32_USBB.UHINTESET.dconnies = true;
+ break;
+ case USB_INT_DDISCI:
+ AVR32_USBB.UHINTESET.ddiscies = true;
+ break;
+ case USB_INT_RSTI:
+ AVR32_USBB.UHINTESET.rsties = true;
+ break;
+ case USB_INT_BCERRI:
+ AVR32_USBB.USBCON.bcerre = true;
+ break;
+ case USB_INT_VBERRI:
+ AVR32_USBB.USBCON.vberre = true;
+ break;
+ #endif
+ default:
+ break;
+ }
+ }
+
+ static inline void USB_INT_Disable(const uint8_t Interrupt) ATTR_ALWAYS_INLINE;
+ static inline void USB_INT_Disable(const uint8_t Interrupt)
+ {
+ switch (Interrupt)
+ {
+ case USB_INT_VBUSTI:
+ AVR32_USBB.USBCON.vbuste = false;
+ break;
+ #if defined(USB_CAN_BE_BOTH)
+ case USB_INT_IDTI:
+ AVR32_USBB.USBCON.idte = false;
+ break;
+ #endif
+ #if defined(USB_CAN_BE_DEVICE)
+ case USB_INT_WAKEUPI:
+ AVR32_USBB.UDINTECLR.wakeupec = true;
+ break;
+ case USB_INT_SUSPI:
+ AVR32_USBB.UDINTECLR.suspec = true;
+ break;
+ case USB_INT_EORSTI:
+ AVR32_USBB.UDINTECLR.eorstec = true;
+ break;
+ case USB_INT_SOFI:
+ AVR32_USBB.UDINTECLR.sofec = true;
+ break;
+ case USB_INT_RXSTPI:
+ (&AVR32_USBB.UECON0CLR)[USB_Endpoint_SelectedEndpoint].rxstpec = true;
+ break;
+ #endif
+ #if defined(USB_CAN_BE_HOST)
+ case USB_INT_HSOFI:
+ AVR32_USBB.UHINTECLR.hsofiec = true;
+ break;
+ case USB_INT_DCONNI:
+ AVR32_USBB.UHINTECLR.dconniec = true;
+ break;
+ case USB_INT_DDISCI:
+ AVR32_USBB.UHINTECLR.ddisciec = true;
+ break;
+ case USB_INT_RSTI:
+ AVR32_USBB.UHINTECLR.rstiec = true;
+ break;
+ case USB_INT_BCERRI:
+ AVR32_USBB.USBCON.bcerre = false;
+ break;
+ case USB_INT_VBERRI:
+ AVR32_USBB.USBCON.vberre = false;
+ break;
+ #endif
+ default:
+ break;
+ }
+ }
+
+ static inline void USB_INT_Clear(const uint8_t Interrupt) ATTR_ALWAYS_INLINE;
+ static inline void USB_INT_Clear(const uint8_t Interrupt)
+ {
+ switch (Interrupt)
+ {
+ case USB_INT_VBUSTI:
+ AVR32_USBB.USBSTACLR.vbustic = true;
+ (void)AVR32_USBB.USBSTACLR;
+ break;
+ #if defined(USB_CAN_BE_BOTH)
+ case USB_INT_IDTI:
+ AVR32_USBB.USBSTACLR.idtic = true;
+ (void)AVR32_USBB.USBSTACLR;
+ break;
+ #endif
+ #if defined(USB_CAN_BE_DEVICE)
+ case USB_INT_WAKEUPI:
+ AVR32_USBB.UDINTCLR.wakeupc = true;
+ (void)AVR32_USBB.UDINTCLR;
+ break;
+ case USB_INT_SUSPI:
+ AVR32_USBB.UDINTCLR.suspc = true;
+ (void)AVR32_USBB.UDINTCLR;
+ break;
+ case USB_INT_EORSTI:
+ AVR32_USBB.UDINTCLR.eorstc = true;
+ (void)AVR32_USBB.UDINTCLR;
+ break;
+ case USB_INT_SOFI:
+ AVR32_USBB.UDINTCLR.sofc = true;
+ (void)AVR32_USBB.UDINTCLR;
+ break;
+ case USB_INT_RXSTPI:
+ (&AVR32_USBB.UESTA0CLR)[USB_Endpoint_SelectedEndpoint].rxstpic = true;
+ break;
+ #endif
+ #if defined(USB_CAN_BE_HOST)
+ case USB_INT_HSOFI:
+ AVR32_USBB.UHINTCLR.hsofic = true;
+ (void)AVR32_USBB.UHINTCLR;
+ break;
+ case USB_INT_DCONNI:
+ AVR32_USBB.UHINTCLR.dconnic = true;
+ (void)AVR32_USBB.UHINTCLR;
+ break;
+ case USB_INT_DDISCI:
+ AVR32_USBB.UHINTCLR.ddiscic = true;
+ (void)AVR32_USBB.UHINTCLR;
+ break;
+ case USB_INT_RSTI:
+ AVR32_USBB.UHINTCLR.rstic = true;
+ (void)AVR32_USBB.UHINTCLR;
+ break;
+ case USB_INT_BCERRI:
+ AVR32_USBB.USBSTACLR.bcerric = true;
+ (void)AVR32_USBB.USBSTACLR;
+ break;
+ case USB_INT_VBERRI:
+ AVR32_USBB.USBSTACLR.vberric = true;
+ (void)AVR32_USBB.USBSTACLR;
+ break;
+ #endif
+ default:
+ break;
+ }
+ }
+
+ static inline bool USB_INT_IsEnabled(const uint8_t Interrupt) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline bool USB_INT_IsEnabled(const uint8_t Interrupt)
+ {
+ switch (Interrupt)
+ {
+ case USB_INT_VBUSTI:
+ return AVR32_USBB.USBCON.vbuste;
+ #if defined(USB_CAN_BE_BOTH)
+ case USB_INT_IDTI:
+ return AVR32_USBB.USBCON.idte;
+ #endif
+ #if defined(USB_CAN_BE_DEVICE)
+ case USB_INT_WAKEUPI:
+ return AVR32_USBB.UDINTE.wakeupe;
+ case USB_INT_SUSPI:
+ return AVR32_USBB.UDINTE.suspe;
+ case USB_INT_EORSTI:
+ return AVR32_USBB.UDINTE.eorste;
+ case USB_INT_SOFI:
+ return AVR32_USBB.UDINTE.sofe;
+ case USB_INT_RXSTPI:
+ return (&AVR32_USBB.UECON0)[USB_Endpoint_SelectedEndpoint].rxstpe;
+ #endif
+ #if defined(USB_CAN_BE_HOST)
+ case USB_INT_HSOFI:
+ return AVR32_USBB.UHINTE.hsofie;
+ case USB_INT_DCONNI:
+ return AVR32_USBB.UHINTE.dconnie;
+ case USB_INT_DDISCI:
+ return AVR32_USBB.UHINTE.ddiscie;
+ case USB_INT_RSTI:
+ return AVR32_USBB.UHINTE.rstie;
+ case USB_INT_BCERRI:
+ return AVR32_USBB.USBCON.bcerre;
+ case USB_INT_VBERRI:
+ return AVR32_USBB.USBCON.vberre;
+ #endif
+ default:
+ return false;
+ }
+ }
+
+ static inline bool USB_INT_HasOccurred(const uint8_t Interrupt) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline bool USB_INT_HasOccurred(const uint8_t Interrupt)
+ {
+ switch (Interrupt)
+ {
+ case USB_INT_VBUSTI:
+ return AVR32_USBB.USBSTA.vbusti;
+ #if defined(USB_CAN_BE_BOTH)
+ case USB_INT_IDTI:
+ return AVR32_USBB.USBSTA.idti;
+ #endif
+ #if defined(USB_CAN_BE_DEVICE)
+ case USB_INT_WAKEUPI:
+ return AVR32_USBB.UDINT.wakeup;
+ case USB_INT_SUSPI:
+ return AVR32_USBB.UDINT.susp;
+ case USB_INT_EORSTI:
+ return AVR32_USBB.UDINT.eorst;
+ case USB_INT_SOFI:
+ return AVR32_USBB.UDINT.sof;
+ case USB_INT_RXSTPI:
+ return (&AVR32_USBB.UESTA0)[USB_Endpoint_SelectedEndpoint].rxstpi;
+ #endif
+ #if defined(USB_CAN_BE_HOST)
+ case USB_INT_HSOFI:
+ return AVR32_USBB.UHINT.hsofi;
+ case USB_INT_DCONNI:
+ return AVR32_USBB.UHINT.dconni;
+ case USB_INT_DDISCI:
+ return AVR32_USBB.UHINT.ddisci;
+ case USB_INT_RSTI:
+ return AVR32_USBB.UHINT.rsti;
+ case USB_INT_BCERRI:
+ return AVR32_USBB.USBSTA.bcerri;
+ case USB_INT_VBERRI:
+ return AVR32_USBB.USBSTA.vberri;
+ #endif
+ default:
+ return false;
+ }
+ }
+
+ /* Includes: */
+ #include "../USBMode.h"
+ #include "../Events.h"
+ #include "../USBController.h"
+
+ /* Function Prototypes: */
+ void USB_INT_ClearAllInterrupts(void);
+ void USB_INT_DisableAllInterrupts(void);
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Function Prototypes: */
+ #if defined(__DOXYGEN__)
+ /** Interrupt service routine handler for the USB controller ISR group. This interrupt routine <b>must</b> be
+ * linked to the entire USB controller ISR vector group inside the AVR32's interrupt controller peripheral,
+ * using the user application's preferred USB controller driver.
+ */
+ void USB_GEN_vect(void);
+ #else
+ ISR(USB_GEN_vect);
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/USBController.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/USBController.h
new file mode 100644
index 000000000..c1d74c32b
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/USBController.h
@@ -0,0 +1,165 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Common USB Controller definitions for all architectures.
+ * \copydetails Group_USBManagement
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_USB
+ * \defgroup Group_USBManagement USB Interface Management
+ * \brief USB Controller definitions for general USB controller management.
+ *
+ * Functions, macros, variables, enums and types related to the setup and management of the USB interface.
+ *
+ * @{
+ */
+
+#ifndef __USBCONTROLLER_H__
+#define __USBCONTROLLER_H__
+
+ /* Includes: */
+ #include "../../../Common/Common.h"
+ #include "USBMode.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks and Defines: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Defines: */
+ /** \name Endpoint Direction Masks */
+ //@{
+ /** Endpoint direction mask, for masking against endpoint addresses to retrieve the endpoint's
+ * direction for comparing with the \c ENDPOINT_DIR_* masks.
+ */
+ #define ENDPOINT_DIR_MASK 0x80
+
+ /** Endpoint address direction mask for an OUT direction (Host to Device) endpoint. This may be ORed with
+ * the index of the address within a device to obtain the full endpoint address.
+ */
+ #define ENDPOINT_DIR_OUT 0x00
+
+ /** Endpoint address direction mask for an IN direction (Device to Host) endpoint. This may be ORed with
+ * the index of the address within a device to obtain the full endpoint address.
+ */
+ #define ENDPOINT_DIR_IN 0x80
+ //@}
+
+ /** \name Pipe Direction Masks */
+ //@{
+ /** Pipe direction mask, for masking against pipe addresses to retrieve the pipe's
+ * direction for comparing with the \c PIPE_DIR_* masks.
+ */
+ #define PIPE_DIR_MASK 0x80
+
+ /** Endpoint address direction mask for an OUT direction (Host to Device) endpoint. This may be ORed with
+ * the index of the address within a device to obtain the full endpoint address.
+ */
+ #define PIPE_DIR_OUT 0x00
+
+ /** Endpoint address direction mask for an IN direction (Device to Host) endpoint. This may be ORed with
+ * the index of the address within a device to obtain the full endpoint address.
+ */
+ #define PIPE_DIR_IN 0x80
+ //@}
+
+ /** \name Endpoint/Pipe Type Masks */
+ //@{
+ /** Mask for determining the type of an endpoint from an endpoint descriptor. This should then be compared
+ * with the \c EP_TYPE_* masks to determine the exact type of the endpoint.
+ */
+ #define EP_TYPE_MASK 0x03
+
+ /** Mask for a CONTROL type endpoint or pipe.
+ *
+ * \note See \ref Group_EndpointManagement and \ref Group_PipeManagement for endpoint/pipe functions.
+ */
+ #define EP_TYPE_CONTROL 0x00
+
+ /** Mask for an ISOCHRONOUS type endpoint or pipe.
+ *
+ * \note See \ref Group_EndpointManagement and \ref Group_PipeManagement for endpoint/pipe functions.
+ */
+ #define EP_TYPE_ISOCHRONOUS 0x01
+
+ /** Mask for a BULK type endpoint or pipe.
+ *
+ * \note See \ref Group_EndpointManagement and \ref Group_PipeManagement for endpoint/pipe functions.
+ */
+ #define EP_TYPE_BULK 0x02
+
+ /** Mask for an INTERRUPT type endpoint or pipe.
+ *
+ * \note See \ref Group_EndpointManagement and \ref Group_PipeManagement for endpoint/pipe functions.
+ */
+ #define EP_TYPE_INTERRUPT 0x03
+ //@}
+
+ /* Enums: */
+ /** Enum for the possible USB controller modes, for initialization via \ref USB_Init() and indication back to the
+ * user application via \ref USB_CurrentMode.
+ */
+ enum USB_Modes_t
+ {
+ USB_MODE_None = 0, /**< Indicates that the controller is currently not initialized in any specific USB mode. */
+ USB_MODE_Device = 1, /**< Indicates that the controller is currently initialized in USB Device mode. */
+ USB_MODE_Host = 2, /**< Indicates that the controller is currently initialized in USB Host mode. */
+ USB_MODE_UID = 3, /**< Indicates that the controller should determine the USB mode from the UID pin of the
+ * USB connector.
+ */
+ };
+
+ /* Architecture Includes: */
+ #if (ARCH == ARCH_AVR8)
+ #include "AVR8/USBController_AVR8.h"
+ #elif (ARCH == ARCH_UC3)
+ #include "UC3/USBController_UC3.h"
+ #elif (ARCH == ARCH_XMEGA)
+ #include "XMEGA/USBController_XMEGA.h"
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/USBInterrupt.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/USBInterrupt.h
new file mode 100644
index 000000000..3dcfd5fed
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/USBInterrupt.h
@@ -0,0 +1,73 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief USB controller interrupt service routine management.
+ *
+ * This file contains definitions required for the correct handling of low level USB service routine interrupts
+ * from the USB controller.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+#ifndef __USBINTERRUPT_H__
+#define __USBINTERRUPT_H__
+
+ /* Includes: */
+ #include "../../../Common/Common.h"
+ #include "USBMode.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Architecture Includes: */
+ #if (ARCH == ARCH_AVR8)
+ #include "AVR8/USBInterrupt_AVR8.h"
+ #elif (ARCH == ARCH_UC3)
+ #include "UC3/USBInterrupt_UC3.h"
+ #elif (ARCH == ARCH_XMEGA)
+ #include "XMEGA/USBInterrupt_XMEGA.h"
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/USBMode.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/USBMode.h
new file mode 100644
index 000000000..09cf3076b
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/USBMode.h
@@ -0,0 +1,283 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief USB mode and feature support definitions.
+ * \copydetails Group_USBMode
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_USB
+ * \defgroup Group_USBMode USB Mode Tokens
+ * \brief USB mode and feature support definitions.
+ *
+ * This file defines macros indicating the type of USB controller the library is being compiled for, and its
+ * capabilities. These macros may then be referenced in the user application to selectively enable or disable
+ * code sections depending on if they are defined or not.
+ *
+ * After the inclusion of the master USB driver header, one or more of the following tokens may be defined, to
+ * allow the user code to conditionally enable or disable code based on the USB controller family and allowable
+ * USB modes. These tokens may be tested against to eliminate code relating to a USB mode which is not enabled for
+ * the given compilation.
+ *
+ * @{
+ */
+
+#ifndef __USBMODE_H__
+#define __USBMODE_H__
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Includes: */
+ #include "../../../Common/Common.h"
+
+ /* Public Interface - May be used in end-application: */
+ #if defined(__DOXYGEN__)
+ /** Indicates that the target AVR microcontroller belongs to the Series 2 AVR8 USB controller
+ * (i.e. AT90USBxxx2 or ATMEGAxxU2) when defined.
+ */
+ #define USB_SERIES_2_AVR
+
+ /** Indicates that the target AVR microcontroller belongs to the Series 4 AVR8 USB controller
+ * (i.e. ATMEGAxxU4) when defined.
+ */
+ #define USB_SERIES_4_AVR
+
+ /** Indicates that the target AVR microcontroller belongs to the Series 6 AVR8 USB controller
+ * (i.e. AT90USBxxx6) when defined.
+ */
+ #define USB_SERIES_6_AVR
+
+ /** Indicates that the target AVR microcontroller belongs to the Series 7 AVR8 USB controller
+ * (i.e. AT90USBxxx7) when defined.
+ */
+ #define USB_SERIES_7_AVR
+
+ /** Indicates that the target AVR microcontroller belongs to the AVR32 UC3A0 Series USB controller
+ * (i.e. AT32UC3A0*) when defined.
+ */
+ #define USB_SERIES_UC3A0_AVR
+
+ /** Indicates that the target AVR microcontroller belongs to the AVR32 UC3A1 Series USB controller
+ * (i.e. AT32UC3A1*) when defined.
+ */
+ #define USB_SERIES_UC3A1_AVR
+
+ /** Indicates that the target AVR microcontroller belongs to the AVR32 UC3A3 Series USB controller
+ * (i.e. AT32UC3A3*) when defined.
+ */
+ #define USB_SERIES_UC3A3_AVR
+
+ /** Indicates that the target AVR microcontroller belongs to the AVR32 UC3A4 Series USB controller
+ * (i.e. AT32UC3A4*) when defined.
+ */
+ #define USB_SERIES_UC3A4_AVR
+
+ /** Indicates that the target AVR microcontroller belongs to the AVR32 UC3B0 Series USB controller
+ * (i.e. AT32UC3B0*) when defined.
+ */
+ #define USB_SERIES_UC3B0_AVR
+
+ /** Indicates that the target AVR microcontroller belongs to the AVR32 UC3B1 Series USB controller
+ * (i.e. AT32UC3B1*) when defined.
+ */
+ #define USB_SERIES_UC3B1_AVR
+
+ /** Indicates that the target AVR microcontroller belongs to the XMEGA A1U Series USB controller
+ * (i.e. ATXMEGA*A1U) when defined.
+ */
+ #define USB_SERIES_A1U_XMEGA
+
+ /** Indicates that the target AVR microcontroller belongs to the XMEGA A3U Series USB controller
+ * (i.e. ATXMEGA*A3U) when defined.
+ */
+ #define USB_SERIES_A3U_XMEGA
+
+ /** Indicates that the target AVR microcontroller belongs to the XMEGA A4U Series USB controller
+ * (i.e. ATXMEGA*A4U) when defined.
+ */
+ #define USB_SERIES_A4U_XMEGA
+
+ /** Indicates that the target AVR microcontroller belongs to the XMEGA B1 Series USB controller
+ * (i.e. ATXMEGA*B1) when defined.
+ */
+ #define USB_SERIES_B1_XMEGA
+
+ /** Indicates that the target AVR microcontroller belongs to the XMEGA B3 Series USB controller
+ * (i.e. ATXMEGA*B3) when defined.
+ */
+ #define USB_SERIES_B3_XMEGA
+
+ /** Indicates that the target AVR microcontroller belongs to the XMEGA C3 Series USB controller
+ * (i.e. ATXMEGA*C3) when defined.
+ */
+ #define USB_SERIES_C3_XMEGA
+
+ /** Indicates that the target AVR microcontroller belongs to the XMEGA C4 Series USB controller
+ * (i.e. ATXMEGA*C4) when defined.
+ */
+ #define USB_SERIES_C4_XMEGA
+
+ /** Indicates that the target microcontroller and compilation settings allow for the
+ * target to be configured in USB Device mode when defined.
+ */
+ #define USB_CAN_BE_DEVICE
+
+ /** Indicates that the target microcontroller and compilation settings allow for the
+ * target to be configured in USB Host mode when defined.
+ */
+ #define USB_CAN_BE_HOST
+
+ /** Indicates that the target microcontroller and compilation settings allow for the
+ * target to be configured in either USB Device or Host mode when defined.
+ */
+ #define USB_CAN_BE_BOTH
+ #else
+ /* Macros: */
+ #if (defined(__AVR_AT90USB162__) || defined(__AVR_AT90USB82__) || \
+ defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__))
+ #define USB_SERIES_2_AVR
+ #define USB_CAN_BE_DEVICE
+ #elif (defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__))
+ #define USB_SERIES_4_AVR
+ #define USB_CAN_BE_DEVICE
+ #elif (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__))
+ #define USB_SERIES_6_AVR
+ #define USB_CAN_BE_DEVICE
+ #elif (defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1287__))
+ #define USB_SERIES_7_AVR
+ #define USB_CAN_BE_DEVICE
+ #define USB_CAN_BE_HOST
+ #elif (defined(__AVR32_UC3A0512__) || defined(__AVR32_UC3A0256__) || \
+ defined(__AVR32_UC3A0128__) || defined(__AVR32_UC3A064__))
+ #define USB_SERIES_UC3A0_AVR32
+ #define USB_CAN_BE_DEVICE
+ #define USB_CAN_BE_HOST
+ #elif (defined(__AVR32_UC3A1512__) || defined(__AVR32_UC3A1256__) || \
+ defined(__AVR32_UC3A1128__) || defined(__AVR32_UC3A164__))
+ #define USB_SERIES_UC3A1_AVR32
+ #define USB_CAN_BE_DEVICE
+ #define USB_CAN_BE_HOST
+ #elif (defined(__AVR32_UC3A3256__) || defined(__AVR32_UC3A3256S__) || \
+ defined(__AVR32_UC3A3128__) || defined(__AVR32_UC3A3128S__) || \
+ defined(__AVR32_UC3A364__) || defined(__AVR32_UC3A364S__))
+ #define USB_SERIES_UC3A3_AVR32
+ #define USB_CAN_BE_DEVICE
+ #define USB_CAN_BE_HOST
+ #elif (defined(__AVR32_UC3A4256__) || defined(__AVR32_UC3A4256S__) || \
+ defined(__AVR32_UC3A4128__) || defined(__AVR32_UC3A4128S__) || \
+ defined(__AVR32_UC3A464__) || defined(__AVR32_UC3A464S__))
+ #define USB_SERIES_UC3A4_AVR32
+ #define USB_CAN_BE_DEVICE
+ #define USB_CAN_BE_HOST
+ #elif (defined(__AVR32_UC3B0512__) || defined(__AVR32_UC3B0256__) || \
+ defined(__AVR32_UC3B0128__) || defined(__AVR32_UC3B064__))
+ #define USB_SERIES_UC3B0_AVR32
+ #define USB_CAN_BE_DEVICE
+ #define USB_CAN_BE_HOST
+ #elif (defined(__AVR32_UC3B1512__) || defined(__AVR32_UC3B1256__) || \
+ defined(__AVR32_UC3B1128__) || defined(__AVR32_UC3B164__))
+ #define USB_SERIES_UC3B1_AVR32
+ #define USB_CAN_BE_DEVICE
+ #define USB_CAN_BE_HOST
+ #elif (defined(__AVR_ATxmega128A1U__) || defined(__AVR_ATxmega64A1U__))
+ #define USB_SERIES_A1U_XMEGA
+ #define USB_CAN_BE_DEVICE
+ #elif (defined(__AVR_ATxmega64A3U__) || defined(__AVR_ATxmega128A3U__) || \
+ defined(__AVR_ATxmega192A3U__) || defined(__AVR_ATxmega256A3U__))
+ #define USB_SERIES_A3U_XMEGA
+ #define USB_CAN_BE_DEVICE
+ #elif (defined(__AVR_ATxmega256A3BU__))
+ #define USB_SERIES_A3BU_XMEGA
+ #define USB_CAN_BE_DEVICE
+ #elif (defined(__AVR_ATxmega16A4U__) || defined(__AVR_ATxmega32A4U__) || \
+ defined(__AVR_ATxmega64A4U__) || defined(__AVR_ATxmega128A4U__))
+ #define USB_SERIES_A4U_XMEGA
+ #define USB_CAN_BE_DEVICE
+ #elif (defined(__AVR_ATxmega128B1__) || defined(__AVR_ATxmega64B1__))
+ #define USB_SERIES_B1_XMEGA
+ #define USB_CAN_BE_DEVICE
+ #elif (defined(__AVR_ATxmega128B3__) || defined(__AVR_ATxmega64B3__))
+ #define USB_SERIES_B3_XMEGA
+ #define USB_CAN_BE_DEVICE
+ #elif (defined(__AVR_ATxmega128C3__) || defined(__AVR_ATxmega64C3__) || \
+ defined(__AVR_ATxmega192C3__) || defined(__AVR_ATxmega256C3__) || \
+ defined(__AVR_ATxmega384C3__))
+ #define USB_SERIES_C3_XMEGA
+ #define USB_CAN_BE_DEVICE
+ #elif (defined(__AVR_ATxmega16C4__) || defined(__AVR_ATxmega32C4__))
+ #define USB_SERIES_C4_XMEGA
+ #define USB_CAN_BE_DEVICE
+ #endif
+
+ #if (defined(USB_HOST_ONLY) && defined(USB_DEVICE_ONLY))
+ #error USB_HOST_ONLY and USB_DEVICE_ONLY are mutually exclusive.
+ #elif defined(USB_HOST_ONLY)
+ #if !defined(USB_CAN_BE_HOST)
+ #error USB_HOST_ONLY is not available for the currently selected microcontroller model.
+ #else
+ #undef USB_CAN_BE_DEVICE
+ #endif
+ #elif defined(USB_DEVICE_ONLY)
+ #if !defined(USB_CAN_BE_DEVICE)
+ #error USB_DEVICE_ONLY is not available for the currently selected microcontroller model.
+ #else
+ #undef USB_CAN_BE_HOST
+ #endif
+ #endif
+
+ #if (defined(USB_CAN_BE_DEVICE) && defined(USB_CAN_BE_HOST))
+ #define USB_CAN_BE_BOTH
+ #endif
+
+ #if (!defined(USB_CAN_BE_DEVICE) && !defined(USB_CAN_BE_HOST))
+ #error The currently selected device, USB mode or architecture is not supported.
+ #endif
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/USBTask.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/USBTask.c
new file mode 100644
index 000000000..30a3cd682
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/USBTask.c
@@ -0,0 +1,89 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#define __INCLUDE_FROM_USBTASK_C
+#define __INCLUDE_FROM_USB_DRIVER
+#include "USBTask.h"
+
+volatile bool USB_IsInitialized;
+USB_Request_Header_t USB_ControlRequest;
+
+#if defined(USB_CAN_BE_HOST) && !defined(HOST_STATE_AS_GPIOR)
+volatile uint8_t USB_HostState;
+#endif
+
+#if defined(USB_CAN_BE_DEVICE) && !defined(DEVICE_STATE_AS_GPIOR)
+volatile uint8_t USB_DeviceState;
+#endif
+
+void USB_USBTask(void)
+{
+ #if defined(USB_CAN_BE_BOTH)
+ if (USB_CurrentMode == USB_MODE_Device)
+ USB_DeviceTask();
+ else if (USB_CurrentMode == USB_MODE_Host)
+ USB_HostTask();
+ #elif defined(USB_CAN_BE_HOST)
+ USB_HostTask();
+ #elif defined(USB_CAN_BE_DEVICE)
+ USB_DeviceTask();
+ #endif
+}
+
+#if defined(USB_CAN_BE_DEVICE)
+static void USB_DeviceTask(void)
+{
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+
+ uint8_t PrevEndpoint = Endpoint_GetCurrentEndpoint();
+
+ Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);
+
+ if (Endpoint_IsSETUPReceived())
+ USB_Device_ProcessControlRequest();
+
+ Endpoint_SelectEndpoint(PrevEndpoint);
+}
+#endif
+
+#if defined(USB_CAN_BE_HOST)
+static void USB_HostTask(void)
+{
+ uint8_t PrevPipe = Pipe_GetCurrentPipe();
+
+ Pipe_SelectPipe(PIPE_CONTROLPIPE);
+
+ USB_Host_ProcessNextHostState();
+
+ Pipe_SelectPipe(PrevPipe);
+}
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/USBTask.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/USBTask.h
new file mode 100644
index 000000000..7205ea1da
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/USBTask.h
@@ -0,0 +1,200 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Main USB service task management.
+ *
+ * This file contains the function definitions required for the main USB service task, which must be called
+ * from the user application to ensure that the USB connection to or from a connected USB device is maintained.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+#ifndef __USBTASK_H__
+#define __USBTASK_H__
+
+ /* Includes: */
+ #include "../../../Common/Common.h"
+ #include "USBMode.h"
+ #include "USBController.h"
+ #include "Events.h"
+ #include "StdRequestType.h"
+ #include "StdDescriptors.h"
+
+ #if defined(USB_CAN_BE_DEVICE)
+ #include "DeviceStandardReq.h"
+ #endif
+
+ #if defined(USB_CAN_BE_HOST)
+ #include "HostStandardReq.h"
+ #endif
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Global Variables: */
+ /** Indicates if the USB interface is currently initialized but not necessarily connected to a host
+ * or device (i.e. if \ref USB_Init() has been run). If this is false, all other library globals related
+ * to the USB driver are invalid.
+ *
+ * \attention This variable should be treated as read-only in the user application, and never manually
+ * changed in value.
+ *
+ * \ingroup Group_USBManagement
+ */
+ extern volatile bool USB_IsInitialized;
+
+ /** Structure containing the last received Control request when in Device mode (for use in user-applications
+ * inside of the \ref EVENT_USB_Device_ControlRequest() event, or for filling up with a control request to
+ * issue when in Host mode before calling \ref USB_Host_SendControlRequest().
+ *
+ * \note The contents of this structure is automatically endian-corrected for the current CPU architecture.
+ *
+ * \ingroup Group_USBManagement
+ */
+ extern USB_Request_Header_t USB_ControlRequest;
+
+ #if defined(USB_CAN_BE_HOST) || defined(__DOXYGEN__)
+ #if !defined(HOST_STATE_AS_GPIOR) || defined(__DOXYGEN__)
+ /** Indicates the current host state machine state. When in host mode, this indicates the state
+ * via one of the values of the \ref USB_Host_States_t enum values.
+ *
+ * This value should not be altered by the user application as it is handled automatically by the
+ * library.
+ *
+ * To reduce program size and speed up checks of this global on the AVR8 architecture, it can be
+ * placed into one of the AVR's \c GPIOR hardware registers instead of RAM by defining the
+ * \c HOST_STATE_AS_GPIOR token to a value between 0 and 2 in the project makefile and passing it to
+ * the compiler via the -D switch. When defined, the corresponding GPIOR register should not be used
+ * in the user application except implicitly via the library APIs.
+ *
+ * \note This global is only present if the user application can be a USB host.
+ *
+ * \see \ref USB_Host_States_t for a list of possible device states.
+ *
+ * \ingroup Group_Host
+ */
+ extern volatile uint8_t USB_HostState;
+ #else
+ #define USB_HostState CONCAT_EXPANDED(GPIOR, HOST_STATE_AS_GPIOR)
+ #endif
+ #endif
+
+ #if defined(USB_CAN_BE_DEVICE) || defined(__DOXYGEN__)
+ #if !defined(DEVICE_STATE_AS_GPIOR) || defined(__DOXYGEN__)
+ /** Indicates the current device state machine state. When in device mode, this indicates the state
+ * via one of the values of the \ref USB_Device_States_t enum values.
+ *
+ * This value should not be altered by the user application as it is handled automatically by the
+ * library. The only exception to this rule is if the NO_LIMITED_CONTROLLER_CONNECT token is used
+ * (see \ref EVENT_USB_Device_Connect() and \ref EVENT_USB_Device_Disconnect() events).
+ *
+ * To reduce program size and speed up checks of this global on the AVR8 architecture, it can be
+ * placed into one of the AVR's \c GPIOR hardware registers instead of RAM by defining the
+ * \c DEVICE_STATE_AS_GPIOR token to a value between 0 and 2 in the project makefile and passing it to
+ * the compiler via the -D switch. When defined, the corresponding GPIOR register should not be used
+ * in the user application except implicitly via the library APIs.
+ *
+ * \attention This variable should be treated as read-only in the user application, and never manually
+ * changed in value except in the circumstances outlined above.
+ *
+ * \note This global is only present if the user application can be a USB device.
+ * \n\n
+ *
+ * \see \ref USB_Device_States_t for a list of possible device states.
+ *
+ * \ingroup Group_Device
+ */
+ extern volatile uint8_t USB_DeviceState;
+ #else
+ #define USB_DeviceState CONCAT_EXPANDED(GPIOR, DEVICE_STATE_AS_GPIOR)
+ #endif
+ #endif
+
+ /* Function Prototypes: */
+ /** This is the main USB management task. The USB driver requires this task to be executed
+ * continuously when the USB system is active (device attached in host mode, or attached to a host
+ * in device mode) in order to manage USB communications. This task may be executed inside an RTOS,
+ * fast timer ISR or the main user application loop.
+ *
+ * The USB task must be serviced within 30ms while in device mode, or within 1ms while in host mode.
+ * The task may be serviced at all times, or (for minimum CPU consumption):
+ *
+ * - In device mode, it may be disabled at start-up, enabled on the firing of the \ref EVENT_USB_Device_Connect()
+ * event and disabled again on the firing of the \ref EVENT_USB_Device_Disconnect() event.
+ *
+ * - In host mode, it may be disabled at start-up, enabled on the firing of the \ref EVENT_USB_Host_DeviceAttached()
+ * event and disabled again on the firing of the \ref EVENT_USB_Host_DeviceEnumerationComplete() or
+ * \ref EVENT_USB_Host_DeviceEnumerationFailed() events.
+ *
+ * If in device mode (only), the control endpoint can instead be managed via interrupts entirely by the library
+ * by defining the INTERRUPT_CONTROL_ENDPOINT token and passing it to the compiler via the -D switch.
+ *
+ * \see \ref Group_Events for more information on the USB events.
+ *
+ * \ingroup Group_USBManagement
+ */
+ void USB_USBTask(void);
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Function Prototypes: */
+ #if defined(__INCLUDE_FROM_USBTASK_C)
+ #if defined(USB_CAN_BE_HOST)
+ static void USB_HostTask(void);
+ #endif
+
+ #if defined(USB_CAN_BE_DEVICE)
+ static void USB_DeviceTask(void);
+ #endif
+ #endif
+
+ /* Macros: */
+ #define HOST_TASK_NONBLOCK_WAIT(Duration, NextState) do { USB_HostState = HOST_STATE_WaitForDevice; \
+ WaitMSRemaining = (Duration); \
+ PostWaitState = (NextState); } while (0)
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.c
new file mode 100644
index 000000000..10c3279f3
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.c
@@ -0,0 +1,49 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "../../../../Common/Common.h"
+#if (ARCH == ARCH_XMEGA)
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../USBMode.h"
+
+#if defined(USB_CAN_BE_DEVICE)
+
+#include "../Device.h"
+
+void USB_Device_SendRemoteWakeup(void)
+{
+ USB.CTRLB |= USB_RWAKEUP_bm;
+}
+
+#endif
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.h
new file mode 100644
index 000000000..b203e1026
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.h
@@ -0,0 +1,266 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief USB Device definitions for the AVR XMEGA microcontrollers.
+ * \copydetails Group_Device_XMEGA
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_Device
+ * \defgroup Group_Device_XMEGA Device Management (XMEGA)
+ * \brief USB Device definitions for the AVR XMEGA microcontrollers.
+ *
+ * Architecture specific USB Device definitions for the Atmel AVR XMEGA microcontrollers.
+ *
+ * @{
+ */
+
+#ifndef __USBDEVICE_XMEGA_H__
+#define __USBDEVICE_XMEGA_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../USBController.h"
+ #include "../StdDescriptors.h"
+ #include "../USBInterrupt.h"
+ #include "../Endpoint.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ #if (defined(USE_RAM_DESCRIPTORS) && defined(USE_EEPROM_DESCRIPTORS))
+ #error USE_RAM_DESCRIPTORS and USE_EEPROM_DESCRIPTORS are mutually exclusive.
+ #endif
+
+ #if (defined(USE_FLASH_DESCRIPTORS) && defined(USE_EEPROM_DESCRIPTORS))
+ #error USE_FLASH_DESCRIPTORS and USE_EEPROM_DESCRIPTORS are mutually exclusive.
+ #endif
+
+ #if (defined(USE_FLASH_DESCRIPTORS) && defined(USE_RAM_DESCRIPTORS))
+ #error USE_FLASH_DESCRIPTORS and USE_RAM_DESCRIPTORS are mutually exclusive.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** \name USB Device Mode Option Masks */
+ //@{
+ /** Mask for the Options parameter of the \ref USB_Init() function. This indicates that the
+ * USB interface should be initialized in low speed (1.5Mb/s) mode.
+ *
+ * \note Low Speed mode is not available on all USB AVR models.
+ * \n
+ *
+ * \note Restrictions apply on the number, size and type of endpoints which can be used
+ * when running in low speed mode - refer to the USB 2.0 specification.
+ */
+ #define USB_DEVICE_OPT_LOWSPEED (1 << 0)
+
+ #if (F_USB > 6000000)
+ /** Mask for the Options parameter of the \ref USB_Init() function. This indicates that the
+ * USB interface should be initialized in full speed (12Mb/s) mode.
+ */
+ #define USB_DEVICE_OPT_FULLSPEED (0 << 0)
+ #endif
+ //@}
+
+ #if (!defined(NO_INTERNAL_SERIAL) || defined(__DOXYGEN__))
+ /** String descriptor index for the device's unique serial number string descriptor within the device.
+ * This unique serial number is used by the host to associate resources to the device (such as drivers or COM port
+ * number allocations) to a device regardless of the port it is plugged in to on the host. Some microcontrollers contain
+ * a unique serial number internally, and setting the device descriptors serial number string index to this value
+ * will cause it to use the internal serial number.
+ *
+ * On unsupported devices, this will evaluate to \ref NO_DESCRIPTOR and so will force the host to create a pseudo-serial
+ * number for the device.
+ */
+ #define USE_INTERNAL_SERIAL 0xDC
+
+ /** Length of the device's unique internal serial number, in bits, if present on the selected microcontroller
+ * model.
+ */
+ #define INTERNAL_SERIAL_LENGTH_BITS (8 * (1 + (offsetof(NVM_PROD_SIGNATURES_t, COORDY1) - offsetof(NVM_PROD_SIGNATURES_t, LOTNUM0))))
+
+ /** Start address of the internal serial number, in the appropriate address space, if present on the selected microcontroller
+ * model.
+ */
+ #define INTERNAL_SERIAL_START_ADDRESS offsetof(NVM_PROD_SIGNATURES_t, LOTNUM0)
+ #else
+ #define USE_INTERNAL_SERIAL NO_DESCRIPTOR
+
+ #define INTERNAL_SERIAL_LENGTH_BITS 0
+ #define INTERNAL_SERIAL_START_ADDRESS 0
+ #endif
+
+ /* Function Prototypes: */
+ /** Sends a Remote Wakeup request to the host. This signals to the host that the device should
+ * be taken out of suspended mode, and communications should resume.
+ *
+ * Typically, this is implemented so that HID devices (mice, keyboards, etc.) can wake up the
+ * host computer when the host has suspended all USB devices to enter a low power state.
+ *
+ * \note This function should only be used if the device has indicated to the host that it
+ * supports the Remote Wakeup feature in the device descriptors, and should only be
+ * issued if the host is currently allowing remote wakeup events from the device (i.e.,
+ * the \ref USB_Device_RemoteWakeupEnabled flag is set). When the \c NO_DEVICE_REMOTE_WAKEUP
+ * compile time option is used, this function is unavailable.
+ * \n\n
+ *
+ * \note The USB clock must be running for this function to operate. If the stack is initialized with
+ * the \ref USB_OPT_MANUAL_PLL option enabled, the user must ensure that the PLL is running
+ * before attempting to call this function.
+ *
+ * \see \ref Group_StdDescriptors for more information on the RMWAKEUP feature and device descriptors.
+ */
+ void USB_Device_SendRemoteWakeup(void);
+
+ /* Inline Functions: */
+ /** Returns the current USB frame number, when in device mode. Every millisecond the USB bus is active (i.e. enumerated to a host)
+ * the frame number is incremented by one.
+ *
+ * \return Current USB frame number from the USB controller.
+ */
+ static inline uint16_t USB_Device_GetFrameNumber(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline uint16_t USB_Device_GetFrameNumber(void)
+ {
+ return ((USB_EndpointTable_t*)USB.EPPTR)->FrameNum;
+ }
+
+ #if !defined(NO_SOF_EVENTS)
+ /** Enables the device mode Start Of Frame events. When enabled, this causes the
+ * \ref EVENT_USB_Device_StartOfFrame() event to fire once per millisecond, synchronized to the USB bus,
+ * at the start of each USB frame when enumerated in device mode.
+ *
+ * \note This function is not available when the \c NO_SOF_EVENTS compile time token is defined.
+ */
+ static inline void USB_Device_EnableSOFEvents(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Device_EnableSOFEvents(void)
+ {
+ USB.INTCTRLA |= USB_SOFIE_bm;
+ }
+
+ /** Disables the device mode Start Of Frame events. When disabled, this stops the firing of the
+ * \ref EVENT_USB_Device_StartOfFrame() event when enumerated in device mode.
+ *
+ * \note This function is not available when the \c NO_SOF_EVENTS compile time token is defined.
+ */
+ static inline void USB_Device_DisableSOFEvents(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Device_DisableSOFEvents(void)
+ {
+ USB.INTCTRLA &= ~USB_SOFIE_bm;
+ }
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Inline Functions: */
+ static inline void USB_Device_SetLowSpeed(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Device_SetLowSpeed(void)
+ {
+ USB.CTRLA &= ~USB_SPEED_bm;
+ }
+
+ static inline void USB_Device_SetFullSpeed(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Device_SetFullSpeed(void)
+ {
+ USB.CTRLA |= USB_SPEED_bm;
+ }
+
+ static inline void USB_Device_SetDeviceAddress(const uint8_t Address) ATTR_ALWAYS_INLINE;
+ static inline void USB_Device_SetDeviceAddress(const uint8_t Address)
+ {
+ (void)Address;
+
+ /* No implementation for XMEGA architecture */
+ }
+
+ static inline void USB_Device_EnableDeviceAddress(const uint8_t Address) ATTR_ALWAYS_INLINE;
+ static inline void USB_Device_EnableDeviceAddress(const uint8_t Address)
+ {
+ USB.ADDR = Address;
+ }
+
+ static inline bool USB_Device_IsAddressSet(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline bool USB_Device_IsAddressSet(void)
+ {
+ return ((USB.ADDR != 0) ? true : false);
+ }
+
+ static inline void USB_Device_GetSerialString(uint16_t* const UnicodeString) ATTR_NON_NULL_PTR_ARG(1);
+ static inline void USB_Device_GetSerialString(uint16_t* const UnicodeString)
+ {
+ uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask();
+ GlobalInterruptDisable();
+
+ uint8_t SigReadAddress = INTERNAL_SERIAL_START_ADDRESS;
+
+ for (uint8_t SerialCharNum = 0; SerialCharNum < (INTERNAL_SERIAL_LENGTH_BITS / 4); SerialCharNum++)
+ {
+ uint8_t SerialByte;
+
+ NVM.CMD = NVM_CMD_READ_CALIB_ROW_gc;
+ SerialByte = pgm_read_byte(SigReadAddress);
+ NVM.CMD = 0;
+
+ if (SerialCharNum & 0x01)
+ {
+ SerialByte >>= 4;
+ SigReadAddress++;
+ }
+
+ SerialByte &= 0x0F;
+
+ UnicodeString[SerialCharNum] = cpu_to_le16((SerialByte >= 10) ?
+ (('A' - 10) + SerialByte) : ('0' + SerialByte));
+ }
+
+ SetGlobalInterruptMask(CurrentGlobalInt);
+ }
+
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/EndpointStream_XMEGA.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/EndpointStream_XMEGA.c
new file mode 100644
index 000000000..421d71709
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/EndpointStream_XMEGA.c
@@ -0,0 +1,275 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "../../../../Common/Common.h"
+#if (ARCH == ARCH_XMEGA)
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../USBMode.h"
+
+#if defined(USB_CAN_BE_DEVICE)
+
+#include "EndpointStream_XMEGA.h"
+
+#if !defined(CONTROL_ONLY_DEVICE)
+uint8_t Endpoint_Discard_Stream(uint16_t Length,
+ uint16_t* const BytesProcessed)
+{
+ uint8_t ErrorCode;
+ uint16_t BytesInTransfer = 0;
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()))
+ return ErrorCode;
+
+ if (BytesProcessed != NULL)
+ Length -= *BytesProcessed;
+
+ while (Length)
+ {
+ if (!(Endpoint_IsReadWriteAllowed()))
+ {
+ Endpoint_ClearOUT();
+
+ if (BytesProcessed != NULL)
+ {
+ *BytesProcessed += BytesInTransfer;
+ return ENDPOINT_RWSTREAM_IncompleteTransfer;
+ }
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()))
+ return ErrorCode;
+ }
+ else
+ {
+ Endpoint_Discard_8();
+
+ Length--;
+ BytesInTransfer++;
+ }
+ }
+
+ return ENDPOINT_RWSTREAM_NoError;
+}
+
+uint8_t Endpoint_Null_Stream(uint16_t Length,
+ uint16_t* const BytesProcessed)
+{
+ uint8_t ErrorCode;
+ uint16_t BytesInTransfer = 0;
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()))
+ return ErrorCode;
+
+ if (BytesProcessed != NULL)
+ Length -= *BytesProcessed;
+
+ while (Length)
+ {
+ if (!(Endpoint_IsReadWriteAllowed()))
+ {
+ Endpoint_ClearIN();
+
+ if (BytesProcessed != NULL)
+ {
+ *BytesProcessed += BytesInTransfer;
+ return ENDPOINT_RWSTREAM_IncompleteTransfer;
+ }
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()))
+ return ErrorCode;
+ }
+ else
+ {
+ Endpoint_Write_8(0);
+
+ Length--;
+ BytesInTransfer++;
+ }
+ }
+
+ return ENDPOINT_RWSTREAM_NoError;
+}
+
+/* The following abuses the C preprocessor in order to copy-paste common code with slight alterations,
+ * so that the code needs to be written once. It is a crude form of templating to reduce code maintenance. */
+
+#define TEMPLATE_FUNC_NAME Endpoint_Write_Stream_LE
+#define TEMPLATE_BUFFER_TYPE const void*
+#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearIN()
+#define TEMPLATE_BUFFER_OFFSET(Length) 0
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(*BufferPtr)
+#include "Template/Template_Endpoint_RW.c"
+
+#define TEMPLATE_FUNC_NAME Endpoint_Write_Stream_BE
+#define TEMPLATE_BUFFER_TYPE const void*
+#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearIN()
+#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(*BufferPtr)
+#include "Template/Template_Endpoint_RW.c"
+
+#define TEMPLATE_FUNC_NAME Endpoint_Read_Stream_LE
+#define TEMPLATE_BUFFER_TYPE void*
+#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearOUT()
+#define TEMPLATE_BUFFER_OFFSET(Length) 0
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) *BufferPtr = Endpoint_Read_8()
+#include "Template/Template_Endpoint_RW.c"
+
+#define TEMPLATE_FUNC_NAME Endpoint_Read_Stream_BE
+#define TEMPLATE_BUFFER_TYPE void*
+#define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearOUT()
+#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) *BufferPtr = Endpoint_Read_8()
+#include "Template/Template_Endpoint_RW.c"
+
+#if defined(ARCH_HAS_FLASH_ADDRESS_SPACE)
+ #define TEMPLATE_FUNC_NAME Endpoint_Write_PStream_LE
+ #define TEMPLATE_BUFFER_TYPE const void*
+ #define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearIN()
+ #define TEMPLATE_BUFFER_OFFSET(Length) 0
+ #define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
+ #define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(pgm_read_byte(BufferPtr))
+ #include "Template/Template_Endpoint_RW.c"
+
+ #define TEMPLATE_FUNC_NAME Endpoint_Write_PStream_BE
+ #define TEMPLATE_BUFFER_TYPE const void*
+ #define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearIN()
+ #define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+ #define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
+ #define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(pgm_read_byte(BufferPtr))
+ #include "Template/Template_Endpoint_RW.c"
+#endif
+
+#if defined(ARCH_HAS_EEPROM_ADDRESS_SPACE)
+ #define TEMPLATE_FUNC_NAME Endpoint_Write_EStream_LE
+ #define TEMPLATE_BUFFER_TYPE const void*
+ #define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearIN()
+ #define TEMPLATE_BUFFER_OFFSET(Length) 0
+ #define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
+ #define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(eeprom_read_byte(BufferPtr))
+ #include "Template/Template_Endpoint_RW.c"
+
+ #define TEMPLATE_FUNC_NAME Endpoint_Write_EStream_BE
+ #define TEMPLATE_BUFFER_TYPE const void*
+ #define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearIN()
+ #define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+ #define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
+ #define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(eeprom_read_byte(BufferPtr))
+ #include "Template/Template_Endpoint_RW.c"
+
+ #define TEMPLATE_FUNC_NAME Endpoint_Read_EStream_LE
+ #define TEMPLATE_BUFFER_TYPE void*
+ #define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearOUT()
+ #define TEMPLATE_BUFFER_OFFSET(Length) 0
+ #define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
+ #define TEMPLATE_TRANSFER_BYTE(BufferPtr) eeprom_update_byte(BufferPtr, Endpoint_Read_8())
+ #include "Template/Template_Endpoint_RW.c"
+
+ #define TEMPLATE_FUNC_NAME Endpoint_Read_EStream_BE
+ #define TEMPLATE_BUFFER_TYPE void*
+ #define TEMPLATE_CLEAR_ENDPOINT() Endpoint_ClearOUT()
+ #define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+ #define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
+ #define TEMPLATE_TRANSFER_BYTE(BufferPtr) eeprom_update_byte(BufferPtr, Endpoint_Read_8())
+ #include "Template/Template_Endpoint_RW.c"
+#endif
+
+#endif
+
+#define TEMPLATE_FUNC_NAME Endpoint_Write_Control_Stream_LE
+#define TEMPLATE_BUFFER_OFFSET(Length) 0
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(*BufferPtr)
+#include "Template/Template_Endpoint_Control_W.c"
+
+#define TEMPLATE_FUNC_NAME Endpoint_Write_Control_Stream_BE
+#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(*BufferPtr)
+#include "Template/Template_Endpoint_Control_W.c"
+
+#define TEMPLATE_FUNC_NAME Endpoint_Read_Control_Stream_LE
+#define TEMPLATE_BUFFER_OFFSET(Length) 0
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) *BufferPtr = Endpoint_Read_8()
+#include "Template/Template_Endpoint_Control_R.c"
+
+#define TEMPLATE_FUNC_NAME Endpoint_Read_Control_Stream_BE
+#define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+#define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
+#define TEMPLATE_TRANSFER_BYTE(BufferPtr) *BufferPtr = Endpoint_Read_8()
+#include "Template/Template_Endpoint_Control_R.c"
+
+#if defined(ARCH_HAS_FLASH_ADDRESS_SPACE)
+ #define TEMPLATE_FUNC_NAME Endpoint_Write_Control_PStream_LE
+ #define TEMPLATE_BUFFER_OFFSET(Length) 0
+ #define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
+ #define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(pgm_read_byte(BufferPtr))
+ #include "Template/Template_Endpoint_Control_W.c"
+
+ #define TEMPLATE_FUNC_NAME Endpoint_Write_Control_PStream_BE
+ #define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+ #define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
+ #define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(pgm_read_byte(BufferPtr))
+ #include "Template/Template_Endpoint_Control_W.c"
+#endif
+
+#if defined(ARCH_HAS_EEPROM_ADDRESS_SPACE)
+ #define TEMPLATE_FUNC_NAME Endpoint_Write_Control_EStream_LE
+ #define TEMPLATE_BUFFER_OFFSET(Length) 0
+ #define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
+ #define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(eeprom_read_byte(BufferPtr))
+ #include "Template/Template_Endpoint_Control_W.c"
+
+ #define TEMPLATE_FUNC_NAME Endpoint_Write_Control_EStream_BE
+ #define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+ #define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
+ #define TEMPLATE_TRANSFER_BYTE(BufferPtr) Endpoint_Write_8(eeprom_read_byte(BufferPtr))
+ #include "Template/Template_Endpoint_Control_W.c"
+
+ #define TEMPLATE_FUNC_NAME Endpoint_Read_Control_EStream_LE
+ #define TEMPLATE_BUFFER_OFFSET(Length) 0
+ #define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr += Amount
+ #define TEMPLATE_TRANSFER_BYTE(BufferPtr) eeprom_update_byte(BufferPtr, Endpoint_Read_8())
+ #include "Template/Template_Endpoint_Control_R.c"
+
+ #define TEMPLATE_FUNC_NAME Endpoint_Read_Control_EStream_BE
+ #define TEMPLATE_BUFFER_OFFSET(Length) (Length - 1)
+ #define TEMPLATE_BUFFER_MOVE(BufferPtr, Amount) BufferPtr -= Amount
+ #define TEMPLATE_TRANSFER_BYTE(BufferPtr) eeprom_update_byte(BufferPtr, Endpoint_Read_8())
+ #include "Template/Template_Endpoint_Control_R.c"
+#endif
+
+#endif
+
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/EndpointStream_XMEGA.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/EndpointStream_XMEGA.h
new file mode 100644
index 000000000..cba6537db
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/EndpointStream_XMEGA.h
@@ -0,0 +1,658 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Endpoint data stream transmission and reception management for the AVR XMEGA microcontrollers.
+ * \copydetails Group_EndpointStreamRW_XMEGA
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_EndpointStreamRW
+ * \defgroup Group_EndpointStreamRW_XMEGA Read/Write of Multi-Byte Streams (XMEGA)
+ * \brief Endpoint data stream transmission and reception management for the Atmel AVR XMEGA architecture.
+ *
+ * Functions, macros, variables, enums and types related to data reading and writing of data streams from
+ * and to endpoints.
+ *
+ * @{
+ */
+
+#ifndef __ENDPOINT_STREAM_XMEGA_H__
+#define __ENDPOINT_STREAM_XMEGA_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../USBMode.h"
+ #include "../USBTask.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Function Prototypes: */
+ /** \name Stream functions for null data */
+ //@{
+
+ /** Reads and discards the given number of bytes from the currently selected endpoint's bank,
+ * discarding fully read packets from the host as needed. The last packet is not automatically
+ * discarded once the remaining bytes has been read; the user is responsible for manually
+ * discarding the last packet from the host via the \ref Endpoint_ClearOUT() macro.
+ *
+ * If the BytesProcessed parameter is \c NULL, the entire stream transfer is attempted at once,
+ * failing or succeeding as a single unit. If the BytesProcessed parameter points to a valid
+ * storage location, the transfer will instead be performed as a series of chunks. Each time
+ * the endpoint bank becomes empty while there is still data to process (and after the current
+ * packet has been acknowledged) the BytesProcessed location will be updated with the total number
+ * of bytes processed in the stream, and the function will exit with an error code of
+ * \ref ENDPOINT_RWSTREAM_IncompleteTransfer. This allows for any abort checking to be performed
+ * in the user code - to continue the transfer, call the function again with identical parameters
+ * and it will resume until the BytesProcessed value reaches the total transfer length.
+ *
+ * <b>Single Stream Transfer Example:</b>
+ * \code
+ * uint8_t ErrorCode;
+ *
+ * if ((ErrorCode = Endpoint_Discard_Stream(512, NULL)) != ENDPOINT_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * <b>Partial Stream Transfers Example:</b>
+ * \code
+ * uint8_t ErrorCode;
+ * uint16_t BytesProcessed;
+ *
+ * BytesProcessed = 0;
+ * while ((ErrorCode = Endpoint_Discard_Stream(512, &BytesProcessed)) == ENDPOINT_RWSTREAM_IncompleteTransfer)
+ * {
+ * // Stream not yet complete - do other actions here, abort if required
+ * }
+ *
+ * if (ErrorCode != ENDPOINT_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * \note This routine should not be used on CONTROL type endpoints.
+ *
+ * \param[in] Length Number of bytes to discard via the currently selected endpoint.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
+ * transaction should be updated, \c NULL if the entire stream should be read at once.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Discard_Stream(uint16_t Length,
+ uint16_t* const BytesProcessed);
+
+ /** Writes a given number of zeroed bytes to the currently selected endpoint's bank, sending
+ * full packets to the host as needed. The last packet is not automatically sent once the
+ * remaining bytes have been written; the user is responsible for manually sending the last
+ * packet to the host via the \ref Endpoint_ClearIN() macro.
+ *
+ * If the BytesProcessed parameter is \c NULL, the entire stream transfer is attempted at once,
+ * failing or succeeding as a single unit. If the BytesProcessed parameter points to a valid
+ * storage location, the transfer will instead be performed as a series of chunks. Each time
+ * the endpoint bank becomes full while there is still data to process (and after the current
+ * packet transmission has been initiated) the BytesProcessed location will be updated with the
+ * total number of bytes processed in the stream, and the function will exit with an error code of
+ * \ref ENDPOINT_RWSTREAM_IncompleteTransfer. This allows for any abort checking to be performed
+ * in the user code - to continue the transfer, call the function again with identical parameters
+ * and it will resume until the BytesProcessed value reaches the total transfer length.
+ *
+ * <b>Single Stream Transfer Example:</b>
+ * \code
+ * uint8_t ErrorCode;
+ *
+ * if ((ErrorCode = Endpoint_Null_Stream(512, NULL)) != ENDPOINT_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * <b>Partial Stream Transfers Example:</b>
+ * \code
+ * uint8_t ErrorCode;
+ * uint16_t BytesProcessed;
+ *
+ * BytesProcessed = 0;
+ * while ((ErrorCode = Endpoint_Null_Stream(512, &BytesProcessed)) == ENDPOINT_RWSTREAM_IncompleteTransfer)
+ * {
+ * // Stream not yet complete - do other actions here, abort if required
+ * }
+ *
+ * if (ErrorCode != ENDPOINT_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * \note This routine should not be used on CONTROL type endpoints.
+ *
+ * \param[in] Length Number of zero bytes to send via the currently selected endpoint.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
+ * transaction should be updated, \c NULL if the entire stream should be read at once.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Null_Stream(uint16_t Length,
+ uint16_t* const BytesProcessed);
+
+ //@}
+
+ /** \name Stream functions for RAM source/destination data */
+ //@{
+
+ /** Writes the given number of bytes to the endpoint from the given buffer in little endian,
+ * sending full packets to the host as needed. The last packet filled is not automatically sent;
+ * the user is responsible for manually sending the last written packet to the host via the
+ * \ref Endpoint_ClearIN() macro.
+ *
+ * If the BytesProcessed parameter is \c NULL, the entire stream transfer is attempted at once,
+ * failing or succeeding as a single unit. If the BytesProcessed parameter points to a valid
+ * storage location, the transfer will instead be performed as a series of chunks. Each time
+ * the endpoint bank becomes full while there is still data to process (and after the current
+ * packet transmission has been initiated) the BytesProcessed location will be updated with the
+ * total number of bytes processed in the stream, and the function will exit with an error code of
+ * \ref ENDPOINT_RWSTREAM_IncompleteTransfer. This allows for any abort checking to be performed
+ * in the user code - to continue the transfer, call the function again with identical parameters
+ * and it will resume until the BytesProcessed value reaches the total transfer length.
+ *
+ * <b>Single Stream Transfer Example:</b>
+ * \code
+ * uint8_t DataStream[512];
+ * uint8_t ErrorCode;
+ *
+ * if ((ErrorCode = Endpoint_Write_Stream_LE(DataStream, sizeof(DataStream),
+ * NULL)) != ENDPOINT_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * <b>Partial Stream Transfers Example:</b>
+ * \code
+ * uint8_t DataStream[512];
+ * uint8_t ErrorCode;
+ * uint16_t BytesProcessed;
+ *
+ * BytesProcessed = 0;
+ * while ((ErrorCode = Endpoint_Write_Stream_LE(DataStream, sizeof(DataStream),
+ * &BytesProcessed)) == ENDPOINT_RWSTREAM_IncompleteTransfer)
+ * {
+ * // Stream not yet complete - do other actions here, abort if required
+ * }
+ *
+ * if (ErrorCode != ENDPOINT_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * \note This routine should not be used on CONTROL type endpoints.
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
+ * transaction should be updated, \c NULL if the entire stream should be written at once.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_Stream_LE(const void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Writes the given number of bytes to the endpoint from the given buffer in big endian,
+ * sending full packets to the host as needed. The last packet filled is not automatically sent;
+ * the user is responsible for manually sending the last written packet to the host via the
+ * \ref Endpoint_ClearIN() macro.
+ *
+ * \note This routine should not be used on CONTROL type endpoints.
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
+ * transaction should be updated, \c NULL if the entire stream should be written at once.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_Stream_BE(const void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Reads the given number of bytes from the endpoint from the given buffer in little endian,
+ * discarding fully read packets from the host as needed. The last packet is not automatically
+ * discarded once the remaining bytes has been read; the user is responsible for manually
+ * discarding the last packet from the host via the \ref Endpoint_ClearOUT() macro.
+ *
+ * If the BytesProcessed parameter is \c NULL, the entire stream transfer is attempted at once,
+ * failing or succeeding as a single unit. If the BytesProcessed parameter points to a valid
+ * storage location, the transfer will instead be performed as a series of chunks. Each time
+ * the endpoint bank becomes empty while there is still data to process (and after the current
+ * packet has been acknowledged) the BytesProcessed location will be updated with the total number
+ * of bytes processed in the stream, and the function will exit with an error code of
+ * \ref ENDPOINT_RWSTREAM_IncompleteTransfer. This allows for any abort checking to be performed
+ * in the user code - to continue the transfer, call the function again with identical parameters
+ * and it will resume until the BytesProcessed value reaches the total transfer length.
+ *
+ * <b>Single Stream Transfer Example:</b>
+ * \code
+ * uint8_t DataStream[512];
+ * uint8_t ErrorCode;
+ *
+ * if ((ErrorCode = Endpoint_Read_Stream_LE(DataStream, sizeof(DataStream),
+ * NULL)) != ENDPOINT_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * <b>Partial Stream Transfers Example:</b>
+ * \code
+ * uint8_t DataStream[512];
+ * uint8_t ErrorCode;
+ * uint16_t BytesProcessed;
+ *
+ * BytesProcessed = 0;
+ * while ((ErrorCode = Endpoint_Read_Stream_LE(DataStream, sizeof(DataStream),
+ * &BytesProcessed)) == ENDPOINT_RWSTREAM_IncompleteTransfer)
+ * {
+ * // Stream not yet complete - do other actions here, abort if required
+ * }
+ *
+ * if (ErrorCode != ENDPOINT_RWSTREAM_NoError)
+ * {
+ * // Stream failed to complete - check ErrorCode here
+ * }
+ * \endcode
+ *
+ * \note This routine should not be used on CONTROL type endpoints.
+ *
+ * \param[out] Buffer Pointer to the destination data buffer to write to.
+ * \param[in] Length Number of bytes to send via the currently selected endpoint.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
+ * transaction should be updated, \c NULL if the entire stream should be read at once.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Read_Stream_LE(void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Reads the given number of bytes from the endpoint from the given buffer in big endian,
+ * discarding fully read packets from the host as needed. The last packet is not automatically
+ * discarded once the remaining bytes has been read; the user is responsible for manually
+ * discarding the last packet from the host via the \ref Endpoint_ClearOUT() macro.
+ *
+ * \note This routine should not be used on CONTROL type endpoints.
+ *
+ * \param[out] Buffer Pointer to the destination data buffer to write to.
+ * \param[in] Length Number of bytes to send via the currently selected endpoint.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
+ * transaction should be updated, \c NULL if the entire stream should be read at once.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Read_Stream_BE(void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Writes the given number of bytes to the CONTROL type endpoint from the given buffer in little endian,
+ * sending full packets to the host as needed. The host OUT acknowledgement is not automatically cleared
+ * in both failure and success states; the user is responsible for manually clearing the status OUT packet
+ * to finalize the transfer's status stage via the \ref Endpoint_ClearOUT() macro.
+ *
+ * \note This function automatically sends the last packet in the data stage of the transaction; when the
+ * function returns, the user is responsible for clearing the <b>status</b> stage of the transaction.
+ * Note that the status stage packet is sent or received in the opposite direction of the data flow.
+ * \n\n
+ *
+ * \note This routine should only be used on CONTROL type endpoints.
+ *
+ * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
+ * together; i.e. the entire stream data must be read or written at the one time.
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
+ *
+ * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_Control_Stream_LE(const void* const Buffer,
+ uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Writes the given number of bytes to the CONTROL type endpoint from the given buffer in big endian,
+ * sending full packets to the host as needed. The host OUT acknowledgement is not automatically cleared
+ * in both failure and success states; the user is responsible for manually clearing the status OUT packet
+ * to finalize the transfer's status stage via the \ref Endpoint_ClearOUT() macro.
+ *
+ * \note This function automatically sends the last packet in the data stage of the transaction; when the
+ * function returns, the user is responsible for clearing the <b>status</b> stage of the transaction.
+ * Note that the status stage packet is sent or received in the opposite direction of the data flow.
+ * \n\n
+ *
+ * \note This routine should only be used on CONTROL type endpoints.
+ *
+ * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
+ * together; i.e. the entire stream data must be read or written at the one time.
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
+ *
+ * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_Control_Stream_BE(const void* const Buffer,
+ uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Reads the given number of bytes from the CONTROL endpoint from the given buffer in little endian,
+ * discarding fully read packets from the host as needed. The device IN acknowledgement is not
+ * automatically sent after success or failure states; the user is responsible for manually sending the
+ * status IN packet to finalize the transfer's status stage via the \ref Endpoint_ClearIN() macro.
+ *
+ * \note This function automatically sends the last packet in the data stage of the transaction; when the
+ * function returns, the user is responsible for clearing the <b>status</b> stage of the transaction.
+ * Note that the status stage packet is sent or received in the opposite direction of the data flow.
+ * \n\n
+ *
+ * \note This routine should only be used on CONTROL type endpoints.
+ *
+ * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
+ * together; i.e. the entire stream data must be read or written at the one time.
+ *
+ * \param[out] Buffer Pointer to the destination data buffer to write to.
+ * \param[in] Length Number of bytes to send via the currently selected endpoint.
+ *
+ * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Read_Control_Stream_LE(void* const Buffer,
+ uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** Reads the given number of bytes from the CONTROL endpoint from the given buffer in big endian,
+ * discarding fully read packets from the host as needed. The device IN acknowledgement is not
+ * automatically sent after success or failure states; the user is responsible for manually sending the
+ * status IN packet to finalize the transfer's status stage via the \ref Endpoint_ClearIN() macro.
+ *
+ * \note This function automatically sends the last packet in the data stage of the transaction; when the
+ * function returns, the user is responsible for clearing the <b>status</b> stage of the transaction.
+ * Note that the status stage packet is sent or received in the opposite direction of the data flow.
+ * \n\n
+ *
+ * \note This routine should only be used on CONTROL type endpoints.
+ *
+ * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
+ * together; i.e. the entire stream data must be read or written at the one time.
+ *
+ * \param[out] Buffer Pointer to the destination data buffer to write to.
+ * \param[in] Length Number of bytes to send via the currently selected endpoint.
+ *
+ * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Read_Control_Stream_BE(void* const Buffer,
+ uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+ //@}
+
+ /** \name Stream functions for EEPROM source/destination data */
+ //@{
+
+ /** EEPROM buffer source version of \ref Endpoint_Write_Stream_LE().
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
+ * transaction should be updated, \c NULL if the entire stream should be written at once.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_EStream_LE(const void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** EEPROM buffer source version of \ref Endpoint_Write_Stream_BE().
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
+ * transaction should be updated, \c NULL if the entire stream should be written at once.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_EStream_BE(const void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** EEPROM buffer destination version of \ref Endpoint_Read_Stream_LE().
+ *
+ * \param[out] Buffer Pointer to the destination data buffer to write to, located in EEPROM memory space.
+ * \param[in] Length Number of bytes to send via the currently selected endpoint.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
+ * transaction should be updated, \c NULL if the entire stream should be read at once.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Read_EStream_LE(void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** EEPROM buffer destination version of \ref Endpoint_Read_Stream_BE().
+ *
+ * \param[out] Buffer Pointer to the destination data buffer to write to, located in EEPROM memory space.
+ * \param[in] Length Number of bytes to send via the currently selected endpoint.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
+ * transaction should be updated, \c NULL if the entire stream should be read at once.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Read_EStream_BE(void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** EEPROM buffer source version of Endpoint_Write_Control_Stream_LE.
+ *
+ * \note This function automatically sends the last packet in the data stage of the transaction; when the
+ * function returns, the user is responsible for clearing the <b>status</b> stage of the transaction.
+ * Note that the status stage packet is sent or received in the opposite direction of the data flow.
+ * \n\n
+ *
+ * \note This routine should only be used on CONTROL type endpoints.
+ * \n\n
+ *
+ * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
+ * together; i.e. the entire stream data must be read or written at the one time.
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
+ *
+ * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_Control_EStream_LE(const void* const Buffer,
+ uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** EEPROM buffer source version of \ref Endpoint_Write_Control_Stream_BE().
+ *
+ * \note This function automatically sends the last packet in the data stage of the transaction; when the
+ * function returns, the user is responsible for clearing the <b>status</b> stage of the transaction.
+ * Note that the status stage packet is sent or received in the opposite direction of the data flow.
+ * \n\n
+ *
+ * \note This routine should only be used on CONTROL type endpoints.
+ * \n\n
+ *
+ * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
+ * together; i.e. the entire stream data must be read or written at the one time.
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
+ *
+ * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_Control_EStream_BE(const void* const Buffer,
+ uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** EEPROM buffer source version of \ref Endpoint_Read_Control_Stream_LE().
+ *
+ * \note This function automatically sends the last packet in the data stage of the transaction; when the
+ * function returns, the user is responsible for clearing the <b>status</b> stage of the transaction.
+ * Note that the status stage packet is sent or received in the opposite direction of the data flow.
+ * \n\n
+ *
+ * \note This routine should only be used on CONTROL type endpoints.
+ * \n\n
+ *
+ * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
+ * together; i.e. the entire stream data must be read or written at the one time.
+ *
+ * \param[out] Buffer Pointer to the destination data buffer to write to.
+ * \param[in] Length Number of bytes to send via the currently selected endpoint.
+ *
+ * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Read_Control_EStream_LE(void* const Buffer,
+ uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** EEPROM buffer source version of \ref Endpoint_Read_Control_Stream_BE().
+ *
+ * \note This function automatically sends the last packet in the data stage of the transaction; when the
+ * function returns, the user is responsible for clearing the <b>status</b> stage of the transaction.
+ * Note that the status stage packet is sent or received in the opposite direction of the data flow.
+ * \n\n
+ *
+ * \note This routine should only be used on CONTROL type endpoints.
+ * \n\n
+ *
+ * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
+ * together; i.e. the entire stream data must be read or written at the one time.
+ *
+ * \param[out] Buffer Pointer to the destination data buffer to write to.
+ * \param[in] Length Number of bytes to send via the currently selected endpoint.
+ *
+ * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Read_Control_EStream_BE(void* const Buffer,
+ uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+ //@}
+
+ /** \name Stream functions for PROGMEM source/destination data */
+ //@{
+
+ /** FLASH buffer source version of \ref Endpoint_Write_Stream_LE().
+ *
+ * \pre The FLASH data must be located in the first 64KB of FLASH for this function to work correctly.
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
+ * transaction should be updated, \c NULL if the entire stream should be written at once.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_PStream_LE(const void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** FLASH buffer source version of \ref Endpoint_Write_Stream_BE().
+ *
+ * \pre The FLASH data must be located in the first 64KB of FLASH for this function to work correctly.
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
+ * \param[in] BytesProcessed Pointer to a location where the total number of bytes processed in the current
+ * transaction should be updated, \c NULL if the entire stream should be written at once.
+ *
+ * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_PStream_BE(const void* const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** FLASH buffer source version of \ref Endpoint_Write_Control_Stream_LE().
+ *
+ * \pre The FLASH data must be located in the first 64KB of FLASH for this function to work correctly.
+ *
+ * \note This function automatically sends the last packet in the data stage of the transaction; when the
+ * function returns, the user is responsible for clearing the <b>status</b> stage of the transaction.
+ * Note that the status stage packet is sent or received in the opposite direction of the data flow.
+ * \n\n
+ *
+ * \note This routine should only be used on CONTROL type endpoints.
+ * \n\n
+ *
+ * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
+ * together; i.e. the entire stream data must be read or written at the one time.
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
+ *
+ * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_Control_PStream_LE(const void* const Buffer,
+ uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+
+ /** FLASH buffer source version of \ref Endpoint_Write_Control_Stream_BE().
+ *
+ * \pre The FLASH data must be located in the first 64KB of FLASH for this function to work correctly.
+ *
+ * \note This function automatically sends the last packet in the data stage of the transaction; when the
+ * function returns, the user is responsible for clearing the <b>status</b> stage of the transaction.
+ * Note that the status stage packet is sent or received in the opposite direction of the data flow.
+ * \n\n
+ *
+ * \note This routine should only be used on CONTROL type endpoints.
+ * \n\n
+ *
+ * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained
+ * together; i.e. the entire stream data must be read or written at the one time.
+ *
+ * \param[in] Buffer Pointer to the source data buffer to read from.
+ * \param[in] Length Number of bytes to read for the currently selected endpoint into the buffer.
+ *
+ * \return A value from the \ref Endpoint_ControlStream_RW_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_Write_Control_PStream_BE(const void* const Buffer,
+ uint16_t Length) ATTR_NON_NULL_PTR_ARG(1);
+ //@}
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.c
new file mode 100644
index 000000000..8155ecf7d
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.c
@@ -0,0 +1,268 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "../../../../Common/Common.h"
+#if (ARCH == ARCH_XMEGA)
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../USBMode.h"
+
+#if defined(USB_CAN_BE_DEVICE)
+
+#include "../Endpoint.h"
+
+#if !defined(FIXED_CONTROL_ENDPOINT_SIZE)
+uint8_t USB_Device_ControlEndpointSize = ENDPOINT_CONTROLEP_DEFAULT_SIZE;
+#endif
+
+Endpoint_FIFOPair_t USB_Endpoint_FIFOs[ENDPOINT_TOTAL_ENDPOINTS];
+
+volatile uint8_t USB_Endpoint_SelectedEndpoint;
+volatile USB_EP_t* USB_Endpoint_SelectedHandle;
+volatile Endpoint_FIFO_t* USB_Endpoint_SelectedFIFO;
+
+bool Endpoint_IsINReady(void)
+{
+ Endpoint_SelectEndpoint(USB_Endpoint_SelectedEndpoint | ENDPOINT_DIR_IN);
+
+ return ((USB_Endpoint_SelectedHandle->STATUS & USB_EP_BUSNACK0_bm) ? true : false);
+}
+
+bool Endpoint_IsOUTReceived(void)
+{
+ Endpoint_SelectEndpoint(USB_Endpoint_SelectedEndpoint & ~ENDPOINT_DIR_IN);
+
+ if (USB_Endpoint_SelectedHandle->STATUS & USB_EP_TRNCOMPL0_bm)
+ {
+ USB_Endpoint_SelectedFIFO->Length = USB_Endpoint_SelectedHandle->CNT;
+ return true;
+ }
+
+ return false;
+}
+
+bool Endpoint_IsSETUPReceived(void)
+{
+ Endpoint_SelectEndpoint(USB_Endpoint_SelectedEndpoint & ~ENDPOINT_DIR_IN);
+
+ if (USB_Endpoint_SelectedHandle->STATUS & USB_EP_SETUP_bm)
+ {
+ USB_Endpoint_SelectedFIFO->Length = USB_Endpoint_SelectedHandle->CNT;
+ return true;
+ }
+
+ return false;
+}
+
+void Endpoint_ClearSETUP(void)
+{
+ Endpoint_SelectEndpoint(USB_Endpoint_SelectedEndpoint & ~ENDPOINT_DIR_IN);
+ USB_Endpoint_SelectedHandle->STATUS &= ~(USB_EP_SETUP_bm | USB_EP_TRNCOMPL0_bm | USB_EP_BUSNACK0_bm | USB_EP_OVF_bm);
+ USB_Endpoint_SelectedHandle->STATUS |= USB_EP_TOGGLE_bm;
+ USB_Endpoint_SelectedFIFO->Position = 0;
+
+ Endpoint_SelectEndpoint(USB_Endpoint_SelectedEndpoint | ENDPOINT_DIR_IN);
+ USB_Endpoint_SelectedHandle->STATUS |= USB_EP_TOGGLE_bm;
+ USB_Endpoint_SelectedFIFO->Position = 0;
+}
+
+void Endpoint_ClearIN(void)
+{
+ USB_Endpoint_SelectedHandle->CNT = USB_Endpoint_SelectedFIFO->Position;
+ USB_Endpoint_SelectedHandle->STATUS &= ~(USB_EP_TRNCOMPL0_bm | USB_EP_BUSNACK0_bm | USB_EP_OVF_bm);
+ USB_Endpoint_SelectedFIFO->Position = 0;
+}
+
+void Endpoint_ClearOUT(void)
+{
+ USB_Endpoint_SelectedHandle->STATUS &= ~(USB_EP_TRNCOMPL0_bm | USB_EP_BUSNACK0_bm | USB_EP_OVF_bm);
+ USB_Endpoint_SelectedFIFO->Position = 0;
+}
+
+void Endpoint_StallTransaction(void)
+{
+ USB_Endpoint_SelectedHandle->CTRL |= USB_EP_STALL_bm;
+
+ if ((USB_Endpoint_SelectedHandle->CTRL & USB_EP_TYPE_gm) == USB_EP_TYPE_CONTROL_gc)
+ {
+ Endpoint_SelectEndpoint(USB_Endpoint_SelectedEndpoint ^ ENDPOINT_DIR_IN);
+ USB_Endpoint_SelectedHandle->CTRL |= USB_EP_STALL_bm;
+ }
+}
+
+uint8_t Endpoint_Read_8(void)
+{
+ return USB_Endpoint_SelectedFIFO->Data[USB_Endpoint_SelectedFIFO->Position++];
+}
+
+void Endpoint_Write_8(const uint8_t Data)
+{
+ USB_Endpoint_SelectedFIFO->Data[USB_Endpoint_SelectedFIFO->Position++] = Data;
+}
+
+void Endpoint_SelectEndpoint(const uint8_t Address)
+{
+ uint8_t EndpointNumber = (Address & ENDPOINT_EPNUM_MASK);
+
+ USB_Endpoint_SelectedEndpoint = Address;
+
+ Endpoint_FIFOPair_t* EndpointFIFOPair = &USB_Endpoint_FIFOs[EndpointNumber];
+ USB_EndpointTable_t* EndpointTable = (USB_EndpointTable_t*)USB.EPPTR;
+
+ if (Address & ENDPOINT_DIR_IN)
+ {
+ USB_Endpoint_SelectedFIFO = &EndpointFIFOPair->IN;
+ USB_Endpoint_SelectedHandle = &EndpointTable->Endpoints[EndpointNumber].IN;
+ }
+ else
+ {
+ USB_Endpoint_SelectedFIFO = &EndpointFIFOPair->OUT;
+ USB_Endpoint_SelectedHandle = &EndpointTable->Endpoints[EndpointNumber].OUT;
+ }
+}
+
+bool Endpoint_ConfigureEndpointTable(const USB_Endpoint_Table_t* const Table,
+ const uint8_t Entries)
+{
+ for (uint8_t i = 0; i < Entries; i++)
+ {
+ if (!(Table[i].Address))
+ continue;
+
+ if (!(Endpoint_ConfigureEndpoint(Table[i].Address, Table[i].Type, Table[i].Size, Table[i].Banks)))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool Endpoint_ConfigureEndpoint_PRV(const uint8_t Address,
+ const uint8_t Config,
+ const uint8_t Size)
+{
+ Endpoint_SelectEndpoint(Address);
+
+ USB_Endpoint_SelectedHandle->CTRL = 0;
+ USB_Endpoint_SelectedHandle->STATUS = (Address & ENDPOINT_DIR_IN) ? USB_EP_BUSNACK0_bm : 0;
+ USB_Endpoint_SelectedHandle->CTRL = Config;
+ USB_Endpoint_SelectedHandle->CNT = 0;
+ USB_Endpoint_SelectedHandle->DATAPTR = (intptr_t)USB_Endpoint_SelectedFIFO->Data;
+
+ USB_Endpoint_SelectedFIFO->Length = (Address & ENDPOINT_DIR_IN) ? Size : 0;
+ USB_Endpoint_SelectedFIFO->Position = 0;
+
+ return true;
+}
+
+void Endpoint_ClearEndpoints(void)
+{
+ for (uint8_t EPNum = 0; EPNum < ENDPOINT_TOTAL_ENDPOINTS; EPNum++)
+ {
+ ((USB_EndpointTable_t*)USB.EPPTR)->Endpoints[EPNum].IN.CTRL = 0;
+ ((USB_EndpointTable_t*)USB.EPPTR)->Endpoints[EPNum].OUT.CTRL = 0;
+ }
+}
+
+void Endpoint_ClearStatusStage(void)
+{
+ if (USB_ControlRequest.bmRequestType & REQDIR_DEVICETOHOST)
+ {
+ while (!(Endpoint_IsOUTReceived()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+
+ Endpoint_ClearOUT();
+ }
+ else
+ {
+ while (!(Endpoint_IsINReady()))
+ {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+
+ Endpoint_ClearIN();
+ }
+}
+
+#if !defined(CONTROL_ONLY_DEVICE)
+uint8_t Endpoint_WaitUntilReady(void)
+{
+ #if (USB_STREAM_TIMEOUT_MS < 0xFF)
+ uint8_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
+ #else
+ uint16_t TimeoutMSRem = USB_STREAM_TIMEOUT_MS;
+ #endif
+
+ uint16_t PreviousFrameNumber = USB_Device_GetFrameNumber();
+
+ for (;;)
+ {
+ if (Endpoint_GetEndpointDirection() == ENDPOINT_DIR_IN)
+ {
+ if (Endpoint_IsINReady())
+ return ENDPOINT_READYWAIT_NoError;
+ }
+ else
+ {
+ if (Endpoint_IsOUTReceived())
+ return ENDPOINT_READYWAIT_NoError;
+ }
+
+ uint8_t USB_DeviceState_LCL = USB_DeviceState;
+
+ if (USB_DeviceState_LCL == DEVICE_STATE_Unattached)
+ return ENDPOINT_READYWAIT_DeviceDisconnected;
+ else if (USB_DeviceState_LCL == DEVICE_STATE_Suspended)
+ return ENDPOINT_READYWAIT_BusSuspended;
+ else if (Endpoint_IsStalled())
+ return ENDPOINT_READYWAIT_EndpointStalled;
+
+ uint16_t CurrentFrameNumber = USB_Device_GetFrameNumber();
+
+ if (CurrentFrameNumber != PreviousFrameNumber)
+ {
+ PreviousFrameNumber = CurrentFrameNumber;
+
+ if (!(TimeoutMSRem--))
+ return ENDPOINT_READYWAIT_Timeout;
+ }
+ }
+}
+#endif
+
+#endif
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.h
new file mode 100644
index 000000000..42c476b24
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.h
@@ -0,0 +1,689 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief USB Endpoint definitions for the AVR XMEGA microcontrollers.
+ * \copydetails Group_EndpointManagement_XMEGA
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_EndpointRW
+ * \defgroup Group_EndpointRW_XMEGA Endpoint Data Reading and Writing (XMEGA)
+ * \brief Endpoint data read/write definitions for the Atmel AVR XMEGA architecture.
+ *
+ * Functions, macros, variables, enums and types related to data reading and writing from and to endpoints.
+ */
+
+/** \ingroup Group_EndpointPrimitiveRW
+ * \defgroup Group_EndpointPrimitiveRW_XMEGA Read/Write of Primitive Data Types (XMEGA)
+ * \brief Endpoint primitive read/write definitions for the Atmel AVR XMEGA architecture.
+ *
+ * Functions, macros, variables, enums and types related to data reading and writing of primitive data types
+ * from and to endpoints.
+ */
+
+/** \ingroup Group_EndpointPacketManagement
+ * \defgroup Group_EndpointPacketManagement_XMEGA Endpoint Packet Management (XMEGA)
+ * \brief Endpoint packet management definitions for the Atmel AVR XMEGA architecture.
+ *
+ * Functions, macros, variables, enums and types related to packet management of endpoints.
+ */
+
+/** \ingroup Group_EndpointManagement
+ * \defgroup Group_EndpointManagement_XMEGA Endpoint Management (XMEGA)
+ * \brief Endpoint management definitions for the Atmel AVR XMEGA architecture.
+ *
+ * Functions, macros and enums related to endpoint management when in USB Device mode. This
+ * module contains the endpoint management macros, as well as endpoint interrupt and data
+ * send/receive functions for various data types.
+ *
+ * @{
+ */
+
+#ifndef __ENDPOINT_XMEGA_H__
+#define __ENDPOINT_XMEGA_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../USBTask.h"
+ #include "../USBInterrupt.h"
+ #include "../USBController.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ #if (!defined(MAX_ENDPOINT_INDEX) && !defined(CONTROL_ONLY_DEVICE)) || defined(__DOXYGEN__)
+ /** Total number of endpoints (including the default control endpoint at address 0) which may
+ * be used in the device. Different USB AVR models support different amounts of endpoints,
+ * this value reflects the maximum number of endpoints for the currently selected AVR model.
+ */
+ #define ENDPOINT_TOTAL_ENDPOINTS 16
+ #else
+ #if defined(CONTROL_ONLY_DEVICE)
+ #define ENDPOINT_TOTAL_ENDPOINTS 1
+ #else
+ #define ENDPOINT_TOTAL_ENDPOINTS (MAX_ENDPOINT_INDEX + 1)
+ #endif
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Type Defines: */
+ typedef struct
+ {
+ uint8_t Data[64];
+
+ uint8_t Length;
+ uint8_t Position;
+ } Endpoint_FIFO_t;
+
+ typedef struct
+ {
+ Endpoint_FIFO_t OUT;
+ Endpoint_FIFO_t IN;
+ } Endpoint_FIFOPair_t;
+
+ /* External Variables: */
+ extern Endpoint_FIFOPair_t USB_Endpoint_FIFOs[ENDPOINT_TOTAL_ENDPOINTS];
+ extern volatile uint8_t USB_Endpoint_SelectedEndpoint;
+ extern volatile USB_EP_t* USB_Endpoint_SelectedHandle;
+ extern volatile Endpoint_FIFO_t* USB_Endpoint_SelectedFIFO;
+
+ /* Inline Functions: */
+ static inline uint8_t Endpoint_BytesToEPSizeMask(const uint16_t Bytes) ATTR_WARN_UNUSED_RESULT ATTR_CONST
+ ATTR_ALWAYS_INLINE;
+ static inline uint8_t Endpoint_BytesToEPSizeMask(const uint16_t Bytes)
+ {
+ uint8_t MaskVal = 0;
+ uint16_t CheckBytes = 8;
+
+ while (CheckBytes < Bytes)
+ {
+ MaskVal++;
+ CheckBytes <<= 1;
+ }
+
+ return (MaskVal << USB_EP_BUFSIZE_gp);
+ }
+
+ /* Function Prototypes: */
+ bool Endpoint_ConfigureEndpoint_PRV(const uint8_t Address,
+ const uint8_t Config,
+ const uint8_t Size);
+ void Endpoint_ClearEndpoints(void);
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ #if (!defined(FIXED_CONTROL_ENDPOINT_SIZE) || defined(__DOXYGEN__))
+ /** Default size of the default control endpoint's bank, until altered by the control endpoint bank size
+ * value in the device descriptor. Not available if the \c FIXED_CONTROL_ENDPOINT_SIZE token is defined.
+ */
+ #define ENDPOINT_CONTROLEP_DEFAULT_SIZE 8
+ #endif
+
+ /* Enums: */
+ /** Enum for the possible error return codes of the \ref Endpoint_WaitUntilReady() function.
+ *
+ * \ingroup Group_EndpointRW_XMEGA
+ */
+ enum Endpoint_WaitUntilReady_ErrorCodes_t
+ {
+ ENDPOINT_READYWAIT_NoError = 0, /**< Endpoint is ready for next packet, no error. */
+ ENDPOINT_READYWAIT_EndpointStalled = 1, /**< The endpoint was stalled during the stream
+ * transfer by the host or device.
+ */
+ ENDPOINT_READYWAIT_DeviceDisconnected = 2, /**< Device was disconnected from the host while
+ * waiting for the endpoint to become ready.
+ */
+ ENDPOINT_READYWAIT_BusSuspended = 3, /**< The USB bus has been suspended by the host and
+ * no USB endpoint traffic can occur until the bus
+ * has resumed.
+ */
+ ENDPOINT_READYWAIT_Timeout = 4, /**< The host failed to accept or send the next packet
+ * within the software timeout period set by the
+ * \ref USB_STREAM_TIMEOUT_MS macro.
+ */
+ };
+
+ /* Inline Functions: */
+ /** Selects the given endpoint address.
+ *
+ * Any endpoint operations which do not require the endpoint address to be indicated will operate on
+ * the currently selected endpoint.
+ *
+ * \param[in] Address Endpoint address to select.
+ */
+ void Endpoint_SelectEndpoint(const uint8_t Address);
+
+ /** Configures the specified endpoint address with the given endpoint type, bank size and number of hardware
+ * banks. Once configured, the endpoint may be read from or written to, depending on its direction.
+ *
+ * \param[in] Address Endpoint address to configure.
+ *
+ * \param[in] Type Type of endpoint to configure, a \c EP_TYPE_* mask. Not all endpoint types
+ * are available on Low Speed USB devices - refer to the USB 2.0 specification.
+ *
+ * \param[in] Size Size of the endpoint's bank, where packets are stored before they are transmitted
+ * to the USB host, or after they have been received from the USB host (depending on
+ * the endpoint's data direction). The bank size must indicate the maximum packet size
+ * that the endpoint can handle.
+ *
+ * \param[in] Banks Number of hardware banks to use for the endpoint being configured.
+ *
+ * \note The default control endpoint should not be manually configured by the user application, as
+ * it is automatically configured by the library internally.
+ * \n\n
+ *
+ * \note This routine will automatically select the specified endpoint.
+ *
+ * \return Boolean \c true if the configuration succeeded, \c false otherwise.
+ */
+ static inline bool Endpoint_ConfigureEndpoint(const uint8_t Address,
+ const uint8_t Type,
+ const uint16_t Size,
+ const uint8_t Banks) ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_ConfigureEndpoint(const uint8_t Address,
+ const uint8_t Type,
+ const uint16_t Size,
+ const uint8_t Banks)
+ {
+ uint8_t EPConfigMask = (USB_EP_INTDSBL_bm | ((Banks > 1) ? USB_EP_PINGPONG_bm : 0) | Endpoint_BytesToEPSizeMask(Size));
+
+ if ((Address & ENDPOINT_EPNUM_MASK) >= ENDPOINT_TOTAL_ENDPOINTS)
+ return false;
+
+ // TODO - Fix once limitations are lifted
+ EPConfigMask &= ~USB_EP_PINGPONG_bm;
+ if (Size > 64)
+ return false;
+
+ switch (Type)
+ {
+ case EP_TYPE_CONTROL:
+ EPConfigMask |= USB_EP_TYPE_CONTROL_gc;
+ break;
+ case EP_TYPE_ISOCHRONOUS:
+ EPConfigMask |= USB_EP_TYPE_ISOCHRONOUS_gc;
+ break;
+ default:
+ EPConfigMask |= USB_EP_TYPE_BULK_gc;
+ break;
+ }
+
+ if (Type == EP_TYPE_CONTROL)
+ Endpoint_ConfigureEndpoint_PRV(Address ^ ENDPOINT_DIR_IN, EPConfigMask, Size);
+
+ return Endpoint_ConfigureEndpoint_PRV(Address, EPConfigMask, Size);
+ }
+
+ /** Indicates the number of bytes currently stored in the current endpoint's selected bank.
+ *
+ * \ingroup Group_EndpointRW_XMEGA
+ *
+ * \return Total number of bytes in the currently selected Endpoint's FIFO buffer.
+ */
+ static inline uint16_t Endpoint_BytesInEndpoint(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint16_t Endpoint_BytesInEndpoint(void)
+ {
+ if (USB_Endpoint_SelectedEndpoint & ENDPOINT_DIR_IN)
+ return USB_Endpoint_SelectedFIFO->Position;
+ else
+ return (USB_Endpoint_SelectedFIFO->Length - USB_Endpoint_SelectedFIFO->Position);
+ }
+
+ /** Get the endpoint address of the currently selected endpoint. This is typically used to save
+ * the currently selected endpoint so that it can be restored after another endpoint has been
+ * manipulated.
+ *
+ * \return Index of the currently selected endpoint.
+ */
+ static inline uint8_t Endpoint_GetCurrentEndpoint(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Endpoint_GetCurrentEndpoint(void)
+ {
+ return USB_Endpoint_SelectedEndpoint;
+ }
+
+ /** Resets the endpoint bank FIFO. This clears all the endpoint banks and resets the USB controller's
+ * data In and Out pointers to the bank's contents.
+ *
+ * \param[in] Address Endpoint address whose FIFO buffers are to be reset.
+ */
+ static inline void Endpoint_ResetEndpoint(const uint8_t Address) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_ResetEndpoint(const uint8_t Address)
+ {
+ if (Address & ENDPOINT_DIR_IN)
+ USB_Endpoint_FIFOs[Address & ENDPOINT_EPNUM_MASK].IN.Position = 0;
+ else
+ USB_Endpoint_FIFOs[Address & ENDPOINT_EPNUM_MASK].OUT.Position = 0;
+ }
+
+ /** Determines if the currently selected endpoint is enabled, but not necessarily configured.
+ *
+ * \return Boolean \c true if the currently selected endpoint is enabled, \c false otherwise.
+ */
+ static inline bool Endpoint_IsEnabled(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_IsEnabled(void)
+ {
+ return true;
+ }
+
+ /** Aborts all pending IN transactions on the currently selected endpoint, once the bank
+ * has been queued for transmission to the host via \ref Endpoint_ClearIN(). This function
+ * will terminate all queued transactions, resetting the endpoint banks ready for a new
+ * packet.
+ *
+ * \ingroup Group_EndpointPacketManagement_XMEGA
+ */
+ static inline void Endpoint_AbortPendingIN(void)
+ {
+ USB_Endpoint_SelectedHandle->STATUS |= USB_EP_BUSNACK0_bm;
+ }
+
+ /** Determines if the currently selected endpoint may be read from (if data is waiting in the endpoint
+ * bank and the endpoint is an OUT direction, or if the bank is not yet full if the endpoint is an IN
+ * direction). This function will return false if an error has occurred in the endpoint, if the endpoint
+ * is an OUT direction and no packet (or an empty packet) has been received, or if the endpoint is an IN
+ * direction and the endpoint bank is full.
+ *
+ * \ingroup Group_EndpointPacketManagement_XMEGA
+ *
+ * \return Boolean \c true if the currently selected endpoint may be read from or written to, depending
+ * on its direction.
+ */
+ static inline bool Endpoint_IsReadWriteAllowed(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_IsReadWriteAllowed(void)
+ {
+ return (USB_Endpoint_SelectedFIFO->Position < USB_Endpoint_SelectedFIFO->Length);
+ }
+
+ /** Determines if the currently selected endpoint is configured.
+ *
+ * \return Boolean \c true if the currently selected endpoint has been configured, \c false otherwise.
+ */
+ static inline bool Endpoint_IsConfigured(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_IsConfigured(void)
+ {
+ return ((USB_Endpoint_SelectedHandle->CTRL & USB_EP_TYPE_gm) ? true : false);
+ }
+
+ /** Determines if the selected IN endpoint is ready for a new packet to be sent to the host.
+ *
+ * \ingroup Group_EndpointPacketManagement_XMEGA
+ *
+ * \return Boolean \c true if the current endpoint is ready for an IN packet, \c false otherwise.
+ */
+ bool Endpoint_IsINReady(void) ATTR_WARN_UNUSED_RESULT;
+
+ /** Determines if the selected OUT endpoint has received new packet from the host.
+ *
+ * \ingroup Group_EndpointPacketManagement_XMEGA
+ *
+ * \return Boolean \c true if current endpoint is has received an OUT packet, \c false otherwise.
+ */
+ bool Endpoint_IsOUTReceived(void) ATTR_WARN_UNUSED_RESULT;
+
+ /** Determines if the current CONTROL type endpoint has received a SETUP packet.
+ *
+ * \ingroup Group_EndpointPacketManagement_XMEGA
+ *
+ * \return Boolean \c true if the selected endpoint has received a SETUP packet, \c false otherwise.
+ */
+ bool Endpoint_IsSETUPReceived(void) ATTR_WARN_UNUSED_RESULT;
+
+ /** Clears a received SETUP packet on the currently selected CONTROL type endpoint, freeing up the
+ * endpoint for the next packet.
+ *
+ * \ingroup Group_EndpointPacketManagement_XMEGA
+ *
+ * \note This is not applicable for non CONTROL type endpoints.
+ */
+ void Endpoint_ClearSETUP(void);
+
+ /** Sends an IN packet to the host on the currently selected endpoint, freeing up the endpoint for the
+ * next packet and switching to the alternative endpoint bank if double banked.
+ *
+ * \ingroup Group_EndpointPacketManagement_XMEGA
+ */
+ void Endpoint_ClearIN(void);
+
+ /** Acknowledges an OUT packet to the host on the currently selected endpoint, freeing up the endpoint
+ * for the next packet and switching to the alternative endpoint bank if double banked.
+ *
+ * \ingroup Group_EndpointPacketManagement_XMEGA
+ */
+ void Endpoint_ClearOUT(void);
+
+ /** Stalls the current endpoint, indicating to the host that a logical problem occurred with the
+ * indicated endpoint and that the current transfer sequence should be aborted. This provides a
+ * way for devices to indicate invalid commands to the host so that the current transfer can be
+ * aborted and the host can begin its own recovery sequence.
+ *
+ * The currently selected endpoint remains stalled until either the \ref Endpoint_ClearStall() macro
+ * is called, or the host issues a CLEAR FEATURE request to the device for the currently selected
+ * endpoint.
+ *
+ * \ingroup Group_EndpointPacketManagement_XMEGA
+ */
+ void Endpoint_StallTransaction(void);
+
+ /** Clears the STALL condition on the currently selected endpoint.
+ *
+ * \ingroup Group_EndpointPacketManagement_XMEGA
+ */
+ static inline void Endpoint_ClearStall(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_ClearStall(void)
+ {
+ USB_Endpoint_SelectedHandle->CTRL &= ~USB_EP_STALL_bm;
+ }
+
+ /** Determines if the currently selected endpoint is stalled, \c false otherwise.
+ *
+ * \ingroup Group_EndpointPacketManagement_XMEGA
+ *
+ * \return Boolean \c true if the currently selected endpoint is stalled, \c false otherwise.
+ */
+ static inline bool Endpoint_IsStalled(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Endpoint_IsStalled(void)
+ {
+ return ((USB_Endpoint_SelectedHandle->CTRL & USB_EP_STALL_bm) ? true : false);
+ }
+
+ /** Resets the data toggle of the currently selected endpoint. */
+ static inline void Endpoint_ResetDataToggle(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_ResetDataToggle(void)
+ {
+ USB_Endpoint_SelectedHandle->STATUS &= ~USB_EP_TOGGLE_bm;
+ }
+
+ /** Determines the currently selected endpoint's direction.
+ *
+ * \return The currently selected endpoint's direction, as a \c ENDPOINT_DIR_* mask.
+ */
+ static inline uint8_t Endpoint_GetEndpointDirection(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Endpoint_GetEndpointDirection(void)
+ {
+ return (USB_Endpoint_SelectedEndpoint & ENDPOINT_DIR_IN);
+ }
+
+ /** Reads one byte from the currently selected endpoint's bank, for OUT direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_XMEGA
+ *
+ * \return Next byte in the currently selected endpoint's FIFO buffer.
+ */
+ uint8_t Endpoint_Read_8(void) ATTR_WARN_UNUSED_RESULT;
+
+ /** Writes one byte to the currently selected endpoint's bank, for IN direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_XMEGA
+ *
+ * \param[in] Data Data to write into the the currently selected endpoint's FIFO buffer.
+ */
+ void Endpoint_Write_8(const uint8_t Data);
+
+ /** Discards one byte from the currently selected endpoint's bank, for OUT direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_XMEGA
+ */
+ static inline void Endpoint_Discard_8(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_Discard_8(void)
+ {
+ USB_Endpoint_SelectedFIFO->Position++;
+ }
+
+ /** Reads two bytes from the currently selected endpoint's bank in little endian format, for OUT
+ * direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_XMEGA
+ *
+ * \return Next two bytes in the currently selected endpoint's FIFO buffer.
+ */
+ static inline uint16_t Endpoint_Read_16_LE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint16_t Endpoint_Read_16_LE(void)
+ {
+ uint16_t Byte0 = Endpoint_Read_8();
+ uint16_t Byte1 = Endpoint_Read_8();
+
+ return ((Byte1 << 8) | Byte0);
+ }
+
+ /** Reads two bytes from the currently selected endpoint's bank in big endian format, for OUT
+ * direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_XMEGA
+ *
+ * \return Next two bytes in the currently selected endpoint's FIFO buffer.
+ */
+ static inline uint16_t Endpoint_Read_16_BE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint16_t Endpoint_Read_16_BE(void)
+ {
+ uint16_t Byte0 = Endpoint_Read_8();
+ uint16_t Byte1 = Endpoint_Read_8();
+
+ return ((Byte0 << 8) | Byte1);
+ }
+
+ /** Writes two bytes to the currently selected endpoint's bank in little endian format, for IN
+ * direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_XMEGA
+ *
+ * \param[in] Data Data to write to the currently selected endpoint's FIFO buffer.
+ */
+ static inline void Endpoint_Write_16_LE(const uint16_t Data) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_Write_16_LE(const uint16_t Data)
+ {
+ Endpoint_Write_8(Data & 0xFF);
+ Endpoint_Write_8(Data >> 8);
+ }
+
+ /** Writes two bytes to the currently selected endpoint's bank in big endian format, for IN
+ * direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_XMEGA
+ *
+ * \param[in] Data Data to write to the currently selected endpoint's FIFO buffer.
+ */
+ static inline void Endpoint_Write_16_BE(const uint16_t Data) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_Write_16_BE(const uint16_t Data)
+ {
+ Endpoint_Write_8(Data >> 8);
+ Endpoint_Write_8(Data & 0xFF);
+ }
+
+ /** Discards two bytes from the currently selected endpoint's bank, for OUT direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_XMEGA
+ */
+ static inline void Endpoint_Discard_16(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_Discard_16(void)
+ {
+ Endpoint_Discard_8();
+ Endpoint_Discard_8();
+ }
+
+ /** Reads four bytes from the currently selected endpoint's bank in little endian format, for OUT
+ * direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_XMEGA
+ *
+ * \return Next four bytes in the currently selected endpoint's FIFO buffer.
+ */
+ static inline uint32_t Endpoint_Read_32_LE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint32_t Endpoint_Read_32_LE(void)
+ {
+ uint32_t Byte0 = Endpoint_Read_8();
+ uint32_t Byte1 = Endpoint_Read_8();
+ uint32_t Byte2 = Endpoint_Read_8();
+ uint32_t Byte3 = Endpoint_Read_8();
+
+ return ((Byte3 << 24) | (Byte2 << 16) | (Byte1 << 8) | Byte0);
+ }
+
+ /** Reads four bytes from the currently selected endpoint's bank in big endian format, for OUT
+ * direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_XMEGA
+ *
+ * \return Next four bytes in the currently selected endpoint's FIFO buffer.
+ */
+ static inline uint32_t Endpoint_Read_32_BE(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint32_t Endpoint_Read_32_BE(void)
+ {
+ uint32_t Byte0 = Endpoint_Read_8();
+ uint32_t Byte1 = Endpoint_Read_8();
+ uint32_t Byte2 = Endpoint_Read_8();
+ uint32_t Byte3 = Endpoint_Read_8();
+
+ return ((Byte0 << 24) | (Byte1 << 16) | (Byte2 << 8) | Byte3);
+ }
+
+ /** Writes four bytes to the currently selected endpoint's bank in little endian format, for IN
+ * direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_XMEGA
+ *
+ * \param[in] Data Data to write to the currently selected endpoint's FIFO buffer.
+ */
+ static inline void Endpoint_Write_32_LE(const uint32_t Data) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_Write_32_LE(const uint32_t Data)
+ {
+ Endpoint_Write_8(Data & 0xFF);
+ Endpoint_Write_8(Data >> 8);
+ Endpoint_Write_8(Data >> 16);
+ Endpoint_Write_8(Data >> 24);
+ }
+
+ /** Writes four bytes to the currently selected endpoint's bank in big endian format, for IN
+ * direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_XMEGA
+ *
+ * \param[in] Data Data to write to the currently selected endpoint's FIFO buffer.
+ */
+ static inline void Endpoint_Write_32_BE(const uint32_t Data) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_Write_32_BE(const uint32_t Data)
+ {
+ Endpoint_Write_8(Data >> 24);
+ Endpoint_Write_8(Data >> 16);
+ Endpoint_Write_8(Data >> 8);
+ Endpoint_Write_8(Data & 0xFF);
+ }
+
+ /** Discards four bytes from the currently selected endpoint's bank, for OUT direction endpoints.
+ *
+ * \ingroup Group_EndpointPrimitiveRW_XMEGA
+ */
+ static inline void Endpoint_Discard_32(void) ATTR_ALWAYS_INLINE;
+ static inline void Endpoint_Discard_32(void)
+ {
+ Endpoint_Discard_8();
+ Endpoint_Discard_8();
+ Endpoint_Discard_8();
+ Endpoint_Discard_8();
+ }
+
+ /* External Variables: */
+ /** Global indicating the maximum packet size of the default control endpoint located at address
+ * 0 in the device. This value is set to the value indicated in the device descriptor in the user
+ * project once the USB interface is initialized into device mode.
+ *
+ * If space is an issue, it is possible to fix this to a static value by defining the control
+ * endpoint size in the \c FIXED_CONTROL_ENDPOINT_SIZE token passed to the compiler in the makefile
+ * via the -D switch. When a fixed control endpoint size is used, the size is no longer dynamically
+ * read from the descriptors at runtime and instead fixed to the given value. When used, it is
+ * important that the descriptor control endpoint size value matches the size given as the
+ * \c FIXED_CONTROL_ENDPOINT_SIZE token - it is recommended that the \c FIXED_CONTROL_ENDPOINT_SIZE token
+ * be used in the device descriptors to ensure this.
+ *
+ * \attention This variable should be treated as read-only in the user application, and never manually
+ * changed in value.
+ */
+ #if (!defined(FIXED_CONTROL_ENDPOINT_SIZE) || defined(__DOXYGEN__))
+ extern uint8_t USB_Device_ControlEndpointSize;
+ #else
+ #define USB_Device_ControlEndpointSize FIXED_CONTROL_ENDPOINT_SIZE
+ #endif
+
+ /* Function Prototypes: */
+ /** Configures a table of endpoint descriptions, in sequence. This function can be used to configure multiple
+ * endpoints at the same time.
+ *
+ * \note Endpoints with a zero address will be ignored, thus this function cannot be used to configure the
+ * control endpoint.
+ *
+ * \param[in] Table Pointer to a table of endpoint descriptions.
+ * \param[in] Entries Number of entries in the endpoint table to configure.
+ *
+ * \return Boolean \c true if all endpoints configured successfully, \c false otherwise.
+ */
+ bool Endpoint_ConfigureEndpointTable(const USB_Endpoint_Table_t* const Table,
+ const uint8_t Entries);
+
+ /** Completes the status stage of a control transfer on a CONTROL type endpoint automatically,
+ * with respect to the data direction. This is a convenience function which can be used to
+ * simplify user control request handling.
+ *
+ * \note This routine should not be called on non CONTROL type endpoints.
+ */
+ void Endpoint_ClearStatusStage(void);
+
+ /** Spin-loops until the currently selected non-control endpoint is ready for the next packet of data
+ * to be read or written to it.
+ *
+ * \note This routine should not be called on CONTROL type endpoints.
+ *
+ * \ingroup Group_EndpointRW_XMEGA
+ *
+ * \return A value from the \ref Endpoint_WaitUntilReady_ErrorCodes_t enum.
+ */
+ uint8_t Endpoint_WaitUntilReady(void);
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Host_XMEGA.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Host_XMEGA.c
new file mode 100644
index 000000000..c46773303
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Host_XMEGA.c
@@ -0,0 +1,41 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "../../../../Common/Common.h"
+#if (ARCH == ARCH_XMEGA)
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../USBMode.h"
+
+#if defined(USB_CAN_BE_HOST)
+
+#endif
+
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/PipeStream_XMEGA.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/PipeStream_XMEGA.c
new file mode 100644
index 000000000..c46773303
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/PipeStream_XMEGA.c
@@ -0,0 +1,41 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "../../../../Common/Common.h"
+#if (ARCH == ARCH_XMEGA)
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../USBMode.h"
+
+#if defined(USB_CAN_BE_HOST)
+
+#endif
+
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Pipe_XMEGA.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Pipe_XMEGA.c
new file mode 100644
index 000000000..69f369e43
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Pipe_XMEGA.c
@@ -0,0 +1,37 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../USBMode.h"
+
+#if defined(USB_CAN_BE_HOST)
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_Control_R.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_Control_R.c
new file mode 100644
index 000000000..0bd384348
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_Control_R.c
@@ -0,0 +1,86 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#if defined(TEMPLATE_FUNC_NAME)
+
+uint8_t TEMPLATE_FUNC_NAME (void* const Buffer,
+ uint16_t Length)
+{
+ uint8_t* DataStream = ((uint8_t*)Buffer + TEMPLATE_BUFFER_OFFSET(Length));
+
+ Endpoint_SelectEndpoint(USB_Endpoint_SelectedEndpoint & ~ENDPOINT_DIR_IN);
+
+ if (!(Length))
+ Endpoint_ClearOUT();
+
+ while (Length)
+ {
+ uint8_t USB_DeviceState_LCL = USB_DeviceState;
+
+ if (USB_DeviceState_LCL == DEVICE_STATE_Unattached)
+ return ENDPOINT_RWCSTREAM_DeviceDisconnected;
+ else if (USB_DeviceState_LCL == DEVICE_STATE_Suspended)
+ return ENDPOINT_RWCSTREAM_BusSuspended;
+ else if (Endpoint_IsSETUPReceived())
+ return ENDPOINT_RWCSTREAM_HostAborted;
+
+ if (Endpoint_IsOUTReceived())
+ {
+ while (Length && Endpoint_BytesInEndpoint())
+ {
+ TEMPLATE_TRANSFER_BYTE(DataStream);
+ TEMPLATE_BUFFER_MOVE(DataStream, 1);
+ Length--;
+ }
+
+ Endpoint_ClearOUT();
+ }
+ }
+
+ while (!(Endpoint_IsINReady()))
+ {
+ uint8_t USB_DeviceState_LCL = USB_DeviceState;
+
+ if (USB_DeviceState_LCL == DEVICE_STATE_Unattached)
+ return ENDPOINT_RWCSTREAM_DeviceDisconnected;
+ else if (USB_DeviceState_LCL == DEVICE_STATE_Suspended)
+ return ENDPOINT_RWCSTREAM_BusSuspended;
+ }
+
+ return ENDPOINT_RWCSTREAM_NoError;
+}
+
+#undef TEMPLATE_BUFFER_OFFSET
+#undef TEMPLATE_BUFFER_MOVE
+#undef TEMPLATE_FUNC_NAME
+#undef TEMPLATE_TRANSFER_BYTE
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_Control_W.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_Control_W.c
new file mode 100644
index 000000000..703f253c0
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_Control_W.c
@@ -0,0 +1,97 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#if defined(TEMPLATE_FUNC_NAME)
+
+uint8_t TEMPLATE_FUNC_NAME (const void* const Buffer,
+ uint16_t Length)
+{
+ uint8_t* DataStream = ((uint8_t*)Buffer + TEMPLATE_BUFFER_OFFSET(Length));
+ bool LastPacketFull = false;
+
+ Endpoint_SelectEndpoint(USB_Endpoint_SelectedEndpoint | ENDPOINT_DIR_IN);
+
+ if (Length > USB_ControlRequest.wLength)
+ Length = USB_ControlRequest.wLength;
+ else if (!(Length))
+ Endpoint_ClearIN();
+
+ while (Length || LastPacketFull)
+ {
+ uint8_t USB_DeviceState_LCL = USB_DeviceState;
+
+ if (USB_DeviceState_LCL == DEVICE_STATE_Unattached)
+ return ENDPOINT_RWCSTREAM_DeviceDisconnected;
+ else if (USB_DeviceState_LCL == DEVICE_STATE_Suspended)
+ return ENDPOINT_RWCSTREAM_BusSuspended;
+ else if (Endpoint_IsSETUPReceived())
+ return ENDPOINT_RWCSTREAM_HostAborted;
+ else if (Endpoint_IsOUTReceived())
+ break;
+
+ if (Endpoint_IsINReady())
+ {
+ uint16_t BytesInEndpoint = Endpoint_BytesInEndpoint();
+
+ while (Length && (BytesInEndpoint < USB_Device_ControlEndpointSize))
+ {
+ TEMPLATE_TRANSFER_BYTE(DataStream);
+ TEMPLATE_BUFFER_MOVE(DataStream, 1);
+ Length--;
+ BytesInEndpoint++;
+ }
+
+ LastPacketFull = (BytesInEndpoint == USB_Device_ControlEndpointSize);
+ Endpoint_ClearIN();
+ }
+ }
+
+ while (!(Endpoint_IsOUTReceived()))
+ {
+ uint8_t USB_DeviceState_LCL = USB_DeviceState;
+
+ if (USB_DeviceState_LCL == DEVICE_STATE_Unattached)
+ return ENDPOINT_RWCSTREAM_DeviceDisconnected;
+ else if (USB_DeviceState_LCL == DEVICE_STATE_Suspended)
+ return ENDPOINT_RWCSTREAM_BusSuspended;
+ else if (Endpoint_IsSETUPReceived())
+ return ENDPOINT_RWCSTREAM_HostAborted;
+ }
+
+ return ENDPOINT_RWCSTREAM_NoError;
+}
+
+#undef TEMPLATE_BUFFER_OFFSET
+#undef TEMPLATE_BUFFER_MOVE
+#undef TEMPLATE_FUNC_NAME
+#undef TEMPLATE_TRANSFER_BYTE
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_RW.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_RW.c
new file mode 100644
index 000000000..d51afdfb1
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_RW.c
@@ -0,0 +1,89 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#if defined(TEMPLATE_FUNC_NAME)
+
+uint8_t TEMPLATE_FUNC_NAME (TEMPLATE_BUFFER_TYPE const Buffer,
+ uint16_t Length,
+ uint16_t* const BytesProcessed)
+{
+ uint8_t* DataStream = ((uint8_t*)Buffer + TEMPLATE_BUFFER_OFFSET(Length));
+ uint16_t BytesInTransfer = 0;
+ uint8_t ErrorCode;
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()))
+ return ErrorCode;
+
+ if (BytesProcessed != NULL)
+ {
+ Length -= *BytesProcessed;
+ TEMPLATE_BUFFER_MOVE(DataStream, *BytesProcessed);
+ }
+
+ while (Length)
+ {
+ if (!(Endpoint_IsReadWriteAllowed()))
+ {
+ TEMPLATE_CLEAR_ENDPOINT();
+
+ #if !defined(INTERRUPT_CONTROL_ENDPOINT)
+ USB_USBTask();
+ #endif
+
+ if (BytesProcessed != NULL)
+ {
+ *BytesProcessed += BytesInTransfer;
+ return ENDPOINT_RWSTREAM_IncompleteTransfer;
+ }
+
+ if ((ErrorCode = Endpoint_WaitUntilReady()))
+ return ErrorCode;
+ }
+ else
+ {
+ TEMPLATE_TRANSFER_BYTE(DataStream);
+ TEMPLATE_BUFFER_MOVE(DataStream, 1);
+ Length--;
+ BytesInTransfer++;
+ }
+ }
+
+ return ENDPOINT_RWSTREAM_NoError;
+}
+
+#undef TEMPLATE_FUNC_NAME
+#undef TEMPLATE_BUFFER_TYPE
+#undef TEMPLATE_TRANSFER_BYTE
+#undef TEMPLATE_CLEAR_ENDPOINT
+#undef TEMPLATE_BUFFER_OFFSET
+#undef TEMPLATE_BUFFER_MOVE
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.c
new file mode 100644
index 000000000..99589809e
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.c
@@ -0,0 +1,204 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "../../../../Common/Common.h"
+#if (ARCH == ARCH_XMEGA)
+
+#define __INCLUDE_FROM_USB_DRIVER
+#define __INCLUDE_FROM_USB_CONTROLLER_C
+#include "../USBController.h"
+
+#if defined(USB_CAN_BE_BOTH)
+volatile uint8_t USB_CurrentMode = USB_MODE_None;
+#endif
+
+#if !defined(USE_STATIC_OPTIONS)
+volatile uint8_t USB_Options;
+#endif
+
+/* Ugly workaround to ensure an aligned table, since __BIGGEST_ALIGNMENT__ == 1 for the 8-bit AVR-GCC toolchain */
+uint8_t USB_EndpointTable[sizeof(USB_EndpointTable_t) + 1];
+
+void USB_Init(
+ #if defined(USB_CAN_BE_BOTH)
+ const uint8_t Mode
+ #endif
+
+ #if (defined(USB_CAN_BE_BOTH) && !defined(USE_STATIC_OPTIONS))
+ ,
+ #elif (!defined(USB_CAN_BE_BOTH) && defined(USE_STATIC_OPTIONS))
+ void
+ #endif
+
+ #if !defined(USE_STATIC_OPTIONS)
+ const uint8_t Options
+ #endif
+ )
+{
+ #if !defined(USE_STATIC_OPTIONS)
+ USB_Options = Options;
+ #endif
+
+ uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask();
+ GlobalInterruptDisable();
+
+ NVM.CMD = NVM_CMD_READ_CALIB_ROW_gc;
+ USB.CAL0 = pgm_read_byte(offsetof(NVM_PROD_SIGNATURES_t, USBCAL0));
+ USB.CAL1 = pgm_read_byte(offsetof(NVM_PROD_SIGNATURES_t, USBCAL1));
+ NVM.CMD = NVM_CMD_NO_OPERATION_gc;
+
+ /* Ugly workaround to ensure an aligned table, since __BIGGEST_ALIGNMENT__ == 1 for the 8-bit AVR-GCC toolchain */
+ USB.EPPTR = ((intptr_t)&USB_EndpointTable[1] & ~(1 << 0));
+ USB.CTRLA = (USB_STFRNUM_bm | ((ENDPOINT_TOTAL_ENDPOINTS - 1) << USB_MAXEP_gp));
+
+ if ((USB_Options & USB_OPT_BUSEVENT_PRIHIGH) == USB_OPT_BUSEVENT_PRIHIGH)
+ USB.INTCTRLA = (3 << USB_INTLVL_gp);
+ else if ((USB_Options & USB_OPT_BUSEVENT_PRIMED) == USB_OPT_BUSEVENT_PRIMED)
+ USB.INTCTRLA = (2 << USB_INTLVL_gp);
+ else
+ USB.INTCTRLA = (1 << USB_INTLVL_gp);
+
+ SetGlobalInterruptMask(CurrentGlobalInt);
+
+ #if defined(USB_CAN_BE_BOTH)
+ USB_CurrentMode = Mode;
+ #endif
+
+ USB_IsInitialized = true;
+
+ USB_ResetInterface();
+}
+
+void USB_Disable(void)
+{
+ USB_INT_DisableAllInterrupts();
+ USB_INT_ClearAllInterrupts();
+
+ USB_Detach();
+ USB_Controller_Disable();
+
+ USB_IsInitialized = false;
+}
+
+void USB_ResetInterface(void)
+{
+ uint8_t PrescalerNeeded;
+
+ #if defined(USB_DEVICE_OPT_FULLSPEED)
+ if (USB_Options & USB_DEVICE_OPT_LOWSPEED)
+ PrescalerNeeded = F_USB / 6000000;
+ else
+ PrescalerNeeded = F_USB / 48000000;
+ #else
+ PrescalerNeeded = F_USB / 6000000;
+ #endif
+
+ uint8_t DividerIndex = 0;
+ while (PrescalerNeeded > 0)
+ {
+ DividerIndex++;
+ PrescalerNeeded >>= 1;
+ }
+
+ CLK.USBCTRL = (DividerIndex - 1) << CLK_USBPSDIV_gp;
+
+ if (USB_Options & USB_OPT_PLLCLKSRC)
+ CLK.USBCTRL |= (CLK_USBSRC_PLL_gc | CLK_USBSEN_bm);
+ else
+ CLK.USBCTRL |= (CLK_USBSRC_RC32M_gc | CLK_USBSEN_bm);
+
+ USB_Device_SetDeviceAddress(0);
+
+ USB_INT_DisableAllInterrupts();
+ USB_INT_ClearAllInterrupts();
+
+ USB_Controller_Reset();
+ USB_Init_Device();
+}
+
+#if defined(USB_CAN_BE_DEVICE)
+static void USB_Init_Device(void)
+{
+ USB_DeviceState = DEVICE_STATE_Unattached;
+ USB_Device_ConfigurationNumber = 0;
+
+ #if !defined(NO_DEVICE_REMOTE_WAKEUP)
+ USB_Device_RemoteWakeupEnabled = false;
+ #endif
+
+ #if !defined(NO_DEVICE_SELF_POWER)
+ USB_Device_CurrentlySelfPowered = false;
+ #endif
+
+ #if !defined(FIXED_CONTROL_ENDPOINT_SIZE)
+ USB_Descriptor_Device_t* DeviceDescriptorPtr;
+
+ #if defined(ARCH_HAS_MULTI_ADDRESS_SPACE) && \
+ !(defined(USE_FLASH_DESCRIPTORS) || defined(USE_EEPROM_DESCRIPTORS) || defined(USE_RAM_DESCRIPTORS))
+ uint8_t DescriptorAddressSpace;
+
+ if (CALLBACK_USB_GetDescriptor((DTYPE_Device << 8), 0, (void*)&DeviceDescriptorPtr, &DescriptorAddressSpace) != NO_DESCRIPTOR)
+ {
+ if (DescriptorAddressSpace == MEMSPACE_FLASH)
+ USB_Device_ControlEndpointSize = pgm_read_byte(&DeviceDescriptorPtr->Endpoint0Size);
+ else if (DescriptorAddressSpace == MEMSPACE_EEPROM)
+ USB_Device_ControlEndpointSize = eeprom_read_byte(&DeviceDescriptorPtr->Endpoint0Size);
+ else
+ USB_Device_ControlEndpointSize = DeviceDescriptorPtr->Endpoint0Size;
+ }
+ #else
+ if (CALLBACK_USB_GetDescriptor((DTYPE_Device << 8), 0, (void*)&DeviceDescriptorPtr) != NO_DESCRIPTOR)
+ {
+ #if defined(USE_RAM_DESCRIPTORS)
+ USB_Device_ControlEndpointSize = DeviceDescriptorPtr->Endpoint0Size;
+ #elif defined(USE_EEPROM_DESCRIPTORS)
+ USB_Device_ControlEndpointSize = eeprom_read_byte(&DeviceDescriptorPtr->Endpoint0Size);
+ #else
+ USB_Device_ControlEndpointSize = pgm_read_byte(&DeviceDescriptorPtr->Endpoint0Size);
+ #endif
+ }
+ #endif
+ #endif
+
+ if (USB_Options & USB_DEVICE_OPT_LOWSPEED)
+ USB_Device_SetLowSpeed();
+ else
+ USB_Device_SetFullSpeed();
+
+ Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL,
+ USB_Device_ControlEndpointSize, 1);
+
+ USB_INT_Enable(USB_INT_BUSEVENTI);
+
+ USB_Attach();
+}
+#endif
+
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.h
new file mode 100644
index 000000000..15d4eec34
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.h
@@ -0,0 +1,313 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief USB Controller definitions for the AVR XMEGA microcontrollers.
+ * \copydetails Group_USBManagement_XMEGA
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+/** \ingroup Group_USBManagement
+ * \defgroup Group_USBManagement_XMEGA USB Interface Management (XMEGA)
+ * \brief USB Controller definitions for the AVR XMEGA microcontrollers.
+ *
+ * Functions, macros, variables, enums and types related to the setup and management of the USB interface.
+ *
+ * @{
+ */
+
+#ifndef __USBCONTROLLER_XMEGA_H__
+#define __USBCONTROLLER_XMEGA_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+ #include "../USBMode.h"
+ #include "../Events.h"
+ #include "../USBTask.h"
+ #include "../USBInterrupt.h"
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Macros: */
+ #if defined(MAX_ENDPOINT_INDEX)
+ #define ENDPOINT_TABLE_COUNT (MAX_ENDPOINT_INDEX + 1)
+ #else
+ #define ENDPOINT_TABLE_COUNT 16
+ #endif
+
+ /* Type Defines: */
+ typedef struct
+ {
+ struct
+ {
+ USB_EP_t OUT;
+ USB_EP_t IN;
+ } Endpoints[ENDPOINT_TABLE_COUNT];
+ uint16_t FrameNum;
+ } ATTR_PACKED USB_EndpointTable_t;
+
+ /* External Variables: */
+ extern uint8_t USB_EndpointTable[];
+ #endif
+
+ /* Includes: */
+ #if defined(USB_CAN_BE_DEVICE) || defined(__DOXYGEN__)
+ #include "../Device.h"
+ #include "../Endpoint.h"
+ #include "../DeviceStandardReq.h"
+ #include "../EndpointStream.h"
+ #endif
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks and Defines: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ #if !defined(F_USB)
+ #error F_USB is not defined. You must define F_USB to the frequency of the unprescaled USB controller clock in your project makefile.
+ #endif
+
+ #if ((F_USB % 6000000) || (F_USB < 6000000))
+ #error Invalid F_USB specified. F_USB must be a multiple of 6MHz for USB Low Speed operation, and a multiple of 48MHz for Full Speed operation.
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** \name USB Controller Option Masks */
+ //@{
+ /** Sets the USB bus interrupt priority level to be low priority. The USB bus interrupt is used for Start of Frame events, bus suspend
+ * and resume events, bus reset events and other events related to the management of the USB bus.
+ */
+ #define USB_OPT_BUSEVENT_PRILOW ((0 << 2) | (0 << 1))
+
+ /** Sets the USB bus interrupt priority level to be medium priority. The USB bus interrupt is used for Start of Frame events, bus suspend
+ * and resume events, bus reset events and other events related to the management of the USB bus.
+ */
+ #define USB_OPT_BUSEVENT_PRIMED ((0 << 2) | (1 << 1))
+
+ /** Sets the USB bus interrupt priority level to be high priority. The USB bus interrupt is used for Start of Frame events, bus suspend
+ * and resume events, bus reset events and other events related to the management of the USB bus.
+ */
+ #define USB_OPT_BUSEVENT_PRIHIGH ((1 << 2) | (0 << 1))
+
+ /** Sets the USB controller to source its clock from the internal RC 32MHz clock, once it has been DFLL calibrated to 48MHz. */
+ #define USB_OPT_RC32MCLKSRC (0 << 3)
+
+ /** Sets the USB controller to source its clock from the internal PLL. */
+ #define USB_OPT_PLLCLKSRC (1 << 3)
+ //@}
+
+ #if !defined(USB_STREAM_TIMEOUT_MS) || defined(__DOXYGEN__)
+ /** Constant for the maximum software timeout period of the USB data stream transfer functions
+ * (both control and standard) when in either device or host mode. If the next packet of a stream
+ * is not received or acknowledged within this time period, the stream function will fail.
+ *
+ * This value may be overridden in the user project makefile as the value of the
+ * \ref USB_STREAM_TIMEOUT_MS token, and passed to the compiler using the -D switch.
+ */
+ #define USB_STREAM_TIMEOUT_MS 100
+ #endif
+
+ /* Inline Functions: */
+ /** Detaches the device from the USB bus. This has the effect of removing the device from any
+ * attached host, ceasing USB communications. If no host is present, this prevents any host from
+ * enumerating the device once attached until \ref USB_Attach() is called.
+ */
+ static inline void USB_Detach(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Detach(void)
+ {
+ USB.CTRLB &= ~USB_ATTACH_bm;
+ }
+
+ /** Attaches the device to the USB bus. This announces the device's presence to any attached
+ * USB host, starting the enumeration process. If no host is present, attaching the device
+ * will allow for enumeration once a host is connected to the device.
+ *
+ * This is inexplicably also required for proper operation while in host mode, to enable the
+ * attachment of a device to the host. This is despite the bit being located in the device-mode
+ * register and despite the datasheet making no mention of its requirement in host mode.
+ */
+ static inline void USB_Attach(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Attach(void)
+ {
+ USB.CTRLB |= USB_ATTACH_bm;
+ }
+
+ /* Function Prototypes: */
+ /** Main function to initialize and start the USB interface. Once active, the USB interface will
+ * allow for device connection to a host when in device mode, or for device enumeration while in
+ * host mode.
+ *
+ * As the USB library relies on interrupts for the device and host mode enumeration processes,
+ * the user must enable global interrupts before or shortly after this function is called. In
+ * device mode, interrupts must be enabled within 500ms of this function being called to ensure
+ * that the host does not time out whilst enumerating the device. In host mode, interrupts may be
+ * enabled at the application's leisure however enumeration will not begin of an attached device
+ * until after this has occurred.
+ *
+ * Calling this function when the USB interface is already initialized will cause a complete USB
+ * interface reset and re-enumeration.
+ *
+ * \param[in] Mode Mask indicating what mode the USB interface is to be initialized to, a value
+ * from the \ref USB_Modes_t enum.
+ * \note This parameter does not exist on devices with only one supported USB
+ * mode (device or host).
+ *
+ * \param[in] Options Mask indicating the options which should be used when initializing the USB
+ * interface to control the USB interface's behavior. This should be comprised of
+ * a \c USB_OPT_REG_* mask to control the regulator, a \c USB_OPT_*_PLL mask to control the
+ * PLL, and a \c USB_DEVICE_OPT_* mask (when the device mode is enabled) to set the device
+ * mode speed.
+ *
+ * \note To reduce the FLASH requirements of the library if only device or host mode is required,
+ * the mode can be statically set in the project makefile by defining the token \c USB_DEVICE_ONLY
+ * (for device mode) or \c USB_HOST_ONLY (for host mode), passing the token to the compiler
+ * via the -D switch. If the mode is statically set, this parameter does not exist in the
+ * function prototype.
+ * \n\n
+ *
+ * \note To reduce the FLASH requirements of the library if only fixed settings are required,
+ * the options may be set statically in the same manner as the mode (see the Mode parameter of
+ * this function). To statically set the USB options, pass in the \c USE_STATIC_OPTIONS token,
+ * defined to the appropriate options masks. When the options are statically set, this
+ * parameter does not exist in the function prototype.
+ * \n\n
+ *
+ * \note The mode parameter does not exist on devices where only one mode is possible, such as USB
+ * AVR models which only implement the USB device mode in hardware.
+ *
+ * \see \ref Group_Device for the \c USB_DEVICE_OPT_* masks.
+ */
+ void USB_Init(
+ #if defined(USB_CAN_BE_BOTH) || defined(__DOXYGEN__)
+ const uint8_t Mode
+ #endif
+
+ #if (defined(USB_CAN_BE_BOTH) && !defined(USE_STATIC_OPTIONS)) || defined(__DOXYGEN__)
+ ,
+ #elif (!defined(USB_CAN_BE_BOTH) && defined(USE_STATIC_OPTIONS))
+ void
+ #endif
+
+ #if !defined(USE_STATIC_OPTIONS) || defined(__DOXYGEN__)
+ const uint8_t Options
+ #endif
+ );
+
+ /** Shuts down the USB interface. This turns off the USB interface after deallocating all USB FIFO
+ * memory, endpoints and pipes. When turned off, no USB functionality can be used until the interface
+ * is restarted with the \ref USB_Init() function.
+ */
+ void USB_Disable(void);
+
+ /** Resets the interface, when already initialized. This will re-enumerate the device if already connected
+ * to a host, or re-enumerate an already attached device when in host mode.
+ */
+ void USB_ResetInterface(void);
+
+ /* Global Variables: */
+ #if defined(USB_CAN_BE_BOTH) || defined(__DOXYGEN__)
+ /** Indicates the mode that the USB interface is currently initialized to, a value from the
+ * \ref USB_Modes_t enum.
+ *
+ * \attention This variable should be treated as read-only in the user application, and never manually
+ * changed in value.
+ *
+ * \note When the controller is initialized into UID auto-detection mode, this variable will hold the
+ * currently selected USB mode (i.e. \ref USB_MODE_Device or \ref USB_MODE_Host). If the controller
+ * is fixed into a specific mode (either through the \c USB_DEVICE_ONLY or \c USB_HOST_ONLY compile time
+ * options, or a limitation of the USB controller in the chosen device model) this will evaluate to
+ * a constant of the appropriate value and will never evaluate to \ref USB_MODE_None even when the
+ * USB interface is not initialized.
+ */
+ extern volatile uint8_t USB_CurrentMode;
+ #elif defined(USB_CAN_BE_HOST)
+ #define USB_CurrentMode USB_MODE_Host
+ #elif defined(USB_CAN_BE_DEVICE)
+ #define USB_CurrentMode USB_MODE_Device
+ #endif
+
+ #if !defined(USE_STATIC_OPTIONS) || defined(__DOXYGEN__)
+ /** Indicates the current USB options that the USB interface was initialized with when \ref USB_Init()
+ * was called. This value will be one of the \c USB_MODE_* masks defined elsewhere in this module.
+ *
+ * \attention This variable should be treated as read-only in the user application, and never manually
+ * changed in value.
+ */
+ extern volatile uint8_t USB_Options;
+ #elif defined(USE_STATIC_OPTIONS)
+ #define USB_Options USE_STATIC_OPTIONS
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Function Prototypes: */
+ #if defined(__INCLUDE_FROM_USB_CONTROLLER_C)
+ static void USB_Init_Device(void);
+ #endif
+
+ /* Inline Functions: */
+ static inline void USB_Controller_Enable(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Controller_Enable(void)
+ {
+ USB.CTRLA |= USB_ENABLE_bm;
+ }
+
+ static inline void USB_Controller_Disable(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Controller_Disable(void)
+ {
+ USB.CTRLA &= ~USB_ENABLE_bm;
+ }
+
+ static inline void USB_Controller_Reset(void) ATTR_ALWAYS_INLINE;
+ static inline void USB_Controller_Reset(void)
+ {
+ USB.CTRLA &= ~USB_ENABLE_bm;
+ USB.CTRLA |= USB_ENABLE_bm;
+ }
+
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/USBInterrupt_XMEGA.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/USBInterrupt_XMEGA.c
new file mode 100644
index 000000000..f03f3f292
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/USBInterrupt_XMEGA.c
@@ -0,0 +1,106 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "../../../../Common/Common.h"
+#if (ARCH == ARCH_XMEGA)
+
+#define __INCLUDE_FROM_USB_DRIVER
+#include "../USBInterrupt.h"
+
+void USB_INT_DisableAllInterrupts(void)
+{
+ USB.INTCTRLA &= USB_INTLVL_gm;
+ USB.INTCTRLB = 0;
+}
+
+void USB_INT_ClearAllInterrupts(void)
+{
+ USB.INTFLAGSACLR = 0xFF;
+ USB.INTFLAGSBCLR = 0xFF;
+}
+
+ISR(USB_BUSEVENT_vect)
+{
+ #if !defined(NO_SOF_EVENTS)
+ if (USB_INT_HasOccurred(USB_INT_SOFI) && USB_INT_IsEnabled(USB_INT_SOFI))
+ {
+ USB_INT_Clear(USB_INT_SOFI);
+
+ EVENT_USB_Device_StartOfFrame();
+ }
+ #endif
+
+ if (USB_INT_HasOccurred(USB_INT_BUSEVENTI_Suspend))
+ {
+ USB_INT_Clear(USB_INT_BUSEVENTI_Suspend);
+
+ #if !defined(NO_LIMITED_CONTROLLER_CONNECT)
+ USB_DeviceState = DEVICE_STATE_Unattached;
+ EVENT_USB_Device_Disconnect();
+ #else
+ USB_DeviceState = DEVICE_STATE_Suspended;
+ EVENT_USB_Device_Suspend();
+ #endif
+ }
+
+ if (USB_INT_HasOccurred(USB_INT_BUSEVENTI_Resume))
+ {
+ USB_INT_Clear(USB_INT_BUSEVENTI_Resume);
+
+ if (USB_Device_ConfigurationNumber)
+ USB_DeviceState = DEVICE_STATE_Configured;
+ else
+ USB_DeviceState = (USB_Device_IsAddressSet()) ? DEVICE_STATE_Addressed : DEVICE_STATE_Powered;
+
+ #if !defined(NO_LIMITED_CONTROLLER_CONNECT)
+ EVENT_USB_Device_Connect();
+ #else
+ EVENT_USB_Device_WakeUp();
+ #endif
+ }
+
+ if (USB_INT_HasOccurred(USB_INT_BUSEVENTI_Reset))
+ {
+ USB_INT_Clear(USB_INT_BUSEVENTI_Reset);
+
+ USB_DeviceState = DEVICE_STATE_Default;
+ USB_Device_ConfigurationNumber = 0;
+
+ USB_Device_EnableDeviceAddress(0);
+
+ Endpoint_ClearEndpoints();
+ Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL,
+ USB_Device_ControlEndpointSize, 1);
+
+ EVENT_USB_Device_Reset();
+ }
+}
+
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/USBInterrupt_XMEGA.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/USBInterrupt_XMEGA.h
new file mode 100644
index 000000000..e224e225a
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/XMEGA/USBInterrupt_XMEGA.h
@@ -0,0 +1,172 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief USB Controller Interrupt definitions for the AVR XMEGA microcontrollers.
+ *
+ * This file contains definitions required for the correct handling of low level USB service routine interrupts
+ * from the USB controller.
+ *
+ * \note This file should not be included directly. It is automatically included as needed by the USB driver
+ * dispatch header located in LUFA/Drivers/USB/USB.h.
+ */
+
+#ifndef __USBINTERRUPT_XMEGA_H__
+#define __USBINTERRUPT_XMEGA_H__
+
+ /* Includes: */
+ #include "../../../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Preprocessor Checks: */
+ #if !defined(__INCLUDE_FROM_USB_DRIVER)
+ #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Enums: */
+ enum USB_Interrupts_t
+ {
+ USB_INT_BUSEVENTI = 1,
+ USB_INT_BUSEVENTI_Suspend = 2,
+ USB_INT_BUSEVENTI_Resume = 3,
+ USB_INT_BUSEVENTI_Reset = 4,
+ USB_INT_SOFI = 5,
+ };
+
+ /* Inline Functions: */
+ static inline void USB_INT_Enable(const uint8_t Interrupt) ATTR_ALWAYS_INLINE;
+ static inline void USB_INT_Enable(const uint8_t Interrupt)
+ {
+ switch (Interrupt)
+ {
+ case USB_INT_BUSEVENTI:
+ USB.INTCTRLA |= USB_BUSEVIE_bm;
+ break;
+ case USB_INT_SOFI:
+ USB.INTCTRLA |= USB_SOFIE_bm;
+ break;
+ default:
+ break;
+ }
+ }
+
+ static inline void USB_INT_Disable(const uint8_t Interrupt) ATTR_ALWAYS_INLINE;
+ static inline void USB_INT_Disable(const uint8_t Interrupt)
+ {
+ switch (Interrupt)
+ {
+ case USB_INT_BUSEVENTI:
+ USB.INTCTRLA &= ~USB_BUSEVIE_bm;
+ break;
+ case USB_INT_SOFI:
+ USB.INTCTRLA &= ~USB_SOFIE_bm;
+ break;
+ default:
+ break;
+ }
+ }
+
+ static inline void USB_INT_Clear(const uint8_t Interrupt) ATTR_ALWAYS_INLINE;
+ static inline void USB_INT_Clear(const uint8_t Interrupt)
+ {
+ switch (Interrupt)
+ {
+ case USB_INT_BUSEVENTI_Suspend:
+ USB.INTFLAGSACLR = USB_SUSPENDIF_bm;
+ break;
+ case USB_INT_BUSEVENTI_Resume:
+ USB.INTFLAGSACLR = USB_RESUMEIF_bm;
+ break;
+ case USB_INT_BUSEVENTI_Reset:
+ USB.INTFLAGSACLR = USB_RSTIF_bm;
+ break;
+ case USB_INT_SOFI:
+ USB.INTFLAGSACLR = USB_SOFIF_bm;
+ break;
+ default:
+ break;
+ }
+ }
+
+ static inline bool USB_INT_IsEnabled(const uint8_t Interrupt) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline bool USB_INT_IsEnabled(const uint8_t Interrupt)
+ {
+ switch (Interrupt)
+ {
+ case USB_INT_BUSEVENTI:
+ return ((USB.INTCTRLA & USB_BUSEVIE_bm) ? true : false);
+ case USB_INT_SOFI:
+ return ((USB.INTCTRLA & USB_SOFIE_bm) ? true : false);
+ default:
+ return false;
+ }
+ }
+
+ static inline bool USB_INT_HasOccurred(const uint8_t Interrupt) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
+ static inline bool USB_INT_HasOccurred(const uint8_t Interrupt)
+ {
+ switch (Interrupt)
+ {
+ case USB_INT_BUSEVENTI_Suspend:
+ return ((USB.INTFLAGSACLR & USB_SUSPENDIF_bm) ? true : false);
+ case USB_INT_BUSEVENTI_Resume:
+ return ((USB.INTFLAGSACLR & USB_RESUMEIF_bm) ? true : false);
+ case USB_INT_BUSEVENTI_Reset:
+ return ((USB.INTFLAGSACLR & USB_RSTIF_bm) ? true : false);
+ case USB_INT_SOFI:
+ return ((USB.INTFLAGSACLR & USB_SOFIF_bm) ? true : false);
+ default:
+ return false;
+ }
+ }
+
+ /* Includes: */
+ #include "../USBMode.h"
+ #include "../Events.h"
+ #include "../USBController.h"
+
+ /* Function Prototypes: */
+ void USB_INT_ClearAllInterrupts(void);
+ void USB_INT_DisableAllInterrupts(void);
+ #endif
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/USB.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/USB.h
new file mode 100644
index 000000000..a8df26fd1
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/USB.h
@@ -0,0 +1,422 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Master include file for the library USB functionality.
+ *
+ * Master include file for the library USB functionality.
+ *
+ * This file should be included in all user projects making use of the USB portions of the library, instead of
+ * the individual USB driver submodule headers.
+ */
+
+/** \defgroup Group_USB USB Core - LUFA/Drivers/USB/USB.h
+ *
+ * \brief Core driver for the microcontroller hardware USB module
+ *
+ * \section Sec_USB_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Drivers/USB/Core/ConfigDescriptors.c <i>(Makefile source module name: LUFA_SRC_USB)</i>
+ * - LUFA/Drivers/USB/Core/DeviceStandardReq.c <i>(Makefile source module name: LUFA_SRC_USB)</i>
+ * - LUFA/Drivers/USB/Core/Events.c <i>(Makefile source module name: LUFA_SRC_USB)</i>
+ * - LUFA/Drivers/USB/Core/HostStandardReq.c <i>(Makefile source module name: LUFA_SRC_USB)</i>
+ * - LUFA/Drivers/USB/Core/USBTask.c <i>(Makefile source module name: LUFA_SRC_USB)</i>
+ * - LUFA/Drivers/USB/Core/<i>ARCH</i>/Device_<i>ARCH</i>.c <i>(Makefile source module name: LUFA_SRC_USB)</i>
+ * - LUFA/Drivers/USB/Core/<i>ARCH</i>/Endpoint_<i>ARCH</i>.c <i>(Makefile source module name: LUFA_SRC_USB)</i>
+ * - LUFA/Drivers/USB/Core/<i>ARCH</i>/EndpointStream_<i>ARCH</i>.c <i>(Makefile source module name: LUFA_SRC_USB)</i>
+ * - LUFA/Drivers/USB/Core/<i>ARCH</i>/Host_<i>ARCH</i>.c <i>(Makefile source module name: LUFA_SRC_USB)</i>
+ * - LUFA/Drivers/USB/Core/<i>ARCH</i>/Pipe_<i>ARCH</i>.c <i>(Makefile source module name: LUFA_SRC_USB)</i>
+ * - LUFA/Drivers/USB/Core/<i>ARCH</i>/PipeStream_<i>ARCH</i>.c <i>(Makefile source module name: LUFA_SRC_USB)</i>
+ * - LUFA/Drivers/USB/Core/<i>ARCH</i>/USBController_<i>ARCH</i>.c <i>(Makefile source module name: LUFA_SRC_USB)</i>
+ * - LUFA/Drivers/USB/Core/<i>ARCH</i>/USBInterrupt_<i>ARCH</i>.c <i>(Makefile source module name: LUFA_SRC_USB)</i>
+ * - LUFA/Drivers/USB/Class/Common/HIDParser.c <i>(Makefile source module name: LUFA_SRC_USB)</i>
+ *
+ * \section Sec_USB_ModDescription Module Description
+ * Driver and framework for the USB controller of the selected architecture and microcontroller model. This module
+ * consists of many submodules, and is designed to provide an easy way to configure and control USB host, device
+ * or OTG mode USB applications.
+ *
+ * The USB stack requires the sole control over the USB controller in the microcontroller only; i.e. it does not
+ * require any additional timers or other peripherals to operate. This ensures that the USB stack requires as few
+ * resources as possible.
+ *
+ * The USB stack can be used in Device Mode for connections to USB Hosts (see \ref Group_Device), in Host mode for
+ * hosting of other USB devices (see \ref Group_Host), or as a dual role device which can either act as a USB host
+ * or device depending on what peripheral is connected (see \ref Group_OTG). Both modes also require a common set
+ * of USB management functions found \ref Group_USBManagement.
+ */
+
+/** \defgroup Group_USBClassDrivers USB Class Drivers
+ *
+ * \brief Drivers for the various standardized USB device classes
+ *
+ * Drivers for both host and device mode of the standard USB classes, for rapid application development.
+ * Class drivers give a framework which sits on top of the low level library API, allowing for standard
+ * USB classes to be implemented in a project with minimal user code. These drivers can be used in
+ * conjunction with the library low level APIs to implement interfaces both via the class drivers and via
+ * the standard library APIs.
+ *
+ * Multiple device mode class drivers can be used within a project, including multiple instances of the
+ * same class driver. In this way, USB Hosts and Devices can be made quickly using the internal class drivers
+ * so that more time and effort can be put into the end application instead of the USB protocol.
+ *
+ * The available class drivers and their modes are listed below.
+ *
+ * <table>
+ * <tr>
+ * <th width="200px">USB Class</th>
+ * <th width="90px">Device Mode</th>
+ * <th width="90px">Host Mode</th>
+ * </tr>
+ * <tr>
+ * <td>Android Open Accessory</td>
+ * <td bgcolor="#EE0000">No</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>Audio 1.0</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>CDC-ACM</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>HID</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>MIDI</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>Mass Storage</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>Printer</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>RNDIS</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * <tr>
+ * <td>Still Image</td>
+ * <td bgcolor="#EE0000">No</td>
+ * <td bgcolor="#00EE00">Yes</td>
+ * </tr>
+ * </table>
+ *
+ *
+ * \section Sec_USB_UsingClassDrivers Using the Class Drivers
+ * To make the Class drivers easy to integrate into a user application, they all implement a standardized
+ * design with similarly named/used function, enums, defines and types. The two different modes are implemented
+ * slightly differently, and thus will be explained separately. For information on a specific class driver, read
+ * the class driver's module documentation.
+ *
+ * \subsection Sec_USB_ClassDriverDevice Device Mode Class Drivers
+ * Implementing a Device Mode Class Driver in a user application requires a number of steps to be followed. Firstly,
+ * the module configuration and state structure must be added to the project source. These structures are named in a
+ * similar manner between classes, that of <tt>USB_ClassInfo_<i>{Class Name}</i>_Device_t</tt>, and are used to hold the
+ * complete state and configuration for each class instance. Multiple class instances is where the power of the class
+ * drivers lie; multiple interfaces of the same class simply require more instances of the Class Driver's \c USB_ClassInfo_*
+ * structure.
+ *
+ * Inside the ClassInfo structure lies two sections, a \c Config section, and a \c State section. The \c Config
+ * section contains the instance's configuration parameters, and <b>must have all fields set by the user application</b>
+ * before the class driver is used. Each Device mode Class driver typically contains a set of configuration parameters
+ * for the endpoint size/number of the associated logical USB interface, plus any class-specific configuration parameters.
+ *
+ * The following is an example of a properly initialized instance of the Audio Class Driver structure:
+ *
+ * \code
+ * USB_ClassInfo_Audio_Device_t My_Audio_Interface =
+ * {
+ * .Config =
+ * {
+ * .StreamingInterfaceNumber = 1,
+ * .DataINEndpoint =
+ * {
+ * .Address = (ENDPOINT_DIR_IN | 1),
+ * .Size = 64,
+ * .Banks = 1,
+ * },
+ * },
+ * };
+ * \endcode
+ *
+ * \note The class driver's configuration parameters should match those used in the device's descriptors that are
+ * sent to the host.
+ *
+ * To initialize the Class driver instance, the driver's <tt><i>{Class Name}</i>_Device_ConfigureEndpoints()</tt> function
+ * should be called in response to the \ref EVENT_USB_Device_ConfigurationChanged() event. This function will return a
+ * boolean true value if the driver successfully initialized the instance. Like all the class driver functions, this function
+ * takes in the address of the specific instance you wish to initialize - in this manner, multiple separate instances of
+ * the same class type can be initialized like this:
+ *
+ * \code
+ * void EVENT_USB_Device_ConfigurationChanged(void)
+ * {
+ * LEDs_SetAllLEDs(LEDMASK_USB_READY);
+ *
+ * if (!(Audio_Device_ConfigureEndpoints(&My_Audio_Interface)))
+ * LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
+ * }
+ * \endcode
+ *
+ * Once initialized, it is important to maintain the class driver's state by repeatedly calling the Class Driver's
+ * <tt><i>{Class Name}</i>_Device_USBTask()</tt> function in the main program loop. The exact implementation of this
+ * function varies between class drivers, and can be used for any internal class driver purpose to maintain each
+ * instance. Again, this function uses the address of the instance to operate on, and thus needs to be called for each
+ * separate instance, just like the main USB maintenance routine \ref USB_USBTask():
+ *
+ * \code
+ * int main(void)
+ * {
+ * SetupHardware();
+ *
+ * LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
+ *
+ * for (;;)
+ * {
+ * if (USB_DeviceState != DEVICE_STATE_Configured)
+ * Create_And_Process_Samples();
+ *
+ * Audio_Device_USBTask(&My_Audio_Interface);
+ * USB_USBTask();
+ * }
+ * }
+ * \endcode
+ *
+ * The final standardized Device Class Driver function is the Control Request handler function
+ * <tt><i>{Class Name}</i>_Device_ProcessControlRequest()</tt>, which should be called when the
+ * \ref EVENT_USB_Device_ControlRequest() event fires. This function should also be called for
+ * each class driver instance, using the address of the instance to operate on as the function's
+ * parameter. The request handler will abort if it is determined that the current request is not
+ * targeted at the given class driver instance, thus these methods can safely be called
+ * one-after-another in the event handler with no form of error checking:
+ *
+ * \code
+ * void EVENT_USB_Device_ControlRequest(void)
+ * {
+ * Audio_Device_ProcessControlRequest(&My_Audio_Interface);
+ * }
+ * \endcode
+ *
+ * Each class driver may also define a set of callback functions (which are prefixed by \c CALLBACK_*
+ * in the function's name) which <b>must</b> also be added to the user application - refer to each
+ * individual class driver's documentation for mandatory callbacks. In addition, each class driver may
+ * also define a set of events (identifiable by their prefix of \c EVENT_* in the function's name), which
+ * the user application <b>may</b> choose to implement, or ignore if not needed.
+ *
+ * The individual Device Mode Class Driver documentation contains more information on the non-standardized,
+ * class-specific functions which the user application can then use on the driver instances, such as data
+ * read and write routines. See each driver's individual documentation for more information on the
+ * class-specific functions.
+ *
+ * \subsection Sec_USB_ClassDriverHost Host Mode Class Drivers
+ * Implementing a Host Mode Class Driver in a user application requires a number of steps to be followed. Firstly,
+ * the module configuration and state structure must be added to the project source. These structures are named in a
+ * similar manner between classes, that of <tt>USB_ClassInfo_<b>{Class Name}</b>_Host_t</tt>, and are used to hold the
+ * complete state and configuration for each class instance. Multiple class instances is where the power of the class
+ * drivers lie; multiple interfaces of the same class simply require more instances of the Class Driver's \c USB_ClassInfo_*
+ * structure.
+ *
+ * Inside the \c USB_ClassInfo_* structure lies two sections, a \c Config section, and a \c State section. The \c Config
+ * section contains the instance's configuration parameters, and <b>must have all fields set by the user application</b>
+ * before the class driver is used. Each Device mode Class driver typically contains a set of configuration parameters
+ * for the endpoint size/number of the associated logical USB interface, plus any class-specific configuration parameters.
+ *
+ * The following is an example of a properly initialized instance of the MIDI Host Class Driver structure:
+ *
+ * \code
+ * USB_ClassInfo_MIDI_Host_t My_MIDI_Interface =
+ * {
+ * .Config =
+ * {
+ * .DataINPipe =
+ * {
+ * .Address = (PIPE_DIR_IN | 1),
+ * .Size = 64,
+ * .Banks = 1,
+ * },
+ * .DataOUTPipe =
+ * {
+ * .Address = (PIPE_DIR_OUT | 2),
+ * .Size = 64,
+ * .Banks = 1,
+ * },
+ * },
+ * };
+ * \endcode
+ *
+ * To initialize the Class driver instance, the driver's <tt><b>{Class Name}</b>_Host_ConfigurePipes()</tt> function
+ * should be called in response to the \c EVENT_USB_Host_DeviceEnumerationComplete() event firing. This function will
+ * will return an error code from the class driver's <tt><b>{Class Name}</b>_EnumerationFailure_ErrorCodes_t</tt> enum
+ * to indicate if the driver successfully initialized the instance and bound it to an interface in the attached device.
+ * Like all the class driver functions, this function takes in the address of the specific instance you wish to initialize -
+ * in this manner, multiple separate instances of the same class type can be initialized. A fragment of a Class Driver
+ * based Host mode application may look like the following:
+ *
+ * \code
+ * void EVENT_USB_Host_DeviceEnumerationComplete(void)
+ * {
+ * LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
+ *
+ * uint16_t ConfigDescriptorSize;
+ * uint8_t ConfigDescriptorData[512];
+ *
+ * if (USB_Host_GetDeviceConfigDescriptor(1, &ConfigDescriptorSize, ConfigDescriptorData,
+ * sizeof(ConfigDescriptorData)) != HOST_GETCONFIG_Successful)
+ * {
+ * LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
+ * return;
+ * }
+ *
+ * if (MIDI_Host_ConfigurePipes(&Keyboard_MIDI_Interface,
+ * ConfigDescriptorSize, ConfigDescriptorData) != MIDI_ENUMERROR_NoError)
+ * {
+ * LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
+ * return;
+ * }
+ *
+ * if (USB_Host_SetDeviceConfiguration(1) != HOST_SENDCONTROL_Successful)
+ * {
+ * LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
+ * return;
+ * }
+ *
+ * LEDs_SetAllLEDs(LEDMASK_USB_READY);
+ * }
+ * \endcode
+ *
+ * Note that the function also requires the device's configuration descriptor so that it can determine which interface
+ * in the device to bind to - this can be retrieved as shown in the above fragment using the
+ * \ref USB_Host_GetDeviceConfigDescriptor() function. If the device does not implement the interface the class driver
+ * is looking for, if all the matching interfaces are already bound to class driver instances or if an error occurs while
+ * binding to a device interface (for example, a device endpoint bank larger that the maximum supported bank size is used)
+ * the configuration will fail.
+ *
+ * To complete the device enumeration after binding the host mode Class Drivers to the attached device, a call to
+ * \c USB_Host_SetDeviceConfiguration() must be made. If the device configuration is not set within the
+ * \c EVENT_USB_Host_DeviceEnumerationComplete() event, the host still will assume the device enumeration has failed.
+ *
+ * Once initialized, it is important to maintain the class driver's state by repeatedly calling the Class Driver's
+ * <tt><b>{Class Name}</b>_Host_USBTask()</tt> function in the main program loop. The exact implementation of this
+ * function varies between class drivers, and can be used for any internal class driver purpose to maintain each
+ * instance. Again, this function uses the address of the instance to operate on, and thus needs to be called for each
+ * separate instance, just like the main USB maintenance routine \ref USB_USBTask():
+ *
+ * \code
+ * int main(void)
+ * {
+ * SetupHardware();
+ *
+ * LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
+ *
+ * for (;;)
+ * {
+ * if (USB_HostState != HOST_STATE_Configured)
+ * Create_And_Process_Samples();
+ *
+ * MIDI_Host_USBTask(&My_Audio_Interface);
+ * USB_USBTask();
+ * }
+ * }
+ * \endcode
+ *
+ * Each class driver may also define a set of callback functions (which are prefixed by \c CALLBACK_*
+ * in the function's name) which <b>must</b> also be added to the user application - refer to each
+ * individual class driver's documentation for mandatory callbacks. In addition, each class driver may
+ * also define a set of events (identifiable by their prefix of \c EVENT_* in the function's name), which
+ * the user application <b>may</b> choose to implement, or ignore if not needed.
+ *
+ * The individual Host Mode Class Driver documentation contains more information on the non-standardized,
+ * class-specific functions which the user application can then use on the driver instances, such as data
+ * read and write routines. See each driver's individual documentation for more information on the
+ * class-specific functions.
+ */
+
+#ifndef __USB_H__
+#define __USB_H__
+
+ /* Macros: */
+ #define __INCLUDE_FROM_USB_DRIVER
+
+ /* Includes: */
+ #include "../../Common/Common.h"
+ #include "Core/USBMode.h"
+
+ /* Includes: */
+ #include "Core/USBTask.h"
+ #include "Core/Events.h"
+ #include "Core/StdDescriptors.h"
+ #include "Core/ConfigDescriptors.h"
+ #include "Core/USBController.h"
+ #include "Core/USBInterrupt.h"
+
+ #if defined(USB_CAN_BE_HOST) || defined(__DOXYGEN__)
+ #include "Core/Host.h"
+ #include "Core/Pipe.h"
+ #include "Core/HostStandardReq.h"
+ #include "Core/PipeStream.h"
+ #endif
+
+ #if defined(USB_CAN_BE_DEVICE) || defined(__DOXYGEN__)
+ #include "Core/Device.h"
+ #include "Core/Endpoint.h"
+ #include "Core/DeviceStandardReq.h"
+ #include "Core/EndpointStream.h"
+ #endif
+
+ #if defined(USB_CAN_BE_BOTH) || defined(__DOXYGEN__)
+ #include "Core/OTG.h"
+ #endif
+
+ #include "Class/AndroidAccessoryClass.h"
+ #include "Class/AudioClass.h"
+ #include "Class/CDCClass.h"
+ #include "Class/HIDClass.h"
+ #include "Class/MassStorageClass.h"
+ #include "Class/MIDIClass.h"
+ #include "Class/PrinterClass.h"
+ #include "Class/RNDISClass.h"
+ #include "Class/StillImageClass.h"
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/License.txt b/tmk_core/protocol/lufa/LUFA-git/LUFA/License.txt
new file mode 100644
index 000000000..8d4ad7536
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/License.txt
@@ -0,0 +1,24 @@
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+
+
+Permission to use, copy, modify, and distribute this software
+and its documentation for any purpose is hereby granted without
+fee, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of the author not be used in
+advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+The author disclaims all warranties with regard to this
+software, including all implied warranties of merchantability
+and fitness. In no event shall the author be liable for any
+special, indirect or consequential damages or any damages
+whatsoever resulting from loss of use, data or profits, whether
+in an action of contract, negligence or other tortious action,
+arising out of or in connection with the use or performance of
+this software.
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/Platform.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/Platform.h
new file mode 100644
index 000000000..a9eedebc4
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/Platform.h
@@ -0,0 +1,80 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Architecture Specific Hardware Platform Drivers.
+ *
+ * This file is the master dispatch header file for the device-specific hardware platform drivers, for low level
+ * hardware configuration and management. The platform drivers are a set of drivers which are designed to provide
+ * a high level management layer for the various low level system functions such as clock control and interrupt
+ * management.
+ *
+ * User code may choose to either include this master dispatch header file to include all available platform
+ * driver header files for the current architecture, or may choose to only include the specific platform driver
+ * modules required for a particular application.
+ */
+
+/** \defgroup Group_PlatformDrivers System Platform Drivers - LUFA/Platform/Platform.h
+ * \brief Hardware platform drivers.
+ *
+ * \section Sec_PlatformDrivers_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - <b>UC3 Architecture Only:</b> LUFA/Platform/UC3/InterruptManagement.c <i>(Makefile source module name: LUFA_SRC_PLATFORM)</i>
+ * - <b>UC3 Architecture Only:</b> LUFA/Platform/UC3/Exception.S <i>(Makefile source module name: LUFA_SRC_PLATFORM)</i>
+ *
+ * \section Sec_PlatformDrivers_ModDescription Module Description
+ * Device-specific hardware platform drivers, for low level hardware configuration and management. The platform
+ * drivers are a set of drivers which are designed to provide a high level management layer for the various low level
+ * system functions such as clock control and interrupt management.
+ *
+ * User code may choose to either include this master dispatch header file to include all available platform
+ * driver header files for the current architecture, or may choose to only include the specific platform driver
+ * modules required for a particular application.
+ *
+ * \note The exact APIs and availability of sub-modules within the platform driver group may vary depending on the
+ * target used - see individual target module documentation for the API specific to your target processor.
+ */
+
+#ifndef __LUFA_PLATFORM_H__
+#define __LUFA_PLATFORM_H__
+
+ /* Includes: */
+ #include "../Common/Common.h"
+
+ /* Includes: */
+ #if (ARCH == ARCH_UC3)
+ #include "UC3/ClockManagement.h"
+ #include "UC3/InterruptManagement.h"
+ #elif (ARCH == ARCH_XMEGA)
+ #include "XMEGA/ClockManagement.h"
+ #endif
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/UC3/ClockManagement.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/UC3/ClockManagement.h
new file mode 100644
index 000000000..fb062628e
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/UC3/ClockManagement.h
@@ -0,0 +1,338 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Module Clock Driver for the AVR32 UC3 microcontrollers.
+ *
+ * Clock management driver for the AVR32 UC3 microcontrollers. This driver allows for the configuration
+ * of the various clocks within the device to clock the various peripherals.
+ */
+
+/** \ingroup Group_PlatformDrivers_UC3
+ * \defgroup Group_PlatformDrivers_UC3Clocks Clock Management Driver - LUFA/Platform/UC3/ClockManagement.h
+ * \brief Module Clock Driver for the AVR32 UC3 microcontrollers.
+ *
+ * \section Sec_PlatformDrivers_UC3Clocks_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - None
+ *
+ * \section Sec_PlatformDrivers_UC3Clocks_ModDescription Module Description
+ * Clock management driver for the AVR32 UC3 microcontrollers. This driver allows for the configuration
+ * of the various clocks within the device to clock the various peripherals.
+ *
+ * Usage Example:
+ * \code
+ * #include <LUFA/Platform/UC3/ClockManagement.h>
+ *
+ * void main(void)
+ * {
+ * // Start the master external oscillator which will be used as the main clock reference
+ * UC3CLK_StartExternalOscillator(0, EXOSC_MODE_8MHZ_OR_MORE, EXOSC_START_0CLK);
+ *
+ * // Start the PLL for the CPU clock, switch CPU to it
+ * UC3CLK_StartPLL(0, CLOCK_SRC_OSC0, 12000000, F_CPU);
+ * UC3CLK_SetCPUClockSource(CLOCK_SRC_PLL0, F_CPU);
+ *
+ * // Start the PLL for the USB Generic Clock module
+ * UC3CLK_StartPLL(1, CLOCK_SRC_OSC0, 12000000, 48000000);
+ * }
+ * \endcode
+ *
+ * @{
+ */
+
+#ifndef _UC3_CLOCK_MANAGEMENT_H_
+#define _UC3_CLOCK_MANAGEMENT_H_
+
+ /* Includes: */
+ #include "../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Enum for the possible external oscillator types. */
+ enum UC3_Extern_OSC_ClockTypes_t
+ {
+ EXOSC_MODE_CLOCK = AVR32_PM_OSCCTRL0_MODE_EXT_CLOCK, /**< External clock (non-crystal) mode. */
+ EXOSC_MODE_900KHZ_MAX = AVR32_PM_OSCCTRL0_MODE_CRYSTAL_G0, /**< External crystal oscillator equal to or slower than 900KHz. */
+ EXOSC_MODE_3MHZ_MAX = AVR32_PM_OSCCTRL0_MODE_CRYSTAL_G1, /**< External crystal oscillator equal to or slower than 3MHz. */
+ EXOSC_MODE_8MHZ_MAX = AVR32_PM_OSCCTRL0_MODE_CRYSTAL_G2, /**< External crystal oscillator equal to or slower than 8MHz. */
+ EXOSC_MODE_8MHZ_OR_MORE = AVR32_PM_OSCCTRL0_MODE_CRYSTAL_G3, /**< External crystal oscillator equal to or faster than 8MHz. */
+ };
+
+ /** Enum for the possible external oscillator startup times. */
+ enum UC3_Extern_OSC_ClockStartup_t
+ {
+ EXOSC_START_0CLK = AVR32_PM_OSCCTRL0_STARTUP_0_RCOSC, /**< Immediate startup, no delay. */
+ EXOSC_START_64CLK = AVR32_PM_OSCCTRL0_STARTUP_64_RCOSC, /**< Wait 64 clock cycles before startup for stability. */
+ EXOSC_START_128CLK = AVR32_PM_OSCCTRL0_STARTUP_128_RCOSC, /**< Wait 128 clock cycles before startup for stability. */
+ EXOSC_START_2048CLK = AVR32_PM_OSCCTRL0_STARTUP_2048_RCOSC, /**< Wait 2048 clock cycles before startup for stability. */
+ EXOSC_START_4096CLK = AVR32_PM_OSCCTRL0_STARTUP_4096_RCOSC, /**< Wait 4096 clock cycles before startup for stability. */
+ EXOSC_START_8192CLK = AVR32_PM_OSCCTRL0_STARTUP_8192_RCOSC, /**< Wait 8192 clock cycles before startup for stability. */
+ EXOSC_START_16384CLK = AVR32_PM_OSCCTRL0_STARTUP_16384_RCOSC, /**< Wait 16384 clock cycles before startup for stability. */
+ };
+
+ /** Enum for the possible module clock sources. */
+ enum UC3_System_ClockSource_t
+ {
+ CLOCK_SRC_SLOW_CLK = 0, /**< Clock sourced from the internal slow clock. */
+ CLOCK_SRC_OSC0 = 1, /**< Clock sourced from the Oscillator 0 clock. */
+ CLOCK_SRC_OSC1 = 2, /**< Clock sourced from the Oscillator 1 clock. */
+ CLOCK_SRC_PLL0 = 3, /**< Clock sourced from the PLL 0 clock. */
+ CLOCK_SRC_PLL1 = 4, /**< Clock sourced from the PLL 1 clock. */
+ };
+
+ /* Inline Functions: */
+ /** Starts the given external oscillator of the UC3 microcontroller, with the given options. This routine blocks until
+ * the oscillator is ready for use.
+ *
+ * \param[in] Channel Index of the external oscillator to start.
+ * \param[in] Type Type of clock attached to the given oscillator channel, a value from \ref UC3_Extern_OSC_ClockTypes_t.
+ * \param[in] Startup Startup time of the external oscillator, a value from \ref UC3_Extern_OSC_ClockStartup_t.
+ *
+ * \return Boolean \c true if the external oscillator was successfully started, \c false if invalid parameters specified.
+ */
+ static inline bool UC3CLK_StartExternalOscillator(const uint8_t Channel,
+ const uint8_t Type,
+ const uint8_t Startup) ATTR_ALWAYS_INLINE;
+ static inline bool UC3CLK_StartExternalOscillator(const uint8_t Channel,
+ const uint8_t Type,
+ const uint8_t Startup)
+ {
+ switch (Channel)
+ {
+ case 0:
+ AVR32_PM.OSCCTRL0.startup = Startup;
+ AVR32_PM.OSCCTRL0.mode = Type;
+ break;
+ case 1:
+ AVR32_PM.OSCCTRL1.startup = Startup;
+ AVR32_PM.OSCCTRL1.mode = Type;
+ break;
+ default:
+ return false;
+ }
+
+ AVR32_PM.mcctrl |= (1 << (AVR32_PM_MCCTRL_OSC0EN_OFFSET + Channel));
+
+ while (!(AVR32_PM.poscsr & (1 << (AVR32_PM_POSCSR_OSC0RDY_OFFSET + Channel))));
+ return true;
+ }
+
+ /** Stops the given external oscillator of the UC3 microcontroller.
+ *
+ * \param[in] Channel Index of the external oscillator to stop.
+ */
+ static inline void UC3CLK_StopExternalOscillator(const uint8_t Channel) ATTR_ALWAYS_INLINE;
+ static inline void UC3CLK_StopExternalOscillator(const uint8_t Channel)
+ {
+ AVR32_PM.mcctrl &= ~(1 << (AVR32_PM_MCCTRL_OSC0EN_OFFSET + Channel));
+ }
+
+ /** Starts the given PLL of the UC3 microcontroller, with the given options. This routine blocks until the PLL is ready for use.
+ *
+ * \attention The output frequency must be equal to or greater than the source frequency.
+ *
+ * \param[in] Channel Index of the PLL to start.
+ * \param[in] Source Clock source for the PLL, a value from \ref UC3_System_ClockSource_t.
+ * \param[in] SourceFreq Frequency of the PLL's clock source, in Hz.
+ * \param[in] Frequency Target frequency of the PLL's output.
+ *
+ * \return Boolean \c true if the PLL was successfully started, \c false if invalid parameters specified.
+ */
+ static inline bool UC3CLK_StartPLL(const uint8_t Channel,
+ const uint8_t Source,
+ const uint32_t SourceFreq,
+ const uint32_t Frequency) ATTR_ALWAYS_INLINE;
+ static inline bool UC3CLK_StartPLL(const uint8_t Channel,
+ const uint8_t Source,
+ const uint32_t SourceFreq,
+ const uint32_t Frequency)
+ {
+ if (SourceFreq > Frequency)
+ return false;
+
+ switch (Source)
+ {
+ case CLOCK_SRC_OSC0:
+ AVR32_PM.PLL[Channel].pllosc = 0;
+ break;
+ case CLOCK_SRC_OSC1:
+ AVR32_PM.PLL[Channel].pllosc = 1;
+ break;
+ default:
+ return false;
+ }
+
+ AVR32_PM.PLL[Channel].pllmul = (Frequency / SourceFreq) ? (((Frequency / SourceFreq) - 1) / 2) : 0;
+ AVR32_PM.PLL[Channel].plldiv = 0;
+ AVR32_PM.PLL[Channel].pllen = true;
+
+ while (!(AVR32_PM.poscsr & (1 << (AVR32_PM_POSCSR_LOCK0_OFFSET + Channel))));
+ return true;
+ }
+
+ /** Stops the given PLL of the UC3 microcontroller.
+ *
+ * \param[in] Channel Index of the PLL to stop.
+ */
+ static inline void UC3CLK_StopPLL(const uint8_t Channel) ATTR_ALWAYS_INLINE;
+ static inline void UC3CLK_StopPLL(const uint8_t Channel)
+ {
+ AVR32_PM.PLL[Channel].pllen = false;
+ }
+
+ /** Starts the given Generic Clock of the UC3 microcontroller, with the given options.
+ *
+ * \param[in] Channel Index of the Generic Clock to start.
+ * \param[in] Source Clock source for the Generic Clock, a value from \ref UC3_System_ClockSource_t.
+ * \param[in] SourceFreq Frequency of the Generic Clock's clock source, in Hz.
+ * \param[in] Frequency Target frequency of the Generic Clock's output.
+ *
+ * \return Boolean \c true if the Generic Clock was successfully started, \c false if invalid parameters specified.
+ */
+ static inline bool UC3CLK_StartGenericClock(const uint8_t Channel,
+ const uint8_t Source,
+ const uint32_t SourceFreq,
+ const uint32_t Frequency) ATTR_ALWAYS_INLINE;
+ static inline bool UC3CLK_StartGenericClock(const uint8_t Channel,
+ const uint8_t Source,
+ const uint32_t SourceFreq,
+ const uint32_t Frequency)
+ {
+ if (Channel >= AVR32_PM_GCLK_NUM)
+ return false;
+
+ if (SourceFreq < Frequency)
+ return false;
+
+ switch (Source)
+ {
+ case CLOCK_SRC_OSC0:
+ AVR32_PM.GCCTRL[Channel].pllsel = false;
+ AVR32_PM.GCCTRL[Channel].oscsel = 0;
+ break;
+ case CLOCK_SRC_OSC1:
+ AVR32_PM.GCCTRL[Channel].pllsel = false;
+ AVR32_PM.GCCTRL[Channel].oscsel = 1;
+ break;
+ case CLOCK_SRC_PLL0:
+ AVR32_PM.GCCTRL[Channel].pllsel = true;
+ AVR32_PM.GCCTRL[Channel].oscsel = 0;
+ break;
+ case CLOCK_SRC_PLL1:
+ AVR32_PM.GCCTRL[Channel].pllsel = true;
+ AVR32_PM.GCCTRL[Channel].oscsel = 1;
+ break;
+ default:
+ return false;
+ }
+
+ AVR32_PM.GCCTRL[Channel].diven = (SourceFreq > Frequency) ? true : false;
+ AVR32_PM.GCCTRL[Channel].div = (((SourceFreq / Frequency) - 1) / 2);
+ AVR32_PM.GCCTRL[Channel].cen = true;
+
+ return true;
+ }
+
+ /** Stops the given generic clock of the UC3 microcontroller.
+ *
+ * \param[in] Channel Index of the generic clock to stop.
+ *
+ * \return Boolean \c true if the generic clock was successfully stopped, \c false if invalid parameters specified.
+ */
+ static inline bool UC3CLK_StopGenericClock(const uint8_t Channel) ATTR_ALWAYS_INLINE;
+ static inline bool UC3CLK_StopGenericClock(const uint8_t Channel)
+ {
+ if (Channel >= AVR32_PM_GCLK_NUM)
+ return false;
+
+ AVR32_PM.GCCTRL[Channel].cen = false;
+
+ return true;
+ }
+
+ /** Sets the clock source for the main microcontroller core. The given clock source should be configured
+ * and ready for use before this function is called.
+ *
+ * This function will configure the FLASH controller's wait states automatically to suit the given clock source.
+ *
+ * \param[in] Source Clock source for the CPU core, a value from \ref UC3_System_ClockSource_t.
+ * \param[in] SourceFreq Frequency of the CPU core's clock source, in Hz.
+ *
+ * \return Boolean \c true if the CPU core clock was successfully altered, \c false if invalid parameters specified.
+ */
+ static inline bool UC3CLK_SetCPUClockSource(const uint8_t Source,
+ const uint32_t SourceFreq) ATTR_ALWAYS_INLINE;
+ static inline bool UC3CLK_SetCPUClockSource(const uint8_t Source,
+ const uint32_t SourceFreq)
+ {
+ if (SourceFreq > AVR32_PM_CPU_MAX_FREQ)
+ return false;
+
+ AVR32_FLASHC.FCR.fws = (SourceFreq > AVR32_FLASHC_FWS_0_MAX_FREQ) ? true : false;
+
+ switch (Source)
+ {
+ #if defined(AVR32_PM_MCCTRL_MCSEL_SLOW)
+ case CLOCK_SRC_SLOW_CLK:
+ AVR32_PM.MCCTRL.mcsel = AVR32_PM_MCCTRL_MCSEL_SLOW;
+ break;
+ #endif
+ #if defined(AVR32_PM_MCCTRL_MCSEL_OSC0)
+ case CLOCK_SRC_OSC0:
+ AVR32_PM.MCCTRL.mcsel = AVR32_PM_MCCTRL_MCSEL_OSC0;
+ break;
+ #endif
+ #if defined(AVR32_PM_MCCTRL_MCSEL_PLL0)
+ case CLOCK_SRC_PLL0:
+ AVR32_PM.MCCTRL.mcsel = AVR32_PM_MCCTRL_MCSEL_PLL0;
+ break;
+ #endif
+ default:
+ return false;
+ }
+
+ return true;
+ }
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/UC3/Exception.S b/tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/UC3/Exception.S
new file mode 100644
index 000000000..3a5f24005
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/UC3/Exception.S
@@ -0,0 +1,128 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#if defined(__AVR32__)
+#include <avr32/io.h>
+
+.section .exception_handlers, "ax", @progbits
+
+// ================= EXCEPTION TABLE ================
+.balign 0x200
+.global EVBA_Table
+EVBA_Table:
+
+.org 0x000
+Exception_Unrecoverable_Exception:
+ rjmp $
+.org 0x004
+Exception_TLB_Multiple_Hit:
+ rjmp $
+.org 0x008
+Exception_Bus_Error_Data_Fetch:
+ rjmp $
+.org 0x00C
+Exception_Bus_Error_Instruction_Fetch:
+ rjmp $
+.org 0x010
+Exception_NMI:
+ rjmp $
+.org 0x014
+Exception_Instruction_Address:
+ rjmp $
+.org 0x018
+Exception_ITLB_Protection:
+ rjmp $
+.org 0x01C
+Exception_OCD_Breakpoint:
+ rjmp $
+.org 0x020
+Exception_Illegal_Opcode:
+ rjmp $
+.org 0x024
+Exception_Unimplemented_Instruction:
+ rjmp $
+.org 0x028
+Exception_Privilege_Violation:
+ rjmp $
+.org 0x02C
+Exception_Floating_Point:
+ rjmp $
+.org 0x030
+Exception_Coprocessor_Absent:
+ rjmp $
+.org 0x034
+Exception_Data_Address_Read:
+ rjmp $
+.org 0x038
+Exception_Data_Address_Write:
+ rjmp $
+.org 0x03C
+Exception_DTLB_Protection_Read:
+ rjmp $
+.org 0x040
+Exception_DTLB_Protection_Write:
+ rjmp $
+.org 0x044
+Exception_DTLB_Modified:
+ rjmp $
+.org 0x050
+Exception_ITLB_Miss:
+ rjmp $
+.org 0x060
+Exception_DTLB_Miss_Read:
+ rjmp $
+.org 0x070
+Exception_DTLB_Miss_Write:
+ rjmp $
+.org 0x100
+Exception_Supervisor_Call:
+ rjmp $
+// ============== END OF EXCEPTION TABLE =============
+
+// ============= GENERAL INTERRUPT HANDLER ===========
+.balign 4
+.irp Level, 0, 1, 2, 3
+Exception_INT\Level:
+ mov r12, \Level
+ call INTC_GetInterruptHandler
+ mov pc, r12
+.endr
+// ========= END OF GENERAL INTERRUPT HANDLER ========
+
+// ====== GENERAL INTERRUPT HANDLER OFFSET TABLE ======
+.balign 4
+.global Autovector_Table
+Autovector_Table:
+.irp Level, 0, 1, 2, 3
+ .word ((AVR32_INTC_INT0 + \Level) << AVR32_INTC_IPR_INTLEVEL_OFFSET) | (Exception_INT\Level - EVBA_Table)
+.endr
+// === END OF GENERAL INTERRUPT HANDLER OFFSET TABLE ===
+
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/UC3/InterruptManagement.c b/tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/UC3/InterruptManagement.c
new file mode 100644
index 000000000..80d193f12
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/UC3/InterruptManagement.c
@@ -0,0 +1,62 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "../../Common/Common.h"
+#if (ARCH == ARCH_UC3)
+
+#define __INCLUDE_FROM_INTMANAGEMENT_C
+#include "InterruptManagement.h"
+
+/** Interrupt vector table, containing the ISR to call for each interrupt group */
+InterruptHandlerPtr_t InterruptHandlers[AVR32_INTC_NUM_INT_GRPS];
+
+/** ISR for unhandled interrupt groups */
+ISR(Unhandled_Interrupt)
+{
+ for (;;);
+}
+
+InterruptHandlerPtr_t INTC_GetInterruptHandler(const uint_reg_t InterruptLevel)
+{
+ return InterruptHandlers[AVR32_INTC.icr[AVR32_INTC_INT3 - InterruptLevel]];
+}
+
+void INTC_Init(void)
+{
+ for (uint8_t InterruptGroup = 0; InterruptGroup < AVR32_INTC_NUM_INT_GRPS; InterruptGroup++)
+ {
+ InterruptHandlers[InterruptGroup] = Unhandled_Interrupt;
+ AVR32_INTC.ipr[InterruptGroup] = Autovector_Table[AVR32_INTC_INT0];
+ }
+
+ __builtin_mtsr(AVR32_EVBA, (uintptr_t)&EVBA_Table);
+}
+
+#endif
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/UC3/InterruptManagement.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/UC3/InterruptManagement.h
new file mode 100644
index 000000000..90198cddd
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/UC3/InterruptManagement.h
@@ -0,0 +1,174 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Interrupt Controller Driver for the AVR32 UC3 microcontrollers.
+ *
+ * Interrupt controller driver for the AVR32 UC3 microcontrollers, for the configuration of interrupt
+ * handlers within the device.
+ */
+
+/** \ingroup Group_PlatformDrivers_UC3
+ * \defgroup Group_PlatformDrivers_UC3Interrupts Interrupt Controller Driver - LUFA/Platform/UC3/InterruptManagement.h
+ * \brief Interrupt Controller Driver for the AVR32 UC3 microcontrollers.
+ *
+ * \section Sec_PlatformDrivers_UC3Interrupts_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - LUFA/Platform/UC3/InterruptManagement.c <i>(Makefile source module name: LUFA_SRC_PLATFORM)</i>
+ * - LUFA/Platform/UC3/Exception.S <i>(Makefile source module name: LUFA_SRC_PLATFORM)</i>
+ *
+ * \section Sec_PlatformDrivers_UC3Interrupts_ModDescription Module Description
+ * Interrupt controller driver for the AVR32 UC3 microcontrollers, for the configuration of interrupt
+ * handlers within the device.
+ *
+ * Usage Example:
+ * \code
+ * #include <LUFA/Platform/UC3/InterruptManagement.h>
+ *
+ * ISR(USB_Group_IRQ_Handler)
+ * {
+ * // USB group handler code here
+ * }
+ *
+ * void main(void)
+ * {
+ * INTC_Init();
+ * INTC_RegisterGroupHandler(INTC_IRQ_GROUP(AVR32_USBB_IRQ), AVR32_INTC_INT0, USB_Group_IRQ_Handler);
+ * }
+ * \endcode
+ *
+ * @{
+ */
+
+#ifndef _UC3_INTERRUPT_MANAGEMENT_H_
+#define _UC3_INTERRUPT_MANAGEMENT_H_
+
+ /* Includes: */
+ #include "../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Private Interface - For use in library only: */
+ #if !defined(__DOXYGEN__)
+ /* Type Defines: */
+ typedef void (*InterruptHandlerPtr_t)(void);
+
+ /* External Variables: */
+ #if defined(__INCLUDE_FROM_INTMANAGEMENT_C)
+ extern const void EVBA_Table;
+ #endif
+ extern InterruptHandlerPtr_t InterruptHandlers[AVR32_INTC_NUM_INT_GRPS];
+ extern const uint32_t Autovector_Table[];
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Converts a given interrupt index into its associated interrupt group.
+ *
+ * \param[in] IRQIndex Index of the interrupt request to convert.
+ *
+ * \return Interrupt group number associated with the interrupt index.
+ */
+ #define INTC_IRQ_GROUP(IRQIndex) (IRQIndex / 32)
+
+ /** Converts a given interrupt index into its associated interrupt line.
+ *
+ * \param[in] IRQIndex Index of the interrupt request to convert.
+ *
+ * \return Interrupt line number associated with the interrupt index.
+ */
+ #define INTC_IRQ_LINE(IRQIndex) (IRQIndex % 32)
+
+ /* Function Prototypes: */
+ /** Initializes the interrupt controller ready to handle interrupts. This must be called at the
+ * start of the user program before any interrupts are registered or enabled.
+ */
+ void INTC_Init(void);
+
+ /** Retrieves the associated interrupt handler for the interrupt group currently being fired. This
+ * is called directly from the exception handler routine before dispatching to the ISR.
+ *
+ * \param[in] InterruptLevel Priority level of the interrupt.
+ *
+ * \return Pointer to the associated interrupt handler function, or NULL if no handler set.
+ */
+ InterruptHandlerPtr_t INTC_GetInterruptHandler(const uint_reg_t InterruptLevel);
+
+ /* Inline Functions: */
+ /** Registers a handler for a given interrupt group. On the AVR32 UC3 devices, interrupts are grouped by
+ * peripheral. To save on SRAM used, a single ISR handles all interrupt lines within a single group - to
+ * determine the exact line that has interrupted within the group ISR handler, use \ref INTC_GetGroupInterrupts().
+ *
+ * If multiple interrupts with the same group are registered, the last registered handler will become the
+ * handler called for interrupts raised within that group.
+ *
+ * To obtain the group number of a specific interrupt index, use the \ref INTC_IRQ_GROUP() macro.
+ *
+ * \param[in] GroupNumber Group number of the interrupt group to register a handler for.
+ * \param[in] InterruptLevel Priority level for the specified interrupt, a \c AVR32_INTC_INT* mask.
+ * \param[in] Handler Address of the ISR handler for the interrupt group.
+ */
+ static inline void INTC_RegisterGroupHandler(const uint16_t GroupNumber,
+ const uint8_t InterruptLevel,
+ const InterruptHandlerPtr_t Handler) ATTR_ALWAYS_INLINE;
+ static inline void INTC_RegisterGroupHandler(const uint16_t GroupNumber,
+ const uint8_t InterruptLevel,
+ const InterruptHandlerPtr_t Handler)
+ {
+ InterruptHandlers[GroupNumber] = Handler;
+ AVR32_INTC.ipr[GroupNumber] = Autovector_Table[InterruptLevel];
+ }
+
+ /** Retrieves the pending interrupts for a given interrupt group. The result of this function should be masked
+ * against interrupt request indexes converted to a request line number via the \ref INTC_IRQ_LINE() macro. To
+ * obtain the group number of a given interrupt request, use the \ref INTC_IRQ_GROUP() macro.
+ *
+ * \param[in] GroupNumber Group number of the interrupt group to check.
+ *
+ * \return Mask of pending interrupt lines for the given interrupt group.
+ */
+ static inline uint_reg_t INTC_GetGroupInterrupts(const uint16_t GroupNumber) ATTR_ALWAYS_INLINE;
+ static inline uint_reg_t INTC_GetGroupInterrupts(const uint16_t GroupNumber)
+ {
+ return AVR32_INTC.irr[GroupNumber];
+ }
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/UC3/UC3ExperimentalInfo.txt b/tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/UC3/UC3ExperimentalInfo.txt
new file mode 100644
index 000000000..8aadb3ed7
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/UC3/UC3ExperimentalInfo.txt
@@ -0,0 +1 @@
+Please note that the UC3 architecture support is EXPERIMENTAL at this time, and may be non-functional/incomplete in some areas. Please refer to the Known Issues section of the LUFA manual. \ No newline at end of file
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/XMEGA/ClockManagement.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/XMEGA/ClockManagement.h
new file mode 100644
index 000000000..9edaa7223
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/XMEGA/ClockManagement.h
@@ -0,0 +1,397 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief Module Clock Driver for the AVR USB XMEGA microcontrollers.
+ *
+ * Clock management driver for the AVR USB XMEGA microcontrollers. This driver allows for the configuration
+ * of the various clocks within the device to clock the various peripherals.
+ */
+
+/** \ingroup Group_PlatformDrivers_XMEGA
+ * \defgroup Group_PlatformDrivers_XMEGAClocks Clock Management Driver - LUFA/Platform/XMEGA/ClockManagement.h
+ * \brief Module Clock Driver for the AVR USB XMEGA microcontrollers.
+ *
+ * \section Sec_PlatformDrivers_XMEGAClocks_Dependencies Module Source Dependencies
+ * The following files must be built with any user project that uses this module:
+ * - None
+ *
+ * \section Sec_PlatformDrivers_XMEGAClocks_ModDescription Module Description
+ * Clock management driver for the AVR USB XMEGA microcontrollers. This driver allows for the configuration
+ * of the various clocks within the device to clock the various peripherals.
+ *
+ * Usage Example:
+ * \code
+ * #include <LUFA/Platform/XMEGA/ClockManagement.h>
+ *
+ * void main(void)
+ * {
+ * // Start the PLL to multiply the 2MHz RC oscillator to F_CPU and switch the CPU core to run from it
+ * XMEGACLK_StartPLL(CLOCK_SRC_INT_RC2MHZ, 2000000, F_CPU);
+ * XMEGACLK_SetCPUClockSource(CLOCK_SRC_PLL);
+ *
+ * // Start the 32MHz internal RC oscillator and start the DFLL to increase it to F_USB using the USB SOF as a reference
+ * XMEGACLK_StartInternalOscillator(CLOCK_SRC_INT_RC32MHZ);
+ * XMEGACLK_StartDFLL(CLOCK_SRC_INT_RC32MHZ, DFLL_REF_INT_USBSOF, F_USB);
+ * }
+ * \endcode
+ *
+ * @{
+ */
+
+#ifndef _XMEGA_CLOCK_MANAGEMENT_H_
+#define _XMEGA_CLOCK_MANAGEMENT_H_
+
+ /* Includes: */
+ #include "../../Common/Common.h"
+
+ /* Enable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ extern "C" {
+ #endif
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Enum for the possible external oscillator frequency ranges. */
+ enum XMEGA_Extern_OSC_ClockFrequency_t
+ {
+ EXOSC_FREQ_2MHZ_MAX = OSC_FRQRANGE_04TO2_gc, /**< External crystal oscillator equal to or slower than 2MHz. */
+ EXOSC_FREQ_9MHZ_MAX = OSC_FRQRANGE_2TO9_gc, /**< External crystal oscillator equal to or slower than 9MHz. */
+ EXOSC_FREQ_12MHZ_MAX = OSC_FRQRANGE_9TO12_gc, /**< External crystal oscillator equal to or slower than 12MHz. */
+ EXOSC_FREQ_16MHZ_MAX = OSC_FRQRANGE_12TO16_gc, /**< External crystal oscillator equal to or slower than 16MHz. */
+ };
+
+ /** Enum for the possible external oscillator startup times. */
+ enum XMEGA_Extern_OSC_ClockStartup_t
+ {
+ EXOSC_START_6CLK = OSC_XOSCSEL_EXTCLK_gc, /**< Wait 6 clock cycles before startup (external clock). */
+ EXOSC_START_32KCLK = OSC_XOSCSEL_32KHz_gc, /**< Wait 32K clock cycles before startup (32.768KHz crystal). */
+ EXOSC_START_256CLK = OSC_XOSCSEL_XTAL_256CLK_gc, /**< Wait 256 clock cycles before startup. */
+ EXOSC_START_1KCLK = OSC_XOSCSEL_XTAL_1KCLK_gc, /**< Wait 1K clock cycles before startup. */
+ EXOSC_START_16KCLK = OSC_XOSCSEL_XTAL_16KCLK_gc, /**< Wait 16K clock cycles before startup. */
+ };
+
+ /** Enum for the possible module clock sources. */
+ enum XMEGA_System_ClockSource_t
+ {
+ CLOCK_SRC_INT_RC2MHZ = 0, /**< Clock sourced from the Internal 2MHz RC Oscillator clock. */
+ CLOCK_SRC_INT_RC32MHZ = 1, /**< Clock sourced from the Internal 32MHz RC Oscillator clock. */
+ CLOCK_SRC_INT_RC32KHZ = 2, /**< Clock sourced from the Internal 32KHz RC Oscillator clock. */
+ CLOCK_SRC_XOSC = 3, /**< Clock sourced from the External Oscillator clock. */
+ CLOCK_SRC_PLL = 4, /**< Clock sourced from the Internal PLL clock. */
+ };
+
+ /** Enum for the possible DFLL clock reference sources. */
+ enum XMEGA_System_DFLLReference_t
+ {
+ DFLL_REF_INT_RC32KHZ = 0, /**< Reference clock sourced from the Internal 32KHz RC Oscillator clock. */
+ DFLL_REF_EXT_RC32KHZ = 1, /**< Reference clock sourced from the External 32KHz RC Oscillator clock connected to TOSC pins. */
+ DFLL_REF_INT_USBSOF = 2, /**< Reference clock sourced from the USB Start Of Frame packets. */
+ };
+
+ /* Inline Functions: */
+ /** Write a value to a location protected by the XMEGA CCP protection mechanism. This function uses inline assembly to ensure that
+ * the protected address is written to within four clock cycles of the CCP key being written.
+ *
+ * \param[in] Address Address to write to, a memory address protected by the CCP mechanism
+ * \param[in] Value Value to write to the protected location
+ */
+ static inline void XMEGACLK_CCP_Write(volatile void* Address, const uint8_t Value) ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
+ static inline void XMEGACLK_CCP_Write(volatile void* Address, const uint8_t Value)
+ {
+ __asm__ __volatile__ (
+ "out %0, __zero_reg__" "\n\t" /* Zero RAMPZ using fixed zero value register */
+ "movw r30, %1" "\n\t" /* Copy address to Z register pair */
+ "out %2, %3" "\n\t" /* Write key to CCP register */
+ "st Z, %4" "\n\t" /* Indirectly write value to address */
+ : /* No output operands */
+ : /* Input operands: */ "m" (RAMPZ), "e" (Address), "m" (CCP), "r" (CCP_IOREG_gc), "r" (Value)
+ : /* Clobbered registers: */ "r30", "r31"
+ );
+ }
+
+ /** Starts the external oscillator of the XMEGA microcontroller, with the given options. This routine blocks until
+ * the oscillator is ready for use.
+ *
+ * \param[in] FreqRange Frequency range of the external oscillator, a value from \ref XMEGA_Extern_OSC_ClockFrequency_t.
+ * \param[in] Startup Startup time of the external oscillator, a value from \ref XMEGA_Extern_OSC_ClockStartup_t.
+ *
+ * \return Boolean \c true if the external oscillator was successfully started, \c false if invalid parameters specified.
+ */
+ static inline bool XMEGACLK_StartExternalOscillator(const uint8_t FreqRange,
+ const uint8_t Startup) ATTR_ALWAYS_INLINE;
+ static inline bool XMEGACLK_StartExternalOscillator(const uint8_t FreqRange,
+ const uint8_t Startup)
+ {
+ OSC.XOSCCTRL = (FreqRange | ((Startup == EXOSC_START_32KCLK) ? OSC_X32KLPM_bm : 0) | Startup);
+ OSC.CTRL |= OSC_XOSCEN_bm;
+
+ while (!(OSC.STATUS & OSC_XOSCRDY_bm));
+ return true;
+ }
+
+ /** Stops the external oscillator of the XMEGA microcontroller. */
+ static inline void XMEGACLK_StopExternalOscillator(void) ATTR_ALWAYS_INLINE;
+ static inline void XMEGACLK_StopExternalOscillator(void)
+ {
+ OSC.CTRL &= ~OSC_XOSCEN_bm;
+ }
+
+ /** Starts the given internal oscillator of the XMEGA microcontroller, with the given options. This routine blocks until
+ * the oscillator is ready for use.
+ *
+ * \param[in] Source Internal oscillator to start, a value from \ref XMEGA_System_ClockSource_t.
+ *
+ * \return Boolean \c true if the internal oscillator was successfully started, \c false if invalid parameters specified.
+ */
+ static inline bool XMEGACLK_StartInternalOscillator(const uint8_t Source) ATTR_ALWAYS_INLINE;
+ static inline bool XMEGACLK_StartInternalOscillator(const uint8_t Source)
+ {
+ switch (Source)
+ {
+ case CLOCK_SRC_INT_RC2MHZ:
+ OSC.CTRL |= OSC_RC2MEN_bm;
+ while (!(OSC.STATUS & OSC_RC2MRDY_bm));
+ return true;
+ case CLOCK_SRC_INT_RC32MHZ:
+ OSC.CTRL |= OSC_RC32MEN_bm;
+ while (!(OSC.STATUS & OSC_RC32MRDY_bm));
+ return true;
+ case CLOCK_SRC_INT_RC32KHZ:
+ OSC.CTRL |= OSC_RC32KEN_bm;
+ while (!(OSC.STATUS & OSC_RC32KRDY_bm));
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /** Stops the given internal oscillator of the XMEGA microcontroller.
+ *
+ * \param[in] Source Internal oscillator to stop, a value from \ref XMEGA_System_ClockSource_t.
+ *
+ * \return Boolean \c true if the internal oscillator was successfully stopped, \c false if invalid parameters specified.
+ */
+ static inline bool XMEGACLK_StopInternalOscillator(const uint8_t Source) ATTR_ALWAYS_INLINE;
+ static inline bool XMEGACLK_StopInternalOscillator(const uint8_t Source)
+ {
+ switch (Source)
+ {
+ case CLOCK_SRC_INT_RC2MHZ:
+ OSC.CTRL &= ~OSC_RC2MEN_bm;
+ return true;
+ case CLOCK_SRC_INT_RC32MHZ:
+ OSC.CTRL &= ~OSC_RC32MEN_bm;
+ return true;
+ case CLOCK_SRC_INT_RC32KHZ:
+ OSC.CTRL &= ~OSC_RC32KEN_bm;
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /** Starts the PLL of the XMEGA microcontroller, with the given options. This routine blocks until the PLL is ready for use.
+ *
+ * \attention The output frequency must be equal to or greater than the source frequency.
+ *
+ * \param[in] Source Clock source for the PLL, a value from \ref XMEGA_System_ClockSource_t.
+ * \param[in] SourceFreq Frequency of the PLL's clock source, in Hz.
+ * \param[in] Frequency Target frequency of the PLL's output.
+ *
+ * \return Boolean \c true if the PLL was successfully started, \c false if invalid parameters specified.
+ */
+ static inline bool XMEGACLK_StartPLL(const uint8_t Source,
+ const uint32_t SourceFreq,
+ const uint32_t Frequency) ATTR_ALWAYS_INLINE;
+ static inline bool XMEGACLK_StartPLL(const uint8_t Source,
+ const uint32_t SourceFreq,
+ const uint32_t Frequency)
+ {
+ uint8_t MulFactor = (Frequency / SourceFreq);
+
+ if (SourceFreq > Frequency)
+ return false;
+
+ if (MulFactor > 31)
+ return false;
+
+ switch (Source)
+ {
+ case CLOCK_SRC_INT_RC2MHZ:
+ OSC.PLLCTRL = (OSC_PLLSRC_RC2M_gc | MulFactor);
+ break;
+ case CLOCK_SRC_INT_RC32MHZ:
+ OSC.PLLCTRL = (OSC_PLLSRC_RC32M_gc | MulFactor);
+ break;
+ case CLOCK_SRC_XOSC:
+ OSC.PLLCTRL = (OSC_PLLSRC_XOSC_gc | MulFactor);
+ break;
+ default:
+ return false;
+ }
+
+ OSC.CTRL |= OSC_PLLEN_bm;
+
+ while (!(OSC.STATUS & OSC_PLLRDY_bm));
+ return true;
+ }
+
+ /** Stops the PLL of the XMEGA microcontroller. */
+ static inline void XMEGACLK_StopPLL(void) ATTR_ALWAYS_INLINE;
+ static inline void XMEGACLK_StopPLL(void)
+ {
+ OSC.CTRL &= ~OSC_PLLEN_bm;
+ }
+
+ /** Starts the DFLL of the XMEGA microcontroller, with the given options.
+ *
+ * \param[in] Source RC Clock source for the DFLL, a value from \ref XMEGA_System_ClockSource_t.
+ * \param[in] Reference Reference clock source for the DFLL, an value from \ref XMEGA_System_DFLLReference_t.
+ * \param[in] Frequency Target frequency of the DFLL's output.
+ *
+ * \return Boolean \c true if the DFLL was successfully started, \c false if invalid parameters specified.
+ */
+ static inline bool XMEGACLK_StartDFLL(const uint8_t Source,
+ const uint8_t Reference,
+ const uint32_t Frequency) ATTR_ALWAYS_INLINE;
+ static inline bool XMEGACLK_StartDFLL(const uint8_t Source,
+ const uint8_t Reference,
+ const uint32_t Frequency)
+ {
+ uint16_t DFLLCompare = (Frequency / 1024);
+
+ switch (Source)
+ {
+ case CLOCK_SRC_INT_RC2MHZ:
+ OSC.DFLLCTRL |= (Reference << OSC_RC2MCREF_bp);
+ DFLLRC2M.COMP1 = (DFLLCompare & 0xFF);
+ DFLLRC2M.COMP2 = (DFLLCompare >> 8);
+ DFLLRC2M.CTRL = DFLL_ENABLE_bm;
+ break;
+ case CLOCK_SRC_INT_RC32MHZ:
+ OSC.DFLLCTRL |= (Reference << OSC_RC32MCREF_gp);
+ DFLLRC32M.COMP1 = (DFLLCompare & 0xFF);
+ DFLLRC32M.COMP2 = (DFLLCompare >> 8);
+
+ if (Reference == DFLL_REF_INT_USBSOF)
+ {
+ NVM.CMD = NVM_CMD_READ_CALIB_ROW_gc;
+ DFLLRC32M.CALA = pgm_read_byte(offsetof(NVM_PROD_SIGNATURES_t, USBRCOSCA));
+ DFLLRC32M.CALB = pgm_read_byte(offsetof(NVM_PROD_SIGNATURES_t, USBRCOSC));
+ NVM.CMD = 0;
+ }
+
+ DFLLRC32M.CTRL = DFLL_ENABLE_bm;
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+ }
+
+ /** Stops the given DFLL of the XMEGA microcontroller.
+ *
+ * \param[in] Source RC Clock source for the DFLL to be stopped, a value from \ref XMEGA_System_ClockSource_t.
+ *
+ * \return Boolean \c true if the DFLL was successfully stopped, \c false if invalid parameters specified.
+ */
+ static inline bool XMEGACLK_StopDFLL(const uint8_t Source) ATTR_ALWAYS_INLINE;
+ static inline bool XMEGACLK_StopDFLL(const uint8_t Source)
+ {
+ switch (Source)
+ {
+ case CLOCK_SRC_INT_RC2MHZ:
+ DFLLRC2M.CTRL = 0;
+ break;
+ case CLOCK_SRC_INT_RC32MHZ:
+ DFLLRC32M.CTRL = 0;
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+ }
+
+ /** Sets the clock source for the main microcontroller core. The given clock source should be configured
+ * and ready for use before this function is called.
+ *
+ * \param[in] Source Clock source for the CPU core, a value from \ref XMEGA_System_ClockSource_t.
+ *
+ * \return Boolean \c true if the CPU core clock was successfully altered, \c false if invalid parameters specified.
+ */
+ static inline bool XMEGACLK_SetCPUClockSource(const uint8_t Source) ATTR_ALWAYS_INLINE;
+ static inline bool XMEGACLK_SetCPUClockSource(const uint8_t Source)
+ {
+ uint8_t ClockSourceMask = 0;
+
+ switch (Source)
+ {
+ case CLOCK_SRC_INT_RC2MHZ:
+ ClockSourceMask = CLK_SCLKSEL_RC2M_gc;
+ break;
+ case CLOCK_SRC_INT_RC32MHZ:
+ ClockSourceMask = CLK_SCLKSEL_RC32M_gc;
+ break;
+ case CLOCK_SRC_INT_RC32KHZ:
+ ClockSourceMask = CLK_SCLKSEL_RC32K_gc;
+ break;
+ case CLOCK_SRC_XOSC:
+ ClockSourceMask = CLK_SCLKSEL_XOSC_gc;
+ break;
+ case CLOCK_SRC_PLL:
+ ClockSourceMask = CLK_SCLKSEL_PLL_gc;
+ break;
+ default:
+ return false;
+ }
+
+ uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask();
+ GlobalInterruptDisable();
+
+ XMEGACLK_CCP_Write(&CLK.CTRL, ClockSourceMask);
+
+ SetGlobalInterruptMask(CurrentGlobalInt);
+
+ Delay_MS(1);
+ return (CLK.CTRL == ClockSourceMask);
+ }
+
+ /* Disable C linkage for C++ Compilers: */
+ #if defined(__cplusplus)
+ }
+ #endif
+
+#endif
+
+/** @} */
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/XMEGA/XMEGAExperimentalInfo.txt b/tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/XMEGA/XMEGAExperimentalInfo.txt
new file mode 100644
index 000000000..42144aac4
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Platform/XMEGA/XMEGAExperimentalInfo.txt
@@ -0,0 +1 @@
+Please note that the XMEGA architecture support is EXPERIMENTAL at this time, and may be non-functional/incomplete in some areas. Please refer to the Known Issues section of the LUFA manual. \ No newline at end of file
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/Docbook/mshelp/placeholder.txt b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/Docbook/mshelp/placeholder.txt
new file mode 100644
index 000000000..486e9a427
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/Docbook/mshelp/placeholder.txt
@@ -0,0 +1 @@
+Copy the Microsoft HV1 Docbook transform contents into this directory (i.e. with the XSLT files in the current folder). The HV1 transform proposal can be found at http://sourceforge.net/tracker/?func=detail&aid=3610290&group_id=21935&atid=373750 .
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/Docbook/placeholder.txt b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/Docbook/placeholder.txt
new file mode 100644
index 000000000..c017acfd7
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/Docbook/placeholder.txt
@@ -0,0 +1 @@
+Copy the Docbook XSLT docbook-xsl-1.78.1 release contents into this directory (i.e. with the root Docbook files in the current folder). The Docbook releases can be found at http://sourceforge.net/projects/docbook/files/docbook-xsl/ .
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/HV1/helpcontentsetup.msha b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/HV1/helpcontentsetup.msha
new file mode 100644
index 000000000..cb1c4b9eb
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/HV1/helpcontentsetup.msha
@@ -0,0 +1,27 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>LUFA Help</title>
+ </head>
+ <body class="vendor-book">
+ <div class="details">
+ <span class="vendor">FourWalledCubicle</span>
+ <span class="product">LUFA</span>
+ <span class="name">LUFA Help</span>
+ <span class="locale">en-us</span>
+ </div>
+ <div class="package-list">
+ <div class="package">
+ <span class="name">LUFA</span>
+ <a class="current-link" href="lufa_studio_help.mshc">lufa_studio_help.mshc</a>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/HV1/lufa_docbook_transform.xslt b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/HV1/lufa_docbook_transform.xslt
new file mode 100644
index 000000000..2ebda6d5d
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/HV1/lufa_docbook_transform.xslt
@@ -0,0 +1,808 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+ <xsl:output method="xml" indent="no"/>
+
+ <xsl:param name="keyword.namespace" select="'Atmel.Language.C'"/>
+
+ <xsl:template name="generate.book.title">
+ <xsl:text>LUFA Library</xsl:text>
+ </xsl:template>
+
+ <xsl:template name="generate.book.id">
+ <xsl:param name="book.title"/>
+ <xsl:choose>
+ <xsl:when test="@id">
+ <xsl:value-of select="@id"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="translate($book.title, ' ','')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="generate.index.id">
+ <xsl:param name="name"/>
+ <xsl:variable name="book.title">
+ <xsl:call-template name="generate.book.title"/>
+ </xsl:variable>
+ <xsl:variable name="book.id">
+ <xsl:call-template name="generate.book.id">
+ <xsl:with-param name="book.title" select="$book.title"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <indexterm id="{$keyword.namespace}.{$name}">
+ <primary>
+ <xsl:value-of select="$book.title"/>
+ </primary>
+ <secondary>
+ <xsl:value-of select="$name"/>
+ </secondary>
+ </indexterm>
+ </xsl:template>
+
+ <xsl:template match="doxygen">
+ <xsl:variable name="book.title">
+ <xsl:call-template name="generate.book.title"/>
+ </xsl:variable>
+
+ <xsl:variable name="book.id">
+ <xsl:call-template name="generate.book.id">
+ <xsl:with-param name="book.title" select="$book.title"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <book id="{$book.id}">
+ <title>
+ <xsl:value-of select="$book.title"/>
+ </title>
+
+ <!-- Add index chapter -->
+ <xsl:apply-templates select="compounddef[@kind = 'page' and @id = 'indexpage']">
+ <xsl:with-param name="element.type" select="'chapter'"/>
+ <xsl:with-param name="page.title" select="'Library Information'"/>
+ </xsl:apply-templates>
+
+ <!-- Add free-floating chapters -->
+ <xsl:apply-templates select="compounddef[@kind = 'page' and not(@id = 'indexpage') and not(//innerpage/@refid = @id)]">
+ <xsl:with-param name="element.type" select="'chapter'"/>
+ </xsl:apply-templates>
+
+ <!-- Add Modules chapter -->
+ <chapter>
+ <title>Modules</title>
+ <xsl:apply-templates select="compounddef[@kind = 'group' and not(//innergroup/@refid = @id)]"/>
+ </chapter>
+ </book>
+ </xsl:template>
+
+ <xsl:template match="compounddef[@kind = 'page']">
+ <xsl:param name="element.type" select="'section'"/>
+ <xsl:param name="page.title" select="title"/>
+
+ <xsl:element name="{$element.type}">
+ <xsl:attribute name="id">
+ <xsl:value-of select="@id"/>
+ </xsl:attribute>
+
+ <xsl:variable name="name">
+ <xsl:text>LUFA.</xsl:text>
+ <xsl:value-of select="translate(compoundname, '_', '.')"/>
+ </xsl:variable>
+
+ <xsl:call-template name="generate.index.id">
+ <xsl:with-param name="name" select="$name"/>
+ </xsl:call-template>
+
+ <title>
+ <xsl:value-of select="$page.title"/>
+ </title>
+
+ <xsl:apply-templates select="detaileddescription"/>
+
+ <xsl:if test="not(innerpage) and count(detaileddescription//sect1)">
+ <para>
+ <emphasis role="bold">Subsections:</emphasis>
+ <itemizedlist>
+ <xsl:for-each select="detaileddescription//sect1">
+ <listitem>
+ <link linkend="{@id}">
+ <xsl:value-of select="title"/>
+ </link>
+ </listitem>
+ </xsl:for-each>
+ </itemizedlist>
+ </para>
+ </xsl:if>
+
+ <xsl:for-each select="innerpage">
+ <xsl:apply-templates select="ancestor::*/compounddef[@kind = 'page' and @id = current()/@refid]"/>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="compounddef[@kind = 'group']">
+ <section id="{@id}">
+ <title>
+ <xsl:value-of select="title"/>
+ </title>
+
+ <xsl:variable name="name">
+ <xsl:text>LUFA.</xsl:text>
+ <xsl:value-of select="translate(compoundname, '_', '.')"/>
+ </xsl:variable>
+
+ <xsl:call-template name="generate.index.id">
+ <xsl:with-param name="name" select="$name"/>
+ </xsl:call-template>
+
+ <xsl:apply-templates select="detaileddescription"/>
+
+ <xsl:if test="count(innergroup)">
+ <para>
+ <emphasis role="bold">Subgroups:</emphasis>
+ <itemizedlist>
+ <xsl:for-each select="innergroup">
+ <listitem>
+ <link linkend="{@refid}">
+ <xsl:value-of select="text()"/>
+ </link>
+ </listitem>
+ </xsl:for-each>
+ </itemizedlist>
+ </para>
+ </xsl:if>
+
+ <xsl:apply-templates select="sectiondef"/>
+
+ <xsl:for-each select="innerclass">
+ <xsl:apply-templates select="ancestor::*/compounddef[@id = current()/@refid]"/>
+ </xsl:for-each>
+
+ <xsl:for-each select="innergroup">
+ <xsl:apply-templates select="ancestor::*/compounddef[@kind = 'group' and @id = current()/@refid]"/>
+ </xsl:for-each>
+ </section>
+ </xsl:template>
+
+ <xsl:template match="compounddef[@kind = 'struct' or @kind = 'union']">
+ <xsl:variable name="name" select="compoundname"/>
+
+ <section id="{@id}" xreflabel="{$name}">
+ <title>
+ <xsl:choose>
+ <xsl:when test="@kind = 'struct'">
+ <xsl:text>Struct </xsl:text>
+ </xsl:when>
+
+ <xsl:when test="@kind = 'union'">
+ <xsl:text>Union </xsl:text>
+ </xsl:when>
+ </xsl:choose>
+
+ <xsl:value-of select="$name"/>
+ </title>
+
+ <xsl:call-template name="generate.index.id">
+ <xsl:with-param name="name" select="$name"/>
+ </xsl:call-template>
+
+ <xsl:apply-templates select="detaileddescription"/>
+
+ <xsl:for-each select="sectiondef[@kind = 'public-attrib']">
+ <table>
+ <title>
+ <xsl:value-of select="$name"/>
+ </title>
+
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>Type</entry>
+ <entry>Name</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <xsl:for-each select="memberdef">
+ <row id="{@id}" xreflabel="{name}">
+ <entry>
+ <xsl:value-of select="type"/>
+ </entry>
+ <entry>
+ <xsl:value-of select="name"/>
+ <xsl:if test="starts-with(argsstring, '[')">
+ <xsl:text>[]</xsl:text>
+ </xsl:if>
+
+ <xsl:variable name="struct.element.name">
+ <xsl:value-of select="$name"/>
+ <xsl:text>.</xsl:text>
+ <xsl:value-of select="name"/>
+ </xsl:variable>
+
+ <xsl:call-template name="generate.index.id">
+ <xsl:with-param name="name" select="$struct.element.name"/>
+ </xsl:call-template>
+ </entry>
+ <entry>
+ <xsl:apply-templates select="detaileddescription"/>
+ </entry>
+ </row>
+ </xsl:for-each>
+ </tbody>
+ </tgroup>
+ </table>
+ </xsl:for-each>
+ </section>
+ </xsl:template>
+
+ <xsl:template match="memberdef[@kind = 'function']">
+ <section id="{@id}" xreflabel="{name}">
+ <title>
+ <xsl:text>Function </xsl:text>
+ <xsl:value-of select="name"/>
+ <xsl:text>()</xsl:text>
+ </title>
+
+ <xsl:call-template name="generate.index.id">
+ <xsl:with-param name="name" select="name"/>
+ </xsl:call-template>
+
+ <para>
+ <emphasis role="italic">
+ <xsl:value-of select="briefdescription"/>
+ </emphasis>
+ </para>
+
+ <programlisting language="c">
+ <emphasis role="keyword">
+ <xsl:value-of select="type"/>
+ </emphasis>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="name"/>
+ <xsl:text>(</xsl:text>
+
+ <xsl:choose>
+ <xsl:when test="not(param[1]/declname)">
+ <emphasis role="keyword">void</emphasis>
+ </xsl:when>
+
+ <xsl:otherwise>
+ <xsl:for-each select="param">
+ <xsl:if test="position() > 1">
+ <xsl:text>,</xsl:text>
+ </xsl:if>
+ <xsl:text>&#10;&#9;</xsl:text>
+ <emphasis role="keyword">
+ <xsl:value-of select="type"/>
+ </emphasis>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="declname"/>
+ </xsl:for-each>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:text>)</xsl:text>
+ </programlisting>
+
+ <xsl:apply-templates select="detaileddescription"/>
+ </section>
+ </xsl:template>
+
+ <xsl:template match="memberdef[@kind = 'enum']">
+ <section id="{@id}" xreflabel="{name}">
+ <title>
+ <xsl:text>Enum </xsl:text>
+ <xsl:value-of select="name"/>
+ </title>
+
+ <xsl:call-template name="generate.index.id">
+ <xsl:with-param name="name" select="name"/>
+ </xsl:call-template>
+
+ <xsl:apply-templates select="detaileddescription"/>
+
+ <table>
+ <title>Members</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>Enum Value</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <xsl:for-each select="enumvalue">
+ <row>
+ <entry>
+ <para id="{@id}" xreflabel="{name}">
+ <xsl:value-of select="name"/>
+
+ <xsl:call-template name="generate.index.id">
+ <xsl:with-param name="name" select="name"/>
+ </xsl:call-template>
+ </para>
+ </entry>
+ <entry>
+ <xsl:apply-templates select="detaileddescription"/>
+ </entry>
+ </row>
+ </xsl:for-each>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ </xsl:template>
+
+ <xsl:template match="memberdef[@kind = 'define']">
+ <section id="{@id}" xreflabel="{name}">
+ <title>
+ <xsl:text>Macro </xsl:text>
+ <xsl:value-of select="name"/>
+ </title>
+
+ <xsl:call-template name="generate.index.id">
+ <xsl:with-param name="name" select="name"/>
+ </xsl:call-template>
+
+ <programlisting language="c">
+ <emphasis role="preprocessor">
+ <xsl:text>#define </xsl:text>
+ <xsl:value-of select="name"/>
+ <xsl:if test="count(param) > 0">
+ <xsl:text>(</xsl:text>
+ <xsl:for-each select="param/defname">
+ <xsl:if test="position() > 1">
+ <xsl:text>,</xsl:text>
+ </xsl:if>
+ <xsl:value-of select="."/>
+ </xsl:for-each>
+ <xsl:text>)</xsl:text>
+ </xsl:if>
+ <xsl:text> </xsl:text>
+
+ <!-- Split long macro definitions across multiple lines -->
+ <xsl:if test="(string-length(initializer) > 50) or (count(param) > 0)">
+ <xsl:text>\&#10;&#9;</xsl:text>
+ </xsl:if>
+
+ <xsl:value-of select="initializer"/>
+ </emphasis>
+ <xsl:text> </xsl:text>
+ </programlisting>
+
+ <xsl:apply-templates select="detaileddescription"/>
+ </section>
+ </xsl:template>
+
+ <xsl:template match="memberdef[@kind = 'typedef']">
+ <section id="{@id}" xreflabel="{name}">
+ <title>
+ <xsl:text>Type </xsl:text>
+ <xsl:value-of select="name"/>
+ </title>
+
+ <xsl:call-template name="generate.index.id">
+ <xsl:with-param name="name" select="name"/>
+ </xsl:call-template>
+
+ <programlisting language="c">
+ <emphasis role="keyword">
+ <xsl:text>typedef </xsl:text>
+ <xsl:value-of select="type"/>
+ </emphasis>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="name"/>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="argsstring"/>
+ </programlisting>
+
+ <xsl:apply-templates select="detaileddescription"/>
+ </section>
+ </xsl:template>
+
+
+ <xsl:template match="memberdef[@kind = 'variable']">
+ <section id="{@id}" xreflabel="{name}">
+ <title>
+ <xsl:text>Variable </xsl:text>
+ <xsl:value-of select="name"/>
+ </title>
+
+ <xsl:call-template name="generate.index.id">
+ <xsl:with-param name="name" select="name"/>
+ </xsl:call-template>
+
+ <programlisting language="c">
+ <emphasis role="keyword">
+ <xsl:value-of select="type"/>
+ </emphasis>
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="name"/>
+ </programlisting>
+
+ <xsl:apply-templates select="detaileddescription"/>
+ </section>
+ </xsl:template>
+
+ <xsl:template match="linebreak | simplesectsep">
+ <!-- MUST be on two separate lines, as this is a *literal* newline -->
+ <literallayout>
+ </literallayout>
+ </xsl:template>
+
+ <xsl:template match="verbatim">
+ <programlisting>
+ <xsl:apply-templates/>
+ </programlisting>
+ </xsl:template>
+
+ <xsl:template match="sectiondef">
+ <para>
+ <xsl:value-of select="description"/>
+ </para>
+
+ <xsl:apply-templates select="memberdef"/>
+ </xsl:template>
+
+ <xsl:template match="simplesect" mode="struct">
+ <footnote>
+ <xsl:apply-templates/>
+ </footnote>
+ </xsl:template>
+
+ <xsl:template match="simplesect">
+ <xsl:choose>
+ <xsl:when test="@kind = 'par'">
+ <note>
+ <title>
+ <xsl:value-of select="title"/>
+ </title>
+ <xsl:apply-templates/>
+ </note>
+ </xsl:when>
+
+ <xsl:when test="@kind = 'return'">
+ <note>
+ <title>Returns</title>
+ <xsl:apply-templates/>
+ </note>
+ </xsl:when>
+
+ <xsl:when test="@kind = 'warning'">
+ <warning>
+ <title>Warning</title>
+ <xsl:apply-templates/>
+ </warning>
+ </xsl:when>
+
+ <xsl:when test="@kind = 'pre'">
+ <note>
+ <title>Precondition</title>
+ <xsl:apply-templates/>
+ </note>
+ </xsl:when>
+
+ <xsl:when test="@kind = 'see'">
+ <note>
+ <title>See also</title>
+ <xsl:apply-templates/>
+ </note>
+ </xsl:when>
+
+ <xsl:when test="@kind = 'note'">
+ <note>
+ <title>Note</title>
+ <xsl:apply-templates/>
+ </note>
+ </xsl:when>
+
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="parameterlist[@kind = 'param']">
+ <table>
+ <title>Parameters</title>
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>Data Direction</entry>
+ <entry>Parameter Name</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <xsl:for-each select="parameteritem">
+ <row>
+ <xsl:apply-templates select="."/>
+ </row>
+ </xsl:for-each>
+ </tbody>
+ </tgroup>
+ </table>
+ </xsl:template>
+
+ <xsl:template match="parameterlist[@kind = 'retval']">
+ <table>
+ <title>Return Values</title>
+ <tgroup cols="2">
+ <thead>
+ <row>
+ <entry>Return Value</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <xsl:for-each select="parameteritem">
+ <row>
+ <xsl:apply-templates select="."/>
+ </row>
+ </xsl:for-each>
+ </tbody>
+ </tgroup>
+ </table>
+ </xsl:template>
+
+ <xsl:template match="parameteritem">
+ <xsl:if test="parent::parameterlist/@kind = 'param'">
+ <entry>
+ <para>
+ <xsl:choose>
+ <xsl:when test="not(descendant::parametername/@direction)">
+ <emphasis role="italic">?</emphasis>
+ </xsl:when>
+
+ <xsl:otherwise>
+ <emphasis role="bold">
+ [<xsl:value-of select="descendant::parametername/@direction"/>]
+ </emphasis>
+ </xsl:otherwise>
+ </xsl:choose>
+ </para>
+ </entry>
+ </xsl:if>
+
+ <entry>
+ <para>
+ <xsl:value-of select="parameternamelist/parametername"/>
+ </para>
+ </entry>
+
+ <entry>
+ <xsl:apply-templates select="parameterdescription"/>
+ </entry>
+ </xsl:template>
+
+ <xsl:template match="parameterdescription">
+ <para>
+ <xsl:apply-templates/>
+ </para>
+ </xsl:template>
+
+ <xsl:template match="type">
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <xsl:template match="bold">
+ <emphasis role="bold">
+ <xsl:apply-templates/>
+ </emphasis>
+ </xsl:template>
+
+ <xsl:template match="emphasis">
+ <emphasis role="italic">
+ <xsl:apply-templates/>
+ </emphasis>
+ </xsl:template>
+
+ <xsl:template match="small">
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <xsl:template match="mdash | ndash">
+ <!-- Doxygen bug; double dashed are replaced with single HTML dash
+ entities, even in verbatim-like <tt> sections -->
+ <xsl:text>--</xsl:text>
+ </xsl:template>
+
+ <xsl:template match="computeroutput | preformatted">
+ <computeroutput>
+ <xsl:apply-templates/>
+ </computeroutput>
+ </xsl:template>
+
+ <xsl:template match="codeline">
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <xsl:template match="ulink">
+ <ulink url="{@url}">
+ <xsl:value-of select="."/>
+ </ulink>
+ </xsl:template>
+
+ <xsl:template match="superscript">
+ <superscript>
+ <xsl:apply-templates/>
+ </superscript>
+ </xsl:template>
+
+ <xsl:template match="subscript">
+ <subscript>
+ <xsl:apply-templates/>
+ </subscript>
+ </xsl:template>
+
+ <xsl:template match="para">
+ <para>
+ <xsl:apply-templates/>
+ </para>
+ </xsl:template>
+
+ <xsl:template match="ref">
+ <xsl:choose>
+ <!-- Don't show links inside program listings -->
+ <xsl:when test="ancestor::programlisting">
+ <xsl:value-of select="."/>
+ </xsl:when>
+
+ <!-- Don't show links to file compound definitions, as they are discarded -->
+ <xsl:when test="ancestor::*/compounddef[@kind = 'file' and @id = current()/@refid]">
+ <xsl:value-of select="."/>
+ </xsl:when>
+
+ <!-- Show links outside program listings -->
+ <xsl:otherwise>
+ <link linkend="{@refid}">
+ <xsl:value-of select="text()"/>
+ </link>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="entry">
+ <entry>
+ <xsl:apply-templates/>
+ </entry>
+ </xsl:template>
+
+ <xsl:template match="table[caption]">
+ <table>
+ <title>
+ <xsl:value-of select="caption"/>
+ </title>
+
+ <tgroup cols="{@cols}">
+ <thead>
+ <xsl:apply-templates select="row[entry/@thead = 'yes']"/>
+ </thead>
+
+ <tbody>
+ <xsl:apply-templates select="row[entry/@thead != 'yes']"/>
+ </tbody>
+ </tgroup>
+ </table>
+ </xsl:template>
+
+ <xsl:template match="table[not(caption)]">
+ <informaltable>
+ <tgroup cols="{@cols}">
+ <thead>
+ <xsl:apply-templates select="row[entry/@thead = 'yes']"/>
+ </thead>
+
+ <tbody>
+ <xsl:apply-templates select="row[entry/@thead != 'yes']"/>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </xsl:template>
+
+ <xsl:template match="row">
+ <row>
+ <xsl:apply-templates/>
+ </row>
+ </xsl:template>
+
+ <xsl:template match="itemizedlist">
+ <itemizedlist>
+ <xsl:apply-templates/>
+ </itemizedlist>
+ </xsl:template>
+
+ <xsl:template match="orderedlist">
+ <orderedlist>
+ <xsl:apply-templates/>
+ </orderedlist>
+ </xsl:template>
+
+ <xsl:template match="listitem">
+ <listitem>
+ <xsl:apply-templates/>
+ </listitem>
+ </xsl:template>
+
+ <xsl:template match="programlisting">
+ <programlisting language="c">
+ <xsl:for-each select="codeline[position() > 1 or highlight]">
+ <xsl:apply-templates select="."/>
+ <xsl:text>&#10;</xsl:text>
+ </xsl:for-each>
+ </programlisting>
+ </xsl:template>
+
+ <xsl:template match="highlight">
+ <emphasis role="{@class}">
+ <xsl:apply-templates/>
+ </emphasis>
+ </xsl:template>
+
+ <xsl:template match="highlight[1]/text()">
+ <xsl:choose>
+ <xsl:when test="substring(., 1, 1) = '*'">
+ <xsl:value-of select="substring(., 2)"/>
+ </xsl:when>
+
+ <xsl:otherwise>
+ <xsl:value-of select="."/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="sp[ancestor::codeline]">
+ <xsl:text> </xsl:text>
+ </xsl:template>
+
+ <xsl:template match="image">
+ <mediaobject>
+ <imageobject>
+ <imagedata align="center">
+ <xsl:attribute name="fileref">
+ <xsl:text>images/</xsl:text>
+ <xsl:value-of select="@name"/>
+ </xsl:attribute>
+ </imagedata>
+ </imageobject>
+ </mediaobject>
+ </xsl:template>
+
+ <xsl:template match="detaileddescription">
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <xsl:template match="sect1 | sect2 | sect3 | sect4 | sect5 | sect6 | sect7 | sect8 | sect9">
+ <section>
+ <xsl:if test="@id">
+ <xsl:attribute name="id">
+ <xsl:value-of select="@id"/>
+ </xsl:attribute>
+ </xsl:if>
+
+ <title>
+ <xsl:value-of select="title"/>
+ </title>
+
+ <xsl:apply-templates/>
+ </section>
+ </xsl:template>
+
+ <xsl:template match="anchor">
+ <xsl:if test="@id">
+ <indexterm id="{@id}"/>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="title"/>
+
+ <xsl:template match="htmlonly"/>
+
+ <xsl:template match="*">
+ <xsl:message>NO XSL TEMPLATE MATCH: <xsl:value-of select="local-name()"/></xsl:message>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/HV1/lufa_helpcontentsetup_transform.xslt b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/HV1/lufa_helpcontentsetup_transform.xslt
new file mode 100644
index 000000000..b43354f8d
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/HV1/lufa_helpcontentsetup_transform.xslt
@@ -0,0 +1,43 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio HV1 Setup XHTML transform file -->
+
+<!-- Updates a helpcontentsetup.msha document to add appropriate version
+ information. -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xhtml="http://www.w3.org/1999/xhtml" version="1.0">
+ <xsl:output method="xml" omit-xml-declaration="yes"/>
+
+ <!-- Need to input the LUFA extension version for later use -->
+ <xsl:param name="extension-version"/>
+
+ <!-- Recursively match and copy/process all nodes/attributes -->
+ <xsl:template match="node()">
+ <xsl:copy>
+ <xsl:copy-of select="@*"/>
+ <xsl:apply-templates select="node()"/>
+ </xsl:copy>
+ </xsl:template>
+
+ <!-- Update the LUFA help package file name -->
+ <xsl:template match="xhtml:div[@class='package']/xhtml:a">
+ <xsl:copy>
+ <xsl:copy-of select="@class"/>
+
+ <xsl:attribute name="href">
+ <xsl:text>lufa_help_</xsl:text>
+ <xsl:value-of select="$extension-version"/>
+ <xsl:text>.mshc</xsl:text>
+ </xsl:attribute>
+
+ <xsl:text>lufa_help_</xsl:text>
+ <xsl:value-of select="$extension-version"/>
+ <xsl:text>.mshc</xsl:text>
+ </xsl:copy>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/HV1/lufa_hv1_transform.xslt b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/HV1/lufa_hv1_transform.xslt
new file mode 100644
index 000000000..ee8a38340
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/HV1/lufa_hv1_transform.xslt
@@ -0,0 +1,45 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Docbook XML to Microsoft Help Viewer 1.0 transform file -->
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+ <xsl:import href="../Docbook/mshelp/docbook.xsl"/>
+
+ <xsl:output method="xml" indent="no"/>
+
+ <xsl:template match="emphasis[@role = 'keyword' or @role = 'keywordtype' or @role = 'keywordflow']">
+ <span class="hl-keyword" style="color: #0079C1">
+ <xsl:apply-templates/>
+ </span>
+ </xsl:template>
+
+ <xsl:template match="emphasis[@role = 'stringliteral' or @role = 'charliteral']">
+ <span class="hl-string" style="color: #800000">
+ <xsl:apply-templates/>
+ </span>
+ </xsl:template>
+
+ <xsl:template match="emphasis[@role = 'comment']">
+ <em class="hl-comment" style="color: #008000">
+ <xsl:apply-templates/>
+ </em>
+ </xsl:template>
+
+ <xsl:template match="emphasis[@role = 'preprocessor']">
+ <span class="hl-preprocessor" style="color: #A000A0">
+ <xsl:apply-templates/>
+ </span>
+ </xsl:template>
+
+ <xsl:template match="emphasis[@role = 'normal' and ancestor::programlisting]">
+ <xsl:apply-templates />
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/HV1/lufa_studio_help_styling.css b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/HV1/lufa_studio_help_styling.css
new file mode 100644
index 000000000..49eb7e970
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/HV1/lufa_studio_help_styling.css
@@ -0,0 +1,53 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+.programlisting {
+ display: block;
+ margin-left: 15px;
+ padding: 10px;
+ background-color: #f4f4f4;
+ border: 1px solid #aaaaaa;
+ font-family: "Consolas", "Courier New", sans-serif;
+ }
+
+ code {
+ background-color: #f4f4f4;
+ font-family: "Consolas", "Courier New", sans-serif;
+ }
+
+.note, .warning, .tip {
+ display: block;
+ margin-left: 15px;
+ padding-left: 10px;
+ padding-bottom: 5px;
+ background-color: #f4f4f4;
+ border: 1px solid #aaaaaa;
+}
+
+table {
+ border: 1px solid #aaaaaa;
+ border-collapse: collapse;
+ margin-left: 15px;
+ font-size: 10pt;
+}
+
+table thead {
+ background-color: #f4f4f4;
+}
+
+table thead th {
+ padding: 5px;
+}
+
+table tbody td {
+ padding: 5px;
+}
+
+ul {
+ padding-left: 20px;
+}
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/ProjectGenerator/placeholder.txt b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/ProjectGenerator/placeholder.txt
new file mode 100644
index 000000000..e89b0404b
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/ProjectGenerator/placeholder.txt
@@ -0,0 +1 @@
+Copy the ASF Project Generator into this directory (i.e. with the Python scripts in the current folder). The project generator can be extracted from the release versions of Atmel Studio's ASF extension. \ No newline at end of file
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/LUFA.dll b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/LUFA.dll
new file mode 100644
index 000000000..665b8029f
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/LUFA.dll
Binary files differ
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/LUFA.pkgdef b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/LUFA.pkgdef
new file mode 100644
index 000000000..b1b2f943b
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/LUFA.pkgdef
Binary files differ
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/[Content_Types].xml b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/[Content_Types].xml
new file mode 100644
index 000000000..05ef8b6ba
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/[Content_Types].xml
@@ -0,0 +1,13 @@
+<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
+ <Default Extension="vsixmanifest" ContentType="text/xml"/>
+ <Default Extension="cache" ContentType="text/xml"/>
+ <Default Extension="png" ContentType="application/octet-stream"/>
+ <Default Extension="txt" ContentType="text/plain"/>
+ <Default Extension="xml" ContentType="text/xml"/>
+ <Default Extension="zip" ContentType="application/octet-stream"/>
+ <Default Extension="dll" ContentType="application/octet-stream" />
+ <Default Extension="pkgdef" ContentType="text/plain" />
+ <Default Extension="htm" ContentType="text/html" />
+ <Default Extension="msha" ContentType="text/html" />
+ <Default Extension="mshc" ContentType="application/octet-stream"/>
+</Types>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/asf-manifest.xml b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/asf-manifest.xml
new file mode 100644
index 000000000..794fd689e
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/asf-manifest.xml
@@ -0,0 +1,18 @@
+<AsfContentProvider Version="1.0.0">
+ <Identifier Id="0e160d5c-e331-48d9-850b-e0387912171b">
+ <Org>FourWalledCubicle</Org>
+ <ShortName>LUFA</ShortName>
+ <Author>Dean Camera</Author>
+ <Description/>
+ <FollowFolderStructure>True</FollowFolderStructure>
+ </Identifier>
+ <AsfContent Type="zip" Path="contents.zip">
+ <Content>
+ <Version>0</Version>
+ <HelpURL/>
+ <Locator/>
+ <DbXMLPath>content.xml.cache</DbXMLPath>
+ <Description/>
+ </Content>
+ </AsfContent>
+</AsfContentProvider>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/extension.vsixmanifest b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/extension.vsixmanifest
new file mode 100644
index 000000000..ea6edeb25
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/extension.vsixmanifest
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<Vsix xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Version="1.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2010">
+ <Identifier Id="FourWalledCubicle.LUFA.0e160d5c-e331-48d9-850b-e0387912171b">
+ <Name>LUFA Library</Name>
+ <Author>Dean Camera</Author>
+ <Version>0</Version>
+ <MoreInfoUrl>http://www.lufa-lib.org</MoreInfoUrl>
+ <Description xml:space="preserve">LUFA, the Lightweight USB Framework for AVRs.</Description>
+
+ <License>License.txt</License>
+ <Icon>LUFA_thumb.png</Icon>
+ <PreviewImage>LUFA.png</PreviewImage>
+
+ <SupportedProducts>
+ <IsolatedShell Version="6.1">AtmelStudio</IsolatedShell>
+ <IsolatedShell Version="6.2">AtmelStudio</IsolatedShell>
+ </SupportedProducts>
+
+ <SupportedFrameworkRuntimeEdition MinVersion="4.0" MaxVersion="4.5"/>
+ <Locale>1033</Locale>
+
+ <AllUsers>false</AllUsers>
+ </Identifier>
+
+ <References/>
+
+ <Content>
+ <VsPackage>LUFA.pkgdef</VsPackage>
+ <CustomExtension Type="MSHelp">helpcontentsetup.msha</CustomExtension>
+ <CustomExtension Type="asf-manifest">asf-manifest.xml</CustomExtension>
+ </Content>
+</Vsix>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/generate_caches.py b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/generate_caches.py
new file mode 100644
index 000000000..c51cff400
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/generate_caches.py
@@ -0,0 +1,38 @@
+"""
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+"""
+
+import sys
+sys.path.append("ProjectGenerator")
+
+
+def show_message(message):
+ print("[Project Generator] %s" % message)
+ sys.stdout.flush()
+
+
+def main(lufa_root_path):
+ try:
+ from asf_avrstudio5_interface import PythonFacade
+ except ImportError:
+ print("Fatal Error: The ASF project generator is missing.")
+ return 1
+
+ p = PythonFacade(lufa_root_path)
+
+ show_message("Checking database sanity...")
+ p.check_extension_database_sanity(lufa_root_path)
+
+ show_message("Building cache files...")
+ p.generate_extension_cache_files(lufa_root_path)
+
+ show_message("Cache files created.")
+ return 0
+
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv[1]))
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/lufa_asfmanifest_transform.xslt b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/lufa_asfmanifest_transform.xslt
new file mode 100644
index 000000000..8fc98412f
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/lufa_asfmanifest_transform.xslt
@@ -0,0 +1,36 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework VSIX XML transform file -->
+
+<!-- Updates an asf-manifest.xml document to add appropriate version
+ information. -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+ <xsl:output method="xml" omit-xml-declaration="yes"/>
+
+ <!-- Need to input the LUFA version for later use -->
+ <xsl:param name="lufa-version"/>
+
+ <!-- Recursively match and copy/process all nodes/attributes -->
+ <xsl:template match="@*|node()">
+ <xsl:copy>
+ <xsl:apply-templates select="@*|node()"/>
+ </xsl:copy>
+ </xsl:template>
+
+ <!-- Update the LUFA version to the version passed as a parameter -->
+ <xsl:template match="Version">
+ <xsl:copy>
+ <xsl:value-of select="substring($lufa-version, 1, 2)"/>
+ <xsl:text>.</xsl:text>
+ <xsl:value-of select="substring($lufa-version, 3, 2)"/>
+ <xsl:text>.</xsl:text>
+ <xsl:value-of select="substring($lufa-version, 5, 2)"/>
+ </xsl:copy>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/lufa_vsmanifest_transform.xslt b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/lufa_vsmanifest_transform.xslt
new file mode 100644
index 000000000..db12d9ea2
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/VSIX/lufa_vsmanifest_transform.xslt
@@ -0,0 +1,33 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework VSIX XML transform file -->
+
+<!-- Updates the version element of a Visual Studio VSIX manifest file to the
+ value passed as a parameter to the stylesheet transform -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:vs="http://schemas.microsoft.com/developer/vsx-schema/2010" version="1.0">
+ <xsl:output method="xml" omit-xml-declaration="yes"/>
+
+ <!-- Need to input the extension version for later use -->
+ <xsl:param name="extension-version"/>
+
+ <!-- Recursively match and copy/process all nodes/attributes -->
+ <xsl:template match="@*|node()">
+ <xsl:copy>
+ <xsl:apply-templates select="@*|node()"/>
+ </xsl:copy>
+ </xsl:template>
+
+ <!-- Update the extension version to the version passed as a parameter -->
+ <xsl:template match="vs:Version">
+ <xsl:copy>
+ <xsl:value-of select="$extension-version"/>
+ </xsl:copy>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/XDK/lufa_extension_transform.xslt b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/XDK/lufa_extension_transform.xslt
new file mode 100644
index 000000000..f50f8a4dd
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/XDK/lufa_extension_transform.xslt
@@ -0,0 +1,68 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework Extension XML transform file -->
+
+<!-- Creates an extension.xml document from a given manifest list of XML files,
+ and adds appropriate documentation base URI entries and version
+ information. -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+ <xsl:output method="xml" omit-xml-declaration="yes"/>
+
+ <!-- Store the LUFA version mentioned in the root node for later use -->
+ <xsl:param name="lufa-version" select="lufa-manifest/@version"/>
+
+ <!-- Read manifest list and then process all FDK nodes in the referenced
+ document -->
+ <xsl:template match="lufa-manifest">
+ <xsl:comment>This file has been automatically generated from the LUFA Atmel Studio integration XML files.</xsl:comment>
+
+ <extension-container xmlversion="2.0">
+ <xsl:for-each select="xml-source">
+ <xsl:apply-templates select="document(@filename)/lufa/extension-container/*"/>
+ </xsl:for-each>
+ </extension-container>
+ </xsl:template>
+
+ <!-- Recursively match and copy/process all nodes/attributes -->
+ <xsl:template match="@*|node()">
+ <xsl:copy>
+ <xsl:apply-templates select="@*|node()"/>
+ </xsl:copy>
+ </xsl:template>
+
+ <!-- Update the extension version to the version of LUFA being used -->
+ <xsl:template match="extension/@version">
+ <xsl:attribute name="version">
+ <xsl:value-of select="substring($lufa-version, 1, 2)"/>
+ <xsl:text>.</xsl:text>
+ <xsl:value-of select="substring($lufa-version, 3, 2)"/>
+ <xsl:text>.</xsl:text>
+ <xsl:value-of select="substring($lufa-version, 5, 2)"/>
+ </xsl:attribute>
+ </xsl:template>
+
+ <!-- Update the extension online help URLs to the version of LUFA being
+ used -->
+ <xsl:template match="online-help/*/@baseurl">
+ <xsl:attribute name="baseurl">
+ <xsl:value-of select="current()"/>
+ <xsl:value-of select="$lufa-version"/>
+ <xsl:text>/html/</xsl:text>
+ </xsl:attribute>
+ </xsl:template>
+
+ <xsl:template match="online-help/index-page/@url">
+ <xsl:attribute name="url">
+ <xsl:value-of select="current()"/>
+ <xsl:value-of select="$lufa-version"/>
+ <xsl:text>/html/</xsl:text>
+ </xsl:attribute>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/XDK/lufa_filelist_transform.xslt b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/XDK/lufa_filelist_transform.xslt
new file mode 100644
index 000000000..9affc9f67
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/XDK/lufa_filelist_transform.xslt
@@ -0,0 +1,35 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework Module XML transform file -->
+
+<!-- Outputs a flat file list of all source files referenced in all modules of
+ the input manifest XML file, so that they can be checked for existence. -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+ <xsl:output method="xml" omit-xml-declaration="yes"/>
+
+ <!-- Read manifest list, add a comment to indicate the source filename
+ and then process all ASF nodes in the referenced document -->
+ <xsl:template match="lufa-manifest">
+ <xsl:for-each select="xml-source">
+ <xsl:comment>Sourced from <xsl:value-of select="@filename"/></xsl:comment>
+ <xsl:apply-templates select="document(@filename)/lufa/asf/*"/>
+ </xsl:for-each>
+ </xsl:template>
+
+ <!-- Recursively match and process all nodes/attributes -->
+ <xsl:template match="@*|node()">
+ <xsl:apply-templates select="@*|node()"/>
+ </xsl:template>
+
+ <!-- Match source file nodes, output filename -->
+ <xsl:template match="build[@type='c-source']|build[@type='header-file']|build[@type='distribute']">
+ <xsl:value-of select="@value"/>
+ <xsl:text>&#xA;</xsl:text>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/XDK/lufa_indent_transform.xslt b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/XDK/lufa_indent_transform.xslt
new file mode 100644
index 000000000..166f42571
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/XDK/lufa_indent_transform.xslt
@@ -0,0 +1,23 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework XML transform file -->
+
+<!-- Indents a given XML document to match the node hierarchy. -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+ <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
+
+ <!-- Remove all white-space on all elements so that they can be indented -->
+ <xsl:strip-space elements="*"/>
+
+ <!-- Match the root node and copy, so that the output will be a correctly
+ indented version of the input document -->
+ <xsl:template match="/">
+ <xsl:copy-of select="."/>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/XDK/lufa_module_transform.xslt b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/XDK/lufa_module_transform.xslt
new file mode 100644
index 000000000..ee9a050c1
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/XDK/lufa_module_transform.xslt
@@ -0,0 +1,66 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework Module XML transform file -->
+
+<!-- Creates an asf.xml module document from a given manifest list of XML files,
+ and adds appropriate documentation links by cross-referencing the Doxygen
+ tag output file to map Doxygen group names to generated filenames. -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+ <xsl:output method="xml" omit-xml-declaration="yes"/>
+
+ <!-- Store the LUFA Doxygen tag filename mentioned in the root node for later use -->
+ <xsl:param name="lufa-doxygen-tagfile" select="lufa-manifest/@tagfile"/>
+
+ <!-- Store the LUFA Doxygen documentation filename mentioned in the root node for later use -->
+ <xsl:param name="lufa-doxygen-docfile" select="lufa-manifest/@docfile"/>
+
+ <!-- Read manifest list, add a comment to indicate the source filename
+ and then copy/process all ASF nodes in the referenced document -->
+ <xsl:template match="lufa-manifest">
+ <xsl:comment>This file has been automatically generated from the LUFA Atmel Studio integration XML files.</xsl:comment>
+
+ <asf xmlversion="1.0">
+ <xsl:for-each select="xml-source">
+ <xsl:comment>Sourced from <xsl:value-of select="@filename"/></xsl:comment>
+ <xsl:apply-templates select="document(@filename)/lufa/asf/*"/>
+ </xsl:for-each>
+ </asf>
+ </xsl:template>
+
+ <!-- Recursively match and copy/process all nodes/attributes -->
+ <xsl:template match="@*|node()">
+ <xsl:copy>
+ <xsl:apply-templates select="@*|node()"/>
+ </xsl:copy>
+ </xsl:template>
+
+ <!-- For Doxygen entry point nodes we need to convert them into help link
+ nodes instead and add descriptions, so that they show up as links in
+ Studio correctly -->
+ <xsl:template match="build[@type='doxygen-entry-point']">
+ <!-- select-by-config entries should not have a help link -->
+ <xsl:if test="not(parent::select-by-config)">
+ <build type="online-help" subtype="module-help-page-append">
+ <xsl:attribute name="value">
+ <!-- Extract filename of the HTML file that contains the documentation for this module from the Doxgen tag file -->
+ <xsl:value-of select="document($lufa-doxygen-tagfile)/tagfile/compound[name=current()/@value]/filename"/>
+ </xsl:attribute>
+ </build>
+ </xsl:if>
+
+ <!-- Modules inside a select-by-config entries should not have a help link -->
+ <xsl:if test="not(parent::module and ../parent::select-by-config)">
+ <info type="description" value="summary">
+ <!-- Extract brief description of the module from the Doxygen combined XML documentation file -->
+ <xsl:value-of select="document($lufa-doxygen-docfile)/doxygen/compounddef[compoundname=current()/@value]/briefdescription/para"/>
+ </info>
+ </xsl:if>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa.xml b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa.xml
new file mode 100644
index 000000000..28afdda58
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa.xml
@@ -0,0 +1,96 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework integration file -->
+
+<lufa>
+ <extension-container>
+ <extension uuid="0e160d5c-e331-48d9-850b-e0387912171b" org="FourWalledCubicle" shortname="LUFA" version="" fullname="Lightweight USB Framework for AVRs (LUFA)">
+ <author name="Dean Camera" website="http://www.lufa-lib.org/" email="dean@fourwalledcubicle.com"/>
+ <description>Lightweight USB Framework for AVRs (LUFA), a USB software stack/framework.</description>
+ <icon-image path="LUFA/DoxygenPages/Images/LUFA_thumb.png"/>
+ <preview-image path="LUFA/DoxygenPages/Images/LUFA.png"/>
+ <license caption="LUFA License" path="LUFA/License.txt"/>
+ <release-notes caption="LUFA Information" url="http://www.lufa-lib.org"/>
+ <online-help>
+ <index-page caption="LUFA Documentation" url="http://www.lufa-lib.org/documentation/"/>
+ <module-help-page scheme="append" baseurl="http://www.lufa-lib.org/documentation/"/>
+ <module-guide-page scheme="append" baseurl="http://www.lufa-lib.org/documentation/"/>
+ </online-help>
+ <dependencies/>
+ </extension>
+ </extension-container>
+
+ <asf>
+ <device-alias-map name="lufa_avr8">
+ <device-support value="at90usb82"/>
+ <device-support value="atmega8u2"/>
+ <device-support value="at90usb162"/>
+ <device-support value="atmega16u2"/>
+ <device-support value="atmega16u4"/>
+ <device-support value="atmega32u2"/>
+ <device-support value="atmega32u4"/>
+ <device-support value="at90usb646"/>
+ <device-support value="at90usb647"/>
+ <device-support value="at90usb1286"/>
+ <device-support value="at90usb1287"/>
+ </device-alias-map>
+
+ <device-alias-map name="lufa_xmega">
+ <device-support value="atxmega16a4u"/>
+ <device-support value="atxmega32a4u"/>
+ <device-support value="atxmega64a4u"/>
+ <device-support value="atxmega128a4u"/>
+ <device-support value="atxmega64a3u"/>
+ <device-support value="atxmega128a3u"/>
+ <device-support value="atxmega192a3u"/>
+ <device-support value="atxmega256a3u"/>
+ <device-support value="atxmega256a3bu"/>
+ <device-support value="atxmega128a1u"/>
+ <device-support value="atxmega64b3"/>
+ <device-support value="atxmega128b3"/>
+ <device-support value="atxmega64b1"/>
+ <device-support value="atxmega128b1"/>
+ <device-support value="atxmega64c3"/>
+ <device-support value="atxmega128c3"/>
+ <!-- <device-support value="atxmega192c3"/> Wait for ASFP-3339 merge and release before enabling -->
+ <device-support value="atxmega256c3"/>
+ <device-support value="atxmega384c3"/>
+ <device-support value="atxmega16c4"/>
+ </device-alias-map>
+
+ <device-alias-map name="lufa_uc3">
+ <device-support value="at32uc3a364"/>
+ <device-support value="at32uc3a364s"/>
+ <device-support value="at32uc3a464"/>
+ <device-support value="at32uc3a464s"/>
+ <device-support value="at32uc3b064"/>
+ <device-support value="at32uc3b164"/>
+ <device-support value="at32uc3a0128"/>
+ <device-support value="at32uc3a1128"/>
+ <device-support value="at32uc3a3128"/>
+ <device-support value="at32uc3a3128s"/>
+ <device-support value="at32uc3a4128"/>
+ <device-support value="at32uc3a4128s"/>
+ <device-support value="at32uc3b0128"/>
+ <device-support value="at32uc3b1128"/>
+ <device-support value="at32uc3a0256"/>
+ <device-support value="at32uc3a1256"/>
+ <device-support value="at32uc3a3256"/>
+ <device-support value="at32uc3a3256s"/>
+ <device-support value="at32uc3a4256"/>
+ <device-support value="at32uc3a4256s"/>
+ <device-support value="at32uc3b0256"/>
+ <device-support value="at32uc3b1256"/>
+ <device-support value="at32uc3a0512"/>
+ <device-support value="at32uc3a1512"/>
+ <device-support value="at32uc3b0512"/>
+ <device-support value="at32uc3b1512"/>
+ </device-alias-map>
+ </asf>
+</lufa>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_common.xml b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_common.xml
new file mode 100644
index 000000000..9e17b188b
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_common.xml
@@ -0,0 +1,34 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework integration file -->
+
+<lufa>
+ <asf>
+ <module type="service" id="lufa.common" caption="LUFA Common Infrastructure">
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <info type="gui-flag" value="hidden"/>
+ <build type="doxygen-entry-point" value="Group_Common"/>
+
+ <build type="include-path" value=".."/>
+ <build type="header-file" subtype="api" value="Version.h"/>
+ <build type="distribute" subtype="license" value="License.txt"/>
+
+ <build type="header-file" subtype="api" value="Common/Common.h"/>
+ <build type="header-file" value="Common/Architectures.h"/>
+ <build type="header-file" value="Common/ArchitectureSpecific.h"/>
+ <build type="header-file" value="Common/Attributes.h"/>
+ <build type="header-file" value="Common/BoardTypes.h"/>
+ <build type="header-file" value="Common/CompilerSpecific.h"/>
+ <build type="header-file" value="Common/Endianness.h"/>
+ </module>
+ </asf>
+</lufa>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_board.xml b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_board.xml
new file mode 100644
index 000000000..3677d2003
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_board.xml
@@ -0,0 +1,114 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework integration file -->
+
+<lufa>
+ <asf>
+ <board id="lufa.boards.dummy.avr8" vendor="LUFA" caption="AVR8 Architecture">
+ <device-support value="mega"/>
+
+ <require idref="lufa.drivers.board"/>
+ <require idref="lufa.drivers.board.info"/>
+ </board>
+
+ <board id="lufa.boards.dummy.xmega" vendor="LUFA" caption="XMEGA Architecture">
+ <device-support value="xmega"/>
+
+ <require idref="lufa.drivers.board"/>
+ <require idref="lufa.drivers.board.info"/>
+ </board>
+
+ <board id="lufa.boards.dummy.uc3" vendor="LUFA" caption="UC3 Architecture">
+ <device-support value="uc3"/>
+
+ <require idref="lufa.drivers.board"/>
+ <require idref="lufa.drivers.board.info"/>
+ </board>
+
+ <module type="driver" id="lufa.drivers.board.info" caption="LUFA Board Hardware Information Driver">
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="doxygen-entry-point" value="Group_BoardInfo"/>
+
+ <require idref="lufa.common"/>
+
+ <build type="include-path" value=".."/>
+ <build type="header-file" subtype="api" value="Drivers/Board/Board.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board.leds" caption="LUFA Board LED Driver">
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="doxygen-entry-point" value="Group_LEDs"/>
+
+ <require idref="lufa.common"/>
+
+ <build type="include-path" value=".."/>
+ <build type="header-file" subtype="api" value="Drivers/Board/LEDs.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board.buttons" caption="LUFA Board Buttons Driver">
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="doxygen-entry-point" value="Group_Buttons"/>
+
+ <require idref="lufa.common"/>
+
+ <build type="include-path" value=".."/>
+ <build type="header-file" subtype="api" value="Drivers/Board/Buttons.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board.dataflash" caption="LUFA Board Dataflash Driver">
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="doxygen-entry-point" value="Group_Dataflash"/>
+
+ <require idref="lufa.common"/>
+
+ <build type="include-path" value=".."/>
+ <build type="header-file" subtype="api" value="Drivers/Board/Dataflash.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board.joystick" caption="LUFA Board Joystick Driver">
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="doxygen-entry-point" value="Group_Joystick"/>
+
+ <require idref="lufa.common"/>
+
+ <build type="include-path" value=".."/>
+ <build type="header-file" subtype="api" value="Drivers/Board/Joystick.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board.temperature" caption="LUFA Board Temperature Sensor Driver">
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="doxygen-entry-point" value="Group_Temperature"/>
+
+ <require idref="lufa.common"/>
+ <require idref="lufa.drivers.peripheral.adc"/>
+
+ <build type="c-source" value="Drivers/Board/Temperature.c"/>
+ <build type="include-path" value=".."/>
+ <build type="header-file" subtype="api" value="Drivers/Board/Temperature.h"/>
+ </module>
+ </asf>
+</lufa>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_board_names.xml b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_board_names.xml
new file mode 100644
index 000000000..4b099920b
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_board_names.xml
@@ -0,0 +1,853 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework integration file -->
+
+<lufa>
+ <asf>
+ <select-by-config id="lufa.drivers.board" name="lufa.drivers.board.name" default="none" caption="LUFA Board Support">
+ <info type="description" value="summary">
+ Board hardware (LEDs, Buttons, etc.) drivers for the preconfigured LUFA boards. Note that only the boards
+ compatible with the currently selected device will be shown.
+
+ To disable all hardware drivers silently, use NONE. To supply customer drivers, use USER (see manual).
+ </info>
+
+ <module type="driver" id="lufa.drivers.board#none" caption="Board Support - None">
+ <device-support value="avr"/>
+ <build type="define" name="BOARD" value="BOARD_NONE"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#user" caption="Board Support - User Supplied">
+ <device-support value="avr"/>
+ <build type="define" name="BOARD" value="BOARD_USER"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#adafruit_u4" caption="Board Support - ADAFRUITU4">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_ADAFRUITU4"/>
+
+ <device-support value="atmega32u4"/>
+ <build type="define" name="BOARD" value="BOARD_ADAFRUITU4"/>
+
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/ADAFRUITU4/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/ADAFRUITU4/LEDs.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#atavrusbrf01" caption="Board Support - ATAVRUSBRF01">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_ATAVRUSBRF01"/>
+
+ <device-support value="at90usb1287"/>
+ <build type="define" name="BOARD" value="BOARD_ATAVRUSBRF01"/>
+
+ <require idref="lufa.drivers.board.buttons"/>
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/ATAVRUSBRF01/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/ATAVRUSBRF01/Buttons.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/ATAVRUSBRF01/LEDs.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#benito" caption="Board Support - BENITO">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_BENITO"/>
+
+ <device-support value="at90usb162"/>
+ <build type="define" name="BOARD" value="BOARD_BENITO"/>
+
+ <require idref="lufa.drivers.board.buttons"/>
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/BENITO/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/BENITO/Buttons.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/BENITO/LEDs.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#big_multio" caption="Board Support - BIGMULTIO">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_BIGMULTIO"/>
+
+ <device-support value="atmega32u4"/>
+ <build type="define" name="BOARD" value="BOARD_BIGMULTIO"/>
+
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/BIGMULTIO/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/BIGMULTIO/LEDs.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#blackcat" caption="Board Support - BLACKCAT">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_BLACKCAT"/>
+
+ <device-support value="at90usb162"/>
+ <build type="define" name="BOARD" value="BOARD_BLACKCAT"/>
+
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/BLACKCAT/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/BLACKCAT/LEDs.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#bui" caption="Board Support - BUI">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_BUI"/>
+
+ <device-support value="at90usb646"/>
+ <build type="define" name="BOARD" value="BOARD_BUI"/>
+
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/BUI/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/BUI/LEDs.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#bumbleb" caption="Board Support - BUMBLEB">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_BUMBLEB"/>
+
+ <device-support value="at90usb162"/>
+ <build type="define" name="BOARD" value="BOARD_BUMBLEB"/>
+
+ <require idref="lufa.drivers.board.buttons"/>
+ <require idref="lufa.drivers.board.leds"/>
+ <require idref="lufa.drivers.board.joystick"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/BUMBLEB/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/BUMBLEB/Buttons.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/BUMBLEB/Joystick.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/BUMBLEB/LEDs.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#culv3" caption="Board Support - CULV3">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_CULV3"/>
+
+ <device-support value="atmega32u4"/>
+ <build type="define" name="BOARD" value="BOARD_CULV3"/>
+
+ <require idref="lufa.drivers.board.buttons"/>
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/CULV3/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/CULV3/Buttons.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/CULV3/LEDs.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#duce" caption="Board Support - DUCE">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_DUCE"/>
+
+ <device-support value="atmega32u2"/>
+ <build type="define" name="BOARD" value="BOARD_DUCE"/>
+
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/DUCE/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/DUCE/LEDs.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#evk527" caption="Board Support - EVK527">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_EVK527"/>
+
+ <device-support value="atmega32u4"/>
+ <build type="define" name="BOARD" value="BOARD_EVK527"/>
+
+ <require idref="lufa.drivers.misc.at45db321c"/>
+ <require idref="lufa.drivers.peripheral.spi"/>
+ <require idref="lufa.drivers.board.buttons"/>
+ <require idref="lufa.drivers.board.dataflash"/>
+ <require idref="lufa.drivers.board.joystick"/>
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/EVK527/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/EVK527/Buttons.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/EVK527/Dataflash.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/EVK527/Joystick.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/EVK527/LEDs.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#jm_db_u2" caption="Board Support - JMDBU2">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_JMDBU2"/>
+
+ <device-support value="atmega32u2"/>
+ <build type="define" name="BOARD" value="BOARD_JMDBU2"/>
+
+ <require idref="lufa.drivers.board.buttons"/>
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/JMDBU2/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/JMDBU2/Buttons.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/JMDBU2/LEDs.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#leonardo" caption="Board Support - LEONARDO">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_LEONARDO"/>
+
+ <device-support value="atmega32u4"/>
+ <build type="define" name="BOARD" value="BOARD_LEONARDO"/>
+
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/LEONARDO/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/LEONARDO/LEDs.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#maximus" caption="Board Support - MAXIMUS">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_MAXIMUS"/>
+
+ <device-support value="at90usb162"/>
+ <build type="define" name="BOARD" value="BOARD_MAXIMUS"/>
+
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/MAXIMUS/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/MAXIMUS/LEDs.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#micropendous_32u2" caption="Board Support - MICROPENDOUS_32U2">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_MICROPENDOUS_32U2"/>
+
+ <device-support value="atmega32u2"/>
+ <build type="define" name="BOARD" value="BOARD_MICROPENDOUS_32U2"/>
+
+ <require idref="lufa.drivers.board.leds"/>
+ <require idref="lufa.drivers.board.buttons"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/MICROPENDOUS/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/MICROPENDOUS/LEDs.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/MICROPENDOUS/Buttons.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#micropendous_a" caption="Board Support - MICROPENDOUS_A">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_MICROPENDOUS_A"/>
+
+ <device-support value="at90usb1287"/>
+ <build type="define" name="BOARD" value="BOARD_MICROPENDOUS_A"/>
+
+ <require idref="lufa.drivers.board.buttons"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/MICROPENDOUS/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/MICROPENDOUS/Buttons.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#micropendous_1" caption="Board Support - MICROPENDOUS_1">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_MICROPENDOUS_1"/>
+
+ <device-support value="at90usb162"/>
+ <build type="define" name="BOARD" value="BOARD_MICROPENDOUS_1"/>
+
+ <require idref="lufa.drivers.board.buttons"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/MICROPENDOUS/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/MICROPENDOUS/Buttons.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#micropendous_2" caption="Board Support - MICROPENDOUS_2">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_MICROPENDOUS_2"/>
+
+ <device-support value="atmega32u4"/>
+ <build type="define" name="BOARD" value="BOARD_MICROPENDOUS_2"/>
+
+ <require idref="lufa.drivers.board.buttons"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/MICROPENDOUS/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/MICROPENDOUS/Buttons.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#micropendous_3" caption="Board Support - MICROPENDOUS_3">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_MICROPENDOUS_3"/>
+
+ <device-support value="at90usb1287"/>
+ <build type="define" name="BOARD" value="BOARD_MICROPENDOUS_3"/>
+
+ <require idref="lufa.drivers.board.buttons"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/MICROPENDOUS/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/MICROPENDOUS/Buttons.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#micropendous_4" caption="Board Support - MICROPENDOUS_4">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_MICROPENDOUS_4"/>
+
+ <device-support value="at90usb1287"/>
+ <build type="define" name="BOARD" value="BOARD_MICROPENDOUS_4"/>
+
+ <require idref="lufa.drivers.board.buttons"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/MICROPENDOUS/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/MICROPENDOUS/Buttons.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#micropendous_dip" caption="Board Support - MICROPENDOUS_DIP">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_MICROPENDOUS_DIP"/>
+
+ <device-support value="at90usb1287"/>
+ <build type="define" name="BOARD" value="BOARD_MICROPENDOUS_DIP"/>
+
+ <require idref="lufa.drivers.board.buttons"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/MICROPENDOUS/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/MICROPENDOUS/Buttons.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#micropendous_rev1" caption="Board Support - MICROPENDOUS_REV1">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_MICROPENDOUS_REV1"/>
+
+ <device-support value="at90usb1287"/>
+ <build type="define" name="BOARD" value="BOARD_MICROPENDOUS_REV1"/>
+
+ <require idref="lufa.drivers.board.leds"/>
+ <require idref="lufa.drivers.board.buttons"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/MICROPENDOUS/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/MICROPENDOUS/LEDs.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/MICROPENDOUS/Buttons.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#micropendous_rev2" caption="Board Support - MICROPENDOUS_REV2">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_MICROPENDOUS_REV2"/>
+
+ <device-support value="at90usb1287"/>
+ <build type="define" name="BOARD" value="BOARD_MICROPENDOUS_REV2"/>
+
+ <require idref="lufa.drivers.board.leds"/>
+ <require idref="lufa.drivers.board.buttons"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/MICROPENDOUS/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/MICROPENDOUS/LEDs.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/MICROPENDOUS/Buttons.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#microsin_162" caption="Board Support - MICROSIN162">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_MICROSIN162"/>
+
+ <device-support value="atmega162"/>
+ <build type="define" name="BOARD" value="BOARD_MICROSIN162"/>
+
+ <require idref="lufa.drivers.board.leds"/>
+ <require idref="lufa.drivers.board.buttons"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/MICROSIN162/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/MICROSIN162/LEDs.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/MICROSIN162/Buttons.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#minimus" caption="Board Support - MINIMUS">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_MINIMUS"/>
+
+ <device-support value="atmega32u2"/>
+ <build type="define" name="BOARD" value="BOARD_MINIMUS"/>
+
+ <require idref="lufa.drivers.board.leds"/>
+ <require idref="lufa.drivers.board.buttons"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/MINIMUS/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/MINIMUS/LEDs.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/MINIMUS/Buttons.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#multio" caption="Board Support - MULTIO">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_MULTIO"/>
+
+ <device-support value="at90usb162"/>
+ <build type="define" name="BOARD" value="BOARD_MULTIO"/>
+
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/MULTIO/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/MULTIO/LEDs.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#olimex_162" caption="Board Support - OLIMEX162">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_OLIMEX162"/>
+
+ <device-support value="at90usb162"/>
+ <build type="define" name="BOARD" value="BOARD_OLIMEX162"/>
+
+ <require idref="lufa.drivers.board.leds"/>
+ <require idref="lufa.drivers.board.buttons"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/OLIMEX162/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/OLIMEX162/LEDs.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/OLIMEX162/Buttons.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#olimex_32u4" caption="Board Support - OLIMEX32U4">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_OLIMEX32U4"/>
+
+ <device-support value="atmega32u4"/>
+ <build type="define" name="BOARD" value="BOARD_OLIMEX32U4"/>
+
+ <require idref="lufa.drivers.board.leds"/>
+ <require idref="lufa.drivers.board.buttons"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/OLIMEX32U4/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/OLIMEX32U4/LEDs.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/OLIMEX32U4/Buttons.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#olimex_isp_mkii" caption="Board Support - OLIMEXISPMK2">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_OLIMEXISPMK2"/>
+
+ <device-support value="at90usb162"/>
+ <build type="define" name="BOARD" value="BOARD_OLIMEXISPMK2"/>
+
+ <require idref="lufa.drivers.board.leds"/>
+ <require idref="lufa.drivers.board.buttons"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/OLIMEXISPMK2/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/OLIMEXISPMK2/LEDs.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/OLIMEXISPMK2/Buttons.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#olimex_t32u4" caption="Board Support - OLIMEX_T32U4">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_OLIMEXT32U4"/>
+
+ <device-support value="atmega32u4"/>
+ <build type="define" name="BOARD" value="BOARD_OLIMEXT32U4"/>
+
+ <require idref="lufa.drivers.board.leds"/>
+ <require idref="lufa.drivers.board.buttons"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/OLIMEXT32U4/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/OLIMEXT32U4/LEDs.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/OLIMEXT32U4/Buttons.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#rzusbstick" caption="Board Support - RZUSBSTICK">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_RZUSBSTICK"/>
+
+ <device-support value="at90usb1287"/>
+ <build type="define" name="BOARD" value="BOARD_RZUSBSTICK"/>
+
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/RZUSBSTICK/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/RZUSBSTICK/LEDs.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#sparkfun_8u2" caption="Board Support - SPARKFUN8U2">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_SPARKFUN8U2"/>
+
+ <device-support value="atmega8u2"/>
+ <build type="define" name="BOARD" value="BOARD_SPARKFUN8U2"/>
+
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/SPARKFUN8U2/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/SPARKFUN8U2/LEDs.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#stk525" caption="Board Support - STK525">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_STK525"/>
+
+ <device-support value="at90usb1287"/>
+ <device-support value="at90usb1286"/>
+ <device-support value="at90usb647"/>
+ <device-support value="at90usb646"/>
+ <build type="define" name="BOARD" value="BOARD_STK525"/>
+
+ <require idref="lufa.drivers.misc.at45db321c"/>
+ <require idref="lufa.drivers.peripheral.spi"/>
+ <require idref="lufa.drivers.board.buttons"/>
+ <require idref="lufa.drivers.board.dataflash"/>
+ <require idref="lufa.drivers.board.joystick"/>
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/STK525/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/STK525/Buttons.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/STK525/Dataflash.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/STK525/Joystick.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/STK525/LEDs.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#stk526" caption="Board Support - STK526">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_STK526"/>
+
+ <device-support value="at90usb162"/>
+ <device-support value="at90usb82"/>
+ <device-support value="atmega32u2"/>
+ <device-support value="atmega16u2"/>
+ <device-support value="atmega8u2"/>
+ <build type="define" name="BOARD" value="BOARD_STK526"/>
+
+ <require idref="lufa.drivers.misc.at45db642d"/>
+ <require idref="lufa.drivers.peripheral.spi"/>
+ <require idref="lufa.drivers.board.buttons"/>
+ <require idref="lufa.drivers.board.dataflash"/>
+ <require idref="lufa.drivers.board.joystick"/>
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/STK526/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/STK526/Buttons.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/STK526/Dataflash.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/STK526/Joystick.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/STK526/LEDs.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#teensy" caption="Board Support - TEENSY">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_TEENSY"/>
+
+ <device-support value="at90usb162"/>
+ <build type="define" name="BOARD" value="BOARD_TEENSY"/>
+
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/TEENSY/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/TEENSY/LEDs.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#teensy2" caption="Board Support - TEENSY2">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_TEENSY2"/>
+
+ <device-support value="at90usb646"/>
+ <build type="define" name="BOARD" value="BOARD_TEENSY2"/>
+
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/TEENSY/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/TEENSY/LEDs.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#tul" caption="Board Support - TUL">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_TUL"/>
+
+ <device-support value="atmega32u4"/>
+ <build type="define" name="BOARD" value="BOARD_TUL"/>
+
+ <require idref="lufa.drivers.board.buttons"/>
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/TUL/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/TUL/Buttons.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/TUL/LEDs.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#udip" caption="Board Support - UDIP">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_UDIP"/>
+
+ <device-support value="atmega32u2"/>
+ <build type="define" name="BOARD" value="BOARD_UDIP"/>
+
+ <require idref="lufa.drivers.board.buttons"/>
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/UDIP/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/UDIP/Buttons.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/UDIP/LEDs.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#uno" caption="Board Support - UNO">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_UNO"/>
+
+ <device-support value="atmega8u2"/>
+ <device-support value="atmega16u2"/>
+ <build type="define" name="BOARD" value="BOARD_UNO"/>
+
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/UNO/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/UNO/LEDs.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#usb2ax" caption="Board Support - USB2AX">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_USB2AX"/>
+
+ <device-support value="atmega32u2"/>
+ <build type="define" name="BOARD" value="BOARD_USB2AX"/>
+
+ <require idref="lufa.drivers.board.buttons"/>
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/USB2AX/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/USB2AX/Buttons.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/USB2AX/LEDs.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#usb2ax_v3" caption="Board Support - USB2AX_V3">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_USB2AX_V3"/>
+
+ <device-support value="atmega32u2"/>
+ <build type="define" name="BOARD" value="BOARD_USB2AX_V3"/>
+
+ <require idref="lufa.drivers.board.buttons"/>
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/USB2AX/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/USB2AX/Buttons.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/USB2AX/LEDs.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#usb2ax_v3_1" caption="Board Support - USB2AX_V31">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_USB2AX_V31"/>
+
+ <device-support value="atmega32u2"/>
+ <build type="define" name="BOARD" value="BOARD_USB2AX_V31"/>
+
+ <require idref="lufa.drivers.board.buttons"/>
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/USB2AX/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/USB2AX/Buttons.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/USB2AX/LEDs.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#usbfoo" caption="Board Support - USBFOO">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_USBFOO"/>
+
+ <device-support value="atmega162"/>
+ <build type="define" name="BOARD" value="BOARD_USBFOO"/>
+
+ <require idref="lufa.drivers.board.buttons"/>
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/USBFOO/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/USBFOO/Buttons.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/USBFOO/LEDs.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#usbkey" caption="Board Support - USBKEY">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_USBKEY"/>
+
+ <device-support value="at90usb1287"/>
+ <build type="define" name="BOARD" value="BOARD_USBKEY"/>
+
+ <require idref="lufa.drivers.misc.at45db642d"/>
+ <require idref="lufa.drivers.peripheral.spi"/>
+
+ <require idref="lufa.drivers.board.buttons"/>
+ <require idref="lufa.drivers.board.dataflash"/>
+ <require idref="lufa.drivers.board.joystick"/>
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/USBKEY/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/USBKEY/Buttons.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/USBKEY/Dataflash.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/USBKEY/Joystick.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/USBKEY/LEDs.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#usbtiny_mkii" caption="Board Support - USBTINYMKII">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_USBTINYMKII"/>
+
+ <device-support value="at90usb162"/>
+ <build type="define" name="BOARD" value="BOARD_USBTINYMKII"/>
+
+ <require idref="lufa.drivers.board.buttons"/>
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/USBTINYMKII/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/USBTINYMKII/Buttons.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/USBTINYMKII/LEDs.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#xplain_rev1" caption="Board Support - XPLAIN (HW Rev 1)">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_XPLAIN_REV1"/>
+
+ <device-support value="at90usb1287"/>
+
+ <require idref="lufa.drivers.misc.at45db642d"/>
+ <require idref="lufa.drivers.peripheral.spi"/>
+ <require idref="lufa.drivers.board.dataflash"/>
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/XPLAIN/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/XPLAIN/Dataflash.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/XPLAIN/LEDs.h"/>
+
+ <build type="define" name="BOARD" value="BOARD_XPLAIN_REV1"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#xplain" caption="Board Support - XPLAIN (HW Rev 2+)">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_XPLAIN"/>
+
+ <device-support value="at90usb1287"/>
+
+ <require idref="lufa.drivers.misc.at45db642d"/>
+ <require idref="lufa.drivers.peripheral.spi"/>
+ <require idref="lufa.drivers.board.dataflash"/>
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/XPLAIN/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/XPLAIN/Dataflash.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/XPLAIN/LEDs.h"/>
+
+ <build type="define" name="BOARD" value="BOARD_XPLAIN"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#a3bu_xplained" caption="Board Support - A3BU_XPLAINED">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_A3BU_XPLAINED"/>
+
+ <device-support value="atxmega256a3bu"/>
+
+ <require idref="lufa.drivers.misc.at45db642d"/>
+ <require idref="lufa.drivers.peripheral.usart_spi"/>
+
+ <require idref="lufa.drivers.board.buttons"/>
+ <require idref="lufa.drivers.board.dataflash"/>
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/XMEGA/A3BU_XPLAINED/Board.h"/>
+ <build type="header-file" value="Drivers/Board/XMEGA/A3BU_XPLAINED/Buttons.h"/>
+ <build type="header-file" value="Drivers/Board/XMEGA/A3BU_XPLAINED/Dataflash.h"/>
+ <build type="header-file" value="Drivers/Board/XMEGA/A3BU_XPLAINED/LEDs.h"/>
+
+ <build type="define" name="BOARD" value="BOARD_A3BU_XPLAINED"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#b1_xplained" caption="Board Support - B1_XPLAINED">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_B1_XPLAINED"/>
+
+ <device-support value="atxmega128b1"/>
+
+ <require idref="lufa.drivers.misc.at45db642d"/>
+ <require idref="lufa.drivers.peripheral.usart_spi"/>
+ <require idref="lufa.drivers.board.buttons"/>
+ <require idref="lufa.drivers.board.dataflash"/>
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/XMEGA/B1_XPLAINED/Board.h"/>
+ <build type="header-file" value="Drivers/Board/XMEGA/B1_XPLAINED/Buttons.h"/>
+ <build type="header-file" value="Drivers/Board/XMEGA/B1_XPLAINED/Dataflash.h"/>
+ <build type="header-file" value="Drivers/Board/XMEGA/B1_XPLAINED/LEDs.h"/>
+
+ <build type="define" name="BOARD" value="BOARD_B1_XPLAINED"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#evk1100" caption="Board Support - EVK1100">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_EVK1100"/>
+
+ <device-support value="at32uc3a0512"/>
+
+ <require idref="lufa.drivers.board.buttons"/>
+ <require idref="lufa.drivers.board.joystick"/>
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/UC3/EVK1100/Board.h"/>
+ <build type="header-file" value="Drivers/Board/UC3/EVK1100/Buttons.h"/>
+ <build type="header-file" value="Drivers/Board/UC3/EVK1100/Joystick.h"/>
+ <build type="header-file" value="Drivers/Board/UC3/EVK1100/LEDs.h"/>
+
+ <build type="define" name="BOARD" value="BOARD_EVK1100"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#evk1101" caption="Board Support - EVK1101">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_EVK1101"/>
+
+ <device-support value="at32uc3b0256"/>
+
+ <require idref="lufa.drivers.board.buttons"/>
+ <require idref="lufa.drivers.board.joystick"/>
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/UC3/EVK1101/Board.h"/>
+ <build type="header-file" value="Drivers/Board/UC3/EVK1101/Buttons.h"/>
+ <build type="header-file" value="Drivers/Board/UC3/EVK1101/Joystick.h"/>
+ <build type="header-file" value="Drivers/Board/UC3/EVK1101/LEDs.h"/>
+
+ <build type="define" name="BOARD" value="BOARD_EVK1101"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#evk1104" caption="Board Support - EVK1104">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_EVK1104"/>
+
+ <device-support value="at32uc3a3256"/>
+
+ <require idref="lufa.drivers.board.buttons"/>
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/UC3/EVK1104/Board.h"/>
+ <build type="header-file" value="Drivers/Board/UC3/EVK1104/Buttons.h"/>
+ <build type="header-file" value="Drivers/Board/UC3/EVK1104/LEDs.h"/>
+
+ <build type="define" name="BOARD" value="BOARD_EVK1104"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#uc3a3_xplained" caption="Board Support - UC3A3_XPLAINED">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_UC3_A3_XPLAINED"/>
+
+ <device-support value="at32uc3a3256"/>
+
+ <require idref="lufa.drivers.board.buttons"/>
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/UC3/UC3A3_XPLAINED/Board.h"/>
+ <build type="header-file" value="Drivers/Board/UC3/UC3A3_XPLAINED/Buttons.h"/>
+ <build type="header-file" value="Drivers/Board/UC3/UC3A3_XPLAINED/LEDs.h"/>
+
+ <build type="define" name="BOARD" value="BOARD_UC3A3_XPLAINED"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#stange_isp" caption="Board Support - STANGE_ISP">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_STANGE_ISP"/>
+
+ <device-support value="at90usb162"/>
+
+ <require idref="lufa.drivers.board.buttons"/>
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/STANGE_ISP/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/STANGE_ISP/Buttons.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/STANGE_ISP/LEDs.h"/>
+
+ <build type="define" name="BOARD" value="BOARD_STANGE_ISP"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#c3_xplained" caption="Board Support - C3_XPLAINED">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_C3_XPLAINED"/>
+
+ <device-support value="atxmega384c3"/>
+
+ <require idref="lufa.drivers.board.buttons"/>
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/XMEGA/C3_XPLAINED/Board.h"/>
+ <build type="header-file" value="Drivers/Board/XMEGA/C3_XPLAINED/Buttons.h"/>
+ <build type="header-file" value="Drivers/Board/XMEGA/C3_XPLAINED/LEDs.h"/>
+
+ <build type="define" name="BOARD" value="BOARD_C3_XPLAINED"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#u2s" caption="Board Support - U2S">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_U2S"/>
+
+ <device-support value="atmega32u2"/>
+
+ <require idref="lufa.drivers.board.buttons"/>
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/U2S/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/U2S/Buttons.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/U2S/LEDs.h"/>
+
+ <build type="define" name="BOARD" value="BOARD_U2S"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#yun" caption="Board Support - YUN">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_YUN"/>
+
+ <device-support value="atmega32u4"/>
+
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/YUN/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/YUN/LEDs.h"/>
+
+ <build type="define" name="BOARD" value="BOARD_YUN"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.board#yun" caption="Board Support - MICRO">
+ <build type="doxygen-entry-point" value="Group_BoardInfo_MICRO"/>
+
+ <device-support value="atmega32u4"/>
+
+ <require idref="lufa.drivers.board.leds"/>
+
+ <build type="header-file" value="Drivers/Board/AVR8/MICRO/Board.h"/>
+ <build type="header-file" value="Drivers/Board/AVR8/MICRO/LEDs.h"/>
+
+ <build type="define" name="BOARD" value="BOARD_MICRO"/>
+ </module>
+ </select-by-config>
+ </asf>
+</lufa>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_misc.xml b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_misc.xml
new file mode 100644
index 000000000..8680ca2df
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_misc.xml
@@ -0,0 +1,57 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework integration file -->
+
+<lufa>
+ <asf>
+ <module type="component" id="lufa.drivers.misc.at45db321c" caption="LUFA AT45DB321C Dataflash Commands">
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="doxygen-entry-point" value="Group_AT45DB321C"/>
+
+ <build type="include-path" value=".."/>
+ <build type="header-file" subtype="api" value="Drivers/Misc/AT45DB321C.h"/>
+ </module>
+
+ <module type="component" id="lufa.drivers.misc.at45db642d" caption="LUFA AT45DB642D Dataflash Commands">
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="doxygen-entry-point" value="Group_AT45DB321C"/>
+
+ <build type="include-path" value=".."/>
+ <build type="header-file" subtype="api" value="Drivers/Misc/AT45DB642D.h"/>
+ </module>
+
+ <module type="service" id="lufa.drivers.misc.ringbuffer" caption="LUFA Ring Buffer">
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="doxygen-entry-point" value="Group_RingBuff"/>
+
+ <build type="include-path" value=".."/>
+ <build type="header-file" subtype="api" value="Drivers/Misc/RingBuffer.h"/>
+ </module>
+
+ <module type="service" id="lufa.drivers.misc.ansi" caption="LUFA ANSI Terminal Commands">
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="doxygen-entry-point" value="Group_Terminal"/>
+
+ <build type="include-path" value=".."/>
+ <build type="header-file" subtype="api" value="Drivers/Misc/TerminalCodes.h"/>
+ </module>
+ </asf>
+</lufa> \ No newline at end of file
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_peripheral.xml b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_peripheral.xml
new file mode 100644
index 000000000..3a982e565
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_peripheral.xml
@@ -0,0 +1,198 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework integration file -->
+
+<lufa>
+ <asf>
+ <select-by-device id="lufa.drivers.peripheral.usart" caption="LUFA USART Driver">
+ <module type="driver" id="lufa.drivers.peripheral.usart#avr8" caption="LUFA USART Driver - AVR8">
+ <device-support-alias value="lufa_avr8"/>
+
+ <build type="doxygen-entry-point" value="Group_Serial"/>
+
+ <require idref="lufa.common"/>
+ <require idref="lufa.drivers.misc.ansi"/>
+
+ <build type="c-source" value="Drivers/Peripheral/AVR8/Serial_AVR8.c"/>
+ <build type="header-file" value="Drivers/Peripheral/AVR8/Serial_AVR8.h"/>
+ <build type="include-path" value=".."/>
+ <build type="header-file" subtype="api" value="Drivers/Peripheral/Serial.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.peripheral.usart#xmega" caption="LUFA USART Driver - AVR8">
+ <device-support-alias value="lufa_xmega"/>
+
+ <build type="doxygen-entry-point" value="Group_Serial"/>
+
+ <require idref="lufa.common"/>
+ <require idref="lufa.drivers.misc.ansi"/>
+
+ <build type="c-source" value="Drivers/Peripheral/XMEGA/Serial_XMEGA.c"/>
+ <build type="header-file" value="Drivers/Peripheral/XMEGA/Serial_XMEGA.h"/>
+ <build type="include-path" value=".."/>
+ <build type="header-file" subtype="api" value="Drivers/Peripheral/Serial.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.peripheral.usart#uc3" caption="LUFA USART Driver - UC3">
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="doxygen-entry-point" value="Group_Serial"/>
+
+ <require idref="lufa.common"/>
+ <require idref="lufa.drivers.misc.ansi"/>
+
+ <info type="gui-flag" value="hidden"/>
+ </module>
+ </select-by-device>
+
+ <select-by-device id="lufa.drivers.peripheral.spi" caption="LUFA SPI Driver">
+ <module type="driver" id="lufa.drivers.peripheral.spi#avr8" caption="LUFA SPI Driver - AVR8">
+ <device-support-alias value="lufa_avr8"/>
+
+ <build type="doxygen-entry-point" value="Group_SPI"/>
+
+ <require idref="lufa.common"/>
+
+ <build type="header-file" value="Drivers/Peripheral/AVR8/SPI_AVR8.h"/>
+ <build type="include-path" value=".."/>
+ <build type="header-file" subtype="api" value="Drivers/Peripheral/SPI.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.peripheral.spi#xmega" caption="LUFA SPI Driver - XMEGA">
+ <device-support-alias value="lufa_xmega"/>
+
+ <build type="doxygen-entry-point" value="Group_SPI"/>
+
+ <require idref="lufa.common"/>
+
+ <build type="header-file" value="Drivers/Peripheral/XMEGA/SPI_XMEGA.h"/>
+ <build type="include-path" value=".."/>
+ <build type="header-file" subtype="api" value="Drivers/Peripheral/SPI.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.peripheral.spi#uc3" caption="LUFA SPI Driver - UC3">
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="doxygen-entry-point" value="Group_SPI"/>
+
+ <require idref="lufa.common"/>
+
+ <info type="gui-flag" value="hidden"/>
+ </module>
+ </select-by-device>
+
+ <select-by-device id="lufa.drivers.peripheral.usart_spi" caption="LUFA USART SPI Driver">
+ <module type="driver" id="lufa.drivers.peripheral.usart_spi#avr8" caption="LUFA USART SPI Driver - AVR8">
+ <device-support-alias value="lufa_avr8"/>
+
+ <build type="doxygen-entry-point" value="Group_SerialSPI"/>
+
+ <require idref="lufa.common"/>
+
+ <build type="header-file" value="Drivers/Peripheral/AVR8/SerialSPI_AVR8.h"/>
+ <build type="include-path" value=".."/>
+ <build type="header-file" subtype="api" value="Drivers/Peripheral/SerialSPI.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.peripheral.usart_spi#xmega" caption="LUFA USART SPI Driver - XMEGA">
+ <device-support-alias value="lufa_xmega"/>
+
+ <build type="doxygen-entry-point" value="Group_SerialSPI"/>
+
+ <require idref="lufa.common"/>
+
+ <build type="header-file" value="Drivers/Peripheral/XMEGA/SerialSPI_XMEGA.h"/>
+ <build type="include-path" value=".."/>
+ <build type="header-file" subtype="api" value="Drivers/Peripheral/SerialSPI.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.peripheral.usart_spi#uc3" caption="LUFA USART SPI Driver - UC3">
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="doxygen-entry-point" value="Group_SerialSPI"/>
+
+ <require idref="lufa.common"/>
+
+ <info type="gui-flag" value="hidden"/>
+ </module>
+ </select-by-device>
+
+ <select-by-device id="lufa.drivers.peripheral.twi" caption="LUFA TWI Master Driver">
+ <module type="driver" id="lufa.drivers.peripheral.twi#avr8" caption="LUFA TWI Master Driver - AVR8">
+ <device-support-alias value="lufa_avr8"/>
+
+ <build type="doxygen-entry-point" value="Group_TWI"/>
+
+ <require idref="lufa.common"/>
+
+ <build type="c-source" value="Drivers/Peripheral/AVR8/TWI_AVR8.c"/>
+ <build type="header-file" value="Drivers/Peripheral/AVR8/TWI_AVR8.h"/>
+ <build type="include-path" value=".."/>
+ <build type="header-file" subtype="api" value="Drivers/Peripheral/TWI.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.peripheral.twi#xmega" caption="LUFA TWI Master Driver - XMEGA">
+ <device-support-alias value="lufa_xmega"/>
+
+ <build type="doxygen-entry-point" value="Group_TWI"/>
+
+ <require idref="lufa.common"/>
+
+ <build type="c-source" value="Drivers/Peripheral/XMEGA/TWI_XMEGA.c"/>
+ <build type="header-file" value="Drivers/Peripheral/XMEGA/TWI_XMEGA.h"/>
+ <build type="include-path" value=".."/>
+ <build type="header-file" subtype="api" value="Drivers/Peripheral/TWI.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.peripheral.twi#uc3" caption="LUFA TWI Master Driver - UC3">
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="doxygen-entry-point" value="Group_TWI"/>
+
+ <require idref="lufa.common"/>
+
+ <info type="gui-flag" value="hidden"/>
+ </module>
+ </select-by-device>
+
+ <select-by-device id="lufa.drivers.peripheral.adc" caption="LUFA ADC Driver">
+ <module type="driver" id="lufa.drivers.peripheral.adc#avr8" caption="LUFA ADC Driver - AVR8">
+ <device-support-alias value="lufa_avr8"/>
+
+ <build type="doxygen-entry-point" value="Group_ADC"/>
+
+ <require idref="lufa.common"/>
+
+ <build type="header-file" value="Drivers/Peripheral/AVR8/ADC_AVR8.h"/>
+ <build type="include-path" value=".."/>
+ <build type="header-file" subtype="api" value="Drivers/Peripheral/ADC.h"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.peripheral.adc#xmega" caption="LUFA ADC Driver - XMEGA">
+ <device-support-alias value="lufa_xmega"/>
+
+ <build type="doxygen-entry-point" value="Group_ADC"/>
+
+ <require idref="lufa.common"/>
+
+ <info type="gui-flag" value="hidden"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.peripheral.adc#uc3" caption="LUFA ADC Driver - UC3">
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="doxygen-entry-point" value="Group_ADC"/>
+
+ <require idref="lufa.common"/>
+
+ <info type="gui-flag" value="hidden"/>
+ </module>
+ </select-by-device>
+ </asf>
+</lufa>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb.xml b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb.xml
new file mode 100644
index 000000000..7ff4b3949
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb.xml
@@ -0,0 +1,32 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework integration file -->
+
+<lufa>
+ <asf>
+ <module type="driver" id="lufa.drivers.usb" caption="LUFA USB Driver">
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="doxygen-entry-point" value="Group_USB"/>
+
+ <build type="define" name="USE_LUFA_CONFIG_HEADER" value=""/>
+ <build type="module-config" subtype="path" value="CodeTemplates"/>
+ <build type="module-config" subtype="required-header-file" value="LUFAConfig.h"/>
+
+ <build type="include-path" value=".."/>
+ <build type="header-file" subtype="api" value="Drivers/USB/USB.h"/>
+
+ <require idref="lufa.common"/>
+ <require idref="lufa.drivers.usb.class"/>
+ <require idref="lufa.drivers.usb.core"/>
+ </module>
+ </asf>
+</lufa> \ No newline at end of file
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class.xml b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class.xml
new file mode 100644
index 000000000..cd18bf10e
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class.xml
@@ -0,0 +1,32 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework integration file -->
+
+<lufa>
+ <asf>
+ <module type="service" id="lufa.drivers.usb.class" caption="LUFA USB Class Drivers">
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <info type="gui-flag" value="hidden"/>
+ <build type="doxygen-entry-point" value="Group_USBClassDrivers"/>
+
+ <require idref="lufa.drivers.usb.class.android"/>
+ <require idref="lufa.drivers.usb.class.audio"/>
+ <require idref="lufa.drivers.usb.class.cdc"/>
+ <require idref="lufa.drivers.usb.class.hid"/>
+ <require idref="lufa.drivers.usb.class.ms"/>
+ <require idref="lufa.drivers.usb.class.midi"/>
+ <require idref="lufa.drivers.usb.class.printer"/>
+ <require idref="lufa.drivers.usb.class.rndis"/>
+ <require idref="lufa.drivers.usb.class.si"/>
+ </module>
+ </asf>
+</lufa>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_android.xml b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_android.xml
new file mode 100644
index 000000000..345171257
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_android.xml
@@ -0,0 +1,54 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework integration file -->
+
+<lufa>
+ <asf>
+ <select-by-config id="lufa.drivers.usb.class.android" name="lufa.drivers.usb.class.android.mode" default="host" caption="LUFA USB Class Driver - Android Accessory">
+ <build type="doxygen-entry-point" value="Group_USBClassAOA"/>
+
+ <module type="service" id="lufa.drivers.usb.class.android#host" caption="LUFA USB Class Driver - Android Accessory (Host)">
+ <info type="description" value="summary">
+ Common definitions and Host mode implementation of the Android Open Accessory USB class.
+ </info>
+
+ <build type="doxygen-entry-point" value="Group_USBClassAOA"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/AndroidAccessoryClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/AndroidAccessoryClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/AndroidAccessoryClassHost.h"/>
+ <build type="c-source" value="Drivers/USB/Class/Host/AndroidAccessoryClassHost.c"/>
+ </module>
+
+ <module type="service" id="lufa.drivers.usb.class.android#definitions_only" caption="LUFA USB Class Driver - Android Accessory (Definitions Only)">
+ <info type="description" value="summary">
+ Common definitions only (no implementations) of the Android Open Accessory USB class.
+ </info>
+
+ <build type="doxygen-entry-point" value="Group_USBClassAOA"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/AndroidAccessoryClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/AndroidAccessoryClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/AndroidAccessoryClassHost.h"/>
+ </module>
+ </select-by-config>
+ </asf>
+</lufa>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_audio.xml b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_audio.xml
new file mode 100644
index 000000000..5f7c3ad4d
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_audio.xml
@@ -0,0 +1,109 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework integration file -->
+
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework integration file -->
+
+<lufa>
+ <asf>
+ <select-by-config id="lufa.drivers.usb.class.audio" name="lufa.drivers.usb.class.audio.mode" default="host_device" caption="LUFA USB Class Driver - Audio 1.0">
+ <build type="doxygen-entry-point" value="Group_USBClassAudio"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <module type="service" id="lufa.drivers.usb.class.audio#host_device" caption="LUFA USB Class Driver - Audio 1.0 (Host/Device)">
+ <info type="description" value="summary">
+ Common definitions and Host/Device mode implementations of the Audio 1.0 USB class.
+ </info>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <build type="doxygen-entry-point" value="Group_USBClassAudio"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/AudioClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/AudioClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Device/AudioClassDevice.h"/>
+ <build type="c-source" value="Drivers/USB/Class/Device/AudioClassDevice.c"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/AudioClassHost.h"/>
+ <build type="c-source" value="Drivers/USB/Class/Host/AudioClassHost.c"/>
+ </module>
+
+ <module type="service" id="lufa.drivers.usb.class.audio#host" caption="LUFA USB Class Driver - Audio 1.0 (Host)">
+ <info type="description" value="summary">
+ Common definitions and Host mode implementation of the Audio 1.0 USB class.
+ </info>
+
+ <build type="doxygen-entry-point" value="Group_USBClassAudio"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/AudioClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/AudioClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Device/AudioClassDevice.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/AudioClassHost.h"/>
+ <build type="c-source" value="Drivers/USB/Class/Host/AudioClassHost.c"/>
+ </module>
+
+ <module type="service" id="lufa.drivers.usb.class.audio#device" caption="LUFA USB Class Driver - Audio 1.0 (Device)">
+ <info type="description" value="summary">
+ Common definitions and Device mode implementation of the Audio 1.0 USB class.
+ </info>
+
+ <build type="doxygen-entry-point" value="Group_USBClassAudio"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/AudioClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/AudioClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Device/AudioClassDevice.h"/>
+ <build type="c-source" value="Drivers/USB/Class/Device/AudioClassDevice.c"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/AudioClassHost.h"/>
+ </module>
+
+ <module type="service" id="lufa.drivers.usb.class.audio#definitions_only" caption="LUFA USB Class Driver - Audio 1.0 (Definitions Only)">
+ <info type="description" value="summary">
+ Common definitions only (no implementations) of the Audio 1.0 USB class.
+ </info>
+
+ <build type="doxygen-entry-point" value="Group_USBClassAudio"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/AudioClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/AudioClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Device/AudioClassDevice.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/AudioClassHost.h"/>
+ </module>
+ </select-by-config>
+ </asf>
+</lufa>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_cdc.xml b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_cdc.xml
new file mode 100644
index 000000000..65d8cc98f
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_cdc.xml
@@ -0,0 +1,99 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework integration file -->
+
+<lufa>
+ <asf>
+ <select-by-config id="lufa.drivers.usb.class.cdc" name="lufa.drivers.usb.class.cdc.mode" default="host_device" caption="LUFA USB Class Driver - CDC">
+ <build type="doxygen-entry-point" value="Group_USBClassCDC"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <module type="service" id="lufa.drivers.usb.class.cdc#host_device" caption="LUFA USB Class Driver - CDC (Host/Device)">
+ <info type="description" value="summary">
+ Common definitions and Host/Device mode implementations of the CDC USB class.
+ </info>
+
+ <build type="doxygen-entry-point" value="Group_USBClassCDC"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/CDCClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/CDCClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Device/CDCClassDevice.h"/>
+ <build type="c-source" value="Drivers/USB/Class/Device/CDCClassDevice.c"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/CDCClassHost.h"/>
+ <build type="c-source" value="Drivers/USB/Class/Host/CDCClassHost.c"/>
+ </module>
+
+ <module type="service" id="lufa.drivers.usb.class.cdc#host" caption="LUFA USB Class Driver - CDC (Host)">
+ <info type="description" value="summary">
+ Common definitions and Host mode implementation of the CDC USB class.
+ </info>
+
+ <build type="doxygen-entry-point" value="Group_USBClassCDC"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/CDCClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/CDCClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Device/CDCClassDevice.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/CDCClassHost.h"/>
+ <build type="c-source" value="Drivers/USB/Class/Host/CDCClassHost.c"/>
+ </module>
+
+ <module type="service" id="lufa.drivers.usb.class.cdc#device" caption="LUFA USB Class Driver - CDC (Device)">
+ <info type="description" value="summary">
+ Common definitions and Device mode implementation of the CDC USB class.
+ </info>
+
+ <build type="doxygen-entry-point" value="Group_USBClassCDC"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/CDCClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/CDCClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Device/CDCClassDevice.h"/>
+ <build type="c-source" value="Drivers/USB/Class/Device/CDCClassDevice.c"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/CDCClassHost.h"/>
+ </module>
+
+ <module type="service" id="lufa.drivers.usb.class.cdc#definitions_only" caption="LUFA USB Class Driver - CDC (Definitions Only)">
+ <info type="description" value="summary">
+ Common definitions only (no implementations) of the CDC USB class.
+ </info>
+
+ <build type="doxygen-entry-point" value="Group_USBClassCDC"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/CDCClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/CDCClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Device/CDCClassDevice.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/CDCClassHost.h"/>
+ </module>
+ </select-by-config>
+ </asf>
+</lufa>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_hid.xml b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_hid.xml
new file mode 100644
index 000000000..3d533fb53
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_hid.xml
@@ -0,0 +1,99 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework integration file -->
+
+<lufa>
+ <asf>
+ <select-by-config id="lufa.drivers.usb.class.hid" name="lufa.drivers.usb.class.hid.mode" default="host_device" caption="LUFA USB Class Driver - HID">
+ <build type="doxygen-entry-point" value="Group_USBClassHID"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <module type="service" id="lufa.drivers.usb.class.hid#host_device" caption="LUFA USB Class Driver - HID (Host/Device)">
+ <info type="description" value="summary">
+ Common definitions and Host/Device mode implementations of the HID USB class.
+ </info>
+
+ <build type="doxygen-entry-point" value="Group_USBClassHID"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/HIDClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/HIDClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Device/HIDClassDevice.h"/>
+ <build type="c-source" value="Drivers/USB/Class/Device/HIDClassDevice.c"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/HIDClassHost.h"/>
+ <build type="c-source" value="Drivers/USB/Class/Host/HIDClassHost.c"/>
+ </module>
+
+ <module type="service" id="lufa.drivers.usb.class.hid#host" caption="LUFA USB Class Driver - HID (Host)">
+ <info type="description" value="summary">
+ Common definitions and Host mode implementation of the HID USB class.
+ </info>
+
+ <build type="doxygen-entry-point" value="Group_USBClassHID"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/HIDClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/HIDClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Device/HIDClassDevice.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/HIDClassHost.h"/>
+ <build type="c-source" value="Drivers/USB/Class/Host/HIDClassHost.c"/>
+ </module>
+
+ <module type="service" id="lufa.drivers.usb.class.hid#device" caption="LUFA USB Class Driver - HID (Device)">
+ <info type="description" value="summary">
+ Common definitions and Device mode implementation of the HID USB class.
+ </info>
+
+ <build type="doxygen-entry-point" value="Group_USBClassHID"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/HIDClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/HIDClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Device/HIDClassDevice.h"/>
+ <build type="c-source" value="Drivers/USB/Class/Device/HIDClassDevice.c"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/HIDClassHost.h"/>
+ </module>
+
+ <module type="service" id="lufa.drivers.usb.class.hid#definitions_only" caption="LUFA USB Class Driver - HID (Definitions Only)">
+ <info type="description" value="summary">
+ Common definitions only (no implementations) of the HID USB class.
+ </info>
+
+ <build type="doxygen-entry-point" value="Group_USBClassHID"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/HIDClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/HIDClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Device/HIDClassDevice.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/HIDClassHost.h"/>
+ </module>
+ </select-by-config>
+ </asf>
+</lufa>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_midi.xml b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_midi.xml
new file mode 100644
index 000000000..3ddab0bbd
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_midi.xml
@@ -0,0 +1,99 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework integration file -->
+
+<lufa>
+ <asf>
+ <select-by-config id="lufa.drivers.usb.class.midi" name="lufa.drivers.usb.class.midi.mode" default="host_device" caption="LUFA USB Class Driver - MIDI">
+ <build type="doxygen-entry-point" value="Group_USBClassMIDI"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <module type="service" id="lufa.drivers.usb.class.midi#host_device" caption="LUFA USB Class Driver - MIDI (Host/Device)">
+ <info type="description" value="summary">
+ Common definitions and Host/Device mode implementations of the MIDI USB class.
+ </info>
+
+ <build type="doxygen-entry-point" value="Group_USBClassMIDI"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/MIDIClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/MIDIClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Device/MIDIClassDevice.h"/>
+ <build type="c-source" value="Drivers/USB/Class/Device/MIDIClassDevice.c"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/MIDIClassHost.h"/>
+ <build type="c-source" value="Drivers/USB/Class/Host/MIDIClassHost.c"/>
+ </module>
+
+ <module type="service" id="lufa.drivers.usb.class.midi#host" caption="LUFA USB Class Driver - MIDI (Host)">
+ <info type="description" value="summary">
+ Common definitions and Host mode implementation of the MIDI USB class.
+ </info>
+
+ <build type="doxygen-entry-point" value="Group_USBClassMIDI"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/MIDIClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/MIDIClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Device/MIDIClassDevice.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/MIDIClassHost.h"/>
+ <build type="c-source" value="Drivers/USB/Class/Host/MIDIClassHost.c"/>
+ </module>
+
+ <module type="service" id="lufa.drivers.usb.class.midi#device" caption="LUFA USB Class Driver - MIDI (Device)">
+ <info type="description" value="summary">
+ Common definitions and Device mode implementation of the MIDI USB class.
+ </info>
+
+ <build type="doxygen-entry-point" value="Group_USBClassMIDI"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/MIDIClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/MIDIClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Device/MIDIClassDevice.h"/>
+ <build type="c-source" value="Drivers/USB/Class/Device/MIDIClassDevice.c"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/MIDIClassHost.h"/>
+ </module>
+
+ <module type="service" id="lufa.drivers.usb.class.midi#definitions_only" caption="LUFA USB Class Driver - MIDI (Definitions Only)">
+ <info type="description" value="summary">
+ Common definitions only (no implementations) of the MIDI USB class.
+ </info>
+
+ <build type="doxygen-entry-point" value="Group_USBClassMIDI"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/MIDIClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/MIDIClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Device/MIDIClassDevice.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/MIDIClassHost.h"/>
+ </module>
+ </select-by-config>
+ </asf>
+</lufa>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_ms.xml b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_ms.xml
new file mode 100644
index 000000000..283b85ca7
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_ms.xml
@@ -0,0 +1,99 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework integration file -->
+
+<lufa>
+ <asf>
+ <select-by-config id="lufa.drivers.usb.class.ms" name="lufa.drivers.usb.class.ms.mode" default="host_device" caption="LUFA USB Class Driver - Mass Storage">
+ <build type="doxygen-entry-point" value="Group_USBClassMS"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <module type="service" id="lufa.drivers.usb.class.ms#host_device" caption="LUFA USB Class Driver - Mass Storage (Host/Device)">
+ <info type="description" value="summary">
+ Common definitions and Host/Device mode implementations of the Mass Storage USB class.
+ </info>
+
+ <build type="doxygen-entry-point" value="Group_USBClassMS"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/MassStorageClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/MassStorageClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Device/MassStorageClassDevice.h"/>
+ <build type="c-source" value="Drivers/USB/Class/Device/MassStorageClassDevice.c"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/MassStorageClassHost.h"/>
+ <build type="c-source" value="Drivers/USB/Class/Host/MassStorageClassHost.c"/>
+ </module>
+
+ <module type="service" id="lufa.drivers.usb.class.ms#host" caption="LUFA USB Class Driver - Mass Storage (Host)">
+ <info type="description" value="summary">
+ Common definitions and Host mode implementation of the Mass Storage USB class.
+ </info>
+
+ <build type="doxygen-entry-point" value="Group_USBClassMS"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/MassStorageClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/MassStorageClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Device/MassStorageClassDevice.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/MassStorageClassHost.h"/>
+ <build type="c-source" value="Drivers/USB/Class/Host/MassStorageClassHost.c"/>
+ </module>
+
+ <module type="service" id="lufa.drivers.usb.class.ms#device" caption="LUFA USB Class Driver - Mass Storage (Device)">
+ <info type="description" value="summary">
+ Common definitions and Device mode implementation of the Mass Storage USB class.
+ </info>
+
+ <build type="doxygen-entry-point" value="Group_USBClassMS"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/MassStorageClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/MassStorageClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Device/MassStorageClassDevice.h"/>
+ <build type="c-source" value="Drivers/USB/Class/Device/MassStorageClassDevice.c"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/MassStorageClassHost.h"/>
+ </module>
+
+ <module type="service" id="lufa.drivers.usb.class.ms#definitions_only" caption="LUFA USB Class Driver - Mass Storage (Definitions Only)">
+ <info type="description" value="summary">
+ Common definitions only (no implementations) of the Mass Storage USB class.
+ </info>
+
+ <build type="doxygen-entry-point" value="Group_USBClassMS"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/MassStorageClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/MassStorageClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Device/MassStorageClassDevice.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/MassStorageClassHost.h"/>
+ </module>
+ </select-by-config>
+ </asf>
+</lufa>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_printer.xml b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_printer.xml
new file mode 100644
index 000000000..2465035ce
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_printer.xml
@@ -0,0 +1,99 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework integration file -->
+
+<lufa>
+ <asf>
+ <select-by-config id="lufa.drivers.usb.class.printer" name="lufa.drivers.usb.class.printer.mode" default="host_device" caption="LUFA USB Class Driver - Printer">
+ <build type="doxygen-entry-point" value="Group_USBClassPrinter"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <module type="service" id="lufa.drivers.usb.class.printer#host_device" caption="LUFA USB Class Driver - Printer (Host/Device)">
+ <info type="description" value="summary">
+ Common definitions and Host/Device mode implementations of the Printer USB class.
+ </info>
+
+ <build type="doxygen-entry-point" value="Group_USBClassPrinter"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/PrinterClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/PrinterClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Device/PrinterClassDevice.h"/>
+ <build type="c-source" value="Drivers/USB/Class/Device/PrinterClassDevice.c"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/PrinterClassHost.h"/>
+ <build type="c-source" value="Drivers/USB/Class/Host/PrinterClassHost.c"/>
+ </module>
+
+ <module type="service" id="lufa.drivers.usb.class.printer#host" caption="LUFA USB Class Driver - Printer (Host)">
+ <info type="description" value="summary">
+ Common definitions and Host mode implementation of the Printer USB class.
+ </info>
+
+ <build type="doxygen-entry-point" value="Group_USBClassPrinter"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/PrinterClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/PrinterClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Device/PrinterClassDevice.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/PrinterClassHost.h"/>
+ <build type="c-source" value="Drivers/USB/Class/Host/PrinterClassHost.c"/>
+ </module>
+
+ <module type="service" id="lufa.drivers.usb.class.printer#device" caption="LUFA USB Class Driver - Printer (Device)">
+ <info type="description" value="summary">
+ Common definitions and Device mode implementation of the Printer USB class.
+ </info>
+
+ <build type="doxygen-entry-point" value="Group_USBClassPrinter"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/PrinterClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/PrinterClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Device/PrinterClassDevice.h"/>
+ <build type="c-source" value="Drivers/USB/Class/Device/PrinterClassDevice.c"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/PrinterClassHost.h"/>
+ </module>
+
+ <module type="service" id="lufa.drivers.usb.class.printer#definitions_only" caption="LUFA USB Class Driver - Printer (Definitions Only)">
+ <info type="description" value="summary">
+ Common definitions only (no implementations) of the Printer USB class.
+ </info>
+
+ <build type="doxygen-entry-point" value="Group_USBClassPrinter"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/PrinterClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/PrinterClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Device/PrinterClassDevice.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/PrinterClassHost.h"/>
+ </module>
+ </select-by-config>
+ </asf>
+</lufa>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_rndis.xml b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_rndis.xml
new file mode 100644
index 000000000..6a606679d
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_rndis.xml
@@ -0,0 +1,99 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework integration file -->
+
+<lufa>
+ <asf>
+ <select-by-config id="lufa.drivers.usb.class.rndis" name="lufa.drivers.usb.class.rndis.mode" default="host_device" caption="LUFA USB Class Driver - RNDIS Ethernet">
+ <build type="doxygen-entry-point" value="Group_USBClassRNDIS"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <module type="service" id="lufa.drivers.usb.class.rndis#host_device" caption="LUFA USB Class Driver - RNDIS Ethernet (Host/Device)">
+ <info type="description" value="summary">
+ Common definitions and Host/Device mode implementations of the RNDIS Ethernet USB class.
+ </info>
+
+ <build type="doxygen-entry-point" value="Group_USBClassRNDIS"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/RNDISClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/RNDISClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Device/RNDISClassDevice.h"/>
+ <build type="c-source" value="Drivers/USB/Class/Device/RNDISClassDevice.c"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/RNDISClassHost.h"/>
+ <build type="c-source" value="Drivers/USB/Class/Host/RNDISClassHost.c"/>
+ </module>
+
+ <module type="service" id="lufa.drivers.usb.class.rndis#host" caption="LUFA USB Class Driver - RNDIS Ethernet (Host)">
+ <info type="description" value="summary">
+ Common definitions and Host mode implementation of the RNDIS Ethernet USB class.
+ </info>
+
+ <build type="doxygen-entry-point" value="Group_USBClassRNDIS"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/RNDISClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/RNDISClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Device/RNDISClassDevice.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/RNDISClassHost.h"/>
+ <build type="c-source" value="Drivers/USB/Class/Host/RNDISClassHost.c"/>
+ </module>
+
+ <module type="service" id="lufa.drivers.usb.class.rndis#device" caption="LUFA USB Class Driver - RNDIS Ethernet (Device)">
+ <info type="description" value="summary">
+ Common definitions and Device mode implementation of the RNDIS Ethernet USB class.
+ </info>
+
+ <build type="doxygen-entry-point" value="Group_USBClassRNDIS"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/RNDISClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/RNDISClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Device/RNDISClassDevice.h"/>
+ <build type="c-source" value="Drivers/USB/Class/Device/RNDISClassDevice.c"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/RNDISClassHost.h"/>
+ </module>
+
+ <module type="service" id="lufa.drivers.usb.class.rndis#definitions_only" caption="LUFA USB Class Driver - RNDIS Ethernet (Definitions Only)">
+ <info type="description" value="summary">
+ Common definitions only (no implementations) of the RNDIS Ethernet USB class.
+ </info>
+
+ <build type="doxygen-entry-point" value="Group_USBClassRNDIS"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/RNDISClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/RNDISClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Device/RNDISClassDevice.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/RNDISClassHost.h"/>
+ </module>
+ </select-by-config>
+ </asf>
+</lufa>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_si.xml b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_si.xml
new file mode 100644
index 000000000..c1bf8d560
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_class_si.xml
@@ -0,0 +1,56 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework integration file -->
+
+<lufa>
+ <asf>
+ <select-by-config id="lufa.drivers.usb.class.si" name="lufa.drivers.usb.class.si.mode" default="host" caption="LUFA USB Class Driver - Still Image">
+ <build type="doxygen-entry-point" value="Group_USBClassSI"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <module type="service" id="lufa.drivers.usb.class.si#host" caption="LUFA USB Class Driver - Still Image (Host)">
+ <info type="description" value="summary">
+ Common definitions and Host mode implementation of the Still Image USB class.
+ </info>
+
+ <build type="doxygen-entry-point" value="Group_USBClassSI"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/StillImageClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/StillImageClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/StillImageClassHost.h"/>
+ <build type="c-source" value="Drivers/USB/Class/Host/StillImageClassHost.c"/>
+ </module>
+
+ <module type="service" id="lufa.drivers.usb.class.si#definitions_only" caption="LUFA USB Class Driver - Still Image (Definitions Only)">
+ <info type="description" value="summary">
+ Common definitions only (no implementations) of the Still Image USB class.
+ </info>
+
+ <build type="doxygen-entry-point" value="Group_USBClassSI"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="header-file" value="Drivers/USB/Class/StillImageClass.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/StillImageClassCommon.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Host/StillImageClassHost.h"/>
+ </module>
+ </select-by-config>
+ </asf>
+</lufa>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_core.xml b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_core.xml
new file mode 100644
index 000000000..58f8917ef
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_core.xml
@@ -0,0 +1,85 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework integration file -->
+
+<lufa>
+ <asf>
+ <module type="driver" id="lufa.drivers.usb.core.common" caption="LUFA USB Core Driver - Common">
+ <device-support-alias value="lufa_avr8"/>
+ <device-support-alias value="lufa_xmega"/>
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="doxygen-entry-point" value="Group_USBManagement"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <build type="header-file" value="Drivers/USB/Core/Device.h"/>
+ <build type="header-file" value="Drivers/USB/Core/Endpoint.h"/>
+ <build type="header-file" value="Drivers/USB/Core/Host.h"/>
+ <build type="header-file" value="Drivers/USB/Core/Pipe.h"/>
+ <build type="header-file" value="Drivers/USB/Core/OTG.h"/>
+ <build type="header-file" value="Drivers/USB/Core/USBController.h"/>
+ <build type="header-file" value="Drivers/USB/Core/USBInterrupt.h"/>
+ <build type="header-file" value="Drivers/USB/Core/EndpointStream.h"/>
+ <build type="header-file" value="Drivers/USB/Core/PipeStream.h"/>
+ <build type="c-source" value="Drivers/USB/Core/ConfigDescriptors.c"/>
+ <build type="header-file" value="Drivers/USB/Core/ConfigDescriptors.h"/>
+ <build type="c-source" value="Drivers/USB/Core/DeviceStandardReq.c"/>
+ <build type="header-file" value="Drivers/USB/Core/DeviceStandardReq.h"/>
+ <build type="c-source" value="Drivers/USB/Core/Events.c"/>
+ <build type="header-file" value="Drivers/USB/Core/Events.h"/>
+ <build type="c-source" value="Drivers/USB/Core/HostStandardReq.c"/>
+ <build type="header-file" value="Drivers/USB/Core/HostStandardReq.h"/>
+ <build type="c-source" value="Drivers/USB/Core/USBTask.c"/>
+ <build type="header-file" value="Drivers/USB/Core/USBTask.h"/>
+ <build type="header-file" value="Drivers/USB/Core/USBMode.h"/>
+ <build type="header-file" value="Drivers/USB/Core/StdDescriptors.h"/>
+ <build type="header-file" value="Drivers/USB/Core/StdRequestType.h"/>
+
+ <build type="c-source" value="Drivers/USB/Class/Common/HIDParser.c"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/HIDParser.h"/>
+ <build type="header-file" value="Drivers/USB/Class/Common/HIDReportData.h"/>
+ </module>
+
+ <select-by-device id="lufa.drivers.usb.core" caption="LUFA USB Core Driver">
+ <module type="driver" id="lufa.drivers.usb.core#avr8" caption="LUFA USB Core Driver - AVR8">
+ <device-support-alias value="lufa_avr8"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <build type="doxygen-entry-point" value="Group_USBManagement_AVR8"/>
+
+ <require idref="lufa.drivers.usb.core.common"/>
+ <require idref="lufa.drivers.usb.core.avr8"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.usb.core#xmega" caption="LUFA USB Core Driver - XMEGA">
+ <device-support-alias value="lufa_xmega"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <build type="doxygen-entry-point" value="Group_USBManagement_XMEGA"/>
+
+ <require idref="lufa.drivers.usb.core.common"/>
+ <require idref="lufa.drivers.usb.core.xmega"/>
+ </module>
+
+ <module type="driver" id="lufa.drivers.usb.core#uc3" caption="LUFA USB Core Driver - UC3">
+ <device-support-alias value="lufa_uc3"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <build type="doxygen-entry-point" value="Group_USBManagement_UC3"/>
+
+ <require idref="lufa.drivers.usb.core.common"/>
+ <require idref="lufa.drivers.usb.core.uc3"/>
+ </module>
+ </select-by-device>
+ </asf>
+</lufa>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_core_avr8.xml b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_core_avr8.xml
new file mode 100644
index 000000000..166b9257a
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_core_avr8.xml
@@ -0,0 +1,43 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework integration file -->
+
+<lufa>
+ <asf>
+ <module type="driver" id="lufa.drivers.usb.core.avr8" caption="LUFA USB Core Driver for AVR8">
+ <device-support-alias value="lufa_avr8"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <build type="doxygen-entry-point" value="Group_USBManagement_AVR8"/>
+
+ <build type="c-source" value="Drivers/USB/Core/AVR8/Template/Template_Endpoint_Control_R.c"/>
+ <build type="c-source" value="Drivers/USB/Core/AVR8/Template/Template_Endpoint_Control_W.c"/>
+ <build type="c-source" value="Drivers/USB/Core/AVR8/Template/Template_Endpoint_RW.c"/>
+ <build type="c-source" value="Drivers/USB/Core/AVR8/Template/Template_Pipe_RW.c"/>
+ <build type="c-source" value="Drivers/USB/Core/AVR8/Device_AVR8.c"/>
+ <build type="header-file" value="Drivers/USB/Core/AVR8/Device_AVR8.h"/>
+ <build type="c-source" value="Drivers/USB/Core/AVR8/Endpoint_AVR8.c"/>
+ <build type="header-file" value="Drivers/USB/Core/AVR8/Endpoint_AVR8.h"/>
+ <build type="c-source" value="Drivers/USB/Core/AVR8/Host_AVR8.c"/>
+ <build type="header-file" value="Drivers/USB/Core/AVR8/Host_AVR8.h"/>
+ <build type="c-source" value="Drivers/USB/Core/AVR8/Pipe_AVR8.c"/>
+ <build type="header-file" value="Drivers/USB/Core/AVR8/Pipe_AVR8.h"/>
+ <build type="header-file" value="Drivers/USB/Core/AVR8/OTG_AVR8.h"/>
+ <build type="c-source" value="Drivers/USB/Core/AVR8/USBController_AVR8.c"/>
+ <build type="header-file" value="Drivers/USB/Core/AVR8/USBController_AVR8.h"/>
+ <build type="c-source" value="Drivers/USB/Core/AVR8/USBInterrupt_AVR8.c"/>
+ <build type="header-file" value="Drivers/USB/Core/AVR8/USBInterrupt_AVR8.h"/>
+ <build type="c-source" value="Drivers/USB/Core/AVR8/EndpointStream_AVR8.c"/>
+ <build type="header-file" value="Drivers/USB/Core/AVR8/EndpointStream_AVR8.h"/>
+ <build type="c-source" value="Drivers/USB/Core/AVR8/PipeStream_AVR8.c"/>
+ <build type="header-file" value="Drivers/USB/Core/AVR8/PipeStream_AVR8.h"/>
+ </module>
+ </asf>
+</lufa>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_core_uc3.xml b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_core_uc3.xml
new file mode 100644
index 000000000..7e0540cda
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_core_uc3.xml
@@ -0,0 +1,42 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework integration file -->
+
+<lufa>
+ <asf>
+ <module type="driver" id="lufa.drivers.usb.core.uc3" caption="LUFA USB Core Driver for UC3">
+ <device-support-alias value="lufa_uc3"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <build type="doxygen-entry-point" value="Group_USBManagement_UC3"/>
+
+ <build type="c-source" value="Drivers/USB/Core/UC3/Template/Template_Endpoint_Control_R.c"/>
+ <build type="c-source" value="Drivers/USB/Core/UC3/Template/Template_Endpoint_Control_W.c"/>
+ <build type="c-source" value="Drivers/USB/Core/UC3/Template/Template_Endpoint_RW.c"/>
+ <build type="c-source" value="Drivers/USB/Core/UC3/Template/Template_Pipe_RW.c"/>
+ <build type="c-source" value="Drivers/USB/Core/UC3/Device_UC3.c"/>
+ <build type="header-file" value="Drivers/USB/Core/UC3/Device_UC3.h"/>
+ <build type="c-source" value="Drivers/USB/Core/UC3/Endpoint_UC3.c"/>
+ <build type="header-file" value="Drivers/USB/Core/UC3/Endpoint_UC3.h"/>
+ <build type="c-source" value="Drivers/USB/Core/UC3/Host_UC3.c"/>
+ <build type="header-file" value="Drivers/USB/Core/UC3/Host_UC3.h"/>
+ <build type="c-source" value="Drivers/USB/Core/UC3/Pipe_UC3.c"/>
+ <build type="header-file" value="Drivers/USB/Core/UC3/Pipe_UC3.h"/>
+ <build type="c-source" value="Drivers/USB/Core/UC3/USBController_UC3.c"/>
+ <build type="header-file" value="Drivers/USB/Core/UC3/USBController_UC3.h"/>
+ <build type="c-source" value="Drivers/USB/Core/UC3/USBInterrupt_UC3.c"/>
+ <build type="header-file" value="Drivers/USB/Core/UC3/USBInterrupt_UC3.h"/>
+ <build type="c-source" value="Drivers/USB/Core/UC3/EndpointStream_UC3.c"/>
+ <build type="header-file" value="Drivers/USB/Core/UC3/EndpointStream_UC3.h"/>
+ <build type="c-source" value="Drivers/USB/Core/UC3/PipeStream_UC3.c"/>
+ <build type="header-file" value="Drivers/USB/Core/UC3/PipeStream_UC3.h"/>
+ </module>
+ </asf>
+</lufa>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_core_xmega.xml b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_core_xmega.xml
new file mode 100644
index 000000000..9e9f4f6a1
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_drivers_usb_core_xmega.xml
@@ -0,0 +1,36 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework integration file -->
+
+<lufa>
+ <asf>
+ <module type="driver" id="lufa.drivers.usb.core.xmega" caption="LUFA USB Core Driver for XMEGA">
+ <device-support-alias value="lufa_xmega"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <build type="doxygen-entry-point" value="Group_USBManagement_XMEGA"/>
+
+ <build type="c-source" value="Drivers/USB/Core/XMEGA/Template/Template_Endpoint_Control_R.c"/>
+ <build type="c-source" value="Drivers/USB/Core/XMEGA/Template/Template_Endpoint_Control_W.c"/>
+ <build type="c-source" value="Drivers/USB/Core/XMEGA/Template/Template_Endpoint_RW.c"/>
+ <build type="c-source" value="Drivers/USB/Core/XMEGA/Device_XMEGA.c"/>
+ <build type="header-file" value="Drivers/USB/Core/XMEGA/Device_XMEGA.h"/>
+ <build type="c-source" value="Drivers/USB/Core/XMEGA/Endpoint_XMEGA.c"/>
+ <build type="header-file" value="Drivers/USB/Core/XMEGA/Endpoint_XMEGA.h"/>
+ <build type="c-source" value="Drivers/USB/Core/XMEGA/Pipe_XMEGA.c"/>
+ <build type="c-source" value="Drivers/USB/Core/XMEGA/USBController_XMEGA.c"/>
+ <build type="header-file" value="Drivers/USB/Core/XMEGA/USBController_XMEGA.h"/>
+ <build type="c-source" value="Drivers/USB/Core/XMEGA/USBInterrupt_XMEGA.c"/>
+ <build type="header-file" value="Drivers/USB/Core/XMEGA/USBInterrupt_XMEGA.h"/>
+ <build type="c-source" value="Drivers/USB/Core/XMEGA/EndpointStream_XMEGA.c"/>
+ <build type="header-file" value="Drivers/USB/Core/XMEGA/EndpointStream_XMEGA.h"/>
+ </module>
+ </asf>
+</lufa>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_platform.xml b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_platform.xml
new file mode 100644
index 000000000..02c7463ee
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_platform.xml
@@ -0,0 +1,60 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework integration file -->
+
+<lufa>
+ <asf>
+ <select-by-device id="lufa.platform" caption="LUFA Platform Specific Support">
+ <module type="service" id="lufa.platform#avr8" caption="LUFA Platform Specific Support - AVR8">
+ <device-support-alias value="lufa_avr8"/>
+
+ <build type="define" name="ARCH" value="ARCH_AVR8"/>
+
+ <build type="doxygen-entry-point" value="Group_PlatformDrivers"/>
+
+ <build type="include-path" value=".."/>
+ <build type="header-file" subtype="api" value="Platform/Platform.h"/>
+
+ <require idref="lufa.common"/>
+ </module>
+
+ <module type="service" id="lufa.platform#xmega" caption="LUFA Platform Specific Support - XMEGA">
+ <device-support-alias value="lufa_xmega"/>
+
+ <build type="define" name="ARCH" value="ARCH_XMEGA"/>
+
+ <build type="doxygen-entry-point" value="Group_PlatformDrivers"/>
+
+ <build type="include-path" value=".."/>
+ <build type="header-file" subtype="api" value="Platform/Platform.h"/>
+
+ <build type="distribute" value="Platform/XMEGA/XMEGAExperimentalInfo.txt" subtype="license"/>
+
+ <require idref="lufa.platform.xmega"/>
+ <require idref="lufa.common"/>
+ </module>
+
+ <module type="service" id="lufa.platform#uc3" caption="LUFA Platform Specific Support - UC3">
+ <device-support-alias value="lufa_uc3"/>
+
+ <build type="define" name="ARCH" value="ARCH_UC3"/>
+
+ <build type="doxygen-entry-point" value="Group_PlatformDrivers"/>
+
+ <build type="include-path" value=".."/>
+ <build type="header-file" subtype="api" value="Platform/Platform.h"/>
+
+ <build type="distribute" value="Platform/UC3/UC3ExperimentalInfo.txt" subtype="license"/>
+
+ <require idref="lufa.platform.uc3"/>
+ <require idref="lufa.common"/>
+ </module>
+ </select-by-device>
+ </asf>
+</lufa>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_platform_uc3.xml b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_platform_uc3.xml
new file mode 100644
index 000000000..a488c4b83
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_platform_uc3.xml
@@ -0,0 +1,26 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework integration file -->
+
+<lufa>
+ <asf>
+ <module type="driver" id="lufa.platform.uc3" caption="LUFA UC3 Platform Drivers">
+ <device-support-alias value="lufa_uc3"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <build type="doxygen-entry-point" value="Group_PlatformDrivers_UC3"/>
+
+ <build type="header-file" value="Platform/UC3/ClockManagement.h"/>
+ <build type="header-file" value="Platform/UC3/InterruptManagement.h"/>
+ <build type="c-source" value="Platform/UC3/InterruptManagement.c"/>
+ <build type="asm-source" value="Platform/UC3/Exception.S"/>
+ </module>
+ </asf>
+</lufa>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_platform_xmega.xml b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_platform_xmega.xml
new file mode 100644
index 000000000..1674a77b0
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_platform_xmega.xml
@@ -0,0 +1,23 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework integration file -->
+
+<lufa>
+ <asf xmlversion="1.0">
+ <module type="driver" id="lufa.platform.xmega" caption="LUFA XMEGA Platform Drivers">
+ <device-support-alias value="lufa_xmega"/>
+
+ <info type="gui-flag" value="hidden"/>
+
+ <build type="doxygen-entry-point" value="Group_PlatformDrivers_XMEGA"/>
+
+ <build type="header-file" value="Platform/XMEGA/ClockManagement.h"/>
+ </module>
+ </asf>
+</lufa>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_toolchain.xml b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_toolchain.xml
new file mode 100644
index 000000000..031c8a2be
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/lufa_toolchain.xml
@@ -0,0 +1,43 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2013.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Atmel Studio framework integration file -->
+
+<lufa>
+ <asf>
+ <select-by-device id="common.utils.toolchain_config" caption="Toolchain configuration defaults">
+ <module type="build-specific" id="common.utils.toolchain_config#avr" caption="Toolchain configuration defaults for 8-bit AVR">
+ <info type="gui-flag" value="hidden"/>
+ <device-support value="avr"/>
+
+ <toolchain-config name="avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned" value="True" toolchain="avrgcc"/>
+ <toolchain-config name="avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned" value="True" toolchain="avrgcc"/>
+ <toolchain-config name="avrgcc.compiler.optimization.OtherFlags" value="-fdata-sections" toolchain="avrgcc"/>
+ <toolchain-config name="avrgcc.compiler.optimization.PrepareFunctionsForGarbageCollection" value="True" toolchain="avrgcc"/>
+ <toolchain-config name="avrgcc.compiler.warnings.AllWarnings" value="True" toolchain="avrgcc"/>
+ <toolchain-config name="avrgcc.compiler.miscellaneous.OtherFlags" value="-mrelax -std=gnu99 -fno-strict-aliasing -fno-jump-tables" toolchain="avrgcc"/>
+ <toolchain-config name="avrgcc.linker.optimization.GarbageCollectUnusedSections" value="True" toolchain="avrgcc"/>
+ <toolchain-config name="avrgcc.linker.optimization.RelaxBranches" value="True" toolchain="avrgcc"/>
+ </module>
+ </select-by-device>
+
+ <module type="build-specific" id="common.utils.toolchain_config#uc3" caption="Toolchain configuration defaults for 32-bit AVR">
+ <info type="gui-flag" value="hidden"/>
+ <device-support value="uc3"/>
+
+ <toolchain-config name="avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned" value="True" toolchain="avr32gcc"/>
+ <toolchain-config name="avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned" value="True" toolchain="avr32gcc"/>
+ <toolchain-config name="avr32gcc.compiler.optimization.OtherFlags" value="-fdata-sections" toolchain="avr32gcc"/>
+ <toolchain-config name="avr32gcc.compiler.optimization.PrepareFunctionsForGarbageCollection" value="True" toolchain="avr32gcc"/>
+ <toolchain-config name="avr32gcc.compiler.warnings.AllWarnings" value="True" toolchain="avr32gcc"/>
+ <toolchain-config name="avr32gcc.compiler.miscellaneous.OtherFlags" value="-mrelax -std=gnu99 -fno-strict-aliasing -mno-cond-exec-before-reload" toolchain="avr32gcc"/>
+ <toolchain-config name="avr32gcc.linker.optimization.GarbageCollectUnusedSections" value="True" toolchain="avr32gcc"/>
+ <toolchain-config name="avr32gcc.linker.optimization.RelaxBranches" value="True" toolchain="avr32gcc"/>
+ </module>
+ </asf>
+</lufa>
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/makefile b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/makefile
new file mode 100644
index 000000000..9d6329b5f
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/StudioIntegration/makefile
@@ -0,0 +1,140 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2013.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+# ---------------------------------------
+# Makefile for the LUFA Atmel Studio Integration.
+# ---------------------------------------
+
+LUFA_ROOT := ..
+LUFA_VERSION_NUM := $(shell grep LUFA_VERSION_STRING $(LUFA_ROOT)/Version.h | cut -d'"' -f2)
+
+ifneq ($(LUFA_VERSION_NUM),000000)
+ EXT_VERSION_NUM := $(shell date +"%y.%m.%d").$(LUFA_VERSION_NUM)
+ EXT_VSIX_NAME := LUFA-RELEASE-$(LUFA_VERSION_NUM).vsix
+else
+ EXT_VERSION_NUM := 0.$(shell date +"%y%m%d.%H%M%S")
+ EXT_VSIX_NAME := LUFA-TESTING-$(shell date +"%y.%m.%d-%H.%M.%S").vsix
+
+ $(warning No LUFA version set - assuming a test version should be created.)
+endif
+
+DOXYGEN_TAG_FILE_XML := $(LUFA_ROOT)/Documentation/lufa_doc_tags.xml
+DOXYGEN_COMBINED_XML := $(LUFA_ROOT)/Documentation/xml/lufa_doc.xml
+TEMP_MANIFEST_XML := manifest.xml
+EXTENSION_OUTPUT_XML := $(LUFA_ROOT)/../extension.xml
+MODULE_OUTPUT_XML := $(LUFA_ROOT)/asf.xml
+MSHELP_OUTPUT_XML := $(LUFA_ROOT)/../lufa_help_$(EXT_VERSION_NUM).mshc
+XML_FILES := $(filter-out $(TEMP_MANIFEST_FILE), $(shell ls *.xml))
+VSIX_ASSETS := $(LUFA_ROOT)/DoxygenPages/Images/LUFA_thumb.png \
+ $(LUFA_ROOT)/DoxygenPages/Images/LUFA.png \
+ $(LUFA_ROOT)/License.txt \
+ VSIX/"[Content_Types].xml" \
+ VSIX/LUFA.dll \
+ VSIX/LUFA.pkgdef
+VSIX_GEN_PARAMS := --stringparam extension-version "$(EXT_VERSION_NUM)" \
+ --stringparam lufa-version "$(LUFA_VERSION_NUM)"
+MSHELP_GEN_PARAMS := --stringparam generate.toc "book toc" \
+ --stringparam chunk.quietly "1" \
+ --stringparam chunk.section.depth "3" \
+ --stringparam chunk.first.sections "1" \
+ --stringparam chapter.autolabel "0" \
+ --stringparam root.filename "LUFA" \
+ --stringparam html.stylesheet "lufa_studio_help_styling.css"
+
+all: clear_project_dirs generate_xml check_filenames generate_vsix
+
+clear_project_dirs:
+ @make -s -C $(LUFA_ROOT)/.. clean
+
+clean:
+ @rm -f $(TEMP_MANIFEST_XML) $(MODULE_OUTPUT_XML) $(EXTENSION_OUTPUT_XML) $(DOXYGEN_TAG_FILE_XML) $(DOXYGEN_COMBINED_XML) $(MSHELP_OUTPUT_XML)
+ @rm -rf mshelp
+ @cd $(LUFA_ROOT)/.. && rm -f contents.zip exampleProjects.xml content.xml.cache extension.vsixmanifest asf-manifest.xml extension.xml helpcontentsetup.msha $(notdir $(VSIX_ASSETS)) *.vsix *.mshc
+
+$(DOXYGEN_TAG_FILE_XML):
+ @$(MAKE) -C ../ doxygen DOXYGEN_OVERRIDE_PARAMS="GENERATE_TAGFILE=Documentation/lufa_doc_tags.xml GENERATE_HTML=no GENERATE_XML=yes"
+
+$(DOXYGEN_COMBINED_XML): $(DOXYGEN_TAG_FILE_XML)
+ @xsltproc $(dir $@)/combine.xslt $(dir $@)/index.xml > $(DOXYGEN_COMBINED_XML)
+
+$(TEMP_MANIFEST_XML): $(DOXYGEN_TAG_FILE_XML) $(DOXYGEN_COMBINED_XML)
+ @echo Generating temporary module manifest XML...
+
+ @printf "<lufa-manifest version=\"%s\" tagfile=\"%s\" docfile=\"%s\">\n" $(LUFA_VERSION_NUM) $(DOXYGEN_TAG_FILE_XML) $(DOXYGEN_COMBINED_XML) > $@
+ @for i in $(XML_FILES); do \
+ printf "\t<xml-source filename=\"%s\"/>\n" $$i >> $@; \
+ done;
+ @echo '</lufa-manifest>' >> $@
+
+$(MODULE_OUTPUT_XML): $(TEMP_MANIFEST_XML)
+ @echo Generating library core XDK module manifest file...
+ @xsltproc XDK/lufa_module_transform.xslt $< | xsltproc XDK/lufa_indent_transform.xslt - > $(MODULE_OUTPUT_XML)
+
+$(EXTENSION_OUTPUT_XML): $(TEMP_MANIFEST_XML)
+ @echo Generating library XDK extension manifest file...
+ @xsltproc XDK/lufa_extension_transform.xslt $< | xsltproc XDK/lufa_indent_transform.xslt - > $(EXTENSION_OUTPUT_XML)
+
+$(MSHELP_OUTPUT_XML): $(DOXYGEN_COMBINED_XML)
+ @echo Converting Doxygen XML to DocBook...
+ @-mkdir mshelp 2> /dev/null
+ @xsltproc HV1/lufa_docbook_transform.xslt $(DOXYGEN_COMBINED_XML) > mshelp/lufa_docbook.xml
+
+ @echo Converting DocBook XML to Microsoft Help 1.0...
+ @cd mshelp && xsltproc $(MSHELP_GEN_PARAMS) ../HV1/lufa_hv1_transform.xslt lufa_docbook.xml
+
+ @echo Copying help assets...
+ @cp HV1/lufa_studio_help_styling.css mshelp
+ @-mkdir mshelp/images 2> /dev/null
+ @cp `find $(LUFA_ROOT)/DoxygenPages/Images -type f` mshelp/images
+
+ @echo Archiving help content...
+ @cd mshelp && zip ../$(MSHELP_OUTPUT_XML) -q -0 -r *.html *.css images
+
+ @echo Generating HV1 manifest...
+ @xsltproc $(VSIX_GEN_PARAMS) HV1/lufa_helpcontentsetup_transform.xslt HV1/helpcontentsetup.msha > $(LUFA_ROOT)/../helpcontentsetup.msha
+
+generate_help: $(MSHELP_OUTPUT_XML)
+
+generate_xml: $(EXTENSION_OUTPUT_XML) $(MODULE_OUTPUT_XML)
+
+generate_vsix: $(EXTENSION_OUTPUT_XML) $(MODULE_OUTPUT_XML) $(MSHELP_OUTPUT_XML)
+ @echo Generating XDK cache files...
+ @rm -f $(LUFA_ROOT)/../content.xml.cache
+ @rm -f $(LUFA_ROOT)/../ExampleProjects.xml
+ @python VSIX/generate_caches.py $(LUFA_ROOT)/../
+
+ @echo Archiving XDK content...
+ @rm -f contents.zip
+ @cd $(LUFA_ROOT)/../ && zip contents.zip -q -0 -r --exclude=*Documentation* --exclude=*StudioIntegration* LUFA Bootloaders Demos Projects readme.txt
+
+ @echo Creating VSIX dependencies...
+ @cp $(VSIX_ASSETS) $(LUFA_ROOT)/..
+ @xsltproc $(VSIX_GEN_PARAMS) VSIX/lufa_vsmanifest_transform.xslt VSIX/extension.vsixmanifest > $(LUFA_ROOT)/../extension.vsixmanifest
+ @xsltproc $(VSIX_GEN_PARAMS) VSIX/lufa_asfmanifest_transform.xslt VSIX/asf-manifest.xml > $(LUFA_ROOT)/../asf-manifest.xml
+
+ @echo Generating Atmel Studio VSIX file...
+ cd $(LUFA_ROOT)/../ && zip $(EXT_VSIX_NAME) -q -9 contents.zip exampleProjects.xml content.xml.cache extension.vsixmanifest asf-manifest.xml extension.xml helpcontentsetup.msha $(notdir $(MSHELP_OUTPUT_XML)) $(notdir $(VSIX_ASSETS))
+
+ @echo "Atmel Studio VSIX extension file generated."
+
+check_filenames: $(MODULE_OUTPUT_XML)
+ @echo Verifying referenced filenames of XDK modules...
+ @for f in `find $(LUFA_ROOT)/../ -name "asf.xml"`; do \
+ echo "Checking $$f..."; \
+ asf_file_dir=`dirname $$f`; \
+ xsltproc XDK/lufa_filelist_transform.xslt $$f | sed -e "/^$$/d" | while read -r i; do \
+ if ( ( ! test -f "$$asf_file_dir/$$i" ) && ( ! test -d "$$asf_file_dir/$$i" ) ); then \
+ echo "Source file \"$$i\" referenced in $$f does not exist!"; \
+ exit 1; \
+ fi; \
+ done || exit 1; \
+ done;
+
+check_database:
+ python ProjectGenerator/project_generator.py -b $(LUFA_ROOT)/../ --main-ext-uuid=0e160d5c-e331-48d9-850b-e0387912171b CHECK
+
+.PHONY: all clean generate_help generate_xml generate_vsix check_filenames check_database
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/Version.h b/tmk_core/protocol/lufa/LUFA-git/LUFA/Version.h
new file mode 100644
index 000000000..264c941a7
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/Version.h
@@ -0,0 +1,52 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaims all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * \brief LUFA library version constants.
+ *
+ * Version constants for informational purposes and version-specific macro creation. This header file contains the
+ * current LUFA version number in several forms, for use in the user-application (for example, for printing out
+ * whilst debugging, or for testing for version compatibility).
+ */
+
+#ifndef __LUFA_VERSION_H__
+#define __LUFA_VERSION_H__
+
+ /* Public Interface - May be used in end-application: */
+ /* Macros: */
+ /** Indicates the version number of the library, as an integer. */
+ #define LUFA_VERSION_INTEGER 0x140928
+
+ /** Indicates the version number of the library, as a string. */
+ #define LUFA_VERSION_STRING "140928"
+
+#endif
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/doxyfile b/tmk_core/protocol/lufa/LUFA-git/LUFA/doxyfile
new file mode 100644
index 000000000..77e8def61
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/doxyfile
@@ -0,0 +1,2368 @@
+# Doxyfile 1.8.8
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME = "LUFA Library"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER = 000000
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
+# the documentation. The maximum height of the logo should not exceed 55 pixels
+# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
+# to the output directory.
+
+PROJECT_LOGO = ./DoxygenPages/Images/LUFA_thumb.png
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = ./Documentation/
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF = NO
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
+# new page for each member. If set to NO, the documentation of a member will be
+# part of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
+# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
+# Fortran. In the later case the parser tries to guess whether the code is fixed
+# or free formatted code, this is the default for Fortran type files), VHDL. For
+# instance to make doxygen treat .inc files as Fortran files (default is PHP),
+# and .f files as C (default is Fortran), use: inc=Fortran f=C.
+#
+# Note For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT = NO
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by by putting a % sign in front of the word
+# or globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT = YES
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE = YES
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO these classes will be included in the various overviews. This option has
+# no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS = YES
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES = YES
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING = YES
+
+# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
+# todo list. This list is created by putting \todo commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST = NO
+
+# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
+# test list. This list is created by putting \test commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST = NO
+
+# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST = NO
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES = 1
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES the list
+# will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET = YES
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO doxygen will only warn about wrong or incomplete parameter
+# documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces.
+# Note: If this tag is empty the current directory is searched.
+
+INPUT = ./
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank the
+# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
+# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
+# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
+# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
+# *.qsf, *.as and *.js.
+
+FILE_PATTERNS = *.h \
+ *.txt
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE = Documentation/ \
+ StudioIntegration/ \
+ License.txt
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS = _* \
+ __*
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH = ./ \
+ CodeTemplates/
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH = ./
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER ) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = NO
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS = NO
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the
+# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
+# cost of reduced performance. This can be particularly helpful with template
+# rich C++ code for which doxygen's built-in parser lacks the necessary type
+# information.
+# Note: The availability of this option depends on whether or not doxygen was
+# compiled with the --with-libclang option.
+# The default value is: NO.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_OPTIONS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER = ./DoxygenPages/Style/Footer.htm
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefor more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra stylesheet files is of importance (e.g. the last
+# stylesheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET = ./DoxygenPages/Style/Style.css
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the stylesheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT = 120
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP = NO
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS = YES
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID = com.lufa-lib.library.documentation
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME = DeanCamera
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE = ../LUFA.chm
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated (
+# YES) or that it should be included in the master .chm file ( NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated (
+# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND = YES
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX = YES
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW = YES
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE = 1
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH = 300
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH = http://www.mathjax.org/mathjax
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. To get the times font for
+# instance you can specify
+# EXTRA_PACKAGES=times
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empy string,
+# for the replacement values of the other commands the user is refered to
+# HTML_HEADER.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE = plain
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT = docbook
+
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
+# Definitions (see http://autogen.sf.net) file that captures the structure of
+# the code including all documentation. Note that this feature is still
+# experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
+# in the source code. If set to NO only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF = YES
+
+# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED = __DOXYGEN__ \
+ PROGMEM \
+ EEMEM \
+ ATTR_PACKED
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
+# class index. If set to NO only the inherited external classes will be listed.
+# The default value is: NO.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
+# the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS = YES
+
+# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS = NO
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME =
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH = NO
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH = NO
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY = NO
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot.
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif and svg.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+PLANTUML_JAR_PATH =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES = 15
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH = 2
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT = YES
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP = YES
diff --git a/tmk_core/protocol/lufa/LUFA-git/LUFA/makefile b/tmk_core/protocol/lufa/LUFA-git/LUFA/makefile
new file mode 100644
index 000000000..88449a936
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/LUFA/makefile
@@ -0,0 +1,53 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2014.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+# ---------------------------------------
+# Makefile for the LUFA library itself.
+# ---------------------------------------
+
+LUFA_VERSION_NUM = $(shell grep LUFA_VERSION_STRING $(LUFA_PATH)/Version.h | cut -d'"' -f2)
+EXCLUDE_FROM_EXPORT := Documentation DoxygenPages CodeTemplates Build StudioIntegration doxyfile *.tar *.o *.d *.lss *.lst *.hex *.elf *.hex *.eep *.map *.bin
+
+# Default target - no default action when attempting to build the core directly
+all:
+
+# Export the library core as a TAR archive for importing into an IDE
+export_tar:
+ @echo Exporting LUFA library to a TAR archive...
+ @tar -cf LUFA_$(LUFA_VERSION_NUM).tar --directory=. $(EXCLUDE_FROM_EXPORT:%=--exclude=%) *
+ @tar -cf LUFA_$(LUFA_VERSION_NUM)_Code_Templates.tar CodeTemplates
+ @echo Export LUFA_$(LUFA_VERSION_NUM).tar complete.
+
+# Display the LUFA version of this library copy
+version:
+ @echo "LUFA $(LUFA_VERSION_NUM)"
+
+# Check if this is being included from a legacy or non LUFA build system makefile
+ifneq ($(LUFA_PATH),)
+ LUFA_ROOT_PATH = $(patsubst %/,%,$(LUFA_PATH))/LUFA/
+
+ include $(patsubst %/,%,$(LUFA_PATH))/LUFA/Build/lufa_sources.mk
+else
+ LUFA_BUILD_MODULES += MASTER
+ LUFA_BUILD_TARGETS += export_tar version
+
+ LUFA_PATH = .
+ ARCH = {AVR8,UC3,XMEGA}
+ DOXYGEN_OVERRIDE_PARAMS = QUIET=YES PROJECT_NUMBER=$(LUFA_VERSION_NUM)
+
+ # Remove all object and associated files from the LUFA library core
+ clean:
+ rm -f $(LUFA_SRC_ALL_FILES:%.c=%.o)
+ rm -f $(LUFA_SRC_ALL_FILES:%.c=%.d)
+ rm -f $(LUFA_SRC_ALL_FILES:%.c=%.lst)
+
+ include Build/lufa_core.mk
+ include Build/lufa_sources.mk
+ include Build/lufa_doxygen.mk
+endif
+
+.PHONY: all export_tar version clean
diff --git a/tmk_core/protocol/lufa/LUFA-git/Maintenance/lufa_functionlist_transform.xslt b/tmk_core/protocol/lufa/LUFA-git/Maintenance/lufa_functionlist_transform.xslt
new file mode 100644
index 000000000..671f30f4a
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Maintenance/lufa_functionlist_transform.xslt
@@ -0,0 +1,19 @@
+<!--
+ LUFA Library
+ Copyright (C) Dean Camera, 2014.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+-->
+
+<!-- Extracts out all function signatures from a combined Doxygen XML output. -->
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+ <xsl:output method="xml" omit-xml-declaration="yes"/>
+
+ <xsl:template match="doxygen">
+ <xsl:for-each select="//memberdef[@kind = 'function']">
+ <xsl:value-of select="definition"/><xsl:value-of select="argsstring"/><xsl:text>;&#10;</xsl:text>
+ </xsl:for-each>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/tmk_core/protocol/lufa/LUFA-git/Maintenance/makefile b/tmk_core/protocol/lufa/LUFA-git/Maintenance/makefile
new file mode 100644
index 000000000..c0938f8de
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/Maintenance/makefile
@@ -0,0 +1,94 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2014.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+
+# Maintenance scripts not required by general LUFA users, used for project development purposes.
+
+
+# Path to the root of the LUFA tree
+LUFA_ROOT := ../
+
+all:
+
+# Print a list of all filenames and line numbers that exceed an allowed threshold
+line-lengths:
+ awk '{ if (length > 120) { print FILENAME, ":", FNR, "[", length, "]" } }' `find $(LUFA_ROOT) -name *.[ch]`
+
+# Generate a header containing all library functions
+function-list:
+ $(MAKE) -C $(patsubst %/,%,$(LUFA_ROOT))/LUFA doxygen DOXYGEN_OVERRIDE_PARAMS="GENERATE_HTML=no GENERATE_XML=yes"
+ @xsltproc $(patsubst %/,%,$(LUFA_ROOT))/LUFA/Documentation/xml/combine.xslt $(patsubst %/,%,$(LUFA_ROOT))/LUFA/Documentation/xml/index.xml > temp.xml
+ @xsltproc lufa_functionlist_transform.xslt temp.xml > function_list.h
+ @sort function_list.h | uniq > function_list_unique.h
+ @rm temp.xml
+
+# Update all Doxygen configuration files to the latest Doxygen version
+upgrade-doxygen:
+ @echo Upgrading Doxygen files...
+ @for doxygen_conf in `find $(LUFA_ROOT) -name doxyfile`; do \
+ doxygen -u $$doxygen_conf; \
+ done;
+ @echo Doxygen configuration update complete.
+
+# Make all possible bootloaders for all targets and configurations as set by the BootloaderTest build test
+# and store them in a separate directory called "Bootloaders"
+bootloaders:
+ @echo "build_bootloaders:" > BuildMakefile
+ @printf "\t-mkdir Bootloaders 2>/dev/null\n\n" >> BuildMakefile
+
+ @while read line; \
+ do \
+ build_cfg=`echo $$line | grep -v "#" | sed 's/ //g'`; \
+ \
+ if ( test -n "$$build_cfg" ); then \
+ build_bootloader=`echo $$build_cfg | cut -d'=' -f1`; \
+ build_cfg=`echo $$build_cfg | cut -d'=' -f2-`; \
+ \
+ build_arch=`echo $$build_cfg | cut -d':' -f1`; \
+ build_mcu=`echo $$build_cfg | cut -d':' -f2`; \
+ build_board=`echo $$build_cfg | cut -d':' -f3`; \
+ build_flashsize=`echo $$build_cfg | cut -d':' -f4`; \
+ build_bootsize=`echo $$build_cfg | cut -d':' -f5`; \
+ build_fusb=`echo $$build_cfg | cut -d':' -f6`; \
+ \
+ printf "Found '%s' with FLASH: %3s KB, BOOT: %3s KB, MCU: %12s / %4s, BOARD: %s, F_USB: %sMHz\n" $$build_bootloader $$build_flashsize $$build_bootsize $$build_mcu $$build_arch $$build_board $$build_fusb; \
+ \
+ printf "\t-mkdir Bootloaders/%s 2>/dev/null\n" $$build_bootloader >> BuildMakefile; \
+ printf "\t@echo Building '%s' with FLASH: %3s KB, BOOT: %3s KB, MCU: %12s, BOARD: %s, F_USB: %sMHz\n" $$build_bootloader $$build_flashsize $$build_bootsize $$build_mcu $$build_board $$build_fusb >> BuildMakefile; \
+ printf "\t$(MAKE) -C $(patsubst %/,%,$(LUFA_ROOT))/Bootloaders/%s/ clean hex ARCH=%s MCU=%s BOARD=%s FLASH_SIZE_KB=%s BOOT_SECTION_SIZE_KB=%s F_USB=%s000000 DEBUG_LEVEL=0\n" $$build_bootloader $$build_arch $$build_mcu $$build_board $$build_flashsize $$build_bootsize $$build_fusb >> BuildMakefile; \
+ printf "\tmv $(patsubst %/,%,$(LUFA_ROOT))/Bootloaders/%s/Bootloader%s.hex Bootloaders/%s/%s-%s-%s-BOARD_%s-BOOT_%sKB-%sMHz.hex\n\n" $$build_bootloader $$build_bootloader $$build_bootloader $$build_bootloader $$build_arch $$build_mcu $$build_board $$build_bootsize $$build_fusb >> BuildMakefile; \
+ fi; \
+ done < $(patsubst %/,%,$(LUFA_ROOT))/BuildTests/BootloaderTest/BootloaderDeviceMap.cfg
+
+ $(MAKE) -f BuildMakefile build_bootloaders
+ cp $(patsubst %/,%,$(LUFA_ROOT))/LUFA/License.txt Bootloaders
+ rm -f BuildMakefile
+
+# Check the working branch documentation, ensure no placeholder values
+check-documentation-placeholders:
+ @echo Checking for release suitability...
+ @if ( grep "XXXXXX" $(patsubst %/,%,$(LUFA_ROOT))/LUFA/DoxygenPages/*.txt > /dev/null ;); then \
+ echo " ERROR: Doxygen documentation has not been updated for release!"; \
+ exit 1; \
+ fi;
+ @if ( grep "000000" $(patsubst %/,%,$(LUFA_ROOT))/LUFA/Version.h > /dev/null ;); then \
+ echo " ERROR: Version header has not been updated for release!"; \
+ exit 1; \
+ fi;
+ @echo Done.
+
+# Validate the working branch - compile all documentation, demos/projects/examples and run build tests
+validate-branch:
+ $(MAKE) -C $(patsubst %/,%,$(LUFA_ROOT)) doxygen
+ $(MAKE) -C $(patsubst %/,%,$(LUFA_ROOT)) all DEBUG_LEVEL=0
+ $(MAKE) -C $(patsubst %/,%,$(LUFA_ROOT))/BuildTests all
+
+# Validate the working branch for general release, check for placeholder documentation then build and test everything
+validate-release: check-documentation-placeholders validate-branch
+
+
+.PHONY: all upgrade-doxygen bootloaders check-documentation-placeholders validate-branch
diff --git a/tmk_core/protocol/lufa/LUFA-git/README.txt b/tmk_core/protocol/lufa/LUFA-git/README.txt
new file mode 100644
index 000000000..80a5c81d8
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/README.txt
@@ -0,0 +1,56 @@
+
+ _ _ _ ___ _
+ | | | | | __/ \
+ | |_| U | _| o | - The Lightweight USB
+ |___|___|_||_n_| Framework for AVRs
+ =========================================
+ Written by Dean Camera
+ dean [at] fourwalledcubicle [dot] com
+
+ http://www.lufa-lib.org
+ =========================================
+
+ LUFA is donation supported. To support LUFA,
+ please donate at http://www.lufa-lib.org/donate
+
+ Released under a modified MIT license - see
+ LUFA/License.txt for license details.
+
+ For Commercial Licensing information, see
+ http://www.lufa-lib.org/license
+
+
+This package contains the complete LUFA library, demos, user-submitted
+projects and bootloaders for use with compatible microcontroller models.
+LUFA is a simple to use, lightweight framework which sits atop the hardware
+USB controller in specific AVR microcontroller models, and allows for the
+quick and easy creation of complex USB devices and hosts.
+
+To get started, you will need to install the "Doxygen" documentation
+generation tool. If you use Linux, this can be installed via the "doxygen"
+package in your chosen package management tool - under Ubuntu, this can be
+achieved by running the following command in the terminal:
+
+ sudo apt-get install doxygen
+
+Other package managers and distributions will have similar methods to
+install Doxygen. In Windows, you can download a prebuilt installer for
+Doxygen from its website, www.doxygen.org.
+
+Once installed, you can then use the Doxygen tool to generate the library
+documentation from the command line or terminal of your operating system. To
+do this, open your terminal or command line to the root directory of the
+LUFA package, and type the following command:
+
+ make doxygen
+
+Which will recursively generate documentation for all elements in the
+library - the core, plus all demos, projects and bootloaders. Generated
+documentation will then be available by opening the file "index.html" of the
+created Documentation/html/ subdirectories inside each project folder.
+
+The documentation for the library itself (but not the documentation for the
+individual demos, projects or bootloaders) is also available as a separate
+package from the project webpage for convenience if Doxygen cannot be
+installed.
+
diff --git a/tmk_core/protocol/lufa/LUFA-git/makefile b/tmk_core/protocol/lufa/LUFA-git/makefile
new file mode 100644
index 000000000..880c0cf8d
--- /dev/null
+++ b/tmk_core/protocol/lufa/LUFA-git/makefile
@@ -0,0 +1,26 @@
+#
+# LUFA Library
+# Copyright (C) Dean Camera, 2014.
+#
+# dean [at] fourwalledcubicle [dot] com
+# www.lufa-lib.org
+#
+
+# Makefile to build the LUFA library, projects and demos.
+
+# Call with "make all" to rebuild everything, "make clean" to clean everything,
+# "make mostlyclean" to remove all intermediary files but preserve any binaries,
+# "make doxygen" to document everything with Doxygen (if installed). Call
+# "make help" for additional target build information within a specific project.
+
+all:
+
+%:
+ @echo Executing \"make $@\" on all LUFA library elements.
+ @echo
+ $(MAKE) -C LUFA $@
+ $(MAKE) -C Demos $@
+ $(MAKE) -C Projects $@
+ $(MAKE) -C Bootloaders $@
+ @echo
+ @echo LUFA \"make $@\" operation complete.
diff --git a/tmk_core/protocol/lufa/bluetooth.c b/tmk_core/protocol/lufa/bluetooth.c
new file mode 100644
index 000000000..549606162
--- /dev/null
+++ b/tmk_core/protocol/lufa/bluetooth.c
@@ -0,0 +1,36 @@
+/*
+Bluefruit Protocol for TMK firmware
+Author: Benjamin Gould, 2013
+ Jack Humbert, 2015
+Based on code Copyright 2011 Jun Wako <wakojun@gmail.com>
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdint.h>
+#include "report.h"
+#include "print.h"
+#include "debug.h"
+#include "bluetooth.h"
+
+void bluefruit_keyboard_print_report(report_keyboard_t *report)
+{
+ if (!debug_keyboard) return;
+ dprintf("keys: "); for (int i = 0; i < KEYBOARD_REPORT_KEYS; i++) { debug_hex8(report->keys[i]); dprintf(" "); }
+ dprintf(" mods: "); debug_hex8(report->mods);
+ dprintf(" reserved: "); debug_hex8(report->reserved);
+ dprintf("\n");
+}
+
+void bluefruit_serial_send(uint8_t data)
+{
+ serial_send(data);
+} \ No newline at end of file
diff --git a/tmk_core/protocol/lufa/bluetooth.h b/tmk_core/protocol/lufa/bluetooth.h
new file mode 100644
index 000000000..78ece1cd0
--- /dev/null
+++ b/tmk_core/protocol/lufa/bluetooth.h
@@ -0,0 +1,65 @@
+/*
+Bluefruit Protocol for TMK firmware
+Author: Benjamin Gould, 2013
+ Jack Humbert, 2015
+Based on code Copyright 2011 Jun Wako <wakojun@gmail.com>
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef BLUETOOTH_H
+#define BLUETOOTH_H
+
+#include "../serial.h"
+
+void bluefruit_serial_send(uint8_t data);
+
+/*
++-----------------+-------------------+-------+
+| Consumer Key | Bit Map | Hex |
++-----------------+-------------------+-------+
+| Home | 00000001 00000000 | 01 00 |
+| KeyboardLayout | 00000010 00000000 | 02 00 |
+| Search | 00000100 00000000 | 04 00 |
+| Snapshot | 00001000 00000000 | 08 00 |
+| VolumeUp | 00010000 00000000 | 10 00 |
+| VolumeDown | 00100000 00000000 | 20 00 |
+| Play/Pause | 01000000 00000000 | 40 00 |
+| Fast Forward | 10000000 00000000 | 80 00 |
+| Rewind | 00000000 00000001 | 00 01 |
+| Scan Next Track | 00000000 00000010 | 00 02 |
+| Scan Prev Track | 00000000 00000100 | 00 04 |
+| Random Play | 00000000 00001000 | 00 08 |
+| Stop | 00000000 00010000 | 00 10 |
++-------------------------------------+-------+
+*/
+#define CONSUMER2BLUEFRUIT(usage) \
+ (usage == AUDIO_MUTE ? 0x0000 : \
+ (usage == AUDIO_VOL_UP ? 0x1000 : \
+ (usage == AUDIO_VOL_DOWN ? 0x2000 : \
+ (usage == TRANSPORT_NEXT_TRACK ? 0x0002 : \
+ (usage == TRANSPORT_PREV_TRACK ? 0x0004 : \
+ (usage == TRANSPORT_STOP ? 0x0010 : \
+ (usage == TRANSPORT_STOP_EJECT ? 0x0000 : \
+ (usage == TRANSPORT_PLAY_PAUSE ? 0x4000 : \
+ (usage == AL_CC_CONFIG ? 0x0000 : \
+ (usage == AL_EMAIL ? 0x0000 : \
+ (usage == AL_CALCULATOR ? 0x0000 : \
+ (usage == AL_LOCAL_BROWSER ? 0x0000 : \
+ (usage == AC_SEARCH ? 0x0400 : \
+ (usage == AC_HOME ? 0x0100 : \
+ (usage == AC_BACK ? 0x0000 : \
+ (usage == AC_FORWARD ? 0x0000 : \
+ (usage == AC_STOP ? 0x0000 : \
+ (usage == AC_REFRESH ? 0x0000 : \
+ (usage == AC_BOOKMARKS ? 0x0000 : 0)))))))))))))))))))
+
+#endif \ No newline at end of file
diff --git a/tmk_core/protocol/lufa/descriptor.c b/tmk_core/protocol/lufa/descriptor.c
new file mode 100644
index 000000000..850a20fdb
--- /dev/null
+++ b/tmk_core/protocol/lufa/descriptor.c
@@ -0,0 +1,789 @@
+/*
+ * Copyright 2012 Jun Wako <wakojun@gmail.com>
+ * This file is based on:
+ * LUFA-120219/Demos/Device/Lowlevel/KeyboardMouse
+ * LUFA-120219/Demos/Device/Lowlevel/GenericHID
+ */
+
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2012.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+ Copyright 2010 Denver Gingerich (denver [at] ossguy [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "util.h"
+#include "report.h"
+#include "descriptor.h"
+
+
+/*******************************************************************************
+ * HID Report Descriptors
+ ******************************************************************************/
+const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] =
+{
+ HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
+ HID_RI_USAGE(8, 0x06), /* Keyboard */
+ HID_RI_COLLECTION(8, 0x01), /* Application */
+ HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
+ HID_RI_USAGE_MINIMUM(8, 0xE0), /* Keyboard Left Control */
+ HID_RI_USAGE_MAXIMUM(8, 0xE7), /* Keyboard Right GUI */
+ HID_RI_LOGICAL_MINIMUM(8, 0x00),
+ HID_RI_LOGICAL_MAXIMUM(8, 0x01),
+ HID_RI_REPORT_COUNT(8, 0x08),
+ HID_RI_REPORT_SIZE(8, 0x01),
+ HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+
+ HID_RI_REPORT_COUNT(8, 0x01),
+ HID_RI_REPORT_SIZE(8, 0x08),
+ HID_RI_INPUT(8, HID_IOF_CONSTANT), /* reserved */
+
+ HID_RI_USAGE_PAGE(8, 0x08), /* LEDs */
+ HID_RI_USAGE_MINIMUM(8, 0x01), /* Num Lock */
+ HID_RI_USAGE_MAXIMUM(8, 0x05), /* Kana */
+ HID_RI_REPORT_COUNT(8, 0x05),
+ HID_RI_REPORT_SIZE(8, 0x01),
+ HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
+ HID_RI_REPORT_COUNT(8, 0x01),
+ HID_RI_REPORT_SIZE(8, 0x03),
+ HID_RI_OUTPUT(8, HID_IOF_CONSTANT),
+
+ HID_RI_USAGE_PAGE(8, 0x07), /* Keyboard */
+ HID_RI_USAGE_MINIMUM(8, 0x00), /* Reserved (no event indicated) */
+ HID_RI_USAGE_MAXIMUM(8, 0xFF), /* Keyboard Application */
+ HID_RI_LOGICAL_MINIMUM(8, 0x00),
+ HID_RI_LOGICAL_MAXIMUM(16, 0x00FF),
+ HID_RI_REPORT_COUNT(8, 0x06),
+ HID_RI_REPORT_SIZE(8, 0x08),
+ HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
+ HID_RI_END_COLLECTION(0),
+};
+
+#ifdef MOUSE_ENABLE
+const USB_Descriptor_HIDReport_Datatype_t PROGMEM MouseReport[] =
+{
+ HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
+ HID_RI_USAGE(8, 0x02), /* Mouse */
+ HID_RI_COLLECTION(8, 0x01), /* Application */
+ HID_RI_USAGE(8, 0x01), /* Pointer */
+ HID_RI_COLLECTION(8, 0x00), /* Physical */
+
+ HID_RI_USAGE_PAGE(8, 0x09), /* Button */
+ HID_RI_USAGE_MINIMUM(8, 0x01), /* Button 1 */
+ HID_RI_USAGE_MAXIMUM(8, 0x05), /* Button 5 */
+ HID_RI_LOGICAL_MINIMUM(8, 0x00),
+ HID_RI_LOGICAL_MAXIMUM(8, 0x01),
+ HID_RI_REPORT_COUNT(8, 0x05),
+ HID_RI_REPORT_SIZE(8, 0x01),
+ HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+ HID_RI_REPORT_COUNT(8, 0x01),
+ HID_RI_REPORT_SIZE(8, 0x03),
+ HID_RI_INPUT(8, HID_IOF_CONSTANT),
+
+ HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
+ HID_RI_USAGE(8, 0x30), /* Usage X */
+ HID_RI_USAGE(8, 0x31), /* Usage Y */
+ HID_RI_LOGICAL_MINIMUM(8, -127),
+ HID_RI_LOGICAL_MAXIMUM(8, 127),
+ HID_RI_REPORT_COUNT(8, 0x02),
+ HID_RI_REPORT_SIZE(8, 0x08),
+ HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),
+
+ HID_RI_USAGE(8, 0x38), /* Wheel */
+ HID_RI_LOGICAL_MINIMUM(8, -127),
+ HID_RI_LOGICAL_MAXIMUM(8, 127),
+ HID_RI_REPORT_COUNT(8, 0x01),
+ HID_RI_REPORT_SIZE(8, 0x08),
+ HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),
+
+ HID_RI_USAGE_PAGE(8, 0x0C), /* Consumer */
+ HID_RI_USAGE(16, 0x0238), /* AC Pan (Horizontal wheel) */
+ HID_RI_LOGICAL_MINIMUM(8, -127),
+ HID_RI_LOGICAL_MAXIMUM(8, 127),
+ HID_RI_REPORT_COUNT(8, 0x01),
+ HID_RI_REPORT_SIZE(8, 0x08),
+ HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),
+
+ HID_RI_END_COLLECTION(0),
+ HID_RI_END_COLLECTION(0),
+};
+#endif
+
+#ifdef EXTRAKEY_ENABLE
+const USB_Descriptor_HIDReport_Datatype_t PROGMEM ExtrakeyReport[] =
+{
+ HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
+ HID_RI_USAGE(8, 0x80), /* System Control */
+ HID_RI_COLLECTION(8, 0x01), /* Application */
+ HID_RI_REPORT_ID(8, REPORT_ID_SYSTEM),
+ HID_RI_LOGICAL_MINIMUM(16, 0x0001),
+ HID_RI_LOGICAL_MAXIMUM(16, 0x00B7),
+ HID_RI_USAGE_MINIMUM(16, 0x0001), /* System Power Down */
+ HID_RI_USAGE_MAXIMUM(16, 0x00B7), /* System Display LCD Autoscale */
+ HID_RI_REPORT_SIZE(8, 16),
+ HID_RI_REPORT_COUNT(8, 1),
+ HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
+ HID_RI_END_COLLECTION(0),
+
+ HID_RI_USAGE_PAGE(8, 0x0C), /* Consumer */
+ HID_RI_USAGE(8, 0x01), /* Consumer Control */
+ HID_RI_COLLECTION(8, 0x01), /* Application */
+ HID_RI_REPORT_ID(8, REPORT_ID_CONSUMER),
+ HID_RI_LOGICAL_MINIMUM(16, 0x0001),
+ HID_RI_LOGICAL_MAXIMUM(16, 0x029C),
+ HID_RI_USAGE_MINIMUM(16, 0x0001), /* +10 */
+ HID_RI_USAGE_MAXIMUM(16, 0x029C), /* AC Distribute Vertically */
+ HID_RI_REPORT_SIZE(8, 16),
+ HID_RI_REPORT_COUNT(8, 1),
+ HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_ARRAY | HID_IOF_ABSOLUTE),
+ HID_RI_END_COLLECTION(0),
+};
+#endif
+
+#ifdef CONSOLE_ENABLE
+const USB_Descriptor_HIDReport_Datatype_t PROGMEM ConsoleReport[] =
+{
+ HID_RI_USAGE_PAGE(16, 0xFF31), /* Vendor Page(PJRC Teensy compatible) */
+ HID_RI_USAGE(8, 0x74), /* Vendor Usage(PJRC Teensy compatible) */
+ HID_RI_COLLECTION(8, 0x01), /* Application */
+ HID_RI_USAGE(8, 0x75), /* Vendor Usage 0x75 */
+ HID_RI_LOGICAL_MINIMUM(8, 0x00),
+ HID_RI_LOGICAL_MAXIMUM(16, 0x00FF),
+ HID_RI_REPORT_COUNT(8, CONSOLE_EPSIZE),
+ HID_RI_REPORT_SIZE(8, 0x08),
+ HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+ HID_RI_USAGE(8, 0x76), /* Vendor Usage 0x76 */
+ HID_RI_LOGICAL_MINIMUM(8, 0x00),
+ HID_RI_LOGICAL_MAXIMUM(16, 0x00FF),
+ HID_RI_REPORT_COUNT(8, CONSOLE_EPSIZE),
+ HID_RI_REPORT_SIZE(8, 0x08),
+ HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
+ HID_RI_END_COLLECTION(0),
+};
+#endif
+
+#ifdef NKRO_ENABLE
+const USB_Descriptor_HIDReport_Datatype_t PROGMEM NKROReport[] =
+{
+ HID_RI_USAGE_PAGE(8, 0x01), /* Generic Desktop */
+ HID_RI_USAGE(8, 0x06), /* Keyboard */
+ HID_RI_COLLECTION(8, 0x01), /* Application */
+ HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
+ HID_RI_USAGE_MINIMUM(8, 0xE0), /* Keyboard Left Control */
+ HID_RI_USAGE_MAXIMUM(8, 0xE7), /* Keyboard Right GUI */
+ HID_RI_LOGICAL_MINIMUM(8, 0x00),
+ HID_RI_LOGICAL_MAXIMUM(8, 0x01),
+ HID_RI_REPORT_COUNT(8, 0x08),
+ HID_RI_REPORT_SIZE(8, 0x01),
+ HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+
+ HID_RI_USAGE_PAGE(8, 0x08), /* LEDs */
+ HID_RI_USAGE_MINIMUM(8, 0x01), /* Num Lock */
+ HID_RI_USAGE_MAXIMUM(8, 0x05), /* Kana */
+ HID_RI_REPORT_COUNT(8, 0x05),
+ HID_RI_REPORT_SIZE(8, 0x01),
+ HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
+ HID_RI_REPORT_COUNT(8, 0x01),
+ HID_RI_REPORT_SIZE(8, 0x03),
+ HID_RI_OUTPUT(8, HID_IOF_CONSTANT),
+
+ HID_RI_USAGE_PAGE(8, 0x07), /* Key Codes */
+ HID_RI_USAGE_MINIMUM(8, 0x00), /* Keyboard 0 */
+ HID_RI_USAGE_MAXIMUM(8, (NKRO_EPSIZE-1)*8-1), /* Keyboard Right GUI */
+ HID_RI_LOGICAL_MINIMUM(8, 0x00),
+ HID_RI_LOGICAL_MAXIMUM(8, 0x01),
+ HID_RI_REPORT_COUNT(8, (NKRO_EPSIZE-1)*8),
+ HID_RI_REPORT_SIZE(8, 0x01),
+ HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
+ HID_RI_END_COLLECTION(0),
+};
+#endif
+
+/*******************************************************************************
+ * Device Descriptors
+ ******************************************************************************/
+const USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
+{
+ .Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
+
+ .USBSpecification = VERSION_BCD(1,1,0),
+ .Class = USB_CSCP_NoDeviceClass,
+ .SubClass = USB_CSCP_NoDeviceSubclass,
+ .Protocol = USB_CSCP_NoDeviceProtocol,
+
+ .Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
+
+ /* specified in config.h */
+ .VendorID = VENDOR_ID,
+ .ProductID = PRODUCT_ID,
+ .ReleaseNumber = DEVICE_VER,
+
+ .ManufacturerStrIndex = 0x01,
+ .ProductStrIndex = 0x02,
+ .SerialNumStrIndex = NO_DESCRIPTOR,
+
+ .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
+};
+
+/*******************************************************************************
+ * Configuration Descriptors
+ ******************************************************************************/
+const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
+{
+ .Config =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration},
+
+ .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
+ .TotalInterfaces = TOTAL_INTERFACES,
+
+ .ConfigurationNumber = 1,
+ .ConfigurationStrIndex = NO_DESCRIPTOR,
+
+ .ConfigAttributes = (USB_CONFIG_ATTR_RESERVED | USB_CONFIG_ATTR_REMOTEWAKEUP),
+
+ .MaxPowerConsumption = USB_CONFIG_POWER_MA(500)
+ },
+
+ /*
+ * Keyboard
+ */
+ .Keyboard_Interface =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
+
+ .InterfaceNumber = KEYBOARD_INTERFACE,
+ .AlternateSetting = 0x00,
+
+ .TotalEndpoints = 1,
+
+ .Class = HID_CSCP_HIDClass,
+ .SubClass = HID_CSCP_BootSubclass,
+ .Protocol = HID_CSCP_KeyboardBootProtocol,
+
+ .InterfaceStrIndex = NO_DESCRIPTOR
+ },
+
+ .Keyboard_HID =
+ {
+ .Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
+
+ .HIDSpec = VERSION_BCD(1,1,1),
+ .CountryCode = 0x00,
+ .TotalReportDescriptors = 1,
+ .HIDReportType = HID_DTYPE_Report,
+ .HIDReportLength = sizeof(KeyboardReport)
+ },
+
+ .Keyboard_INEndpoint =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
+
+ .EndpointAddress = (ENDPOINT_DIR_IN | KEYBOARD_IN_EPNUM),
+ .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
+ .EndpointSize = KEYBOARD_EPSIZE,
+ .PollingIntervalMS = 0x0A
+ },
+
+ /*
+ * Mouse
+ */
+#ifdef MOUSE_ENABLE
+ .Mouse_Interface =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
+
+ .InterfaceNumber = MOUSE_INTERFACE,
+ .AlternateSetting = 0x00,
+
+ .TotalEndpoints = 1,
+
+ .Class = HID_CSCP_HIDClass,
+ .SubClass = HID_CSCP_BootSubclass,
+ .Protocol = HID_CSCP_MouseBootProtocol,
+
+ .InterfaceStrIndex = NO_DESCRIPTOR
+ },
+
+ .Mouse_HID =
+ {
+ .Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
+
+ .HIDSpec = VERSION_BCD(1,1,1),
+ .CountryCode = 0x00,
+ .TotalReportDescriptors = 1,
+ .HIDReportType = HID_DTYPE_Report,
+ .HIDReportLength = sizeof(MouseReport)
+ },
+
+ .Mouse_INEndpoint =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
+
+ .EndpointAddress = (ENDPOINT_DIR_IN | MOUSE_IN_EPNUM),
+ .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
+ .EndpointSize = MOUSE_EPSIZE,
+ .PollingIntervalMS = 0x0A
+ },
+#endif
+
+ /*
+ * Extra
+ */
+#ifdef EXTRAKEY_ENABLE
+ .Extrakey_Interface =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
+
+ .InterfaceNumber = EXTRAKEY_INTERFACE,
+ .AlternateSetting = 0x00,
+
+ .TotalEndpoints = 1,
+
+ .Class = HID_CSCP_HIDClass,
+ .SubClass = HID_CSCP_NonBootSubclass,
+ .Protocol = HID_CSCP_NonBootProtocol,
+
+ .InterfaceStrIndex = NO_DESCRIPTOR
+ },
+
+ .Extrakey_HID =
+ {
+ .Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
+
+ .HIDSpec = VERSION_BCD(1,1,1),
+ .CountryCode = 0x00,
+ .TotalReportDescriptors = 1,
+ .HIDReportType = HID_DTYPE_Report,
+ .HIDReportLength = sizeof(ExtrakeyReport)
+ },
+
+ .Extrakey_INEndpoint =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
+
+ .EndpointAddress = (ENDPOINT_DIR_IN | EXTRAKEY_IN_EPNUM),
+ .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
+ .EndpointSize = EXTRAKEY_EPSIZE,
+ .PollingIntervalMS = 0x0A
+ },
+#endif
+
+ /*
+ * Console
+ */
+#ifdef CONSOLE_ENABLE
+ .Console_Interface =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
+
+ .InterfaceNumber = CONSOLE_INTERFACE,
+ .AlternateSetting = 0x00,
+
+ .TotalEndpoints = 2,
+
+ .Class = HID_CSCP_HIDClass,
+ .SubClass = HID_CSCP_NonBootSubclass,
+ .Protocol = HID_CSCP_NonBootProtocol,
+
+ .InterfaceStrIndex = NO_DESCRIPTOR
+ },
+
+ .Console_HID =
+ {
+ .Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
+
+ .HIDSpec = VERSION_BCD(1,1,1),
+ .CountryCode = 0x00,
+ .TotalReportDescriptors = 1,
+ .HIDReportType = HID_DTYPE_Report,
+ .HIDReportLength = sizeof(ConsoleReport)
+ },
+
+ .Console_INEndpoint =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
+
+ .EndpointAddress = (ENDPOINT_DIR_IN | CONSOLE_IN_EPNUM),
+ .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
+ .EndpointSize = CONSOLE_EPSIZE,
+ .PollingIntervalMS = 0x01
+ },
+
+ .Console_OUTEndpoint =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
+
+ .EndpointAddress = (ENDPOINT_DIR_OUT | CONSOLE_OUT_EPNUM),
+ .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
+ .EndpointSize = CONSOLE_EPSIZE,
+ .PollingIntervalMS = 0x01
+ },
+#endif
+
+ /*
+ * NKRO
+ */
+#ifdef NKRO_ENABLE
+ .NKRO_Interface =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
+
+ .InterfaceNumber = NKRO_INTERFACE,
+ .AlternateSetting = 0x00,
+
+ .TotalEndpoints = 1,
+
+ .Class = HID_CSCP_HIDClass,
+ .SubClass = HID_CSCP_NonBootSubclass,
+ .Protocol = HID_CSCP_NonBootProtocol,
+
+ .InterfaceStrIndex = NO_DESCRIPTOR
+ },
+
+ .NKRO_HID =
+ {
+ .Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
+
+ .HIDSpec = VERSION_BCD(1,1,1),
+ .CountryCode = 0x00,
+ .TotalReportDescriptors = 1,
+ .HIDReportType = HID_DTYPE_Report,
+ .HIDReportLength = sizeof(NKROReport)
+ },
+
+ .NKRO_INEndpoint =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
+
+ .EndpointAddress = (ENDPOINT_DIR_IN | NKRO_IN_EPNUM),
+ .Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
+ .EndpointSize = NKRO_EPSIZE,
+ .PollingIntervalMS = 0x01
+ },
+#endif
+
+#ifdef MIDI_ENABLE
+ .Audio_ControlInterface =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
+
+ .InterfaceNumber = AC_INTERFACE,
+ .AlternateSetting = 0,
+
+ .TotalEndpoints = 0,
+
+ .Class = AUDIO_CSCP_AudioClass,
+ .SubClass = AUDIO_CSCP_ControlSubclass,
+ .Protocol = AUDIO_CSCP_ControlProtocol,
+
+ .InterfaceStrIndex = NO_DESCRIPTOR
+ },
+
+ .Audio_ControlInterface_SPC =
+ {
+ .Header = {.Size = sizeof(USB_Audio_Descriptor_Interface_AC_t), .Type = DTYPE_CSInterface},
+ .Subtype = AUDIO_DSUBTYPE_CSInterface_Header,
+
+ .ACSpecification = VERSION_BCD(1,0,0),
+ .TotalLength = sizeof(USB_Audio_Descriptor_Interface_AC_t),
+
+ .InCollection = 1,
+ .InterfaceNumber = AS_INTERFACE,
+ },
+
+ .Audio_StreamInterface =
+ {
+ .Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
+
+ .InterfaceNumber = AS_INTERFACE,
+ .AlternateSetting = 0,
+
+ .TotalEndpoints = 2,
+
+ .Class = AUDIO_CSCP_AudioClass,
+ .SubClass = AUDIO_CSCP_MIDIStreamingSubclass,
+ .Protocol = AUDIO_CSCP_StreamingProtocol,
+
+ .InterfaceStrIndex = NO_DESCRIPTOR
+ },
+
+ .Audio_StreamInterface_SPC =
+ {
+ .Header = {.Size = sizeof(USB_MIDI_Descriptor_AudioInterface_AS_t), .Type = DTYPE_CSInterface},
+ .Subtype = AUDIO_DSUBTYPE_CSInterface_General,
+
+ .AudioSpecification = VERSION_BCD(1,0,0),
+
+ .TotalLength = (sizeof(USB_Descriptor_Configuration_t) -
+ offsetof(USB_Descriptor_Configuration_t, Audio_StreamInterface_SPC))
+ },
+
+ .MIDI_In_Jack_Emb =
+ {
+ .Header = {.Size = sizeof(USB_MIDI_Descriptor_InputJack_t), .Type = DTYPE_CSInterface},
+ .Subtype = AUDIO_DSUBTYPE_CSInterface_InputTerminal,
+
+ .JackType = MIDI_JACKTYPE_Embedded,
+ .JackID = 0x01,
+
+ .JackStrIndex = NO_DESCRIPTOR
+ },
+
+ .MIDI_In_Jack_Ext =
+ {
+ .Header = {.Size = sizeof(USB_MIDI_Descriptor_InputJack_t), .Type = DTYPE_CSInterface},
+ .Subtype = AUDIO_DSUBTYPE_CSInterface_InputTerminal,
+
+ .JackType = MIDI_JACKTYPE_External,
+ .JackID = 0x02,
+
+ .JackStrIndex = NO_DESCRIPTOR
+ },
+
+ .MIDI_Out_Jack_Emb =
+ {
+ .Header = {.Size = sizeof(USB_MIDI_Descriptor_OutputJack_t), .Type = DTYPE_CSInterface},
+ .Subtype = AUDIO_DSUBTYPE_CSInterface_OutputTerminal,
+
+ .JackType = MIDI_JACKTYPE_Embedded,
+ .JackID = 0x03,
+
+ .NumberOfPins = 1,
+ .SourceJackID = {0x02},
+ .SourcePinID = {0x01},
+
+ .JackStrIndex = NO_DESCRIPTOR
+ },
+
+ .MIDI_Out_Jack_Ext =
+ {
+ .Header = {.Size = sizeof(USB_MIDI_Descriptor_OutputJack_t), .Type = DTYPE_CSInterface},
+ .Subtype = AUDIO_DSUBTYPE_CSInterface_OutputTerminal,
+
+ .JackType = MIDI_JACKTYPE_External,
+ .JackID = 0x04,
+
+ .NumberOfPins = 1,
+ .SourceJackID = {0x01},
+ .SourcePinID = {0x01},
+
+ .JackStrIndex = NO_DESCRIPTOR
+ },
+
+ .MIDI_In_Jack_Endpoint =
+ {
+ .Endpoint =
+ {
+ .Header = {.Size = sizeof(USB_Audio_Descriptor_StreamEndpoint_Std_t), .Type = DTYPE_Endpoint},
+
+ .EndpointAddress = MIDI_STREAM_OUT_EPADDR,
+ .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
+ .EndpointSize = MIDI_STREAM_EPSIZE,
+ .PollingIntervalMS = 0x05
+ },
+
+ .Refresh = 0,
+ .SyncEndpointNumber = 0
+ },
+
+ .MIDI_In_Jack_Endpoint_SPC =
+ {
+ .Header = {.Size = sizeof(USB_MIDI_Descriptor_Jack_Endpoint_t), .Type = DTYPE_CSEndpoint},
+ .Subtype = AUDIO_DSUBTYPE_CSEndpoint_General,
+
+ .TotalEmbeddedJacks = 0x01,
+ .AssociatedJackID = {0x01}
+ },
+
+ .MIDI_Out_Jack_Endpoint =
+ {
+ .Endpoint =
+ {
+ .Header = {.Size = sizeof(USB_Audio_Descriptor_StreamEndpoint_Std_t), .Type = DTYPE_Endpoint},
+
+ .EndpointAddress = MIDI_STREAM_IN_EPADDR,
+ .Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
+ .EndpointSize = MIDI_STREAM_EPSIZE,
+ .PollingIntervalMS = 0x05
+ },
+
+ .Refresh = 0,
+ .SyncEndpointNumber = 0
+ },
+
+ .MIDI_Out_Jack_Endpoint_SPC =
+ {
+ .Header = {.Size = sizeof(USB_MIDI_Descriptor_Jack_Endpoint_t), .Type = DTYPE_CSEndpoint},
+ .Subtype = AUDIO_DSUBTYPE_CSEndpoint_General,
+
+ .TotalEmbeddedJacks = 0x01,
+ .AssociatedJackID = {0x03}
+ }
+#endif
+};
+
+
+/*******************************************************************************
+ * String Descriptors
+ ******************************************************************************/
+const USB_Descriptor_String_t PROGMEM LanguageString =
+{
+ .Header = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String},
+
+ .UnicodeString = {LANGUAGE_ID_ENG}
+};
+
+const USB_Descriptor_String_t PROGMEM ManufacturerString =
+{
+ /* subtract 1 for null terminator */
+ .Header = {.Size = USB_STRING_LEN(sizeof(STR(MANUFACTURER))-1), .Type = DTYPE_String},
+
+ .UnicodeString = LSTR(MANUFACTURER)
+};
+
+const USB_Descriptor_String_t PROGMEM ProductString =
+{
+ /* subtract 1 for null terminator */
+ .Header = {.Size = USB_STRING_LEN(sizeof(STR(PRODUCT))-1), .Type = DTYPE_String},
+
+ .UnicodeString = LSTR(PRODUCT)
+};
+
+
+/** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
+ * documentation) by the application code so that the address and size of a requested descriptor can be given
+ * to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function
+ * is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the
+ * USB host.
+ */
+uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+ const uint8_t wIndex,
+ const void** const DescriptorAddress)
+{
+ const uint8_t DescriptorType = (wValue >> 8);
+ const uint8_t DescriptorIndex = (wValue & 0xFF);
+
+ const void* Address = NULL;
+ uint16_t Size = NO_DESCRIPTOR;
+
+ switch (DescriptorType)
+ {
+ case DTYPE_Device:
+ Address = &DeviceDescriptor;
+ Size = sizeof(USB_Descriptor_Device_t);
+ break;
+ case DTYPE_Configuration:
+ Address = &ConfigurationDescriptor;
+ Size = sizeof(USB_Descriptor_Configuration_t);
+ break;
+ case DTYPE_String:
+ switch (DescriptorIndex )
+ {
+ case 0x00:
+ Address = &LanguageString;
+ Size = pgm_read_byte(&LanguageString.Header.Size);
+ break;
+ case 0x01:
+ Address = &ManufacturerString;
+ Size = pgm_read_byte(&ManufacturerString.Header.Size);
+ break;
+ case 0x02:
+ Address = &ProductString;
+ Size = pgm_read_byte(&ProductString.Header.Size);
+ break;
+ }
+ break;
+ case HID_DTYPE_HID:
+ switch (wIndex) {
+ case KEYBOARD_INTERFACE:
+ Address = &ConfigurationDescriptor.Keyboard_HID;
+ Size = sizeof(USB_HID_Descriptor_HID_t);
+ break;
+#ifdef MOUSE_ENABLE
+ case MOUSE_INTERFACE:
+ Address = &ConfigurationDescriptor.Mouse_HID;
+ Size = sizeof(USB_HID_Descriptor_HID_t);
+ break;
+#endif
+#ifdef EXTRAKEY_ENABLE
+ case EXTRAKEY_INTERFACE:
+ Address = &ConfigurationDescriptor.Extrakey_HID;
+ Size = sizeof(USB_HID_Descriptor_HID_t);
+ break;
+#endif
+#ifdef CONSOLE_ENABLE
+ case CONSOLE_INTERFACE:
+ Address = &ConfigurationDescriptor.Console_HID;
+ Size = sizeof(USB_HID_Descriptor_HID_t);
+ break;
+#endif
+#ifdef NKRO_ENABLE
+ case NKRO_INTERFACE:
+ Address = &ConfigurationDescriptor.NKRO_HID;
+ Size = sizeof(USB_HID_Descriptor_HID_t);
+ break;
+#endif
+ }
+ break;
+ case HID_DTYPE_Report:
+ switch (wIndex) {
+ case KEYBOARD_INTERFACE:
+ Address = &KeyboardReport;
+ Size = sizeof(KeyboardReport);
+ break;
+#ifdef MOUSE_ENABLE
+ case MOUSE_INTERFACE:
+ Address = &MouseReport;
+ Size = sizeof(MouseReport);
+ break;
+#endif
+#ifdef EXTRAKEY_ENABLE
+ case EXTRAKEY_INTERFACE:
+ Address = &ExtrakeyReport;
+ Size = sizeof(ExtrakeyReport);
+ break;
+#endif
+#ifdef CONSOLE_ENABLE
+ case CONSOLE_INTERFACE:
+ Address = &ConsoleReport;
+ Size = sizeof(ConsoleReport);
+ break;
+#endif
+#ifdef NKRO_ENABLE
+ case NKRO_INTERFACE:
+ Address = &NKROReport;
+ Size = sizeof(NKROReport);
+ break;
+#endif
+ }
+ break;
+ }
+
+ *DescriptorAddress = Address;
+ return Size;
+}
diff --git a/tmk_core/protocol/lufa/descriptor.h b/tmk_core/protocol/lufa/descriptor.h
new file mode 100644
index 000000000..4fd81a0e8
--- /dev/null
+++ b/tmk_core/protocol/lufa/descriptor.h
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2012,2013 Jun Wako <wakojun@gmail.com>
+ * This file is based on:
+ * LUFA-120219/Demos/Device/Lowlevel/KeyboardMouse
+ * LUFA-120219/Demos/Device/Lowlevel/GenericHID
+ */
+
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2012.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+ Copyright 2010 Denver Gingerich (denver [at] ossguy [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ *
+ * Header file for Descriptors.c.
+ */
+
+#ifndef _DESCRIPTORS_H_
+#define _DESCRIPTORS_H_
+
+#include <LUFA/Drivers/USB/USB.h>
+#include <avr/pgmspace.h>
+
+
+typedef struct
+{
+ USB_Descriptor_Configuration_Header_t Config;
+
+ // Keyboard HID Interface
+ USB_Descriptor_Interface_t Keyboard_Interface;
+ USB_HID_Descriptor_HID_t Keyboard_HID;
+ USB_Descriptor_Endpoint_t Keyboard_INEndpoint;
+
+#ifdef MOUSE_ENABLE
+ // Mouse HID Interface
+ USB_Descriptor_Interface_t Mouse_Interface;
+ USB_HID_Descriptor_HID_t Mouse_HID;
+ USB_Descriptor_Endpoint_t Mouse_INEndpoint;
+#endif
+
+#ifdef EXTRAKEY_ENABLE
+ // Extrakey HID Interface
+ USB_Descriptor_Interface_t Extrakey_Interface;
+ USB_HID_Descriptor_HID_t Extrakey_HID;
+ USB_Descriptor_Endpoint_t Extrakey_INEndpoint;
+#endif
+
+#ifdef CONSOLE_ENABLE
+ // Console HID Interface
+ USB_Descriptor_Interface_t Console_Interface;
+ USB_HID_Descriptor_HID_t Console_HID;
+ USB_Descriptor_Endpoint_t Console_INEndpoint;
+ USB_Descriptor_Endpoint_t Console_OUTEndpoint;
+#endif
+
+#ifdef NKRO_ENABLE
+ // NKRO HID Interface
+ USB_Descriptor_Interface_t NKRO_Interface;
+ USB_HID_Descriptor_HID_t NKRO_HID;
+ USB_Descriptor_Endpoint_t NKRO_INEndpoint;
+#endif
+
+#ifdef MIDI_ENABLE
+ // MIDI Audio Control Interface
+ USB_Descriptor_Interface_t Audio_ControlInterface;
+ USB_Audio_Descriptor_Interface_AC_t Audio_ControlInterface_SPC;
+
+ // MIDI Audio Streaming Interface
+ USB_Descriptor_Interface_t Audio_StreamInterface;
+ USB_MIDI_Descriptor_AudioInterface_AS_t Audio_StreamInterface_SPC;
+ USB_MIDI_Descriptor_InputJack_t MIDI_In_Jack_Emb;
+ USB_MIDI_Descriptor_InputJack_t MIDI_In_Jack_Ext;
+ USB_MIDI_Descriptor_OutputJack_t MIDI_Out_Jack_Emb;
+ USB_MIDI_Descriptor_OutputJack_t MIDI_Out_Jack_Ext;
+ USB_Audio_Descriptor_StreamEndpoint_Std_t MIDI_In_Jack_Endpoint;
+ USB_MIDI_Descriptor_Jack_Endpoint_t MIDI_In_Jack_Endpoint_SPC;
+ USB_Audio_Descriptor_StreamEndpoint_Std_t MIDI_Out_Jack_Endpoint;
+ USB_MIDI_Descriptor_Jack_Endpoint_t MIDI_Out_Jack_Endpoint_SPC;
+#endif
+
+} USB_Descriptor_Configuration_t;
+
+
+/* index of interface */
+#define KEYBOARD_INTERFACE 0
+
+#ifdef MOUSE_ENABLE
+# define MOUSE_INTERFACE (KEYBOARD_INTERFACE + 1)
+#else
+# define MOUSE_INTERFACE KEYBOARD_INTERFACE
+#endif
+
+#ifdef EXTRAKEY_ENABLE
+# define EXTRAKEY_INTERFACE (MOUSE_INTERFACE + 1)
+#else
+# define EXTRAKEY_INTERFACE MOUSE_INTERFACE
+#endif
+
+#ifdef CONSOLE_ENABLE
+# define CONSOLE_INTERFACE (EXTRAKEY_INTERFACE + 1)
+#else
+# define CONSOLE_INTERFACE EXTRAKEY_INTERFACE
+#endif
+
+#ifdef NKRO_ENABLE
+# define NKRO_INTERFACE (CONSOLE_INTERFACE + 1)
+#else
+# define NKRO_INTERFACE CONSOLE_INTERFACE
+#endif
+
+#ifdef MIDI_ENABLE
+# define AC_INTERFACE (NKRO_INTERFACE + 1)
+# define AS_INTERFACE (NKRO_INTERFACE + 2)
+#else
+# define AS_INTERFACE NKRO_INTERFACE
+#endif
+
+/* nubmer of interfaces */
+#define TOTAL_INTERFACES AS_INTERFACE + 1
+
+
+// Endopoint number and size
+#define KEYBOARD_IN_EPNUM 1
+
+#ifdef MOUSE_ENABLE
+# define MOUSE_IN_EPNUM (KEYBOARD_IN_EPNUM + 1)
+#else
+# define MOUSE_IN_EPNUM KEYBOARD_IN_EPNUM
+#endif
+
+#ifdef EXTRAKEY_ENABLE
+# define EXTRAKEY_IN_EPNUM (MOUSE_IN_EPNUM + 1)
+#else
+# define EXTRAKEY_IN_EPNUM MOUSE_IN_EPNUM
+#endif
+
+#ifdef CONSOLE_ENABLE
+# define CONSOLE_IN_EPNUM (EXTRAKEY_IN_EPNUM + 1)
+# define CONSOLE_OUT_EPNUM (EXTRAKEY_IN_EPNUM + 1)
+//# define CONSOLE_OUT_EPNUM (EXTRAKEY_IN_EPNUM + 2)
+#else
+# define CONSOLE_OUT_EPNUM EXTRAKEY_IN_EPNUM
+#endif
+
+#ifdef NKRO_ENABLE
+# define NKRO_IN_EPNUM (CONSOLE_OUT_EPNUM + 1)
+#else
+# define NKRO_IN_EPNUM CONSOLE_OUT_EPNUM
+#endif
+
+#ifdef MIDI_ENABLE
+# define MIDI_STREAM_IN_EPNUM (NKRO_IN_EPNUM + 1)
+// # define MIDI_STREAM_OUT_EPNUM (NKRO_IN_EPNUM + 1)
+# define MIDI_STREAM_OUT_EPNUM (NKRO_IN_EPNUM + 2)
+# define MIDI_STREAM_IN_EPADDR (ENDPOINT_DIR_IN | MIDI_STREAM_IN_EPNUM)
+# define MIDI_STREAM_OUT_EPADDR (ENDPOINT_DIR_OUT | MIDI_STREAM_OUT_EPNUM)
+#endif
+
+
+#if defined(__AVR_ATmega32U2__) && MIDI_STREAM_OUT_EPADDR > 4
+# error "Endpoints are not available enough to support all functions. Remove some in Makefile.(MOUSEKEY, EXTRAKEY, CONSOLE, NKRO, MIDI)"
+#endif
+
+#define KEYBOARD_EPSIZE 8
+#define MOUSE_EPSIZE 8
+#define EXTRAKEY_EPSIZE 8
+#define CONSOLE_EPSIZE 32
+#define NKRO_EPSIZE 16
+#define MIDI_STREAM_EPSIZE 64
+
+
+uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
+ const uint8_t wIndex,
+ const void** const DescriptorAddress)
+ ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
+
+
+/* new API */
+#if LUFA_VERSION_INTEGER < 0x140302
+ #undef VERSION_BCD
+ #define VERSION_BCD(Major, Minor, Revision) \
+ CPU_TO_LE16( ((Major & 0xFF) << 8) | \
+ ((Minor & 0x0F) << 4) | \
+ (Revision & 0x0F) )
+#endif
+
+#endif
diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c
new file mode 100644
index 000000000..9ca55dbc9
--- /dev/null
+++ b/tmk_core/protocol/lufa/lufa.c
@@ -0,0 +1,977 @@
+/*
+ * Copyright 2012 Jun Wako <wakojun@gmail.com>
+ * This file is based on:
+ * LUFA-120219/Demos/Device/Lowlevel/KeyboardMouse
+ * LUFA-120219/Demos/Device/Lowlevel/GenericHID
+ */
+
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2012.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+ Copyright 2010 Denver Gingerich (denver [at] ossguy [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#include "report.h"
+#include "host.h"
+#include "host_driver.h"
+#include "keyboard.h"
+#include "action.h"
+#include "led.h"
+#include "sendchar.h"
+#include "debug.h"
+#ifdef SLEEP_LED_ENABLE
+#include "sleep_led.h"
+#endif
+#include "suspend.h"
+
+#include "descriptor.h"
+#include "lufa.h"
+
+#ifdef AUDIO_ENABLE
+ #include <audio.h>
+#endif
+
+#ifdef BLUETOOTH_ENABLE
+ #include "bluetooth.h"
+#endif
+
+uint8_t keyboard_idle = 0;
+/* 0: Boot Protocol, 1: Report Protocol(default) */
+uint8_t keyboard_protocol = 1;
+static uint8_t keyboard_led_stats = 0;
+
+static report_keyboard_t keyboard_report_sent;
+
+#ifdef MIDI_ENABLE
+void usb_send_func(MidiDevice * device, uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2);
+void usb_get_midi(MidiDevice * device);
+void midi_usb_init(MidiDevice * device);
+#endif
+
+/* Host driver */
+static uint8_t keyboard_leds(void);
+static void send_keyboard(report_keyboard_t *report);
+static void send_mouse(report_mouse_t *report);
+static void send_system(uint16_t data);
+static void send_consumer(uint16_t data);
+host_driver_t lufa_driver = {
+ keyboard_leds,
+ send_keyboard,
+ send_mouse,
+ send_system,
+ send_consumer,
+#ifdef MIDI_ENABLE
+ usb_send_func,
+ usb_get_midi,
+ midi_usb_init
+#endif
+};
+
+/*******************************************************************************
+ * MIDI
+ ******************************************************************************/
+
+#ifdef MIDI_ENABLE
+USB_ClassInfo_MIDI_Device_t USB_MIDI_Interface =
+{
+ .Config =
+ {
+ .StreamingInterfaceNumber = AS_INTERFACE,
+ .DataINEndpoint =
+ {
+ .Address = MIDI_STREAM_IN_EPADDR,
+ .Size = MIDI_STREAM_EPSIZE,
+ .Banks = 1,
+ },
+ .DataOUTEndpoint =
+ {
+ .Address = MIDI_STREAM_OUT_EPADDR,
+ .Size = MIDI_STREAM_EPSIZE,
+ .Banks = 1,
+ },
+ },
+};
+
+#define SYSEX_START_OR_CONT 0x40
+#define SYSEX_ENDS_IN_1 0x50
+#define SYSEX_ENDS_IN_2 0x60
+#define SYSEX_ENDS_IN_3 0x70
+
+#define SYS_COMMON_1 0x50
+#define SYS_COMMON_2 0x20
+#define SYS_COMMON_3 0x30
+#endif
+
+
+/*******************************************************************************
+ * Console
+ ******************************************************************************/
+#ifdef CONSOLE_ENABLE
+static void Console_Task(void)
+{
+ /* Device must be connected and configured for the task to run */
+ if (USB_DeviceState != DEVICE_STATE_Configured)
+ return;
+
+ uint8_t ep = Endpoint_GetCurrentEndpoint();
+
+#if 0
+ // TODO: impl receivechar()/recvchar()
+ Endpoint_SelectEndpoint(CONSOLE_OUT_EPNUM);
+
+ /* Check to see if a packet has been sent from the host */
+ if (Endpoint_IsOUTReceived())
+ {
+ /* Check to see if the packet contains data */
+ if (Endpoint_IsReadWriteAllowed())
+ {
+ /* Create a temporary buffer to hold the read in report from the host */
+ uint8_t ConsoleData[CONSOLE_EPSIZE];
+
+ /* Read Console Report Data */
+ Endpoint_Read_Stream_LE(&ConsoleData, sizeof(ConsoleData), NULL);
+
+ /* Process Console Report Data */
+ //ProcessConsoleHIDReport(ConsoleData);
+ }
+
+ /* Finalize the stream transfer to send the last packet */
+ Endpoint_ClearOUT();
+ }
+#endif
+
+ /* IN packet */
+ Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
+ if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
+ Endpoint_SelectEndpoint(ep);
+ return;
+ }
+
+ // fill empty bank
+ while (Endpoint_IsReadWriteAllowed())
+ Endpoint_Write_8(0);
+
+ // flash senchar packet
+ if (Endpoint_IsINReady()) {
+ Endpoint_ClearIN();
+ }
+
+ Endpoint_SelectEndpoint(ep);
+}
+#endif
+
+
+/*******************************************************************************
+ * USB Events
+ ******************************************************************************/
+/*
+ * Event Order of Plug in:
+ * 0) EVENT_USB_Device_Connect
+ * 1) EVENT_USB_Device_Suspend
+ * 2) EVENT_USB_Device_Reset
+ * 3) EVENT_USB_Device_Wake
+*/
+void EVENT_USB_Device_Connect(void)
+{
+ print("[C]");
+ /* For battery powered device */
+ if (!USB_IsInitialized) {
+ USB_Disable();
+ USB_Init();
+ USB_Device_EnableSOFEvents();
+ }
+}
+
+void EVENT_USB_Device_Disconnect(void)
+{
+ print("[D]");
+ /* For battery powered device */
+ USB_IsInitialized = false;
+/* TODO: This doesn't work. After several plug in/outs can not be enumerated.
+ if (USB_IsInitialized) {
+ USB_Disable(); // Disable all interrupts
+ USB_Controller_Enable();
+ USB_INT_Enable(USB_INT_VBUSTI);
+ }
+*/
+}
+
+void EVENT_USB_Device_Reset(void)
+{
+ print("[R]");
+}
+
+void EVENT_USB_Device_Suspend()
+{
+ print("[S]");
+#ifdef SLEEP_LED_ENABLE
+ sleep_led_enable();
+#endif
+}
+
+void EVENT_USB_Device_WakeUp()
+{
+ print("[W]");
+ suspend_wakeup_init();
+
+#ifdef SLEEP_LED_ENABLE
+ sleep_led_disable();
+ // NOTE: converters may not accept this
+ led_set(host_keyboard_leds());
+#endif
+}
+
+#ifdef CONSOLE_ENABLE
+static bool console_flush = false;
+#define CONSOLE_FLUSH_SET(b) do { \
+ uint8_t sreg = SREG; cli(); console_flush = b; SREG = sreg; \
+} while (0)
+
+// called every 1ms
+void EVENT_USB_Device_StartOfFrame(void)
+{
+ static uint8_t count;
+ if (++count % 50) return;
+ count = 0;
+
+ if (!console_flush) return;
+ Console_Task();
+ console_flush = false;
+}
+#endif
+
+/** Event handler for the USB_ConfigurationChanged event.
+ * This is fired when the host sets the current configuration of the USB device after enumeration.
+ *
+ * ATMega32u2 supports dual bank(ping-pong mode) only on endpoint 3 and 4,
+ * it is safe to use singl bank for all endpoints.
+ */
+void EVENT_USB_Device_ConfigurationChanged(void)
+{
+ bool ConfigSuccess = true;
+
+ /* Setup Keyboard HID Report Endpoints */
+ ConfigSuccess &= ENDPOINT_CONFIG(KEYBOARD_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
+ KEYBOARD_EPSIZE, ENDPOINT_BANK_SINGLE);
+
+#ifdef MOUSE_ENABLE
+ /* Setup Mouse HID Report Endpoint */
+ ConfigSuccess &= ENDPOINT_CONFIG(MOUSE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
+ MOUSE_EPSIZE, ENDPOINT_BANK_SINGLE);
+#endif
+
+#ifdef EXTRAKEY_ENABLE
+ /* Setup Extra HID Report Endpoint */
+ ConfigSuccess &= ENDPOINT_CONFIG(EXTRAKEY_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
+ EXTRAKEY_EPSIZE, ENDPOINT_BANK_SINGLE);
+#endif
+
+#ifdef CONSOLE_ENABLE
+ /* Setup Console HID Report Endpoints */
+ ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
+ CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
+#if 0
+ ConfigSuccess &= ENDPOINT_CONFIG(CONSOLE_OUT_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_OUT,
+ CONSOLE_EPSIZE, ENDPOINT_BANK_SINGLE);
+#endif
+#endif
+
+#ifdef NKRO_ENABLE
+ /* Setup NKRO HID Report Endpoints */
+ ConfigSuccess &= ENDPOINT_CONFIG(NKRO_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
+ NKRO_EPSIZE, ENDPOINT_BANK_SINGLE);
+#endif
+
+#ifdef MIDI_ENABLE
+ ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_IN_EPADDR, EP_TYPE_BULK, MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE);
+ ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_OUT_EPADDR, EP_TYPE_BULK, MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE);
+#endif
+}
+
+/*
+Appendix G: HID Request Support Requirements
+
+The following table enumerates the requests that need to be supported by various types of HID class devices.
+
+Device type GetReport SetReport GetIdle SetIdle GetProtocol SetProtocol
+------------------------------------------------------------------------------------------
+Boot Mouse Required Optional Optional Optional Required Required
+Non-Boot Mouse Required Optional Optional Optional Optional Optional
+Boot Keyboard Required Optional Required Required Required Required
+Non-Boot Keybrd Required Optional Required Required Optional Optional
+Other Device Required Optional Optional Optional Optional Optional
+*/
+/** Event handler for the USB_ControlRequest event.
+ * This is fired before passing along unhandled control requests to the library for processing internally.
+ */
+void EVENT_USB_Device_ControlRequest(void)
+{
+ uint8_t* ReportData = NULL;
+ uint8_t ReportSize = 0;
+
+ /* Handle HID Class specific requests */
+ switch (USB_ControlRequest.bRequest)
+ {
+ case HID_REQ_GetReport:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+
+ // Interface
+ switch (USB_ControlRequest.wIndex) {
+ case KEYBOARD_INTERFACE:
+ // TODO: test/check
+ ReportData = (uint8_t*)&keyboard_report_sent;
+ ReportSize = sizeof(keyboard_report_sent);
+ break;
+ }
+
+ /* Write the report data to the control endpoint */
+ Endpoint_Write_Control_Stream_LE(ReportData, ReportSize);
+ Endpoint_ClearOUT();
+ }
+
+ break;
+ case HID_REQ_SetReport:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+
+ // Interface
+ switch (USB_ControlRequest.wIndex) {
+ case KEYBOARD_INTERFACE:
+#ifdef NKRO_ENABLE
+ case NKRO_INTERFACE:
+#endif
+ Endpoint_ClearSETUP();
+
+ while (!(Endpoint_IsOUTReceived())) {
+ if (USB_DeviceState == DEVICE_STATE_Unattached)
+ return;
+ }
+ keyboard_led_stats = Endpoint_Read_8();
+
+ Endpoint_ClearOUT();
+ Endpoint_ClearStatusStage();
+ break;
+ }
+
+ }
+
+ break;
+
+ case HID_REQ_GetProtocol:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
+ Endpoint_ClearSETUP();
+ while (!(Endpoint_IsINReady()));
+ Endpoint_Write_8(keyboard_protocol);
+ Endpoint_ClearIN();
+ Endpoint_ClearStatusStage();
+ }
+ }
+
+ break;
+ case HID_REQ_SetProtocol:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ if (USB_ControlRequest.wIndex == KEYBOARD_INTERFACE) {
+ Endpoint_ClearSETUP();
+ Endpoint_ClearStatusStage();
+
+ keyboard_protocol = (USB_ControlRequest.wValue & 0xFF);
+ clear_keyboard();
+ }
+ }
+
+ break;
+ case HID_REQ_SetIdle:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+ Endpoint_ClearStatusStage();
+
+ keyboard_idle = ((USB_ControlRequest.wValue & 0xFF00) >> 8);
+ }
+
+ break;
+ case HID_REQ_GetIdle:
+ if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
+ {
+ Endpoint_ClearSETUP();
+ while (!(Endpoint_IsINReady()));
+ Endpoint_Write_8(keyboard_idle);
+ Endpoint_ClearIN();
+ Endpoint_ClearStatusStage();
+ }
+
+ break;
+ }
+}
+
+/*******************************************************************************
+ * Host driver
+ ******************************************************************************/
+static uint8_t keyboard_leds(void)
+{
+ return keyboard_led_stats;
+}
+
+static void send_keyboard(report_keyboard_t *report)
+{
+
+#ifdef BLUETOOTH_ENABLE
+ bluefruit_serial_send(0xFD);
+ for (uint8_t i = 0; i < KEYBOARD_EPSIZE; i++) {
+ bluefruit_serial_send(report->raw[i]);
+ }
+#endif
+
+ uint8_t timeout = 255;
+
+ if (USB_DeviceState != DEVICE_STATE_Configured)
+ return;
+
+ /* Select the Keyboard Report Endpoint */
+#ifdef NKRO_ENABLE
+ if (keyboard_protocol && keyboard_nkro) {
+ /* Report protocol - NKRO */
+ Endpoint_SelectEndpoint(NKRO_IN_EPNUM);
+
+ /* Check if write ready for a polling interval around 1ms */
+ while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(4);
+ if (!Endpoint_IsReadWriteAllowed()) return;
+
+ /* Write Keyboard Report Data */
+ Endpoint_Write_Stream_LE(report, NKRO_EPSIZE, NULL);
+ }
+ else
+#endif
+ {
+ /* Boot protocol */
+ Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM);
+
+ /* Check if write ready for a polling interval around 10ms */
+ while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
+ if (!Endpoint_IsReadWriteAllowed()) return;
+
+ /* Write Keyboard Report Data */
+ Endpoint_Write_Stream_LE(report, KEYBOARD_EPSIZE, NULL);
+ }
+
+ /* Finalize the stream transfer to send the last packet */
+ Endpoint_ClearIN();
+
+ keyboard_report_sent = *report;
+}
+
+static void send_mouse(report_mouse_t *report)
+{
+#ifdef MOUSE_ENABLE
+
+#ifdef BLUETOOTH_ENABLE
+ bluefruit_serial_send(0xFD);
+ bluefruit_serial_send(0x00);
+ bluefruit_serial_send(0x03);
+ bluefruit_serial_send(report->buttons);
+ bluefruit_serial_send(report->x);
+ bluefruit_serial_send(report->y);
+ bluefruit_serial_send(report->v); // should try sending the wheel v here
+ bluefruit_serial_send(report->h); // should try sending the wheel h here
+ bluefruit_serial_send(0x00);
+#endif
+
+ uint8_t timeout = 255;
+
+ if (USB_DeviceState != DEVICE_STATE_Configured)
+ return;
+
+ /* Select the Mouse Report Endpoint */
+ Endpoint_SelectEndpoint(MOUSE_IN_EPNUM);
+
+ /* Check if write ready for a polling interval around 10ms */
+ while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
+ if (!Endpoint_IsReadWriteAllowed()) return;
+
+ /* Write Mouse Report Data */
+ Endpoint_Write_Stream_LE(report, sizeof(report_mouse_t), NULL);
+
+ /* Finalize the stream transfer to send the last packet */
+ Endpoint_ClearIN();
+#endif
+}
+
+static void send_system(uint16_t data)
+{
+ uint8_t timeout = 255;
+
+ if (USB_DeviceState != DEVICE_STATE_Configured)
+ return;
+
+ report_extra_t r = {
+ .report_id = REPORT_ID_SYSTEM,
+ .usage = data
+ };
+ Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
+
+ /* Check if write ready for a polling interval around 10ms */
+ while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
+ if (!Endpoint_IsReadWriteAllowed()) return;
+
+ Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
+ Endpoint_ClearIN();
+}
+
+static void send_consumer(uint16_t data)
+{
+
+#ifdef BLUETOOTH_ENABLE
+ static uint16_t last_data = 0;
+ if (data == last_data) return;
+ last_data = data;
+ uint16_t bitmap = CONSUMER2BLUEFRUIT(data);
+ bluefruit_serial_send(0xFD);
+ bluefruit_serial_send(0x00);
+ bluefruit_serial_send(0x02);
+ bluefruit_serial_send((bitmap>>8)&0xFF);
+ bluefruit_serial_send(bitmap&0xFF);
+ bluefruit_serial_send(0x00);
+ bluefruit_serial_send(0x00);
+ bluefruit_serial_send(0x00);
+ bluefruit_serial_send(0x00);
+#endif
+
+ uint8_t timeout = 255;
+
+ if (USB_DeviceState != DEVICE_STATE_Configured)
+ return;
+
+ report_extra_t r = {
+ .report_id = REPORT_ID_CONSUMER,
+ .usage = data
+ };
+ Endpoint_SelectEndpoint(EXTRAKEY_IN_EPNUM);
+
+ /* Check if write ready for a polling interval around 10ms */
+ while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
+ if (!Endpoint_IsReadWriteAllowed()) return;
+
+ Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL);
+ Endpoint_ClearIN();
+}
+
+
+/*******************************************************************************
+ * sendchar
+ ******************************************************************************/
+#ifdef CONSOLE_ENABLE
+#define SEND_TIMEOUT 5
+int8_t sendchar(uint8_t c)
+{
+ // Not wait once timeouted.
+ // Because sendchar() is called so many times, waiting each call causes big lag.
+ static bool timeouted = false;
+
+ // prevents Console_Task() from running during sendchar() runs.
+ // or char will be lost. These two function is mutually exclusive.
+ CONSOLE_FLUSH_SET(false);
+
+ if (USB_DeviceState != DEVICE_STATE_Configured)
+ return -1;
+
+ uint8_t ep = Endpoint_GetCurrentEndpoint();
+ Endpoint_SelectEndpoint(CONSOLE_IN_EPNUM);
+ if (!Endpoint_IsEnabled() || !Endpoint_IsConfigured()) {
+ goto ERROR_EXIT;
+ }
+
+ if (timeouted && !Endpoint_IsReadWriteAllowed()) {
+ goto ERROR_EXIT;
+ }
+
+ timeouted = false;
+
+ uint8_t timeout = SEND_TIMEOUT;
+ while (!Endpoint_IsReadWriteAllowed()) {
+ if (USB_DeviceState != DEVICE_STATE_Configured) {
+ goto ERROR_EXIT;
+ }
+ if (Endpoint_IsStalled()) {
+ goto ERROR_EXIT;
+ }
+ if (!(timeout--)) {
+ timeouted = true;
+ goto ERROR_EXIT;
+ }
+ _delay_ms(1);
+ }
+
+ Endpoint_Write_8(c);
+
+ // send when bank is full
+ if (!Endpoint_IsReadWriteAllowed()) {
+ while (!(Endpoint_IsINReady()));
+ Endpoint_ClearIN();
+ } else {
+ CONSOLE_FLUSH_SET(true);
+ }
+
+ Endpoint_SelectEndpoint(ep);
+ return 0;
+ERROR_EXIT:
+ Endpoint_SelectEndpoint(ep);
+ return -1;
+}
+#else
+int8_t sendchar(uint8_t c)
+{
+ return 0;
+}
+#endif
+
+/*******************************************************************************
+ * MIDI
+ ******************************************************************************/
+
+#ifdef MIDI_ENABLE
+void usb_send_func(MidiDevice * device, uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2) {
+ MIDI_EventPacket_t event;
+ event.Data1 = byte0;
+ event.Data2 = byte1;
+ event.Data3 = byte2;
+
+ uint8_t cable = 0;
+
+// Endpoint_SelectEndpoint(MIDI_STREAM_IN_EPNUM);
+
+ //if the length is undefined we assume it is a SYSEX message
+ if (midi_packet_length(byte0) == UNDEFINED) {
+ switch(cnt) {
+ case 3:
+ if (byte2 == SYSEX_END)
+ event.Event = MIDI_EVENT(cable, SYSEX_ENDS_IN_3);
+ else
+ event.Event = MIDI_EVENT(cable, SYSEX_START_OR_CONT);
+ break;
+ case 2:
+ if (byte1 == SYSEX_END)
+ event.Event = MIDI_EVENT(cable, SYSEX_ENDS_IN_2);
+ else
+ event.Event = MIDI_EVENT(cable, SYSEX_START_OR_CONT);
+ break;
+ case 1:
+ if (byte0 == SYSEX_END)
+ event.Event = MIDI_EVENT(cable, SYSEX_ENDS_IN_1);
+ else
+ event.Event = MIDI_EVENT(cable, SYSEX_START_OR_CONT);
+ break;
+ default:
+ return; //invalid cnt
+ }
+ } else {
+ //deal with 'system common' messages
+ //TODO are there any more?
+ switch(byte0 & 0xF0){
+ case MIDI_SONGPOSITION:
+ event.Event = MIDI_EVENT(cable, SYS_COMMON_3);
+ break;
+ case MIDI_SONGSELECT:
+ case MIDI_TC_QUARTERFRAME:
+ event.Event = MIDI_EVENT(cable, SYS_COMMON_2);
+ break;
+ default:
+ event.Event = MIDI_EVENT(cable, byte0);
+ break;
+ }
+ }
+
+// Endpoint_Write_Stream_LE(&event, sizeof(event), NULL);
+// Endpoint_ClearIN();
+
+ MIDI_Device_SendEventPacket(&USB_MIDI_Interface, &event);
+ MIDI_Device_Flush(&USB_MIDI_Interface);
+ MIDI_Device_USBTask(&USB_MIDI_Interface);
+ USB_USBTask();
+}
+
+void usb_get_midi(MidiDevice * device) {
+ MIDI_EventPacket_t event;
+ while (MIDI_Device_ReceiveEventPacket(&USB_MIDI_Interface, &event)) {
+
+ midi_packet_length_t length = midi_packet_length(event.Data1);
+ uint8_t input[3];
+ input[0] = event.Data1;
+ input[1] = event.Data2;
+ input[2] = event.Data3;
+ if (length == UNDEFINED) {
+ //sysex
+ if (event.Event == MIDI_EVENT(0, SYSEX_START_OR_CONT) || event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_3)) {
+ length = 3;
+ } else if (event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_2)) {
+ length = 2;
+ } else if(event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_1)) {
+ length = 1;
+ } else {
+ //XXX what to do?
+ }
+ }
+
+ //pass the data to the device input function
+ if (length != UNDEFINED)
+ midi_device_input(device, length, input);
+ }
+ MIDI_Device_USBTask(&USB_MIDI_Interface);
+ USB_USBTask();
+}
+
+void midi_usb_init(MidiDevice * device){
+ midi_device_init(device);
+ midi_device_set_send_func(device, usb_send_func);
+ midi_device_set_pre_input_process_func(device, usb_get_midi);
+
+ SetupHardware();
+ sei();
+}
+
+void MIDI_Task(void)
+{
+
+ /* Device must be connected and configured for the task to run */
+ dprint("in MIDI_TASK\n");
+ if (USB_DeviceState != DEVICE_STATE_Configured)
+ return;
+ dprint("continuing in MIDI_TASK\n");
+
+ Endpoint_SelectEndpoint(MIDI_STREAM_IN_EPADDR);
+
+ if (Endpoint_IsINReady())
+ {
+
+ dprint("Endpoint is ready\n");
+
+ uint8_t MIDICommand = 0;
+ uint8_t MIDIPitch;
+
+ /* Get board button status - if pressed use channel 10 (percussion), otherwise use channel 1 */
+ uint8_t Channel = MIDI_CHANNEL(1);
+
+ MIDICommand = MIDI_COMMAND_NOTE_ON;
+ MIDIPitch = 0x3E;
+
+ /* Check if a MIDI command is to be sent */
+ if (MIDICommand)
+ {
+ dprint("Command exists\n");
+ MIDI_EventPacket_t MIDIEvent = (MIDI_EventPacket_t)
+ {
+ .Event = MIDI_EVENT(0, MIDICommand),
+
+ .Data1 = MIDICommand | Channel,
+ .Data2 = MIDIPitch,
+ .Data3 = MIDI_STANDARD_VELOCITY,
+ };
+
+ /* Write the MIDI event packet to the endpoint */
+ Endpoint_Write_Stream_LE(&MIDIEvent, sizeof(MIDIEvent), NULL);
+
+ /* Send the data in the endpoint to the host */
+ Endpoint_ClearIN();
+ }
+ }
+
+
+ /* Select the MIDI OUT stream */
+ Endpoint_SelectEndpoint(MIDI_STREAM_OUT_EPADDR);
+
+ /* Check if a MIDI command has been received */
+ if (Endpoint_IsOUTReceived())
+ {
+ MIDI_EventPacket_t MIDIEvent;
+
+ /* Read the MIDI event packet from the endpoint */
+ Endpoint_Read_Stream_LE(&MIDIEvent, sizeof(MIDIEvent), NULL);
+
+ /* If the endpoint is now empty, clear the bank */
+ if (!(Endpoint_BytesInEndpoint()))
+ {
+ /* Clear the endpoint ready for new packet */
+ Endpoint_ClearOUT();
+ }
+ }
+}
+
+#endif
+
+
+/*******************************************************************************
+ * main
+ ******************************************************************************/
+static void setup_mcu(void)
+{
+ /* Disable watchdog if enabled by bootloader/fuses */
+ MCUSR &= ~(1 << WDRF);
+ wdt_disable();
+
+ /* Disable clock division */
+ // clock_prescale_set(clock_div_1);
+
+ CLKPR = (1 << CLKPCE);
+ CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0);
+}
+
+static void setup_usb(void)
+{
+ // Leonardo needs. Without this USB device is not recognized.
+ USB_Disable();
+
+ USB_Init();
+
+ // for Console_Task
+ USB_Device_EnableSOFEvents();
+ print_set_sendchar(sendchar);
+}
+
+
+#ifdef MIDI_ENABLE
+void fallthrough_callback(MidiDevice * device,
+ uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2);
+void cc_callback(MidiDevice * device,
+ uint8_t chan, uint8_t num, uint8_t val);
+void sysex_callback(MidiDevice * device,
+ uint16_t start, uint8_t length, uint8_t * data);
+#endif
+
+int main(void) __attribute__ ((weak));
+int main(void)
+{
+
+#ifdef MIDI_ENABLE
+ midi_device_init(&midi_device);
+ midi_device_set_send_func(&midi_device, usb_send_func);
+ midi_device_set_pre_input_process_func(&midi_device, usb_get_midi);
+#endif
+
+ setup_mcu();
+ keyboard_setup();
+ setup_usb();
+ sei();
+
+#ifdef MIDI_ENABLE
+ midi_register_fallthrough_callback(&midi_device, fallthrough_callback);
+ midi_register_cc_callback(&midi_device, cc_callback);
+ midi_register_sysex_callback(&midi_device, sysex_callback);
+
+ // init_notes();
+ // midi_send_cc(&midi_device, 0, 1, 2);
+ // midi_send_cc(&midi_device, 15, 1, 0);
+ // midi_send_noteon(&midi_device, 0, 64, 127);
+ // midi_send_noteoff(&midi_device, 0, 64, 127);
+#endif
+
+#ifdef BLUETOOTH_ENABLE
+ serial_init();
+#endif
+
+ /* wait for USB startup & debug output */
+
+#ifdef WAIT_FOR_USB
+ while (USB_DeviceState != DEVICE_STATE_Configured) {
+ #if defined(INTERRUPT_CONTROL_ENDPOINT)
+ ;
+ #else
+ USB_USBTask();
+ #endif
+ }
+ print("USB configured.\n");
+#else
+ USB_USBTask();
+#endif
+ /* init modules */
+ keyboard_init();
+ host_set_driver(&lufa_driver);
+#ifdef SLEEP_LED_ENABLE
+ sleep_led_init();
+#endif
+
+ print("Keyboard start.\n");
+ while (1) {
+ #ifndef BLUETOOTH_ENABLE
+ while (USB_DeviceState == DEVICE_STATE_Suspended) {
+ print("[s]");
+ suspend_power_down();
+ if (USB_Device_RemoteWakeupEnabled && suspend_wakeup_condition()) {
+ USB_Device_SendRemoteWakeup();
+ }
+ }
+ #endif
+
+#ifdef MIDI_ENABLE
+ midi_device_process(&midi_device);
+ // MIDI_Task();
+#endif
+ keyboard_task();
+
+#if !defined(INTERRUPT_CONTROL_ENDPOINT)
+ USB_USBTask();
+#endif
+ }
+}
+
+#ifdef MIDI_ENABLE
+void fallthrough_callback(MidiDevice * device,
+ uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2){
+
+#ifdef AUDIO_ENABLE
+ if (cnt == 3) {
+ switch (byte0 & 0xF0) {
+ case MIDI_NOTEON:
+ play_note(((double)261.6)*pow(2.0, -4.0)*pow(2.0,(byte1 & 0x7F)/12.0), (byte2 & 0x7F) / 8);
+ break;
+ case MIDI_NOTEOFF:
+ stop_note(((double)261.6)*pow(2.0, -4.0)*pow(2.0,(byte1 & 0x7F)/12.0));
+ break;
+ }
+ }
+ if (byte0 == MIDI_STOP) {
+ stop_all_notes();
+ }
+#endif
+}
+
+void cc_callback(MidiDevice * device,
+ uint8_t chan, uint8_t num, uint8_t val) {
+ //sending it back on the next channel
+ midi_send_cc(device, (chan + 1) % 16, num, val);
+}
+
+void sysex_callback(MidiDevice * device,
+ uint16_t start, uint8_t length, uint8_t * data) {
+ for (int i = 0; i < length; i++)
+ midi_send_cc(device, 15, 0x7F & data[i], 0x7F & (start + i));
+}
+#endif
diff --git a/tmk_core/protocol/lufa/lufa.h b/tmk_core/protocol/lufa/lufa.h
new file mode 100644
index 000000000..aad08d640
--- /dev/null
+++ b/tmk_core/protocol/lufa/lufa.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2012 Jun Wako <wakojun@gmail.com>
+ * This file is based on:
+ * LUFA-120219/Demos/Device/Lowlevel/KeyboardMouse
+ * LUFA-120219/Demos/Device/Lowlevel/GenericHID
+ */
+
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2012.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+ Copyright 2010 Denver Gingerich (denver [at] ossguy [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+#ifndef _LUFA_H_
+#define _LUFA_H_
+
+#include <avr/io.h>
+#include <avr/wdt.h>
+#include <avr/power.h>
+#include <avr/interrupt.h>
+#include <stdbool.h>
+#include <string.h>
+#include <LUFA/Version.h>
+#include <LUFA/Drivers/USB/USB.h>
+#include "host.h"
+#ifdef MIDI_ENABLE
+ #include "midi.h"
+#endif
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern host_driver_t lufa_driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+/* extra report structure */
+typedef struct {
+ uint8_t report_id;
+ uint16_t usage;
+} __attribute__ ((packed)) report_extra_t;
+
+#ifdef MIDI_ENABLE
+void MIDI_Task(void);
+MidiDevice midi_device;
+#endif
+
+// #if LUFA_VERSION_INTEGER < 0x120730
+// /* old API 120219 */
+// #define ENDPOINT_CONFIG(epnum, eptype, epdir, epsize, epbank) Endpoint_ConfigureEndpoint(epnum, eptype, epdir, epsize, epbank)
+// #else
+ /* new API >= 120730 */
+ #define ENDPOINT_BANK_SINGLE 1
+ #define ENDPOINT_BANK_DOUBLE 2
+ #define ENDPOINT_CONFIG(epnum, eptype, epdir, epsize, epbank) Endpoint_ConfigureEndpoint((epdir) | (epnum) , eptype, epsize, epbank)
+// #endif
+
+#endif
diff --git a/tmk_core/protocol/m0110.c b/tmk_core/protocol/m0110.c
new file mode 100644
index 000000000..0d3a5aaa4
--- /dev/null
+++ b/tmk_core/protocol/m0110.c
@@ -0,0 +1,591 @@
+/*
+Copyright 2011,2012 Jun WAKO <wakojun@gmail.com>
+
+This software is licensed with a Modified BSD License.
+All of this is supposed to be Free Software, Open Source, DFSG-free,
+GPL-compatible, and OK to use in both free and proprietary applications.
+Additions and corrections to this file are welcome.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+* Neither the name of the copyright holders nor the names of
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+/* M0110A Support was contributed by skagon@github */
+
+#include <stdbool.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <util/delay.h>
+#include "m0110.h"
+#include "debug.h"
+
+
+static inline uint8_t raw2scan(uint8_t raw);
+static inline uint8_t inquiry(void);
+static inline uint8_t instant(void);
+static inline void clock_lo(void);
+static inline void clock_hi(void);
+static inline bool clock_in(void);
+static inline void data_lo(void);
+static inline void data_hi(void);
+static inline bool data_in(void);
+static inline uint16_t wait_clock_lo(uint16_t us);
+static inline uint16_t wait_clock_hi(uint16_t us);
+static inline uint16_t wait_data_lo(uint16_t us);
+static inline uint16_t wait_data_hi(uint16_t us);
+static inline void idle(void);
+static inline void request(void);
+
+
+#define WAIT_US(stat, us, err) do { \
+ if (!wait_##stat(us)) { \
+ m0110_error = err; \
+ goto ERROR; \
+ } \
+} while (0)
+
+#define WAIT_MS(stat, ms, err) do { \
+ uint16_t _ms = ms; \
+ while (_ms) { \
+ if (wait_##stat(1000)) { \
+ break; \
+ } \
+ _ms--; \
+ } \
+ if (_ms == 0) { \
+ m0110_error = err; \
+ goto ERROR; \
+ } \
+} while (0)
+
+#define KEY(raw) ((raw) & 0x7f)
+#define IS_BREAK(raw) (((raw) & 0x80) == 0x80)
+
+
+uint8_t m0110_error = 0;
+
+
+void m0110_init(void)
+{
+ idle();
+ _delay_ms(1000);
+
+/* Not needed to initialize in fact.
+ uint8_t data;
+ m0110_send(M0110_MODEL);
+ data = m0110_recv();
+ print("m0110_init model: "); phex(data); print("\n");
+
+ m0110_send(M0110_TEST);
+ data = m0110_recv();
+ print("m0110_init test: "); phex(data); print("\n");
+*/
+}
+
+uint8_t m0110_send(uint8_t data)
+{
+ m0110_error = 0;
+
+ request();
+ WAIT_MS(clock_lo, 250, 1); // keyboard may block long time
+ for (uint8_t bit = 0x80; bit; bit >>= 1) {
+ WAIT_US(clock_lo, 250, 3);
+ if (data&bit) {
+ data_hi();
+ } else {
+ data_lo();
+ }
+ WAIT_US(clock_hi, 200, 4);
+ }
+ _delay_us(100); // hold last bit for 80us
+ idle();
+ return 1;
+ERROR:
+ print("m0110_send err: "); phex(m0110_error); print("\n");
+ _delay_ms(500);
+ idle();
+ return 0;
+}
+
+uint8_t m0110_recv(void)
+{
+ uint8_t data = 0;
+ m0110_error = 0;
+
+ WAIT_MS(clock_lo, 250, 1); // keyboard may block long time
+ for (uint8_t i = 0; i < 8; i++) {
+ data <<= 1;
+ WAIT_US(clock_lo, 200, 2);
+ WAIT_US(clock_hi, 200, 3);
+ if (data_in()) {
+ data |= 1;
+ }
+ }
+ idle();
+ return data;
+ERROR:
+ print("m0110_recv err: "); phex(m0110_error); print("\n");
+ _delay_ms(500);
+ idle();
+ return 0xFF;
+}
+
+/*
+Handling for exceptional case of key combinations for M0110A
+
+Shift and Calc/Arrow key could be operated simultaneously:
+
+ Case Shift Arrow Events Interpret
+ -------------------------------------------------------------------
+ 1 Down Down 71, 79, DD Calc(d)*a *b
+ 2 Down Up 71, 79, UU Arrow&Calc(u)*a
+ 3 Up Down F1, 79, DD Shift(u) *c
+ 4 Up Up F1, 79, UU Shift(u) and Arrow&Calc(u)*a
+
+ Case Shift Calc Events Interpret
+ -------------------------------------------------------------------
+ 5(1) Down Down 71, 71, 79, DD Shift(d) and Cacl(d)
+ 6(2) Down Up F1, 71, 79, UU Shift(u) and Arrow&Calc(u)*a
+ 7(1) Up Down F1, 71, 79, DD Shift(u) and Calc(d)
+ 8(4) Up Up F1, F1, 79, UU Shift(ux2) and Arrow&Calc(u)*a
+
+During Calc key is hold:
+ Case Shift Arrow Events Interpret
+ -------------------------------------------------------------------
+ A(3) ---- Down F1, 79, DD Shift(u) *c
+ B ---- Up 79, UU Arrow&Calc(u)*a
+ C Down ---- F1, 71 Shift(u) and Shift(d)
+ D Up ---- F1 Shift(u)
+ E Hold Down 79, DD Normal
+ F Hold Up 79, UU Arrow&Calc(u)*a
+ G(1) Down Down F1, 71, 79, DD Shift(u)*b and Calc(d)*a
+ H(2) Down Up F1, 71, 79, UU Shift(u) and Arrow&Calc(u)*a
+ I(3) Up Down F1, F1, 79, DD Shift(ux2) *c
+ J(4) Up Up F1, 79, UU Shift(u) and Arrow&Calc(u)*a
+
+ Case Shift Calc Events Interpret
+ -------------------------------------------------------------------
+ K(1) ---- Down 71, 79, DD Calc(d)*a
+ L(4) ---- Up F1, 79, UU Shift(u) and Arrow&Calc(u)*a
+ M(1) Hold Down 71, 79, DD Calc(d)*a
+ N Hold Up 79, UU Arrow&Calc(u)*a
+
+ Where DD/UU indicates part of Keypad Down/Up event.
+ *a: Impossible to distinguish btween Arrow and Calc event.
+ *b: Shift(d) event is ignored.
+ *c: Arrow/Calc(d) event is ignored.
+*/
+uint8_t m0110_recv_key(void)
+{
+ static uint8_t keybuf = 0x00;
+ static uint8_t keybuf2 = 0x00;
+ static uint8_t rawbuf = 0x00;
+ uint8_t raw, raw2, raw3;
+
+ if (keybuf) {
+ raw = keybuf;
+ keybuf = 0x00;
+ return raw;
+ }
+ if (keybuf2) {
+ raw = keybuf2;
+ keybuf2 = 0x00;
+ return raw;
+ }
+
+ if (rawbuf) {
+ raw = rawbuf;
+ rawbuf = 0x00;
+ } else {
+ raw = instant(); // Use INSTANT for better response. Should be INQUIRY ?
+ }
+ switch (KEY(raw)) {
+ case M0110_KEYPAD:
+ raw2 = instant();
+ switch (KEY(raw2)) {
+ case M0110_ARROW_UP:
+ case M0110_ARROW_DOWN:
+ case M0110_ARROW_LEFT:
+ case M0110_ARROW_RIGHT:
+ if (IS_BREAK(raw2)) {
+ // Case B,F,N:
+ keybuf = (raw2scan(raw2) | M0110_CALC_OFFSET); // Calc(u)
+ return (raw2scan(raw2) | M0110_KEYPAD_OFFSET); // Arrow(u)
+ }
+ break;
+ }
+ // Keypad or Arrow
+ return (raw2scan(raw2) | M0110_KEYPAD_OFFSET);
+ break;
+ case M0110_SHIFT:
+ raw2 = instant();
+ switch (KEY(raw2)) {
+ case M0110_SHIFT:
+ // Case: 5-8,C,G,H
+ rawbuf = raw2;
+ return raw2scan(raw); // Shift(d/u)
+ break;
+ case M0110_KEYPAD:
+ // Shift + Arrow, Calc, or etc.
+ raw3 = instant();
+ switch (KEY(raw3)) {
+ case M0110_ARROW_UP:
+ case M0110_ARROW_DOWN:
+ case M0110_ARROW_LEFT:
+ case M0110_ARROW_RIGHT:
+ if (IS_BREAK(raw)) {
+ if (IS_BREAK(raw3)) {
+ // Case 4:
+ print("(4)\n");
+ keybuf2 = raw2scan(raw); // Shift(u)
+ keybuf = (raw2scan(raw3) | M0110_CALC_OFFSET); // Calc(u)
+ return (raw2scan(raw3) | M0110_KEYPAD_OFFSET); // Arrow(u)
+ } else {
+ // Case 3:
+ print("(3)\n");
+ return (raw2scan(raw)); // Shift(u)
+ }
+ } else {
+ if (IS_BREAK(raw3)) {
+ // Case 2:
+ print("(2)\n");
+ keybuf = (raw2scan(raw3) | M0110_CALC_OFFSET); // Calc(u)
+ return (raw2scan(raw3) | M0110_KEYPAD_OFFSET); // Arrow(u)
+ } else {
+ // Case 1:
+ print("(1)\n");
+ return (raw2scan(raw3) | M0110_CALC_OFFSET); // Calc(d)
+ }
+ }
+ break;
+ default:
+ // Shift + Keypad
+ keybuf = (raw2scan(raw3) | M0110_KEYPAD_OFFSET);
+ return raw2scan(raw); // Shift(d/u)
+ break;
+ }
+ break;
+ default:
+ // Shift + Normal keys
+ keybuf = raw2scan(raw2);
+ return raw2scan(raw); // Shift(d/u)
+ break;
+ }
+ break;
+ default:
+ // Normal keys
+ return raw2scan(raw);
+ break;
+ }
+}
+
+
+static inline uint8_t raw2scan(uint8_t raw) {
+ return (raw == M0110_NULL) ? M0110_NULL : (
+ (raw == M0110_ERROR) ? M0110_ERROR : (
+ ((raw&0x80) | ((raw&0x7F)>>1))
+ )
+ );
+}
+
+static inline uint8_t inquiry(void)
+{
+ m0110_send(M0110_INQUIRY);
+ return m0110_recv();
+}
+
+static inline uint8_t instant(void)
+{
+ m0110_send(M0110_INSTANT);
+ uint8_t data = m0110_recv();
+ if (data != M0110_NULL) {
+ debug_hex(data); debug(" ");
+ }
+ return data;
+}
+
+static inline void clock_lo()
+{
+ M0110_CLOCK_PORT &= ~(1<<M0110_CLOCK_BIT);
+ M0110_CLOCK_DDR |= (1<<M0110_CLOCK_BIT);
+}
+static inline void clock_hi()
+{
+ /* input with pull up */
+ M0110_CLOCK_DDR &= ~(1<<M0110_CLOCK_BIT);
+ M0110_CLOCK_PORT |= (1<<M0110_CLOCK_BIT);
+}
+static inline bool clock_in()
+{
+ M0110_CLOCK_DDR &= ~(1<<M0110_CLOCK_BIT);
+ M0110_CLOCK_PORT |= (1<<M0110_CLOCK_BIT);
+ _delay_us(1);
+ return M0110_CLOCK_PIN&(1<<M0110_CLOCK_BIT);
+}
+static inline void data_lo()
+{
+ M0110_DATA_PORT &= ~(1<<M0110_DATA_BIT);
+ M0110_DATA_DDR |= (1<<M0110_DATA_BIT);
+}
+static inline void data_hi()
+{
+ /* input with pull up */
+ M0110_DATA_DDR &= ~(1<<M0110_DATA_BIT);
+ M0110_DATA_PORT |= (1<<M0110_DATA_BIT);
+}
+static inline bool data_in()
+{
+ M0110_DATA_DDR &= ~(1<<M0110_DATA_BIT);
+ M0110_DATA_PORT |= (1<<M0110_DATA_BIT);
+ _delay_us(1);
+ return M0110_DATA_PIN&(1<<M0110_DATA_BIT);
+}
+
+static inline uint16_t wait_clock_lo(uint16_t us)
+{
+ while (clock_in() && us) { asm(""); _delay_us(1); us--; }
+ return us;
+}
+static inline uint16_t wait_clock_hi(uint16_t us)
+{
+ while (!clock_in() && us) { asm(""); _delay_us(1); us--; }
+ return us;
+}
+static inline uint16_t wait_data_lo(uint16_t us)
+{
+ while (data_in() && us) { asm(""); _delay_us(1); us--; }
+ return us;
+}
+static inline uint16_t wait_data_hi(uint16_t us)
+{
+ while (!data_in() && us) { asm(""); _delay_us(1); us--; }
+ return us;
+}
+
+static inline void idle(void)
+{
+ clock_hi();
+ data_hi();
+}
+
+static inline void request(void)
+{
+ clock_hi();
+ data_lo();
+}
+
+
+
+/*
+Primitive M0110 Library for AVR
+==============================
+
+
+Signaling
+---------
+CLOCK is always from KEYBOARD. DATA are sent with MSB first.
+
+1) IDLE: both lines are high.
+ CLOCK ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ DATA ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+2) KEYBOARD->HOST: HOST reads bit on rising edge.
+ CLOCK ~~~~~~~~~~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~~~~~~~~~
+ DATA ~~~~~~~~~~~~X777777X666666X555555X444444X333333X222222X111111X000000X~~~~~~~
+ <--> 160us(clock low)
+ <---> 180us(clock high)
+
+3) HOST->KEYBOARD: HOST asserts bit on falling edge.
+ CLOCK ~~~~~~~~~~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~~~~~~~~~
+ DATA ~~~~~~|_____X777777X666666X555555X444444X333333X222222X111111X000000X~~~~~~~
+ <----> 840us(request to send by host) <---> 80us(hold DATA)
+ <--> 180us(clock low)
+ <---> 220us(clock high)
+
+
+Protocol
+--------
+COMMAND:
+ Inquiry 0x10 get key event with block
+ Instant 0x12 get key event
+ Model 0x14 get model number(M0110 responds with 0x09)
+ bit 7 1 if another device connected(used when keypad exists?)
+ bit4-6 next device model number
+ bit1-3 keyboard model number
+ bit 0 always 1
+ Test 0x16 test(ACK:0x7D/NAK:0x77)
+
+KEY EVENT:
+ bit 7 key state(0:press 1:release)
+ bit 6-1 scan code(see below)
+ bit 0 always 1
+ To get scan code use this: ((bits&(1<<7)) | ((bits&0x7F))>>1).
+
+ Note: On the M0110A, Keypad keys and Arrow keys are preceded by 0x79.
+ Moreover, some Keypad keys(=, /, * and +) are preceded by 0x71 on press and 0xF1 on release.
+
+ARROW KEYS:
+ Arrow keys and Calc keys(+,*,/,= on keypad) share same byte sequence and preceding byte of
+ Calc keys(0x71 and 0xF1) means press and release event of SHIFT. This causes a very confusing situation,
+ it is difficult or impossible to tell Calc key from Arrow key plus SHIFT in some cases.
+
+ Raw key events:
+ press release
+ ---------------- ----------------
+ Left: 0x79, 0x0D 0x79, 0x8D
+ Right: 0x79, 0x05 0x79, 0x85
+ Up: 0x79, 0x1B 0x79, 0x9B
+ Down: 0x79, 0x11 0x79, 0x91
+ Pad+: 0x71, 0x79, 0x0D 0xF1, 0x79, 0x8D
+ Pad*: 0x71, 0x79, 0x05 0xF1, 0x79, 0x85
+ Pad/: 0x71, 0x79, 0x1B 0xF1, 0x79, 0x9B
+ Pad=: 0x71, 0x79, 0x11 0xF1, 0x79, 0x91
+
+
+RAW CODE:
+ M0110A
+ ,---------------------------------------------------------. ,---------------.
+ | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Bcksp| |Clr| =| /| *|
+ |---------------------------------------------------------| |---------------|
+ |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| | | 7| 8| 9| -|
+ |-----------------------------------------------------' | |---------------|
+ |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return| | 4| 5| 6| +|
+ |---------------------------------------------------------| |---------------|
+ |Shift | Z| X| C| V| B| N| M| ,| ,| /|Shft|Up | | 1| 2| 3| |
+ |---------------------------------------------------------' |-----------|Ent|
+ |Optio|Mac | Space | \|Lft|Rgt|Dn | | 0| .| |
+ `---------------------------------------------------------' `---------------'
+ ,---------------------------------------------------------. ,---------------.
+ | 65| 25| 27| 29| 2B| 2F| 2D| 35| 39| 33| 3B| 37| 31| 67| |+0F|*11|*1B|*05|
+ |---------------------------------------------------------| |---------------|
+ | 61| 19| 1B| 1D| 1F| 23| 21| 41| 45| 3F| 47| 43| 3D| | |+33|+37|+39|+1D|
+ |-----------------------------------------------------' | |---------------|
+ | 73| 01| 03| 05| 07| 0B| 09| 4D| 51| 4B| 53| 4F| 49| |+2D|+2F|+31|*0D|
+ |---------------------------------------------------------| |---------------|
+ | 71| 0D| 0F| 11| 13| 17| 5B| 5D| 27| 5F| 59| 71|+1B| |+27|+29|+2B| |
+ |---------------------------------------------------------' |-----------|+19|
+ | 75| 6F| 63 | 55|+0D|+05|+11| | +25|+03| |
+ `---------------------------------------------------------' `---------------'
+ + 0x79, 0xDD / 0xF1, 0xUU
+ * 0x71, 0x79,DD / 0xF1, 0x79, 0xUU
+
+
+MODEL NUMBER:
+ M0110: 0x09 00001001 : model number 4 (100)
+ M0110A: 0x0B 00001011 : model number 5 (101)
+ M0110 & M0120: ???
+
+
+Scan Code
+---------
+ m0110_recv_key() function returns following scan codes instead of M0110 raw codes.
+ Scan codes are 1 byte size and MSB(bit7) is set when key is released.
+
+ scancode = ((raw&0x80) | ((raw&0x7F)>>1))
+
+ M0110 M0120
+ ,---------------------------------------------------------. ,---------------.
+ | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backs| |Clr| -|Lft|Rgt|
+ |---------------------------------------------------------| |---------------|
+ |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| | 7| 8| 9|Up |
+ |---------------------------------------------------------| |---------------|
+ |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return| | 4| 5| 6|Dn |
+ |---------------------------------------------------------| |---------------|
+ |Shift | Z| X| C| V| B| N| M| ,| ,| /| | | 1| 2| 3| |
+ `---------------------------------------------------------' |-----------|Ent|
+ |Opt|Mac | Space |Enter|Opt| | 0| .| |
+ `------------------------------------------------' `---------------'
+ ,---------------------------------------------------------. ,---------------.
+ | 32| 12| 13| 14| 15| 17| 16| 1A| 1C| 19| 1D| 1B| 18| 33| | 47| 4E| 46| 42|
+ |---------------------------------------------------------| |---------------|
+ | 30| 0C| 0D| 0E| 0F| 10| 11| 20| 22| 1F| 23| 21| 1E| 2A| | 59| 5B| 5C| 4D|
+ |---------------------------------------------------------| |---------------|
+ | 39| 00| 01| 02| 03| 05| 04| 26| 28| 25| 29| 27| 24| | 56| 57| 58| 48|
+ |---------------------------------------------------------| |---------------|
+ | 38| 06| 07| 08| 09| 0B| 2D| 2E| 2B| 2F| 2C| 38| | 53| 54| 55| |
+ `---------------------------------------------------------' |-----------| 4C|
+ | 3A| 37| 31 | 34| 3A| | 52| 41| |
+ `------------------------------------------------' `---------------'
+
+ International keyboard(See page 22 of "Technical Info for 128K/512K")
+ ,---------------------------------------------------------.
+ | 32| 12| 13| 14| 15| 17| 16| 1A| 1C| 19| 1D| 1B| 18| 33|
+ |---------------------------------------------------------|
+ | 30| 0C| 0D| 0E| 0F| 10| 11| 20| 22| 1F| 23| 21| 1E| 2A|
+ |------------------------------------------------------ |
+ | 39| 00| 01| 02| 03| 05| 04| 26| 28| 25| 29| 27| 24| |
+ |---------------------------------------------------------|
+ | 38| 06| 07| 08| 09| 0B| 2D| 2E| 2B| 2F| 2C| 0A| 38|
+ `---------------------------------------------------------'
+ | 3A| 37| 34 | 31| 3A|
+ `------------------------------------------------'
+
+ M0110A
+ ,---------------------------------------------------------. ,---------------.
+ | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Bcksp| |Clr| =| /| *|
+ |---------------------------------------------------------| |---------------|
+ |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| | | 7| 8| 9| -|
+ |-----------------------------------------------------' | |---------------|
+ |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return| | 4| 5| 6| +|
+ |---------------------------------------------------------| |---------------|
+ |Shift | Z| X| C| V| B| N| M| ,| ,| /|Shft|Up | | 1| 2| 3| |
+ |---------------------------------------------------------' |-----------|Ent|
+ |Optio|Mac | Space | \|Lft|Rgt|Dn | | 0| .| |
+ `---------------------------------------------------------' `---------------'
+ ,---------------------------------------------------------. ,---------------.
+ | 32| 12| 13| 14| 15| 17| 16| 1A| 1C| 19| 1D| 1B| 18| 33| | 47| 68| 6D| 62|
+ |---------------------------------------------------------| |---------------|
+ | 30| 0C| 0D| 0E| 0F| 10| 11| 20| 22| 1F| 23| 21| 1E| | | 59| 5B| 5C| 4E|
+ |-----------------------------------------------------' | |---------------|
+ | 39| 00| 01| 02| 03| 05| 04| 26| 28| 25| 29| 27| 24| | 56| 57| 58| 66|
+ |---------------------------------------------------------| |---------------|
+ | 38| 06| 07| 08| 09| 0B| 2D| 2E| 2B| 2F| 2C| 38| 4D| | 53| 54| 55| |
+ |---------------------------------------------------------' |-----------| 4C|
+ | 3A| 37| 31 | 2A| 46| 42| 48| | 52| 41| |
+ `---------------------------------------------------------' `---------------'
+
+
+References
+----------
+Technical Info for 128K/512K and Plus
+ ftp://ftp.apple.asimov.net/pub/apple_II/documentation/macintosh/Mac%20Hardware%20Info%20-%20Mac%20128K.pdf
+ ftp://ftp.apple.asimov.net/pub/apple_II/documentation/macintosh/Mac%20Hardware%20Info%20-%20Mac%20Plus.pdf
+Protocol:
+ Page 20 of Tech Info for 128K/512K
+ http://www.mac.linux-m68k.org/devel/plushw.php
+Connector:
+ Page 20 of Tech Info for 128K/512K
+ http://www.kbdbabel.org/conn/kbd_connector_macplus.png
+Signaling:
+ http://www.kbdbabel.org/signaling/kbd_signaling_mac.png
+ http://typematic.blog.shinobi.jp/Entry/14/
+M0110 raw scan codes:
+ Page 22 of Tech Info for 128K/512K
+ Page 07 of Tech Info for Plus
+ http://m0115.web.fc2.com/m0110.jpg
+ http://m0115.web.fc2.com/m0110a.jpg
+*/
diff --git a/tmk_core/protocol/m0110.h b/tmk_core/protocol/m0110.h
new file mode 100644
index 000000000..2b95ed34d
--- /dev/null
+++ b/tmk_core/protocol/m0110.h
@@ -0,0 +1,92 @@
+/*
+Copyright 2011,2012 Jun WAKO <wakojun@gmail.com>
+
+This software is licensed with a Modified BSD License.
+All of this is supposed to be Free Software, Open Source, DFSG-free,
+GPL-compatible, and OK to use in both free and proprietary applications.
+Additions and corrections to this file are welcome.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+* Neither the name of the copyright holders nor the names of
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef M0110_H
+#define M0110_H
+
+
+/* port settings for clock and data line */
+#if !(defined(M0110_CLOCK_PORT) && \
+ defined(M0110_CLOCK_PIN) && \
+ defined(M0110_CLOCK_DDR) && \
+ defined(M0110_CLOCK_BIT))
+# error "M0110 clock port setting is required in config.h"
+#endif
+
+#if !(defined(M0110_DATA_PORT) && \
+ defined(M0110_DATA_PIN) && \
+ defined(M0110_DATA_DDR) && \
+ defined(M0110_DATA_BIT))
+# error "M0110 data port setting is required in config.h"
+#endif
+
+/* Commands */
+#define M0110_INQUIRY 0x10
+#define M0110_INSTANT 0x14
+#define M0110_MODEL 0x16
+#define M0110_TEST 0x36
+
+/* Response(raw byte from M0110) */
+#define M0110_NULL 0x7B
+#define M0110_KEYPAD 0x79
+#define M0110_TEST_ACK 0x7D
+#define M0110_TEST_NAK 0x77
+#define M0110_SHIFT 0x71
+#define M0110_ARROW_UP 0x1B
+#define M0110_ARROW_DOWN 0x11
+#define M0110_ARROW_LEFT 0x0D
+#define M0110_ARROW_RIGHT 0x05
+
+/* This inidcates no response. */
+#define M0110_ERROR 0xFF
+
+/* scan code offset for keypad and arrow keys */
+#define M0110_KEYPAD_OFFSET 0x40
+#define M0110_CALC_OFFSET 0x60
+
+
+extern uint8_t m0110_error;
+
+/* host role */
+void m0110_init(void);
+uint8_t m0110_send(uint8_t data);
+uint8_t m0110_recv(void);
+uint8_t m0110_recv_key(void);
+uint8_t m0110_inquiry(void);
+uint8_t m0110_instant(void);
+
+#endif
diff --git a/tmk_core/protocol/mbed/HIDKeyboard.cpp b/tmk_core/protocol/mbed/HIDKeyboard.cpp
new file mode 100644
index 000000000..947077cd2
--- /dev/null
+++ b/tmk_core/protocol/mbed/HIDKeyboard.cpp
@@ -0,0 +1,271 @@
+#include <stdint.h>
+#include "USBHID.h"
+#include "USBHID_Types.h"
+#include "USBDescriptor.h"
+#include "HIDKeyboard.h"
+
+#define DEFAULT_CONFIGURATION (1)
+
+
+HIDKeyboard::HIDKeyboard(uint16_t vendor_id, uint16_t product_id, uint16_t product_release): USBDevice(vendor_id, product_id, product_release)
+{
+ USBDevice::connect();
+}
+
+bool HIDKeyboard::sendReport(report_keyboard_t report) {
+ USBDevice::write(EP1IN, report.raw, sizeof(report), MAX_PACKET_SIZE_EP1);
+ return true;
+}
+
+uint8_t HIDKeyboard::leds() {
+ return led_state;
+}
+
+bool HIDKeyboard::USBCallback_setConfiguration(uint8_t configuration) {
+ if (configuration != DEFAULT_CONFIGURATION) {
+ return false;
+ }
+
+ // Configure endpoints > 0
+ addEndpoint(EPINT_IN, MAX_PACKET_SIZE_EPINT);
+ //addEndpoint(EPINT_OUT, MAX_PACKET_SIZE_EPINT);
+
+ // We activate the endpoint to be able to recceive data
+ //readStart(EPINT_OUT, MAX_PACKET_SIZE_EPINT);
+ return true;
+}
+
+
+uint8_t * HIDKeyboard::stringImanufacturerDesc() {
+ static uint8_t stringImanufacturerDescriptor[] = {
+ 0x18, /*bLength*/
+ STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
+ 't',0,'m',0,'k',0,'-',0,'k',0,'b',0,'d',0,'.',0,'c',0,'o',0,'m',0 /*bString iManufacturer*/
+ };
+ return stringImanufacturerDescriptor;
+}
+
+uint8_t * HIDKeyboard::stringIproductDesc() {
+ static uint8_t stringIproductDescriptor[] = {
+ 0x0a, /*bLength*/
+ STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
+ 'm',0,'b',0,'e',0,'d',0 /*bString iProduct*/
+ };
+ return stringIproductDescriptor;
+}
+
+uint8_t * HIDKeyboard::stringIserialDesc() {
+ static uint8_t stringIserialDescriptor[] = {
+ 0x04, /*bLength*/
+ STRING_DESCRIPTOR, /*bDescriptorType 0x03*/
+ '0',0 /*bString iSerial*/
+ };
+ return stringIserialDescriptor;
+}
+
+uint8_t * HIDKeyboard::reportDesc() {
+ static uint8_t reportDescriptor[] = {
+ USAGE_PAGE(1), 0x01, // Generic Desktop
+ USAGE(1), 0x06, // Keyboard
+ COLLECTION(1), 0x01, // Application
+
+ USAGE_PAGE(1), 0x07, // Key Codes
+ USAGE_MINIMUM(1), 0xE0,
+ USAGE_MAXIMUM(1), 0xE7,
+ LOGICAL_MINIMUM(1), 0x00,
+ LOGICAL_MAXIMUM(1), 0x01,
+ REPORT_SIZE(1), 0x01,
+ REPORT_COUNT(1), 0x08,
+ INPUT(1), 0x02, // Data, Variable, Absolute
+
+ REPORT_COUNT(1), 0x01,
+ REPORT_SIZE(1), 0x08,
+ INPUT(1), 0x01, // Constant
+
+ REPORT_COUNT(1), 0x05,
+ REPORT_SIZE(1), 0x01,
+ USAGE_PAGE(1), 0x08, // LEDs
+ USAGE_MINIMUM(1), 0x01,
+ USAGE_MAXIMUM(1), 0x05,
+ OUTPUT(1), 0x02, // Data, Variable, Absolute
+
+ REPORT_COUNT(1), 0x01,
+ REPORT_SIZE(1), 0x03,
+ OUTPUT(1), 0x01, // Constant
+
+
+ REPORT_COUNT(1), 0x06,
+ REPORT_SIZE(1), 0x08,
+ LOGICAL_MINIMUM(1), 0x00,
+ LOGICAL_MAXIMUM(1), 0xFF,
+ USAGE_PAGE(1), 0x07, // Key Codes
+ USAGE_MINIMUM(1), 0x00,
+ USAGE_MAXIMUM(1), 0xFF,
+ INPUT(1), 0x00, // Data, Array
+ END_COLLECTION(0),
+ };
+ reportLength = sizeof(reportDescriptor);
+ return reportDescriptor;
+}
+
+uint16_t HIDKeyboard::reportDescLength() {
+ reportDesc();
+ return reportLength;
+}
+
+#define TOTAL_DESCRIPTOR_LENGTH ((1 * CONFIGURATION_DESCRIPTOR_LENGTH) \
+ + (1 * INTERFACE_DESCRIPTOR_LENGTH) \
+ + (1 * HID_DESCRIPTOR_LENGTH) \
+ + (1 * ENDPOINT_DESCRIPTOR_LENGTH))
+uint8_t * HIDKeyboard::configurationDesc() {
+ static uint8_t configurationDescriptor[] = {
+ CONFIGURATION_DESCRIPTOR_LENGTH,// bLength
+ CONFIGURATION_DESCRIPTOR, // bDescriptorType
+ LSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (LSB)
+ MSB(TOTAL_DESCRIPTOR_LENGTH), // wTotalLength (MSB)
+ 0x01, // bNumInterfaces
+ DEFAULT_CONFIGURATION, // bConfigurationValue
+ 0x00, // iConfiguration
+ C_RESERVED | C_REMOTE_WAKEUP, // bmAttributes
+ C_POWER(100), // bMaxPowerHello World from Mbed
+
+ INTERFACE_DESCRIPTOR_LENGTH, // bLength
+ INTERFACE_DESCRIPTOR, // bDescriptorType
+ 0x00, // bInterfaceNumber
+ 0x00, // bAlternateSetting
+ 0x01, // bNumEndpoints
+ HID_CLASS, // bInterfaceClass
+ 1, // bInterfaceSubClass (boot)
+ 1, // bInterfaceProtocol (keyboard)
+ 0x00, // iInterface
+
+ HID_DESCRIPTOR_LENGTH, // bLength
+ HID_DESCRIPTOR, // bDescriptorType
+ LSB(HID_VERSION_1_11), // bcdHID (LSB)
+ MSB(HID_VERSION_1_11), // bcdHID (MSB)
+ 0x00, // bCountryCode
+ 0x01, // bNumDescriptors
+ REPORT_DESCRIPTOR, // bDescriptorType
+ (uint8_t)(LSB(reportDescLength())), // wDescriptorLength (LSB)
+ (uint8_t)(MSB(reportDescLength())), // wDescriptorLength (MSB)
+
+ ENDPOINT_DESCRIPTOR_LENGTH, // bLength
+ ENDPOINT_DESCRIPTOR, // bDescriptorType
+ PHY_TO_DESC(EP1IN), // bEndpointAddress
+ E_INTERRUPT, // bmAttributes
+ LSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (LSB)
+ MSB(MAX_PACKET_SIZE_EPINT), // wMaxPacketSize (MSB)
+ 1, // bInterval (milliseconds)
+ };
+ return configurationDescriptor;
+}
+
+#if 0
+uint8_t * HIDKeyboard::deviceDesc() {
+ static uint8_t deviceDescriptor[] = {
+ DEVICE_DESCRIPTOR_LENGTH, /* bLength */
+ DEVICE_DESCRIPTOR, /* bDescriptorType */
+ LSB(USB_VERSION_2_0), /* bcdUSB (LSB) */
+ MSB(USB_VERSION_2_0), /* bcdUSB (MSB) */
+ 0x00, /* bDeviceClass */
+ 0x00, /* bDeviceSubClass */
+ 0x00, /* bDeviceprotocol */
+ MAX_PACKET_SIZE_EP0, /* bMaxPacketSize0 */
+ (uint8_t)(LSB(0xfeed)), /* idVendor (LSB) */
+ (uint8_t)(MSB(0xfeed)), /* idVendor (MSB) */
+ (uint8_t)(LSB(0x1bed)), /* idProduct (LSB) */
+ (uint8_t)(MSB(0x1bed)), /* idProduct (MSB) */
+ (uint8_t)(LSB(0x0002)), /* bcdDevice (LSB) */
+ (uint8_t)(MSB(0x0002)), /* bcdDevice (MSB) */
+ 0, /* iManufacturer */
+ 0, /* iProduct */
+ 0, /* iSerialNumber */
+ 0x01 /* bNumConfigurations */
+ };
+ return deviceDescriptor;
+}
+#endif
+
+bool HIDKeyboard::USBCallback_request() {
+ bool success = false;
+ CONTROL_TRANSFER * transfer = getTransferPtr();
+ uint8_t *hidDescriptor;
+
+ // Process additional standard requests
+
+ if ((transfer->setup.bmRequestType.Type == STANDARD_TYPE))
+ {
+ switch (transfer->setup.bRequest)
+ {
+ case GET_DESCRIPTOR:
+ switch (DESCRIPTOR_TYPE(transfer->setup.wValue))
+ {
+ case REPORT_DESCRIPTOR:
+ if ((reportDesc() != NULL) \
+ && (reportDescLength() != 0))
+ {
+ transfer->remaining = reportDescLength();
+ transfer->ptr = reportDesc();
+ transfer->direction = DEVICE_TO_HOST;
+ success = true;
+ }
+ break;
+ case HID_DESCRIPTOR:
+ // Find the HID descriptor, after the configuration descriptor
+ hidDescriptor = findDescriptor(HID_DESCRIPTOR);
+ if (hidDescriptor != NULL)
+ {
+ transfer->remaining = HID_DESCRIPTOR_LENGTH;
+ transfer->ptr = hidDescriptor;
+ transfer->direction = DEVICE_TO_HOST;
+ success = true;
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Process class-specific requests
+ if (transfer->setup.bmRequestType.Type == CLASS_TYPE)
+ {
+ switch (transfer->setup.bRequest) {
+ case SET_REPORT:
+ // LED indicator
+ // TODO: check Interface and Report length?
+ // if (transfer->setup.wIndex == INTERFACE_KEYBOAD) { }
+ // if (transfer->setup.wLength == 1)
+
+ transfer->remaining = 1;
+ //transfer->ptr = ?? what ptr should be set when OUT(not used?)
+ transfer->direction = HOST_TO_DEVICE;
+ transfer->notify = true; /* notify with USBCallback_requestCompleted */
+ success = true;
+ default:
+ break;
+ }
+ }
+
+ return success;
+}
+
+void HIDKeyboard::USBCallback_requestCompleted(uint8_t * buf, uint32_t length)
+{
+ if (length > 0) {
+ CONTROL_TRANSFER *transfer = getTransferPtr();
+ if (transfer->setup.bmRequestType.Type == CLASS_TYPE) {
+ switch (transfer->setup.bRequest) {
+ case SET_REPORT:
+ led_state = buf[0];
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
diff --git a/tmk_core/protocol/mbed/HIDKeyboard.h b/tmk_core/protocol/mbed/HIDKeyboard.h
new file mode 100644
index 000000000..c537e5ece
--- /dev/null
+++ b/tmk_core/protocol/mbed/HIDKeyboard.h
@@ -0,0 +1,31 @@
+#ifndef HIDKEYBOARD_H
+
+#include "stdint.h"
+#include "stdbool.h"
+#include "USBHID.h"
+#include "report.h"
+
+
+class HIDKeyboard : public USBDevice {
+public:
+ HIDKeyboard(uint16_t vendor_id = 0xFEED, uint16_t product_id = 0xabed, uint16_t product_release = 0x0001);
+
+ bool sendReport(report_keyboard_t report);
+ uint8_t leds(void);
+protected:
+ uint16_t reportLength;
+ virtual bool USBCallback_setConfiguration(uint8_t configuration);
+ virtual uint8_t * stringImanufacturerDesc();
+ virtual uint8_t * stringIproductDesc();
+ virtual uint8_t * stringIserialDesc();
+ virtual uint16_t reportDescLength();
+ virtual uint8_t * reportDesc();
+ virtual uint8_t * configurationDesc();
+ //virtual uint8_t * deviceDesc();
+ virtual bool USBCallback_request();
+ virtual void USBCallback_requestCompleted(uint8_t * buf, uint32_t length);
+private:
+ uint8_t led_state;
+};
+
+#endif
diff --git a/tmk_core/protocol/mbed/mbed_driver.cpp b/tmk_core/protocol/mbed/mbed_driver.cpp
new file mode 100644
index 000000000..6c7b16e23
--- /dev/null
+++ b/tmk_core/protocol/mbed/mbed_driver.cpp
@@ -0,0 +1,41 @@
+#include "HIDKeyboard.h"
+#include "host.h"
+#include "host_driver.h"
+#include "mbed_driver.h"
+
+HIDKeyboard keyboard;
+
+
+/* Host driver */
+static uint8_t keyboard_leds(void);
+static void send_keyboard(report_keyboard_t *report);
+static void send_mouse(report_mouse_t *report);
+static void send_system(uint16_t data);
+static void send_consumer(uint16_t data);
+
+host_driver_t mbed_driver = {
+ keyboard_leds,
+ send_keyboard,
+ send_mouse,
+ send_system,
+ send_consumer
+};
+
+
+static uint8_t keyboard_leds(void)
+{
+ return keyboard.leds();
+}
+static void send_keyboard(report_keyboard_t *report)
+{
+ keyboard.sendReport(*report);
+}
+static void send_mouse(report_mouse_t *report)
+{
+}
+static void send_system(uint16_t data)
+{
+}
+static void send_consumer(uint16_t data)
+{
+}
diff --git a/tmk_core/protocol/mbed/mbed_driver.h b/tmk_core/protocol/mbed/mbed_driver.h
new file mode 100644
index 000000000..dd1153b43
--- /dev/null
+++ b/tmk_core/protocol/mbed/mbed_driver.h
@@ -0,0 +1,3 @@
+#include "host_driver.h"
+
+extern host_driver_t mbed_driver;
diff --git a/tmk_core/protocol/midi.mk b/tmk_core/protocol/midi.mk
new file mode 100644
index 000000000..c85ae42ff
--- /dev/null
+++ b/tmk_core/protocol/midi.mk
@@ -0,0 +1,9 @@
+MIDI_DIR = protocol/midi
+
+SRC += midi.c \
+ midi_device.c \
+ bytequeue/bytequeue.c \
+ bytequeue/interrupt_setting.c \
+ $(LUFA_SRC_USBCLASS)
+
+VPATH += $(TMK_PATH)/$(MIDI_DIR) \ No newline at end of file
diff --git a/tmk_core/protocol/midi/Config/LUFAConfig.h b/tmk_core/protocol/midi/Config/LUFAConfig.h
new file mode 100755
index 000000000..fa9404498
--- /dev/null
+++ b/tmk_core/protocol/midi/Config/LUFAConfig.h
@@ -0,0 +1,93 @@
+/*
+ LUFA Library
+ Copyright (C) Dean Camera, 2012.
+
+ dean [at] fourwalledcubicle [dot] com
+ www.lufa-lib.org
+*/
+
+/*
+ Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+ Permission to use, copy, modify, distribute, and sell this
+ software and its documentation for any purpose is hereby granted
+ without fee, provided that the above copyright notice appear in
+ all copies and that both that the copyright notice and this
+ permission notice and warranty disclaimer appear in supporting
+ documentation, and that the name of the author not be used in
+ advertising or publicity pertaining to distribution of the
+ software without specific, written prior permission.
+
+ The author disclaim all warranties with regard to this
+ software, including all implied warranties of merchantability
+ and fitness. In no event shall the author be liable for any
+ special, indirect or consequential damages or any damages
+ whatsoever resulting from loss of use, data or profits, whether
+ in an action of contract, negligence or other tortious action,
+ arising out of or in connection with the use or performance of
+ this software.
+*/
+
+/** \file
+ * \brief LUFA Library Configuration Header File
+ *
+ * This header file is used to configure LUFA's compile time options,
+ * as an alternative to the compile time constants supplied through
+ * a makefile.
+ *
+ * For information on what each token does, refer to the LUFA
+ * manual section "Summary of Compile Tokens".
+ */
+
+#ifndef _LUFA_CONFIG_H_
+#define _LUFA_CONFIG_H_
+
+ #if (ARCH == ARCH_AVR8)
+
+ /* Non-USB Related Configuration Tokens: */
+// #define DISABLE_TERMINAL_CODES
+
+ /* USB Class Driver Related Tokens: */
+// #define HID_HOST_BOOT_PROTOCOL_ONLY
+// #define HID_STATETABLE_STACK_DEPTH {Insert Value Here}
+// #define HID_USAGE_STACK_DEPTH {Insert Value Here}
+// #define HID_MAX_COLLECTIONS {Insert Value Here}
+// #define HID_MAX_REPORTITEMS {Insert Value Here}
+// #define HID_MAX_REPORT_IDS {Insert Value Here}
+// #define NO_CLASS_DRIVER_AUTOFLUSH
+
+ /* General USB Driver Related Tokens: */
+// #define ORDERED_EP_CONFIG
+ #define USE_STATIC_OPTIONS (USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)
+ #define USB_DEVICE_ONLY
+// #define USB_HOST_ONLY
+// #define USB_STREAM_TIMEOUT_MS {Insert Value Here}
+// #define NO_LIMITED_CONTROLLER_CONNECT
+// #define NO_SOF_EVENTS
+
+ /* USB Device Mode Driver Related Tokens: */
+// #define USE_RAM_DESCRIPTORS
+ #define USE_FLASH_DESCRIPTORS
+// #define USE_EEPROM_DESCRIPTORS
+// #define NO_INTERNAL_SERIAL
+ #define FIXED_CONTROL_ENDPOINT_SIZE 8
+// #define DEVICE_STATE_AS_GPIOR {Insert Value Here}
+ #define FIXED_NUM_CONFIGURATIONS 1
+// #define CONTROL_ONLY_DEVICE
+// #define INTERRUPT_CONTROL_ENDPOINT
+// #define NO_DEVICE_REMOTE_WAKEUP
+// #define NO_DEVICE_SELF_POWER
+
+ /* USB Host Mode Driver Related Tokens: */
+// #define HOST_STATE_AS_GPIOR {Insert Value Here}
+// #define USB_HOST_TIMEOUT_MS {Insert Value Here}
+// #define HOST_DEVICE_SETTLE_DELAY_MS {Insert Value Here}
+// #define NO_AUTO_VBUS_MANAGEMENT
+// #define INVERTED_VBUS_ENABLE_LINE
+
+ #else
+
+ #error Unsupported architecture for this LUFA configuration file.
+
+ #endif
+#endif
diff --git a/tmk_core/protocol/midi/bytequeue/COPYING b/tmk_core/protocol/midi/bytequeue/COPYING
new file mode 100755
index 000000000..94a9ed024
--- /dev/null
+++ b/tmk_core/protocol/midi/bytequeue/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/tmk_core/protocol/midi/bytequeue/bytequeue.c b/tmk_core/protocol/midi/bytequeue/bytequeue.c
new file mode 100755
index 000000000..e43495632
--- /dev/null
+++ b/tmk_core/protocol/midi/bytequeue/bytequeue.c
@@ -0,0 +1,65 @@
+//this is a single reader [maybe multiple writer?] byte queue
+//Copyright 2008 Alex Norman
+//writen by Alex Norman
+//
+//This file is part of avr-bytequeue.
+//
+//avr-bytequeue is free software: you can redistribute it and/or modify
+//it under the terms of the GNU General Public License as published by
+//the Free Software Foundation, either version 3 of the License, or
+//(at your option) any later version.
+//
+//avr-bytequeue is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//GNU General Public License for more details.
+//
+//You should have received a copy of the GNU General Public License
+//along with avr-bytequeue. If not, see <http://www.gnu.org/licenses/>.
+
+#include "bytequeue.h"
+#include "interrupt_setting.h"
+
+void bytequeue_init(byteQueue_t * queue, uint8_t * dataArray, byteQueueIndex_t arrayLen){
+ queue->length = arrayLen;
+ queue->data = dataArray;
+ queue->start = queue->end = 0;
+}
+
+bool bytequeue_enqueue(byteQueue_t * queue, uint8_t item){
+ interrupt_setting_t setting = store_and_clear_interrupt();
+ //full
+ if(((queue->end + 1) % queue->length) == queue->start){
+ restore_interrupt_setting(setting);
+ return false;
+ } else {
+ queue->data[queue->end] = item;
+ queue->end = (queue->end + 1) % queue->length;
+ restore_interrupt_setting(setting);
+ return true;
+ }
+}
+
+byteQueueIndex_t bytequeue_length(byteQueue_t * queue){
+ byteQueueIndex_t len;
+ interrupt_setting_t setting = store_and_clear_interrupt();
+ if(queue->end >= queue->start)
+ len = queue->end - queue->start;
+ else
+ len = (queue->length - queue->start) + queue->end;
+ restore_interrupt_setting(setting);
+ return len;
+}
+
+//we don't need to avoid interrupts if there is only one reader
+uint8_t bytequeue_get(byteQueue_t * queue, byteQueueIndex_t index){
+ return queue->data[(queue->start + index) % queue->length];
+}
+
+//we just update the start index to remove elements
+void bytequeue_remove(byteQueue_t * queue, byteQueueIndex_t numToRemove){
+ interrupt_setting_t setting = store_and_clear_interrupt();
+ queue->start = (queue->start + numToRemove) % queue->length;
+ restore_interrupt_setting(setting);
+}
+
diff --git a/tmk_core/protocol/midi/bytequeue/bytequeue.h b/tmk_core/protocol/midi/bytequeue/bytequeue.h
new file mode 100755
index 000000000..e4a286134
--- /dev/null
+++ b/tmk_core/protocol/midi/bytequeue/bytequeue.h
@@ -0,0 +1,59 @@
+//this is a single reader [maybe multiple writer?] byte queue
+//Copyright 2008 Alex Norman
+//writen by Alex Norman
+//
+//This file is part of avr-bytequeue.
+//
+//avr-bytequeue is free software: you can redistribute it and/or modify
+//it under the terms of the GNU General Public License as published by
+//the Free Software Foundation, either version 3 of the License, or
+//(at your option) any later version.
+//
+//avr-bytequeue is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//GNU General Public License for more details.
+//
+//You should have received a copy of the GNU General Public License
+//along with avr-bytequeue. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef BYTEQUEUE_H
+#define BYTEQUEUE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+typedef uint8_t byteQueueIndex_t;
+
+typedef struct {
+ byteQueueIndex_t start;
+ byteQueueIndex_t end;
+ byteQueueIndex_t length;
+ uint8_t * data;
+} byteQueue_t;
+
+//you must have a queue, an array of data which the queue will use, and the length of that array
+void bytequeue_init(byteQueue_t * queue, uint8_t * dataArray, byteQueueIndex_t arrayLen);
+
+//add an item to the queue, returns false if the queue is full
+bool bytequeue_enqueue(byteQueue_t * queue, uint8_t item);
+
+//get the length of the queue
+byteQueueIndex_t bytequeue_length(byteQueue_t * queue);
+
+//this grabs data at the index given [starting at queue->start]
+uint8_t bytequeue_get(byteQueue_t * queue, byteQueueIndex_t index);
+
+//update the index in the queue to reflect data that has been dealt with
+void bytequeue_remove(byteQueue_t * queue, byteQueueIndex_t numToRemove);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/tmk_core/protocol/midi/bytequeue/interrupt_setting.c b/tmk_core/protocol/midi/bytequeue/interrupt_setting.c
new file mode 100755
index 000000000..eafef527c
--- /dev/null
+++ b/tmk_core/protocol/midi/bytequeue/interrupt_setting.c
@@ -0,0 +1,36 @@
+//Copyright 20010 Alex Norman
+//writen by Alex Norman
+//
+//This file is part of avr-bytequeue.
+//
+//avr-bytequeue is free software: you can redistribute it and/or modify
+//it under the terms of the GNU General Public License as published by
+//the Free Software Foundation, either version 3 of the License, or
+//(at your option) any later version.
+//
+//avr-bytequeue is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//GNU General Public License for more details.
+//
+//You should have received a copy of the GNU General Public License
+//along with avr-bytequeue. If not, see <http://www.gnu.org/licenses/>.
+
+
+//AVR specific code
+//should be able to port to other systems by simply providing chip specific
+//implementations of the typedef and these functions
+
+#include "interrupt_setting.h"
+#include <avr/interrupt.h>
+
+interrupt_setting_t store_and_clear_interrupt(void) {
+ uint8_t sreg = SREG;
+ cli();
+ return sreg;
+}
+
+void restore_interrupt_setting(interrupt_setting_t setting) {
+ SREG = setting;
+}
+
diff --git a/tmk_core/protocol/midi/bytequeue/interrupt_setting.h b/tmk_core/protocol/midi/bytequeue/interrupt_setting.h
new file mode 100755
index 000000000..053d02c9d
--- /dev/null
+++ b/tmk_core/protocol/midi/bytequeue/interrupt_setting.h
@@ -0,0 +1,39 @@
+//Copyright 20010 Alex Norman
+//writen by Alex Norman
+//
+//This file is part of avr-bytequeue.
+//
+//avr-bytequeue is free software: you can redistribute it and/or modify
+//it under the terms of the GNU General Public License as published by
+//the Free Software Foundation, either version 3 of the License, or
+//(at your option) any later version.
+//
+//avr-bytequeue is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//GNU General Public License for more details.
+//
+//You should have received a copy of the GNU General Public License
+//along with avr-bytequeue. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef INTERRUPT_SETTING_H
+#define INTERRUPT_SETTING_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <inttypes.h>
+
+//AVR specific typedef
+typedef uint8_t interrupt_setting_t;
+
+interrupt_setting_t store_and_clear_interrupt(void);
+void restore_interrupt_setting(interrupt_setting_t setting);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/tmk_core/protocol/midi/midi.c b/tmk_core/protocol/midi/midi.c
new file mode 100755
index 000000000..11a589078
--- /dev/null
+++ b/tmk_core/protocol/midi/midi.c
@@ -0,0 +1,277 @@
+//midi for embedded chips,
+//Copyright 2010 Alex Norman
+//
+//This file is part of avr-midi.
+//
+//avr-midi is free software: you can redistribute it and/or modify
+//it under the terms of the GNU General Public License as published by
+//the Free Software Foundation, either version 3 of the License, or
+//(at your option) any later version.
+//
+//avr-midi is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//GNU General Public License for more details.
+//
+//You should have received a copy of the GNU General Public License
+//along with avr-midi. If not, see <http://www.gnu.org/licenses/>.
+
+#include "midi.h"
+#include <string.h> //for memcpy
+
+#define MIN(x,y) (((x) < (y)) ? (x) : (y))
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+bool midi_is_statusbyte(uint8_t theByte){
+ return (bool)(theByte & MIDI_STATUSMASK);
+}
+
+bool midi_is_realtime(uint8_t theByte){
+ return (theByte >= MIDI_CLOCK);
+}
+
+midi_packet_length_t midi_packet_length(uint8_t status){
+ switch(status & 0xF0){
+ case MIDI_CC:
+ case MIDI_NOTEON:
+ case MIDI_NOTEOFF:
+ case MIDI_AFTERTOUCH:
+ case MIDI_PITCHBEND:
+ return THREE;
+ case MIDI_PROGCHANGE:
+ case MIDI_CHANPRESSURE:
+ case MIDI_SONGSELECT:
+ return TWO;
+ case 0xF0:
+ switch(status) {
+ case MIDI_CLOCK:
+ case MIDI_TICK:
+ case MIDI_START:
+ case MIDI_CONTINUE:
+ case MIDI_STOP:
+ case MIDI_ACTIVESENSE:
+ case MIDI_RESET:
+ case MIDI_TUNEREQUEST:
+ return ONE;
+ case MIDI_SONGPOSITION:
+ return THREE;
+ case MIDI_TC_QUARTERFRAME:
+ case MIDI_SONGSELECT:
+ return TWO;
+ case SYSEX_END:
+ case SYSEX_BEGIN:
+ default:
+ return UNDEFINED;
+ }
+ default:
+ return UNDEFINED;
+ }
+}
+
+void midi_send_cc(MidiDevice * device, uint8_t chan, uint8_t num, uint8_t val){
+ //CC Status: 0xB0 to 0xBF where the low nibble is the MIDI channel.
+ //CC Data: Controller Num, Controller Val
+ device->send_func(device, 3,
+ MIDI_CC | (chan & MIDI_CHANMASK),
+ num & 0x7F,
+ val & 0x7F);
+}
+
+void midi_send_noteon(MidiDevice * device, uint8_t chan, uint8_t num, uint8_t vel){
+ //Note Data: Note Num, Note Velocity
+ device->send_func(device, 3,
+ MIDI_NOTEON | (chan & MIDI_CHANMASK),
+ num & 0x7F,
+ vel & 0x7F);
+}
+
+void midi_send_noteoff(MidiDevice * device, uint8_t chan, uint8_t num, uint8_t vel){
+ //Note Data: Note Num, Note Velocity
+ device->send_func(device, 3,
+ MIDI_NOTEOFF | (chan & MIDI_CHANMASK),
+ num & 0x7F,
+ vel & 0x7F);
+}
+
+void midi_send_aftertouch(MidiDevice * device, uint8_t chan, uint8_t note_num, uint8_t amt){
+ device->send_func(device, 3,
+ MIDI_AFTERTOUCH | (chan & MIDI_CHANMASK),
+ note_num & 0x7F,
+ amt & 0x7F);
+}
+
+//XXX does this work right?
+//amt in range -0x2000, 0x1fff
+//uAmt should be in range..
+//0x0000 to 0x3FFF
+void midi_send_pitchbend(MidiDevice * device, uint8_t chan, int16_t amt){
+ uint16_t uAmt;
+ //check range
+ if(amt > 0x1fff){
+ uAmt = 0x3FFF;
+ } else if(amt < -0x2000){
+ uAmt = 0;
+ } else {
+ uAmt = amt + 0x2000;
+ }
+ device->send_func(device, 3,
+ MIDI_PITCHBEND | (chan & MIDI_CHANMASK),
+ uAmt & 0x7F,
+ (uAmt >> 7) & 0x7F);
+}
+
+void midi_send_programchange(MidiDevice * device, uint8_t chan, uint8_t num){
+ device->send_func(device, 2,
+ MIDI_PROGCHANGE | (chan & MIDI_CHANMASK),
+ num & 0x7F,
+ 0);
+}
+
+void midi_send_channelpressure(MidiDevice * device, uint8_t chan, uint8_t amt){
+ device->send_func(device, 2,
+ MIDI_CHANPRESSURE | (chan & MIDI_CHANMASK),
+ amt & 0x7F,
+ 0);
+}
+
+void midi_send_clock(MidiDevice * device){
+ device->send_func(device, 1, MIDI_CLOCK, 0, 0);
+}
+
+void midi_send_tick(MidiDevice * device){
+ device->send_func(device, 1, MIDI_TICK, 0, 0);
+}
+
+void midi_send_start(MidiDevice * device){
+ device->send_func(device, 1, MIDI_START, 0, 0);
+}
+
+void midi_send_continue(MidiDevice * device){
+ device->send_func(device, 1, MIDI_CONTINUE, 0, 0);
+}
+
+void midi_send_stop(MidiDevice * device){
+ device->send_func(device, 1, MIDI_STOP, 0, 0);
+}
+
+void midi_send_activesense(MidiDevice * device){
+ device->send_func(device, 1, MIDI_ACTIVESENSE, 0, 0);
+}
+
+void midi_send_reset(MidiDevice * device){
+ device->send_func(device, 1, MIDI_RESET, 0, 0);
+}
+
+void midi_send_tcquarterframe(MidiDevice * device, uint8_t time){
+ device->send_func(device, 2,
+ MIDI_TC_QUARTERFRAME,
+ time & 0x7F,
+ 0);
+}
+
+//XXX is this right?
+void midi_send_songposition(MidiDevice * device, uint16_t pos){
+ device->send_func(device, 3,
+ MIDI_SONGPOSITION,
+ pos & 0x7F,
+ (pos >> 7) & 0x7F);
+}
+
+void midi_send_songselect(MidiDevice * device, uint8_t song){
+ device->send_func(device, 2,
+ MIDI_SONGSELECT,
+ song & 0x7F,
+ 0);
+}
+
+void midi_send_tunerequest(MidiDevice * device){
+ device->send_func(device, 1, MIDI_TUNEREQUEST, 0, 0);
+}
+
+void midi_send_byte(MidiDevice * device, uint8_t b){
+ device->send_func(device, 1, b, 0, 0);
+}
+
+void midi_send_data(MidiDevice * device, uint16_t count, uint8_t byte0, uint8_t byte1, uint8_t byte2){
+ //ensure that the count passed along is always 3 or lower
+ if (count > 3) {
+ //TODO how to do this correctly?
+ }
+ device->send_func(device, count, byte0, byte1, byte2);
+}
+
+void midi_send_array(MidiDevice * device, uint16_t count, uint8_t * array) {
+ uint16_t i;
+ for (i = 0; i < count; i += 3) {
+ uint8_t b[3] = { 0, 0, 0 };
+ uint16_t to_send = count - i;
+ to_send = (to_send > 3) ? 3 : to_send;
+ memcpy(b, array + i, to_send);
+ midi_send_data(device, to_send, b[0], b[1], b[2]);
+ }
+}
+
+
+void midi_register_cc_callback(MidiDevice * device, midi_three_byte_func_t func){
+ device->input_cc_callback = func;
+}
+
+void midi_register_noteon_callback(MidiDevice * device, midi_three_byte_func_t func){
+ device->input_noteon_callback = func;
+}
+
+void midi_register_noteoff_callback(MidiDevice * device, midi_three_byte_func_t func){
+ device->input_noteoff_callback = func;
+}
+
+void midi_register_aftertouch_callback(MidiDevice * device, midi_three_byte_func_t func){
+ device->input_aftertouch_callback = func;
+}
+
+void midi_register_pitchbend_callback(MidiDevice * device, midi_three_byte_func_t func){
+ device->input_pitchbend_callback = func;
+}
+
+void midi_register_songposition_callback(MidiDevice * device, midi_three_byte_func_t func){
+ device->input_songposition_callback = func;
+}
+
+void midi_register_progchange_callback(MidiDevice * device, midi_two_byte_func_t func) {
+ device->input_progchange_callback = func;
+}
+
+void midi_register_chanpressure_callback(MidiDevice * device, midi_two_byte_func_t func) {
+ device->input_chanpressure_callback = func;
+}
+
+void midi_register_songselect_callback(MidiDevice * device, midi_two_byte_func_t func) {
+ device->input_songselect_callback = func;
+}
+
+void midi_register_tc_quarterframe_callback(MidiDevice * device, midi_two_byte_func_t func) {
+ device->input_tc_quarterframe_callback = func;
+}
+
+void midi_register_realtime_callback(MidiDevice * device, midi_one_byte_func_t func){
+ device->input_realtime_callback = func;
+}
+
+void midi_register_tunerequest_callback(MidiDevice * device, midi_one_byte_func_t func){
+ device->input_tunerequest_callback = func;
+}
+
+void midi_register_sysex_callback(MidiDevice * device, midi_sysex_func_t func) {
+ device->input_sysex_callback = func;
+}
+
+void midi_register_fallthrough_callback(MidiDevice * device, midi_var_byte_func_t func){
+ device->input_fallthrough_callback = func;
+}
+
+void midi_register_catchall_callback(MidiDevice * device, midi_var_byte_func_t func){
+ device->input_catchall_callback = func;
+}
+
diff --git a/tmk_core/protocol/midi/midi.h b/tmk_core/protocol/midi/midi.h
new file mode 100755
index 000000000..1a36737df
--- /dev/null
+++ b/tmk_core/protocol/midi/midi.h
@@ -0,0 +1,498 @@
+//midi for embedded chips,
+//Copyright 2010 Alex Norman
+//
+//This file is part of avr-midi.
+//
+//avr-midi is free software: you can redistribute it and/or modify
+//it under the terms of the GNU General Public License as published by
+//the Free Software Foundation, either version 3 of the License, or
+//(at your option) any later version.
+//
+//avr-midi is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//GNU General Public License for more details.
+//
+//You should have received a copy of the GNU General Public License
+//along with avr-midi. If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * @file
+ * @brief The main midi functions
+ *
+ * This file includes all of the functions you need to set up and process a
+ * midi device, send midi, and register midi callbacks.
+ *
+ */
+
+#ifndef XNOR_MIDI_H
+#define XNOR_MIDI_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "midi_device.h"
+#include "midi_function_types.h"
+
+/**
+ * @defgroup midi_device_setup_process Device initialization and processing
+ * @brief These are method that you must use to initialize and run a device
+ *
+ * @{
+ */
+
+/**
+ * @brief Initialize a device
+ *
+ * You must call this before using the device in question.
+ *
+ * @param device the device to initialize
+*/
+void midi_device_init(MidiDevice * device); // [implementation in midi_device.c]
+
+/**
+ * @brief Process input data
+ *
+ * This method drives the input processing, you must call this method frequently
+ * if you expect to have your input callbacks called.
+ *
+ * @param device the device to process
+*/
+void midi_device_process(MidiDevice * device); // [implementation in midi_device.c]
+
+/**@}*/
+
+/**
+ * @defgroup send_functions Midi send functions
+ * @brief These are the functions you use to send midi data through a device.
+ * @{
+ */
+
+/**
+ * @brief Send a control change message (cc) via the given device.
+ *
+ * @param device the device to use for sending
+ * @param chan the channel to send on, 0-15
+ * @param num the cc num
+ * @param val the value of that cc num
+*/
+void midi_send_cc(MidiDevice * device, uint8_t chan, uint8_t num, uint8_t val);
+
+/**
+ * @brief Send a note on message via the given device.
+ *
+ * @param device the device to use for sending
+ * @param chan the channel to send on, 0-15
+ * @param num the note number
+ * @param vel the note velocity
+*/
+void midi_send_noteon(MidiDevice * device, uint8_t chan, uint8_t num, uint8_t vel);
+
+/**
+ * @brief Send a note off message via the given device.
+ *
+ * @param device the device to use for sending
+ * @param chan the channel to send on, 0-15
+ * @param num the note number
+ * @param vel the note velocity
+*/
+void midi_send_noteoff(MidiDevice * device, uint8_t chan, uint8_t num, uint8_t vel);
+
+/**
+ * @brief Send an after touch message via the given device.
+ *
+ * @param device the device to use for sending
+ * @param chan the channel to send on, 0-15
+ * @param note_num the note number
+ * @param amt the after touch amount
+*/
+void midi_send_aftertouch(MidiDevice * device, uint8_t chan, uint8_t note_num, uint8_t amt);
+
+/**
+ * @brief Send a pitch bend message via the given device.
+ *
+ * @param device the device to use for sending
+ * @param chan the channel to send on, 0-15
+ * @param amt the bend amount range: -8192..8191, 0 means no bend
+*/
+void midi_send_pitchbend(MidiDevice * device, uint8_t chan, int16_t amt); //range -8192, 8191
+
+/**
+ * @brief Send a program change message via the given device.
+ *
+ * @param device the device to use for sending
+ * @param chan the channel to send on, 0-15
+ * @param num the program to change to
+*/
+void midi_send_programchange(MidiDevice * device, uint8_t chan, uint8_t num);
+
+/**
+ * @brief Send a channel pressure message via the given device.
+ *
+ * @param device the device to use for sending
+ * @param chan the channel to send on, 0-15
+ * @param amt the amount of channel pressure
+*/
+void midi_send_channelpressure(MidiDevice * device, uint8_t chan, uint8_t amt);
+
+/**
+ * @brief Send a clock message via the given device.
+ *
+ * @param device the device to use for sending
+ */
+void midi_send_clock(MidiDevice * device);
+
+/**
+ * @brief Send a tick message via the given device.
+ *
+ * @param device the device to use for sending
+ */
+void midi_send_tick(MidiDevice * device);
+
+/**
+ * @brief Send a start message via the given device.
+ *
+ * @param device the device to use for sending
+ */
+void midi_send_start(MidiDevice * device);
+
+/**
+ * @brief Send a continue message via the given device.
+ *
+ * @param device the device to use for sending
+ */
+void midi_send_continue(MidiDevice * device);
+
+/**
+ * @brief Send a stop message via the given device.
+ *
+ * @param device the device to use for sending
+ */
+void midi_send_stop(MidiDevice * device);
+
+/**
+ * @brief Send an active sense message via the given device.
+ *
+ * @param device the device to use for sending
+ */
+void midi_send_activesense(MidiDevice * device);
+
+/**
+ * @brief Send a reset message via the given device.
+ *
+ * @param device the device to use for sending
+ */
+void midi_send_reset(MidiDevice * device);
+
+
+/**
+ * @brief Send a tc quarter frame message via the given device.
+ *
+ * @param device the device to use for sending
+ * @param time the time of this quarter frame, range 0..16383
+ */
+void midi_send_tcquarterframe(MidiDevice * device, uint8_t time);
+
+/**
+ * @brief Send a song position message via the given device.
+ *
+ * @param device the device to use for sending
+ * @param pos the song position
+ */
+void midi_send_songposition(MidiDevice * device, uint16_t pos);
+
+/**
+ * @brief Send a song select message via the given device.
+ *
+ * @param device the device to use for sending
+ * @param song the song to select
+ */
+void midi_send_songselect(MidiDevice * device, uint8_t song);
+
+/**
+ * @brief Send a tune request message via the given device.
+ *
+ * @param device the device to use for sending
+ */
+void midi_send_tunerequest(MidiDevice * device);
+
+/**
+ * @brief Send a byte via the given device.
+ *
+ * This is a generic method for sending data via the given midi device.
+ * This would be useful for sending sysex data or messages that are not
+ * implemented in this API, if there are any. Please contact the author
+ * if you find some so we can add them.
+ *
+ * @param device the device to use for sending
+ * @param b the byte to send
+ */
+void midi_send_byte(MidiDevice * device, uint8_t b);
+
+/**
+ * @brief Send up to 3 bytes of data
+ *
+ * % 4 is applied to count so that you can use this to pass sysex through
+ *
+ * @param device the device to use for sending
+ * @param count the count of bytes to send, %4 is applied
+ * @param byte0 the first byte
+ * @param byte1 the second byte, ignored if cnt % 4 != 2
+ * @param byte2 the third byte, ignored if cnt % 4 != 3
+ */
+void midi_send_data(MidiDevice * device, uint16_t count, uint8_t byte0, uint8_t byte1, uint8_t byte2);
+
+/**
+ * @brief Send an array of formatted midi data.
+ *
+ * Can be used for sysex.
+ *
+ * @param device the device to use for sending
+ * @param count the count of bytes to send
+ * @param array the array of bytes
+ */
+void midi_send_array(MidiDevice * device, uint16_t count, uint8_t * array);
+
+/**@}*/
+
+
+/**
+ * @defgroup input_callback_reg Input callback registration functions
+ *
+ * @brief These are the functions you use to register your input callbacks.
+ *
+ * The functions are called when the appropriate midi message is matched on the
+ * associated device's input.
+ *
+ * @{
+ */
+
+//three byte funcs
+
+/**
+ * @brief Register a control change message (cc) callback.
+ *
+ * @param device the device associate with
+ * @param func the callback function to register
+ */
+void midi_register_cc_callback(MidiDevice * device, midi_three_byte_func_t func);
+
+/**
+ * @brief Register a note on callback.
+ *
+ * @param device the device associate with
+ * @param func the callback function to register
+ */
+void midi_register_noteon_callback(MidiDevice * device, midi_three_byte_func_t func);
+
+/**
+ * @brief Register a note off callback.
+ *
+ * @param device the device associate with
+ * @param func the callback function to register
+ */
+void midi_register_noteoff_callback(MidiDevice * device, midi_three_byte_func_t func);
+
+/**
+ * @brief Register an after touch callback.
+ *
+ * @param device the device associate with
+ * @param func the callback function to register
+ */
+
+void midi_register_aftertouch_callback(MidiDevice * device, midi_three_byte_func_t func);
+
+/**
+ * @brief Register a pitch bend callback.
+ *
+ * @param device the device associate with
+ * @param func the callback function to register
+ */
+void midi_register_pitchbend_callback(MidiDevice * device, midi_three_byte_func_t func);
+
+/**
+ * @brief Register a song position callback.
+ *
+ * @param device the device associate with
+ * @param func the callback function to register
+ */
+void midi_register_songposition_callback(MidiDevice * device, midi_three_byte_func_t func);
+
+//two byte funcs
+
+/**
+ * @brief Register a program change callback.
+ *
+ * @param device the device associate with
+ * @param func the callback function to register
+ */
+void midi_register_progchange_callback(MidiDevice * device, midi_two_byte_func_t func);
+
+/**
+ * @brief Register a channel pressure callback.
+ *
+ * @param device the device associate with
+ * @param func the callback function to register
+ */
+void midi_register_chanpressure_callback(MidiDevice * device, midi_two_byte_func_t func);
+
+/**
+ * @brief Register a song select callback.
+ *
+ * @param device the device associate with
+ * @param func the callback function to register
+ */
+void midi_register_songselect_callback(MidiDevice * device, midi_two_byte_func_t func);
+
+/**
+ * @brief Register a tc quarter frame callback.
+ *
+ * @param device the device associate with
+ * @param func the callback function to register
+ */
+void midi_register_tc_quarterframe_callback(MidiDevice * device, midi_two_byte_func_t func);
+
+//one byte funcs
+
+/**
+ * @brief Register a realtime callback.
+ *
+ * The callback will be called for all of the real time message types.
+ *
+ * @param device the device associate with
+ * @param func the callback function to register
+ */
+void midi_register_realtime_callback(MidiDevice * device, midi_one_byte_func_t func);
+
+/**
+ * @brief Register a tune request callback.
+ *
+ * @param device the device associate with
+ * @param func the callback function to register
+ */
+void midi_register_tunerequest_callback(MidiDevice * device, midi_one_byte_func_t func);
+
+/**
+ * @brief Register a sysex callback.
+ *
+ * @param device the device associate with
+ * @param func the callback function to register
+ */
+void midi_register_sysex_callback(MidiDevice * device, midi_sysex_func_t func);
+
+/**
+ * @brief Register fall through callback.
+ *
+ * This is only called if a more specific callback is not matched and called.
+ * For instance, if you don't register a note on callback but you get a note on message
+ * the fall through callback will be called, if it is registered.
+ *
+ * @param device the device associate with
+ * @param func the callback function to register
+ */
+void midi_register_fallthrough_callback(MidiDevice * device, midi_var_byte_func_t func);
+
+
+/**
+ * @brief Register a catch all callback.
+ *
+ * If registered, the catch all callback is called for every message that is
+ * matched, even if a more specific or the fallthrough callback is registered.
+ *
+ * @param device the device associate with
+ * @param func the callback function to register
+ */
+void midi_register_catchall_callback(MidiDevice * device, midi_var_byte_func_t func);
+
+/**@}*/
+
+/**
+ * @defgroup midi_util Device independent utility functions.
+ * @{
+ */
+
+/**
+ * \enum midi_packet_length_t
+ *
+ * An enumeration of the possible packet length values.
+ */
+typedef enum {
+ UNDEFINED = 0,
+ ONE = 1,
+ TWO = 2,
+ THREE = 3} midi_packet_length_t;
+
+/**
+ * @brief Test to see if the byte given is a status byte
+ * @param theByte the byte to test
+ * @return true if the byte given is a midi status byte
+ */
+bool midi_is_statusbyte(uint8_t theByte);
+
+/**
+ * @brief Test to see if the byte given is a realtime message
+ * @param theByte the byte to test
+ * @return true if it is a realtime message, false otherwise
+ */
+bool midi_is_realtime(uint8_t theByte);
+
+/**
+ * @brief Find the length of the packet associated with the status byte given
+ * @param status the status byte
+ * @return the length of the packet, will return UNDEFINED if the byte is not
+ * a status byte or if it is a sysex status byte
+ */
+midi_packet_length_t midi_packet_length(uint8_t status);
+
+/**@}*/
+
+/**
+ * @defgroup defines Midi status and miscellaneous utility #defines
+ *
+ * @{
+ */
+
+#define SYSEX_BEGIN 0xF0
+#define SYSEX_END 0xF7
+
+//if you and this with a byte and you get anything non-zero
+//it is a status message
+#define MIDI_STATUSMASK 0x80
+//if you and this with a status message that contains channel info,
+//you'll get the channel
+#define MIDI_CHANMASK 0x0F
+
+#define MIDI_CC 0xB0
+#define MIDI_NOTEON 0x90
+#define MIDI_NOTEOFF 0x80
+#define MIDI_AFTERTOUCH 0xA0
+#define MIDI_PITCHBEND 0xE0
+#define MIDI_PROGCHANGE 0xC0
+#define MIDI_CHANPRESSURE 0xD0
+
+//midi realtime
+#define MIDI_CLOCK 0xF8
+#define MIDI_TICK 0xF9
+#define MIDI_START 0xFA
+#define MIDI_CONTINUE 0xFB
+#define MIDI_STOP 0xFC
+#define MIDI_ACTIVESENSE 0xFE
+#define MIDI_RESET 0xFF
+
+#define MIDI_TC_QUARTERFRAME 0xF1
+#define MIDI_SONGPOSITION 0xF2
+#define MIDI_SONGSELECT 0xF3
+#define MIDI_TUNEREQUEST 0xF6
+
+//This ID is for educational or development use only
+#define SYSEX_EDUMANUFID 0x7D
+
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/tmk_core/protocol/midi/midi_device.c b/tmk_core/protocol/midi/midi_device.c
new file mode 100755
index 000000000..3215a007d
--- /dev/null
+++ b/tmk_core/protocol/midi/midi_device.c
@@ -0,0 +1,291 @@
+//midi for embedded chips,
+//Copyright 2010 Alex Norman
+//
+//This file is part of avr-midi.
+//
+//avr-midi is free software: you can redistribute it and/or modify
+//it under the terms of the GNU General Public License as published by
+//the Free Software Foundation, either version 3 of the License, or
+//(at your option) any later version.
+//
+//avr-midi is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//GNU General Public License for more details.
+//
+//You should have received a copy of the GNU General Public License
+//along with avr-midi. If not, see <http://www.gnu.org/licenses/>.
+
+#include "midi_device.h"
+#include "midi.h"
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+//forward declarations, internally used to call the callbacks
+void midi_input_callbacks(MidiDevice * device, uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2);
+void midi_process_byte(MidiDevice * device, uint8_t input);
+
+void midi_device_init(MidiDevice * device){
+ device->input_state = IDLE;
+ device->input_count = 0;
+ bytequeue_init(&device->input_queue, device->input_queue_data, MIDI_INPUT_QUEUE_LENGTH);
+
+ //three byte funcs
+ device->input_cc_callback = NULL;
+ device->input_noteon_callback = NULL;
+ device->input_noteoff_callback = NULL;
+ device->input_aftertouch_callback = NULL;
+ device->input_pitchbend_callback = NULL;
+ device->input_songposition_callback = NULL;
+
+ //two byte funcs
+ device->input_progchange_callback = NULL;
+ device->input_chanpressure_callback = NULL;
+ device->input_songselect_callback = NULL;
+ device->input_tc_quarterframe_callback = NULL;
+
+ //one byte funcs
+ device->input_realtime_callback = NULL;
+ device->input_tunerequest_callback = NULL;
+
+ //var byte functions
+ device->input_sysex_callback = NULL;
+ device->input_fallthrough_callback = NULL;
+ device->input_catchall_callback = NULL;
+
+ device->pre_input_process_callback = NULL;
+}
+
+void midi_device_input(MidiDevice * device, uint8_t cnt, uint8_t * input) {
+ uint8_t i;
+ for (i = 0; i < cnt; i++)
+ bytequeue_enqueue(&device->input_queue, input[i]);
+}
+
+void midi_device_set_send_func(MidiDevice * device, midi_var_byte_func_t send_func){
+ device->send_func = send_func;
+}
+
+void midi_device_set_pre_input_process_func(MidiDevice * device, midi_no_byte_func_t pre_process_func){
+ device->pre_input_process_callback = pre_process_func;
+}
+
+void midi_device_process(MidiDevice * device) {
+ //call the pre_input_process_callback if there is one
+ if(device->pre_input_process_callback)
+ device->pre_input_process_callback(device);
+
+ //pull stuff off the queue and process
+ byteQueueIndex_t len = bytequeue_length(&device->input_queue);
+ uint16_t i;
+ //TODO limit number of bytes processed?
+ for(i = 0; i < len; i++) {
+ uint8_t val = bytequeue_get(&device->input_queue, 0);
+ midi_process_byte(device, val);
+ bytequeue_remove(&device->input_queue, 1);
+ }
+}
+
+void midi_process_byte(MidiDevice * device, uint8_t input) {
+ if (midi_is_realtime(input)) {
+ //call callback, store and restore state
+ input_state_t state = device->input_state;
+ device->input_state = ONE_BYTE_MESSAGE;
+ midi_input_callbacks(device, 1, input, 0, 0);
+ device->input_state = state;
+ } else if (midi_is_statusbyte(input)) {
+ //store the byte
+ if (device->input_state != SYSEX_MESSAGE) {
+ device->input_buffer[0] = input;
+ device->input_count = 1;
+ }
+ switch (midi_packet_length(input)) {
+ case ONE:
+ device->input_state = ONE_BYTE_MESSAGE;;
+ midi_input_callbacks(device, 1, input, 0, 0);
+ device->input_state = IDLE;
+ break;
+ case TWO:
+ device->input_state = TWO_BYTE_MESSAGE;
+ break;
+ case THREE:
+ device->input_state = THREE_BYTE_MESSAGE;
+ break;
+ case UNDEFINED:
+ switch(input) {
+ case SYSEX_BEGIN:
+ device->input_state = SYSEX_MESSAGE;
+ device->input_buffer[0] = input;
+ device->input_count = 1;
+ break;
+ case SYSEX_END:
+ //send what is left in the input buffer, set idle
+ device->input_buffer[device->input_count % 3] = input;
+ device->input_count += 1;
+ //call the callback
+ midi_input_callbacks(device, device->input_count,
+ device->input_buffer[0], device->input_buffer[1], device->input_buffer[2]);
+ device->input_state = IDLE;
+ break;
+ default:
+ device->input_state = IDLE;
+ device->input_count = 0;
+ }
+
+ break;
+ default:
+ device->input_state = IDLE;
+ device->input_count = 0;
+ break;
+ }
+ } else {
+ if (device->input_state != IDLE) {
+ //store the byte
+ device->input_buffer[device->input_count % 3] = input;
+ //increment count
+ uint16_t prev = device->input_count;
+ device->input_count += 1;
+
+ switch(prev % 3) {
+ case 2:
+ //call callback
+ midi_input_callbacks(device, device->input_count,
+ device->input_buffer[0], device->input_buffer[1], device->input_buffer[2]);
+ if (device->input_state != SYSEX_MESSAGE) {
+ //set to 1, keeping status byte, allowing for running status
+ device->input_count = 1;
+ }
+ break;
+ case 1:
+ if (device->input_state == TWO_BYTE_MESSAGE) {
+ //call callback
+ midi_input_callbacks(device, device->input_count,
+ device->input_buffer[0], device->input_buffer[1], 0);
+ if (device->input_state != SYSEX_MESSAGE) {
+ //set to 1, keeping status byte, allowing for running status
+ device->input_count = 1;
+ }
+ }
+ break;
+ case 0:
+ default:
+ //one byte messages are dealt with directly
+ break;
+ }
+ }
+ }
+}
+
+void midi_input_callbacks(MidiDevice * device, uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2) {
+ //did we end up calling a callback?
+ bool called = false;
+ if (device->input_state == SYSEX_MESSAGE) {
+ if (device->input_sysex_callback) {
+ const uint16_t start = ((cnt - 1) / 3) * 3;
+ const uint8_t length = (cnt - start);
+ uint8_t data[3];
+ data[0] = byte0;
+ data[1] = byte1;
+ data[2] = byte2;
+ device->input_sysex_callback(device, start, length, data);
+ called = true;
+ }
+ } else {
+ switch (cnt) {
+ case 3:
+ {
+ midi_three_byte_func_t func = NULL;
+ switch (byte0 & 0xF0) {
+ case MIDI_CC:
+ func = device->input_cc_callback;
+ break;
+ case MIDI_NOTEON:
+ func = device->input_noteon_callback;
+ break;
+ case MIDI_NOTEOFF:
+ func = device->input_noteoff_callback;
+ break;
+ case MIDI_AFTERTOUCH:
+ func = device->input_aftertouch_callback;
+ break;
+ case MIDI_PITCHBEND:
+ func = device->input_pitchbend_callback;
+ break;
+ case 0xF0:
+ if (byte0 == MIDI_SONGPOSITION)
+ func = device->input_songposition_callback;
+ break;
+ default:
+ break;
+ }
+ if(func) {
+ //mask off the channel for non song position functions
+ if (byte0 == MIDI_SONGPOSITION)
+ func(device, byte0, byte1, byte2);
+ else
+ func(device, byte0 & 0x0F, byte1, byte2);
+ called = true;
+ }
+ }
+ break;
+ case 2:
+ {
+ midi_two_byte_func_t func = NULL;
+ switch (byte0 & 0xF0) {
+ case MIDI_PROGCHANGE:
+ func = device->input_progchange_callback;
+ break;
+ case MIDI_CHANPRESSURE:
+ func = device->input_chanpressure_callback;
+ break;
+ case 0xF0:
+ if (byte0 == MIDI_SONGSELECT)
+ func = device->input_songselect_callback;
+ else if (byte0 == MIDI_TC_QUARTERFRAME)
+ func = device->input_tc_quarterframe_callback;
+ break;
+ default:
+ break;
+ }
+ if(func) {
+ //mask off the channel
+ if (byte0 == MIDI_SONGSELECT || byte0 == MIDI_TC_QUARTERFRAME)
+ func(device, byte0, byte1);
+ else
+ func(device, byte0 & 0x0F, byte1);
+ called = true;
+ }
+ }
+ break;
+ case 1:
+ {
+ midi_one_byte_func_t func = NULL;
+ if (midi_is_realtime(byte0))
+ func = device->input_realtime_callback;
+ else if (byte0 == MIDI_TUNEREQUEST)
+ func = device->input_tunerequest_callback;
+ if (func) {
+ func(device, byte0);
+ called = true;
+ }
+ }
+ break;
+ default:
+ //just in case
+ if (cnt > 3)
+ cnt = 0;
+ break;
+ }
+ }
+
+ //if there is fallthrough default callback and we haven't called a more specific one,
+ //call the fallthrough
+ if (!called && device->input_fallthrough_callback)
+ device->input_fallthrough_callback(device, cnt, byte0, byte1, byte2);
+ //always call the catch all if it exists
+ if (device->input_catchall_callback)
+ device->input_catchall_callback(device, cnt, byte0, byte1, byte2);
+}
+
diff --git a/tmk_core/protocol/midi/midi_device.h b/tmk_core/protocol/midi/midi_device.h
new file mode 100755
index 000000000..088995286
--- /dev/null
+++ b/tmk_core/protocol/midi/midi_device.h
@@ -0,0 +1,156 @@
+//midi for embedded chips,
+//Copyright 2010 Alex Norman
+//
+//This file is part of avr-midi.
+//
+//avr-midi is free software: you can redistribute it and/or modify
+//it under the terms of the GNU General Public License as published by
+//the Free Software Foundation, either version 3 of the License, or
+//(at your option) any later version.
+//
+//avr-midi is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//GNU General Public License for more details.
+//
+//You should have received a copy of the GNU General Public License
+//along with avr-midi. If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * @file
+ * @brief Device implementation functions
+ */
+
+#ifndef MIDI_DEVICE_H
+#define MIDI_DEVICE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup midi_device Functions used when implementing your own midi device.
+ *
+ * You use the functions when you are implementing your own midi device.
+ *
+ * You set a send function to actually send bytes via your device, this method
+ * is called when you call a send function with this device, for instance
+ * midi_send_cc
+ *
+ * You use the midi_device_input to process input data from the device and pass
+ * it through the device's associated callbacks.
+ *
+ * You use the midi_device_set_pre_input_process_func if you want to have a
+ * function called at the beginning of the device's process function, generally
+ * to poll for input and pass that into midi_device_input
+ *
+ * @{
+ */
+
+#include "midi_function_types.h"
+#include "bytequeue/bytequeue.h"
+#define MIDI_INPUT_QUEUE_LENGTH 192
+
+typedef enum {
+ IDLE,
+ ONE_BYTE_MESSAGE = 1,
+ TWO_BYTE_MESSAGE = 2,
+ THREE_BYTE_MESSAGE = 3,
+ SYSEX_MESSAGE} input_state_t;
+
+typedef void (* midi_no_byte_func_t)(MidiDevice * device);
+
+/**
+ * \struct _midi_device
+ *
+ * @brief This structure represents the input and output functions and
+ * processing data for a midi device.
+ *
+ * A device can represent an actual physical device [serial port, usb port] or
+ * something virtual.
+ * You should not need to modify this structure directly.
+ */
+struct _midi_device {
+ //output send function
+ midi_var_byte_func_t send_func;
+
+ //********input callbacks
+ //three byte funcs
+ midi_three_byte_func_t input_cc_callback;
+ midi_three_byte_func_t input_noteon_callback;
+ midi_three_byte_func_t input_noteoff_callback;
+ midi_three_byte_func_t input_aftertouch_callback;
+ midi_three_byte_func_t input_pitchbend_callback;
+ midi_three_byte_func_t input_songposition_callback;
+ //two byte funcs
+ midi_two_byte_func_t input_progchange_callback;
+ midi_two_byte_func_t input_chanpressure_callback;
+ midi_two_byte_func_t input_songselect_callback;
+ midi_two_byte_func_t input_tc_quarterframe_callback;
+ //one byte funcs
+ midi_one_byte_func_t input_realtime_callback;
+ midi_one_byte_func_t input_tunerequest_callback;
+
+ //sysex
+ midi_sysex_func_t input_sysex_callback;
+
+ //only called if more specific callback is not matched
+ midi_var_byte_func_t input_fallthrough_callback;
+ //called if registered, independent of other callbacks
+ midi_var_byte_func_t input_catchall_callback;
+
+ //pre input processing function
+ midi_no_byte_func_t pre_input_process_callback;
+
+ //for internal input processing
+ uint8_t input_buffer[3];
+ input_state_t input_state;
+ uint16_t input_count;
+
+ //for queueing data between the input and the processing functions
+ uint8_t input_queue_data[MIDI_INPUT_QUEUE_LENGTH];
+ byteQueue_t input_queue;
+};
+
+/**
+ * @brief Process input bytes. This function parses bytes and calls the
+ * appropriate callbacks associated with the given device. You use this
+ * function if you are creating a custom device and you want to have midi
+ * input.
+ *
+ * @param device the midi device to associate the input with
+ * @param cnt the number of bytes you are processing
+ * @param input the bytes to process
+ */
+void midi_device_input(MidiDevice * device, uint8_t cnt, uint8_t * input);
+
+/**
+ * @brief Set the callback function that will be used for sending output
+ * data bytes. This is only used if you're creating a custom device.
+ * You'll most likely want the callback function to disable interrupts so
+ * that you can call the various midi send functions without worrying about
+ * locking.
+ *
+ * \param device the midi device to associate this callback with
+ * \param send_func the callback function that will do the sending
+ */
+void midi_device_set_send_func(MidiDevice * device, midi_var_byte_func_t send_func);
+
+/**
+ * @brief Set a callback which is called at the beginning of the
+ * midi_device_process call. This can be used to poll for input
+ * data and send the data through the midi_device_input function.
+ * You'll probably only use this if you're creating a custom device.
+ *
+ * \param device the midi device to associate this callback with
+ * \param midi_no_byte_func_t the actual callback function
+ */
+void midi_device_set_pre_input_process_func(MidiDevice * device, midi_no_byte_func_t pre_process_func);
+
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/tmk_core/protocol/midi/midi_function_types.h b/tmk_core/protocol/midi/midi_function_types.h
new file mode 100755
index 000000000..35c4601b2
--- /dev/null
+++ b/tmk_core/protocol/midi/midi_function_types.h
@@ -0,0 +1,50 @@
+//midi for embedded chips,
+//Copyright 2010 Alex Norman
+//
+//This file is part of avr-midi.
+//
+//avr-midi is free software: you can redistribute it and/or modify
+//it under the terms of the GNU General Public License as published by
+//the Free Software Foundation, either version 3 of the License, or
+//(at your option) any later version.
+//
+//avr-midi is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//GNU General Public License for more details.
+//
+//You should have received a copy of the GNU General Public License
+//along with avr-midi. If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * @file
+ * @brief Function signature definitions
+ */
+
+#ifndef MIDI_FUNCTION_TYPES_H
+#define MIDI_FUNCTION_TYPES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+//forward declaration
+typedef struct _midi_device MidiDevice;
+
+typedef void (* midi_one_byte_func_t)(MidiDevice * device, uint8_t byte);
+typedef void (* midi_two_byte_func_t)(MidiDevice * device, uint8_t byte0, uint8_t byte1);
+typedef void (* midi_three_byte_func_t)(MidiDevice * device, uint8_t byte0, uint8_t byte1, uint8_t byte2);
+//all bytes after count bytes should be ignored
+typedef void (* midi_var_byte_func_t)(MidiDevice * device, uint16_t count, uint8_t byte0, uint8_t byte1, uint8_t byte2);
+
+//the start byte tells you how far into the sysex message you are, the data_length tells you how many bytes data is
+typedef void (* midi_sysex_func_t)(MidiDevice * device, uint16_t start_byte, uint8_t data_length, uint8_t *data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/tmk_core/protocol/midi/sysex_tools.c b/tmk_core/protocol/midi/sysex_tools.c
new file mode 100755
index 000000000..7563a3e2a
--- /dev/null
+++ b/tmk_core/protocol/midi/sysex_tools.c
@@ -0,0 +1,99 @@
+//midi for embedded chips,
+//Copyright 2010 Alex Norman
+//
+//This file is part of avr-midi.
+//
+//avr-midi is free software: you can redistribute it and/or modify
+//it under the terms of the GNU General Public License as published by
+//the Free Software Foundation, either version 3 of the License, or
+//(at your option) any later version.
+//
+//avr-midi is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//GNU General Public License for more details.
+//
+//You should have received a copy of the GNU General Public License
+//along with avr-midi. If not, see <http://www.gnu.org/licenses/>.
+
+#include "sysex_tools.h"
+
+uint16_t sysex_encoded_length(uint16_t decoded_length){
+ uint8_t remainder = decoded_length % 7;
+ if (remainder)
+ return (decoded_length / 7) * 8 + remainder + 1;
+ else
+ return (decoded_length / 7) * 8;
+}
+
+uint16_t sysex_decoded_length(uint16_t encoded_length){
+ uint8_t remainder = encoded_length % 8;
+ if (remainder)
+ return (encoded_length / 8) * 7 + remainder - 1;
+ else
+ return (encoded_length / 8) * 7;
+}
+
+uint16_t sysex_encode(uint8_t *encoded, const uint8_t *source, const uint16_t length){
+ uint16_t encoded_full = length / 7; //number of full 8 byte sections from 7 bytes of input
+ uint16_t i,j;
+
+ //fill out the fully encoded sections
+ for(i = 0; i < encoded_full; i++) {
+ uint16_t encoded_msb_idx = i * 8;
+ uint16_t input_start_idx = i * 7;
+ encoded[encoded_msb_idx] = 0;
+ for(j = 0; j < 7; j++){
+ uint8_t current = source[input_start_idx + j];
+ encoded[encoded_msb_idx] |= (0x80 & current) >> (1 + j);
+ encoded[encoded_msb_idx + 1 + j] = 0x7F & current;
+ }
+ }
+
+ //fill out the rest if there is any more
+ uint8_t remainder = length % 7;
+ if (remainder) {
+ uint16_t encoded_msb_idx = encoded_full * 8;
+ uint16_t input_start_idx = encoded_full * 7;
+ encoded[encoded_msb_idx] = 0;
+ for(j = 0; j < remainder; j++){
+ uint8_t current = source[input_start_idx + j];
+ encoded[encoded_msb_idx] |= (0x80 & current) >> (1 + j);
+ encoded[encoded_msb_idx + 1 + j] = 0x7F & current;
+ }
+ return encoded_msb_idx + remainder + 1;
+ } else {
+ return encoded_full * 8;
+ }
+}
+
+uint16_t sysex_decode(uint8_t *decoded, const uint8_t *source, const uint16_t length){
+ uint16_t decoded_full = length / 8;
+ uint16_t i,j;
+
+ if (length < 2)
+ return 0;
+
+ //fill out the fully encoded sections
+ for(i = 0; i < decoded_full; i++) {
+ uint16_t encoded_msb_idx = i * 8;
+ uint16_t output_start_index = i * 7;
+ for(j = 0; j < 7; j++){
+ decoded[output_start_index + j] = 0x7F & source[encoded_msb_idx + j + 1];
+ decoded[output_start_index + j] |= (0x80 & (source[encoded_msb_idx] << (1 + j)));
+ }
+ }
+ uint8_t remainder = length % 8;
+ if (remainder) {
+ uint16_t encoded_msb_idx = decoded_full * 8;
+ uint16_t output_start_index = decoded_full * 7;
+ for(j = 0; j < (remainder - 1); j++) {
+ decoded[output_start_index + j] = 0x7F & source[encoded_msb_idx + j + 1];
+ decoded[output_start_index + j] |= (0x80 & (source[encoded_msb_idx] << (1 + j)));
+ }
+ return decoded_full * 7 + remainder - 1;
+ } else {
+ return decoded_full * 7;
+ }
+}
+
diff --git a/tmk_core/protocol/midi/sysex_tools.h b/tmk_core/protocol/midi/sysex_tools.h
new file mode 100755
index 000000000..3654d0114
--- /dev/null
+++ b/tmk_core/protocol/midi/sysex_tools.h
@@ -0,0 +1,95 @@
+//midi for embedded chips,
+//Copyright 2010 Alex Norman
+//
+//This file is part of avr-midi.
+//
+//avr-midi is free software: you can redistribute it and/or modify
+//it under the terms of the GNU General Public License as published by
+//the Free Software Foundation, either version 3 of the License, or
+//(at your option) any later version.
+//
+//avr-midi is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//GNU General Public License for more details.
+//
+//You should have received a copy of the GNU General Public License
+//along with avr-midi. If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef SYSEX_TOOLS_H
+#define SYSEX_TOOLS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <inttypes.h>
+
+/**
+ * @file
+ * @brief Sysex utility functions
+ *
+ * These functions are for converting data to and from a "midi-safe" format,
+ * which can be use to send data with sysex messages. Sysex messages may only
+ * contain data where the to bit is not set.
+ *
+ * An "encoded" midi message is one that contains all of the data from its
+ * original state, but does not have any of the top bits set.
+ *
+ * Every 7 bytes of decoded data is converted into 8 bytes of encoded data and
+ * visa-versa. If you'd like to operate on small segments, make sure that you
+ * encode in 7 byte increments and decode in 8 byte increments.
+ *
+ */
+
+/** @defgroup sysex_tools Sysex utility functions
+ * @{
+ */
+
+/**
+ * @brief Compute the length of a message after it is encoded.
+ *
+ * @param decoded_length The length, in bytes, of the message to encode.
+ *
+ * @return The length, in bytes, of the message after encodeing.
+ */
+uint16_t sysex_encoded_length(uint16_t decoded_length);
+
+/**
+ * @brief Compute the length of a message after it is decoded.
+ *
+ * @param encoded_length The length, in bytes, of the encoded message.
+ *
+ * @return The length, in bytes, of the message after it is decoded.
+ */
+uint16_t sysex_decoded_length(uint16_t encoded_length);
+
+/**
+ * @brief Encode data so that it can be transmitted safely in a sysex message.
+ *
+ * @param encoded The output data buffer, must be at least sysex_encoded_length(length) bytes long.
+ * @param source The input buffer of data to be encoded.
+ * @param length The number of bytes from the input buffer to encode.
+ *
+ * @return number of bytes encoded.
+ */
+uint16_t sysex_encode(uint8_t *encoded, const uint8_t *source, uint16_t length);
+
+/**
+ * @brief Decode encoded data.
+ *
+ * @param decoded The output data buffer, must be at least sysex_decoded_length(length) bytes long.
+ * @param source The input buffer of data to be decoded.
+ * @param length The number of bytes from the input buffer to decode.
+ *
+ * @return number of bytes decoded.
+ */
+uint16_t sysex_decode(uint8_t *decoded, const uint8_t *source, uint16_t length);
+
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/tmk_core/protocol/news.c b/tmk_core/protocol/news.c
new file mode 100644
index 000000000..00755a5e2
--- /dev/null
+++ b/tmk_core/protocol/news.c
@@ -0,0 +1,168 @@
+/*
+Copyright 2012 Jun WAKO <wakojun@gmail.com>
+
+This software is licensed with a Modified BSD License.
+All of this is supposed to be Free Software, Open Source, DFSG-free,
+GPL-compatible, and OK to use in both free and proprietary applications.
+Additions and corrections to this file are welcome.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+* Neither the name of the copyright holders nor the names of
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdbool.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include "news.h"
+
+
+void news_init(void)
+{
+ NEWS_KBD_RX_INIT();
+}
+
+// RX ring buffer
+#define RBUF_SIZE 8
+static uint8_t rbuf[RBUF_SIZE];
+static uint8_t rbuf_head = 0;
+static uint8_t rbuf_tail = 0;
+
+uint8_t news_recv(void)
+{
+ uint8_t data = 0;
+ if (rbuf_head == rbuf_tail) {
+ return 0;
+ }
+
+ data = rbuf[rbuf_tail];
+ rbuf_tail = (rbuf_tail + 1) % RBUF_SIZE;
+ return data;
+}
+
+// USART RX complete interrupt
+ISR(NEWS_KBD_RX_VECT)
+{
+ uint8_t next = (rbuf_head + 1) % RBUF_SIZE;
+ if (next != rbuf_tail) {
+ rbuf[rbuf_head] = NEWS_KBD_RX_DATA;
+ rbuf_head = next;
+ }
+}
+
+
+/*
+SONY NEWS Keyboard Protocol
+===========================
+
+Resources
+---------
+ Mouse protocol of NWA-5461(Japanese)
+ http://groups.google.com/group/fj.sys.news/browse_thread/thread/a01b3e3ac6ae5b2d
+
+ SONY NEWS Info(Japanese)
+ http://katsu.watanabe.name/doc/sonynews/
+
+
+Pinouts
+-------
+ EIA 232 male connector from NWP-5461
+ -------------
+ \ 1 2 3 4 5 /
+ \ 6 7 8 9 /
+ ---------
+ 1 VCC
+ 2 BZ(Speaker)
+ 3 Keyboard Data(from keyboard MCU TxD)
+ 4 NC
+ 5 GND
+ 6 Unknown Input(to keyboard MCU RxD via schmitt trigger)
+ 7 Mouse Data(from Mouse Ext connector)
+ 8 Unknown Input(to Keyboard MCU Input via diode and buffer)
+ 9 FG
+ NOTE: Two LED on keyboard are controlled by pin 6,8?
+
+ EIA 232 male connector from NWP-411A
+ -------------
+ \ 1 2 3 4 5 /
+ \ 6 7 8 9 /
+ ---------
+ 1 VCC
+ 2 BZ(Speaker)
+ 3 Keyboard Data(from keyboard MCU TxD)
+ 4 NC
+ 5 GND
+ 6 NC
+ 7 Mouse Data(from Mouse Ext connector)
+ 8 NC
+ 9 FG
+ NOTE: These are just from my guess and not confirmed.
+
+
+Signaling
+---------
+ ~~~~~~~~~~ ____XOO0X111X222X333X444X555X666X777~~~~ ~~~~~~~
+ Idle Start LSB MSB Stop Idle
+
+ Idle: High
+ Start bit: Low
+ Stop bit: High
+ Bit order: LSB first
+
+ Baud rate: 9600
+ Interface: TTL level(5V) UART
+
+ NOTE: This is observed on NWP-5461 with its DIP switch all OFF.
+
+
+Format
+------
+ MSB LSB
+ 7 6 5 4 3 2 1 0 bit
+ | | | | | | | |
+ | +-+-+-+-+-+-+-- scan code(00-7F)
+ +---------------- break flag: sets when released
+
+
+Scan Codes
+----------
+ SONY NEWS NWP-5461
+ ,---. ,------------------------, ,------------------------. ,---------.
+ | 7A| | 01 | 02 | 03 | 04 | 05 | | 06 | 07 | 08 | 09 | 0A | | 68 | 69 | ,-----------.
+ `---' `------------------------' `------------------------' `---------' | 64| 65| 52|
+ ,-------------------------------------------------------------. ,---. ,---------------|
+ | 0B| 0C| 0D| 0E| 0F| 10| 11| 12| 13| 14| 15| 16| 17| 18| 19 | | 6A| | 4B| 4C| 4D| 4E|
+ |-------------------------------------------------------------| |---| |---------------|
+ | 1A | 1B| 1C| 1D| 1E| 1F| 20| 21| 22| 23| 24| 25| 26| 27| | | 6B| | 4F| 50| 51| 56|
+ |---------------------------------------------------------' | |---| |---------------|
+ | 28 | 29| 2A| 2B| 2C| 2D| 2E| 2F| 30| 31| 32| 33| 34| 35 | | 6C| | 53| 54| 55| |
+ |-------------------------------------------------------------| |---| |-----------| 5A|
+ | 36 | 37| 38| 39| 3A| 3B| 3C| 3D| 3E| 3F| 40| 41| 42 | | 6D| | 57| 59| 58| |
+ |-------------------------------------------------------------| |---| |---------------|
+ | 43 | 44 | 45 | 46 | 47 | 48| 49| 4A | | 6E| | 66| 5B| 5C| 5D|
+ `-------------------------------------------------------------' `---' `---------------'
+*/
diff --git a/tmk_core/protocol/news.h b/tmk_core/protocol/news.h
new file mode 100644
index 000000000..35e09c4d2
--- /dev/null
+++ b/tmk_core/protocol/news.h
@@ -0,0 +1,51 @@
+/*
+Copyright 2012 Jun WAKO <wakojun@gmail.com>
+
+This software is licensed with a Modified BSD License.
+All of this is supposed to be Free Software, Open Source, DFSG-free,
+GPL-compatible, and OK to use in both free and proprietary applications.
+Additions and corrections to this file are welcome.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+* Neither the name of the copyright holders nor the names of
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef NEWS_H
+#define NEWS_H
+/*
+ * Primitive PS/2 Library for AVR
+ */
+
+
+/* host role */
+void news_init(void);
+uint8_t news_recv(void);
+
+/* device role */
+
+#endif
diff --git a/tmk_core/protocol/next_kbd.c b/tmk_core/protocol/next_kbd.c
new file mode 100644
index 000000000..fa3034b3f
--- /dev/null
+++ b/tmk_core/protocol/next_kbd.c
@@ -0,0 +1,212 @@
+/*
+
+NeXT non-ADB Keyboard Protocol
+
+Copyright 2013, Benjamin Gould (bgould@github.com)
+
+Based on:
+TMK firmware code Copyright 2011,2012 Jun WAKO <wakojun@gmail.com>
+Arduino code by "Ladyada" Limor Fried (http://ladyada.net/, http://adafruit.com/), released under BSD license
+
+Timing reference thanks to http://m0115.web.fc2.com/ (dead link), http://cfile7.uf.tistory.com/image/14448E464F410BF22380BB
+Pinouts thanks to http://www.68k.org/~degs/nextkeyboard.html
+Keycodes from http://ftp.netbsd.org/pub/NetBSD/NetBSD-release-6/src/sys/arch/next68k/dev/
+
+This software is licensed with a Modified BSD License.
+All of this is supposed to be Free Software, Open Source, DFSG-free,
+GPL-compatible, and OK to use in both free and proprietary applications.
+Additions and corrections to this file are welcome.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+* Neither the name of the copyright holders nor the names of
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <util/atomic.h>
+#include <util/delay.h>
+#include "next_kbd.h"
+#include "debug.h"
+
+static inline void out_lo(void);
+static inline void out_hi(void);
+static inline void query(void);
+static inline void reset(void);
+static inline uint32_t response(void);
+
+/* The keyboard sends signal with 50us pulse width on OUT line
+ * while it seems to miss the 50us pulse on In line.
+ * next_kbd_set_leds() often fails to sync LED status with 50us
+ * but it works well with 51us(+1us) on TMK converter(ATMeaga32u2) at least.
+ * TODO: test on Teensy and Pro Micro configuration
+ */
+#define out_hi_delay(intervals) do { out_hi(); _delay_us((NEXT_KBD_TIMING+1) * intervals); } while (0);
+#define out_lo_delay(intervals) do { out_lo(); _delay_us((NEXT_KBD_TIMING+1) * intervals); } while (0);
+#define query_delay(intervals) do { query(); _delay_us((NEXT_KBD_TIMING+1) * intervals); } while (0);
+#define reset_delay(intervals) do { reset(); _delay_us((NEXT_KBD_TIMING+1) * intervals); } while (0);
+
+void next_kbd_init(void)
+{
+ out_hi();
+ NEXT_KBD_IN_DDR &= ~(1<<NEXT_KBD_IN_BIT); // KBD_IN to input
+ NEXT_KBD_IN_PORT |= (1<<NEXT_KBD_IN_BIT); // KBD_IN pull up
+
+ query_delay(5);
+ reset_delay(8);
+
+ query_delay(5);
+ reset_delay(8);
+}
+
+void next_kbd_set_leds(bool left, bool right)
+{
+ cli();
+ out_lo_delay(9);
+
+ out_hi_delay(3);
+ out_lo_delay(1);
+
+ if (left) {
+ out_hi_delay(1);
+ } else {
+ out_lo_delay(1);
+ }
+
+ if (right) {
+ out_hi_delay(1);
+ } else {
+ out_lo_delay(1);
+ }
+
+ out_lo_delay(7);
+ out_hi();
+ sei();
+}
+
+#define NEXT_KBD_READ (NEXT_KBD_IN_PIN&(1<<NEXT_KBD_IN_BIT))
+uint32_t next_kbd_recv(void)
+{
+
+ // First check to make sure that the keyboard is actually connected;
+ // if not, just return
+ // TODO: reflect the status of the keyboard in a return code
+ if (!NEXT_KBD_READ) {
+ sei();
+ return 0;
+ }
+
+ query();
+ uint32_t resp = response();
+
+ return resp;
+}
+
+static inline uint32_t response(void)
+{
+ cli();
+
+ // try a 5ms read; this should be called after the query method has
+ // been run so if a key is pressed we should get a response within
+ // 5ms; if not then send a reset and exit
+ uint8_t i = 0;
+ uint32_t data = 0;
+ uint16_t reset_timeout = 50000;
+ while (NEXT_KBD_READ && reset_timeout) {
+ asm(""); _delay_us(1); reset_timeout--;
+ }
+ if (!reset_timeout) {
+ reset();
+ sei();
+ return 0;
+ }
+ _delay_us(NEXT_KBD_TIMING / 2);
+ for (; i < 22; i++)
+ {
+ if (NEXT_KBD_READ)
+ {
+ data |= ((uint32_t) 1 << i);
+ /* Note:
+ * My testing with the ATmega32u4 showed that there might
+ * something wrong with the timing here; by the end of the
+ * second data byte some of the modifiers can get bumped out
+ * to the next bit over if we just cycle through the data
+ * based on the expected interval. There is a bit (i = 10)
+ * in the middle of the data that is always on followed by
+ * one that is always off - so we'll use that to reset our
+ * timing in case we've gotten ahead of the keyboard;
+ */
+ if (i == 10)
+ {
+ i++;
+ while (NEXT_KBD_READ) ;
+ _delay_us(NEXT_KBD_TIMING / 2);
+ }
+ } else {
+ /* redundant - but I don't want to remove if it might screw
+ * up the timing
+ */
+ data |= ((uint32_t) 0 << i);
+ }
+ _delay_us(NEXT_KBD_TIMING);
+ }
+
+ sei();
+
+ return data;
+}
+
+static inline void out_lo(void)
+{
+ NEXT_KBD_OUT_PORT &= ~(1<<NEXT_KBD_OUT_BIT);
+ NEXT_KBD_OUT_DDR |= (1<<NEXT_KBD_OUT_BIT);
+}
+
+static inline void out_hi(void)
+{
+ /* input with pull up */
+ NEXT_KBD_OUT_DDR &= ~(1<<NEXT_KBD_OUT_BIT);
+ NEXT_KBD_OUT_PORT |= (1<<NEXT_KBD_OUT_BIT);
+}
+
+static inline void query(void)
+{
+ out_lo_delay(5);
+ out_hi_delay(1);
+ out_lo_delay(3);
+ out_hi();
+}
+
+static inline void reset(void)
+{
+ out_lo_delay(1);
+ out_hi_delay(4);
+ out_lo_delay(1);
+ out_hi_delay(6);
+ out_lo_delay(10);
+ out_hi();
+}
diff --git a/tmk_core/protocol/next_kbd.h b/tmk_core/protocol/next_kbd.h
new file mode 100644
index 000000000..6d455d4fa
--- /dev/null
+++ b/tmk_core/protocol/next_kbd.h
@@ -0,0 +1,63 @@
+/*
+NeXT non-ADB Keyboard Protocol
+
+Copyright 2013, Benjamin Gould (bgould@github.com)
+
+Based on:
+TMK firmware code Copyright 2011,2012 Jun WAKO <wakojun@gmail.com>
+Arduino code by "Ladyada" Limor Fried (http://ladyada.net/, http://adafruit.com/), released under BSD license
+
+Timing reference thanks to http://m0115.web.fc2.com/ (dead link), http://cfile7.uf.tistory.com/image/14448E464F410BF22380BB
+Pinouts thanks to http://www.68k.org/~degs/nextkeyboard.html
+Keycodes from http://ftp.netbsd.org/pub/NetBSD/NetBSD-release-6/src/sys/arch/next68k/dev/
+
+This software is licensed with a Modified BSD License.
+All of this is supposed to be Free Software, Open Source, DFSG-free,
+GPL-compatible, and OK to use in both free and proprietary applications.
+Additions and corrections to this file are welcome.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+* Neither the name of the copyright holders nor the names of
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include <stdbool.h>
+
+#ifndef NEXT_KBD_H
+#define NEXT_KBD_H
+
+#define NEXT_KBD_KMBUS_IDLE 0x300600
+#define NEXT_KBD_TIMING 50
+
+extern uint8_t next_kbd_error;
+
+/* host role */
+void next_kbd_init(void);
+void next_kbd_set_leds(bool left, bool right);
+uint32_t next_kbd_recv(void);
+
+#endif
diff --git a/tmk_core/protocol/pjrc.mk b/tmk_core/protocol/pjrc.mk
new file mode 100644
index 000000000..2b1ba2cbf
--- /dev/null
+++ b/tmk_core/protocol/pjrc.mk
@@ -0,0 +1,30 @@
+PJRC_DIR = protocol/pjrc
+
+SRC += $(PJRC_DIR)/main.c \
+ $(PJRC_DIR)/pjrc.c \
+ $(PJRC_DIR)/usb_keyboard.c \
+ $(PJRC_DIR)/usb_debug.c \
+ $(PJRC_DIR)/usb.c
+
+# Option modules
+ifdef MOUSEKEY_ENABLE
+ SRC += $(PJRC_DIR)/usb_mouse.c
+endif
+
+ifdef ADB_MOUSE_ENABLE
+ SRC += $(PJRC_DIR)/usb_mouse.c
+endif
+
+ifdef PS2_MOUSE_ENABLE
+ SRC += $(PJRC_DIR)/usb_mouse.c
+endif
+
+ifdef EXTRAKEY_ENABLE
+ SRC += $(PJRC_DIR)/usb_extra.c
+endif
+
+# Search Path
+VPATH += $(TMK_DIR)/$(PJRC_DIR)
+
+# This indicates using LUFA stack
+OPT_DEFS += -DPROTOCOL_PJRC
diff --git a/tmk_core/protocol/pjrc/MEMO.txt b/tmk_core/protocol/pjrc/MEMO.txt
new file mode 100644
index 000000000..b0f059831
--- /dev/null
+++ b/tmk_core/protocol/pjrc/MEMO.txt
@@ -0,0 +1,25 @@
+Endpoint configuration
+----------------------
+0 Control endpoint
+1 keyboard
+2 mouse
+3 debug
+4 extra key(consumer/system)
+5 nkro keyboard(supported only on ATmega32U4/16U4 and AT90USB64/128)
+
+
+ATmega32U4/16U4, AT90USB64/128
+• Endpoint 0:programmable size FIFO up to 64 bytes, default control endpoint
+• Endpoints 1 programmable size FIFO up to 256 bytes in ping-pong mode.
+• Endpoints 2 to 6: programmable size FIFO up to 64 bytes in ping-pong mode.
+
+AT90USB82/162, ATmega8U2/16U2/32U2
+• Endpoint 0:programmable size FIFO up to 64 bytes, default control endpoint
+• Endpoints 1 and 2: programmable size FIFO up to 64 bytes.
+• Endpoints 3 and 4: programmable size FIFO up to 64 bytes with ping-pong mode.
+
+ping-pong mode means double buffer feature.
+
+
+NOTE: ATmega8U2/16U2/32U2 is not supported with PJRC stack at this time.
+TODO: Macro definition for ATmega8U2/16U2/32U2 in usb.h
diff --git a/tmk_core/protocol/pjrc/main.c b/tmk_core/protocol/pjrc/main.c
new file mode 100644
index 000000000..45eb17d4c
--- /dev/null
+++ b/tmk_core/protocol/pjrc/main.c
@@ -0,0 +1,74 @@
+/* Keyboard example with debug channel, for Teensy USB Development Board
+ * http://www.pjrc.com/teensy/usb_keyboard.html
+ * Copyright (c) 2008 PJRC.COM, LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdbool.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/wdt.h>
+#include <util/delay.h>
+#include "keyboard.h"
+#include "usb.h"
+#include "matrix.h"
+#include "print.h"
+#include "debug.h"
+#include "sendchar.h"
+#include "util.h"
+#include "suspend.h"
+#include "host.h"
+#include "pjrc.h"
+
+
+#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
+
+
+int main(void)
+{
+ // set for 16 MHz clock
+ CPU_PRESCALE(0);
+
+ keyboard_setup();
+
+ // Initialize the USB, and then wait for the host to set configuration.
+ // If the Teensy is powered without a PC connected to the USB port,
+ // this will wait forever.
+ usb_init();
+ while (!usb_configured()) /* wait */ ;
+
+ print_set_sendchar(sendchar);
+
+ keyboard_init();
+ host_set_driver(pjrc_driver());
+#ifdef SLEEP_LED_ENABLE
+ sleep_led_init();
+#endif
+ while (1) {
+ while (suspend) {
+ suspend_power_down();
+ if (remote_wakeup && suspend_wakeup_condition()) {
+ usb_remote_wakeup();
+ }
+ }
+
+ keyboard_task();
+ }
+}
diff --git a/tmk_core/protocol/pjrc/pjrc.c b/tmk_core/protocol/pjrc/pjrc.c
new file mode 100644
index 000000000..0562a12ff
--- /dev/null
+++ b/tmk_core/protocol/pjrc/pjrc.c
@@ -0,0 +1,76 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdint.h>
+#include "usb_keyboard.h"
+#include "usb_mouse.h"
+#include "usb_extra.h"
+#include "host_driver.h"
+#include "pjrc.h"
+
+
+/*------------------------------------------------------------------*
+ * Host driver
+ *------------------------------------------------------------------*/
+static uint8_t keyboard_leds(void);
+static void send_keyboard(report_keyboard_t *report);
+static void send_mouse(report_mouse_t *report);
+static void send_system(uint16_t data);
+static void send_consumer(uint16_t data);
+
+static host_driver_t driver = {
+ keyboard_leds,
+ send_keyboard,
+ send_mouse,
+ send_system,
+ send_consumer
+};
+
+host_driver_t *pjrc_driver(void)
+{
+ return &driver;
+}
+
+static uint8_t keyboard_leds(void) {
+ return usb_keyboard_leds;
+}
+
+static void send_keyboard(report_keyboard_t *report)
+{
+ usb_keyboard_send_report(report);
+}
+
+static void send_mouse(report_mouse_t *report)
+{
+#ifdef MOUSE_ENABLE
+ usb_mouse_send(report->x, report->y, report->v, report->h, report->buttons);
+#endif
+}
+
+static void send_system(uint16_t data)
+{
+#ifdef EXTRAKEY_ENABLE
+ usb_extra_system_send(data);
+#endif
+}
+
+static void send_consumer(uint16_t data)
+{
+#ifdef EXTRAKEY_ENABLE
+ usb_extra_consumer_send(data);
+#endif
+}
diff --git a/tmk_core/protocol/pjrc/pjrc.h b/tmk_core/protocol/pjrc/pjrc.h
new file mode 100644
index 000000000..06e79626f
--- /dev/null
+++ b/tmk_core/protocol/pjrc/pjrc.h
@@ -0,0 +1,26 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PJRC_H
+#define PJRC_H
+
+#include "host_driver.h"
+
+
+host_driver_t *pjrc_driver(void);
+
+#endif
diff --git a/tmk_core/protocol/pjrc/usb.c b/tmk_core/protocol/pjrc/usb.c
new file mode 100644
index 000000000..1e6ba8719
--- /dev/null
+++ b/tmk_core/protocol/pjrc/usb.c
@@ -0,0 +1,1002 @@
+/* USB Keyboard Plus Debug Channel Example for Teensy USB Development Board
+ * http://www.pjrc.com/teensy/usb_keyboard.html
+ * Copyright (c) 2009 PJRC.COM, LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <avr/io.h>
+#include <avr/pgmspace.h>
+#include <avr/interrupt.h>
+#include "usb.h"
+#include "usb_keyboard.h"
+#include "usb_mouse.h"
+#include "usb_debug.h"
+#include "usb_extra.h"
+#include "led.h"
+#include "print.h"
+#include "util.h"
+#ifdef SLEEP_LED_ENABLE
+#include "sleep_led.h"
+#endif
+#include "suspend.h"
+#include "action.h"
+#include "action_util.h"
+
+
+/**************************************************************************
+ *
+ * Configurable Options
+ *
+ **************************************************************************/
+
+// You can change these to give your code its own name.
+#ifndef MANUFACTURER
+# define STR_MANUFACTURER L"t.m.k."
+#else
+# define STR_MANUFACTURER LSTR(MANUFACTURER)
+#endif
+#ifndef PRODUCT
+# define STR_PRODUCT L"t.m.k. keyboard"
+#else
+# define STR_PRODUCT LSTR(PRODUCT)
+#endif
+
+
+// Mac OS-X and Linux automatically load the correct drivers. On
+// Windows, even though the driver is supplied by Microsoft, an
+// INF file is needed to load the driver. These numbers need to
+// match the INF file.
+#ifndef VENDOR_ID
+# define VENDOR_ID 0xFEED
+#endif
+
+#ifndef PRODUCT_ID
+# define PRODUCT_ID 0xBABE
+#endif
+
+#ifndef DEVICE_VER
+# define DEVICE_VER 0x0100
+#endif
+
+
+// USB devices are supposed to implment a halt feature, which is
+// rarely (if ever) used. If you comment this line out, the halt
+// code will be removed, saving 102 bytes of space (gcc 4.3.0).
+// This is not strictly USB compliant, but works with all major
+// operating systems.
+#define SUPPORT_ENDPOINT_HALT
+
+
+
+/**************************************************************************
+ *
+ * Endpoint Buffer Configuration
+ *
+ **************************************************************************/
+
+#define ENDPOINT0_SIZE 32
+
+bool remote_wakeup = false;
+bool suspend = false;
+
+// 0:control endpoint is enabled automatically by controller.
+static const uint8_t PROGMEM endpoint_config_table[] = {
+ // enable, UECFG0X(type, direction), UECFG1X(size, bank, allocation)
+ 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KBD_SIZE) | KBD_BUFFER, // 1
+#ifdef MOUSE_ENABLE
+ 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(MOUSE_SIZE) | MOUSE_BUFFER, // 2
+#else
+ 0, // 2
+#endif
+#ifdef CONSOLE_ENABLE
+ 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(DEBUG_TX_SIZE) | DEBUG_TX_BUFFER, // 3
+#else
+ 0,
+#endif
+#ifdef EXTRAKEY_ENABLE
+ 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(EXTRA_SIZE) | EXTRA_BUFFER, // 4
+#else
+ 0, // 4
+#endif
+#ifdef NKRO_ENABLE
+ 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KBD2_SIZE) | KBD2_BUFFER, // 5
+#else
+ 0, // 5
+#endif
+ 0, // 6
+};
+
+
+/**************************************************************************
+ *
+ * Descriptor Data
+ *
+ **************************************************************************/
+
+// Descriptors are the data that your computer reads when it auto-detects
+// this USB device (called "enumeration" in USB lingo). The most commonly
+// changed items are editable at the top of this file. Changing things
+// in here should only be done by those who've read chapter 9 of the USB
+// spec and relevant portions of any USB class specifications!
+
+
+static const uint8_t PROGMEM device_descriptor[] = {
+ 18, // bLength
+ 1, // bDescriptorType
+ 0x00, 0x02, // bcdUSB
+ 0, // bDeviceClass
+ 0, // bDeviceSubClass
+ 0, // bDeviceProtocol
+ ENDPOINT0_SIZE, // bMaxPacketSize0
+ LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor
+ LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct
+ LSB(DEVICE_VER), MSB(DEVICE_VER), // bcdDevice
+ 1, // iManufacturer
+ 2, // iProduct
+ 0, // iSerialNumber
+ 1 // bNumConfigurations
+};
+
+// Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60
+static const uint8_t PROGMEM keyboard_hid_report_desc[] = {
+ 0x05, 0x01, // Usage Page (Generic Desktop),
+ 0x09, 0x06, // Usage (Keyboard),
+ 0xA1, 0x01, // Collection (Application),
+ 0x75, 0x01, // Report Size (1),
+ 0x95, 0x08, // Report Count (8),
+ 0x05, 0x07, // Usage Page (Key Codes),
+ 0x19, 0xE0, // Usage Minimum (224),
+ 0x29, 0xE7, // Usage Maximum (231),
+ 0x15, 0x00, // Logical Minimum (0),
+ 0x25, 0x01, // Logical Maximum (1),
+ 0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte
+ 0x95, 0x01, // Report Count (1),
+ 0x75, 0x08, // Report Size (8),
+ 0x81, 0x03, // Input (Constant), ;Reserved byte
+ 0x95, 0x05, // Report Count (5),
+ 0x75, 0x01, // Report Size (1),
+ 0x05, 0x08, // Usage Page (LEDs),
+ 0x19, 0x01, // Usage Minimum (1),
+ 0x29, 0x05, // Usage Maximum (5),
+ 0x91, 0x02, // Output (Data, Variable, Absolute), ;LED report
+ 0x95, 0x01, // Report Count (1),
+ 0x75, 0x03, // Report Size (3),
+ 0x91, 0x03, // Output (Constant), ;LED report padding
+ 0x95, KBD_REPORT_KEYS, // Report Count (),
+ 0x75, 0x08, // Report Size (8),
+ 0x15, 0x00, // Logical Minimum (0),
+ 0x25, 0xFF, // Logical Maximum(255),
+ 0x05, 0x07, // Usage Page (Key Codes),
+ 0x19, 0x00, // Usage Minimum (0),
+ 0x29, 0xFF, // Usage Maximum (255),
+ 0x81, 0x00, // Input (Data, Array),
+ 0xc0 // End Collection
+};
+#ifdef NKRO_ENABLE
+static const uint8_t PROGMEM keyboard2_hid_report_desc[] = {
+ 0x05, 0x01, // Usage Page (Generic Desktop),
+ 0x09, 0x06, // Usage (Keyboard),
+ 0xA1, 0x01, // Collection (Application),
+ // bitmap of modifiers
+ 0x75, 0x01, // Report Size (1),
+ 0x95, 0x08, // Report Count (8),
+ 0x05, 0x07, // Usage Page (Key Codes),
+ 0x19, 0xE0, // Usage Minimum (224),
+ 0x29, 0xE7, // Usage Maximum (231),
+ 0x15, 0x00, // Logical Minimum (0),
+ 0x25, 0x01, // Logical Maximum (1),
+ 0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte
+ // LED output report
+ 0x95, 0x05, // Report Count (5),
+ 0x75, 0x01, // Report Size (1),
+ 0x05, 0x08, // Usage Page (LEDs),
+ 0x19, 0x01, // Usage Minimum (1),
+ 0x29, 0x05, // Usage Maximum (5),
+ 0x91, 0x02, // Output (Data, Variable, Absolute),
+ 0x95, 0x01, // Report Count (1),
+ 0x75, 0x03, // Report Size (3),
+ 0x91, 0x03, // Output (Constant),
+ // bitmap of keys
+ 0x95, KBD2_REPORT_KEYS*8, // Report Count (),
+ 0x75, 0x01, // Report Size (1),
+ 0x15, 0x00, // Logical Minimum (0),
+ 0x25, 0x01, // Logical Maximum(1),
+ 0x05, 0x07, // Usage Page (Key Codes),
+ 0x19, 0x00, // Usage Minimum (0),
+ 0x29, KBD2_REPORT_KEYS*8-1, // Usage Maximum (),
+ 0x81, 0x02, // Input (Data, Variable, Absolute),
+ 0xc0 // End Collection
+};
+#endif
+
+#ifdef MOUSE_ENABLE
+// Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension
+// http://www.microchip.com/forums/tm.aspx?high=&m=391435&mpage=1#391521
+// http://www.keil.com/forum/15671/
+// http://www.microsoft.com/whdc/device/input/wheel.mspx
+static const uint8_t PROGMEM mouse_hid_report_desc[] = {
+ /* mouse */
+ 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+ 0x09, 0x02, // USAGE (Mouse)
+ 0xa1, 0x01, // COLLECTION (Application)
+ //0x85, REPORT_ID_MOUSE, // REPORT_ID (1)
+ 0x09, 0x01, // USAGE (Pointer)
+ 0xa1, 0x00, // COLLECTION (Physical)
+ // ---------------------------- Buttons
+ 0x05, 0x09, // USAGE_PAGE (Button)
+ 0x19, 0x01, // USAGE_MINIMUM (Button 1)
+ 0x29, 0x05, // USAGE_MAXIMUM (Button 5)
+ 0x15, 0x00, // LOGICAL_MINIMUM (0)
+ 0x25, 0x01, // LOGICAL_MAXIMUM (1)
+ 0x75, 0x01, // REPORT_SIZE (1)
+ 0x95, 0x05, // REPORT_COUNT (5)
+ 0x81, 0x02, // INPUT (Data,Var,Abs)
+ 0x75, 0x03, // REPORT_SIZE (3)
+ 0x95, 0x01, // REPORT_COUNT (1)
+ 0x81, 0x03, // INPUT (Cnst,Var,Abs)
+ // ---------------------------- X,Y position
+ 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+ 0x09, 0x30, // USAGE (X)
+ 0x09, 0x31, // USAGE (Y)
+ 0x15, 0x81, // LOGICAL_MINIMUM (-127)
+ 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
+ 0x75, 0x08, // REPORT_SIZE (8)
+ 0x95, 0x02, // REPORT_COUNT (2)
+ 0x81, 0x06, // INPUT (Data,Var,Rel)
+ // ---------------------------- Vertical wheel
+ 0x09, 0x38, // USAGE (Wheel)
+ 0x15, 0x81, // LOGICAL_MINIMUM (-127)
+ 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
+ 0x35, 0x00, // PHYSICAL_MINIMUM (0) - reset physical
+ 0x45, 0x00, // PHYSICAL_MAXIMUM (0)
+ 0x75, 0x08, // REPORT_SIZE (8)
+ 0x95, 0x01, // REPORT_COUNT (1)
+ 0x81, 0x06, // INPUT (Data,Var,Rel)
+ // ---------------------------- Horizontal wheel
+ 0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
+ 0x0a, 0x38, 0x02, // USAGE (AC Pan)
+ 0x15, 0x81, // LOGICAL_MINIMUM (-127)
+ 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
+ 0x75, 0x08, // REPORT_SIZE (8)
+ 0x95, 0x01, // REPORT_COUNT (1)
+ 0x81, 0x06, // INPUT (Data,Var,Rel)
+ 0xc0, // END_COLLECTION
+ 0xc0, // END_COLLECTION
+};
+#endif
+
+static const uint8_t PROGMEM debug_hid_report_desc[] = {
+ 0x06, 0x31, 0xFF, // Usage Page 0xFF31 (vendor defined)
+ 0x09, 0x74, // Usage 0x74
+ 0xA1, 0x53, // Collection 0x53
+ 0x75, 0x08, // report size = 8 bits
+ 0x15, 0x00, // logical minimum = 0
+ 0x26, 0xFF, 0x00, // logical maximum = 255
+ 0x95, DEBUG_TX_SIZE, // report count
+ 0x09, 0x75, // usage
+ 0x81, 0x02, // Input (array)
+ 0xC0 // end collection
+};
+
+#ifdef EXTRAKEY_ENABLE
+// audio controls & system controls
+// http://www.microsoft.com/whdc/archive/w2kbd.mspx
+static const uint8_t PROGMEM extra_hid_report_desc[] = {
+ /* system control */
+ 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+ 0x09, 0x80, // USAGE (System Control)
+ 0xa1, 0x01, // COLLECTION (Application)
+ 0x85, REPORT_ID_SYSTEM, // REPORT_ID (2)
+ 0x15, 0x01, // LOGICAL_MINIMUM (0x1)
+ 0x25, 0xb7, // LOGICAL_MAXIMUM (0xb7)
+ 0x19, 0x01, // USAGE_MINIMUM (0x1)
+ 0x29, 0xb7, // USAGE_MAXIMUM (0xb7)
+ 0x75, 0x10, // REPORT_SIZE (16)
+ 0x95, 0x01, // REPORT_COUNT (1)
+ 0x81, 0x00, // INPUT (Data,Array,Abs)
+ 0xc0, // END_COLLECTION
+ /* consumer */
+ 0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
+ 0x09, 0x01, // USAGE (Consumer Control)
+ 0xa1, 0x01, // COLLECTION (Application)
+ 0x85, REPORT_ID_CONSUMER, // REPORT_ID (3)
+ 0x15, 0x01, // LOGICAL_MINIMUM (0x1)
+ 0x26, 0x9c, 0x02, // LOGICAL_MAXIMUM (0x29c)
+ 0x19, 0x01, // USAGE_MINIMUM (0x1)
+ 0x2a, 0x9c, 0x02, // USAGE_MAXIMUM (0x29c)
+ 0x75, 0x10, // REPORT_SIZE (16)
+ 0x95, 0x01, // REPORT_COUNT (1)
+ 0x81, 0x00, // INPUT (Data,Array,Abs)
+ 0xc0, // END_COLLECTION
+};
+#endif
+
+#define KBD_HID_DESC_NUM 0
+#define KBD_HID_DESC_OFFSET (9+(9+9+7)*KBD_HID_DESC_NUM+9)
+
+#ifdef MOUSE_ENABLE
+# define MOUSE_HID_DESC_NUM (KBD_HID_DESC_NUM + 1)
+# define MOUSE_HID_DESC_OFFSET (9+(9+9+7)*MOUSE_HID_DESC_NUM+9)
+#else
+# define MOUSE_HID_DESC_NUM (KBD_HID_DESC_NUM + 0)
+#endif
+
+#ifdef CONSOLE_ENABLE
+#define DEBUG_HID_DESC_NUM (MOUSE_HID_DESC_NUM + 1)
+#define DEBUG_HID_DESC_OFFSET (9+(9+9+7)*DEBUG_HID_DESC_NUM+9)
+#else
+# define DEBUG_HID_DESC_NUM (MOUSE_HID_DESC_NUM + 0)
+#endif
+
+#ifdef EXTRAKEY_ENABLE
+# define EXTRA_HID_DESC_NUM (DEBUG_HID_DESC_NUM + 1)
+# define EXTRA_HID_DESC_OFFSET (9+(9+9+7)*EXTRA_HID_DESC_NUM+9)
+#else
+# define EXTRA_HID_DESC_NUM (DEBUG_HID_DESC_NUM + 0)
+#endif
+
+#ifdef NKRO_ENABLE
+# define KBD2_HID_DESC_NUM (EXTRA_HID_DESC_NUM + 1)
+# define KBD2_HID_DESC_OFFSET (9+(9+9+7)*EXTRA_HID_DESC_NUM+9)
+#else
+# define KBD2_HID_DESC_NUM (EXTRA_HID_DESC_NUM + 0)
+#endif
+
+#define NUM_INTERFACES (KBD2_HID_DESC_NUM + 1)
+#define CONFIG1_DESC_SIZE (9+(9+9+7)*NUM_INTERFACES)
+static const uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
+ // configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
+ 9, // bLength;
+ 2, // bDescriptorType;
+ LSB(CONFIG1_DESC_SIZE), // wTotalLength
+ MSB(CONFIG1_DESC_SIZE),
+ NUM_INTERFACES, // bNumInterfaces
+ 1, // bConfigurationValue
+ 0, // iConfiguration
+ 0xA0, // bmAttributes
+ 50, // bMaxPower
+
+ // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
+ 9, // bLength
+ 4, // bDescriptorType
+ KBD_INTERFACE, // bInterfaceNumber
+ 0, // bAlternateSetting
+ 1, // bNumEndpoints
+ 0x03, // bInterfaceClass (0x03 = HID)
+ 0x01, // bInterfaceSubClass (0x01 = Boot)
+ 0x01, // bInterfaceProtocol (0x01 = Keyboard)
+ 0, // iInterface
+ // HID descriptor, HID 1.11 spec, section 6.2.1
+ 9, // bLength
+ 0x21, // bDescriptorType
+ 0x11, 0x01, // bcdHID
+ 0, // bCountryCode
+ 1, // bNumDescriptors
+ 0x22, // bDescriptorType
+ sizeof(keyboard_hid_report_desc), // wDescriptorLength
+ 0,
+ // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+ 7, // bLength
+ 5, // bDescriptorType
+ KBD_ENDPOINT | 0x80, // bEndpointAddress
+ 0x03, // bmAttributes (0x03=intr)
+ KBD_SIZE, 0, // wMaxPacketSize
+ 10, // bInterval
+
+#ifdef MOUSE_ENABLE
+ // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
+ 9, // bLength
+ 4, // bDescriptorType
+ MOUSE_INTERFACE, // bInterfaceNumber
+ 0, // bAlternateSetting
+ 1, // bNumEndpoints
+ 0x03, // bInterfaceClass (0x03 = HID)
+ // ThinkPad T23 BIOS doesn't work with boot mouse.
+ 0x00, // bInterfaceSubClass (0x01 = Boot)
+ 0x00, // bInterfaceProtocol (0x02 = Mouse)
+/*
+ 0x01, // bInterfaceSubClass (0x01 = Boot)
+ 0x02, // bInterfaceProtocol (0x02 = Mouse)
+*/
+ 0, // iInterface
+ // HID descriptor, HID 1.11 spec, section 6.2.1
+ 9, // bLength
+ 0x21, // bDescriptorType
+ 0x11, 0x01, // bcdHID
+ 0, // bCountryCode
+ 1, // bNumDescriptors
+ 0x22, // bDescriptorType
+ sizeof(mouse_hid_report_desc), // wDescriptorLength
+ 0,
+ // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+ 7, // bLength
+ 5, // bDescriptorType
+ MOUSE_ENDPOINT | 0x80, // bEndpointAddress
+ 0x03, // bmAttributes (0x03=intr)
+ MOUSE_SIZE, 0, // wMaxPacketSize
+ 1, // bInterval
+#endif
+
+#ifdef CONSOLE_ENABLE
+ // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
+ 9, // bLength
+ 4, // bDescriptorType
+ DEBUG_INTERFACE, // bInterfaceNumber
+ 0, // bAlternateSetting
+ 1, // bNumEndpoints
+ 0x03, // bInterfaceClass (0x03 = HID)
+ 0x00, // bInterfaceSubClass
+ 0x00, // bInterfaceProtocol
+ 0, // iInterface
+ // HID descriptor, HID 1.11 spec, section 6.2.1
+ 9, // bLength
+ 0x21, // bDescriptorType
+ 0x11, 0x01, // bcdHID
+ 0, // bCountryCode
+ 1, // bNumDescriptors
+ 0x22, // bDescriptorType
+ sizeof(debug_hid_report_desc), // wDescriptorLength
+ 0,
+ // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+ 7, // bLength
+ 5, // bDescriptorType
+ DEBUG_TX_ENDPOINT | 0x80, // bEndpointAddress
+ 0x03, // bmAttributes (0x03=intr)
+ DEBUG_TX_SIZE, 0, // wMaxPacketSize
+ 1, // bInterval
+#endif
+
+#ifdef EXTRAKEY_ENABLE
+ // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
+ 9, // bLength
+ 4, // bDescriptorType
+ EXTRA_INTERFACE, // bInterfaceNumber
+ 0, // bAlternateSetting
+ 1, // bNumEndpoints
+ 0x03, // bInterfaceClass (0x03 = HID)
+ 0x00, // bInterfaceSubClass
+ 0x00, // bInterfaceProtocol
+ 0, // iInterface
+ // HID descriptor, HID 1.11 spec, section 6.2.1
+ 9, // bLength
+ 0x21, // bDescriptorType
+ 0x11, 0x01, // bcdHID
+ 0, // bCountryCode
+ 1, // bNumDescriptors
+ 0x22, // bDescriptorType
+ sizeof(extra_hid_report_desc), // wDescriptorLength
+ 0,
+ // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+ 7, // bLength
+ 5, // bDescriptorType
+ EXTRA_ENDPOINT | 0x80, // bEndpointAddress
+ 0x03, // bmAttributes (0x03=intr)
+ EXTRA_SIZE, 0, // wMaxPacketSize
+ 10, // bInterval
+#endif
+
+#ifdef NKRO_ENABLE
+ // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
+ 9, // bLength
+ 4, // bDescriptorType
+ KBD2_INTERFACE, // bInterfaceNumber
+ 0, // bAlternateSetting
+ 1, // bNumEndpoints
+ 0x03, // bInterfaceClass (0x03 = HID)
+ 0x00, // bInterfaceSubClass (0x01 = Boot)
+ 0x00, // bInterfaceProtocol (0x01 = Keyboard)
+ 0, // iInterface
+ // HID descriptor, HID 1.11 spec, section 6.2.1
+ 9, // bLength
+ 0x21, // bDescriptorType
+ 0x11, 0x01, // bcdHID
+ 0, // bCountryCode
+ 1, // bNumDescriptors
+ 0x22, // bDescriptorType
+ sizeof(keyboard2_hid_report_desc), // wDescriptorLength
+ 0,
+ // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
+ 7, // bLength
+ 5, // bDescriptorType
+ KBD2_ENDPOINT | 0x80, // bEndpointAddress
+ 0x03, // bmAttributes (0x03=intr)
+ KBD2_SIZE, 0, // wMaxPacketSize
+ 1, // bInterval
+#endif
+};
+
+// If you're desperate for a little extra code memory, these strings
+// can be completely removed if iManufacturer, iProduct, iSerialNumber
+// in the device desciptor are changed to zeros.
+struct usb_string_descriptor_struct {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ int16_t wString[];
+};
+static const struct usb_string_descriptor_struct PROGMEM string0 = {
+ 4,
+ 3,
+ {0x0409}
+};
+static const struct usb_string_descriptor_struct PROGMEM string1 = {
+ sizeof(STR_MANUFACTURER),
+ 3,
+ STR_MANUFACTURER
+};
+static const struct usb_string_descriptor_struct PROGMEM string2 = {
+ sizeof(STR_PRODUCT),
+ 3,
+ STR_PRODUCT
+};
+
+// This table defines which descriptor data is sent for each specific
+// request from the host (in wValue and wIndex).
+static const struct descriptor_list_struct {
+ uint16_t wValue; // descriptor type
+ uint16_t wIndex;
+ const uint8_t *addr;
+ uint8_t length;
+} PROGMEM descriptor_list[] = {
+ // DEVICE descriptor
+ {0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)},
+ // CONFIGURATION descriptor
+ {0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)},
+ // HID/REPORT descriptors
+ {0x2100, KBD_INTERFACE, config1_descriptor+KBD_HID_DESC_OFFSET, 9},
+ {0x2200, KBD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)},
+#ifdef MOUSE_ENABLE
+ {0x2100, MOUSE_INTERFACE, config1_descriptor+MOUSE_HID_DESC_OFFSET, 9},
+ {0x2200, MOUSE_INTERFACE, mouse_hid_report_desc, sizeof(mouse_hid_report_desc)},
+#endif
+#ifdef CONSOLE_ENABLE
+ {0x2100, DEBUG_INTERFACE, config1_descriptor+DEBUG_HID_DESC_OFFSET, 9},
+ {0x2200, DEBUG_INTERFACE, debug_hid_report_desc, sizeof(debug_hid_report_desc)},
+#endif
+#ifdef EXTRAKEY_ENABLE
+ {0x2100, EXTRA_INTERFACE, config1_descriptor+EXTRA_HID_DESC_OFFSET, 9},
+ {0x2200, EXTRA_INTERFACE, extra_hid_report_desc, sizeof(extra_hid_report_desc)},
+#endif
+#ifdef NKRO_ENABLE
+ {0x2100, KBD2_INTERFACE, config1_descriptor+KBD2_HID_DESC_OFFSET, 9},
+ {0x2200, KBD2_INTERFACE, keyboard2_hid_report_desc, sizeof(keyboard2_hid_report_desc)},
+#endif
+ // STRING descriptors
+ {0x0300, 0x0000, (const uint8_t *)&string0, 4},
+ {0x0301, 0x0409, (const uint8_t *)&string1, sizeof(STR_MANUFACTURER)},
+ {0x0302, 0x0409, (const uint8_t *)&string2, sizeof(STR_PRODUCT)}
+};
+#define NUM_DESC_LIST (sizeof(descriptor_list)/sizeof(struct descriptor_list_struct))
+
+
+/**************************************************************************
+ *
+ * Variables - these are the only non-stack RAM usage
+ *
+ **************************************************************************/
+
+// zero when we are not configured, non-zero when enumerated
+static volatile uint8_t usb_configuration=0;
+
+
+/**************************************************************************
+ *
+ * Public Functions - these are the API intended for the user
+ *
+ **************************************************************************/
+
+
+// initialize USB
+void usb_init(void)
+{
+ HW_CONFIG();
+ USB_FREEZE(); // enable USB
+ PLL_CONFIG(); // config PLL
+ while (!(PLLCSR & (1<<PLOCK))) ; // wait for PLL lock
+ USB_CONFIG(); // start USB clock
+ UDCON = 0; // enable attach resistor
+ usb_configuration = 0;
+ suspend = false;
+ UDIEN = (1<<EORSTE)|(1<<SOFE)|(1<<SUSPE)|(1<<WAKEUPE);
+ sei();
+}
+
+// return 0 if the USB is not configured, or the configuration
+// number selected by the HOST
+uint8_t usb_configured(void)
+{
+ return usb_configuration && !suspend;
+}
+
+void usb_remote_wakeup(void)
+{
+ UDCON |= (1<<RMWKUP);
+ while (UDCON & (1<<RMWKUP));
+}
+
+
+
+/**************************************************************************
+ *
+ * Private Functions - not intended for general user consumption....
+ *
+ **************************************************************************/
+
+
+
+// USB Device Interrupt - handle all device-level events
+// the transmit buffer flushing is triggered by the start of frame
+//
+ISR(USB_GEN_vect)
+{
+ uint8_t intbits, t;
+ static uint8_t div4=0;
+
+ intbits = UDINT;
+ UDINT = 0;
+ if ((intbits & (1<<SUSPI)) && (UDIEN & (1<<SUSPE)) && usb_configuration) {
+#ifdef SLEEP_LED_ENABLE
+ sleep_led_enable();
+#endif
+ UDIEN &= ~(1<<SUSPE);
+ UDIEN |= (1<<WAKEUPE);
+ suspend = true;
+ }
+ if ((intbits & (1<<WAKEUPI)) && (UDIEN & (1<<WAKEUPE)) && usb_configuration) {
+ suspend_wakeup_init();
+#ifdef SLEEP_LED_ENABLE
+ sleep_led_disable();
+ // NOTE: converters may not accept this
+ led_set(host_keyboard_leds());
+#endif
+
+ UDIEN |= (1<<SUSPE);
+ UDIEN &= ~(1<<WAKEUPE);
+ suspend = false;
+ }
+ if (intbits & (1<<EORSTI)) {
+ UENUM = 0;
+ UECONX = 1;
+ UECFG0X = EP_TYPE_CONTROL;
+ UECFG1X = EP_SIZE(ENDPOINT0_SIZE) | EP_SINGLE_BUFFER;
+ UEIENX = (1<<RXSTPE);
+ usb_configuration = 0;
+ }
+ if ((intbits & (1<<SOFI)) && usb_configuration) {
+ t = debug_flush_timer;
+ if (t) {
+ debug_flush_timer = -- t;
+ if (!t) {
+ UENUM = DEBUG_TX_ENDPOINT;
+ while ((UEINTX & (1<<RWAL))) {
+ UEDATX = 0;
+ }
+ UEINTX = 0x3A;
+ }
+ }
+ /* TODO: should keep IDLE rate on each keyboard interface */
+#ifdef NKRO_ENABLE
+ if (!keyboard_nkro && keyboard_idle && (++div4 & 3) == 0) {
+#else
+ if (keyboard_idle && (++div4 & 3) == 0) {
+#endif
+ UENUM = KBD_ENDPOINT;
+ if (UEINTX & (1<<RWAL)) {
+ usb_keyboard_idle_count++;
+ if (usb_keyboard_idle_count == keyboard_idle) {
+ usb_keyboard_idle_count = 0;
+ /* TODO: fix keyboard_report inconsistency */
+/* To avoid Mac SET_IDLE behaviour.
+ UEDATX = keyboard_report_prev->mods;
+ UEDATX = 0;
+ uint8_t keys = keyboard_protocol ? KBD_REPORT_KEYS : 6;
+ for (uint8_t i=0; i<keys; i++) {
+ UEDATX = keyboard_report_prev->keys[i];
+ }
+ UEINTX = 0x3A;
+*/
+ }
+ }
+ }
+ }
+}
+
+
+
+// Misc functions to wait for ready and send/receive packets
+static inline void usb_wait_in_ready(void)
+{
+ while (!(UEINTX & (1<<TXINI))) ;
+}
+static inline void usb_send_in(void)
+{
+ UEINTX = ~(1<<TXINI);
+}
+static inline void usb_wait_receive_out(void)
+{
+ while (!(UEINTX & (1<<RXOUTI))) ;
+}
+static inline void usb_ack_out(void)
+{
+ UEINTX = ~(1<<RXOUTI);
+}
+
+
+
+// USB Endpoint Interrupt - endpoint 0 is handled here. The
+// other endpoints are manipulated by the user-callable
+// functions, and the start-of-frame interrupt.
+//
+ISR(USB_COM_vect)
+{
+ uint8_t intbits;
+ const uint8_t *list;
+ const uint8_t *cfg;
+ uint8_t i, n, len, en;
+ uint8_t bmRequestType;
+ uint8_t bRequest;
+ uint16_t wValue;
+ uint16_t wIndex;
+ uint16_t wLength;
+ uint16_t desc_val;
+ const uint8_t *desc_addr;
+ uint8_t desc_length;
+
+ UENUM = 0;
+ intbits = UEINTX;
+ if (intbits & (1<<RXSTPI)) {
+ bmRequestType = UEDATX;
+ bRequest = UEDATX;
+ wValue = UEDATX;
+ wValue |= (UEDATX << 8);
+ wIndex = UEDATX;
+ wIndex |= (UEDATX << 8);
+ wLength = UEDATX;
+ wLength |= (UEDATX << 8);
+ UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
+ if (bRequest == GET_DESCRIPTOR) {
+ list = (const uint8_t *)descriptor_list;
+ for (i=0; ; i++) {
+ if (i >= NUM_DESC_LIST) {
+ UECONX = (1<<STALLRQ)|(1<<EPEN); //stall
+ return;
+ }
+ desc_val = pgm_read_word(list);
+ if (desc_val != wValue) {
+ list += sizeof(struct descriptor_list_struct);
+ continue;
+ }
+ list += 2;
+ desc_val = pgm_read_word(list);
+ if (desc_val != wIndex) {
+ list += sizeof(struct descriptor_list_struct)-2;
+ continue;
+ }
+ list += 2;
+ desc_addr = (const uint8_t *)pgm_read_word(list);
+ list += 2;
+ desc_length = pgm_read_byte(list);
+ break;
+ }
+ len = (wLength < 256) ? wLength : 255;
+ if (len > desc_length) len = desc_length;
+ do {
+ // wait for host ready for IN packet
+ do {
+ i = UEINTX;
+ } while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
+ if (i & (1<<RXOUTI)) return; // abort
+ // send IN packet
+ n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
+ for (i = n; i; i--) {
+ UEDATX = pgm_read_byte(desc_addr++);
+ }
+ len -= n;
+ usb_send_in();
+ } while (len || n == ENDPOINT0_SIZE);
+ return;
+ }
+ if (bRequest == SET_ADDRESS) {
+ usb_send_in();
+ usb_wait_in_ready();
+ UDADDR = wValue | (1<<ADDEN);
+ return;
+ }
+ if (bRequest == SET_CONFIGURATION && bmRequestType == 0) {
+ usb_configuration = wValue;
+ usb_send_in();
+ cfg = endpoint_config_table;
+ for (i=1; i<=MAX_ENDPOINT; i++) {
+ UENUM = i;
+ en = pgm_read_byte(cfg++);
+ if (en) {
+ UECONX = (1<<EPEN);
+ UECFG0X = pgm_read_byte(cfg++);
+ UECFG1X = pgm_read_byte(cfg++);
+ } else {
+ UECONX = 0;
+ }
+ }
+ UERST = UERST_MASK;
+ UERST = 0;
+ return;
+ }
+ if (bRequest == GET_CONFIGURATION && bmRequestType == 0x80) {
+ usb_wait_in_ready();
+ UEDATX = usb_configuration;
+ usb_send_in();
+ return;
+ }
+
+ if (bRequest == GET_STATUS) {
+ usb_wait_in_ready();
+ i = 0;
+ #ifdef SUPPORT_ENDPOINT_HALT
+ if (bmRequestType == 0x82) {
+ UENUM = wIndex;
+ if (UECONX & (1<<STALLRQ)) i = 1;
+ UENUM = 0;
+ }
+ #endif
+ UEDATX = i;
+ UEDATX = 0;
+ usb_send_in();
+ return;
+ }
+ if (bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE) {
+#ifdef SUPPORT_ENDPOINT_HALT
+ if (bmRequestType == 0x02 && wValue == ENDPOINT_HALT) {
+ i = wIndex & 0x7F;
+ if (i >= 1 && i <= MAX_ENDPOINT) {
+ usb_send_in();
+ UENUM = i;
+ if (bRequest == SET_FEATURE) {
+ UECONX = (1<<STALLRQ)|(1<<EPEN);
+ } else {
+ UECONX = (1<<STALLRQC)|(1<<RSTDT)|(1<<EPEN);
+ UERST = (1 << i);
+ UERST = 0;
+ }
+ return;
+ }
+ }
+#endif
+ if (bmRequestType == 0x00 && wValue == DEVICE_REMOTE_WAKEUP) {
+ if (bRequest == SET_FEATURE) {
+ remote_wakeup = true;
+ } else {
+ remote_wakeup = false;
+ }
+ usb_send_in();
+ return;
+ }
+ }
+ if (wIndex == KBD_INTERFACE) {
+ if (bmRequestType == 0xA1) {
+ if (bRequest == HID_GET_REPORT) {
+ usb_wait_in_ready();
+ UEDATX = keyboard_report->mods;
+ UEDATX = 0;
+ for (i=0; i<6; i++) {
+ UEDATX = keyboard_report->keys[i];
+ }
+ usb_send_in();
+ return;
+ }
+ if (bRequest == HID_GET_IDLE) {
+ usb_wait_in_ready();
+ UEDATX = keyboard_idle;
+ usb_send_in();
+ return;
+ }
+ if (bRequest == HID_GET_PROTOCOL) {
+ usb_wait_in_ready();
+ UEDATX = keyboard_protocol;
+ usb_send_in();
+ return;
+ }
+ }
+ if (bmRequestType == 0x21) {
+ if (bRequest == HID_SET_REPORT) {
+ usb_wait_receive_out();
+ usb_keyboard_leds = UEDATX;
+ usb_ack_out();
+ usb_send_in();
+ return;
+ }
+ if (bRequest == HID_SET_IDLE) {
+ keyboard_idle = (wValue >> 8);
+ usb_keyboard_idle_count = 0;
+ //usb_wait_in_ready();
+ usb_send_in();
+ return;
+ }
+ if (bRequest == HID_SET_PROTOCOL) {
+ keyboard_protocol = wValue;
+#ifdef NKRO_ENABLE
+ keyboard_nkro = !!keyboard_protocol;
+#endif
+ clear_keyboard();
+ //usb_wait_in_ready();
+ usb_send_in();
+ return;
+ }
+ }
+ }
+#ifdef MOUSE_ENABLE
+ if (wIndex == MOUSE_INTERFACE) {
+ if (bmRequestType == 0xA1) {
+ if (bRequest == HID_GET_REPORT) {
+ if (wValue == HID_REPORT_INPUT) {
+ usb_wait_in_ready();
+ UEDATX = 0;
+ UEDATX = 0;
+ UEDATX = 0;
+ UEDATX = 0;
+ usb_send_in();
+ return;
+ }
+ if (wValue == HID_REPORT_FEATURE) {
+ usb_wait_in_ready();
+ UEDATX = 0x05;
+ usb_send_in();
+ return;
+ }
+ }
+ if (bRequest == HID_GET_PROTOCOL) {
+ usb_wait_in_ready();
+ UEDATX = usb_mouse_protocol;
+ usb_send_in();
+ return;
+ }
+ }
+ if (bmRequestType == 0x21) {
+ if (bRequest == HID_SET_PROTOCOL) {
+ usb_mouse_protocol = wValue;
+ usb_send_in();
+ return;
+ }
+ }
+ }
+#endif
+ if (wIndex == DEBUG_INTERFACE) {
+ if (bRequest == HID_GET_REPORT && bmRequestType == 0xA1) {
+ len = wLength;
+ do {
+ // wait for host ready for IN packet
+ do {
+ i = UEINTX;
+ } while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
+ if (i & (1<<RXOUTI)) return; // abort
+ // send IN packet
+ n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
+ for (i = n; i; i--) {
+ UEDATX = 0;
+ }
+ len -= n;
+ usb_send_in();
+ } while (len || n == ENDPOINT0_SIZE);
+ return;
+ }
+ }
+ }
+ UECONX = (1<<STALLRQ) | (1<<EPEN); // stall
+}
diff --git a/tmk_core/protocol/pjrc/usb.h b/tmk_core/protocol/pjrc/usb.h
new file mode 100644
index 000000000..a195b671d
--- /dev/null
+++ b/tmk_core/protocol/pjrc/usb.h
@@ -0,0 +1,137 @@
+/* USB Keyboard Plus Debug Channel Example for Teensy USB Development Board
+ * http://www.pjrc.com/teensy/usb_keyboard.html
+ * Copyright (c) 2009 PJRC.COM, LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef USB_H
+#define USB_H 1
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <avr/io.h>
+
+
+extern bool remote_wakeup;
+extern bool suspend;
+
+void usb_init(void); // initialize everything
+uint8_t usb_configured(void); // is the USB port configured
+void usb_remote_wakeup(void);
+
+
+#define EP_TYPE_CONTROL 0x00
+#define EP_TYPE_BULK_IN 0x81
+#define EP_TYPE_BULK_OUT 0x80
+#define EP_TYPE_INTERRUPT_IN 0xC1
+#define EP_TYPE_INTERRUPT_OUT 0xC0
+#define EP_TYPE_ISOCHRONOUS_IN 0x41
+#define EP_TYPE_ISOCHRONOUS_OUT 0x40
+
+#define EP_SINGLE_BUFFER 0x02
+#define EP_DOUBLE_BUFFER 0x06
+
+#define EP_SIZE(s) ((s) == 64 ? 0x30 : \
+ ((s) == 32 ? 0x20 : \
+ ((s) == 16 ? 0x10 : \
+ 0x00)))
+
+#if defined (__AVR_AT90USB162__) || defined (__AVR_AT90USB82__)
+# define MAX_ENDPOINT 4
+# define UERST_MASK 0x1E
+#else
+# define MAX_ENDPOINT 6
+# define UERST_MASK 0x7E
+#endif
+
+#define LSB(n) (n & 255)
+#define MSB(n) ((n >> 8) & 255)
+
+#if defined(__AVR_AT90USB162__)
+#define HW_CONFIG()
+#define PLL_CONFIG() (PLLCSR = ((1<<PLLE)|(1<<PLLP0)))
+#define USB_CONFIG() (USBCON = (1<<USBE))
+#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
+#elif defined(__AVR_ATmega32U4__)
+#define HW_CONFIG() (UHWCON = 0x01)
+#define PLL_CONFIG() (PLLCSR = 0x12)
+#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
+#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
+#elif defined(__AVR_AT90USB646__)
+#define HW_CONFIG() (UHWCON = 0x81)
+#define PLL_CONFIG() (PLLCSR = 0x1A)
+#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
+#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
+#elif defined(__AVR_AT90USB1286__)
+#define HW_CONFIG() (UHWCON = 0x81)
+#define PLL_CONFIG() (PLLCSR = 0x16)
+#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
+#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
+#endif
+
+// standard control endpoint request types
+#define GET_STATUS 0
+#define CLEAR_FEATURE 1
+#define SET_FEATURE 3
+#define SET_ADDRESS 5
+#define GET_DESCRIPTOR 6
+#define GET_CONFIGURATION 8
+#define SET_CONFIGURATION 9
+#define GET_INTERFACE 10
+#define SET_INTERFACE 11
+// HID (human interface device)
+#define HID_GET_REPORT 1
+#define HID_GET_IDLE 2
+#define HID_GET_PROTOCOL 3
+#define HID_SET_REPORT 9
+#define HID_SET_IDLE 10
+#define HID_SET_PROTOCOL 11
+#define HID_REPORT_INPUT 1
+#define HID_REPORT_OUTPUT 2
+#define HID_REPORT_FEATURE 3
+// CDC (communication class device)
+#define CDC_SET_LINE_CODING 0x20
+#define CDC_GET_LINE_CODING 0x21
+#define CDC_SET_CONTROL_LINE_STATE 0x22
+// HID feature selectors
+#define DEVICE_REMOTE_WAKEUP 1
+#define ENDPOINT_HALT 0
+#define TEST_MODE 2
+
+
+/*------------------------------------------------------------------*
+ * Keyboard descriptor setting
+ *------------------------------------------------------------------*/
+#define KBD_INTERFACE 0
+#define KBD_ENDPOINT 1
+#define KBD_SIZE 8
+#define KBD_BUFFER EP_SINGLE_BUFFER
+#define KBD_REPORT_KEYS (KBD_SIZE - 2)
+
+// secondary keyboard
+#ifdef NKRO_ENABLE
+#define KBD2_INTERFACE 4
+#define KBD2_ENDPOINT 5
+#define KBD2_SIZE 16
+#define KBD2_BUFFER EP_DOUBLE_BUFFER
+#define KBD2_REPORT_KEYS (KBD2_SIZE - 1)
+#endif
+
+#endif
diff --git a/tmk_core/protocol/pjrc/usb_debug.c b/tmk_core/protocol/pjrc/usb_debug.c
new file mode 100644
index 000000000..c1e6f6544
--- /dev/null
+++ b/tmk_core/protocol/pjrc/usb_debug.c
@@ -0,0 +1,102 @@
+/* USB Keyboard Plus Debug Channel Example for Teensy USB Development Board
+ * http://www.pjrc.com/teensy/usb_keyboard.html
+ * Copyright (c) 2009 PJRC.COM, LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <avr/interrupt.h>
+#include "sendchar.h"
+#include "usb_debug.h"
+
+
+// the time remaining before we transmit any partially full
+// packet, or send a zero length packet.
+volatile uint8_t debug_flush_timer=0;
+
+
+int8_t sendchar(uint8_t c)
+{
+ static uint8_t previous_timeout=0;
+ uint8_t timeout, intr_state;
+
+ // if we're not online (enumerated and configured), error
+ if (!usb_configured()) return -1;
+ // interrupts are disabled so these functions can be
+ // used from the main program or interrupt context,
+ // even both in the same program!
+ intr_state = SREG;
+ cli();
+ UENUM = DEBUG_TX_ENDPOINT;
+ // if we gave up due to timeout before, don't wait again
+ if (previous_timeout) {
+ if (!(UEINTX & (1<<RWAL))) {
+ SREG = intr_state;
+ return -1;
+ }
+ previous_timeout = 0;
+ }
+ // wait for the FIFO to be ready to accept data
+ timeout = UDFNUML + 4;
+ while (1) {
+ // are we ready to transmit?
+ if (UEINTX & (1<<RWAL)) break;
+ SREG = intr_state;
+ // have we waited too long?
+ if (UDFNUML == timeout) {
+ previous_timeout = 1;
+ return -1;
+ }
+ // has the USB gone offline?
+ if (!usb_configured()) return -1;
+ // get ready to try checking again
+ intr_state = SREG;
+ cli();
+ UENUM = DEBUG_TX_ENDPOINT;
+ }
+ // actually write the byte into the FIFO
+ UEDATX = c;
+ // if this completed a packet, transmit it now!
+ if (!(UEINTX & (1<<RWAL))) {
+ UEINTX = 0x3A;
+ debug_flush_timer = 0;
+ } else {
+ debug_flush_timer = 2;
+ }
+ SREG = intr_state;
+ return 0;
+}
+
+// immediately transmit any buffered output.
+void usb_debug_flush_output(void)
+{
+ uint8_t intr_state;
+
+ intr_state = SREG;
+ cli();
+ if (debug_flush_timer) {
+ UENUM = DEBUG_TX_ENDPOINT;
+ while ((UEINTX & (1<<RWAL))) {
+ UEDATX = 0;
+ }
+ UEINTX = 0x3A;
+ debug_flush_timer = 0;
+ }
+ SREG = intr_state;
+}
diff --git a/tmk_core/protocol/pjrc/usb_debug.h b/tmk_core/protocol/pjrc/usb_debug.h
new file mode 100644
index 000000000..e70f4ca3a
--- /dev/null
+++ b/tmk_core/protocol/pjrc/usb_debug.h
@@ -0,0 +1,42 @@
+/* USB Keyboard Plus Debug Channel Example for Teensy USB Development Board
+ * http://www.pjrc.com/teensy/usb_keyboard.html
+ * Copyright (c) 2009 PJRC.COM, LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef USB_DEBUG_H
+#define USB_DEBUG_H 1
+
+#include <stdint.h>
+#include "usb.h"
+
+
+#define DEBUG_INTERFACE 2
+#define DEBUG_TX_ENDPOINT 3
+#define DEBUG_TX_SIZE 32
+#define DEBUG_TX_BUFFER EP_DOUBLE_BUFFER
+
+
+extern volatile uint8_t debug_flush_timer;
+
+
+void usb_debug_flush_output(void); // immediately transmit any buffered output
+
+#endif
diff --git a/tmk_core/protocol/pjrc/usb_extra.c b/tmk_core/protocol/pjrc/usb_extra.c
new file mode 100644
index 000000000..fe1f422c0
--- /dev/null
+++ b/tmk_core/protocol/pjrc/usb_extra.c
@@ -0,0 +1,70 @@
+/* USB Keyboard Plus Debug Channel Example for Teensy USB Development Board
+ * http://www.pjrc.com/teensy/usb_keyboard.html
+ * Copyright (c) 2009 PJRC.COM, LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <util/delay.h>
+#include <avr/interrupt.h>
+#include "host.h"
+#include "usb_extra.h"
+
+
+int8_t usb_extra_send(uint8_t report_id, uint16_t data)
+{
+ uint8_t intr_state, timeout;
+
+ if (!usb_configured()) return -1;
+ intr_state = SREG;
+ cli();
+ UENUM = EXTRA_ENDPOINT;
+ timeout = UDFNUML + 50;
+ while (1) {
+ // are we ready to transmit?
+ if (UEINTX & (1<<RWAL)) break;
+ SREG = intr_state;
+ // has the USB gone offline?
+ if (!usb_configured()) return -1;
+ // have we waited too long?
+ if (UDFNUML == timeout) return -1;
+ // get ready to try checking again
+ intr_state = SREG;
+ cli();
+ UENUM = EXTRA_ENDPOINT;
+ }
+
+ UEDATX = report_id;
+ UEDATX = data&0xFF;
+ UEDATX = (data>>8)&0xFF;
+
+ UEINTX = 0x3A;
+ SREG = intr_state;
+ return 0;
+}
+
+int8_t usb_extra_consumer_send(uint16_t bits)
+{
+ return usb_extra_send(REPORT_ID_CONSUMER, bits);
+}
+
+int8_t usb_extra_system_send(uint16_t bits)
+{
+ return usb_extra_send(REPORT_ID_SYSTEM, bits);
+}
diff --git a/tmk_core/protocol/pjrc/usb_extra.h b/tmk_core/protocol/pjrc/usb_extra.h
new file mode 100644
index 000000000..042ac4837
--- /dev/null
+++ b/tmk_core/protocol/pjrc/usb_extra.h
@@ -0,0 +1,46 @@
+/* USB Keyboard Plus Debug Channel Example for Teensy USB Development Board
+ * http://www.pjrc.com/teensy/usb_keyboard.html
+ * Copyright (c) 2009 PJRC.COM, LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef USB_EXTRA_H
+#define USB_EXTRA_H 1
+/*
+ * Enhanced keyboard features for Windows:
+ * Audio control and System control
+ *
+ * http://www.microsoft.com/whdc/archive/w2kbd.mspx
+ */
+
+#include <stdint.h>
+#include "usb.h"
+
+
+#define EXTRA_INTERFACE 3
+#define EXTRA_ENDPOINT 4
+#define EXTRA_SIZE 8
+#define EXTRA_BUFFER EP_DOUBLE_BUFFER
+
+
+int8_t usb_extra_consumer_send(uint16_t bits);
+int8_t usb_extra_system_send(uint16_t bits);
+
+#endif
diff --git a/tmk_core/protocol/pjrc/usb_keyboard.c b/tmk_core/protocol/pjrc/usb_keyboard.c
new file mode 100644
index 000000000..4b87b5d7b
--- /dev/null
+++ b/tmk_core/protocol/pjrc/usb_keyboard.c
@@ -0,0 +1,110 @@
+/* USB Keyboard Plus Debug Channel Example for Teensy USB Development Board
+ * http://www.pjrc.com/teensy/usb_keyboard.html
+ * Copyright (c) 2009 PJRC.COM, LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <avr/interrupt.h>
+#include <avr/pgmspace.h>
+#include "keycode.h"
+#include "usb_keyboard.h"
+#include "print.h"
+#include "debug.h"
+#include "util.h"
+#include "host.h"
+
+
+// protocol setting from the host. We use exactly the same report
+// either way, so this variable only stores the setting since we
+// are required to be able to report which setting is in use.
+uint8_t keyboard_protocol=1;
+
+// the idle configuration, how often we send the report to the
+// host (ms * 4) even when it hasn't changed
+// Windows and Linux set 0 while OS X sets 6(24ms) by SET_IDLE request.
+uint8_t keyboard_idle=125;
+
+// count until idle timeout
+uint8_t usb_keyboard_idle_count=0;
+
+// 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana
+volatile uint8_t usb_keyboard_leds=0;
+
+
+static inline int8_t send_report(report_keyboard_t *report, uint8_t endpoint, uint8_t keys_start, uint8_t keys_end);
+
+
+int8_t usb_keyboard_send_report(report_keyboard_t *report)
+{
+ int8_t result = 0;
+
+#ifdef NKRO_ENABLE
+ if (keyboard_nkro)
+ result = send_report(report, KBD2_ENDPOINT, 0, KBD2_SIZE);
+ else
+#endif
+ {
+ result = send_report(report, KBD_ENDPOINT, 0, KBD_SIZE);
+ }
+
+ if (result) return result;
+ usb_keyboard_idle_count = 0;
+ usb_keyboard_print_report(report);
+ return 0;
+}
+
+void usb_keyboard_print_report(report_keyboard_t *report)
+{
+ if (!debug_keyboard) return;
+ print("keys: ");
+ for (int i = 0; i < KEYBOARD_REPORT_KEYS; i++) { phex(report->keys[i]); print(" "); }
+ print(" mods: "); phex(report->mods); print("\n");
+}
+
+
+static inline int8_t send_report(report_keyboard_t *report, uint8_t endpoint, uint8_t keys_start, uint8_t keys_end)
+{
+ uint8_t intr_state, timeout;
+
+ if (!usb_configured()) return -1;
+ intr_state = SREG;
+ cli();
+ UENUM = endpoint;
+ timeout = UDFNUML + 50;
+ while (1) {
+ // are we ready to transmit?
+ if (UEINTX & (1<<RWAL)) break;
+ SREG = intr_state;
+ // has the USB gone offline?
+ if (!usb_configured()) return -1;
+ // have we waited too long?
+ if (UDFNUML == timeout) return -1;
+ // get ready to try checking again
+ intr_state = SREG;
+ cli();
+ UENUM = endpoint;
+ }
+ for (uint8_t i = keys_start; i < keys_end; i++) {
+ UEDATX = report->raw[i];
+ }
+ UEINTX = 0x3A;
+ SREG = intr_state;
+ return 0;
+}
diff --git a/tmk_core/protocol/pjrc/usb_keyboard.h b/tmk_core/protocol/pjrc/usb_keyboard.h
new file mode 100644
index 000000000..9b798e9a8
--- /dev/null
+++ b/tmk_core/protocol/pjrc/usb_keyboard.h
@@ -0,0 +1,40 @@
+/* USB Keyboard Plus Debug Channel Example for Teensy USB Development Board
+ * http://www.pjrc.com/teensy/usb_keyboard.html
+ * Copyright (c) 2009 PJRC.COM, LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef USB_KEYBOARD_H
+#define USB_KEYBOARD_H 1
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "usb.h"
+#include "host.h"
+
+
+extern uint8_t usb_keyboard_idle_count;
+extern volatile uint8_t usb_keyboard_leds;
+
+
+int8_t usb_keyboard_send_report(report_keyboard_t *report);
+void usb_keyboard_print_report(report_keyboard_t *report);
+
+#endif
diff --git a/tmk_core/protocol/pjrc/usb_mouse.c b/tmk_core/protocol/pjrc/usb_mouse.c
new file mode 100644
index 000000000..d81db756f
--- /dev/null
+++ b/tmk_core/protocol/pjrc/usb_mouse.c
@@ -0,0 +1,81 @@
+/* USB Mouse Plus Debug Channel Example for Teensy USB Development Board
+ * http://www.pjrc.com/teensy/usb_mouse.html
+ * Copyright (c) 2009 PJRC.COM, LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <avr/interrupt.h>
+#include <util/delay.h>
+#include "usb_mouse.h"
+#include "print.h"
+#include "debug.h"
+
+
+uint8_t usb_mouse_protocol=1;
+
+
+int8_t usb_mouse_send(int8_t x, int8_t y, int8_t wheel_v, int8_t wheel_h, uint8_t buttons)
+{
+ uint8_t intr_state, timeout;
+
+ if (!usb_configured()) return -1;
+ if (x == -128) x = -127;
+ if (y == -128) y = -127;
+ if (wheel_v == -128) wheel_v = -127;
+ if (wheel_h == -128) wheel_h = -127;
+ intr_state = SREG;
+ cli();
+ UENUM = MOUSE_ENDPOINT;
+ timeout = UDFNUML + 50;
+ while (1) {
+ // are we ready to transmit?
+ if (UEINTX & (1<<RWAL)) break;
+ SREG = intr_state;
+ // has the USB gone offline?
+ if (!usb_configured()) return -1;
+ // have we waited too long?
+ if (UDFNUML == timeout) return -1;
+ // get ready to try checking again
+ intr_state = SREG;
+ cli();
+ UENUM = MOUSE_ENDPOINT;
+ }
+ UEDATX = buttons;
+ UEDATX = x;
+ UEDATX = y;
+ if (usb_mouse_protocol) {
+ UEDATX = wheel_v;
+ UEDATX = wheel_h;
+ }
+
+ UEINTX = 0x3A;
+ SREG = intr_state;
+ return 0;
+}
+
+void usb_mouse_print(int8_t x, int8_t y, int8_t wheel_v, int8_t wheel_h, uint8_t buttons) {
+ if (!debug_mouse) return;
+ print("usb_mouse[btn|x y v h]: ");
+ phex(buttons); print("|");
+ phex(x); print(" ");
+ phex(y); print(" ");
+ phex(wheel_v); print(" ");
+ phex(wheel_h); print("\n");
+}
diff --git a/tmk_core/protocol/pjrc/usb_mouse.h b/tmk_core/protocol/pjrc/usb_mouse.h
new file mode 100644
index 000000000..ce26887c9
--- /dev/null
+++ b/tmk_core/protocol/pjrc/usb_mouse.h
@@ -0,0 +1,50 @@
+/* USB Mouse Plus Debug Channel Example for Teensy USB Development Board
+ * http://www.pjrc.com/teensy/usb_mouse.html
+ * Copyright (c) 2009 PJRC.COM, LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef USB_MOUSE_H
+#define USB_MOUSE_H 1
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "usb.h"
+
+
+#define MOUSE_INTERFACE 1
+#define MOUSE_ENDPOINT 2
+#define MOUSE_SIZE 8
+#define MOUSE_BUFFER EP_SINGLE_BUFFER
+
+#define MOUSE_BTN1 (1<<0)
+#define MOUSE_BTN2 (1<<1)
+#define MOUSE_BTN3 (1<<2)
+#define MOUSE_BTN4 (1<<3)
+#define MOUSE_BTN5 (1<<4)
+
+
+extern uint8_t usb_mouse_protocol;
+
+
+int8_t usb_mouse_send(int8_t x, int8_t y, int8_t wheel_v, int8_t wheel_h, uint8_t buttons);
+void usb_mouse_print(int8_t x, int8_t y, int8_t wheel_v, int8_t wheel_h, uint8_t buttons);
+
+#endif
diff --git a/tmk_core/protocol/ps2.h b/tmk_core/protocol/ps2.h
new file mode 100644
index 000000000..acde679cf
--- /dev/null
+++ b/tmk_core/protocol/ps2.h
@@ -0,0 +1,134 @@
+/*
+Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com>
+
+This software is licensed with a Modified BSD License.
+All of this is supposed to be Free Software, Open Source, DFSG-free,
+GPL-compatible, and OK to use in both free and proprietary applications.
+Additions and corrections to this file are welcome.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+* Neither the name of the copyright holders nor the names of
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef PS2_H
+#define PS2_H
+
+#include <stdbool.h>
+#include "wait.h"
+#include "ps2_io.h"
+#include "print.h"
+
+/*
+ * Primitive PS/2 Library for AVR
+ *
+ * PS/2 Resources
+ * --------------
+ * [1] The PS/2 Mouse/Keyboard Protocol
+ * http://www.computer-engineering.org/ps2protocol/
+ * Concise and thorough primer of PS/2 protocol.
+ *
+ * [2] Keyboard and Auxiliary Device Controller
+ * http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
+ * Signal Timing and Format
+ *
+ * [3] Keyboards(101- and 102-key)
+ * http://www.mcamafia.de/pdf/ibm_hitrc11.pdf
+ * Keyboard Layout, Scan Code Set, POR, and Commands.
+ *
+ * [4] PS/2 Reference Manuals
+ * http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
+ * Collection of IBM Personal System/2 documents.
+ *
+ * [5] TrackPoint Engineering Specifications for version 3E
+ * https://web.archive.org/web/20100526161812/http://wwwcssrv.almaden.ibm.com/trackpoint/download.html
+ */
+#define PS2_ACK 0xFA
+#define PS2_RESEND 0xFE
+#define PS2_SET_LED 0xED
+
+// TODO: error numbers
+#define PS2_ERR_NONE 0
+#define PS2_ERR_STARTBIT1 1
+#define PS2_ERR_STARTBIT2 2
+#define PS2_ERR_STARTBIT3 3
+#define PS2_ERR_PARITY 0x10
+#define PS2_ERR_NODATA 0x20
+
+#define PS2_LED_SCROLL_LOCK 0
+#define PS2_LED_NUM_LOCK 1
+#define PS2_LED_CAPS_LOCK 2
+
+
+extern uint8_t ps2_error;
+
+void ps2_host_init(void);
+uint8_t ps2_host_send(uint8_t data);
+uint8_t ps2_host_recv_response(void);
+uint8_t ps2_host_recv(void);
+void ps2_host_set_led(uint8_t usb_led);
+
+
+/*--------------------------------------------------------------------
+ * static functions
+ *------------------------------------------------------------------*/
+static inline uint16_t wait_clock_lo(uint16_t us)
+{
+ while (clock_in() && us) { asm(""); wait_us(1); us--; }
+ return us;
+}
+static inline uint16_t wait_clock_hi(uint16_t us)
+{
+ while (!clock_in() && us) { asm(""); wait_us(1); us--; }
+ return us;
+}
+static inline uint16_t wait_data_lo(uint16_t us)
+{
+ while (data_in() && us) { asm(""); wait_us(1); us--; }
+ return us;
+}
+static inline uint16_t wait_data_hi(uint16_t us)
+{
+ while (!data_in() && us) { asm(""); wait_us(1); us--; }
+ return us;
+}
+
+/* idle state that device can send */
+static inline void idle(void)
+{
+ clock_hi();
+ data_hi();
+}
+
+/* inhibit device to send */
+static inline void inhibit(void)
+{
+ clock_lo();
+ data_hi();
+}
+
+#endif
diff --git a/tmk_core/protocol/ps2_busywait.c b/tmk_core/protocol/ps2_busywait.c
new file mode 100644
index 000000000..a64933219
--- /dev/null
+++ b/tmk_core/protocol/ps2_busywait.c
@@ -0,0 +1,189 @@
+/*
+Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com>
+
+This software is licensed with a Modified BSD License.
+All of this is supposed to be Free Software, Open Source, DFSG-free,
+GPL-compatible, and OK to use in both free and proprietary applications.
+Additions and corrections to this file are welcome.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+* Neither the name of the copyright holders nor the names of
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * PS/2 protocol busywait version
+ */
+
+#include <stdbool.h>
+#include "wait.h"
+#include "ps2.h"
+#include "ps2_io.h"
+#include "debug.h"
+
+
+#define WAIT(stat, us, err) do { \
+ if (!wait_##stat(us)) { \
+ ps2_error = err; \
+ goto ERROR; \
+ } \
+} while (0)
+
+
+uint8_t ps2_error = PS2_ERR_NONE;
+
+
+void ps2_host_init(void)
+{
+ clock_init();
+ data_init();
+
+ // POR(150-2000ms) plus BAT(300-500ms) may take 2.5sec([3]p.20)
+ wait_ms(2500);
+
+ inhibit();
+}
+
+uint8_t ps2_host_send(uint8_t data)
+{
+ bool parity = true;
+ ps2_error = PS2_ERR_NONE;
+
+ /* terminate a transmission if we have */
+ inhibit();
+ wait_us(100); // 100us [4]p.13, [5]p.50
+
+ /* 'Request to Send' and Start bit */
+ data_lo();
+ clock_hi();
+ WAIT(clock_lo, 10000, 10); // 10ms [5]p.50
+
+ /* Data bit */
+ for (uint8_t i = 0; i < 8; i++) {
+ wait_us(15);
+ if (data&(1<<i)) {
+ parity = !parity;
+ data_hi();
+ } else {
+ data_lo();
+ }
+ WAIT(clock_hi, 50, 2);
+ WAIT(clock_lo, 50, 3);
+ }
+
+ /* Parity bit */
+ wait_us(15);
+ if (parity) { data_hi(); } else { data_lo(); }
+ WAIT(clock_hi, 50, 4);
+ WAIT(clock_lo, 50, 5);
+
+ /* Stop bit */
+ wait_us(15);
+ data_hi();
+
+ /* Ack */
+ WAIT(data_lo, 50, 6);
+ WAIT(clock_lo, 50, 7);
+
+ /* wait for idle state */
+ WAIT(clock_hi, 50, 8);
+ WAIT(data_hi, 50, 9);
+
+ inhibit();
+ return ps2_host_recv_response();
+ERROR:
+ inhibit();
+ return 0;
+}
+
+/* receive data when host want else inhibit communication */
+uint8_t ps2_host_recv_response(void)
+{
+ // Command may take 25ms/20ms at most([5]p.46, [3]p.21)
+ // 250 * 100us(wait for start bit in ps2_host_recv)
+ uint8_t data = 0;
+ uint8_t try = 250;
+ do {
+ data = ps2_host_recv();
+ } while (try-- && ps2_error);
+ return data;
+}
+
+/* called after start bit comes */
+uint8_t ps2_host_recv(void)
+{
+ uint8_t data = 0;
+ bool parity = true;
+ ps2_error = PS2_ERR_NONE;
+
+ /* release lines(idle state) */
+ idle();
+
+ /* start bit [1] */
+ WAIT(clock_lo, 100, 1); // TODO: this is enough?
+ WAIT(data_lo, 1, 2);
+ WAIT(clock_hi, 50, 3);
+
+ /* data [2-9] */
+ for (uint8_t i = 0; i < 8; i++) {
+ WAIT(clock_lo, 50, 4);
+ if (data_in()) {
+ parity = !parity;
+ data |= (1<<i);
+ }
+ WAIT(clock_hi, 50, 5);
+ }
+
+ /* parity [10] */
+ WAIT(clock_lo, 50, 6);
+ if (data_in() != parity) {
+ ps2_error = PS2_ERR_PARITY;
+ goto ERROR;
+ }
+ WAIT(clock_hi, 50, 7);
+
+ /* stop bit [11] */
+ WAIT(clock_lo, 50, 8);
+ WAIT(data_hi, 1, 9);
+ WAIT(clock_hi, 50, 10);
+
+ inhibit();
+ return data;
+ERROR:
+ if (ps2_error > PS2_ERR_STARTBIT3) {
+ xprintf("x%02X\n", ps2_error);
+ }
+ inhibit();
+ return 0;
+}
+
+/* send LED state to keyboard */
+void ps2_host_set_led(uint8_t led)
+{
+ ps2_host_send(0xED);
+ ps2_host_send(led);
+}
diff --git a/tmk_core/protocol/ps2_interrupt.c b/tmk_core/protocol/ps2_interrupt.c
new file mode 100644
index 000000000..8114442ba
--- /dev/null
+++ b/tmk_core/protocol/ps2_interrupt.c
@@ -0,0 +1,279 @@
+/*
+Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com>
+
+This software is licensed with a Modified BSD License.
+All of this is supposed to be Free Software, Open Source, DFSG-free,
+GPL-compatible, and OK to use in both free and proprietary applications.
+Additions and corrections to this file are welcome.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+* Neither the name of the copyright holders nor the names of
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * PS/2 protocol Pin interrupt version
+ */
+
+#include <stdbool.h>
+#include <avr/interrupt.h>
+#include <util/delay.h>
+#include "ps2.h"
+#include "ps2_io.h"
+#include "print.h"
+
+
+#define WAIT(stat, us, err) do { \
+ if (!wait_##stat(us)) { \
+ ps2_error = err; \
+ goto ERROR; \
+ } \
+} while (0)
+
+
+uint8_t ps2_error = PS2_ERR_NONE;
+
+
+static inline uint8_t pbuf_dequeue(void);
+static inline void pbuf_enqueue(uint8_t data);
+static inline bool pbuf_has_data(void);
+static inline void pbuf_clear(void);
+
+
+void ps2_host_init(void)
+{
+ idle();
+ PS2_INT_INIT();
+ PS2_INT_ON();
+ // POR(150-2000ms) plus BAT(300-500ms) may take 2.5sec([3]p.20)
+ //_delay_ms(2500);
+}
+
+uint8_t ps2_host_send(uint8_t data)
+{
+ bool parity = true;
+ ps2_error = PS2_ERR_NONE;
+
+ PS2_INT_OFF();
+
+ /* terminate a transmission if we have */
+ inhibit();
+ _delay_us(100); // 100us [4]p.13, [5]p.50
+
+ /* 'Request to Send' and Start bit */
+ data_lo();
+ clock_hi();
+ WAIT(clock_lo, 10000, 10); // 10ms [5]p.50
+
+ /* Data bit[2-9] */
+ for (uint8_t i = 0; i < 8; i++) {
+ _delay_us(15);
+ if (data&(1<<i)) {
+ parity = !parity;
+ data_hi();
+ } else {
+ data_lo();
+ }
+ WAIT(clock_hi, 50, 2);
+ WAIT(clock_lo, 50, 3);
+ }
+
+ /* Parity bit */
+ _delay_us(15);
+ if (parity) { data_hi(); } else { data_lo(); }
+ WAIT(clock_hi, 50, 4);
+ WAIT(clock_lo, 50, 5);
+
+ /* Stop bit */
+ _delay_us(15);
+ data_hi();
+
+ /* Ack */
+ WAIT(data_lo, 50, 6);
+ WAIT(clock_lo, 50, 7);
+
+ /* wait for idle state */
+ WAIT(clock_hi, 50, 8);
+ WAIT(data_hi, 50, 9);
+
+ idle();
+ PS2_INT_ON();
+ return ps2_host_recv_response();
+ERROR:
+ idle();
+ PS2_INT_ON();
+ return 0;
+}
+
+uint8_t ps2_host_recv_response(void)
+{
+ // Command may take 25ms/20ms at most([5]p.46, [3]p.21)
+ uint8_t retry = 25;
+ while (retry-- && !pbuf_has_data()) {
+ _delay_ms(1);
+ }
+ return pbuf_dequeue();
+}
+
+/* get data received by interrupt */
+uint8_t ps2_host_recv(void)
+{
+ if (pbuf_has_data()) {
+ ps2_error = PS2_ERR_NONE;
+ return pbuf_dequeue();
+ } else {
+ ps2_error = PS2_ERR_NODATA;
+ return 0;
+ }
+}
+
+ISR(PS2_INT_VECT)
+{
+ static enum {
+ INIT,
+ START,
+ BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7,
+ PARITY,
+ STOP,
+ } state = INIT;
+ static uint8_t data = 0;
+ static uint8_t parity = 1;
+
+ // TODO: abort if elapse 100us from previous interrupt
+
+ // return unless falling edge
+ if (clock_in()) {
+ goto RETURN;
+ }
+
+ state++;
+ switch (state) {
+ case START:
+ if (data_in())
+ goto ERROR;
+ break;
+ case BIT0:
+ case BIT1:
+ case BIT2:
+ case BIT3:
+ case BIT4:
+ case BIT5:
+ case BIT6:
+ case BIT7:
+ data >>= 1;
+ if (data_in()) {
+ data |= 0x80;
+ parity++;
+ }
+ break;
+ case PARITY:
+ if (data_in()) {
+ if (!(parity & 0x01))
+ goto ERROR;
+ } else {
+ if (parity & 0x01)
+ goto ERROR;
+ }
+ break;
+ case STOP:
+ if (!data_in())
+ goto ERROR;
+ pbuf_enqueue(data);
+ goto DONE;
+ break;
+ default:
+ goto ERROR;
+ }
+ goto RETURN;
+ERROR:
+ ps2_error = state;
+DONE:
+ state = INIT;
+ data = 0;
+ parity = 1;
+RETURN:
+ return;
+}
+
+/* send LED state to keyboard */
+void ps2_host_set_led(uint8_t led)
+{
+ ps2_host_send(0xED);
+ ps2_host_send(led);
+}
+
+
+/*--------------------------------------------------------------------
+ * Ring buffer to store scan codes from keyboard
+ *------------------------------------------------------------------*/
+#define PBUF_SIZE 32
+static uint8_t pbuf[PBUF_SIZE];
+static uint8_t pbuf_head = 0;
+static uint8_t pbuf_tail = 0;
+static inline void pbuf_enqueue(uint8_t data)
+{
+ uint8_t sreg = SREG;
+ cli();
+ uint8_t next = (pbuf_head + 1) % PBUF_SIZE;
+ if (next != pbuf_tail) {
+ pbuf[pbuf_head] = data;
+ pbuf_head = next;
+ } else {
+ print("pbuf: full\n");
+ }
+ SREG = sreg;
+}
+static inline uint8_t pbuf_dequeue(void)
+{
+ uint8_t val = 0;
+
+ uint8_t sreg = SREG;
+ cli();
+ if (pbuf_head != pbuf_tail) {
+ val = pbuf[pbuf_tail];
+ pbuf_tail = (pbuf_tail + 1) % PBUF_SIZE;
+ }
+ SREG = sreg;
+
+ return val;
+}
+static inline bool pbuf_has_data(void)
+{
+ uint8_t sreg = SREG;
+ cli();
+ bool has_data = (pbuf_head != pbuf_tail);
+ SREG = sreg;
+ return has_data;
+}
+static inline void pbuf_clear(void)
+{
+ uint8_t sreg = SREG;
+ cli();
+ pbuf_head = pbuf_tail = 0;
+ SREG = sreg;
+}
+
diff --git a/tmk_core/protocol/ps2_io.h b/tmk_core/protocol/ps2_io.h
new file mode 100644
index 000000000..a46a358e7
--- /dev/null
+++ b/tmk_core/protocol/ps2_io.h
@@ -0,0 +1,15 @@
+#ifndef PS2_IO_H
+#define PS2_IO_H
+
+
+void clock_init(void);
+void clock_lo(void);
+void clock_hi(void);
+bool clock_in(void);
+
+void data_init(void);
+void data_lo(void);
+void data_hi(void);
+bool data_in(void);
+
+#endif
diff --git a/tmk_core/protocol/ps2_io_avr.c b/tmk_core/protocol/ps2_io_avr.c
new file mode 100644
index 000000000..ed462345b
--- /dev/null
+++ b/tmk_core/protocol/ps2_io_avr.c
@@ -0,0 +1,75 @@
+#include <stdbool.h>
+#include <avr/io.h>
+#include <util/delay.h>
+
+/* Check port settings for clock and data line */
+#if !(defined(PS2_CLOCK_PORT) && \
+ defined(PS2_CLOCK_PIN) && \
+ defined(PS2_CLOCK_DDR) && \
+ defined(PS2_CLOCK_BIT))
+# error "PS/2 clock port setting is required in config.h"
+#endif
+
+#if !(defined(PS2_DATA_PORT) && \
+ defined(PS2_DATA_PIN) && \
+ defined(PS2_DATA_DDR) && \
+ defined(PS2_DATA_BIT))
+# error "PS/2 data port setting is required in config.h"
+#endif
+
+
+/*
+ * Clock
+ */
+void clock_init(void)
+{
+}
+
+void clock_lo(void)
+{
+ PS2_CLOCK_PORT &= ~(1<<PS2_CLOCK_BIT);
+ PS2_CLOCK_DDR |= (1<<PS2_CLOCK_BIT);
+}
+
+void clock_hi(void)
+{
+ /* input with pull up */
+ PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT);
+ PS2_CLOCK_PORT |= (1<<PS2_CLOCK_BIT);
+}
+
+bool clock_in(void)
+{
+ PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT);
+ PS2_CLOCK_PORT |= (1<<PS2_CLOCK_BIT);
+ _delay_us(1);
+ return PS2_CLOCK_PIN&(1<<PS2_CLOCK_BIT);
+}
+
+/*
+ * Data
+ */
+void data_init(void)
+{
+}
+
+void data_lo(void)
+{
+ PS2_DATA_PORT &= ~(1<<PS2_DATA_BIT);
+ PS2_DATA_DDR |= (1<<PS2_DATA_BIT);
+}
+
+void data_hi(void)
+{
+ /* input with pull up */
+ PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT);
+ PS2_DATA_PORT |= (1<<PS2_DATA_BIT);
+}
+
+bool data_in(void)
+{
+ PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT);
+ PS2_DATA_PORT |= (1<<PS2_DATA_BIT);
+ _delay_us(1);
+ return PS2_DATA_PIN&(1<<PS2_DATA_BIT);
+}
diff --git a/tmk_core/protocol/ps2_io_mbed.c b/tmk_core/protocol/ps2_io_mbed.c
new file mode 100644
index 000000000..83bdcef7f
--- /dev/null
+++ b/tmk_core/protocol/ps2_io_mbed.c
@@ -0,0 +1,60 @@
+#include <stdbool.h>
+#include "ps2_io.h"
+#include "gpio_api.h"
+
+
+static gpio_t clock;
+static gpio_t data;
+
+/*
+ * Clock
+ */
+void clock_init(void)
+{
+ gpio_init(&clock, P0_9);
+ gpio_mode(&clock, OpenDrain|PullNone);
+}
+
+void clock_lo(void)
+{
+ gpio_dir(&clock, PIN_OUTPUT);
+ gpio_write(&clock, 0);
+}
+void clock_hi(void)
+{
+ gpio_dir(&clock, PIN_OUTPUT);
+ gpio_write(&clock, 1);
+}
+
+bool clock_in(void)
+{
+ gpio_dir(&clock, PIN_INPUT);
+ return gpio_read(&clock);
+}
+
+/*
+ * Data
+ */
+void data_init(void)
+{
+ gpio_init(&data, P0_8);
+ gpio_mode(&data, OpenDrain|PullNone);
+}
+
+void data_lo(void)
+{
+ gpio_dir(&data, PIN_OUTPUT);
+ gpio_write(&data, 0);
+}
+
+void data_hi(void)
+{
+ gpio_dir(&data, PIN_OUTPUT);
+ gpio_write(&data, 1);
+}
+
+bool data_in(void)
+{
+ gpio_dir(&data, PIN_INPUT);
+ return gpio_read(&data);
+}
diff --git a/tmk_core/protocol/ps2_mouse.c b/tmk_core/protocol/ps2_mouse.c
new file mode 100644
index 000000000..c3e8b3c1c
--- /dev/null
+++ b/tmk_core/protocol/ps2_mouse.c
@@ -0,0 +1,220 @@
+/*
+Copyright 2011,2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdbool.h>
+#include<avr/io.h>
+#include<util/delay.h>
+#include "ps2.h"
+#include "ps2_mouse.h"
+#include "report.h"
+#include "host.h"
+#include "timer.h"
+#include "print.h"
+#include "debug.h"
+
+
+static report_mouse_t mouse_report = {};
+
+
+static void print_usb_data(void);
+
+
+/* supports only 3 button mouse at this time */
+uint8_t ps2_mouse_init(void) {
+ uint8_t rcv;
+
+ ps2_host_init();
+
+ _delay_ms(1000); // wait for powering up
+
+ // send Reset
+ rcv = ps2_host_send(0xFF);
+ print("ps2_mouse_init: send Reset: ");
+ phex(rcv); phex(ps2_error); print("\n");
+
+ // read completion code of BAT
+ rcv = ps2_host_recv_response();
+ print("ps2_mouse_init: read BAT: ");
+ phex(rcv); phex(ps2_error); print("\n");
+
+ // read Device ID
+ rcv = ps2_host_recv_response();
+ print("ps2_mouse_init: read DevID: ");
+ phex(rcv); phex(ps2_error); print("\n");
+
+ // send Set Remote mode
+ rcv = ps2_host_send(0xF0);
+ print("ps2_mouse_init: send 0xF0: ");
+ phex(rcv); phex(ps2_error); print("\n");
+
+ return 0;
+}
+
+#define X_IS_NEG (mouse_report.buttons & (1<<PS2_MOUSE_X_SIGN))
+#define Y_IS_NEG (mouse_report.buttons & (1<<PS2_MOUSE_Y_SIGN))
+#define X_IS_OVF (mouse_report.buttons & (1<<PS2_MOUSE_X_OVFLW))
+#define Y_IS_OVF (mouse_report.buttons & (1<<PS2_MOUSE_Y_OVFLW))
+void ps2_mouse_task(void)
+{
+ enum { SCROLL_NONE, SCROLL_BTN, SCROLL_SENT };
+ static uint8_t scroll_state = SCROLL_NONE;
+ static uint8_t buttons_prev = 0;
+
+ /* receives packet from mouse */
+ uint8_t rcv;
+ rcv = ps2_host_send(PS2_MOUSE_READ_DATA);
+ if (rcv == PS2_ACK) {
+ mouse_report.buttons = ps2_host_recv_response();
+ mouse_report.x = ps2_host_recv_response();
+ mouse_report.y = ps2_host_recv_response();
+ } else {
+ if (debug_mouse) print("ps2_mouse: fail to get mouse packet\n");
+ return;
+ }
+ xprintf("%ud ", timer_read());
+ print("ps2_mouse raw: [");
+ phex(mouse_report.buttons); print("|");
+ print_hex8((uint8_t)mouse_report.x); print(" ");
+ print_hex8((uint8_t)mouse_report.y); print("]\n");
+
+ /* if mouse moves or buttons state changes */
+ if (mouse_report.x || mouse_report.y ||
+ ((mouse_report.buttons ^ buttons_prev) & PS2_MOUSE_BTN_MASK)) {
+
+#ifdef PS2_MOUSE_DEBUG
+ print("ps2_mouse raw: [");
+ phex(mouse_report.buttons); print("|");
+ print_hex8((uint8_t)mouse_report.x); print(" ");
+ print_hex8((uint8_t)mouse_report.y); print("]\n");
+#endif
+
+ buttons_prev = mouse_report.buttons;
+
+ // PS/2 mouse data is '9-bit integer'(-256 to 255) which is comprised of sign-bit and 8-bit value.
+ // bit: 8 7 ... 0
+ // sign \8-bit/
+ //
+ // Meanwhile USB HID mouse indicates 8bit data(-127 to 127), note that -128 is not used.
+ //
+ // This converts PS/2 data into HID value. Use only -127-127 out of PS/2 9-bit.
+ mouse_report.x = X_IS_NEG ?
+ ((!X_IS_OVF && -127 <= mouse_report.x && mouse_report.x <= -1) ? mouse_report.x : -127) :
+ ((!X_IS_OVF && 0 <= mouse_report.x && mouse_report.x <= 127) ? mouse_report.x : 127);
+ mouse_report.y = Y_IS_NEG ?
+ ((!Y_IS_OVF && -127 <= mouse_report.y && mouse_report.y <= -1) ? mouse_report.y : -127) :
+ ((!Y_IS_OVF && 0 <= mouse_report.y && mouse_report.y <= 127) ? mouse_report.y : 127);
+
+ // remove sign and overflow flags
+ mouse_report.buttons &= PS2_MOUSE_BTN_MASK;
+
+ // invert coordinate of y to conform to USB HID mouse
+ mouse_report.y = -mouse_report.y;
+
+
+#if PS2_MOUSE_SCROLL_BTN_MASK
+ static uint16_t scroll_button_time = 0;
+ if ((mouse_report.buttons & (PS2_MOUSE_SCROLL_BTN_MASK)) == (PS2_MOUSE_SCROLL_BTN_MASK)) {
+ if (scroll_state == SCROLL_NONE) {
+ scroll_button_time = timer_read();
+ scroll_state = SCROLL_BTN;
+ }
+
+ // doesn't send Scroll Button
+ //mouse_report.buttons &= ~(PS2_MOUSE_SCROLL_BTN_MASK);
+
+ if (mouse_report.x || mouse_report.y) {
+ scroll_state = SCROLL_SENT;
+
+ mouse_report.v = -mouse_report.y/(PS2_MOUSE_SCROLL_DIVISOR_V);
+ mouse_report.h = mouse_report.x/(PS2_MOUSE_SCROLL_DIVISOR_H);
+ mouse_report.x = 0;
+ mouse_report.y = 0;
+ //host_mouse_send(&mouse_report);
+ }
+ }
+ else if ((mouse_report.buttons & (PS2_MOUSE_SCROLL_BTN_MASK)) == 0) {
+#if PS2_MOUSE_SCROLL_BTN_SEND
+ if (scroll_state == SCROLL_BTN &&
+ TIMER_DIFF_16(timer_read(), scroll_button_time) < PS2_MOUSE_SCROLL_BTN_SEND) {
+ // send Scroll Button(down and up at once) when not scrolled
+ mouse_report.buttons |= (PS2_MOUSE_SCROLL_BTN_MASK);
+ host_mouse_send(&mouse_report);
+ _delay_ms(100);
+ mouse_report.buttons &= ~(PS2_MOUSE_SCROLL_BTN_MASK);
+ }
+#endif
+ scroll_state = SCROLL_NONE;
+ }
+ // doesn't send Scroll Button
+ mouse_report.buttons &= ~(PS2_MOUSE_SCROLL_BTN_MASK);
+#endif
+
+
+ host_mouse_send(&mouse_report);
+ print_usb_data();
+ }
+ // clear report
+ mouse_report.x = 0;
+ mouse_report.y = 0;
+ mouse_report.v = 0;
+ mouse_report.h = 0;
+ mouse_report.buttons = 0;
+}
+
+static void print_usb_data(void)
+{
+ if (!debug_mouse) return;
+ print("ps2_mouse usb: [");
+ phex(mouse_report.buttons); print("|");
+ print_hex8((uint8_t)mouse_report.x); print(" ");
+ print_hex8((uint8_t)mouse_report.y); print(" ");
+ print_hex8((uint8_t)mouse_report.v); print(" ");
+ print_hex8((uint8_t)mouse_report.h); print("]\n");
+}
+
+
+/* PS/2 Mouse Synopsis
+ * http://www.computer-engineering.org/ps2mouse/
+ *
+ * Command:
+ * 0xFF: Reset
+ * 0xF6: Set Defaults Sampling; rate=100, resolution=4cnt/mm, scaling=1:1, reporting=disabled
+ * 0xF5: Disable Data Reporting
+ * 0xF4: Enable Data Reporting
+ * 0xF3: Set Sample Rate
+ * 0xF2: Get Device ID
+ * 0xF0: Set Remote Mode
+ * 0xEB: Read Data
+ * 0xEA: Set Stream Mode
+ * 0xE9: Status Request
+ * 0xE8: Set Resolution
+ * 0xE7: Set Scaling 2:1
+ * 0xE6: Set Scaling 1:1
+ *
+ * Mode:
+ * Stream Mode: devices sends the data when it changs its state
+ * Remote Mode: host polls the data periodically
+ *
+ * This code uses Remote Mode and polls the data with Read Data(0xEB).
+ *
+ * Data format:
+ * byte|7 6 5 4 3 2 1 0
+ * ----+--------------------------------------------------------------
+ * 0|Yovflw Xovflw Ysign Xsign 1 Middle Right Left
+ * 1| X movement
+ * 2| Y movement
+ */
diff --git a/tmk_core/protocol/ps2_mouse.h b/tmk_core/protocol/ps2_mouse.h
new file mode 100644
index 000000000..27d9790d4
--- /dev/null
+++ b/tmk_core/protocol/ps2_mouse.h
@@ -0,0 +1,66 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef PS2_MOUSE_H
+#define PS2_MOUSE_H
+
+#include <stdbool.h>
+
+#define PS2_MOUSE_READ_DATA 0xEB
+
+/*
+ * Data format:
+ * byte|7 6 5 4 3 2 1 0
+ * ----+--------------------------------------------------------------
+ * 0|Yovflw Xovflw Ysign Xsign 1 Middle Right Left
+ * 1| X movement(0-255)
+ * 2| Y movement(0-255)
+ */
+#define PS2_MOUSE_BTN_MASK 0x07
+#define PS2_MOUSE_BTN_LEFT 0
+#define PS2_MOUSE_BTN_RIGHT 1
+#define PS2_MOUSE_BTN_MIDDLE 2
+#define PS2_MOUSE_X_SIGN 4
+#define PS2_MOUSE_Y_SIGN 5
+#define PS2_MOUSE_X_OVFLW 6
+#define PS2_MOUSE_Y_OVFLW 7
+
+
+/*
+ * Scroll by mouse move with pressing button
+ */
+/* mouse button to start scrolling; set 0 to disable scroll */
+#ifndef PS2_MOUSE_SCROLL_BTN_MASK
+#define PS2_MOUSE_SCROLL_BTN_MASK (1<<PS2_MOUSE_BTN_MIDDLE)
+#endif
+/* send button event when button is released within this value(ms); set 0 to disable */
+#ifndef PS2_MOUSE_SCROLL_BTN_SEND
+#define PS2_MOUSE_SCROLL_BTN_SEND 300
+#endif
+/* divide virtical and horizontal mouse move by this to convert to scroll move */
+#ifndef PS2_MOUSE_SCROLL_DIVISOR_V
+#define PS2_MOUSE_SCROLL_DIVISOR_V 2
+#endif
+#ifndef PS2_MOUSE_SCROLL_DIVISOR_H
+#define PS2_MOUSE_SCROLL_DIVISOR_H 2
+#endif
+
+
+uint8_t ps2_mouse_init(void);
+void ps2_mouse_task(void);
+
+#endif
diff --git a/tmk_core/protocol/ps2_usart.c b/tmk_core/protocol/ps2_usart.c
new file mode 100644
index 000000000..6936ca7b8
--- /dev/null
+++ b/tmk_core/protocol/ps2_usart.c
@@ -0,0 +1,223 @@
+/*
+Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com>
+
+This software is licensed with a Modified BSD License.
+All of this is supposed to be Free Software, Open Source, DFSG-free,
+GPL-compatible, and OK to use in both free and proprietary applications.
+Additions and corrections to this file are welcome.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+* Neither the name of the copyright holders nor the names of
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/*
+ * PS/2 protocol USART version
+ */
+
+#include <stdbool.h>
+#include <avr/interrupt.h>
+#include <util/delay.h>
+#include "ps2.h"
+#include "ps2_io.h"
+#include "print.h"
+
+
+#define WAIT(stat, us, err) do { \
+ if (!wait_##stat(us)) { \
+ ps2_error = err; \
+ goto ERROR; \
+ } \
+} while (0)
+
+
+uint8_t ps2_error = PS2_ERR_NONE;
+
+
+static inline uint8_t pbuf_dequeue(void);
+static inline void pbuf_enqueue(uint8_t data);
+static inline bool pbuf_has_data(void);
+static inline void pbuf_clear(void);
+
+
+void ps2_host_init(void)
+{
+ idle(); // without this many USART errors occur when cable is disconnected
+ PS2_USART_INIT();
+ PS2_USART_RX_INT_ON();
+ // POR(150-2000ms) plus BAT(300-500ms) may take 2.5sec([3]p.20)
+ //_delay_ms(2500);
+}
+
+uint8_t ps2_host_send(uint8_t data)
+{
+ bool parity = true;
+ ps2_error = PS2_ERR_NONE;
+
+ PS2_USART_OFF();
+
+ /* terminate a transmission if we have */
+ inhibit();
+ _delay_us(100); // [4]p.13
+
+ /* 'Request to Send' and Start bit */
+ data_lo();
+ clock_hi();
+ WAIT(clock_lo, 10000, 10); // 10ms [5]p.50
+
+ /* Data bit[2-9] */
+ for (uint8_t i = 0; i < 8; i++) {
+ _delay_us(15);
+ if (data&(1<<i)) {
+ parity = !parity;
+ data_hi();
+ } else {
+ data_lo();
+ }
+ WAIT(clock_hi, 50, 2);
+ WAIT(clock_lo, 50, 3);
+ }
+
+ /* Parity bit */
+ _delay_us(15);
+ if (parity) { data_hi(); } else { data_lo(); }
+ WAIT(clock_hi, 50, 4);
+ WAIT(clock_lo, 50, 5);
+
+ /* Stop bit */
+ _delay_us(15);
+ data_hi();
+
+ /* Ack */
+ WAIT(data_lo, 50, 6);
+ WAIT(clock_lo, 50, 7);
+
+ /* wait for idle state */
+ WAIT(clock_hi, 50, 8);
+ WAIT(data_hi, 50, 9);
+
+ idle();
+ PS2_USART_INIT();
+ PS2_USART_RX_INT_ON();
+ return ps2_host_recv_response();
+ERROR:
+ idle();
+ PS2_USART_INIT();
+ PS2_USART_RX_INT_ON();
+ return 0;
+}
+
+uint8_t ps2_host_recv_response(void)
+{
+ // Command may take 25ms/20ms at most([5]p.46, [3]p.21)
+ uint8_t retry = 25;
+ while (retry-- && !pbuf_has_data()) {
+ _delay_ms(1);
+ }
+ return pbuf_dequeue();
+}
+
+uint8_t ps2_host_recv(void)
+{
+ if (pbuf_has_data()) {
+ ps2_error = PS2_ERR_NONE;
+ return pbuf_dequeue();
+ } else {
+ ps2_error = PS2_ERR_NODATA;
+ return 0;
+ }
+}
+
+ISR(PS2_USART_RX_VECT)
+{
+ // TODO: request RESEND when error occurs?
+ uint8_t error = PS2_USART_ERROR; // USART error should be read before data
+ uint8_t data = PS2_USART_RX_DATA;
+ if (!error) {
+ pbuf_enqueue(data);
+ } else {
+ xprintf("PS2 USART error: %02X data: %02X\n", error, data);
+ }
+}
+
+/* send LED state to keyboard */
+void ps2_host_set_led(uint8_t led)
+{
+ ps2_host_send(0xED);
+ ps2_host_send(led);
+}
+
+
+/*--------------------------------------------------------------------
+ * Ring buffer to store scan codes from keyboard
+ *------------------------------------------------------------------*/
+#define PBUF_SIZE 32
+static uint8_t pbuf[PBUF_SIZE];
+static uint8_t pbuf_head = 0;
+static uint8_t pbuf_tail = 0;
+static inline void pbuf_enqueue(uint8_t data)
+{
+ uint8_t sreg = SREG;
+ cli();
+ uint8_t next = (pbuf_head + 1) % PBUF_SIZE;
+ if (next != pbuf_tail) {
+ pbuf[pbuf_head] = data;
+ pbuf_head = next;
+ } else {
+ print("pbuf: full\n");
+ }
+ SREG = sreg;
+}
+static inline uint8_t pbuf_dequeue(void)
+{
+ uint8_t val = 0;
+
+ uint8_t sreg = SREG;
+ cli();
+ if (pbuf_head != pbuf_tail) {
+ val = pbuf[pbuf_tail];
+ pbuf_tail = (pbuf_tail + 1) % PBUF_SIZE;
+ }
+ SREG = sreg;
+
+ return val;
+}
+static inline bool pbuf_has_data(void)
+{
+ uint8_t sreg = SREG;
+ cli();
+ bool has_data = (pbuf_head != pbuf_tail);
+ SREG = sreg;
+ return has_data;
+}
+static inline void pbuf_clear(void)
+{
+ uint8_t sreg = SREG;
+ cli();
+ pbuf_head = pbuf_tail = 0;
+ SREG = sreg;
+}
diff --git a/tmk_core/protocol/serial.h b/tmk_core/protocol/serial.h
new file mode 100644
index 000000000..96913c867
--- /dev/null
+++ b/tmk_core/protocol/serial.h
@@ -0,0 +1,47 @@
+/*
+Copyright 2012 Jun WAKO <wakojun@gmail.com>
+
+This software is licensed with a Modified BSD License.
+All of this is supposed to be Free Software, Open Source, DFSG-free,
+GPL-compatible, and OK to use in both free and proprietary applications.
+Additions and corrections to this file are welcome.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+* Neither the name of the copyright holders nor the names of
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef SERIAL_H
+#define SERIAL_H
+
+/* host role */
+void serial_init(void);
+uint8_t serial_recv(void);
+int16_t serial_recv2(void);
+void serial_send(uint8_t data);
+
+#endif
diff --git a/tmk_core/protocol/serial_mouse.h b/tmk_core/protocol/serial_mouse.h
new file mode 100644
index 000000000..226314fc0
--- /dev/null
+++ b/tmk_core/protocol/serial_mouse.h
@@ -0,0 +1,33 @@
+/*
+Copyright 2014 Robin Haberkorn <robin.haberkorn@googlemail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef SERIAL_MOUSE_H
+#define SERIAL_MOUSE_H
+
+#include <stdint.h>
+
+#include "serial.h"
+
+static inline uint8_t serial_mouse_init(void)
+{
+ serial_init();
+ return 0;
+}
+
+void serial_mouse_task(void);
+
+#endif
diff --git a/tmk_core/protocol/serial_mouse_microsoft.c b/tmk_core/protocol/serial_mouse_microsoft.c
new file mode 100644
index 000000000..ab74b7cdd
--- /dev/null
+++ b/tmk_core/protocol/serial_mouse_microsoft.c
@@ -0,0 +1,124 @@
+/*
+Copyright 2014 Robin Haberkorn <robin.haberkorn@googlemail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdint.h>
+#include <avr/io.h>
+#include <util/delay.h>
+
+#include "serial.h"
+#include "serial_mouse.h"
+#include "report.h"
+#include "host.h"
+#include "timer.h"
+#include "print.h"
+#include "debug.h"
+
+#ifdef MAX
+#undef MAX
+#endif
+#define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
+
+static void print_usb_data(const report_mouse_t *report);
+
+void serial_mouse_task(void)
+{
+ /* 3 byte ring buffer */
+ static uint8_t buffer[3];
+ static int buffer_cur = 0;
+
+ static report_mouse_t report = {};
+
+ int16_t rcv;
+
+ rcv = serial_recv2();
+ if (rcv < 0)
+ /* no new data */
+ return;
+
+ if (debug_mouse)
+ xprintf("serial_mouse: byte: %04X\n", rcv);
+
+ /*
+ * If bit 6 is one, this signals the beginning
+ * of a 3 byte sequence/packet.
+ */
+ if (rcv & (1 << 6))
+ buffer_cur = 0;
+
+ buffer[buffer_cur] = (uint8_t)rcv;
+
+ if (buffer_cur == 0 && buffer[buffer_cur] == 0x20) {
+ /*
+ * Logitech extension: This must be a follow-up on
+ * the last 3-byte packet signaling a middle button click
+ */
+ report.buttons |= MOUSE_BTN3;
+ report.x = report.y = 0;
+
+ print_usb_data(&report);
+ host_mouse_send(&report);
+ return;
+ }
+
+ buffer_cur++;
+
+ if (buffer_cur < 3)
+ return;
+ buffer_cur = 0;
+
+ /*
+ * parse 3 byte packet.
+ * NOTE: We only get a complete packet
+ * if the mouse moved or the button states
+ * change.
+ */
+ report.buttons = 0;
+ if (buffer[0] & (1 << 5))
+ report.buttons |= MOUSE_BTN1;
+ if (buffer[0] & (1 << 4))
+ report.buttons |= MOUSE_BTN2;
+
+ report.x = (buffer[0] << 6) | buffer[1];
+ report.y = ((buffer[0] << 4) & 0xC0) | buffer[2];
+
+ /* USB HID uses values from -127 to 127 only */
+ report.x = MAX(report.x, -127);
+ report.y = MAX(report.y, -127);
+
+#if 0
+ if (!report.buttons && !report.x && !report.y) {
+ /*
+ * Microsoft extension: Middle mouse button pressed
+ * FIXME: I don't know how exactly this extension works.
+ */
+ report.buttons |= MOUSE_BTN3;
+ }
+#endif
+
+ print_usb_data(&report);
+ host_mouse_send(&report);
+}
+
+static void print_usb_data(const report_mouse_t *report)
+{
+ if (!debug_mouse)
+ return;
+
+ xprintf("serial_mouse usb: [%02X|%d %d %d %d]\n",
+ report->buttons, report->x, report->y,
+ report->v, report->h);
+}
diff --git a/tmk_core/protocol/serial_mouse_mousesystems.c b/tmk_core/protocol/serial_mouse_mousesystems.c
new file mode 100644
index 000000000..cfe899621
--- /dev/null
+++ b/tmk_core/protocol/serial_mouse_mousesystems.c
@@ -0,0 +1,131 @@
+/*
+Copyright 2014 Robin Haberkorn <robin.haberkorn@googlemail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdint.h>
+#include <avr/io.h>
+#include <util/delay.h>
+
+#include "serial.h"
+#include "serial_mouse.h"
+#include "report.h"
+#include "host.h"
+#include "timer.h"
+#include "print.h"
+#include "debug.h"
+
+#ifdef MAX
+#undef MAX
+#endif
+#define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
+
+//#define SERIAL_MOUSE_CENTER_SCROLL
+
+static void print_usb_data(const report_mouse_t *report);
+
+void serial_mouse_task(void)
+{
+ /* 5 byte ring buffer */
+ static uint8_t buffer[5];
+ static int buffer_cur = 0;
+
+ int16_t rcv;
+
+ report_mouse_t report = {0, 0, 0, 0, 0};
+
+ rcv = serial_recv2();
+ if (rcv < 0)
+ /* no new data */
+ return;
+
+ if (debug_mouse)
+ xprintf("serial_mouse: byte: %04X\n", rcv);
+
+ /*
+ * Synchronization: mouse(4) says that all
+ * bytes but the first one in the packet have
+ * bit 7 == 0, but this is untrue.
+ * Therefore we discard all bytes up to the
+ * first one with the characteristic bit pattern.
+ */
+ if (buffer_cur == 0 && (rcv >> 3) != 0x10)
+ return;
+
+ buffer[buffer_cur++] = (uint8_t)rcv;
+
+ if (buffer_cur < 5)
+ return;
+ buffer_cur = 0;
+
+#ifdef SERIAL_MOUSE_CENTER_SCROLL
+ if ((buffer[0] & 0x7) == 0x5 && (buffer[1] || buffer[2])) {
+ /* USB HID uses only values from -127 to 127 */
+ report.h = MAX((int8_t)buffer[1], -127);
+ report.v = MAX((int8_t)buffer[2], -127);
+
+ print_usb_data(&report);
+ host_mouse_send(&report);
+
+ if (buffer[3] || buffer[4]) {
+ report.h = MAX((int8_t)buffer[3], -127);
+ report.v = MAX((int8_t)buffer[4], -127);
+
+ print_usb_data(&report);
+ host_mouse_send(&report);
+ }
+
+ return;
+ }
+#endif
+
+ /*
+ * parse 5 byte packet.
+ * NOTE: We only get a complete packet
+ * if the mouse moved or the button states
+ * change.
+ */
+ if (!(buffer[0] & (1 << 2)))
+ report.buttons |= MOUSE_BTN1;
+ if (!(buffer[0] & (1 << 1)))
+ report.buttons |= MOUSE_BTN3;
+ if (!(buffer[0] & (1 << 0)))
+ report.buttons |= MOUSE_BTN2;
+
+ /* USB HID uses only values from -127 to 127 */
+ report.x = MAX((int8_t)buffer[1], -127);
+ report.y = MAX(-(int8_t)buffer[2], -127);
+
+ print_usb_data(&report);
+ host_mouse_send(&report);
+
+ if (buffer[3] || buffer[4]) {
+ report.x = MAX((int8_t)buffer[3], -127);
+ report.y = MAX(-(int8_t)buffer[4], -127);
+
+ print_usb_data(&report);
+ host_mouse_send(&report);
+ }
+}
+
+static void print_usb_data(const report_mouse_t *report)
+{
+ if (!debug_mouse)
+ return;
+
+ xprintf("serial_mouse usb: [%02X|%d %d %d %d]\n",
+ report->buttons, report->x, report->y,
+ report->v, report->h);
+}
diff --git a/tmk_core/protocol/serial_soft.c b/tmk_core/protocol/serial_soft.c
new file mode 100644
index 000000000..44822b7e4
--- /dev/null
+++ b/tmk_core/protocol/serial_soft.c
@@ -0,0 +1,240 @@
+/*
+Copyright 2012 Jun WAKO <wakojun@gmail.com>
+
+This software is licensed with a Modified BSD License.
+All of this is supposed to be Free Software, Open Source, DFSG-free,
+GPL-compatible, and OK to use in both free and proprietary applications.
+Additions and corrections to this file are welcome.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+* Neither the name of the copyright holders nor the names of
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdbool.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <util/delay.h>
+#include "serial.h"
+
+/*
+ * Stupid Inefficient Busy-wait Software Serial
+ * which is still useful for negative logic signal like Sun protocol
+ * if it is not supported by hardware UART.
+ *
+ * TODO: delay is not accurate enough. Instruction cycle should be counted and inline assemby is needed.
+ */
+
+#define WAIT_US (1000000L/SERIAL_SOFT_BAUD)
+
+#ifdef SERIAL_SOFT_LOGIC_NEGATIVE
+ #define SERIAL_SOFT_RXD_IN() !(SERIAL_SOFT_RXD_READ())
+ #define SERIAL_SOFT_TXD_ON() SERIAL_SOFT_TXD_LO()
+ #define SERIAL_SOFT_TXD_OFF() SERIAL_SOFT_TXD_HI()
+#else
+ #define SERIAL_SOFT_RXD_IN() !!(SERIAL_SOFT_RXD_READ())
+ #define SERIAL_SOFT_TXD_ON() SERIAL_SOFT_TXD_HI()
+ #define SERIAL_SOFT_TXD_OFF() SERIAL_SOFT_TXD_LO()
+#endif
+
+#ifdef SERIAL_SOFT_PARITY_EVEN
+ #define SERIAL_SOFT_PARITY_VAL 0
+#elif defined(SERIAL_SOFT_PARITY_ODD)
+ #define SERIAL_SOFT_PARITY_VAL 1
+#endif
+
+/* debug for signal timing, see debug pin with oscilloscope */
+#define SERIAL_SOFT_DEBUG
+#ifdef SERIAL_SOFT_DEBUG
+ #define SERIAL_SOFT_DEBUG_INIT() (DDRD |= 1<<7)
+ #define SERIAL_SOFT_DEBUG_TGL() (PORTD ^= 1<<7)
+#else
+ #define SERIAL_SOFT_DEBUG_INIT()
+ #define SERIAL_SOFT_DEBUG_TGL()
+#endif
+
+
+void serial_init(void)
+{
+ SERIAL_SOFT_DEBUG_INIT();
+
+ SERIAL_SOFT_RXD_INIT();
+ SERIAL_SOFT_TXD_INIT();
+}
+
+/* RX ring buffer */
+#define RBUF_SIZE 8
+static uint8_t rbuf[RBUF_SIZE];
+static uint8_t rbuf_head = 0;
+static uint8_t rbuf_tail = 0;
+
+
+uint8_t serial_recv(void)
+{
+ uint8_t data = 0;
+ if (rbuf_head == rbuf_tail) {
+ return 0;
+ }
+
+ data = rbuf[rbuf_tail];
+ rbuf_tail = (rbuf_tail + 1) % RBUF_SIZE;
+ return data;
+}
+
+int16_t serial_recv2(void)
+{
+ uint8_t data = 0;
+ if (rbuf_head == rbuf_tail) {
+ return -1;
+ }
+
+ data = rbuf[rbuf_tail];
+ rbuf_tail = (rbuf_tail + 1) % RBUF_SIZE;
+ return data;
+}
+
+void serial_send(uint8_t data)
+{
+ /* signal state: IDLE: ON, START: OFF, STOP: ON, DATA0: OFF, DATA1: ON */
+
+#ifdef SERIAL_SOFT_BIT_ORDER_MSB
+ #ifdef SERIAL_SOFT_DATA_7BIT
+ uint8_t mask = 0x40;
+ #else
+ uint8_t mask = 0x80;
+ #endif
+#else
+ uint8_t mask = 0x01;
+#endif
+
+ uint8_t parity = 0;
+
+ /* start bit */
+ SERIAL_SOFT_TXD_OFF();
+ _delay_us(WAIT_US);
+
+#ifdef SERIAL_SOFT_DATA_7BIT
+ while (mask&0x7F) {
+#else
+ while (mask&0xFF) {
+#endif
+ if (data&mask) {
+ SERIAL_SOFT_TXD_ON();
+ parity ^= 1;
+ } else {
+ SERIAL_SOFT_TXD_OFF();
+ }
+ _delay_us(WAIT_US);
+
+#ifdef SERIAL_SOFT_BIT_ORDER_MSB
+ mask >>= 1;
+#else
+ mask <<= 1;
+#endif
+ }
+
+#if defined(SERIAL_SOFT_PARITY_EVEN) || defined(SERIAL_SOFT_PARITY_ODD)
+ /* to center of parity bit */
+ if (parity != SERIAL_SOFT_PARITY_VAL) {
+ SERIAL_SOFT_TXD_ON();
+ } else {
+ SERIAL_SOFT_TXD_OFF();
+ }
+ _delay_us(WAIT_US);
+#endif
+
+ /* stop bit */
+ SERIAL_SOFT_TXD_ON();
+ _delay_us(WAIT_US);
+}
+
+/* detect edge of start bit */
+ISR(SERIAL_SOFT_RXD_VECT)
+{
+ SERIAL_SOFT_DEBUG_TGL();
+ SERIAL_SOFT_RXD_INT_ENTER()
+
+ uint8_t data = 0;
+
+#ifdef SERIAL_SOFT_BIT_ORDER_MSB
+ #ifdef SERIAL_SOFT_DATA_7BIT
+ uint8_t mask = 0x40;
+ #else
+ uint8_t mask = 0x80;
+ #endif
+#else
+ uint8_t mask = 0x01;
+#endif
+
+ uint8_t parity = 0;
+
+ /* to center of start bit */
+ _delay_us(WAIT_US/2);
+ SERIAL_SOFT_DEBUG_TGL();
+ do {
+ /* to center of next bit */
+ _delay_us(WAIT_US);
+
+ SERIAL_SOFT_DEBUG_TGL();
+ if (SERIAL_SOFT_RXD_IN()) {
+ data |= mask;
+ parity ^= 1;
+ }
+#ifdef SERIAL_SOFT_BIT_ORDER_MSB
+ mask >>= 1;
+#else
+ mask <<= 1;
+#endif
+#ifdef SERIAL_SOFT_DATA_7BIT
+ } while (mask&0x7F);
+#else
+ } while (mask&0xFF);
+#endif
+
+#if defined(SERIAL_SOFT_PARITY_EVEN) || defined(SERIAL_SOFT_PARITY_ODD)
+ /* to center of parity bit */
+ _delay_us(WAIT_US);
+ if (SERIAL_SOFT_RXD_IN()) { parity ^= 1; }
+ SERIAL_SOFT_DEBUG_TGL();
+#endif
+
+ /* to center of stop bit */
+ _delay_us(WAIT_US);
+
+ uint8_t next = (rbuf_head + 1) % RBUF_SIZE;
+#if defined(SERIAL_SOFT_PARITY_EVEN) || defined(SERIAL_SOFT_PARITY_ODD)
+ if ((parity == SERIAL_SOFT_PARITY_VAL) && next != rbuf_tail) {
+#else
+ if (next != rbuf_tail) {
+#endif
+ rbuf[rbuf_head] = data;
+ rbuf_head = next;
+ }
+
+ SERIAL_SOFT_RXD_INT_EXIT();
+ SERIAL_SOFT_DEBUG_TGL();
+}
diff --git a/tmk_core/protocol/serial_uart.c b/tmk_core/protocol/serial_uart.c
new file mode 100644
index 000000000..35df27fd6
--- /dev/null
+++ b/tmk_core/protocol/serial_uart.c
@@ -0,0 +1,112 @@
+/*
+Copyright 2013 Jun WAKO <wakojun@gmail.com>
+
+This software is licensed with a Modified BSD License.
+All of this is supposed to be Free Software, Open Source, DFSG-free,
+GPL-compatible, and OK to use in both free and proprietary applications.
+Additions and corrections to this file are welcome.
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+* Neither the name of the copyright holders nor the names of
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdbool.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include "serial.h"
+
+
+#if defined(SERIAL_UART_RTS_LO) && defined(SERIAL_UART_RTS_HI)
+ // Buffer state
+ // Empty: RBUF_SPACE == RBUF_SIZE(head==tail)
+ // Last 1 space: RBUF_SPACE == 2
+ // Full: RBUF_SPACE == 1(last cell of rbuf be never used.)
+ #define RBUF_SPACE() (rbuf_head < rbuf_tail ? (rbuf_tail - rbuf_head) : (RBUF_SIZE - rbuf_head + rbuf_tail))
+ // allow to send
+ #define rbuf_check_rts_lo() do { if (RBUF_SPACE() > 2) SERIAL_UART_RTS_LO(); } while (0)
+ // prohibit to send
+ #define rbuf_check_rts_hi() do { if (RBUF_SPACE() <= 2) SERIAL_UART_RTS_HI(); } while (0)
+#else
+ #define rbuf_check_rts_lo()
+ #define rbuf_check_rts_hi()
+#endif
+
+
+void serial_init(void)
+{
+ SERIAL_UART_INIT();
+}
+
+// RX ring buffer
+#define RBUF_SIZE 256
+static uint8_t rbuf[RBUF_SIZE];
+static uint8_t rbuf_head = 0;
+static uint8_t rbuf_tail = 0;
+
+uint8_t serial_recv(void)
+{
+ uint8_t data = 0;
+ if (rbuf_head == rbuf_tail) {
+ return 0;
+ }
+
+ data = rbuf[rbuf_tail];
+ rbuf_tail = (rbuf_tail + 1) % RBUF_SIZE;
+ rbuf_check_rts_lo();
+ return data;
+}
+
+int16_t serial_recv2(void)
+{
+ uint8_t data = 0;
+ if (rbuf_head == rbuf_tail) {
+ return -1;
+ }
+
+ data = rbuf[rbuf_tail];
+ rbuf_tail = (rbuf_tail + 1) % RBUF_SIZE;
+ rbuf_check_rts_lo();
+ return data;
+}
+
+void serial_send(uint8_t data)
+{
+ while (!SERIAL_UART_TXD_READY) ;
+ SERIAL_UART_DATA = data;
+}
+
+// USART RX complete interrupt
+ISR(SERIAL_UART_RXD_VECT)
+{
+ uint8_t next = (rbuf_head + 1) % RBUF_SIZE;
+ if (next != rbuf_tail) {
+ rbuf[rbuf_head] = SERIAL_UART_DATA;
+ rbuf_head = next;
+ }
+ rbuf_check_rts_hi();
+}
diff --git a/tmk_core/protocol/usb_hid.mk b/tmk_core/protocol/usb_hid.mk
new file mode 100644
index 000000000..1f79bda3b
--- /dev/null
+++ b/tmk_core/protocol/usb_hid.mk
@@ -0,0 +1,74 @@
+USB_HID_DIR = protocol/usb_hid
+
+
+#
+# USB Host Shield
+#
+USB_HOST_SHIELD_DIR = $(USB_HID_DIR)/USB_Host_Shield_2.0
+USB_HOST_SHIELD_SRC = \
+ $(USB_HOST_SHIELD_DIR)/Usb.cpp \
+ $(USB_HOST_SHIELD_DIR)/hid.cpp \
+ $(USB_HOST_SHIELD_DIR)/usbhub.cpp \
+ $(USB_HOST_SHIELD_DIR)/parsetools.cpp \
+ $(USB_HOST_SHIELD_DIR)/message.cpp
+
+
+
+#
+# Arduino
+#
+ARDUINO_DIR = $(USB_HID_DIR)/arduino-1.0.1
+ARDUINO_CORES_DIR = $(ARDUINO_DIR)/cores/arduino
+ARDUINO_CORES_SRC = \
+ $(ARDUINO_CORES_DIR)/Print.cpp \
+ $(ARDUINO_CORES_DIR)/Stream.cpp
+
+# replaced with override_Serial.c
+# $(ARDUINO_CORES_DIR)/CDC.cpp \
+# $(ARDUINO_CORES_DIR)/HID.cpp \
+# $(ARDUINO_CORES_DIR)/USBCore.cpp \
+
+# replaced with override_wiring.c and common/timer.c
+# $(ARDUINO_CORES_DIR)/wiring.c \
+
+
+
+#
+# HID parser
+#
+SRC += $(USB_HID_DIR)/parser.cpp
+
+# replace arduino/CDC.cpp
+SRC += $(USB_HID_DIR)/override_Serial.cpp
+
+# replace arduino/wiring.c
+SRC += $(USB_HID_DIR)/override_wiring.c
+SRC += common/avr/timer.c
+
+SRC += $(USB_HOST_SHIELD_SRC)
+SRC += $(ARDUINO_CORES_SRC)
+
+
+OPT_DEFS += -DARDUINO=101
+# Arduino USBCore needs USB_VID and USB_PID.
+#OPT_DEFS += -DARDUINO=101 -DUSB_VID=0x2341 -DUSB_PID=0x8036
+
+
+
+#
+# Search Path
+#
+VPATH += $(TMK_DIR)/$(USB_HID_DIR)
+VPATH += $(TMK_DIR)/$(USB_HOST_SHIELD_DIR)
+
+# for #include "Arduino.h"
+VPATH += $(TMK_DIR)/$(ARDUINO_CORES_DIR)
+
+# for #include "pins_arduino.h"
+VPATH += $(TMK_DIR)/$(ARDUINO_DIR)/variants/leonardo
+
+# ad hoc workaround for compile problem on Windows:
+# Windows doesn't know difference between common/print.h and arduino/Print.h.
+# On Linux no problem.
+# Change file name common/print.h to console.h ?
+VPATH := $(TMK_DIR)/common $(VPATH)
diff --git a/tmk_core/protocol/usb_hid/README b/tmk_core/protocol/usb_hid/README
new file mode 100644
index 000000000..0d2efc2aa
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/README
@@ -0,0 +1,47 @@
+USB HID protocol
+================
+Host side of USB HID keyboard protocol implementation.
+Only standard HID Boot mode is supported at this time. This means most of normal keyboards are supported while proprietary >6KRO and NKRO is not.
+
+Third party Libraries
+---------------------
+USB_Host_Shield_2.0
+ Circuits@Home repository is git-submoduled. Do git submodule init & update to get the content.
+ https://github.com/felis/USB_Host_Shield_2.0
+
+arduino-1.0.1
+ Arduino files copied from:
+ https://github.com/arduino/Arduino/hardware/arduino/{cores,variants}
+
+
+Test build
+----------
+In test directory;
+ $ make
+ $ DEV=/dev/ttyACM0 make program
+
+You can see HID keyboard reports on debug output.
+
+
+Restriction and Bug
+-------------------
+Not supported/confirmed yet.
+ Hub, suspend, keyboard LED
+
+Switching power on VBUS:
+ To power reset device.
+ http://www.circuitsathome.com/camera-control/simulating-cable-disconnect-on-usb-host-shield-2-0
+ This is needed for a device which are not initilized with 'USB Bus Reset'(long SE0)
+
+Can't bus-reset a keyboard which already attached on bus properly.
+ Slow start up of Leonardo's bootloader causes this?
+ Need to unplug/plug a keyboard after firmware starts up.
+ MAX3421E doesn't work SAMPLEBUS well to know whether device connected or not.
+
+Keyboard with other endpoints than boot keyboard may go wrong.
+ On my keyboard with mouse key the converter locks up when using mouse key function.
+
+Can't compile on Windows filesystem.
+ On Linux no problem.
+ Windows doesn't know difference between common/print.h and arduino/Print.h.
+ Change file name common/print.h to console.h ?
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/.gitattributes b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/.gitattributes
new file mode 100644
index 000000000..6238b035a
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/.gitattributes
@@ -0,0 +1,23 @@
+# Auto detect text files and perform LF normalization
+* text=auto
+* text eol=lf
+
+# Custom for Visual Studio
+*.cs diff=csharp
+*.sln merge=union
+*.csproj merge=union
+*.vbproj merge=union
+*.fsproj merge=union
+*.dbproj merge=union
+
+# Standard to msysgit
+*.doc diff=astextplain
+*.DOC diff=astextplain
+*.docx diff=astextplain
+*.DOCX diff=astextplain
+*.dot diff=astextplain
+*.DOT diff=astextplain
+*.pdf diff=astextplain
+*.PDF diff=astextplain
+*.rtf diff=astextplain
+*.RTF diff=astextplain
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/.gitignore b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/.gitignore
new file mode 100644
index 000000000..7e69f457b
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/.gitignore
@@ -0,0 +1,4 @@
+*.bak
+*.zip
+*.rar
+build/ \ No newline at end of file
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/.gitmodules b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/.gitmodules
new file mode 100644
index 000000000..32a0783a8
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/.gitmodules
@@ -0,0 +1,12 @@
+[submodule "examples/testusbhostFAT/generic_storage"]
+ path = examples/testusbhostFAT/generic_storage
+ url = https://github.com/xxxajk/generic_storage
+[submodule "examples/testusbhostFAT/xmem2"]
+ path = examples/testusbhostFAT/xmem2
+ url = https://github.com/xxxajk/xmem2
+[submodule "examples/testusbhostFAT/Arduino_Makefile_master"]
+ path = examples/testusbhostFAT/Arduino_Makefile_master
+ url = https://github.com/xxxajk/Arduino_Makefile_master
+[submodule "examples/testusbhostFAT/RTClib"]
+ path = examples/testusbhostFAT/RTClib
+ url = https://github.com/xxxajk/RTClib
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTD.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTD.cpp
new file mode 100755
index 000000000..bcfba14b2
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTD.cpp
@@ -0,0 +1,1364 @@
+/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
+
+ This software may be distributed and modified under the terms of the GNU
+ General Public License version 2 (GPL2) as published by the Free Software
+ Foundation and appearing in the file GPL2.TXT included in the packaging of
+ this file. Please note that GPL2 Section 2[b] requires that all works based
+ on this software must also be made publicly available under the terms of
+ the GPL2 ("Copyleft").
+
+ Contact information
+ -------------------
+
+ Kristian Lauszus, TKJ Electronics
+ Web : http://www.tkjelectronics.com
+ e-mail : kristianl@tkjelectronics.com
+ */
+
+#include "BTD.h"
+// To enable serial debugging see "settings.h"
+//#define EXTRADEBUG // Uncomment to get even more debugging data
+
+const uint8_t BTD::BTD_CONTROL_PIPE = 0;
+const uint8_t BTD::BTD_EVENT_PIPE = 1;
+const uint8_t BTD::BTD_DATAIN_PIPE = 2;
+const uint8_t BTD::BTD_DATAOUT_PIPE = 3;
+
+BTD::BTD(USB *p) :
+connectToWii(false),
+pairWithWii(false),
+connectToHIDDevice(false),
+pairWithHIDDevice(false),
+pUsb(p), // Pointer to USB class instance - mandatory
+bAddress(0), // Device address - mandatory
+bNumEP(1), // If config descriptor needs to be parsed
+qNextPollTime(0), // Reset NextPollTime
+pollInterval(0),
+bPollEnable(false) // Don't start polling before dongle is connected
+{
+ for(uint8_t i = 0; i < BTD_NUM_SERVICES; i++)
+ btService[i] = NULL;
+
+ Initialize(); // Set all variables, endpoint structs etc. to default values
+
+ if(pUsb) // Register in USB subsystem
+ pUsb->RegisterDeviceClass(this); // Set devConfig[] entry
+}
+
+uint8_t BTD::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {
+ const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
+ uint8_t buf[constBufSize];
+ USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
+ uint8_t rcode;
+ UsbDevice *p = NULL;
+ EpInfo *oldep_ptr = NULL;
+
+ Initialize(); // Set all variables, endpoint structs etc. to default values
+
+ AddressPool &addrPool = pUsb->GetAddressPool(); // Get memory address of USB device address pool
+#ifdef EXTRADEBUG
+ Notify(PSTR("\r\nBTD ConfigureDevice"), 0x80);
+#endif
+
+ if(bAddress) { // Check if address has already been assigned to an instance
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nAddress in use"), 0x80);
+#endif
+ return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
+ }
+
+ p = addrPool.GetUsbDevicePtr(0); // Get pointer to pseudo device with address 0 assigned
+ if(!p) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nAddress not found"), 0x80);
+#endif
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+ }
+
+ if(!p->epinfo) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nepinfo is null"), 0x80);
+#endif
+ return USB_ERROR_EPINFO_IS_NULL;
+ }
+
+ oldep_ptr = p->epinfo; // Save old pointer to EP_RECORD of address 0
+ p->epinfo = epInfo; // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
+ p->lowspeed = lowspeed;
+ rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data
+
+ p->epinfo = oldep_ptr; // Restore p->epinfo
+
+ if(rcode)
+ goto FailGetDevDescr;
+
+ bAddress = addrPool.AllocAddress(parent, false, port); // Allocate new address according to device class
+
+ if(!bAddress) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nOut of address space"), 0x80);
+#endif
+ return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
+ }
+
+ epInfo[0].maxPktSize = udd->bMaxPacketSize0; // Extract Max Packet Size from device descriptor
+ epInfo[1].epAddr = udd->bNumConfigurations; // Steal and abuse from epInfo structure to save memory
+
+ VID = udd->idVendor;
+ PID = udd->idProduct;
+
+ return USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET;
+
+FailGetDevDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailGetDevDescr(rcode);
+#endif
+ if(rcode != hrJERR)
+ rcode = USB_ERROR_FailGetDevDescr;
+ Release();
+ return rcode;
+};
+
+uint8_t BTD::Init(uint8_t parent, uint8_t port, bool lowspeed) {
+ uint8_t rcode;
+ uint8_t num_of_conf = epInfo[1].epAddr; // Number of configurations
+ epInfo[1].epAddr = 0;
+
+ AddressPool &addrPool = pUsb->GetAddressPool();
+#ifdef EXTRADEBUG
+ Notify(PSTR("\r\nBTD Init"), 0x80);
+#endif
+ UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record
+
+ if(!p) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nAddress not found"), 0x80);
+#endif
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+ }
+
+ delay(300); // Assign new address to the device
+
+ rcode = pUsb->setAddr(0, 0, bAddress); // Assign new address to the device
+ if(rcode) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nsetAddr: "), 0x80);
+ D_PrintHex<uint8_t > (rcode, 0x80);
+#endif
+ p->lowspeed = false;
+ goto Fail;
+ }
+#ifdef EXTRADEBUG
+ Notify(PSTR("\r\nAddr: "), 0x80);
+ D_PrintHex<uint8_t > (bAddress, 0x80);
+#endif
+
+ p->lowspeed = false;
+
+ p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record
+ if(!p) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nAddress not found"), 0x80);
+#endif
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+ }
+
+ p->lowspeed = lowspeed;
+
+ rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); // Assign epInfo to epinfo pointer - only EP0 is known
+ if(rcode)
+ goto FailSetDevTblEntry;
+
+ if(VID == PS3_VID && (PID == PS3_PID || PID == PS3NAVIGATION_PID || PID == PS3MOVE_PID)) {
+ delay(100);
+ rcode = pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, 1); // We only need the Control endpoint, so we don't have to initialize the other endpoints of device
+ if(rcode)
+ goto FailSetConfDescr;
+
+#ifdef DEBUG_USB_HOST
+ if(PID == PS3_PID || PID == PS3NAVIGATION_PID) {
+ if(PID == PS3_PID)
+ Notify(PSTR("\r\nDualshock 3 Controller Connected"), 0x80);
+ else // It must be a navigation controller
+ Notify(PSTR("\r\nNavigation Controller Connected"), 0x80);
+ } else // It must be a Motion controller
+ Notify(PSTR("\r\nMotion Controller Connected"), 0x80);
+#endif
+
+ if(my_bdaddr[0] == 0x00 && my_bdaddr[1] == 0x00 && my_bdaddr[2] == 0x00 && my_bdaddr[3] == 0x00 && my_bdaddr[4] == 0x00 && my_bdaddr[5] == 0x00) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nPlease plug in the dongle before trying to pair with the PS3 Controller\r\nor set the Bluetooth address in the constructor of the PS3BT class"), 0x80);
+#endif
+ } else {
+ if(PID == PS3_PID || PID == PS3NAVIGATION_PID)
+ setBdaddr(my_bdaddr); // Set internal Bluetooth address
+ else
+ setMoveBdaddr(my_bdaddr); // Set internal Bluetooth address
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nBluetooth Address was set to: "), 0x80);
+ for(int8_t i = 5; i > 0; i--) {
+ D_PrintHex<uint8_t > (my_bdaddr[i], 0x80);
+ Notify(PSTR(":"), 0x80);
+ }
+ D_PrintHex<uint8_t > (my_bdaddr[0], 0x80);
+#endif
+ }
+
+ pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, 0); // Reset configuration value
+ pUsb->setAddr(bAddress, 0, 0); // Reset address
+ Release(); // Release device
+ return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; // Return
+ } else {
+ // Check if attached device is a Bluetooth dongle and fill endpoint data structure
+ // First interface in the configuration must have Bluetooth assigned Class/Subclass/Protocol
+ // And 3 endpoints - interrupt-IN, bulk-IN, bulk-OUT, not necessarily in this order
+ for(uint8_t i = 0; i < num_of_conf; i++) {
+ if(VID == IOGEAR_GBU521_VID && PID == IOGEAR_GBU521_PID) {
+ ConfigDescParser<USB_CLASS_VENDOR_SPECIFIC, WI_SUBCLASS_RF, WI_PROTOCOL_BT, CP_MASK_COMPARE_ALL> confDescrParser(this); // Needed for the IOGEAR GBU521
+ rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
+ } else {
+ ConfigDescParser<USB_CLASS_WIRELESS_CTRL, WI_SUBCLASS_RF, WI_PROTOCOL_BT, CP_MASK_COMPARE_ALL> confDescrParser(this);
+ rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
+ }
+ if(rcode) // Check error code
+ goto FailGetConfDescr;
+ if(bNumEP >= BTD_MAX_ENDPOINTS) // All endpoints extracted
+ break;
+ }
+
+ if(bNumEP < BTD_MAX_ENDPOINTS)
+ goto FailUnknownDevice;
+
+ // Assign epInfo to epinfo pointer - this time all 3 endpoins
+ rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
+ if(rcode)
+ goto FailSetDevTblEntry;
+
+ // Set Configuration Value
+ rcode = pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, bConfNum);
+ if(rcode)
+ goto FailSetConfDescr;
+
+ hci_num_reset_loops = 100; // only loop 100 times before trying to send the hci reset command
+ hci_counter = 0;
+ hci_state = HCI_INIT_STATE;
+ watingForConnection = false;
+ bPollEnable = true;
+
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nBluetooth Dongle Initialized"), 0x80);
+#endif
+ }
+ return 0; // Successful configuration
+
+ /* Diagnostic messages */
+FailSetDevTblEntry:
+#ifdef DEBUG_USB_HOST
+ NotifyFailSetDevTblEntry();
+ goto Fail;
+#endif
+
+FailGetConfDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailGetConfDescr();
+ goto Fail;
+#endif
+
+FailSetConfDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailSetConfDescr();
+#endif
+ goto Fail;
+
+FailUnknownDevice:
+#ifdef DEBUG_USB_HOST
+ NotifyFailUnknownDevice(VID, PID);
+#endif
+ pUsb->setAddr(bAddress, 0, 0); // Reset address
+ rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
+Fail:
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nBTD Init Failed, error code: "), 0x80);
+ NotifyFail(rcode);
+#endif
+ Release();
+ return rcode;
+}
+
+void BTD::Initialize() {
+ uint8_t i;
+ for(i = 0; i < BTD_MAX_ENDPOINTS; i++) {
+ epInfo[i].epAddr = 0;
+ epInfo[i].maxPktSize = (i) ? 0 : 8;
+ epInfo[i].epAttribs = 0;
+ epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
+ }
+ for(i = 0; i < BTD_NUM_SERVICES; i++) {
+ if(btService[i])
+ btService[i]->Reset(); // Reset all Bluetooth services
+ }
+
+ connectToWii = false;
+ incomingWii = false;
+ connectToHIDDevice = false;
+ incomingHIDDevice = false;
+ incomingPS4 = false;
+ bAddress = 0; // Clear device address
+ bNumEP = 1; // Must have to be reset to 1
+ qNextPollTime = 0; // Reset next poll time
+ pollInterval = 0;
+ bPollEnable = false; // Don't start polling before dongle is connected
+}
+
+/* Extracts interrupt-IN, bulk-IN, bulk-OUT endpoint information from config descriptor */
+void BTD::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {
+ //ErrorMessage<uint8_t>(PSTR("Conf.Val"),conf);
+ //ErrorMessage<uint8_t>(PSTR("Iface Num"),iface);
+ //ErrorMessage<uint8_t>(PSTR("Alt.Set"),alt);
+
+ if(alt) // Wrong interface - by BT spec, no alt setting
+ return;
+
+ bConfNum = conf;
+ uint8_t index;
+
+ if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) { // Interrupt In endpoint found
+ index = BTD_EVENT_PIPE;
+ epInfo[index].bmNakPower = USB_NAK_NOWAIT;
+ } else {
+ if((pep->bmAttributes & 0x02) == 2) // Bulk endpoint found
+ index = ((pep->bEndpointAddress & 0x80) == 0x80) ? BTD_DATAIN_PIPE : BTD_DATAOUT_PIPE;
+ else
+ return;
+ }
+
+ // Fill the rest of endpoint data structure
+ epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
+ epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
+#ifdef EXTRADEBUG
+ PrintEndpointDescriptor(pep);
+#endif
+ if(pollInterval < pep->bInterval) // Set the polling interval as the largest polling interval obtained from endpoints
+ pollInterval = pep->bInterval;
+ bNumEP++;
+}
+
+void BTD::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) {
+#ifdef EXTRADEBUG
+ Notify(PSTR("\r\nEndpoint descriptor:"), 0x80);
+ Notify(PSTR("\r\nLength:\t\t"), 0x80);
+ D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
+ Notify(PSTR("\r\nType:\t\t"), 0x80);
+ D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
+ Notify(PSTR("\r\nAddress:\t"), 0x80);
+ D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
+ Notify(PSTR("\r\nAttributes:\t"), 0x80);
+ D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
+ Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
+ D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
+ Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
+ D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
+#endif
+}
+
+/* Performs a cleanup after failed Init() attempt */
+uint8_t BTD::Release() {
+ Initialize(); // Set all variables, endpoint structs etc. to default values
+ pUsb->GetAddressPool().FreeAddress(bAddress);
+ return 0;
+}
+
+uint8_t BTD::Poll() {
+ if(!bPollEnable)
+ return 0;
+ if((long)(millis() - qNextPollTime) >= 0L) { // Don't poll if shorter than polling interval
+ qNextPollTime = millis() + pollInterval; // Set new poll time
+ HCI_event_task(); // Poll the HCI event pipe
+ HCI_task(); // HCI state machine
+ ACL_event_task(); // Poll the ACL input pipe too
+ }
+ return 0;
+}
+
+void BTD::disconnect() {
+ for(uint8_t i = 0; i < BTD_NUM_SERVICES; i++)
+ if(btService[i])
+ btService[i]->disconnect();
+};
+
+void BTD::HCI_event_task() {
+ uint16_t length = BULK_MAXPKTSIZE; // Request more than 16 bytes anyway, the inTransfer routine will take care of this
+ uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ BTD_EVENT_PIPE ].epAddr, &length, hcibuf); // Input on endpoint 1
+
+ if(!rcode || rcode == hrNAK) { // Check for errors
+ switch(hcibuf[0]) { // Switch on event type
+ case EV_COMMAND_COMPLETE:
+ if(!hcibuf[5]) { // Check if command succeeded
+ hci_set_flag(HCI_FLAG_CMD_COMPLETE); // Set command complete flag
+ if((hcibuf[3] == 0x01) && (hcibuf[4] == 0x10)) { // Parameters from read local version information
+ hci_version = hcibuf[6]; // Used to check if it supports 2.0+EDR - see http://www.bluetooth.org/Technical/AssignedNumbers/hci.htm
+ hci_set_flag(HCI_FLAG_READ_VERSION);
+ } else if((hcibuf[3] == 0x09) && (hcibuf[4] == 0x10)) { // Parameters from read local bluetooth address
+ for(uint8_t i = 0; i < 6; i++)
+ my_bdaddr[i] = hcibuf[6 + i];
+ hci_set_flag(HCI_FLAG_READ_BDADDR);
+ }
+ }
+ break;
+
+ case EV_COMMAND_STATUS:
+ if(hcibuf[2]) { // Show status on serial if not OK
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nHCI Command Failed: "), 0x80);
+ D_PrintHex<uint8_t > (hcibuf[2], 0x80);
+#endif
+ }
+ break;
+
+ case EV_INQUIRY_COMPLETE:
+ if(inquiry_counter >= 5 && (pairWithWii || pairWithHIDDevice)) {
+ inquiry_counter = 0;
+#ifdef DEBUG_USB_HOST
+ if(pairWithWii)
+ Notify(PSTR("\r\nCouldn't find Wiimote"), 0x80);
+ else
+ Notify(PSTR("\r\nCouldn't find HID device"), 0x80);
+#endif
+ connectToWii = false;
+ pairWithWii = false;
+ connectToHIDDevice = false;
+ pairWithHIDDevice = false;
+ hci_state = HCI_SCANNING_STATE;
+ }
+ inquiry_counter++;
+ break;
+
+ case EV_INQUIRY_RESULT:
+ if(hcibuf[2]) { // Check that there is more than zero responses
+#ifdef EXTRADEBUG
+ Notify(PSTR("\r\nNumber of responses: "), 0x80);
+ Notify(hcibuf[2], 0x80);
+#endif
+ for(uint8_t i = 0; i < hcibuf[2]; i++) {
+ uint8_t offset = 8 * hcibuf[2] + 3 * i;
+
+ for(uint8_t j = 0; j < 3; j++)
+ classOfDevice[j] = hcibuf[j + 4 + offset];
+
+#ifdef EXTRADEBUG
+ Notify(PSTR("\r\nClass of device: "), 0x80);
+ D_PrintHex<uint8_t > (classOfDevice[2], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (classOfDevice[1], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (classOfDevice[0], 0x80);
+#endif
+
+ if(pairWithWii && classOfDevice[2] == 0x00 && (classOfDevice[1] & 0x05) && (classOfDevice[0] & 0x0C)) { // See http://wiibrew.org/wiki/Wiimote#SDP_information
+ checkRemoteName = true; // Check remote name to distinguish between the different controllers
+
+ for(uint8_t j = 0; j < 6; j++)
+ disc_bdaddr[j] = hcibuf[j + 3 + 6 * i];
+
+ hci_set_flag(HCI_FLAG_DEVICE_FOUND);
+ break;
+ } else if(pairWithHIDDevice && (classOfDevice[1] & 0x05) && (classOfDevice[0] & 0xC8)) { // Check if it is a mouse, keyboard or a gamepad - see: http://bluetooth-pentest.narod.ru/software/bluetooth_class_of_device-service_generator.html
+#ifdef DEBUG_USB_HOST
+ if(classOfDevice[0] & 0x80)
+ Notify(PSTR("\r\nMouse found"), 0x80);
+ if(classOfDevice[0] & 0x40)
+ Notify(PSTR("\r\nKeyboard found"), 0x80);
+ if(classOfDevice[0] & 0x08)
+ Notify(PSTR("\r\nGamepad found"), 0x80);
+#endif
+
+ for(uint8_t j = 0; j < 6; j++)
+ disc_bdaddr[j] = hcibuf[j + 3 + 6 * i];
+
+ hci_set_flag(HCI_FLAG_DEVICE_FOUND);
+ break;
+ }
+ }
+ }
+ break;
+
+ case EV_CONNECT_COMPLETE:
+ hci_set_flag(HCI_FLAG_CONNECT_EVENT);
+ if(!hcibuf[2]) { // Check if connected OK
+#ifdef EXTRADEBUG
+ Notify(PSTR("\r\nConnection established"), 0x80);
+#endif
+ hci_handle = hcibuf[3] | ((hcibuf[4] & 0x0F) << 8); // Store the handle for the ACL connection
+ hci_set_flag(HCI_FLAG_CONNECT_COMPLETE); // Set connection complete flag
+ } else {
+ hci_state = HCI_CHECK_DEVICE_SERVICE;
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nConnection Failed: "), 0x80);
+ D_PrintHex<uint8_t > (hcibuf[2], 0x80);
+#endif
+ }
+ break;
+
+ case EV_DISCONNECT_COMPLETE:
+ if(!hcibuf[2]) { // Check if disconnected OK
+ hci_set_flag(HCI_FLAG_DISCONNECT_COMPLETE); // Set disconnect command complete flag
+ hci_clear_flag(HCI_FLAG_CONNECT_COMPLETE); // Clear connection complete flag
+ }
+ break;
+
+ case EV_REMOTE_NAME_COMPLETE:
+ if(!hcibuf[2]) { // Check if reading is OK
+ for(uint8_t i = 0; i < min(sizeof (remote_name), sizeof (hcibuf) - 9); i++) {
+ remote_name[i] = hcibuf[9 + i];
+ if(remote_name[i] == '\0') // End of string
+ break;
+ }
+ // TODO: Altid sæt '\0' i remote name!
+ hci_set_flag(HCI_FLAG_REMOTE_NAME_COMPLETE);
+ }
+ break;
+
+ case EV_INCOMING_CONNECT:
+ for(uint8_t i = 0; i < 6; i++)
+ disc_bdaddr[i] = hcibuf[i + 2];
+
+ for(uint8_t i = 0; i < 3; i++)
+ classOfDevice[i] = hcibuf[i + 8];
+
+ if((classOfDevice[1] & 0x05) && (classOfDevice[0] & 0xC8)) { // Check if it is a mouse, keyboard or a gamepad
+#ifdef DEBUG_USB_HOST
+ if(classOfDevice[0] & 0x80)
+ Notify(PSTR("\r\nMouse is connecting"), 0x80);
+ if(classOfDevice[0] & 0x40)
+ Notify(PSTR("\r\nKeyboard is connecting"), 0x80);
+ if(classOfDevice[0] & 0x08)
+ Notify(PSTR("\r\nGamepad is connecting"), 0x80);
+#endif
+ incomingHIDDevice = true;
+ }
+
+#ifdef EXTRADEBUG
+ Notify(PSTR("\r\nClass of device: "), 0x80);
+ D_PrintHex<uint8_t > (classOfDevice[2], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (classOfDevice[1], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (classOfDevice[0], 0x80);
+#endif
+ hci_set_flag(HCI_FLAG_INCOMING_REQUEST);
+ break;
+
+ case EV_PIN_CODE_REQUEST:
+ if(pairWithWii) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nPairing with Wiimote"), 0x80);
+#endif
+ hci_pin_code_request_reply();
+ } else if(btdPin != NULL) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nBluetooth pin is set too: "), 0x80);
+ NotifyStr(btdPin, 0x80);
+#endif
+ hci_pin_code_request_reply();
+ } else {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nNo pin was set"), 0x80);
+#endif
+ hci_pin_code_negative_request_reply();
+ }
+ break;
+
+ case EV_LINK_KEY_REQUEST:
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nReceived Key Request"), 0x80);
+#endif
+ hci_link_key_request_negative_reply();
+ break;
+
+ case EV_AUTHENTICATION_COMPLETE:
+ if(pairWithWii && !connectToWii) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nPairing successful with Wiimote"), 0x80);
+#endif
+ connectToWii = true; // Used to indicate to the Wii service, that it should connect to this device
+ } else if(pairWithHIDDevice && !connectToHIDDevice) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nPairing successful with HID device"), 0x80);
+#endif
+ connectToHIDDevice = true; // Used to indicate to the BTHID service, that it should connect to this device
+ }
+ break;
+ /* We will just ignore the following events */
+ case EV_NUM_COMPLETE_PKT:
+ case EV_ROLE_CHANGED:
+ case EV_PAGE_SCAN_REP_MODE:
+ case EV_LOOPBACK_COMMAND:
+ case EV_DATA_BUFFER_OVERFLOW:
+ case EV_CHANGE_CONNECTION_LINK:
+ case EV_MAX_SLOTS_CHANGE:
+ case EV_QOS_SETUP_COMPLETE:
+ case EV_LINK_KEY_NOTIFICATION:
+ case EV_ENCRYPTION_CHANGE:
+ case EV_READ_REMOTE_VERSION_INFORMATION_COMPLETE:
+ break;
+#ifdef EXTRADEBUG
+ default:
+ if(hcibuf[0] != 0x00) {
+ Notify(PSTR("\r\nUnmanaged HCI Event: "), 0x80);
+ D_PrintHex<uint8_t > (hcibuf[0], 0x80);
+ }
+ break;
+#endif
+ } // Switch
+ }
+#ifdef EXTRADEBUG
+ else {
+ Notify(PSTR("\r\nHCI event error: "), 0x80);
+ D_PrintHex<uint8_t > (rcode, 0x80);
+ }
+#endif
+}
+
+/* Poll Bluetooth and print result */
+void BTD::HCI_task() {
+ switch(hci_state) {
+ case HCI_INIT_STATE:
+ hci_counter++;
+ if(hci_counter > hci_num_reset_loops) { // wait until we have looped x times to clear any old events
+ hci_reset();
+ hci_state = HCI_RESET_STATE;
+ hci_counter = 0;
+ }
+ break;
+
+ case HCI_RESET_STATE:
+ hci_counter++;
+ if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) {
+ hci_counter = 0;
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nHCI Reset complete"), 0x80);
+#endif
+ hci_state = HCI_CLASS_STATE;
+ hci_write_class_of_device();
+ } else if(hci_counter > hci_num_reset_loops) {
+ hci_num_reset_loops *= 10;
+ if(hci_num_reset_loops > 2000)
+ hci_num_reset_loops = 2000;
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nNo response to HCI Reset"), 0x80);
+#endif
+ hci_state = HCI_INIT_STATE;
+ hci_counter = 0;
+ }
+ break;
+
+ case HCI_CLASS_STATE:
+ if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nWrite class of device"), 0x80);
+#endif
+ hci_state = HCI_BDADDR_STATE;
+ hci_read_bdaddr();
+ }
+ break;
+
+ case HCI_BDADDR_STATE:
+ if(hci_check_flag(HCI_FLAG_READ_BDADDR)) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nLocal Bluetooth Address: "), 0x80);
+ for(int8_t i = 5; i > 0; i--) {
+ D_PrintHex<uint8_t > (my_bdaddr[i], 0x80);
+ Notify(PSTR(":"), 0x80);
+ }
+ D_PrintHex<uint8_t > (my_bdaddr[0], 0x80);
+#endif
+ hci_read_local_version_information();
+ hci_state = HCI_LOCAL_VERSION_STATE;
+ }
+ break;
+
+ case HCI_LOCAL_VERSION_STATE: // The local version is used by the PS3BT class
+ if(hci_check_flag(HCI_FLAG_READ_VERSION)) {
+ if(btdName != NULL) {
+ hci_set_local_name(btdName);
+ hci_state = HCI_SET_NAME_STATE;
+ } else
+ hci_state = HCI_CHECK_DEVICE_SERVICE;
+ }
+ break;
+
+ case HCI_SET_NAME_STATE:
+ if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nThe name is set to: "), 0x80);
+ NotifyStr(btdName, 0x80);
+#endif
+ hci_state = HCI_CHECK_DEVICE_SERVICE;
+ }
+ break;
+
+ case HCI_CHECK_DEVICE_SERVICE:
+ if(pairWithHIDDevice || pairWithWii) { // Check if it should try to connect to a Wiimote
+#ifdef DEBUG_USB_HOST
+ if(pairWithWii)
+ Notify(PSTR("\r\nStarting inquiry\r\nPress 1 & 2 on the Wiimote\r\nOr press the SYNC button if you are using a Wii U Pro Controller or a Wii Balance Board"), 0x80);
+ else
+ Notify(PSTR("\r\nPlease enable discovery of your device"), 0x80);
+#endif
+ hci_inquiry();
+ hci_state = HCI_INQUIRY_STATE;
+ } else
+ hci_state = HCI_SCANNING_STATE; // Don't try to connect to a Wiimote
+ break;
+
+ case HCI_INQUIRY_STATE:
+ if(hci_check_flag(HCI_FLAG_DEVICE_FOUND)) {
+ hci_inquiry_cancel(); // Stop inquiry
+#ifdef DEBUG_USB_HOST
+ if(pairWithWii)
+ Notify(PSTR("\r\nWiimote found"), 0x80);
+ else
+ Notify(PSTR("\r\nHID device found"), 0x80);
+
+ Notify(PSTR("\r\nNow just create the instance like so:"), 0x80);
+ if(pairWithWii)
+ Notify(PSTR("\r\nWII Wii(&Btd);"), 0x80);
+ else
+ Notify(PSTR("\r\nBTHID bthid(&Btd);"), 0x80);
+
+ Notify(PSTR("\r\nAnd then press any button on the "), 0x80);
+ if(pairWithWii)
+ Notify(PSTR("Wiimote"), 0x80);
+ else
+ Notify(PSTR("device"), 0x80);
+#endif
+ if(checkRemoteName) {
+ hci_remote_name(); // We need to know the name to distinguish between the Wiimote, the new Wiimote with Motion Plus inside, a Wii U Pro Controller and a Wii Balance Board
+ hci_state = HCI_REMOTE_NAME_STATE;
+ } else
+ hci_state = HCI_CONNECT_DEVICE_STATE;
+ }
+ break;
+
+ case HCI_CONNECT_DEVICE_STATE:
+ if(hci_check_flag(HCI_FLAG_CMD_COMPLETE)) {
+#ifdef DEBUG_USB_HOST
+ if(pairWithWii)
+ Notify(PSTR("\r\nConnecting to Wiimote"), 0x80);
+ else
+ Notify(PSTR("\r\nConnecting to HID device"), 0x80);
+#endif
+ checkRemoteName = false;
+ hci_connect();
+ hci_state = HCI_CONNECTED_DEVICE_STATE;
+ }
+ break;
+
+ case HCI_CONNECTED_DEVICE_STATE:
+ if(hci_check_flag(HCI_FLAG_CONNECT_EVENT)) {
+ if(hci_check_flag(HCI_FLAG_CONNECT_COMPLETE)) {
+#ifdef DEBUG_USB_HOST
+ if(pairWithWii)
+ Notify(PSTR("\r\nConnected to Wiimote"), 0x80);
+ else
+ Notify(PSTR("\r\nConnected to HID device"), 0x80);
+#endif
+ hci_authentication_request(); // This will start the pairing with the Wiimote
+ hci_state = HCI_SCANNING_STATE;
+ } else {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nTrying to connect one more time..."), 0x80);
+#endif
+ hci_connect(); // Try to connect one more time
+ }
+ }
+ break;
+
+ case HCI_SCANNING_STATE:
+ if(!connectToWii && !pairWithWii && !connectToHIDDevice && !pairWithHIDDevice) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nWait For Incoming Connection Request"), 0x80);
+#endif
+ hci_write_scan_enable();
+ watingForConnection = true;
+ hci_state = HCI_CONNECT_IN_STATE;
+ }
+ break;
+
+ case HCI_CONNECT_IN_STATE:
+ if(hci_check_flag(HCI_FLAG_INCOMING_REQUEST)) {
+ watingForConnection = false;
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nIncoming Connection Request"), 0x80);
+#endif
+ hci_remote_name();
+ hci_state = HCI_REMOTE_NAME_STATE;
+ } else if(hci_check_flag(HCI_FLAG_DISCONNECT_COMPLETE))
+ hci_state = HCI_DISCONNECT_STATE;
+ break;
+
+ case HCI_REMOTE_NAME_STATE:
+ if(hci_check_flag(HCI_FLAG_REMOTE_NAME_COMPLETE)) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nRemote Name: "), 0x80);
+ for(uint8_t i = 0; i < strlen(remote_name); i++)
+ Notifyc(remote_name[i], 0x80);
+#endif
+ if(strncmp((const char*)remote_name, "Nintendo", 8) == 0) {
+ incomingWii = true;
+ motionPlusInside = false;
+ wiiUProController = false;
+ pairWiiUsingSync = false;
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nWiimote is connecting"), 0x80);
+#endif
+ if(strncmp((const char*)remote_name, "Nintendo RVL-CNT-01-TR", 22) == 0) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR(" with Motion Plus Inside"), 0x80);
+#endif
+ motionPlusInside = true;
+ } else if(strncmp((const char*)remote_name, "Nintendo RVL-CNT-01-UC", 22) == 0) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR(" - Wii U Pro Controller"), 0x80);
+#endif
+ wiiUProController = motionPlusInside = pairWiiUsingSync = true;
+ } else if(strncmp((const char*)remote_name, "Nintendo RVL-WBC-01", 19) == 0) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR(" - Wii Balance Board"), 0x80);
+#endif
+ pairWiiUsingSync = true;
+ }
+ }
+ if(classOfDevice[2] == 0 && classOfDevice[1] == 0x25 && classOfDevice[0] == 0x08 && strncmp((const char*)remote_name, "Wireless Controller", 19) == 0) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nPS4 controller is connecting"), 0x80);
+#endif
+ incomingPS4 = true;
+ }
+ if(pairWithWii && checkRemoteName)
+ hci_state = HCI_CONNECT_DEVICE_STATE;
+ else {
+ hci_accept_connection();
+ hci_state = HCI_CONNECTED_STATE;
+ }
+ }
+ break;
+
+ case HCI_CONNECTED_STATE:
+ if(hci_check_flag(HCI_FLAG_CONNECT_COMPLETE)) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nConnected to Device: "), 0x80);
+ for(int8_t i = 5; i > 0; i--) {
+ D_PrintHex<uint8_t > (disc_bdaddr[i], 0x80);
+ Notify(PSTR(":"), 0x80);
+ }
+ D_PrintHex<uint8_t > (disc_bdaddr[0], 0x80);
+#endif
+ if(incomingPS4)
+ connectToHIDDevice = true; // We should always connect to the PS4 controller
+
+ // Clear these flags for a new connection
+ l2capConnectionClaimed = false;
+ sdpConnectionClaimed = false;
+ rfcommConnectionClaimed = false;
+
+ hci_event_flag = 0;
+ hci_state = HCI_DONE_STATE;
+ }
+ break;
+
+ case HCI_DONE_STATE:
+ hci_counter++;
+ if(hci_counter > 1000) { // Wait until we have looped 1000 times to make sure that the L2CAP connection has been started
+ hci_counter = 0;
+ hci_state = HCI_SCANNING_STATE;
+ }
+ break;
+
+ case HCI_DISCONNECT_STATE:
+ if(hci_check_flag(HCI_FLAG_DISCONNECT_COMPLETE)) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nHCI Disconnected from Device"), 0x80);
+#endif
+ hci_event_flag = 0; // Clear all flags
+
+ // Reset all buffers
+ memset(hcibuf, 0, BULK_MAXPKTSIZE);
+ memset(l2capinbuf, 0, BULK_MAXPKTSIZE);
+
+ connectToWii = incomingWii = pairWithWii = false;
+ connectToHIDDevice = incomingHIDDevice = pairWithHIDDevice = checkRemoteName = false;
+ incomingPS4 = false;
+
+ hci_state = HCI_SCANNING_STATE;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void BTD::ACL_event_task() {
+ uint16_t length = BULK_MAXPKTSIZE;
+ uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ BTD_DATAIN_PIPE ].epAddr, &length, l2capinbuf); // Input on endpoint 2
+
+ if(!rcode) { // Check for errors
+ if(length > 0) { // Check if any data was read
+ for(uint8_t i = 0; i < BTD_NUM_SERVICES; i++) {
+ if(btService[i])
+ btService[i]->ACLData(l2capinbuf);
+ }
+ }
+ }
+#ifdef EXTRADEBUG
+ else if(rcode != hrNAK) {
+ Notify(PSTR("\r\nACL data in error: "), 0x80);
+ D_PrintHex<uint8_t > (rcode, 0x80);
+ }
+#endif
+ for(uint8_t i = 0; i < BTD_NUM_SERVICES; i++)
+ if(btService[i])
+ btService[i]->Run();
+}
+
+/************************************************************/
+/* HCI Commands */
+
+/************************************************************/
+void BTD::HCI_Command(uint8_t* data, uint16_t nbytes) {
+ hci_clear_flag(HCI_FLAG_CMD_COMPLETE);
+ pUsb->ctrlReq(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, bmREQ_HCI_OUT, 0x00, 0x00, 0x00, 0x00, nbytes, nbytes, data, NULL);
+}
+
+void BTD::hci_reset() {
+ hci_event_flag = 0; // Clear all the flags
+ hcibuf[0] = 0x03; // HCI OCF = 3
+ hcibuf[1] = 0x03 << 2; // HCI OGF = 3
+ hcibuf[2] = 0x00;
+
+ HCI_Command(hcibuf, 3);
+}
+
+void BTD::hci_write_scan_enable() {
+ hci_clear_flag(HCI_FLAG_INCOMING_REQUEST);
+ hcibuf[0] = 0x1A; // HCI OCF = 1A
+ hcibuf[1] = 0x03 << 2; // HCI OGF = 3
+ hcibuf[2] = 0x01; // parameter length = 1
+ if(btdName != NULL)
+ hcibuf[3] = 0x03; // Inquiry Scan enabled. Page Scan enabled.
+ else
+ hcibuf[3] = 0x02; // Inquiry Scan disabled. Page Scan enabled.
+
+ HCI_Command(hcibuf, 4);
+}
+
+void BTD::hci_write_scan_disable() {
+ hcibuf[0] = 0x1A; // HCI OCF = 1A
+ hcibuf[1] = 0x03 << 2; // HCI OGF = 3
+ hcibuf[2] = 0x01; // parameter length = 1
+ hcibuf[3] = 0x00; // Inquiry Scan disabled. Page Scan disabled.
+
+ HCI_Command(hcibuf, 4);
+}
+
+void BTD::hci_read_bdaddr() {
+ hci_clear_flag(HCI_FLAG_READ_BDADDR);
+ hcibuf[0] = 0x09; // HCI OCF = 9
+ hcibuf[1] = 0x04 << 2; // HCI OGF = 4
+ hcibuf[2] = 0x00;
+
+ HCI_Command(hcibuf, 3);
+}
+
+void BTD::hci_read_local_version_information() {
+ hci_clear_flag(HCI_FLAG_READ_VERSION);
+ hcibuf[0] = 0x01; // HCI OCF = 1
+ hcibuf[1] = 0x04 << 2; // HCI OGF = 4
+ hcibuf[2] = 0x00;
+
+ HCI_Command(hcibuf, 3);
+}
+
+void BTD::hci_accept_connection() {
+ hci_clear_flag(HCI_FLAG_CONNECT_COMPLETE);
+ hcibuf[0] = 0x09; // HCI OCF = 9
+ hcibuf[1] = 0x01 << 2; // HCI OGF = 1
+ hcibuf[2] = 0x07; // parameter length 7
+ hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr
+ hcibuf[4] = disc_bdaddr[1];
+ hcibuf[5] = disc_bdaddr[2];
+ hcibuf[6] = disc_bdaddr[3];
+ hcibuf[7] = disc_bdaddr[4];
+ hcibuf[8] = disc_bdaddr[5];
+ hcibuf[9] = 0x00; // Switch role to master
+
+ HCI_Command(hcibuf, 10);
+}
+
+void BTD::hci_remote_name() {
+ hci_clear_flag(HCI_FLAG_REMOTE_NAME_COMPLETE);
+ hcibuf[0] = 0x19; // HCI OCF = 19
+ hcibuf[1] = 0x01 << 2; // HCI OGF = 1
+ hcibuf[2] = 0x0A; // parameter length = 10
+ hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr
+ hcibuf[4] = disc_bdaddr[1];
+ hcibuf[5] = disc_bdaddr[2];
+ hcibuf[6] = disc_bdaddr[3];
+ hcibuf[7] = disc_bdaddr[4];
+ hcibuf[8] = disc_bdaddr[5];
+ hcibuf[9] = 0x01; // Page Scan Repetition Mode
+ hcibuf[10] = 0x00; // Reserved
+ hcibuf[11] = 0x00; // Clock offset - low byte
+ hcibuf[12] = 0x00; // Clock offset - high byte
+
+ HCI_Command(hcibuf, 13);
+}
+
+void BTD::hci_set_local_name(const char* name) {
+ hcibuf[0] = 0x13; // HCI OCF = 13
+ hcibuf[1] = 0x03 << 2; // HCI OGF = 3
+ hcibuf[2] = strlen(name) + 1; // parameter length = the length of the string + end byte
+ uint8_t i;
+ for(i = 0; i < strlen(name); i++)
+ hcibuf[i + 3] = name[i];
+ hcibuf[i + 3] = 0x00; // End of string
+
+ HCI_Command(hcibuf, 4 + strlen(name));
+}
+
+void BTD::hci_inquiry() {
+ hci_clear_flag(HCI_FLAG_DEVICE_FOUND);
+ hcibuf[0] = 0x01;
+ hcibuf[1] = 0x01 << 2; // HCI OGF = 1
+ hcibuf[2] = 0x05; // Parameter Total Length = 5
+ hcibuf[3] = 0x33; // LAP: Genera/Unlimited Inquiry Access Code (GIAC = 0x9E8B33) - see https://www.bluetooth.org/Technical/AssignedNumbers/baseband.htm
+ hcibuf[4] = 0x8B;
+ hcibuf[5] = 0x9E;
+ hcibuf[6] = 0x30; // Inquiry time = 61.44 sec (maximum)
+ hcibuf[7] = 0x0A; // 10 number of responses
+
+ HCI_Command(hcibuf, 8);
+}
+
+void BTD::hci_inquiry_cancel() {
+ hcibuf[0] = 0x02;
+ hcibuf[1] = 0x01 << 2; // HCI OGF = 1
+ hcibuf[2] = 0x00; // Parameter Total Length = 0
+
+ HCI_Command(hcibuf, 3);
+}
+
+void BTD::hci_connect() {
+ hci_connect(disc_bdaddr); // Use last discovered device
+}
+
+void BTD::hci_connect(uint8_t *bdaddr) {
+ hci_clear_flag(HCI_FLAG_CONNECT_COMPLETE | HCI_FLAG_CONNECT_EVENT);
+ hcibuf[0] = 0x05;
+ hcibuf[1] = 0x01 << 2; // HCI OGF = 1
+ hcibuf[2] = 0x0D; // parameter Total Length = 13
+ hcibuf[3] = bdaddr[0]; // 6 octet bdaddr (LSB)
+ hcibuf[4] = bdaddr[1];
+ hcibuf[5] = bdaddr[2];
+ hcibuf[6] = bdaddr[3];
+ hcibuf[7] = bdaddr[4];
+ hcibuf[8] = bdaddr[5];
+ hcibuf[9] = 0x18; // DM1 or DH1 may be used
+ hcibuf[10] = 0xCC; // DM3, DH3, DM5, DH5 may be used
+ hcibuf[11] = 0x01; // Page repetition mode R1
+ hcibuf[12] = 0x00; // Reserved
+ hcibuf[13] = 0x00; // Clock offset
+ hcibuf[14] = 0x00; // Invalid clock offset
+ hcibuf[15] = 0x00; // Do not allow role switch
+
+ HCI_Command(hcibuf, 16);
+}
+
+void BTD::hci_pin_code_request_reply() {
+ hcibuf[0] = 0x0D; // HCI OCF = 0D
+ hcibuf[1] = 0x01 << 2; // HCI OGF = 1
+ hcibuf[2] = 0x17; // parameter length 23
+ hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr
+ hcibuf[4] = disc_bdaddr[1];
+ hcibuf[5] = disc_bdaddr[2];
+ hcibuf[6] = disc_bdaddr[3];
+ hcibuf[7] = disc_bdaddr[4];
+ hcibuf[8] = disc_bdaddr[5];
+ if(pairWithWii) {
+ hcibuf[9] = 6; // Pin length is the length of the Bluetooth address
+ if(pairWiiUsingSync) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nParing with Wii controller via SYNC"), 0x80);
+#endif
+ for(uint8_t i = 0; i < 6; i++)
+ hcibuf[10 + i] = my_bdaddr[i]; // The pin is the Bluetooth dongles Bluetooth address backwards
+ } else {
+ for(uint8_t i = 0; i < 6; i++)
+ hcibuf[10 + i] = disc_bdaddr[i]; // The pin is the Wiimote's Bluetooth address backwards
+ }
+ for(uint8_t i = 16; i < 26; i++)
+ hcibuf[i] = 0x00; // The rest should be 0
+ } else {
+ hcibuf[9] = strlen(btdPin); // Length of pin
+ uint8_t i;
+ for(i = 0; i < strlen(btdPin); i++) // The maximum size of the pin is 16
+ hcibuf[i + 10] = btdPin[i];
+ for(; i < 16; i++)
+ hcibuf[i + 10] = 0x00; // The rest should be 0
+ }
+
+ HCI_Command(hcibuf, 26);
+}
+
+void BTD::hci_pin_code_negative_request_reply() {
+ hcibuf[0] = 0x0E; // HCI OCF = 0E
+ hcibuf[1] = 0x01 << 2; // HCI OGF = 1
+ hcibuf[2] = 0x06; // parameter length 6
+ hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr
+ hcibuf[4] = disc_bdaddr[1];
+ hcibuf[5] = disc_bdaddr[2];
+ hcibuf[6] = disc_bdaddr[3];
+ hcibuf[7] = disc_bdaddr[4];
+ hcibuf[8] = disc_bdaddr[5];
+
+ HCI_Command(hcibuf, 9);
+}
+
+void BTD::hci_link_key_request_negative_reply() {
+ hcibuf[0] = 0x0C; // HCI OCF = 0C
+ hcibuf[1] = 0x01 << 2; // HCI OGF = 1
+ hcibuf[2] = 0x06; // parameter length 6
+ hcibuf[3] = disc_bdaddr[0]; // 6 octet bdaddr
+ hcibuf[4] = disc_bdaddr[1];
+ hcibuf[5] = disc_bdaddr[2];
+ hcibuf[6] = disc_bdaddr[3];
+ hcibuf[7] = disc_bdaddr[4];
+ hcibuf[8] = disc_bdaddr[5];
+
+ HCI_Command(hcibuf, 9);
+}
+
+void BTD::hci_authentication_request() {
+ hcibuf[0] = 0x11; // HCI OCF = 11
+ hcibuf[1] = 0x01 << 2; // HCI OGF = 1
+ hcibuf[2] = 0x02; // parameter length = 2
+ hcibuf[3] = (uint8_t)(hci_handle & 0xFF); //connection handle - low byte
+ hcibuf[4] = (uint8_t)((hci_handle >> 8) & 0x0F); //connection handle - high byte
+
+ HCI_Command(hcibuf, 5);
+}
+
+void BTD::hci_disconnect(uint16_t handle) { // This is called by the different services
+ hci_clear_flag(HCI_FLAG_DISCONNECT_COMPLETE);
+ hcibuf[0] = 0x06; // HCI OCF = 6
+ hcibuf[1] = 0x01 << 2; // HCI OGF = 1
+ hcibuf[2] = 0x03; // parameter length = 3
+ hcibuf[3] = (uint8_t)(handle & 0xFF); //connection handle - low byte
+ hcibuf[4] = (uint8_t)((handle >> 8) & 0x0F); //connection handle - high byte
+ hcibuf[5] = 0x13; // reason
+
+ HCI_Command(hcibuf, 6);
+}
+
+void BTD::hci_write_class_of_device() { // See http://bluetooth-pentest.narod.ru/software/bluetooth_class_of_device-service_generator.html
+ hcibuf[0] = 0x24; // HCI OCF = 24
+ hcibuf[1] = 0x03 << 2; // HCI OGF = 3
+ hcibuf[2] = 0x03; // parameter length = 3
+ hcibuf[3] = 0x04; // Robot
+ hcibuf[4] = 0x08; // Toy
+ hcibuf[5] = 0x00;
+
+ HCI_Command(hcibuf, 6);
+}
+/*******************************************************************
+ * *
+ * HCI ACL Data Packet *
+ * *
+ * buf[0] buf[1] buf[2] buf[3]
+ * 0 4 8 11 12 16 24 31 MSB
+ * .-+-+-+-+-+-+-+-|-+-+-+-|-+-|-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-.
+ * | HCI Handle |PB |BC | Data Total Length | HCI ACL Data Packet
+ * .-+-+-+-+-+-+-+-|-+-+-+-|-+-|-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-.
+ *
+ * buf[4] buf[5] buf[6] buf[7]
+ * 0 8 16 31 MSB
+ * .-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-.
+ * | Length | Channel ID | Basic L2CAP header
+ * .-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-.
+ *
+ * buf[8] buf[9] buf[10] buf[11]
+ * 0 8 16 31 MSB
+ * .-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-.
+ * | Code | Identifier | Length | Control frame (C-frame)
+ * .-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-. (signaling packet format)
+ */
+/************************************************************/
+/* L2CAP Commands */
+
+/************************************************************/
+void BTD::L2CAP_Command(uint16_t handle, uint8_t* data, uint8_t nbytes, uint8_t channelLow, uint8_t channelHigh) {
+ uint8_t buf[8 + nbytes];
+ buf[0] = (uint8_t)(handle & 0xff); // HCI handle with PB,BC flag
+ buf[1] = (uint8_t)(((handle >> 8) & 0x0f) | 0x20);
+ buf[2] = (uint8_t)((4 + nbytes) & 0xff); // HCI ACL total data length
+ buf[3] = (uint8_t)((4 + nbytes) >> 8);
+ buf[4] = (uint8_t)(nbytes & 0xff); // L2CAP header: Length
+ buf[5] = (uint8_t)(nbytes >> 8);
+ buf[6] = channelLow;
+ buf[7] = channelHigh;
+
+ for(uint16_t i = 0; i < nbytes; i++) // L2CAP C-frame
+ buf[8 + i] = data[i];
+
+ uint8_t rcode = pUsb->outTransfer(bAddress, epInfo[ BTD_DATAOUT_PIPE ].epAddr, (8 + nbytes), buf);
+ if(rcode) {
+ delay(100); // This small delay prevents it from overflowing if it fails
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nError sending L2CAP message: 0x"), 0x80);
+ D_PrintHex<uint8_t > (rcode, 0x80);
+ Notify(PSTR(" - Channel ID: "), 0x80);
+ D_PrintHex<uint8_t > (channelHigh, 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (channelLow, 0x80);
+#endif
+ }
+}
+
+void BTD::l2cap_connection_request(uint16_t handle, uint8_t rxid, uint8_t* scid, uint16_t psm) {
+ l2capoutbuf[0] = L2CAP_CMD_CONNECTION_REQUEST; // Code
+ l2capoutbuf[1] = rxid; // Identifier
+ l2capoutbuf[2] = 0x04; // Length
+ l2capoutbuf[3] = 0x00;
+ l2capoutbuf[4] = (uint8_t)(psm & 0xff); // PSM
+ l2capoutbuf[5] = (uint8_t)(psm >> 8);
+ l2capoutbuf[6] = scid[0]; // Source CID
+ l2capoutbuf[7] = scid[1];
+
+ L2CAP_Command(handle, l2capoutbuf, 8);
+}
+
+void BTD::l2cap_connection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid, uint8_t result) {
+ l2capoutbuf[0] = L2CAP_CMD_CONNECTION_RESPONSE; // Code
+ l2capoutbuf[1] = rxid; // Identifier
+ l2capoutbuf[2] = 0x08; // Length
+ l2capoutbuf[3] = 0x00;
+ l2capoutbuf[4] = dcid[0]; // Destination CID
+ l2capoutbuf[5] = dcid[1];
+ l2capoutbuf[6] = scid[0]; // Source CID
+ l2capoutbuf[7] = scid[1];
+ l2capoutbuf[8] = result; // Result: Pending or Success
+ l2capoutbuf[9] = 0x00;
+ l2capoutbuf[10] = 0x00; // No further information
+ l2capoutbuf[11] = 0x00;
+
+ L2CAP_Command(handle, l2capoutbuf, 12);
+}
+
+void BTD::l2cap_config_request(uint16_t handle, uint8_t rxid, uint8_t* dcid) {
+ l2capoutbuf[0] = L2CAP_CMD_CONFIG_REQUEST; // Code
+ l2capoutbuf[1] = rxid; // Identifier
+ l2capoutbuf[2] = 0x08; // Length
+ l2capoutbuf[3] = 0x00;
+ l2capoutbuf[4] = dcid[0]; // Destination CID
+ l2capoutbuf[5] = dcid[1];
+ l2capoutbuf[6] = 0x00; // Flags
+ l2capoutbuf[7] = 0x00;
+ l2capoutbuf[8] = 0x01; // Config Opt: type = MTU (Maximum Transmission Unit) - Hint
+ l2capoutbuf[9] = 0x02; // Config Opt: length
+ l2capoutbuf[10] = 0xFF; // MTU
+ l2capoutbuf[11] = 0xFF;
+
+ L2CAP_Command(handle, l2capoutbuf, 12);
+}
+
+void BTD::l2cap_config_response(uint16_t handle, uint8_t rxid, uint8_t* scid) {
+ l2capoutbuf[0] = L2CAP_CMD_CONFIG_RESPONSE; // Code
+ l2capoutbuf[1] = rxid; // Identifier
+ l2capoutbuf[2] = 0x0A; // Length
+ l2capoutbuf[3] = 0x00;
+ l2capoutbuf[4] = scid[0]; // Source CID
+ l2capoutbuf[5] = scid[1];
+ l2capoutbuf[6] = 0x00; // Flag
+ l2capoutbuf[7] = 0x00;
+ l2capoutbuf[8] = 0x00; // Result
+ l2capoutbuf[9] = 0x00;
+ l2capoutbuf[10] = 0x01; // Config
+ l2capoutbuf[11] = 0x02;
+ l2capoutbuf[12] = 0xA0;
+ l2capoutbuf[13] = 0x02;
+
+ L2CAP_Command(handle, l2capoutbuf, 14);
+}
+
+void BTD::l2cap_disconnection_request(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid) {
+ l2capoutbuf[0] = L2CAP_CMD_DISCONNECT_REQUEST; // Code
+ l2capoutbuf[1] = rxid; // Identifier
+ l2capoutbuf[2] = 0x04; // Length
+ l2capoutbuf[3] = 0x00;
+ l2capoutbuf[4] = dcid[0];
+ l2capoutbuf[5] = dcid[1];
+ l2capoutbuf[6] = scid[0];
+ l2capoutbuf[7] = scid[1];
+
+ L2CAP_Command(handle, l2capoutbuf, 8);
+}
+
+void BTD::l2cap_disconnection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid) {
+ l2capoutbuf[0] = L2CAP_CMD_DISCONNECT_RESPONSE; // Code
+ l2capoutbuf[1] = rxid; // Identifier
+ l2capoutbuf[2] = 0x04; // Length
+ l2capoutbuf[3] = 0x00;
+ l2capoutbuf[4] = dcid[0];
+ l2capoutbuf[5] = dcid[1];
+ l2capoutbuf[6] = scid[0];
+ l2capoutbuf[7] = scid[1];
+
+ L2CAP_Command(handle, l2capoutbuf, 8);
+}
+
+void BTD::l2cap_information_response(uint16_t handle, uint8_t rxid, uint8_t infoTypeLow, uint8_t infoTypeHigh) {
+ l2capoutbuf[0] = L2CAP_CMD_INFORMATION_RESPONSE; // Code
+ l2capoutbuf[1] = rxid; // Identifier
+ l2capoutbuf[2] = 0x08; // Length
+ l2capoutbuf[3] = 0x00;
+ l2capoutbuf[4] = infoTypeLow;
+ l2capoutbuf[5] = infoTypeHigh;
+ l2capoutbuf[6] = 0x00; // Result = success
+ l2capoutbuf[7] = 0x00; // Result = success
+ l2capoutbuf[8] = 0x00;
+ l2capoutbuf[9] = 0x00;
+ l2capoutbuf[10] = 0x00;
+ l2capoutbuf[11] = 0x00;
+
+ L2CAP_Command(handle, l2capoutbuf, 12);
+}
+
+/* PS3 Commands - only set Bluetooth address is implemented in this library */
+void BTD::setBdaddr(uint8_t* bdaddr) {
+ /* Set the internal Bluetooth address */
+ uint8_t buf[8];
+ buf[0] = 0x01;
+ buf[1] = 0x00;
+
+ for(uint8_t i = 0; i < 6; i++)
+ buf[i + 2] = bdaddr[5 - i]; // Copy into buffer, has to be written reversed, so it is MSB first
+
+ // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data
+ pUsb->ctrlReq(bAddress, epInfo[BTD_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL);
+}
+
+void BTD::setMoveBdaddr(uint8_t* bdaddr) {
+ /* Set the internal Bluetooth address */
+ uint8_t buf[11];
+ buf[0] = 0x05;
+ buf[7] = 0x10;
+ buf[8] = 0x01;
+ buf[9] = 0x02;
+ buf[10] = 0x12;
+
+ for(uint8_t i = 0; i < 6; i++)
+ buf[i + 1] = bdaddr[i];
+
+ // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x05), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data
+ pUsb->ctrlReq(bAddress, epInfo[BTD_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x05, 0x03, 0x00, 11, 11, buf, NULL);
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTD.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTD.h
new file mode 100755
index 000000000..6549c30c9
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTD.h
@@ -0,0 +1,620 @@
+/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
+
+ This software may be distributed and modified under the terms of the GNU
+ General Public License version 2 (GPL2) as published by the Free Software
+ Foundation and appearing in the file GPL2.TXT included in the packaging of
+ this file. Please note that GPL2 Section 2[b] requires that all works based
+ on this software must also be made publicly available under the terms of
+ the GPL2 ("Copyleft").
+
+ Contact information
+ -------------------
+
+ Kristian Lauszus, TKJ Electronics
+ Web : http://www.tkjelectronics.com
+ e-mail : kristianl@tkjelectronics.com
+ */
+
+#ifndef _btd_h_
+#define _btd_h_
+
+#include "Usb.h"
+#include "hid.h"
+
+//PID and VID of the Sony PS3 devices
+#define PS3_VID 0x054C // Sony Corporation
+#define PS3_PID 0x0268 // PS3 Controller DualShock 3
+#define PS3NAVIGATION_PID 0x042F // Navigation controller
+#define PS3MOVE_PID 0x03D5 // Motion controller
+
+#define IOGEAR_GBU521_VID 0x0A5C // The IOGEAR GBU521 dongle does not presents itself correctly, so we have to check for it manually
+#define IOGEAR_GBU521_PID 0x21E8
+
+/* Bluetooth dongle data taken from descriptors */
+#define BULK_MAXPKTSIZE 64 // Max size for ACL data
+
+// Used in control endpoint header for HCI Commands
+#define bmREQ_HCI_OUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE
+
+/* Bluetooth HCI states for hci_task() */
+#define HCI_INIT_STATE 0
+#define HCI_RESET_STATE 1
+#define HCI_CLASS_STATE 2
+#define HCI_BDADDR_STATE 3
+#define HCI_LOCAL_VERSION_STATE 4
+#define HCI_SET_NAME_STATE 5
+#define HCI_CHECK_DEVICE_SERVICE 6
+
+#define HCI_INQUIRY_STATE 7 // These three states are only used if it should pair and connect to a device
+#define HCI_CONNECT_DEVICE_STATE 8
+#define HCI_CONNECTED_DEVICE_STATE 9
+
+#define HCI_SCANNING_STATE 10
+#define HCI_CONNECT_IN_STATE 11
+#define HCI_REMOTE_NAME_STATE 12
+#define HCI_CONNECTED_STATE 13
+#define HCI_DISABLE_SCAN_STATE 14
+#define HCI_DONE_STATE 15
+#define HCI_DISCONNECT_STATE 16
+
+/* HCI event flags*/
+#define HCI_FLAG_CMD_COMPLETE (1UL << 0)
+#define HCI_FLAG_CONNECT_COMPLETE (1UL << 1)
+#define HCI_FLAG_DISCONNECT_COMPLETE (1UL << 2)
+#define HCI_FLAG_REMOTE_NAME_COMPLETE (1UL << 3)
+#define HCI_FLAG_INCOMING_REQUEST (1UL << 4)
+#define HCI_FLAG_READ_BDADDR (1UL << 5)
+#define HCI_FLAG_READ_VERSION (1UL << 6)
+#define HCI_FLAG_DEVICE_FOUND (1UL << 7)
+#define HCI_FLAG_CONNECT_EVENT (1UL << 8)
+
+/* Macros for HCI event flag tests */
+#define hci_check_flag(flag) (hci_event_flag & (flag))
+#define hci_set_flag(flag) (hci_event_flag |= (flag))
+#define hci_clear_flag(flag) (hci_event_flag &= ~(flag))
+
+/* HCI Events managed */
+#define EV_INQUIRY_COMPLETE 0x01
+#define EV_INQUIRY_RESULT 0x02
+#define EV_CONNECT_COMPLETE 0x03
+#define EV_INCOMING_CONNECT 0x04
+#define EV_DISCONNECT_COMPLETE 0x05
+#define EV_AUTHENTICATION_COMPLETE 0x06
+#define EV_REMOTE_NAME_COMPLETE 0x07
+#define EV_ENCRYPTION_CHANGE 0x08
+#define EV_CHANGE_CONNECTION_LINK 0x09
+#define EV_ROLE_CHANGED 0x12
+#define EV_NUM_COMPLETE_PKT 0x13
+#define EV_PIN_CODE_REQUEST 0x16
+#define EV_LINK_KEY_REQUEST 0x17
+#define EV_LINK_KEY_NOTIFICATION 0x18
+#define EV_DATA_BUFFER_OVERFLOW 0x1A
+#define EV_MAX_SLOTS_CHANGE 0x1B
+#define EV_READ_REMOTE_VERSION_INFORMATION_COMPLETE 0x0C
+#define EV_QOS_SETUP_COMPLETE 0x0D
+#define EV_COMMAND_COMPLETE 0x0E
+#define EV_COMMAND_STATUS 0x0F
+#define EV_LOOPBACK_COMMAND 0x19
+#define EV_PAGE_SCAN_REP_MODE 0x20
+
+/* Bluetooth states for the different Bluetooth drivers */
+#define L2CAP_WAIT 0
+#define L2CAP_DONE 1
+
+/* Used for HID Control channel */
+#define L2CAP_CONTROL_CONNECT_REQUEST 2
+#define L2CAP_CONTROL_CONFIG_REQUEST 3
+#define L2CAP_CONTROL_SUCCESS 4
+#define L2CAP_CONTROL_DISCONNECT 5
+
+/* Used for HID Interrupt channel */
+#define L2CAP_INTERRUPT_SETUP 6
+#define L2CAP_INTERRUPT_CONNECT_REQUEST 7
+#define L2CAP_INTERRUPT_CONFIG_REQUEST 8
+#define L2CAP_INTERRUPT_DISCONNECT 9
+
+/* Used for SDP channel */
+#define L2CAP_SDP_WAIT 10
+#define L2CAP_SDP_SUCCESS 11
+
+/* Used for RFCOMM channel */
+#define L2CAP_RFCOMM_WAIT 12
+#define L2CAP_RFCOMM_SUCCESS 13
+
+#define L2CAP_DISCONNECT_RESPONSE 14 // Used for both SDP and RFCOMM channel
+
+/* Bluetooth states used by some drivers */
+#define TURN_ON_LED 17
+#define PS3_ENABLE_SIXAXIS 18
+#define WII_CHECK_MOTION_PLUS_STATE 19
+#define WII_CHECK_EXTENSION_STATE 20
+#define WII_INIT_MOTION_PLUS_STATE 21
+
+/* L2CAP event flags for HID Control channel */
+#define L2CAP_FLAG_CONNECTION_CONTROL_REQUEST (1UL << 0)
+#define L2CAP_FLAG_CONFIG_CONTROL_SUCCESS (1UL << 1)
+#define L2CAP_FLAG_CONTROL_CONNECTED (1UL << 2)
+#define L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE (1UL << 3)
+
+/* L2CAP event flags for HID Interrupt channel */
+#define L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST (1UL << 4)
+#define L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS (1UL << 5)
+#define L2CAP_FLAG_INTERRUPT_CONNECTED (1UL << 6)
+#define L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE (1UL << 7)
+
+/* L2CAP event flags for SDP channel */
+#define L2CAP_FLAG_CONNECTION_SDP_REQUEST (1UL << 8)
+#define L2CAP_FLAG_CONFIG_SDP_SUCCESS (1UL << 9)
+#define L2CAP_FLAG_DISCONNECT_SDP_REQUEST (1UL << 10)
+
+/* L2CAP event flags for RFCOMM channel */
+#define L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST (1UL << 11)
+#define L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS (1UL << 12)
+#define L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST (1UL << 13)
+
+#define L2CAP_FLAG_DISCONNECT_RESPONSE (1UL << 14)
+
+/* Macros for L2CAP event flag tests */
+#define l2cap_check_flag(flag) (l2cap_event_flag & (flag))
+#define l2cap_set_flag(flag) (l2cap_event_flag |= (flag))
+#define l2cap_clear_flag(flag) (l2cap_event_flag &= ~(flag))
+
+/* L2CAP signaling commands */
+#define L2CAP_CMD_COMMAND_REJECT 0x01
+#define L2CAP_CMD_CONNECTION_REQUEST 0x02
+#define L2CAP_CMD_CONNECTION_RESPONSE 0x03
+#define L2CAP_CMD_CONFIG_REQUEST 0x04
+#define L2CAP_CMD_CONFIG_RESPONSE 0x05
+#define L2CAP_CMD_DISCONNECT_REQUEST 0x06
+#define L2CAP_CMD_DISCONNECT_RESPONSE 0x07
+#define L2CAP_CMD_INFORMATION_REQUEST 0x0A
+#define L2CAP_CMD_INFORMATION_RESPONSE 0x0B
+
+// Used For Connection Response - Remember to Include High Byte
+#define PENDING 0x01
+#define SUCCESSFUL 0x00
+
+/* Bluetooth L2CAP PSM - see http://www.bluetooth.org/Technical/AssignedNumbers/logical_link.htm */
+#define SDP_PSM 0x01 // Service Discovery Protocol PSM Value
+#define RFCOMM_PSM 0x03 // RFCOMM PSM Value
+#define HID_CTRL_PSM 0x11 // HID_Control PSM Value
+#define HID_INTR_PSM 0x13 // HID_Interrupt PSM Value
+
+// Used to determine if it is a Bluetooth dongle
+#define WI_SUBCLASS_RF 0x01 // RF Controller
+#define WI_PROTOCOL_BT 0x01 // Bluetooth Programming Interface
+
+#define BTD_MAX_ENDPOINTS 4
+#define BTD_NUM_SERVICES 4 // Max number of Bluetooth services - if you need more than 4 simply increase this number
+
+#define PAIR 1
+
+class BluetoothService;
+
+/**
+ * The Bluetooth Dongle class will take care of all the USB communication
+ * and then pass the data to the BluetoothService classes.
+ */
+class BTD : public USBDeviceConfig, public UsbConfigXtracter {
+public:
+ /**
+ * Constructor for the BTD class.
+ * @param p Pointer to USB class instance.
+ */
+ BTD(USB *p);
+
+ /** @name USBDeviceConfig implementation */
+ /**
+ * Address assignment and basic initialization is done here.
+ * @param parent Hub number.
+ * @param port Port number on the hub.
+ * @param lowspeed Speed of the device.
+ * @return 0 on success.
+ */
+ uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed);
+ /**
+ * Initialize the Bluetooth dongle.
+ * @param parent Hub number.
+ * @param port Port number on the hub.
+ * @param lowspeed Speed of the device.
+ * @return 0 on success.
+ */
+ uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
+ /**
+ * Release the USB device.
+ * @return 0 on success.
+ */
+ uint8_t Release();
+ /**
+ * Poll the USB Input endpoints and run the state machines.
+ * @return 0 on success.
+ */
+ uint8_t Poll();
+
+ /**
+ * Get the device address.
+ * @return The device address.
+ */
+ virtual uint8_t GetAddress() {
+ return bAddress;
+ };
+
+ /**
+ * Used to check if the dongle has been initialized.
+ * @return True if it's ready.
+ */
+ virtual bool isReady() {
+ return bPollEnable;
+ };
+
+ /**
+ * Used by the USB core to check what this driver support.
+ * @param klass The device's USB class.
+ * @return Returns true if the device's USB class matches this driver.
+ */
+ virtual bool DEVCLASSOK(uint8_t klass) {
+ return (klass == USB_CLASS_WIRELESS_CTRL);
+ };
+
+ /**
+ * Used by the USB core to check what this driver support.
+ * Used to set the Bluetooth address into the PS3 controllers.
+ * @param vid The device's VID.
+ * @param pid The device's PID.
+ * @return Returns true if the device's VID and PID matches this driver.
+ */
+ virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {
+ if(vid == IOGEAR_GBU521_VID && pid == IOGEAR_GBU521_PID)
+ return true;
+ if(my_bdaddr[0] != 0x00 || my_bdaddr[1] != 0x00 || my_bdaddr[2] != 0x00 || my_bdaddr[3] != 0x00 || my_bdaddr[4] != 0x00 || my_bdaddr[5] != 0x00) { // Check if Bluetooth address is set
+ if(vid == PS3_VID && (pid == PS3_PID || pid == PS3NAVIGATION_PID || pid == PS3MOVE_PID))
+ return true;
+ }
+ return false;
+ };
+ /**@}*/
+
+ /** @name UsbConfigXtracter implementation */
+ /**
+ * UsbConfigXtracter implementation, used to extract endpoint information.
+ * @param conf Configuration value.
+ * @param iface Interface number.
+ * @param alt Alternate setting.
+ * @param proto Interface Protocol.
+ * @param ep Endpoint Descriptor.
+ */
+ void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
+ /**@}*/
+
+ /** Disconnects both the L2CAP Channel and the HCI Connection for all Bluetooth services. */
+ void disconnect();
+
+ /**
+ * Register Bluetooth dongle members/services.
+ * @param pService Pointer to BluetoothService class instance.
+ * @return The service ID on success or -1 on fail.
+ */
+ int8_t registerBluetoothService(BluetoothService *pService) {
+ for(uint8_t i = 0; i < BTD_NUM_SERVICES; i++) {
+ if(!btService[i]) {
+ btService[i] = pService;
+ return i; // Return ID
+ }
+ }
+ return -1; // Error registering BluetoothService
+ };
+
+ /** @name HCI Commands */
+ /**
+ * Used to send a HCI Command.
+ * @param data Data to send.
+ * @param nbytes Number of bytes to send.
+ */
+ void HCI_Command(uint8_t* data, uint16_t nbytes);
+ /** Reset the Bluetooth dongle. */
+ void hci_reset();
+ /** Read the Bluetooth address of the dongle. */
+ void hci_read_bdaddr();
+ /** Read the HCI Version of the Bluetooth dongle. */
+ void hci_read_local_version_information();
+ /**
+ * Set the local name of the Bluetooth dongle.
+ * @param name Desired name.
+ */
+ void hci_set_local_name(const char* name);
+ /** Enable visibility to other Bluetooth devices. */
+ void hci_write_scan_enable();
+ /** Disable visibility to other Bluetooth devices. */
+ void hci_write_scan_disable();
+ /** Read the remote devices name. */
+ void hci_remote_name();
+ /** Accept the connection with the Bluetooth device. */
+ void hci_accept_connection();
+ /**
+ * Disconnect the HCI connection.
+ * @param handle The HCI Handle for the connection.
+ */
+ void hci_disconnect(uint16_t handle);
+ /**
+ * Respond with the pin for the connection.
+ * The pin is automatically set for the Wii library,
+ * but can be customized for the SPP library.
+ */
+ void hci_pin_code_request_reply();
+ /** Respons when no pin was set. */
+ void hci_pin_code_negative_request_reply();
+ /**
+ * Command is used to reply to a Link Key Request event from the BR/EDR Controller
+ * if the Host does not have a stored Link Key for the connection.
+ */
+ void hci_link_key_request_negative_reply();
+ /** Used to try to authenticate with the remote device. */
+ void hci_authentication_request();
+ /** Start a HCI inquiry. */
+ void hci_inquiry();
+ /** Cancel a HCI inquiry. */
+ void hci_inquiry_cancel();
+ /** Connect to last device communicated with. */
+ void hci_connect();
+ /**
+ * Connect to device.
+ * @param bdaddr Bluetooth address of the device.
+ */
+ void hci_connect(uint8_t *bdaddr);
+ /** Used to a set the class of the device. */
+ void hci_write_class_of_device();
+ /**@}*/
+
+ /** @name L2CAP Commands */
+ /**
+ * Used to send L2CAP Commands.
+ * @param handle HCI Handle.
+ * @param data Data to send.
+ * @param nbytes Number of bytes to send.
+ * @param channelLow,channelHigh Low and high byte of channel to send to.
+ * If argument is omitted then the Standard L2CAP header: Channel ID (0x01) for ACL-U will be used.
+ */
+ void L2CAP_Command(uint16_t handle, uint8_t* data, uint8_t nbytes, uint8_t channelLow = 0x01, uint8_t channelHigh = 0x00);
+ /**
+ * L2CAP Connection Request.
+ * @param handle HCI handle.
+ * @param rxid Identifier.
+ * @param scid Source Channel Identifier.
+ * @param psm Protocol/Service Multiplexer - see: https://www.bluetooth.org/Technical/AssignedNumbers/logical_link.htm.
+ */
+ void l2cap_connection_request(uint16_t handle, uint8_t rxid, uint8_t* scid, uint16_t psm);
+ /**
+ * L2CAP Connection Response.
+ * @param handle HCI handle.
+ * @param rxid Identifier.
+ * @param dcid Destination Channel Identifier.
+ * @param scid Source Channel Identifier.
+ * @param result Result - First send ::PENDING and then ::SUCCESSFUL.
+ */
+ void l2cap_connection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid, uint8_t result);
+ /**
+ * L2CAP Config Request.
+ * @param handle HCI Handle.
+ * @param rxid Identifier.
+ * @param dcid Destination Channel Identifier.
+ */
+ void l2cap_config_request(uint16_t handle, uint8_t rxid, uint8_t* dcid);
+ /**
+ * L2CAP Config Response.
+ * @param handle HCI Handle.
+ * @param rxid Identifier.
+ * @param scid Source Channel Identifier.
+ */
+ void l2cap_config_response(uint16_t handle, uint8_t rxid, uint8_t* scid);
+ /**
+ * L2CAP Disconnection Request.
+ * @param handle HCI Handle.
+ * @param rxid Identifier.
+ * @param dcid Device Channel Identifier.
+ * @param scid Source Channel Identifier.
+ */
+ void l2cap_disconnection_request(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid);
+ /**
+ * L2CAP Disconnection Response.
+ * @param handle HCI Handle.
+ * @param rxid Identifier.
+ * @param dcid Device Channel Identifier.
+ * @param scid Source Channel Identifier.
+ */
+ void l2cap_disconnection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid);
+ /**
+ * L2CAP Information Response.
+ * @param handle HCI Handle.
+ * @param rxid Identifier.
+ * @param infoTypeLow,infoTypeHigh Infotype.
+ */
+ void l2cap_information_response(uint16_t handle, uint8_t rxid, uint8_t infoTypeLow, uint8_t infoTypeHigh);
+ /**@}*/
+
+ /** Use this to see if it is waiting for a incoming connection. */
+ bool watingForConnection;
+ /** This is used by the service to know when to store the device information. */
+ bool l2capConnectionClaimed;
+ /** This is used by the SPP library to claim the current SDP incoming request. */
+ bool sdpConnectionClaimed;
+ /** This is used by the SPP library to claim the current RFCOMM incoming request. */
+ bool rfcommConnectionClaimed;
+
+ /** The name you wish to make the dongle show up as. It is set automatically by the SPP library. */
+ const char* btdName;
+ /** The pin you wish to make the dongle use for authentication. It is set automatically by the SPP and BTHID library. */
+ const char* btdPin;
+
+ /** The bluetooth dongles Bluetooth address. */
+ uint8_t my_bdaddr[6];
+ /** HCI handle for the last connection. */
+ uint16_t hci_handle;
+ /** Last incoming devices Bluetooth address. */
+ uint8_t disc_bdaddr[6];
+ /** First 30 chars of last remote name. */
+ char remote_name[30];
+ /**
+ * The supported HCI Version read from the Bluetooth dongle.
+ * Used by the PS3BT library to check the HCI Version of the Bluetooth dongle,
+ * it should be at least 3 to work properly with the library.
+ */
+ uint8_t hci_version;
+
+ /** Call this function to pair with a Wiimote */
+ void pairWithWiimote() {
+ pairWithWii = true;
+ hci_state = HCI_CHECK_DEVICE_SERVICE;
+ };
+ /** Used to only send the ACL data to the Wiimote. */
+ bool connectToWii;
+ /** True if a Wiimote is connecting. */
+ bool incomingWii;
+ /** True when it should pair with a Wiimote. */
+ bool pairWithWii;
+ /** True if it's the new Wiimote with the Motion Plus Inside or a Wii U Pro Controller. */
+ bool motionPlusInside;
+ /** True if it's a Wii U Pro Controller. */
+ bool wiiUProController;
+
+ /** Call this function to pair with a Wiimote */
+ void pairWithHID() {
+ pairWithHIDDevice = true;
+ hci_state = HCI_CHECK_DEVICE_SERVICE;
+ };
+ /** Used to only send the ACL data to the Wiimote. */
+ bool connectToHIDDevice;
+ /** True if a Wiimote is connecting. */
+ bool incomingHIDDevice;
+ /** True when it should pair with a device like a mouse or keyboard. */
+ bool pairWithHIDDevice;
+
+ /**
+ * Read the poll interval taken from the endpoint descriptors.
+ * @return The poll interval in ms.
+ */
+ uint8_t readPollInterval() {
+ return pollInterval;
+ };
+
+protected:
+ /** Pointer to USB class instance. */
+ USB *pUsb;
+ /** Device address. */
+ uint8_t bAddress;
+ /** Endpoint info structure. */
+ EpInfo epInfo[BTD_MAX_ENDPOINTS];
+
+ /** Configuration number. */
+ uint8_t bConfNum;
+ /** Total number of endpoints in the configuration. */
+ uint8_t bNumEP;
+ /** Next poll time based on poll interval taken from the USB descriptor. */
+ uint32_t qNextPollTime;
+
+ /** Bluetooth dongle control endpoint. */
+ static const uint8_t BTD_CONTROL_PIPE;
+ /** HCI event endpoint index. */
+ static const uint8_t BTD_EVENT_PIPE;
+ /** ACL In endpoint index. */
+ static const uint8_t BTD_DATAIN_PIPE;
+ /** ACL Out endpoint index. */
+ static const uint8_t BTD_DATAOUT_PIPE;
+
+ /**
+ * Used to print the USB Endpoint Descriptor.
+ * @param ep_ptr Pointer to USB Endpoint Descriptor.
+ */
+ void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr);
+
+private:
+ void Initialize(); // Set all variables, endpoint structs etc. to default values
+ BluetoothService *btService[BTD_NUM_SERVICES];
+
+ uint16_t PID, VID; // PID and VID of device connected
+
+ uint8_t pollInterval;
+ bool bPollEnable;
+
+ bool pairWiiUsingSync; // True if paring was done using the Wii SYNC button.
+ bool checkRemoteName; // Used to check remote device's name before connecting.
+ bool incomingPS4; // True if a PS4 controller is connecting
+ uint8_t classOfDevice[3]; // Class of device of last device
+
+ /* Variables used by high level HCI task */
+ uint8_t hci_state; // Current state of Bluetooth HCI connection
+ uint16_t hci_counter; // Counter used for Bluetooth HCI reset loops
+ uint16_t hci_num_reset_loops; // This value indicate how many times it should read before trying to reset
+ uint16_t hci_event_flag; // HCI flags of received Bluetooth events
+ uint8_t inquiry_counter;
+
+ uint8_t hcibuf[BULK_MAXPKTSIZE]; // General purpose buffer for HCI data
+ uint8_t l2capinbuf[BULK_MAXPKTSIZE]; // General purpose buffer for L2CAP in data
+ uint8_t l2capoutbuf[14]; // General purpose buffer for L2CAP out data
+
+ /* State machines */
+ void HCI_event_task(); // Poll the HCI event pipe
+ void HCI_task(); // HCI state machine
+ void ACL_event_task(); // ACL input pipe
+
+ /* Used to set the Bluetooth Address internally to the PS3 Controllers */
+ void setBdaddr(uint8_t* BDADDR);
+ void setMoveBdaddr(uint8_t* BDADDR);
+};
+
+/** All Bluetooth services should inherit this class. */
+class BluetoothService {
+public:
+ BluetoothService(BTD *p) : pBtd(p) {
+ if(pBtd)
+ pBtd->registerBluetoothService(this); // Register it as a Bluetooth service
+ };
+ /**
+ * Used to pass acldata to the Bluetooth service.
+ * @param ACLData Pointer to the incoming acldata.
+ */
+ virtual void ACLData(uint8_t* ACLData) = 0;
+ /** Used to run the different state machines in the Bluetooth service. */
+ virtual void Run() = 0;
+ /** Used to reset the Bluetooth service. */
+ virtual void Reset() = 0;
+ /** Used to disconnect both the L2CAP Channel and the HCI Connection for the Bluetooth service. */
+ virtual void disconnect() = 0;
+
+ /**
+ * Used to call your own function when the device is successfully initialized.
+ * @param funcOnInit Function to call.
+ */
+ void attachOnInit(void (*funcOnInit)(void)) {
+ pFuncOnInit = funcOnInit; // TODO: This really belong in a class of it's own as it is repeated several times
+ };
+
+protected:
+ /**
+ * Called when a device is successfully initialized.
+ * Use attachOnInit(void (*funcOnInit)(void)) to call your own function.
+ * This is useful for instance if you want to set the LEDs in a specific way.
+ */
+ virtual void onInit() = 0;
+
+ /** Used to check if the incoming L2CAP data matches the HCI Handle */
+ bool checkHciHandle(uint8_t *buf, uint16_t handle) {
+ return (buf[0] == (handle & 0xFF)) && (buf[1] == ((handle >> 8) | 0x20));
+ }
+
+ /** Pointer to function called in onInit(). */
+ void (*pFuncOnInit)(void);
+
+ /** Pointer to BTD instance. */
+ BTD *pBtd;
+
+ /** The HCI Handle for the connection. */
+ uint16_t hci_handle;
+
+ /** L2CAP flags of received Bluetooth events. */
+ uint32_t l2cap_event_flag;
+
+ /** Identifier for L2CAP commands. */
+ uint8_t identifier;
+};
+
+#endif
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTHID.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTHID.cpp
new file mode 100644
index 000000000..bfa9202c3
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTHID.cpp
@@ -0,0 +1,399 @@
+/* Copyright (C) 2013 Kristian Lauszus, TKJ Electronics. All rights reserved.
+
+ This software may be distributed and modified under the terms of the GNU
+ General Public License version 2 (GPL2) as published by the Free Software
+ Foundation and appearing in the file GPL2.TXT included in the packaging of
+ this file. Please note that GPL2 Section 2[b] requires that all works based
+ on this software must also be made publicly available under the terms of
+ the GPL2 ("Copyleft").
+
+ Contact information
+ -------------------
+
+ Kristian Lauszus, TKJ Electronics
+ Web : http://www.tkjelectronics.com
+ e-mail : kristianl@tkjelectronics.com
+ */
+
+#include "BTHID.h"
+// To enable serial debugging see "settings.h"
+//#define EXTRADEBUG // Uncomment to get even more debugging data
+//#define PRINTREPORT // Uncomment to print the report send by the HID device
+
+BTHID::BTHID(BTD *p, bool pair, const char *pin) :
+BluetoothService(p), // Pointer to USB class instance - mandatory
+protocolMode(HID_BOOT_PROTOCOL) {
+ for(uint8_t i = 0; i < NUM_PARSERS; i++)
+ pRptParser[i] = NULL;
+
+ pBtd->pairWithHIDDevice = pair;
+ pBtd->btdPin = pin;
+
+ /* Set device cid for the control and intterrupt channelse - LSB */
+ control_dcid[0] = 0x70; // 0x0070
+ control_dcid[1] = 0x00;
+ interrupt_dcid[0] = 0x71; // 0x0071
+ interrupt_dcid[1] = 0x00;
+
+ Reset();
+}
+
+void BTHID::Reset() {
+ connected = false;
+ activeConnection = false;
+ l2cap_event_flag = 0; // Reset flags
+ l2cap_state = L2CAP_WAIT;
+ ResetBTHID();
+}
+
+void BTHID::disconnect() { // Use this void to disconnect the device
+ // First the HID interrupt channel has to be disconnected, then the HID control channel and finally the HCI connection
+ pBtd->l2cap_disconnection_request(hci_handle, ++identifier, interrupt_scid, interrupt_dcid);
+ Reset();
+ l2cap_state = L2CAP_INTERRUPT_DISCONNECT;
+}
+
+void BTHID::ACLData(uint8_t* l2capinbuf) {
+ if(!pBtd->l2capConnectionClaimed && pBtd->incomingHIDDevice && !connected && !activeConnection) {
+ if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
+ if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) {
+ pBtd->incomingHIDDevice = false;
+ pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service
+ activeConnection = true;
+ hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection
+ l2cap_state = L2CAP_WAIT;
+ }
+ }
+ }
+
+ if(checkHciHandle(l2capinbuf, hci_handle)) { // acl_handle_ok
+ if((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { // l2cap_control - Channel ID for ACL-U
+ if(l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[17], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[16], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
+#endif
+ } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_RESPONSE) {
+ if(((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) && ((l2capinbuf[18] | (l2capinbuf[19] << 8)) == SUCCESSFUL)) { // Success
+ if(l2capinbuf[14] == control_dcid[0] && l2capinbuf[15] == control_dcid[1]) {
+ //Notify(PSTR("\r\nHID Control Connection Complete"), 0x80);
+ identifier = l2capinbuf[9];
+ control_scid[0] = l2capinbuf[12];
+ control_scid[1] = l2capinbuf[13];
+ l2cap_set_flag(L2CAP_FLAG_CONTROL_CONNECTED);
+ } else if(l2capinbuf[14] == interrupt_dcid[0] && l2capinbuf[15] == interrupt_dcid[1]) {
+ //Notify(PSTR("\r\nHID Interrupt Connection Complete"), 0x80);
+ identifier = l2capinbuf[9];
+ interrupt_scid[0] = l2capinbuf[12];
+ interrupt_scid[1] = l2capinbuf[13];
+ l2cap_set_flag(L2CAP_FLAG_INTERRUPT_CONNECTED);
+ }
+ }
+ } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
+#ifdef EXTRADEBUG
+ Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);
+ Notify(PSTR(" SCID: "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
+ Notify(PSTR(" Identifier: "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[9], 0x80);
+#endif
+ if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) {
+ identifier = l2capinbuf[9];
+ control_scid[0] = l2capinbuf[14];
+ control_scid[1] = l2capinbuf[15];
+ l2cap_set_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST);
+ } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) {
+ identifier = l2capinbuf[9];
+ interrupt_scid[0] = l2capinbuf[14];
+ interrupt_scid[1] = l2capinbuf[15];
+ l2cap_set_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST);
+ }
+ } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) {
+ if((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success
+ if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
+ //Notify(PSTR("\r\nHID Control Configuration Complete"), 0x80);
+ identifier = l2capinbuf[9];
+ l2cap_set_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS);
+ } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
+ //Notify(PSTR("\r\nHID Interrupt Configuration Complete"), 0x80);
+ identifier = l2capinbuf[9];
+ l2cap_set_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS);
+ }
+ }
+ } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) {
+ if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
+ //Notify(PSTR("\r\nHID Control Configuration Request"), 0x80);
+ pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], control_scid);
+ } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
+ //Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80);
+ pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], interrupt_scid);
+ }
+ } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) {
+ if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nDisconnect Request: Control Channel"), 0x80);
+#endif
+ identifier = l2capinbuf[9];
+ pBtd->l2cap_disconnection_response(hci_handle, identifier, control_dcid, control_scid);
+ Reset();
+ } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nDisconnect Request: Interrupt Channel"), 0x80);
+#endif
+ identifier = l2capinbuf[9];
+ pBtd->l2cap_disconnection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid);
+ Reset();
+ }
+ } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) {
+ if(l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) {
+ //Notify(PSTR("\r\nDisconnect Response: Control Channel"), 0x80);
+ identifier = l2capinbuf[9];
+ l2cap_set_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE);
+ } else if(l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) {
+ //Notify(PSTR("\r\nDisconnect Response: Interrupt Channel"), 0x80);
+ identifier = l2capinbuf[9];
+ l2cap_set_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE);
+ }
+ }
+#ifdef EXTRADEBUG
+ else {
+ identifier = l2capinbuf[9];
+ Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[8], 0x80);
+ }
+#endif
+ } else if(l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt
+#ifdef PRINTREPORT
+ Notify(PSTR("\r\nL2CAP Interrupt: "), 0x80);
+ for(uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) {
+ D_PrintHex<uint8_t > (l2capinbuf[i + 8], 0x80);
+ Notify(PSTR(" "), 0x80);
+ }
+#endif
+ if(l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT
+ uint16_t length = ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]);
+ ParseBTHIDData((uint8_t)(length - 1), &l2capinbuf[9]);
+
+ switch(l2capinbuf[9]) {
+ case 0x01: // Keyboard or Joystick events
+ if(pRptParser[KEYBOARD_PARSER_ID])
+ pRptParser[KEYBOARD_PARSER_ID]->Parse(reinterpret_cast<HID *>(this), 0, (uint8_t)(length - 2), &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance
+ break;
+
+ case 0x02: // Mouse events
+ if(pRptParser[MOUSE_PARSER_ID])
+ pRptParser[MOUSE_PARSER_ID]->Parse(reinterpret_cast<HID *>(this), 0, (uint8_t)(length - 2), &l2capinbuf[10]); // Use reinterpret_cast again to extract the instance
+ break;
+#ifdef EXTRADEBUG
+ default:
+ Notify(PSTR("\r\nUnknown Report type: "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[9], 0x80);
+ break;
+#endif
+ }
+ }
+ } else if(l2capinbuf[6] == control_dcid[0] && l2capinbuf[7] == control_dcid[1]) { // l2cap_control
+#ifdef PRINTREPORT
+ Notify(PSTR("\r\nL2CAP Control: "), 0x80);
+ for(uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) {
+ D_PrintHex<uint8_t > (l2capinbuf[i + 8], 0x80);
+ Notify(PSTR(" "), 0x80);
+ }
+#endif
+ }
+#ifdef EXTRADEBUG
+ else {
+ Notify(PSTR("\r\nUnsupported L2CAP Data - Channel ID: "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[7], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[6], 0x80);
+
+ Notify(PSTR("\r\nData: "), 0x80);
+ Notify(PSTR("\r\n"), 0x80);
+ for(uint16_t i = 0; i < ((uint16_t)l2capinbuf[5] << 8 | l2capinbuf[4]); i++) {
+ D_PrintHex<uint8_t > (l2capinbuf[i + 8], 0x80);
+ Notify(PSTR(" "), 0x80);
+ }
+ }
+#endif
+ L2CAP_task();
+ }
+}
+
+void BTHID::L2CAP_task() {
+ switch(l2cap_state) {
+ /* These states are used if the HID device is the host */
+ case L2CAP_CONTROL_SUCCESS:
+ if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80);
+#endif
+ setProtocol(); // Set protocol before establishing HID interrupt channel
+ l2cap_state = L2CAP_INTERRUPT_SETUP;
+ }
+ break;
+
+ case L2CAP_INTERRUPT_SETUP:
+ if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST)) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80);
+#endif
+ pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, PENDING);
+ delay(1);
+ pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, SUCCESSFUL);
+ identifier++;
+ delay(1);
+ pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid);
+
+ l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST;
+ }
+ break;
+
+ /* These states are used if the Arduino is the host */
+ case L2CAP_CONTROL_CONNECT_REQUEST:
+ if(l2cap_check_flag(L2CAP_FLAG_CONTROL_CONNECTED)) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nSend HID Control Config Request"), 0x80);
+#endif
+ identifier++;
+ pBtd->l2cap_config_request(hci_handle, identifier, control_scid);
+ l2cap_state = L2CAP_CONTROL_CONFIG_REQUEST;
+ }
+ break;
+
+ case L2CAP_CONTROL_CONFIG_REQUEST:
+ if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) {
+ setProtocol(); // Set protocol before establishing HID interrupt channel
+ delay(1); // Short delay between commands - just to be sure
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nSend HID Interrupt Connection Request"), 0x80);
+#endif
+ identifier++;
+ pBtd->l2cap_connection_request(hci_handle, identifier, interrupt_dcid, HID_INTR_PSM);
+ l2cap_state = L2CAP_INTERRUPT_CONNECT_REQUEST;
+ }
+ break;
+
+ case L2CAP_INTERRUPT_CONNECT_REQUEST:
+ if(l2cap_check_flag(L2CAP_FLAG_INTERRUPT_CONNECTED)) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nSend HID Interrupt Config Request"), 0x80);
+#endif
+ identifier++;
+ pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid);
+ l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST;
+ }
+ break;
+
+ case L2CAP_INTERRUPT_CONFIG_REQUEST:
+ if(l2cap_check_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS)) { // Now the HID channels is established
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nHID Channels Established"), 0x80);
+#endif
+ pBtd->connectToHIDDevice = false;
+ pBtd->pairWithHIDDevice = false;
+ connected = true;
+ onInit();
+ l2cap_state = L2CAP_DONE;
+ }
+ break;
+
+ case L2CAP_DONE:
+ break;
+
+ case L2CAP_INTERRUPT_DISCONNECT:
+ if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE)) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80);
+#endif
+ identifier++;
+ pBtd->l2cap_disconnection_request(hci_handle, identifier, control_scid, control_dcid);
+ l2cap_state = L2CAP_CONTROL_DISCONNECT;
+ }
+ break;
+
+ case L2CAP_CONTROL_DISCONNECT:
+ if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE)) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nDisconnected Control Channel"), 0x80);
+#endif
+ pBtd->hci_disconnect(hci_handle);
+ hci_handle = -1; // Reset handle
+ l2cap_event_flag = 0; // Reset flags
+ l2cap_state = L2CAP_WAIT;
+ }
+ break;
+ }
+}
+
+void BTHID::Run() {
+ switch(l2cap_state) {
+ case L2CAP_WAIT:
+ if(pBtd->connectToHIDDevice && !pBtd->l2capConnectionClaimed && !connected && !activeConnection) {
+ pBtd->l2capConnectionClaimed = true;
+ activeConnection = true;
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nSend HID Control Connection Request"), 0x80);
+#endif
+ hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection
+ l2cap_event_flag = 0; // Reset flags
+ identifier = 0;
+ pBtd->l2cap_connection_request(hci_handle, identifier, control_dcid, HID_CTRL_PSM);
+ l2cap_state = L2CAP_CONTROL_CONNECT_REQUEST;
+ } else if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST)) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80);
+#endif
+ pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, PENDING);
+ delay(1);
+ pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, SUCCESSFUL);
+ identifier++;
+ delay(1);
+ pBtd->l2cap_config_request(hci_handle, identifier, control_scid);
+ l2cap_state = L2CAP_CONTROL_SUCCESS;
+ }
+ break;
+ }
+}
+
+/************************************************************/
+/* HID Commands */
+
+/************************************************************/
+void BTHID::setProtocol() {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nSet protocol mode: "), 0x80);
+ D_PrintHex<uint8_t > (protocolMode, 0x80);
+#endif
+ if (protocolMode != HID_BOOT_PROTOCOL && protocolMode != HID_RPT_PROTOCOL) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nNot a valid protocol mode. Using Boot protocol instead."), 0x80);
+#endif
+ protocolMode = HID_BOOT_PROTOCOL; // Use Boot Protocol by default
+ }
+ uint8_t command = 0x70 | protocolMode; // Set Protocol, see Bluetooth HID specs page 33
+ pBtd->L2CAP_Command(hci_handle, &command, 1, control_scid[0], control_scid[1]);
+}
+
+void BTHID::setLeds(uint8_t data) {
+ uint8_t buf[3];
+ buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
+ buf[1] = 0x01; // Report ID
+ buf[2] = data;
+ pBtd->L2CAP_Command(hci_handle, buf, 3, interrupt_scid[0], interrupt_scid[1]);
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTHID.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTHID.h
new file mode 100644
index 000000000..1a7d8687c
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/BTHID.h
@@ -0,0 +1,155 @@
+/* Copyright (C) 2013 Kristian Lauszus, TKJ Electronics. All rights reserved.
+
+ This software may be distributed and modified under the terms of the GNU
+ General Public License version 2 (GPL2) as published by the Free Software
+ Foundation and appearing in the file GPL2.TXT included in the packaging of
+ this file. Please note that GPL2 Section 2[b] requires that all works based
+ on this software must also be made publicly available under the terms of
+ the GPL2 ("Copyleft").
+
+ Contact information
+ -------------------
+
+ Kristian Lauszus, TKJ Electronics
+ Web : http://www.tkjelectronics.com
+ e-mail : kristianl@tkjelectronics.com
+ */
+
+#ifndef _bthid_h_
+#define _bthid_h_
+
+#include "BTD.h"
+#include "hidboot.h"
+
+#define KEYBOARD_PARSER_ID 0
+#define MOUSE_PARSER_ID 1
+#define NUM_PARSERS 2
+
+/** This BluetoothService class implements support for Bluetooth HID devices. */
+class BTHID : public BluetoothService {
+public:
+ /**
+ * Constructor for the BTHID class.
+ * @param p Pointer to the BTD class instance.
+ * @param pair Set this to true in order to pair with the device. If the argument is omitted then it will not pair with it. One can use ::PAIR to set it to true.
+ * @param pin Write the pin to BTD#btdPin. If argument is omitted, then "0000" will be used.
+ */
+ BTHID(BTD *p, bool pair = false, const char *pin = "0000");
+
+ /** @name BluetoothService implementation */
+ /** Used this to disconnect the devices. */
+ void disconnect();
+ /**@}*/
+
+ /**
+ * Get HIDReportParser.
+ * @param id ID of parser.
+ * @return Returns the corresponding HIDReportParser. Returns NULL if id is not valid.
+ */
+ HIDReportParser *GetReportParser(uint8_t id) {
+ if (id >= NUM_PARSERS)
+ return NULL;
+ return pRptParser[id];
+ };
+
+ /**
+ * Set HIDReportParser to be used.
+ * @param id Id of parser.
+ * @param prs Pointer to HIDReportParser.
+ * @return Returns true if the HIDReportParser is set. False otherwise.
+ */
+ bool SetReportParser(uint8_t id, HIDReportParser *prs) {
+ if (id >= NUM_PARSERS)
+ return false;
+ pRptParser[id] = prs;
+ return true;
+ };
+
+ /**
+ * Set HID protocol mode.
+ * @param mode HID protocol to use. Either HID_BOOT_PROTOCOL or HID_RPT_PROTOCOL.
+ */
+ void setProtocolMode(uint8_t mode) {
+ protocolMode = mode;
+ };
+
+ /**
+ * Used to set the leds on a keyboard.
+ * @param data See KBDLEDS in hidboot.h
+ */
+ void setLeds(uint8_t data);
+
+ /** True if a device is connected */
+ bool connected;
+
+ /** Call this to start the paring sequence with a device */
+ void pair(void) {
+ if(pBtd)
+ pBtd->pairWithHID();
+ };
+
+protected:
+ /** @name BluetoothService implementation */
+ /**
+ * Used to pass acldata to the services.
+ * @param ACLData Incoming acldata.
+ */
+ void ACLData(uint8_t* ACLData);
+ /** Used to run part of the state machine. */
+ void Run();
+ /** Use this to reset the service. */
+ void Reset();
+ /**
+ * Called when a device is successfully initialized.
+ * Use attachOnInit(void (*funcOnInit)(void)) to call your own function.
+ * This is useful for instance if you want to set the LEDs in a specific way.
+ */
+ void onInit() {
+ if(pFuncOnInit)
+ pFuncOnInit(); // Call the user function
+ OnInitBTHID();
+ };
+ /**@}*/
+
+ /** @name Overridable functions */
+ /**
+ * Used to parse Bluetooth HID data to any class that inherits this class.
+ * @param len The length of the incoming data.
+ * @param buf Pointer to the data buffer.
+ */
+ virtual void ParseBTHIDData(uint8_t len, uint8_t *buf) {
+ return;
+ };
+ /** Called when a device is connected */
+ virtual void OnInitBTHID() {
+ return;
+ };
+ /** Used to reset any buffers in the class that inherits this */
+ virtual void ResetBTHID() {
+ return;
+ }
+ /**@}*/
+
+ /** L2CAP source CID for HID_Control */
+ uint8_t control_scid[2];
+
+ /** L2CAP source CID for HID_Interrupt */
+ uint8_t interrupt_scid[2];
+
+private:
+ HIDReportParser *pRptParser[NUM_PARSERS]; // Pointer to HIDReportParsers.
+
+ /** Set report protocol. */
+ void setProtocol();
+ uint8_t protocolMode;
+
+ void L2CAP_task(); // L2CAP state machine
+
+ bool activeConnection; // Used to indicate if it already has established a connection
+
+ /* Variables used for L2CAP communication */
+ uint8_t control_dcid[2]; // L2CAP device CID for HID_Control - Always 0x0070
+ uint8_t interrupt_dcid[2]; // L2CAP device CID for HID_Interrupt - Always 0x0071
+ uint8_t l2cap_state;
+};
+#endif
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3BT.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3BT.cpp
new file mode 100644
index 000000000..235092e0a
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3BT.cpp
@@ -0,0 +1,634 @@
+/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
+
+ This software may be distributed and modified under the terms of the GNU
+ General Public License version 2 (GPL2) as published by the Free Software
+ Foundation and appearing in the file GPL2.TXT included in the packaging of
+ this file. Please note that GPL2 Section 2[b] requires that all works based
+ on this software must also be made publicly available under the terms of
+ the GPL2 ("Copyleft").
+
+ Contact information
+ -------------------
+
+ Kristian Lauszus, TKJ Electronics
+ Web : http://www.tkjelectronics.com
+ e-mail : kristianl@tkjelectronics.com
+ */
+
+#include "PS3BT.h"
+// To enable serial debugging see "settings.h"
+//#define EXTRADEBUG // Uncomment to get even more debugging data
+//#define PRINTREPORT // Uncomment to print the report send by the PS3 Controllers
+
+PS3BT::PS3BT(BTD *p, uint8_t btadr5, uint8_t btadr4, uint8_t btadr3, uint8_t btadr2, uint8_t btadr1, uint8_t btadr0) :
+BluetoothService(p) // Pointer to USB class instance - mandatory
+{
+ pBtd->my_bdaddr[5] = btadr5; // Change to your dongle's Bluetooth address instead
+ pBtd->my_bdaddr[4] = btadr4;
+ pBtd->my_bdaddr[3] = btadr3;
+ pBtd->my_bdaddr[2] = btadr2;
+ pBtd->my_bdaddr[1] = btadr1;
+ pBtd->my_bdaddr[0] = btadr0;
+
+ HIDBuffer[0] = 0x52; // HID BT Set_report (0x50) | Report Type (Output 0x02)
+ HIDBuffer[1] = 0x01; // Report ID
+
+ // Needed for PS3 Move Controller commands to work via bluetooth
+ HIDMoveBuffer[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
+ HIDMoveBuffer[1] = 0x02; // Report ID
+
+ /* Set device cid for the control and intterrupt channelse - LSB */
+ control_dcid[0] = 0x40; // 0x0040
+ control_dcid[1] = 0x00;
+ interrupt_dcid[0] = 0x41; // 0x0041
+ interrupt_dcid[1] = 0x00;
+
+ Reset();
+}
+
+bool PS3BT::getButtonPress(ButtonEnum b) {
+ return (ButtonState & pgm_read_dword(&PS3_BUTTONS[(uint8_t)b]));
+}
+
+bool PS3BT::getButtonClick(ButtonEnum b) {
+ uint32_t button = pgm_read_dword(&PS3_BUTTONS[(uint8_t)b]);
+ bool click = (ButtonClickState & button);
+ ButtonClickState &= ~button; // Clear "click" event
+ return click;
+}
+
+uint8_t PS3BT::getAnalogButton(ButtonEnum a) {
+ return (uint8_t)(l2capinbuf[pgm_read_byte(&PS3_ANALOG_BUTTONS[(uint8_t)a])]);
+}
+
+uint8_t PS3BT::getAnalogHat(AnalogHatEnum a) {
+ return (uint8_t)(l2capinbuf[(uint8_t)a + 15]);
+}
+
+int16_t PS3BT::getSensor(SensorEnum a) {
+ if(PS3Connected) {
+ if(a == aX || a == aY || a == aZ || a == gZ)
+ return ((l2capinbuf[(uint16_t)a] << 8) | l2capinbuf[(uint16_t)a + 1]);
+ else
+ return 0;
+ } else if(PS3MoveConnected) {
+ if(a == mXmove || a == mYmove) // These are all 12-bits long
+ return (((l2capinbuf[(uint16_t)a] & 0x0F) << 8) | (l2capinbuf[(uint16_t)a + 1]));
+ else if(a == mZmove || a == tempMove) // The tempearature is also 12 bits long
+ return ((l2capinbuf[(uint16_t)a] << 4) | ((l2capinbuf[(uint16_t)a + 1] & 0xF0) >> 4));
+ else // aXmove, aYmove, aZmove, gXmove, gYmove and gZmove
+ return (l2capinbuf[(uint16_t)a] | (l2capinbuf[(uint16_t)a + 1] << 8));
+ } else
+ return 0;
+}
+
+double PS3BT::getAngle(AngleEnum a) {
+ double accXval, accYval, accZval;
+
+ if(PS3Connected) {
+ // Data for the Kionix KXPC4 used in the DualShock 3
+ const double zeroG = 511.5; // 1.65/3.3*1023 (1.65V)
+ accXval = -((double)getSensor(aX) - zeroG);
+ accYval = -((double)getSensor(aY) - zeroG);
+ accZval = -((double)getSensor(aZ) - zeroG);
+ } else if(PS3MoveConnected) {
+ // It's a Kionix KXSC4 inside the Motion controller
+ const uint16_t zeroG = 0x8000;
+ accXval = -(int16_t)(getSensor(aXmove) - zeroG);
+ accYval = (int16_t)(getSensor(aYmove) - zeroG);
+ accZval = (int16_t)(getSensor(aZmove) - zeroG);
+ } else
+ return 0;
+
+ // Convert to 360 degrees resolution
+ // atan2 outputs the value of -π to π (radians)
+ // We are then converting it to 0 to 2π and then to degrees
+ if(a == Pitch)
+ return (atan2(accYval, accZval) + PI) * RAD_TO_DEG;
+ else
+ return (atan2(accXval, accZval) + PI) * RAD_TO_DEG;
+}
+
+double PS3BT::get9DOFValues(SensorEnum a) { // Thanks to Manfred Piendl
+ if(!PS3MoveConnected)
+ return 0;
+ int16_t value = getSensor(a);
+ if(a == mXmove || a == mYmove || a == mZmove) {
+ if(value > 2047)
+ value -= 0x1000;
+ return (double)value / 3.2; // unit: muT = 10^(-6) Tesla
+ } else if(a == aXmove || a == aYmove || a == aZmove) {
+ if(value < 0)
+ value += 0x8000;
+ else
+ value -= 0x8000;
+ return (double)value / 442.0; // unit: m/(s^2)
+ } else if(a == gXmove || a == gYmove || a == gZmove) {
+ if(value < 0)
+ value += 0x8000;
+ else
+ value -= 0x8000;
+ if(a == gXmove)
+ return (double)value / 11.6; // unit: deg/s
+ else if(a == gYmove)
+ return (double)value / 11.2; // unit: deg/s
+ else // gZmove
+ return (double)value / 9.6; // unit: deg/s
+ } else
+ return 0;
+}
+
+String PS3BT::getTemperature() {
+ if(PS3MoveConnected) {
+ int16_t input = getSensor(tempMove);
+
+ String output = String(input / 100);
+ output += ".";
+ if(input % 100 < 10)
+ output += "0";
+ output += String(input % 100);
+
+ return output;
+ } else
+ return "Error";
+}
+
+bool PS3BT::getStatus(StatusEnum c) {
+ return (l2capinbuf[(uint16_t)c >> 8] == ((uint8_t)c & 0xff));
+}
+
+void PS3BT::printStatusString() {
+ char statusOutput[100]; // Max string length plus null character
+ if(PS3Connected || PS3NavigationConnected) {
+ strcpy_P(statusOutput, PSTR("ConnectionStatus: "));
+
+ if(getStatus(Plugged)) strcat_P(statusOutput, PSTR("Plugged"));
+ else if(getStatus(Unplugged)) strcat_P(statusOutput, PSTR("Unplugged"));
+ else strcat_P(statusOutput, PSTR("Error"));
+
+ strcat_P(statusOutput, PSTR(" - PowerRating: "));
+
+ if(getStatus(Charging)) strcat_P(statusOutput, PSTR("Charging"));
+ else if(getStatus(NotCharging)) strcat_P(statusOutput, PSTR("Not Charging"));
+ else if(getStatus(Shutdown)) strcat_P(statusOutput, PSTR("Shutdown"));
+ else if(getStatus(Dying)) strcat_P(statusOutput, PSTR("Dying"));
+ else if(getStatus(Low)) strcat_P(statusOutput, PSTR("Low"));
+ else if(getStatus(High)) strcat_P(statusOutput, PSTR("High"));
+ else if(getStatus(Full)) strcat_P(statusOutput, PSTR("Full"));
+ else strcat_P(statusOutput, PSTR("Error"));
+
+ strcat_P(statusOutput, PSTR(" - WirelessStatus: "));
+
+ if(getStatus(CableRumble)) strcat_P(statusOutput, PSTR("Cable - Rumble is on"));
+ else if(getStatus(Cable)) strcat_P(statusOutput, PSTR("Cable - Rumble is off"));
+ else if(getStatus(BluetoothRumble)) strcat_P(statusOutput, PSTR("Bluetooth - Rumble is on"));
+ else if(getStatus(Bluetooth)) strcat_P(statusOutput, PSTR("Bluetooth - Rumble is off"));
+ else strcat_P(statusOutput, PSTR("Error"));
+ } else if(PS3MoveConnected) {
+ strcpy_P(statusOutput, PSTR("PowerRating: "));
+
+ if(getStatus(MoveCharging)) strcat_P(statusOutput, PSTR("Charging"));
+ else if(getStatus(MoveNotCharging)) strcat_P(statusOutput, PSTR("Not Charging"));
+ else if(getStatus(MoveShutdown)) strcat_P(statusOutput, PSTR("Shutdown"));
+ else if(getStatus(MoveDying)) strcat_P(statusOutput, PSTR("Dying"));
+ else if(getStatus(MoveLow)) strcat_P(statusOutput, PSTR("Low"));
+ else if(getStatus(MoveHigh)) strcat_P(statusOutput, PSTR("High"));
+ else if(getStatus(MoveFull)) strcat_P(statusOutput, PSTR("Full"));
+ else strcat_P(statusOutput, PSTR("Error"));
+ } else
+ strcpy_P(statusOutput, PSTR("Error"));
+
+ USB_HOST_SERIAL.write(statusOutput);
+}
+
+void PS3BT::Reset() {
+ PS3Connected = false;
+ PS3MoveConnected = false;
+ PS3NavigationConnected = false;
+ activeConnection = false;
+ l2cap_event_flag = 0; // Reset flags
+ l2cap_state = L2CAP_WAIT;
+
+ // Needed for PS3 Dualshock Controller commands to work via Bluetooth
+ for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++)
+ HIDBuffer[i + 2] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); // First two bytes reserved for report type and ID
+}
+
+void PS3BT::disconnect() { // Use this void to disconnect any of the controllers
+ // First the HID interrupt channel has to be disconnected, then the HID control channel and finally the HCI connection
+ pBtd->l2cap_disconnection_request(hci_handle, ++identifier, interrupt_scid, interrupt_dcid);
+ Reset();
+ l2cap_state = L2CAP_INTERRUPT_DISCONNECT;
+}
+
+void PS3BT::ACLData(uint8_t* ACLData) {
+ if(!pBtd->l2capConnectionClaimed && !PS3Connected && !PS3MoveConnected && !PS3NavigationConnected && !activeConnection && !pBtd->connectToWii && !pBtd->incomingWii && !pBtd->pairWithWii) {
+ if(ACLData[8] == L2CAP_CMD_CONNECTION_REQUEST) {
+ if((ACLData[12] | (ACLData[13] << 8)) == HID_CTRL_PSM) {
+ pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service
+ activeConnection = true;
+ hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection
+ l2cap_state = L2CAP_WAIT;
+ remote_name_first = pBtd->remote_name[0]; // Store the first letter in remote name for the connection
+#ifdef DEBUG_USB_HOST
+ if(pBtd->hci_version < 3) { // Check the HCI Version of the Bluetooth dongle
+ Notify(PSTR("\r\nYour dongle may not support reading the analog buttons, sensors and status\r\nYour HCI Version is: "), 0x80);
+ Notify(pBtd->hci_version, 0x80);
+ Notify(PSTR("\r\nBut should be at least 3\r\nThis means that it doesn't support Bluetooth Version 2.0+EDR"), 0x80);
+ }
+#endif
+ }
+ }
+ }
+
+ if(checkHciHandle(ACLData, hci_handle)) { // acl_handle_ok
+ memcpy(l2capinbuf, ACLData, BULK_MAXPKTSIZE);
+ if((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { // l2cap_control - Channel ID for ACL-U
+ if(l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);
+ Notify(PSTR(" Data: "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[17], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[16], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
+#endif
+ } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
+#ifdef EXTRADEBUG
+ Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);
+ Notify(PSTR(" SCID: "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
+ Notify(PSTR(" Identifier: "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[9], 0x80);
+#endif
+ if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) {
+ identifier = l2capinbuf[9];
+ control_scid[0] = l2capinbuf[14];
+ control_scid[1] = l2capinbuf[15];
+ l2cap_set_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST);
+ } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) {
+ identifier = l2capinbuf[9];
+ interrupt_scid[0] = l2capinbuf[14];
+ interrupt_scid[1] = l2capinbuf[15];
+ l2cap_set_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST);
+ }
+ } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) {
+ if((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success
+ if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
+ //Notify(PSTR("\r\nHID Control Configuration Complete"), 0x80);
+ l2cap_set_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS);
+ } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
+ //Notify(PSTR("\r\nHID Interrupt Configuration Complete"), 0x80);
+ l2cap_set_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS);
+ }
+ }
+ } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) {
+ if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
+ //Notify(PSTR("\r\nHID Control Configuration Request"), 0x80);
+ pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], control_scid);
+ } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
+ //Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80);
+ pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], interrupt_scid);
+ }
+ } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) {
+ if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nDisconnect Request: Control Channel"), 0x80);
+#endif
+ identifier = l2capinbuf[9];
+ pBtd->l2cap_disconnection_response(hci_handle, identifier, control_dcid, control_scid);
+ Reset();
+ } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nDisconnect Request: Interrupt Channel"), 0x80);
+#endif
+ identifier = l2capinbuf[9];
+ pBtd->l2cap_disconnection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid);
+ Reset();
+ }
+ } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) {
+ if(l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) {
+ //Notify(PSTR("\r\nDisconnect Response: Control Channel"), 0x80);
+ identifier = l2capinbuf[9];
+ l2cap_set_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE);
+ } else if(l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) {
+ //Notify(PSTR("\r\nDisconnect Response: Interrupt Channel"), 0x80);
+ identifier = l2capinbuf[9];
+ l2cap_set_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE);
+ }
+ }
+#ifdef EXTRADEBUG
+ else {
+ Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[8], 0x80);
+ }
+#endif
+ } else if(l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt
+ //Notify(PSTR("\r\nL2CAP Interrupt"), 0x80);
+ if(PS3Connected || PS3MoveConnected || PS3NavigationConnected) {
+ /* Read Report */
+ if(l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT
+ lastMessageTime = millis(); // Store the last message time
+
+ if(PS3Connected || PS3NavigationConnected)
+ ButtonState = (uint32_t)(l2capinbuf[11] | ((uint16_t)l2capinbuf[12] << 8) | ((uint32_t)l2capinbuf[13] << 16));
+ else if(PS3MoveConnected)
+ ButtonState = (uint32_t)(l2capinbuf[10] | ((uint16_t)l2capinbuf[11] << 8) | ((uint32_t)l2capinbuf[12] << 16));
+
+ //Notify(PSTR("\r\nButtonState", 0x80);
+ //PrintHex<uint32_t>(ButtonState, 0x80);
+
+ if(ButtonState != OldButtonState) {
+ ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable
+ OldButtonState = ButtonState;
+ }
+
+#ifdef PRINTREPORT // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers
+ for(uint8_t i = 10; i < 58; i++) {
+ D_PrintHex<uint8_t > (l2capinbuf[i], 0x80);
+ Notify(PSTR(" "), 0x80);
+ }
+ Notify(PSTR("\r\n"), 0x80);
+#endif
+ }
+ }
+ }
+ L2CAP_task();
+ }
+}
+
+void PS3BT::L2CAP_task() {
+ switch(l2cap_state) {
+ case L2CAP_WAIT:
+ if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST)) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80);
+#endif
+ pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, PENDING);
+ delay(1);
+ pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, SUCCESSFUL);
+ identifier++;
+ delay(1);
+ pBtd->l2cap_config_request(hci_handle, identifier, control_scid);
+ l2cap_state = L2CAP_CONTROL_SUCCESS;
+ }
+ break;
+
+ case L2CAP_CONTROL_SUCCESS:
+ if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80);
+#endif
+ l2cap_state = L2CAP_INTERRUPT_SETUP;
+ }
+ break;
+
+ case L2CAP_INTERRUPT_SETUP:
+ if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST)) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80);
+#endif
+ pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, PENDING);
+ delay(1);
+ pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, SUCCESSFUL);
+ identifier++;
+ delay(1);
+ pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid);
+
+ l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST;
+ }
+ break;
+
+ case L2CAP_INTERRUPT_CONFIG_REQUEST:
+ if(l2cap_check_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS)) { // Now the HID channels is established
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nHID Interrupt Successfully Configured"), 0x80);
+#endif
+ if(remote_name_first == 'M') { // First letter in Motion Controller ('M')
+ memset(l2capinbuf, 0, BULK_MAXPKTSIZE); // Reset l2cap in buffer as it sometimes read it as a button has been pressed
+ l2cap_state = TURN_ON_LED;
+ } else
+ l2cap_state = PS3_ENABLE_SIXAXIS;
+ timer = millis();
+ }
+ break;
+
+ /* These states are handled in Run() */
+
+ case L2CAP_INTERRUPT_DISCONNECT:
+ if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE)) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80);
+#endif
+ identifier++;
+ pBtd->l2cap_disconnection_request(hci_handle, identifier, control_scid, control_dcid);
+ l2cap_state = L2CAP_CONTROL_DISCONNECT;
+ }
+ break;
+
+ case L2CAP_CONTROL_DISCONNECT:
+ if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE)) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nDisconnected Control Channel"), 0x80);
+#endif
+ pBtd->hci_disconnect(hci_handle);
+ hci_handle = -1; // Reset handle
+ l2cap_event_flag = 0; // Reset flags
+ l2cap_state = L2CAP_WAIT;
+ }
+ break;
+ }
+}
+
+void PS3BT::Run() {
+ switch(l2cap_state) {
+ case PS3_ENABLE_SIXAXIS:
+ if(millis() - timer > 1000) { // loop 1 second before sending the command
+ memset(l2capinbuf, 0, BULK_MAXPKTSIZE); // Reset l2cap in buffer as it sometimes read it as a button has been pressed
+ for(uint8_t i = 15; i < 19; i++)
+ l2capinbuf[i] = 0x7F; // Set the analog joystick values to center position
+ enable_sixaxis();
+ l2cap_state = TURN_ON_LED;
+ timer = millis();
+ }
+ break;
+
+ case TURN_ON_LED:
+ if(millis() - timer > 1000) { // loop 1 second before sending the command
+ if(remote_name_first == 'P') { // First letter in PLAYSTATION(R)3 Controller ('P')
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nDualshock 3 Controller Enabled\r\n"), 0x80);
+#endif
+ PS3Connected = true;
+ } else if(remote_name_first == 'N') { // First letter in Navigation Controller ('N')
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nNavigation Controller Enabled\r\n"), 0x80);
+#endif
+ PS3NavigationConnected = true;
+ } else if(remote_name_first == 'M') { // First letter in Motion Controller ('M')
+ timer = millis();
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nMotion Controller Enabled\r\n"), 0x80);
+#endif
+ PS3MoveConnected = true;
+ }
+ ButtonState = 0; // Clear all values
+ OldButtonState = 0;
+ ButtonClickState = 0;
+
+ onInit(); // Turn on the LED on the controller
+ l2cap_state = L2CAP_DONE;
+ }
+ break;
+
+ case L2CAP_DONE:
+ if(PS3MoveConnected) { // The Bulb and rumble values, has to be send at approximately every 5th second for it to stay on
+ if(millis() - timer > 4000) { // Send at least every 4th second
+ HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE); // The Bulb and rumble values, has to be written again and again, for it to stay turned on
+ timer = millis();
+ }
+ }
+ break;
+ }
+}
+
+/************************************************************/
+/* HID Commands */
+/************************************************************/
+
+// Playstation Sixaxis Dualshock and Navigation Controller commands
+
+void PS3BT::HID_Command(uint8_t* data, uint8_t nbytes) {
+ if(millis() - timerHID <= 150) // Check if is has been more than 150ms since last command
+ delay((uint32_t)(150 - (millis() - timerHID))); // There have to be a delay between commands
+ pBtd->L2CAP_Command(hci_handle, data, nbytes, control_scid[0], control_scid[1]); // Both the Navigation and Dualshock controller sends data via the control channel
+ timerHID = millis();
+}
+
+void PS3BT::setAllOff() {
+ HIDBuffer[3] = 0x00; // Rumble bytes
+ HIDBuffer[4] = 0x00;
+ HIDBuffer[5] = 0x00;
+ HIDBuffer[6] = 0x00;
+
+ HIDBuffer[11] = 0x00; // LED byte
+
+ HID_Command(HIDBuffer, HID_BUFFERSIZE);
+}
+
+void PS3BT::setRumbleOff() {
+ HIDBuffer[3] = 0x00;
+ HIDBuffer[4] = 0x00;
+ HIDBuffer[5] = 0x00;
+ HIDBuffer[6] = 0x00;
+
+ HID_Command(HIDBuffer, HID_BUFFERSIZE);
+}
+
+void PS3BT::setRumbleOn(RumbleEnum mode) {
+ uint8_t power[2] = {0xff, 0x00}; // Defaults to RumbleLow
+ if(mode == RumbleHigh) {
+ power[0] = 0x00;
+ power[1] = 0xff;
+ }
+ setRumbleOn(0xfe, power[0], 0xfe, power[1]);
+}
+
+void PS3BT::setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower) {
+ HIDBuffer[3] = rightDuration;
+ HIDBuffer[4] = rightPower;
+ HIDBuffer[5] = leftDuration;
+ HIDBuffer[6] = leftPower;
+ HID_Command(HIDBuffer, HID_BUFFERSIZE);
+}
+
+void PS3BT::setLedRaw(uint8_t value) {
+ HIDBuffer[11] = value << 1;
+ HID_Command(HIDBuffer, HID_BUFFERSIZE);
+}
+
+void PS3BT::setLedOff(LEDEnum a) {
+ HIDBuffer[11] &= ~((uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1));
+ HID_Command(HIDBuffer, HID_BUFFERSIZE);
+}
+
+void PS3BT::setLedOn(LEDEnum a) {
+ if(a == OFF)
+ setLedRaw(0);
+ else {
+ HIDBuffer[11] |= (uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1);
+ HID_Command(HIDBuffer, HID_BUFFERSIZE);
+ }
+}
+
+void PS3BT::setLedToggle(LEDEnum a) {
+ HIDBuffer[11] ^= (uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1);
+ HID_Command(HIDBuffer, HID_BUFFERSIZE);
+}
+
+void PS3BT::enable_sixaxis() { // Command used to enable the Dualshock 3 and Navigation controller to send data via Bluetooth
+ uint8_t cmd_buf[6];
+ cmd_buf[0] = 0x53; // HID BT Set_report (0x50) | Report Type (Feature 0x03)
+ cmd_buf[1] = 0xF4; // Report ID
+ cmd_buf[2] = 0x42; // Special PS3 Controller enable commands
+ cmd_buf[3] = 0x03;
+ cmd_buf[4] = 0x00;
+ cmd_buf[5] = 0x00;
+
+ HID_Command(cmd_buf, 6);
+}
+
+// Playstation Move Controller commands
+
+void PS3BT::HIDMove_Command(uint8_t* data, uint8_t nbytes) {
+ if(millis() - timerHID <= 150)// Check if is has been less than 150ms since last command
+ delay((uint32_t)(150 - (millis() - timerHID))); // There have to be a delay between commands
+ pBtd->L2CAP_Command(hci_handle, data, nbytes, interrupt_scid[0], interrupt_scid[1]); // The Move controller sends it's data via the intterrupt channel
+ timerHID = millis();
+}
+
+void PS3BT::moveSetBulb(uint8_t r, uint8_t g, uint8_t b) { // Use this to set the Color using RGB values
+ // Set the Bulb's values into the write buffer
+ HIDMoveBuffer[3] = r;
+ HIDMoveBuffer[4] = g;
+ HIDMoveBuffer[5] = b;
+
+ HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE);
+}
+
+void PS3BT::moveSetBulb(ColorsEnum color) { // Use this to set the Color using the predefined colors in enum
+ moveSetBulb((uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color));
+}
+
+void PS3BT::moveSetRumble(uint8_t rumble) {
+#ifdef DEBUG_USB_HOST
+ if(rumble < 64 && rumble != 0) // The rumble value has to at least 64, or approximately 25% (64/255*100)
+ Notify(PSTR("\r\nThe rumble value has to at least 64, or approximately 25%"), 0x80);
+#endif
+ // Set the rumble value into the write buffer
+ HIDMoveBuffer[7] = rumble;
+
+ HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE);
+}
+
+void PS3BT::onInit() {
+ if(pFuncOnInit)
+ pFuncOnInit(); // Call the user function
+ else {
+ if(PS3MoveConnected)
+ moveSetBulb(Red);
+ else // Dualshock 3 or Navigation controller
+ setLedOn(LED1);
+ }
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3BT.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3BT.h
new file mode 100644
index 000000000..c25ac5e59
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3BT.h
@@ -0,0 +1,240 @@
+/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
+
+ This software may be distributed and modified under the terms of the GNU
+ General Public License version 2 (GPL2) as published by the Free Software
+ Foundation and appearing in the file GPL2.TXT included in the packaging of
+ this file. Please note that GPL2 Section 2[b] requires that all works based
+ on this software must also be made publicly available under the terms of
+ the GPL2 ("Copyleft").
+
+ Contact information
+ -------------------
+
+ Kristian Lauszus, TKJ Electronics
+ Web : http://www.tkjelectronics.com
+ e-mail : kristianl@tkjelectronics.com
+ */
+
+#ifndef _ps3bt_h_
+#define _ps3bt_h_
+
+#include "BTD.h"
+#include "PS3Enums.h"
+
+#define HID_BUFFERSIZE 50 // Size of the buffer for the Playstation Motion Controller
+
+/**
+ * This BluetoothService class implements support for all the official PS3 Controllers:
+ * Dualshock 3, Navigation or a Motion controller via Bluetooth.
+ *
+ * Information about the protocol can be found at the wiki: https://github.com/felis/USB_Host_Shield_2.0/wiki/PS3-Information.
+ */
+class PS3BT : public BluetoothService {
+public:
+ /**
+ * Constructor for the PS3BT class.
+ * @param pBtd Pointer to BTD class instance.
+ * @param btadr5,btadr4,btadr3,btadr2,btadr1,btadr0
+ * Pass your dongles Bluetooth address into the constructor,
+ * This will set BTD#my_bdaddr, so you don't have to plug in the dongle before pairing with your controller.
+ */
+ PS3BT(BTD *pBtd, uint8_t btadr5 = 0, uint8_t btadr4 = 0, uint8_t btadr3 = 0, uint8_t btadr2 = 0, uint8_t btadr1 = 0, uint8_t btadr0 = 0);
+
+ /** @name BluetoothService implementation */
+ /** Used this to disconnect any of the controllers. */
+ void disconnect();
+ /**@}*/
+
+ /** @name PS3 Controller functions */
+ /**
+ * getButtonPress(ButtonEnum b) will return true as long as the button is held down.
+ *
+ * While getButtonClick(ButtonEnum b) will only return it once.
+ *
+ * So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b),
+ * but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b).
+ * @param b ::ButtonEnum to read.
+ * @return getButtonPress(ButtonEnum b) will return a true as long as a button is held down, while getButtonClick(ButtonEnum b) will return true once for each button press.
+ */
+ bool getButtonPress(ButtonEnum b);
+ bool getButtonClick(ButtonEnum b);
+ /**@}*/
+ /** @name PS3 Controller functions */
+ /**
+ * Used to get the analog value from button presses.
+ * @param a The ::ButtonEnum to read.
+ * The supported buttons are:
+ * ::UP, ::RIGHT, ::DOWN, ::LEFT, ::L1, ::L2, ::R1, ::R2,
+ * ::TRIANGLE, ::CIRCLE, ::CROSS, ::SQUARE, and ::T.
+ * @return Analog value in the range of 0-255.
+ */
+ uint8_t getAnalogButton(ButtonEnum a);
+ /**
+ * Used to read the analog joystick.
+ * @param a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY.
+ * @return Return the analog value in the range of 0-255.
+ */
+ uint8_t getAnalogHat(AnalogHatEnum a);
+ /**
+ * Used to read the sensors inside the Dualshock 3 and Move controller.
+ * @param a
+ * The Dualshock 3 has a 3-axis accelerometer and a 1-axis gyro inside.
+ * The Move controller has a 3-axis accelerometer, a 3-axis gyro, a 3-axis magnetometer
+ * and a temperature sensor inside.
+ * @return Return the raw sensor value.
+ */
+ int16_t getSensor(SensorEnum a);
+ /**
+ * Use this to get ::Pitch and ::Roll calculated using the accelerometer.
+ * @param a Either ::Pitch or ::Roll.
+ * @return Return the angle in the range of 0-360.
+ */
+ double getAngle(AngleEnum a);
+ /**
+ * Read the sensors inside the Move controller.
+ * @param a ::aXmove, ::aYmove, ::aZmove, ::gXmove, ::gYmove, ::gZmove, ::mXmove, ::mYmove, and ::mXmove.
+ * @return The value in SI units.
+ */
+ double get9DOFValues(SensorEnum a);
+ /**
+ * Get the status from the controller.
+ * @param c The ::StatusEnum you want to read.
+ * @return True if correct and false if not.
+ */
+ bool getStatus(StatusEnum c);
+ /** Read all the available statuses from the controller and prints it as a nice formated string. */
+ void printStatusString();
+ /**
+ * Read the temperature from the Move controller.
+ * @return The temperature in degrees Celsius.
+ */
+ String getTemperature();
+
+ /** Used to set all LEDs and rumble off. */
+ void setAllOff();
+ /** Turn off rumble. */
+ void setRumbleOff();
+ /**
+ * Turn on rumble.
+ * @param mode Either ::RumbleHigh or ::RumbleLow.
+ */
+ void setRumbleOn(RumbleEnum mode);
+ /**
+ * Turn on rumble using custom duration and power.
+ * @param rightDuration The duration of the right/low rumble effect.
+ * @param rightPower The intensity of the right/low rumble effect.
+ * @param leftDuration The duration of the left/high rumble effect.
+ * @param leftPower The intensity of the left/high rumble effect.
+ */
+ void setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower);
+
+ /**
+ * Set LED value without using ::LEDEnum.
+ * @param value See: ::LEDEnum.
+ */
+ void setLedRaw(uint8_t value);
+
+ /** Turn all LEDs off. */
+ void setLedOff() {
+ setLedRaw(0);
+ };
+ /**
+ * Turn the specific LED off.
+ * @param a The ::LEDEnum to turn off.
+ */
+ void setLedOff(LEDEnum a);
+ /**
+ * Turn the specific LED on.
+ * @param a The ::LEDEnum to turn on.
+ */
+ void setLedOn(LEDEnum a);
+ /**
+ * Toggle the specific LED.
+ * @param a The ::LEDEnum to toggle.
+ */
+ void setLedToggle(LEDEnum a);
+
+ /**
+ * Use this to set the Color using RGB values.
+ * @param r,g,b RGB value.
+ */
+ void moveSetBulb(uint8_t r, uint8_t g, uint8_t b);
+ /**
+ * Use this to set the color using the predefined colors in ::ColorsEnum.
+ * @param color The desired color.
+ */
+ void moveSetBulb(ColorsEnum color);
+ /**
+ * Set the rumble value inside the Move controller.
+ * @param rumble The desired value in the range from 64-255.
+ */
+ void moveSetRumble(uint8_t rumble);
+
+ /** Used to get the millis() of the last message */
+ uint32_t getLastMessageTime() {
+ return lastMessageTime;
+ };
+ /**@}*/
+
+ /** Variable used to indicate if the normal Playstation controller is successfully connected. */
+ bool PS3Connected;
+ /** Variable used to indicate if the Move controller is successfully connected. */
+ bool PS3MoveConnected;
+ /** Variable used to indicate if the Navigation controller is successfully connected. */
+ bool PS3NavigationConnected;
+
+protected:
+ /** @name BluetoothService implementation */
+ /**
+ * Used to pass acldata to the services.
+ * @param ACLData Incoming acldata.
+ */
+ void ACLData(uint8_t* ACLData);
+ /** Used to run part of the state machine. */
+ void Run();
+ /** Use this to reset the service. */
+ void Reset();
+ /**
+ * Called when the controller is successfully initialized.
+ * Use attachOnInit(void (*funcOnInit)(void)) to call your own function.
+ * This is useful for instance if you want to set the LEDs in a specific way.
+ */
+ void onInit();
+ /**@}*/
+
+private:
+
+ void L2CAP_task(); // L2CAP state machine
+
+ /* Variables filled from HCI event management */
+ char remote_name_first; // First letter in remote name
+ bool activeConnection; // Used to indicate if it's already has established a connection
+
+ /* Variables used by high level L2CAP task */
+ uint8_t l2cap_state;
+
+ uint32_t lastMessageTime; // Variable used to store the millis value of the last message.
+
+ uint32_t ButtonState;
+ uint32_t OldButtonState;
+ uint32_t ButtonClickState;
+
+ uint32_t timer; // Timer used to limit time between messages and also used to continuously set PS3 Move controller Bulb and rumble values
+ uint32_t timerHID; // Timer used see if there has to be a delay before a new HID command
+
+ uint8_t l2capinbuf[BULK_MAXPKTSIZE]; // General purpose buffer for L2CAP in data
+ uint8_t HIDBuffer[HID_BUFFERSIZE]; // Used to store HID commands
+ uint8_t HIDMoveBuffer[HID_BUFFERSIZE]; // Used to store HID commands for the Move controller
+
+ /* L2CAP Channels */
+ uint8_t control_scid[2]; // L2CAP source CID for HID_Control
+ uint8_t control_dcid[2]; // 0x0040
+ uint8_t interrupt_scid[2]; // L2CAP source CID for HID_Interrupt
+ uint8_t interrupt_dcid[2]; // 0x0041
+
+ /* HID Commands */
+ void HID_Command(uint8_t* data, uint8_t nbytes);
+ void HIDMove_Command(uint8_t* data, uint8_t nbytes);
+ void enable_sixaxis(); // Command used to enable the Dualshock 3 and Navigation controller to send data via Bluetooth
+};
+#endif
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3Enums.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3Enums.h
new file mode 100644
index 000000000..77801945f
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3Enums.h
@@ -0,0 +1,141 @@
+/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
+
+ This software may be distributed and modified under the terms of the GNU
+ General Public License version 2 (GPL2) as published by the Free Software
+ Foundation and appearing in the file GPL2.TXT included in the packaging of
+ this file. Please note that GPL2 Section 2[b] requires that all works based
+ on this software must also be made publicly available under the terms of
+ the GPL2 ("Copyleft").
+
+ Contact information
+ -------------------
+
+ Kristian Lauszus, TKJ Electronics
+ Web : http://www.tkjelectronics.com
+ e-mail : kristianl@tkjelectronics.com
+ */
+
+#ifndef _ps3enums_h
+#define _ps3enums_h
+
+#include "controllerEnums.h"
+
+/** Size of the output report buffer for the Dualshock and Navigation controllers */
+#define PS3_REPORT_BUFFER_SIZE 48
+
+/** Report buffer for all PS3 commands */
+const uint8_t PS3_REPORT_BUFFER[PS3_REPORT_BUFFER_SIZE] PROGMEM = {
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0x27, 0x10, 0x00, 0x32,
+ 0xff, 0x27, 0x10, 0x00, 0x32,
+ 0xff, 0x27, 0x10, 0x00, 0x32,
+ 0xff, 0x27, 0x10, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/** Size of the output report buffer for the Move Controller */
+#define MOVE_REPORT_BUFFER_SIZE 7
+
+/** Used to set the LEDs on the controllers */
+const uint8_t PS3_LEDS[] PROGMEM = {
+ 0x00, // OFF
+ 0x01, // LED1
+ 0x02, // LED2
+ 0x04, // LED3
+ 0x08, // LED4
+
+ 0x09, // LED5
+ 0x0A, // LED6
+ 0x0C, // LED7
+ 0x0D, // LED8
+ 0x0E, // LED9
+ 0x0F, // LED10
+};
+
+/**
+ * Buttons on the controllers.
+ * <B>Note:</B> that the location is shifted 9 when it's connected via USB.
+ */
+const uint32_t PS3_BUTTONS[] PROGMEM = {
+ 0x10, // UP
+ 0x20, // RIGHT
+ 0x40, // DOWN
+ 0x80, // LEFT
+
+ 0x01, // SELECT
+ 0x08, // START
+ 0x02, // L3
+ 0x04, // R3
+
+ 0x0100, // L2
+ 0x0200, // R2
+ 0x0400, // L1
+ 0x0800, // R1
+
+ 0x1000, // TRIANGLE
+ 0x2000, // CIRCLE
+ 0x4000, // CROSS
+ 0x8000, // SQUARE
+
+ 0x010000, // PS
+ 0x080000, // MOVE - covers 12 bits - we only need to read the top 8
+ 0x100000, // T - covers 12 bits - we only need to read the top 8
+};
+
+/**
+ * Analog buttons on the controllers.
+ * <B>Note:</B> that the location is shifted 9 when it's connected via USB.
+ */
+const uint8_t PS3_ANALOG_BUTTONS[] PROGMEM = {
+ 23, // UP_ANALOG
+ 24, // RIGHT_ANALOG
+ 25, // DOWN_ANALOG
+ 26, // LEFT_ANALOG
+ 0, 0, 0, 0, // Skip SELECT, L3, R3 and START
+
+ 27, // L2_ANALOG
+ 28, // R2_ANALOG
+ 29, // L1_ANALOG
+ 30, // R1_ANALOG
+ 31, // TRIANGLE_ANALOG
+ 32, // CIRCLE_ANALOG
+ 33, // CROSS_ANALOG
+ 34, // SQUARE_ANALOG
+ 0, 0, // Skip PS and MOVE
+
+ // Playstation Move Controller
+ 15, // T_ANALOG - Both at byte 14 (last reading) and byte 15 (current reading)
+};
+
+enum StatusEnum {
+ // Note that the location is shifted 9 when it's connected via USB
+ // Byte location | bit location
+ Plugged = (38 << 8) | 0x02,
+ Unplugged = (38 << 8) | 0x03,
+
+ Charging = (39 << 8) | 0xEE,
+ NotCharging = (39 << 8) | 0xF1,
+ Shutdown = (39 << 8) | 0x01,
+ Dying = (39 << 8) | 0x02,
+ Low = (39 << 8) | 0x03,
+ High = (39 << 8) | 0x04,
+ Full = (39 << 8) | 0x05,
+
+ MoveCharging = (21 << 8) | 0xEE,
+ MoveNotCharging = (21 << 8) | 0xF1,
+ MoveShutdown = (21 << 8) | 0x01,
+ MoveDying = (21 << 8) | 0x02,
+ MoveLow = (21 << 8) | 0x03,
+ MoveHigh = (21 << 8) | 0x04,
+ MoveFull = (21 << 8) | 0x05,
+
+ CableRumble = (40 << 8) | 0x10, // Operating by USB and rumble is turned on
+ Cable = (40 << 8) | 0x12, // Operating by USB and rumble is turned off
+ BluetoothRumble = (40 << 8) | 0x14, // Operating by Bluetooth and rumble is turned on
+ Bluetooth = (40 << 8) | 0x16, // Operating by Bluetooth and rumble is turned off
+};
+
+#endif
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3USB.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3USB.cpp
new file mode 100755
index 000000000..c32175389
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3USB.cpp
@@ -0,0 +1,572 @@
+/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
+
+ This software may be distributed and modified under the terms of the GNU
+ General Public License version 2 (GPL2) as published by the Free Software
+ Foundation and appearing in the file GPL2.TXT included in the packaging of
+ this file. Please note that GPL2 Section 2[b] requires that all works based
+ on this software must also be made publicly available under the terms of
+ the GPL2 ("Copyleft").
+
+ Contact information
+ -------------------
+
+ Kristian Lauszus, TKJ Electronics
+ Web : http://www.tkjelectronics.com
+ e-mail : kristianl@tkjelectronics.com
+ */
+
+#include "PS3USB.h"
+// To enable serial debugging see "settings.h"
+//#define EXTRADEBUG // Uncomment to get even more debugging data
+//#define PRINTREPORT // Uncomment to print the report send by the PS3 Controllers
+
+PS3USB::PS3USB(USB *p, uint8_t btadr5, uint8_t btadr4, uint8_t btadr3, uint8_t btadr2, uint8_t btadr1, uint8_t btadr0) :
+pUsb(p), // pointer to USB class instance - mandatory
+bAddress(0), // device address - mandatory
+bPollEnable(false) // don't start polling before dongle is connected
+{
+ for(uint8_t i = 0; i < PS3_MAX_ENDPOINTS; i++) {
+ epInfo[i].epAddr = 0;
+ epInfo[i].maxPktSize = (i) ? 0 : 8;
+ epInfo[i].epAttribs = 0;
+ epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
+ }
+
+ if(pUsb) // register in USB subsystem
+ pUsb->RegisterDeviceClass(this); //set devConfig[] entry
+
+ my_bdaddr[5] = btadr5; // Change to your dongle's Bluetooth address instead
+ my_bdaddr[4] = btadr4;
+ my_bdaddr[3] = btadr3;
+ my_bdaddr[2] = btadr2;
+ my_bdaddr[1] = btadr1;
+ my_bdaddr[0] = btadr0;
+}
+
+uint8_t PS3USB::Init(uint8_t parent, uint8_t port, bool lowspeed) {
+ uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
+ USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
+ uint8_t rcode;
+ UsbDevice *p = NULL;
+ EpInfo *oldep_ptr = NULL;
+ uint16_t PID;
+ uint16_t VID;
+
+ // get memory address of USB device address pool
+ AddressPool &addrPool = pUsb->GetAddressPool();
+#ifdef EXTRADEBUG
+ Notify(PSTR("\r\nPS3USB Init"), 0x80);
+#endif
+ // check if address has already been assigned to an instance
+ if(bAddress) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nAddress in use"), 0x80);
+#endif
+ return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
+ }
+
+ // Get pointer to pseudo device with address 0 assigned
+ p = addrPool.GetUsbDevicePtr(0);
+
+ if(!p) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nAddress not found"), 0x80);
+#endif
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+ }
+
+ if(!p->epinfo) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nepinfo is null"), 0x80);
+#endif
+ return USB_ERROR_EPINFO_IS_NULL;
+ }
+
+ // Save old pointer to EP_RECORD of address 0
+ oldep_ptr = p->epinfo;
+
+ // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
+ p->epinfo = epInfo;
+
+ p->lowspeed = lowspeed;
+
+ // Get device descriptor
+ rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data
+ // Restore p->epinfo
+ p->epinfo = oldep_ptr;
+
+ if(rcode)
+ goto FailGetDevDescr;
+
+ VID = udd->idVendor;
+ PID = udd->idProduct;
+
+ if(VID != PS3_VID || (PID != PS3_PID && PID != PS3NAVIGATION_PID && PID != PS3MOVE_PID))
+ goto FailUnknownDevice;
+
+ // Allocate new address according to device class
+ bAddress = addrPool.AllocAddress(parent, false, port);
+
+ if(!bAddress)
+ return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
+
+ // Extract Max Packet Size from device descriptor
+ epInfo[0].maxPktSize = udd->bMaxPacketSize0;
+
+ // Assign new address to the device
+ rcode = pUsb->setAddr(0, 0, bAddress);
+ if(rcode) {
+ p->lowspeed = false;
+ addrPool.FreeAddress(bAddress);
+ bAddress = 0;
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nsetAddr: "), 0x80);
+ D_PrintHex<uint8_t > (rcode, 0x80);
+#endif
+ return rcode;
+ }
+#ifdef EXTRADEBUG
+ Notify(PSTR("\r\nAddr: "), 0x80);
+ D_PrintHex<uint8_t > (bAddress, 0x80);
+#endif
+ //delay(300); // Spec says you should wait at least 200ms
+
+ p->lowspeed = false;
+
+ //get pointer to assigned address record
+ p = addrPool.GetUsbDevicePtr(bAddress);
+ if(!p)
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+ p->lowspeed = lowspeed;
+
+ // Assign epInfo to epinfo pointer - only EP0 is known
+ rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
+ if(rcode)
+ goto FailSetDevTblEntry;
+
+
+ /* The application will work in reduced host mode, so we can save program and data
+ memory space. After verifying the PID and VID we will use known values for the
+ configuration values for device, interface, endpoints and HID for the PS3 Controllers */
+
+ /* Initialize data structures for endpoints of device */
+ epInfo[ PS3_OUTPUT_PIPE ].epAddr = 0x02; // PS3 output endpoint
+ epInfo[ PS3_OUTPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;
+ epInfo[ PS3_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
+ epInfo[ PS3_OUTPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE;
+ epInfo[ PS3_OUTPUT_PIPE ].bmSndToggle = 0;
+ epInfo[ PS3_OUTPUT_PIPE ].bmRcvToggle = 0;
+ epInfo[ PS3_INPUT_PIPE ].epAddr = 0x01; // PS3 report endpoint
+ epInfo[ PS3_INPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;
+ epInfo[ PS3_INPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
+ epInfo[ PS3_INPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE;
+ epInfo[ PS3_INPUT_PIPE ].bmSndToggle = 0;
+ epInfo[ PS3_INPUT_PIPE ].bmRcvToggle = 0;
+
+ rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo);
+ if(rcode)
+ goto FailSetDevTblEntry;
+
+ delay(200); //Give time for address change
+
+ rcode = pUsb->setConf(bAddress, epInfo[ PS3_CONTROL_PIPE ].epAddr, 1);
+ if(rcode)
+ goto FailSetConfDescr;
+
+ if(PID == PS3_PID || PID == PS3NAVIGATION_PID) {
+ if(PID == PS3_PID) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nDualshock 3 Controller Connected"), 0x80);
+#endif
+ PS3Connected = true;
+ } else { // must be a navigation controller
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nNavigation Controller Connected"), 0x80);
+#endif
+ PS3NavigationConnected = true;
+ }
+ enable_sixaxis(); // The PS3 controller needs a special command before it starts sending data
+
+ // Needed for PS3 Dualshock and Navigation commands to work
+ for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++)
+ writeBuf[i] = pgm_read_byte(&PS3_REPORT_BUFFER[i]);
+
+ for(uint8_t i = 6; i < 10; i++)
+ readBuf[i] = 0x7F; // Set the analog joystick values to center position
+ } else { // must be a Motion controller
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nMotion Controller Connected"), 0x80);
+#endif
+ PS3MoveConnected = true;
+ writeBuf[0] = 0x02; // Set report ID, this is needed for Move commands to work
+ }
+ if(my_bdaddr[0] != 0x00 || my_bdaddr[1] != 0x00 || my_bdaddr[2] != 0x00 || my_bdaddr[3] != 0x00 || my_bdaddr[4] != 0x00 || my_bdaddr[5] != 0x00) {
+ if(PS3MoveConnected)
+ setMoveBdaddr(my_bdaddr); // Set internal Bluetooth address
+ else
+ setBdaddr(my_bdaddr); // Set internal Bluetooth address
+
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nBluetooth Address was set to: "), 0x80);
+ for(int8_t i = 5; i > 0; i--) {
+ D_PrintHex<uint8_t > (my_bdaddr[i], 0x80);
+ Notify(PSTR(":"), 0x80);
+ }
+ D_PrintHex<uint8_t > (my_bdaddr[0], 0x80);
+#endif
+ }
+ onInit();
+
+ bPollEnable = true;
+ Notify(PSTR("\r\n"), 0x80);
+ timer = millis();
+ return 0; // Successful configuration
+
+ /* Diagnostic messages */
+FailGetDevDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailGetDevDescr();
+ goto Fail;
+#endif
+
+FailSetDevTblEntry:
+#ifdef DEBUG_USB_HOST
+ NotifyFailSetDevTblEntry();
+ goto Fail;
+#endif
+
+FailSetConfDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailSetConfDescr();
+#endif
+ goto Fail;
+
+FailUnknownDevice:
+#ifdef DEBUG_USB_HOST
+ NotifyFailUnknownDevice(VID, PID);
+#endif
+ rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
+
+Fail:
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nPS3 Init Failed, error code: "), 0x80);
+ NotifyFail(rcode);
+#endif
+ Release();
+ return rcode;
+}
+
+/* Performs a cleanup after failed Init() attempt */
+uint8_t PS3USB::Release() {
+ PS3Connected = false;
+ PS3MoveConnected = false;
+ PS3NavigationConnected = false;
+ pUsb->GetAddressPool().FreeAddress(bAddress);
+ bAddress = 0;
+ bPollEnable = false;
+ return 0;
+}
+
+uint8_t PS3USB::Poll() {
+ if(!bPollEnable)
+ return 0;
+
+ if(PS3Connected || PS3NavigationConnected) {
+ uint16_t BUFFER_SIZE = EP_MAXPKTSIZE;
+ pUsb->inTransfer(bAddress, epInfo[ PS3_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1
+ if(millis() - timer > 100) { // Loop 100ms before processing data
+ readReport();
+#ifdef PRINTREPORT
+ printReport(); // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers
+#endif
+ }
+ } else if(PS3MoveConnected) { // One can only set the color of the bulb, set the rumble, set and get the bluetooth address and calibrate the magnetometer via USB
+ if(millis() - timer > 4000) { // Send at least every 4th second
+ Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); // The Bulb and rumble values, has to be written again and again, for it to stay turned on
+ timer = millis();
+ }
+ }
+ return 0;
+}
+
+void PS3USB::readReport() {
+ ButtonState = (uint32_t)(readBuf[2] | ((uint16_t)readBuf[3] << 8) | ((uint32_t)readBuf[4] << 16));
+
+ //Notify(PSTR("\r\nButtonState", 0x80);
+ //PrintHex<uint32_t>(ButtonState, 0x80);
+
+ if(ButtonState != OldButtonState) {
+ ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable
+ OldButtonState = ButtonState;
+ }
+}
+
+void PS3USB::printReport() { // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers
+#ifdef PRINTREPORT
+ for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) {
+ D_PrintHex<uint8_t > (readBuf[i], 0x80);
+ Notify(PSTR(" "), 0x80);
+ }
+ Notify(PSTR("\r\n"), 0x80);
+#endif
+}
+
+bool PS3USB::getButtonPress(ButtonEnum b) {
+ return (ButtonState & pgm_read_dword(&PS3_BUTTONS[(uint8_t)b]));
+}
+
+bool PS3USB::getButtonClick(ButtonEnum b) {
+ uint32_t button = pgm_read_dword(&PS3_BUTTONS[(uint8_t)b]);
+ bool click = (ButtonClickState & button);
+ ButtonClickState &= ~button; // Clear "click" event
+ return click;
+}
+
+uint8_t PS3USB::getAnalogButton(ButtonEnum a) {
+ return (uint8_t)(readBuf[(pgm_read_byte(&PS3_ANALOG_BUTTONS[(uint8_t)a])) - 9]);
+}
+
+uint8_t PS3USB::getAnalogHat(AnalogHatEnum a) {
+ return (uint8_t)(readBuf[((uint8_t)a + 6)]);
+}
+
+uint16_t PS3USB::getSensor(SensorEnum a) {
+ return ((readBuf[((uint16_t)a) - 9] << 8) | readBuf[((uint16_t)a + 1) - 9]);
+}
+
+double PS3USB::getAngle(AngleEnum a) {
+ if(PS3Connected) {
+ double accXval;
+ double accYval;
+ double accZval;
+
+ // Data for the Kionix KXPC4 used in the DualShock 3
+ const double zeroG = 511.5; // 1.65/3.3*1023 (1,65V)
+ accXval = -((double)getSensor(aX) - zeroG);
+ accYval = -((double)getSensor(aY) - zeroG);
+ accZval = -((double)getSensor(aZ) - zeroG);
+
+ // Convert to 360 degrees resolution
+ // atan2 outputs the value of -π to π (radians)
+ // We are then converting it to 0 to 2π and then to degrees
+ if(a == Pitch)
+ return (atan2(accYval, accZval) + PI) * RAD_TO_DEG;
+ else
+ return (atan2(accXval, accZval) + PI) * RAD_TO_DEG;
+ } else
+ return 0;
+}
+
+bool PS3USB::getStatus(StatusEnum c) {
+ return (readBuf[((uint16_t)c >> 8) - 9] == ((uint8_t)c & 0xff));
+}
+
+void PS3USB::printStatusString() {
+ char statusOutput[100]; // Max string length plus null character
+ if(PS3Connected || PS3NavigationConnected) {
+ strcpy_P(statusOutput, PSTR("ConnectionStatus: "));
+
+ if(getStatus(Plugged)) strcat_P(statusOutput, PSTR("Plugged"));
+ else if(getStatus(Unplugged)) strcat_P(statusOutput, PSTR("Unplugged"));
+ else strcat_P(statusOutput, PSTR("Error"));
+
+ strcat_P(statusOutput, PSTR(" - PowerRating: "));
+
+ if(getStatus(Charging)) strcat_P(statusOutput, PSTR("Charging"));
+ else if(getStatus(NotCharging)) strcat_P(statusOutput, PSTR("Not Charging"));
+ else if(getStatus(Shutdown)) strcat_P(statusOutput, PSTR("Shutdown"));
+ else if(getStatus(Dying)) strcat_P(statusOutput, PSTR("Dying"));
+ else if(getStatus(Low)) strcat_P(statusOutput, PSTR("Low"));
+ else if(getStatus(High)) strcat_P(statusOutput, PSTR("High"));
+ else if(getStatus(Full)) strcat_P(statusOutput, PSTR("Full"));
+ else strcat_P(statusOutput, PSTR("Error"));
+
+ strcat_P(statusOutput, PSTR(" - WirelessStatus: "));
+
+ if(getStatus(CableRumble)) strcat_P(statusOutput, PSTR("Cable - Rumble is on"));
+ else if(getStatus(Cable)) strcat_P(statusOutput, PSTR("Cable - Rumble is off"));
+ else if(getStatus(BluetoothRumble)) strcat_P(statusOutput, PSTR("Bluetooth - Rumble is on"));
+ else if(getStatus(Bluetooth)) strcat_P(statusOutput, PSTR("Bluetooth - Rumble is off"));
+ else strcat_P(statusOutput, PSTR("Error"));
+ } else
+ strcpy_P(statusOutput, PSTR("Error"));
+
+ USB_HOST_SERIAL.write(statusOutput);
+}
+
+/* Playstation Sixaxis Dualshock and Navigation Controller commands */
+void PS3USB::PS3_Command(uint8_t *data, uint16_t nbytes) {
+ // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x01), Report Type (Output 0x02), interface (0x00), datalength, datalength, data)
+ pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x01, 0x02, 0x00, nbytes, nbytes, data, NULL);
+}
+
+void PS3USB::setAllOff() {
+ for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++)
+ writeBuf[i] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); // Reset buffer
+
+ PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE);
+}
+
+void PS3USB::setRumbleOff() {
+ writeBuf[1] = 0x00;
+ writeBuf[2] = 0x00; // Low mode off
+ writeBuf[3] = 0x00;
+ writeBuf[4] = 0x00; // High mode off
+
+ PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE);
+}
+
+void PS3USB::setRumbleOn(RumbleEnum mode) {
+ if((mode & 0x30) > 0x00) {
+ uint8_t power[2] = {0xff, 0x00}; // Defaults to RumbleLow
+ if(mode == RumbleHigh) {
+ power[0] = 0x00;
+ power[1] = 0xff;
+ }
+ setRumbleOn(0xfe, power[0], 0xfe, power[1]);
+ }
+}
+
+void PS3USB::setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower) {
+ writeBuf[1] = rightDuration;
+ writeBuf[2] = rightPower;
+ writeBuf[3] = leftDuration;
+ writeBuf[4] = leftPower;
+ PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE);
+}
+
+void PS3USB::setLedRaw(uint8_t value) {
+ writeBuf[9] = value << 1;
+ PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE);
+}
+
+void PS3USB::setLedOff(LEDEnum a) {
+ writeBuf[9] &= ~((uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1));
+ PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE);
+}
+
+void PS3USB::setLedOn(LEDEnum a) {
+ if(a == OFF)
+ setLedRaw(0);
+ else {
+ writeBuf[9] |= (uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1);
+ PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE);
+ }
+}
+
+void PS3USB::setLedToggle(LEDEnum a) {
+ writeBuf[9] ^= (uint8_t)((pgm_read_byte(&PS3_LEDS[(uint8_t)a]) & 0x0f) << 1);
+ PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE);
+}
+
+void PS3USB::setBdaddr(uint8_t *bdaddr) {
+ /* Set the internal Bluetooth address */
+ uint8_t buf[8];
+ buf[0] = 0x01;
+ buf[1] = 0x00;
+
+ for(uint8_t i = 0; i < 6; i++)
+ buf[i + 2] = bdaddr[5 - i]; // Copy into buffer, has to be written reversed, so it is MSB first
+
+ // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data
+ pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL);
+}
+
+void PS3USB::getBdaddr(uint8_t *bdaddr) {
+ uint8_t buf[8];
+
+ // bmRequest = Device to host (0x80) | Class (0x20) | Interface (0x01) = 0xA1, bRequest = Get Report (0x01), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data
+ pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL);
+
+ for(uint8_t i = 0; i < 6; i++)
+ bdaddr[5 - i] = buf[i + 2]; // Copy into buffer reversed, so it is LSB first
+}
+
+void PS3USB::enable_sixaxis() { // Command used to enable the Dualshock 3 and Navigation controller to send data via USB
+ uint8_t cmd_buf[4];
+ cmd_buf[0] = 0x42; // Special PS3 Controller enable commands
+ cmd_buf[1] = 0x0c;
+ cmd_buf[2] = 0x00;
+ cmd_buf[3] = 0x00;
+
+ // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF4), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data)
+ pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF4, 0x03, 0x00, 4, 4, cmd_buf, NULL);
+}
+
+/* Playstation Move Controller commands */
+void PS3USB::Move_Command(uint8_t *data, uint16_t nbytes) {
+ pUsb->outTransfer(bAddress, epInfo[ PS3_OUTPUT_PIPE ].epAddr, nbytes, data);
+}
+
+void PS3USB::moveSetBulb(uint8_t r, uint8_t g, uint8_t b) { // Use this to set the Color using RGB values
+ // Set the Bulb's values into the write buffer
+ writeBuf[2] = r;
+ writeBuf[3] = g;
+ writeBuf[4] = b;
+
+ Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE);
+}
+
+void PS3USB::moveSetBulb(ColorsEnum color) { // Use this to set the Color using the predefined colors in "enums.h"
+ moveSetBulb((uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color));
+}
+
+void PS3USB::moveSetRumble(uint8_t rumble) {
+#ifdef DEBUG_USB_HOST
+ if(rumble < 64 && rumble != 0) // The rumble value has to at least 64, or approximately 25% (64/255*100)
+ Notify(PSTR("\r\nThe rumble value has to at least 64, or approximately 25%"), 0x80);
+#endif
+ writeBuf[6] = rumble; // Set the rumble value into the write buffer
+
+ Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE);
+}
+
+void PS3USB::setMoveBdaddr(uint8_t *bdaddr) {
+ /* Set the internal Bluetooth address */
+ uint8_t buf[11];
+ buf[0] = 0x05;
+ buf[7] = 0x10;
+ buf[8] = 0x01;
+ buf[9] = 0x02;
+ buf[10] = 0x12;
+
+ for(uint8_t i = 0; i < 6; i++)
+ buf[i + 1] = bdaddr[i];
+
+ // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x05), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data
+ pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x05, 0x03, 0x00, 11, 11, buf, NULL);
+}
+
+void PS3USB::getMoveBdaddr(uint8_t *bdaddr) {
+ uint8_t buf[16];
+
+ // bmRequest = Device to host (0x80) | Class (0x20) | Interface (0x01) = 0xA1, bRequest = Get Report (0x01), Report ID (0x04), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data
+ pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, 0x04, 0x03, 0x00, 16, 16, buf, NULL);
+
+ for(uint8_t i = 0; i < 6; i++)
+ bdaddr[i] = buf[10 + i];
+}
+
+void PS3USB::getMoveCalibration(uint8_t *data) {
+ uint8_t buf[49];
+
+ for(uint8_t i = 0; i < 3; i++) {
+ // bmRequest = Device to host (0x80) | Class (0x20) | Interface (0x01) = 0xA1, bRequest = Get Report (0x01), Report ID (0x10), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data
+ pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, 0x10, 0x03, 0x00, 49, 49, buf, NULL);
+
+ for(byte j = 0; j < 49; j++)
+ data[49 * i + j] = buf[j];
+ }
+}
+
+void PS3USB::onInit() {
+ if(pFuncOnInit)
+ pFuncOnInit(); // Call the user function
+ else {
+ if(PS3MoveConnected)
+ moveSetBulb(Red);
+ else // Dualshock 3 or Navigation controller
+ setLedOn(LED1);
+ }
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3USB.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3USB.h
new file mode 100644
index 000000000..2eba9258c
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS3USB.h
@@ -0,0 +1,303 @@
+/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
+
+ This software may be distributed and modified under the terms of the GNU
+ General Public License version 2 (GPL2) as published by the Free Software
+ Foundation and appearing in the file GPL2.TXT included in the packaging of
+ this file. Please note that GPL2 Section 2[b] requires that all works based
+ on this software must also be made publicly available under the terms of
+ the GPL2 ("Copyleft").
+
+ Contact information
+ -------------------
+
+ Kristian Lauszus, TKJ Electronics
+ Web : http://www.tkjelectronics.com
+ e-mail : kristianl@tkjelectronics.com
+ */
+
+#ifndef _ps3usb_h_
+#define _ps3usb_h_
+
+#include "Usb.h"
+#include "hid.h"
+#include "PS3Enums.h"
+
+/* PS3 data taken from descriptors */
+#define EP_MAXPKTSIZE 64 // max size for data via USB
+
+/* Names we give to the 3 ps3 pipes - this is only used for setting the bluetooth address into the ps3 controllers */
+#define PS3_CONTROL_PIPE 0
+#define PS3_OUTPUT_PIPE 1
+#define PS3_INPUT_PIPE 2
+
+//PID and VID of the different devices
+#define PS3_VID 0x054C // Sony Corporation
+#define PS3_PID 0x0268 // PS3 Controller DualShock 3
+#define PS3NAVIGATION_PID 0x042F // Navigation controller
+#define PS3MOVE_PID 0x03D5 // Motion controller
+
+#define PS3_MAX_ENDPOINTS 3
+
+/**
+ * This class implements support for all the official PS3 Controllers:
+ * Dualshock 3, Navigation or a Motion controller via USB.
+ *
+ * One can only set the color of the bulb, set the rumble, set and get the bluetooth address and calibrate the magnetometer via USB on the Move controller.
+ *
+ * Information about the protocol can be found at the wiki: https://github.com/felis/USB_Host_Shield_2.0/wiki/PS3-Information.
+ */
+class PS3USB : public USBDeviceConfig {
+public:
+ /**
+ * Constructor for the PS3USB class.
+ * @param pUsb Pointer to USB class instance.
+ * @param btadr5,btadr4,btadr3,btadr2,btadr1,btadr0
+ * Pass your dongles Bluetooth address into the constructor,
+ * so you are able to pair the controller with a Bluetooth dongle.
+ */
+ PS3USB(USB *pUsb, uint8_t btadr5 = 0, uint8_t btadr4 = 0, uint8_t btadr3 = 0, uint8_t btadr2 = 0, uint8_t btadr1 = 0, uint8_t btadr0 = 0);
+
+ /** @name USBDeviceConfig implementation */
+ /**
+ * Initialize the PS3 Controller.
+ * @param parent Hub number.
+ * @param port Port number on the hub.
+ * @param lowspeed Speed of the device.
+ * @return 0 on success.
+ */
+ uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
+ /**
+ * Release the USB device.
+ * @return 0 on success.
+ */
+ uint8_t Release();
+ /**
+ * Poll the USB Input endpoins and run the state machines.
+ * @return 0 on success.
+ */
+ uint8_t Poll();
+
+ /**
+ * Get the device address.
+ * @return The device address.
+ */
+ virtual uint8_t GetAddress() {
+ return bAddress;
+ };
+
+ /**
+ * Used to check if the controller has been initialized.
+ * @return True if it's ready.
+ */
+ virtual bool isReady() {
+ return bPollEnable;
+ };
+
+ /**
+ * Used by the USB core to check what this driver support.
+ * @param vid The device's VID.
+ * @param pid The device's PID.
+ * @return Returns true if the device's VID and PID matches this driver.
+ */
+ virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {
+ return (vid == PS3_VID && (pid == PS3_PID || pid == PS3NAVIGATION_PID || pid == PS3MOVE_PID));
+ };
+ /**@}*/
+
+ /**
+ * Used to set the Bluetooth address inside the Dualshock 3 and Navigation controller.
+ * Set using LSB first.
+ * @param bdaddr Your dongles Bluetooth address.
+ */
+ void setBdaddr(uint8_t *bdaddr);
+ /**
+ * Used to get the Bluetooth address inside the Dualshock 3 and Navigation controller.
+ * Will return LSB first.
+ * @param bdaddr Your dongles Bluetooth address.
+ */
+ void getBdaddr(uint8_t *bdaddr);
+
+ /**
+ * Used to set the Bluetooth address inside the Move controller.
+ * Set using LSB first.
+ * @param bdaddr Your dongles Bluetooth address.
+ */
+ void setMoveBdaddr(uint8_t *bdaddr);
+ /**
+ * Used to get the Bluetooth address inside the Move controller.
+ * Will return LSB first.
+ * @param bdaddr Your dongles Bluetooth address.
+ */
+ void getMoveBdaddr(uint8_t *bdaddr);
+ /**
+ * Used to get the calibration data inside the Move controller.
+ * @param data Buffer to store data in. Must be at least 147 bytes
+ */
+ void getMoveCalibration(uint8_t *data);
+
+ /** @name PS3 Controller functions */
+ /**
+ * getButtonPress(ButtonEnum b) will return true as long as the button is held down.
+ *
+ * While getButtonClick(ButtonEnum b) will only return it once.
+ *
+ * So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b),
+ * but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b).
+ * @param b ::ButtonEnum to read.
+ * @return getButtonPress(ButtonEnum b) will return a true as long as a button is held down, while getButtonClick(ButtonEnum b) will return true once for each button press.
+ */
+ bool getButtonPress(ButtonEnum b);
+ bool getButtonClick(ButtonEnum b);
+ /**@}*/
+ /** @name PS3 Controller functions */
+ /**
+ * Used to get the analog value from button presses.
+ * @param a The ::ButtonEnum to read.
+ * The supported buttons are:
+ * ::UP, ::RIGHT, ::DOWN, ::LEFT, ::L1, ::L2, ::R1, ::R2,
+ * ::TRIANGLE, ::CIRCLE, ::CROSS, ::SQUARE, and ::T.
+ * @return Analog value in the range of 0-255.
+ */
+ uint8_t getAnalogButton(ButtonEnum a);
+ /**
+ * Used to read the analog joystick.
+ * @param a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY.
+ * @return Return the analog value in the range of 0-255.
+ */
+ uint8_t getAnalogHat(AnalogHatEnum a);
+ /**
+ * Used to read the sensors inside the Dualshock 3 controller.
+ * @param a
+ * The Dualshock 3 has a 3-axis accelerometer and a 1-axis gyro inside.
+ * @return Return the raw sensor value.
+ */
+ uint16_t getSensor(SensorEnum a);
+ /**
+ * Use this to get ::Pitch and ::Roll calculated using the accelerometer.
+ * @param a Either ::Pitch or ::Roll.
+ * @return Return the angle in the range of 0-360.
+ */
+ double getAngle(AngleEnum a);
+ /**
+ * Get the ::StatusEnum from the controller.
+ * @param c The ::StatusEnum you want to read.
+ * @return True if correct and false if not.
+ */
+ bool getStatus(StatusEnum c);
+ /** Read all the available statuses from the controller and prints it as a nice formated string. */
+ void printStatusString();
+
+ /** Used to set all LEDs and rumble off. */
+ void setAllOff();
+ /** Turn off rumble. */
+ void setRumbleOff();
+ /**
+ * Turn on rumble.
+ * @param mode Either ::RumbleHigh or ::RumbleLow.
+ */
+ void setRumbleOn(RumbleEnum mode);
+ /**
+ * Turn on rumble using custom duration and power.
+ * @param rightDuration The duration of the right/low rumble effect.
+ * @param rightPower The intensity of the right/low rumble effect.
+ * @param leftDuration The duration of the left/high rumble effect.
+ * @param leftPower The intensity of the left/high rumble effect.
+ */
+ void setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftDuration, uint8_t leftPower);
+
+ /**
+ * Set LED value without using the ::LEDEnum.
+ * @param value See: ::LEDEnum.
+ */
+ void setLedRaw(uint8_t value);
+
+ /** Turn all LEDs off. */
+ void setLedOff() {
+ setLedRaw(0);
+ }
+ /**
+ * Turn the specific ::LEDEnum off.
+ * @param a The ::LEDEnum to turn off.
+ */
+ void setLedOff(LEDEnum a);
+ /**
+ * Turn the specific ::LEDEnum on.
+ * @param a The ::LEDEnum to turn on.
+ */
+ void setLedOn(LEDEnum a);
+ /**
+ * Toggle the specific ::LEDEnum.
+ * @param a The ::LEDEnum to toggle.
+ */
+ void setLedToggle(LEDEnum a);
+
+ /**
+ * Use this to set the Color using RGB values.
+ * @param r,g,b RGB value.
+ */
+ void moveSetBulb(uint8_t r, uint8_t g, uint8_t b);
+ /**
+ * Use this to set the color using the predefined colors in ::ColorsEnum.
+ * @param color The desired color.
+ */
+ void moveSetBulb(ColorsEnum color);
+ /**
+ * Set the rumble value inside the Move controller.
+ * @param rumble The desired value in the range from 64-255.
+ */
+ void moveSetRumble(uint8_t rumble);
+
+ /**
+ * Used to call your own function when the controller is successfully initialized.
+ * @param funcOnInit Function to call.
+ */
+ void attachOnInit(void (*funcOnInit)(void)) {
+ pFuncOnInit = funcOnInit;
+ };
+ /**@}*/
+
+ /** Variable used to indicate if the normal playstation controller is successfully connected. */
+ bool PS3Connected;
+ /** Variable used to indicate if the move controller is successfully connected. */
+ bool PS3MoveConnected;
+ /** Variable used to indicate if the navigation controller is successfully connected. */
+ bool PS3NavigationConnected;
+
+protected:
+ /** Pointer to USB class instance. */
+ USB *pUsb;
+ /** Device address. */
+ uint8_t bAddress;
+ /** Endpoint info structure. */
+ EpInfo epInfo[PS3_MAX_ENDPOINTS];
+
+private:
+ /**
+ * Called when the controller is successfully initialized.
+ * Use attachOnInit(void (*funcOnInit)(void)) to call your own function.
+ * This is useful for instance if you want to set the LEDs in a specific way.
+ */
+ void onInit();
+ void (*pFuncOnInit)(void); // Pointer to function called in onInit()
+
+ bool bPollEnable;
+
+ uint32_t timer; // used to continuously set PS3 Move controller Bulb and rumble values
+
+ uint32_t ButtonState;
+ uint32_t OldButtonState;
+ uint32_t ButtonClickState;
+
+ uint8_t my_bdaddr[6]; // Change to your dongles Bluetooth address in the constructor
+ uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data
+ uint8_t writeBuf[EP_MAXPKTSIZE]; // General purpose buffer for output data
+
+ void readReport(); // read incoming data
+ void printReport(); // print incoming date - Uncomment for debugging
+
+ /* Private commands */
+ void PS3_Command(uint8_t *data, uint16_t nbytes);
+ void enable_sixaxis(); // Command used to enable the Dualshock 3 and Navigation controller to send data via USB
+ void Move_Command(uint8_t *data, uint16_t nbytes);
+};
+#endif
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4BT.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4BT.h
new file mode 100644
index 000000000..b7eb4b5a9
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4BT.h
@@ -0,0 +1,121 @@
+/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved.
+
+ This software may be distributed and modified under the terms of the GNU
+ General Public License version 2 (GPL2) as published by the Free Software
+ Foundation and appearing in the file GPL2.TXT included in the packaging of
+ this file. Please note that GPL2 Section 2[b] requires that all works based
+ on this software must also be made publicly available under the terms of
+ the GPL2 ("Copyleft").
+
+ Contact information
+ -------------------
+
+ Kristian Lauszus, TKJ Electronics
+ Web : http://www.tkjelectronics.com
+ e-mail : kristianl@tkjelectronics.com
+ */
+
+#ifndef _ps4bt_h_
+#define _ps4bt_h_
+
+#include "BTHID.h"
+#include "PS4Parser.h"
+
+/**
+ * This class implements support for the PS4 controller via Bluetooth.
+ * It uses the BTHID class for all the Bluetooth communication.
+ */
+class PS4BT : public BTHID, public PS4Parser {
+public:
+ /**
+ * Constructor for the PS4BT class.
+ * @param p Pointer to the BTD class instance.
+ * @param pair Set this to true in order to pair with the device. If the argument is omitted then it will not pair with it. One can use ::PAIR to set it to true.
+ * @param pin Write the pin to BTD#btdPin. If argument is omitted, then "0000" will be used.
+ */
+ PS4BT(BTD *p, bool pair = false, const char *pin = "0000") :
+ BTHID(p, pair, pin) {
+ PS4Parser::Reset();
+ };
+
+ /**
+ * Used to check if a PS4 controller is connected.
+ * @return Returns true if it is connected.
+ */
+ bool connected() {
+ return BTHID::connected;
+ };
+
+protected:
+ /** @name BTHID implementation */
+ /**
+ * Used to parse Bluetooth HID data.
+ * @param len The length of the incoming data.
+ * @param buf Pointer to the data buffer.
+ */
+ virtual void ParseBTHIDData(uint8_t len, uint8_t *buf) {
+ PS4Parser::Parse(len, buf);
+ };
+
+ /**
+ * Called when a device is successfully initialized.
+ * Use attachOnInit(void (*funcOnInit)(void)) to call your own function.
+ * This is useful for instance if you want to set the LEDs in a specific way.
+ */
+ virtual void OnInitBTHID() {
+ PS4Parser::Reset();
+ enable_sixaxis(); // Make the controller send out the entire output report
+ if (pFuncOnInit)
+ pFuncOnInit(); // Call the user function
+ else
+ setLed(Blue);
+ };
+
+ /** Used to reset the different buffers to there default values */
+ virtual void ResetBTHID() {
+ PS4Parser::Reset();
+ };
+ /**@}*/
+
+ /** @name PS4Parser implementation */
+ virtual void sendOutputReport(PS4Output *output) { // Source: https://github.com/chrippa/ds4drv
+ uint8_t buf[79];
+ memset(buf, 0, sizeof(buf));
+
+ buf[0] = 0x52; // HID BT Set_report (0x50) | Report Type (Output 0x02)
+ buf[1] = 0x11; // Report ID
+ buf[2] = 0x80;
+ buf[4]= 0xFF;
+
+ buf[7] = output->smallRumble; // Small Rumble
+ buf[8] = output->bigRumble; // Big rumble
+
+ buf[9] = output->r; // Red
+ buf[10] = output->g; // Green
+ buf[11] = output->b; // Blue
+
+ buf[12] = output->flashOn; // Time to flash bright (255 = 2.5 seconds)
+ buf[13] = output->flashOff; // Time to flash dark (255 = 2.5 seconds)
+
+ output->reportChanged = false;
+
+ // The PS4 console actually set the four last bytes to a CRC32 checksum, but it seems like it is actually not needed
+
+ HID_Command(buf, sizeof(buf));
+ };
+ /**@}*/
+
+private:
+ void enable_sixaxis() { // Command used to make the PS4 controller send out the entire output report
+ uint8_t buf[2];
+ buf[0] = 0x43; // HID BT Get_report (0x40) | Report Type (Feature 0x03)
+ buf[1] = 0x02; // Report ID
+
+ HID_Command(buf, 2);
+ };
+
+ void HID_Command(uint8_t *data, uint8_t nbytes) {
+ pBtd->L2CAP_Command(hci_handle, data, nbytes, control_scid[0], control_scid[1]);
+ };
+};
+#endif
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4Parser.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4Parser.cpp
new file mode 100644
index 000000000..ca6adce40
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4Parser.cpp
@@ -0,0 +1,116 @@
+/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved.
+
+ This software may be distributed and modified under the terms of the GNU
+ General Public License version 2 (GPL2) as published by the Free Software
+ Foundation and appearing in the file GPL2.TXT included in the packaging of
+ this file. Please note that GPL2 Section 2[b] requires that all works based
+ on this software must also be made publicly available under the terms of
+ the GPL2 ("Copyleft").
+
+ Contact information
+ -------------------
+
+ Kristian Lauszus, TKJ Electronics
+ Web : http://www.tkjelectronics.com
+ e-mail : kristianl@tkjelectronics.com
+ */
+
+#include "PS4Parser.h"
+
+// To enable serial debugging see "settings.h"
+//#define PRINTREPORT // Uncomment to print the report send by the PS4 Controller
+
+bool PS4Parser::checkDpad(ButtonEnum b) {
+ switch (b) {
+ case UP:
+ return ps4Data.btn.dpad == DPAD_LEFT_UP || ps4Data.btn.dpad == DPAD_UP || ps4Data.btn.dpad == DPAD_UP_RIGHT;
+ case RIGHT:
+ return ps4Data.btn.dpad == DPAD_UP_RIGHT || ps4Data.btn.dpad == DPAD_RIGHT || ps4Data.btn.dpad == DPAD_RIGHT_DOWN;
+ case DOWN:
+ return ps4Data.btn.dpad == DPAD_RIGHT_DOWN || ps4Data.btn.dpad == DPAD_DOWN || ps4Data.btn.dpad == DPAD_DOWN_LEFT;
+ case LEFT:
+ return ps4Data.btn.dpad == DPAD_DOWN_LEFT || ps4Data.btn.dpad == DPAD_LEFT || ps4Data.btn.dpad == DPAD_LEFT_UP;
+ default:
+ return false;
+ }
+}
+
+bool PS4Parser::getButtonPress(ButtonEnum b) {
+ if (b <= LEFT) // Dpad
+ return checkDpad(b);
+ else
+ return ps4Data.btn.val & (1UL << pgm_read_byte(&PS4_BUTTONS[(uint8_t)b]));
+}
+
+bool PS4Parser::getButtonClick(ButtonEnum b) {
+ uint32_t mask = 1UL << pgm_read_byte(&PS4_BUTTONS[(uint8_t)b]);
+ bool click = buttonClickState.val & mask;
+ buttonClickState.val &= ~mask; // Clear "click" event
+ return click;
+}
+
+uint8_t PS4Parser::getAnalogButton(ButtonEnum b) {
+ if (b == L2) // These are the only analog buttons on the controller
+ return ps4Data.trigger[0];
+ else if (b == R2)
+ return ps4Data.trigger[1];
+ return 0;
+}
+
+uint8_t PS4Parser::getAnalogHat(AnalogHatEnum a) {
+ return ps4Data.hatValue[(uint8_t)a];
+}
+
+void PS4Parser::Parse(uint8_t len, uint8_t *buf) {
+ if (len > 1 && buf) {
+#ifdef PRINTREPORT
+ Notify(PSTR("\r\n"), 0x80);
+ for (uint8_t i = 0; i < len; i++) {
+ D_PrintHex<uint8_t > (buf[i], 0x80);
+ Notify(PSTR(" "), 0x80);
+ }
+#endif
+
+ if (buf[0] == 0x01) // Check report ID
+ memcpy(&ps4Data, buf + 1, min((uint8_t)(len - 1), sizeof(ps4Data)));
+ else if (buf[0] == 0x11) { // This report is send via Bluetooth, it has an offset of 2 compared to the USB data
+ if (len < 4) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nReport is too short: "), 0x80);
+ D_PrintHex<uint8_t > (len, 0x80);
+#endif
+ return;
+ }
+ memcpy(&ps4Data, buf + 3, min((uint8_t)(len - 3), sizeof(ps4Data)));
+ } else {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nUnknown report id: "), 0x80);
+ D_PrintHex<uint8_t > (buf[0], 0x80);
+#endif
+ return;
+ }
+
+ if (ps4Data.btn.val != oldButtonState.val) { // Check if anything has changed
+ buttonClickState.val = ps4Data.btn.val & ~oldButtonState.val; // Update click state variable
+ oldButtonState.val = ps4Data.btn.val;
+
+ // The DPAD buttons does not set the different bits, but set a value corresponding to the buttons pressed, we will simply set the bits ourself
+ uint8_t newDpad = 0;
+ if (checkDpad(UP))
+ newDpad |= 1 << UP;
+ if (checkDpad(RIGHT))
+ newDpad |= 1 << RIGHT;
+ if (checkDpad(DOWN))
+ newDpad |= 1 << DOWN;
+ if (checkDpad(LEFT))
+ newDpad |= 1 << LEFT;
+ if (newDpad != oldDpad) {
+ buttonClickState.dpad = newDpad & ~oldDpad; // Override values
+ oldDpad = newDpad;
+ }
+ }
+ }
+
+ if (ps4Output.reportChanged)
+ sendOutputReport(&ps4Output); // Send output report
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4Parser.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4Parser.h
new file mode 100644
index 000000000..51f080636
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4Parser.h
@@ -0,0 +1,407 @@
+/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved.
+
+ This software may be distributed and modified under the terms of the GNU
+ General Public License version 2 (GPL2) as published by the Free Software
+ Foundation and appearing in the file GPL2.TXT included in the packaging of
+ this file. Please note that GPL2 Section 2[b] requires that all works based
+ on this software must also be made publicly available under the terms of
+ the GPL2 ("Copyleft").
+
+ Contact information
+ -------------------
+
+ Kristian Lauszus, TKJ Electronics
+ Web : http://www.tkjelectronics.com
+ e-mail : kristianl@tkjelectronics.com
+ */
+
+#ifndef _ps4parser_h_
+#define _ps4parser_h_
+
+#include "Usb.h"
+#include "controllerEnums.h"
+
+/** Buttons on the controller */
+const uint8_t PS4_BUTTONS[] PROGMEM = {
+ UP, // UP
+ RIGHT, // RIGHT
+ DOWN, // DOWN
+ LEFT, // LEFT
+
+ 0x0C, // SHARE
+ 0x0D, // OPTIONS
+ 0x0E, // L3
+ 0x0F, // R3
+
+ 0x0A, // L2
+ 0x0B, // R2
+ 0x08, // L1
+ 0x09, // R1
+
+ 0x07, // TRIANGLE
+ 0x06, // CIRCLE
+ 0x05, // CROSS
+ 0x04, // SQUARE
+
+ 0x10, // PS
+ 0x11, // TOUCHPAD
+};
+
+union PS4Buttons {
+ struct {
+ uint8_t dpad : 4;
+ uint8_t square : 1;
+ uint8_t cross : 1;
+ uint8_t circle : 1;
+ uint8_t triangle : 1;
+
+ uint8_t l1 : 1;
+ uint8_t r1 : 1;
+ uint8_t l2 : 1;
+ uint8_t r2 : 1;
+ uint8_t share : 1;
+ uint8_t options : 1;
+ uint8_t l3 : 1;
+ uint8_t r3 : 1;
+
+ uint8_t ps : 1;
+ uint8_t touchpad : 1;
+ uint8_t reportCounter : 6;
+ } __attribute__((packed));
+ uint32_t val : 24;
+} __attribute__((packed));
+
+struct touchpadXY {
+ uint8_t dummy; // I can not figure out what this data is for, it seems to change randomly, maybe a timestamp?
+ struct {
+ uint8_t counter : 7; // Increments every time a finger is touching the touchpad
+ uint8_t touching : 1; // The top bit is cleared if the finger is touching the touchpad
+ uint16_t x : 12;
+ uint16_t y : 12;
+ } __attribute__((packed)) finger[2]; // 0 = first finger, 1 = second finger
+} __attribute__((packed));
+
+struct PS4Status {
+ uint8_t battery : 4;
+ uint8_t usb : 1;
+ uint8_t audio : 1;
+ uint8_t mic : 1;
+ uint8_t unknown : 1; // Extension port?
+} __attribute__((packed));
+
+struct PS4Data {
+ /* Button and joystick values */
+ uint8_t hatValue[4];
+ PS4Buttons btn;
+ uint8_t trigger[2];
+
+ /* Gyro and accelerometer values */
+ uint8_t dummy[3]; // First two looks random, while the third one might be some kind of status - it increments once in a while
+ int16_t gyroY, gyroZ, gyroX;
+ int16_t accX, accZ, accY;
+
+ uint8_t dummy2[5];
+ PS4Status status;
+ uint8_t dummy3[3];
+
+ /* The rest is data for the touchpad */
+ touchpadXY xy[3]; // It looks like it sends out three coordinates each time, this might be because the microcontroller inside the PS4 controller is much faster than the Bluetooth connection.
+ // The last data is read from the last position in the array while the oldest measurement is from the first position.
+ // The first position will also keep it's value after the finger is released, while the other two will set them to zero.
+ // Note that if you read fast enough from the device, then only the first one will contain any data.
+
+ // The last three bytes are always: 0x00, 0x80, 0x00
+} __attribute__((packed));
+
+struct PS4Output {
+ uint8_t bigRumble, smallRumble; // Rumble
+ uint8_t r, g, b; // RGB
+ uint8_t flashOn, flashOff; // Time to flash bright/dark (255 = 2.5 seconds)
+ bool reportChanged; // The data is send when data is received from the controller
+} __attribute__((packed));
+
+enum DPADEnum {
+ DPAD_UP = 0x0,
+ DPAD_UP_RIGHT = 0x1,
+ DPAD_RIGHT = 0x2,
+ DPAD_RIGHT_DOWN = 0x3,
+ DPAD_DOWN = 0x4,
+ DPAD_DOWN_LEFT = 0x5,
+ DPAD_LEFT = 0x6,
+ DPAD_LEFT_UP = 0x7,
+ DPAD_OFF = 0x8,
+};
+
+/** This class parses all the data sent by the PS4 controller */
+class PS4Parser {
+public:
+ /** Constructor for the PS4Parser class. */
+ PS4Parser() {
+ Reset();
+ };
+
+ /** @name PS4 Controller functions */
+ /**
+ * getButtonPress(ButtonEnum b) will return true as long as the button is held down.
+ *
+ * While getButtonClick(ButtonEnum b) will only return it once.
+ *
+ * So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b),
+ * but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b).
+ * @param b ::ButtonEnum to read.
+ * @return getButtonPress(ButtonEnum b) will return a true as long as a button is held down, while getButtonClick(ButtonEnum b) will return true once for each button press.
+ */
+ bool getButtonPress(ButtonEnum b);
+ bool getButtonClick(ButtonEnum b);
+ /**@}*/
+ /** @name PS4 Controller functions */
+ /**
+ * Used to get the analog value from button presses.
+ * @param b The ::ButtonEnum to read.
+ * The supported buttons are:
+ * ::UP, ::RIGHT, ::DOWN, ::LEFT, ::L1, ::L2, ::R1, ::R2,
+ * ::TRIANGLE, ::CIRCLE, ::CROSS, ::SQUARE, and ::T.
+ * @return Analog value in the range of 0-255.
+ */
+ uint8_t getAnalogButton(ButtonEnum b);
+
+ /**
+ * Used to read the analog joystick.
+ * @param a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY.
+ * @return Return the analog value in the range of 0-255.
+ */
+ uint8_t getAnalogHat(AnalogHatEnum a);
+
+ /**
+ * Get the x-coordinate of the touchpad. Position 0 is in the top left.
+ * @param finger 0 = first finger, 1 = second finger. If omitted, then 0 will be used.
+ * @param xyId The controller sends out three packets with the same structure.
+ * The third one will contain the last measure, but if you read from the controller then there is only be data in the first one.
+ * For that reason it will be set to 0 if the argument is omitted.
+ * @return Returns the x-coordinate of the finger.
+ */
+ uint16_t getX(uint8_t finger = 0, uint8_t xyId = 0) {
+ return ps4Data.xy[xyId].finger[finger].x;
+ };
+
+ /**
+ * Get the y-coordinate of the touchpad. Position 0 is in the top left.
+ * @param finger 0 = first finger, 1 = second finger. If omitted, then 0 will be used.
+ * @param xyId The controller sends out three packets with the same structure.
+ * The third one will contain the last measure, but if you read from the controller then there is only be data in the first one.
+ * For that reason it will be set to 0 if the argument is omitted.
+ * @return Returns the y-coordinate of the finger.
+ */
+ uint16_t getY(uint8_t finger = 0, uint8_t xyId = 0) {
+ return ps4Data.xy[xyId].finger[finger].y;
+ };
+
+ /**
+ * Returns whenever the user is toucing the touchpad.
+ * @param finger 0 = first finger, 1 = second finger. If omitted, then 0 will be used.
+ * @param xyId The controller sends out three packets with the same structure.
+ * The third one will contain the last measure, but if you read from the controller then there is only be data in the first one.
+ * For that reason it will be set to 0 if the argument is omitted.
+ * @return Returns true if the specific finger is touching the touchpad.
+ */
+ bool isTouching(uint8_t finger = 0, uint8_t xyId = 0) {
+ return !(ps4Data.xy[xyId].finger[finger].touching); // The bit is cleared when a finger is touching the touchpad
+ };
+
+ /**
+ * This counter increments every time a finger touches the touchpad.
+ * @param finger 0 = first finger, 1 = second finger. If omitted, then 0 will be used.
+ * @param xyId The controller sends out three packets with the same structure.
+ * The third one will contain the last measure, but if you read from the controller then there is only be data in the first one.
+ * For that reason it will be set to 0 if the argument is omitted.
+ * @return Return the value of the counter, note that it is only a 7-bit value.
+ */
+ uint8_t getTouchCounter(uint8_t finger = 0, uint8_t xyId = 0) {
+ return ps4Data.xy[xyId].finger[finger].counter;
+ };
+
+ /**
+ * Get the angle of the controller calculated using the accelerometer.
+ * @param a Either ::Pitch or ::Roll.
+ * @return Return the angle in the range of 0-360.
+ */
+ double getAngle(AngleEnum a) {
+ if (a == Pitch)
+ return (atan2(ps4Data.accY, ps4Data.accZ) + PI) * RAD_TO_DEG;
+ else
+ return (atan2(ps4Data.accX, ps4Data.accZ) + PI) * RAD_TO_DEG;
+ };
+
+ /**
+ * Used to get the raw values from the 3-axis gyroscope and 3-axis accelerometer inside the PS4 controller.
+ * @param s The sensor to read.
+ * @return Returns the raw sensor reading.
+ */
+ int16_t getSensor(SensorEnum s) {
+ switch(s) {
+ case gX:
+ return ps4Data.gyroX;
+ case gY:
+ return ps4Data.gyroY;
+ case gZ:
+ return ps4Data.gyroZ;
+ case aX:
+ return ps4Data.accX;
+ case aY:
+ return ps4Data.accY;
+ case aZ:
+ return ps4Data.accZ;
+ default:
+ return 0;
+ }
+ };
+
+ /**
+ * Return the battery level of the PS4 controller.
+ * @return The battery level in the range 0-15.
+ */
+ uint8_t getBatteryLevel() {
+ return ps4Data.status.battery;
+ };
+
+ /**
+ * Use this to check if an USB cable is connected to the PS4 controller.
+ * @return Returns true if an USB cable is connected.
+ */
+ bool getUsbStatus() {
+ return ps4Data.status.usb;
+ };
+
+ /**
+ * Use this to check if an audio jack cable is connected to the PS4 controller.
+ * @return Returns true if an audio jack cable is connected.
+ */
+ bool getAudioStatus() {
+ return ps4Data.status.audio;
+ };
+
+ /**
+ * Use this to check if a microphone is connected to the PS4 controller.
+ * @return Returns true if a microphone is connected.
+ */
+ bool getMicStatus() {
+ return ps4Data.status.mic;
+ };
+
+ /** Turn both rumble and the LEDs off. */
+ void setAllOff() {
+ setRumbleOff();
+ setLedOff();
+ };
+
+ /** Set rumble off. */
+ void setRumbleOff() {
+ setRumbleOn(0, 0);
+ };
+
+ /**
+ * Turn on rumble.
+ * @param mode Either ::RumbleHigh or ::RumbleLow.
+ */
+ void setRumbleOn(RumbleEnum mode) {
+ if (mode == RumbleLow)
+ setRumbleOn(0x00, 0xFF);
+ else
+ setRumbleOn(0xFF, 0x00);
+ };
+
+ /**
+ * Turn on rumble.
+ * @param bigRumble Value for big motor.
+ * @param smallRumble Value for small motor.
+ */
+ void setRumbleOn(uint8_t bigRumble, uint8_t smallRumble) {
+ ps4Output.bigRumble = bigRumble;
+ ps4Output.smallRumble = smallRumble;
+ ps4Output.reportChanged = true;
+ };
+
+ /** Turn all LEDs off. */
+ void setLedOff() {
+ setLed(0, 0, 0);
+ };
+
+ /**
+ * Use this to set the color using RGB values.
+ * @param r,g,b RGB value.
+ */
+ void setLed(uint8_t r, uint8_t g, uint8_t b) {
+ ps4Output.r = r;
+ ps4Output.g = g;
+ ps4Output.b = b;
+ ps4Output.reportChanged = true;
+ };
+
+ /**
+ * Use this to set the color using the predefined colors in ::ColorsEnum.
+ * @param color The desired color.
+ */
+ void setLed(ColorsEnum color) {
+ setLed((uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color));
+ };
+
+ /**
+ * Set the LEDs flash time.
+ * @param flashOn Time to flash bright (255 = 2.5 seconds).
+ * @param flashOff Time to flash dark (255 = 2.5 seconds).
+ */
+ void setLedFlash(uint8_t flashOn, uint8_t flashOff) {
+ ps4Output.flashOn = flashOn;
+ ps4Output.flashOff = flashOff;
+ ps4Output.reportChanged = true;
+ };
+ /**@}*/
+
+protected:
+ /**
+ * Used to parse data sent from the PS4 controller.
+ * @param len Length of the data.
+ * @param buf Pointer to the data buffer.
+ */
+ void Parse(uint8_t len, uint8_t *buf);
+
+ /** Used to reset the different buffers to their default values */
+ void Reset() {
+ uint8_t i;
+ for (i = 0; i < sizeof(ps4Data.hatValue); i++)
+ ps4Data.hatValue[i] = 127; // Center value
+ ps4Data.btn.val = 0;
+ oldButtonState.val = 0;
+ for (i = 0; i < sizeof(ps4Data.trigger); i++)
+ ps4Data.trigger[i] = 0;
+ for (i = 0; i < sizeof(ps4Data.xy)/sizeof(ps4Data.xy[0]); i++) {
+ for (uint8_t j = 0; j < sizeof(ps4Data.xy[0].finger)/sizeof(ps4Data.xy[0].finger[0]); j++)
+ ps4Data.xy[i].finger[j].touching = 1; // The bit is cleared if the finger is touching the touchpad
+ }
+
+ ps4Data.btn.dpad = DPAD_OFF;
+ oldButtonState.dpad = DPAD_OFF;
+ buttonClickState.dpad = 0;
+ oldDpad = 0;
+
+ ps4Output.bigRumble = ps4Output.smallRumble = 0;
+ ps4Output.r = ps4Output.g = ps4Output.b = 0;
+ ps4Output.flashOn = ps4Output.flashOff = 0;
+ ps4Output.reportChanged = false;
+ };
+
+ /**
+ * Send the output to the PS4 controller. This is implemented in PS4BT.h and PS4USB.h.
+ * @param output Pointer to PS4Output buffer;
+ */
+ virtual void sendOutputReport(PS4Output *output) = 0;
+
+private:
+ bool checkDpad(ButtonEnum b); // Used to check PS4 DPAD buttons
+
+ PS4Data ps4Data;
+ PS4Buttons oldButtonState, buttonClickState;
+ PS4Output ps4Output;
+ uint8_t oldDpad;
+};
+#endif
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4USB.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4USB.h
new file mode 100644
index 000000000..b43079a6e
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PS4USB.h
@@ -0,0 +1,130 @@
+/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved.
+
+ This software may be distributed and modified under the terms of the GNU
+ General Public License version 2 (GPL2) as published by the Free Software
+ Foundation and appearing in the file GPL2.TXT included in the packaging of
+ this file. Please note that GPL2 Section 2[b] requires that all works based
+ on this software must also be made publicly available under the terms of
+ the GPL2 ("Copyleft").
+
+ Contact information
+ -------------------
+
+ Kristian Lauszus, TKJ Electronics
+ Web : http://www.tkjelectronics.com
+ e-mail : kristianl@tkjelectronics.com
+ */
+
+#ifndef _ps4usb_h_
+#define _ps4usb_h_
+
+#include "hiduniversal.h"
+#include "PS4Parser.h"
+
+#define PS4_VID 0x054C // Sony Corporation
+#define PS4_PID 0x05C4 // PS4 Controller
+
+/**
+ * This class implements support for the PS4 controller via USB.
+ * It uses the HIDUniversal class for all the USB communication.
+ */
+class PS4USB : public HIDUniversal, public PS4Parser {
+public:
+ /**
+ * Constructor for the PS4USB class.
+ * @param p Pointer to the USB class instance.
+ */
+ PS4USB(USB *p) :
+ HIDUniversal(p) {
+ PS4Parser::Reset();
+ };
+
+ /**
+ * Used to check if a PS4 controller is connected.
+ * @return Returns true if it is connected.
+ */
+ bool connected() {
+ return HIDUniversal::isReady() && HIDUniversal::VID == PS4_VID && HIDUniversal::PID == PS4_PID;
+ };
+
+ /**
+ * Used to call your own function when the device is successfully initialized.
+ * @param funcOnInit Function to call.
+ */
+ void attachOnInit(void (*funcOnInit)(void)) {
+ pFuncOnInit = funcOnInit;
+ };
+
+protected:
+ /** @name HIDUniversal implementation */
+ /**
+ * Used to parse USB HID data.
+ * @param hid Pointer to the HID class.
+ * @param is_rpt_id Only used for Hubs.
+ * @param len The length of the incoming data.
+ * @param buf Pointer to the data buffer.
+ */
+ virtual void ParseHIDData(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
+ if (HIDUniversal::VID == PS4_VID && HIDUniversal::PID == PS4_PID)
+ PS4Parser::Parse(len, buf);
+ };
+
+ /**
+ * Called when a device is successfully initialized.
+ * Use attachOnInit(void (*funcOnInit)(void)) to call your own function.
+ * This is useful for instance if you want to set the LEDs in a specific way.
+ */
+ virtual uint8_t OnInitSuccessful() {
+ if (HIDUniversal::VID == PS4_VID && HIDUniversal::PID == PS4_PID) {
+ PS4Parser::Reset();
+ if (pFuncOnInit)
+ pFuncOnInit(); // Call the user function
+ else
+ setLed(Blue);
+ };
+ return 0;
+ };
+ /**@}*/
+
+ /** @name PS4Parser implementation */
+ virtual void sendOutputReport(PS4Output *output) { // Source: https://github.com/chrippa/ds4drv
+ uint8_t buf[32];
+ memset(buf, 0, sizeof(buf));
+
+ buf[0] = 0x05; // Report ID
+ buf[1]= 0xFF;
+
+ buf[4] = output->smallRumble; // Small Rumble
+ buf[5] = output->bigRumble; // Big rumble
+
+ buf[6] = output->r; // Red
+ buf[7] = output->g; // Green
+ buf[8] = output->b; // Blue
+
+ buf[9] = output->flashOn; // Time to flash bright (255 = 2.5 seconds)
+ buf[10] = output->flashOff; // Time to flash dark (255 = 2.5 seconds)
+
+ output->reportChanged = false;
+
+ // The PS4 console actually set the four last bytes to a CRC32 checksum, but it seems like it is actually not needed
+
+ pUsb->outTransfer(bAddress, epInfo[ hidInterfaces[0].epIndex[epInterruptOutIndex] ].epAddr, sizeof(buf), buf);
+ };
+ /**@}*/
+
+ /** @name USBDeviceConfig implementation */
+ /**
+ * Used by the USB core to check what this driver support.
+ * @param vid The device's VID.
+ * @param pid The device's PID.
+ * @return Returns true if the device's VID and PID matches this driver.
+ */
+ virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {
+ return (vid == PS4_VID && pid == PS4_PID);
+ };
+ /**@}*/
+
+private:
+ void (*pFuncOnInit)(void); // Pointer to function called in onInit()
+};
+#endif
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PSBuzz.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PSBuzz.cpp
new file mode 100644
index 000000000..498164d5a
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PSBuzz.cpp
@@ -0,0 +1,82 @@
+/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved.
+
+ This software may be distributed and modified under the terms of the GNU
+ General Public License version 2 (GPL2) as published by the Free Software
+ Foundation and appearing in the file GPL2.TXT included in the packaging of
+ this file. Please note that GPL2 Section 2[b] requires that all works based
+ on this software must also be made publicly available under the terms of
+ the GPL2 ("Copyleft").
+
+ Contact information
+ -------------------
+
+ Kristian Lauszus, TKJ Electronics
+ Web : http://www.tkjelectronics.com
+ e-mail : kristianl@tkjelectronics.com
+ */
+
+#include "PSBuzz.h"
+
+// To enable serial debugging see "settings.h"
+//#define PRINTREPORT // Uncomment to print the report send by the PS Buzz Controllers
+
+void PSBuzz::ParseHIDData(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
+ if (HIDUniversal::VID == PSBUZZ_VID && HIDUniversal::PID == PSBUZZ_PID && len > 2 && buf) {
+#ifdef PRINTREPORT
+ Notify(PSTR("\r\n"), 0x80);
+ for (uint8_t i = 0; i < len; i++) {
+ D_PrintHex<uint8_t > (buf[i], 0x80);
+ Notify(PSTR(" "), 0x80);
+ }
+#endif
+ memcpy(&psbuzzButtons, buf + 2, min((uint8_t)(len - 2), sizeof(psbuzzButtons)));
+
+ if (psbuzzButtons.val != oldButtonState.val) { // Check if anything has changed
+ buttonClickState.val = psbuzzButtons.val & ~oldButtonState.val; // Update click state variable
+ oldButtonState.val = psbuzzButtons.val;
+ }
+ }
+};
+
+uint8_t PSBuzz::OnInitSuccessful() {
+ if (HIDUniversal::VID == PSBUZZ_VID && HIDUniversal::PID == PSBUZZ_PID) {
+ Reset();
+ if (pFuncOnInit)
+ pFuncOnInit(); // Call the user function
+ else
+ setLedOnAll(); // Turn the LED on, on all four controllers
+ };
+ return 0;
+};
+
+bool PSBuzz::getButtonPress(ButtonEnum b, uint8_t controller) {
+ return psbuzzButtons.val & (1UL << (b + 5 * controller)); // Each controller uses 5 bits, so the value is shifted 5 for each controller
+};
+
+bool PSBuzz::getButtonClick(ButtonEnum b, uint8_t controller) {
+ uint32_t mask = (1UL << (b + 5 * controller)); // Each controller uses 5 bits, so the value is shifted 5 for each controller
+ bool click = buttonClickState.val & mask;
+ buttonClickState.val &= ~mask; // Clear "click" event
+ return click;
+};
+
+// Source: http://www.developerfusion.com/article/84338/making-usb-c-friendly/ and https://github.com/torvalds/linux/blob/master/drivers/hid/hid-sony.c
+void PSBuzz::setLedRaw(bool value, uint8_t controller) {
+ ledState[controller] = value; // Save value for next time it is called
+
+ uint8_t buf[7];
+ buf[0] = 0x00;
+ buf[1] = ledState[0] ? 0xFF : 0x00;
+ buf[2] = ledState[1] ? 0xFF : 0x00;
+ buf[3] = ledState[2] ? 0xFF : 0x00;
+ buf[4] = ledState[3] ? 0xFF : 0x00;
+ buf[5] = 0x00;
+ buf[6] = 0x00;
+
+ PSBuzz_Command(buf, sizeof(buf));
+};
+
+void PSBuzz::PSBuzz_Command(uint8_t *data, uint16_t nbytes) {
+ // bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x00), Report Type (Output 0x02), interface (0x00), datalength, datalength, data)
+ pUsb->ctrlReq(bAddress, epInfo[0].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL);
+};
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PSBuzz.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PSBuzz.h
new file mode 100644
index 000000000..8880d9e50
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/PSBuzz.h
@@ -0,0 +1,185 @@
+/* Copyright (C) 2014 Kristian Lauszus, TKJ Electronics. All rights reserved.
+
+ This software may be distributed and modified under the terms of the GNU
+ General Public License version 2 (GPL2) as published by the Free Software
+ Foundation and appearing in the file GPL2.TXT included in the packaging of
+ this file. Please note that GPL2 Section 2[b] requires that all works based
+ on this software must also be made publicly available under the terms of
+ the GPL2 ("Copyleft").
+
+ Contact information
+ -------------------
+
+ Kristian Lauszus, TKJ Electronics
+ Web : http://www.tkjelectronics.com
+ e-mail : kristianl@tkjelectronics.com
+ */
+
+#ifndef _psbuzz_h_
+#define _psbuzz_h_
+
+#include "hiduniversal.h"
+#include "controllerEnums.h"
+
+#define PSBUZZ_VID 0x054C // Sony Corporation
+#define PSBUZZ_PID 0x1000 // PS Buzz Controller
+
+/** Struct used to easily read the different buttons on the controllers */
+union PSBUZZButtons {
+ struct {
+ uint8_t red : 1;
+ uint8_t yellow : 1;
+ uint8_t green : 1;
+ uint8_t orange : 1;
+ uint8_t blue : 1;
+ } __attribute__((packed)) btn[4];
+ uint32_t val : 20;
+} __attribute__((packed));
+
+/**
+ * This class implements support for the PS Buzz controllers via USB.
+ * It uses the HIDUniversal class for all the USB communication.
+ */
+class PSBuzz : public HIDUniversal {
+public:
+ /**
+ * Constructor for the PSBuzz class.
+ * @param p Pointer to the USB class instance.
+ */
+ PSBuzz(USB *p) :
+ HIDUniversal(p) {
+ Reset();
+ };
+
+ /**
+ * Used to check if a PS Buzz controller is connected.
+ * @return Returns true if it is connected.
+ */
+ bool connected() {
+ return HIDUniversal::isReady() && HIDUniversal::VID == PSBUZZ_VID && HIDUniversal::PID == PSBUZZ_PID;
+ };
+
+ /**
+ * Used to call your own function when the device is successfully initialized.
+ * @param funcOnInit Function to call.
+ */
+ void attachOnInit(void (*funcOnInit)(void)) {
+ pFuncOnInit = funcOnInit;
+ };
+
+ /** @name PS Buzzer Controller functions */
+ /**
+ * getButtonPress(ButtonEnum b) will return true as long as the button is held down.
+ *
+ * While getButtonClick(ButtonEnum b) will only return it once.
+ *
+ * So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b),
+ * but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b).
+ * @param b ::ButtonEnum to read.
+ * @param controller The controller to read from. Default to 0.
+ * @return getButtonPress(ButtonEnum b) will return a true as long as a button is held down, while getButtonClick(ButtonEnum b) will return true once for each button press.
+ */
+ bool getButtonPress(ButtonEnum b, uint8_t controller = 0);
+ bool getButtonClick(ButtonEnum b, uint8_t controller = 0);
+ /**@}*/
+ /** @name PS Buzzer Controller functions */
+ /**
+ * Set LED value without using ::LEDEnum.
+ * @param value See: ::LEDEnum.
+ */
+ /**
+ * Set LED values directly.
+ * @param value Used to set whenever the LED should be on or off
+ * @param controller The controller to control. Defaults to 0.
+ */
+ void setLedRaw(bool value, uint8_t controller = 0);
+
+ /** Turn all LEDs off. */
+ void setLedOffAll() {
+ for (uint8_t i = 1; i < 4; i++) // Skip first as it will be set in setLedRaw
+ ledState[i] = false; // Just an easy way to set all four off at the same time
+ setLedRaw(false); // Turn the LED off, on all four controllers
+ };
+
+ /**
+ * Turn the LED off on a specific controller.
+ * @param controller The controller to turn off. Defaults to 0.
+ */
+ void setLedOff(uint8_t controller = 0) {
+ setLedRaw(false, controller);
+ };
+
+
+ /** Turn all LEDs on. */
+ void setLedOnAll() {
+ for (uint8_t i = 1; i < 4; i++) // Skip first as it will be set in setLedRaw
+ ledState[i] = true; // Just an easy way to set all four off at the same time
+ setLedRaw(true); // Turn the LED on, on all four controllers
+ };
+
+ /**
+ * Turn the LED on on a specific controller.
+ * @param controller The controller to turn off. Defaults to 0.
+ */
+ void setLedOn(uint8_t controller = 0) {
+ setLedRaw(true, controller);
+ };
+
+ /**
+ * Toggle the LED on a specific controller.
+ * @param controller The controller to turn off. Defaults to 0.
+ */
+ void setLedToggle(uint8_t controller = 0) {
+ setLedRaw(!ledState[controller], controller);
+ };
+ /**@}*/
+
+protected:
+ /** @name HIDUniversal implementation */
+ /**
+ * Used to parse USB HID data.
+ * @param hid Pointer to the HID class.
+ * @param is_rpt_id Only used for Hubs.
+ * @param len The length of the incoming data.
+ * @param buf Pointer to the data buffer.
+ */
+ void ParseHIDData(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
+
+ /**
+ * Called when a device is successfully initialized.
+ * Use attachOnInit(void (*funcOnInit)(void)) to call your own function.
+ * This is useful for instance if you want to set the LEDs in a specific way.
+ */
+ uint8_t OnInitSuccessful();
+ /**@}*/
+
+ /** Used to reset the different buffers to their default values */
+ void Reset() {
+ psbuzzButtons.val = 0;
+ oldButtonState.val = 0;
+ buttonClickState.val = 0;
+ for (uint8_t i = 0; i < sizeof(ledState); i++)
+ ledState[i] = 0;
+ };
+
+ /** @name USBDeviceConfig implementation */
+ /**
+ * Used by the USB core to check what this driver support.
+ * @param vid The device's VID.
+ * @param pid The device's PID.
+ * @return Returns true if the device's VID and PID matches this driver.
+ */
+ virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {
+ return (vid == PSBUZZ_VID && pid == PSBUZZ_PID);
+ };
+ /**@}*/
+
+private:
+ void (*pFuncOnInit)(void); // Pointer to function called in onInit()
+
+ void PSBuzz_Command(uint8_t *data, uint16_t nbytes);
+
+ PSBUZZButtons psbuzzButtons, oldButtonState, buttonClickState;
+ bool ledState[4];
+};
+#endif
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/SPP.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/SPP.cpp
new file mode 100644
index 000000000..0f4ee5e98
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/SPP.cpp
@@ -0,0 +1,829 @@
+/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
+
+ This software may be distributed and modified under the terms of the GNU
+ General Public License version 2 (GPL2) as published by the Free Software
+ Foundation and appearing in the file GPL2.TXT included in the packaging of
+ this file. Please note that GPL2 Section 2[b] requires that all works based
+ on this software must also be made publicly available under the terms of
+ the GPL2 ("Copyleft").
+
+ Contact information
+ -------------------
+
+ Kristian Lauszus, TKJ Electronics
+ Web : http://www.tkjelectronics.com
+ e-mail : kristianl@tkjelectronics.com
+ */
+
+#include "SPP.h"
+// To enable serial debugging see "settings.h"
+//#define EXTRADEBUG // Uncomment to get even more debugging data
+//#define PRINTREPORT // Uncomment to print the report sent to the Arduino
+
+/*
+ * CRC (reversed crc) lookup table as calculated by the table generator in ETSI TS 101 369 V6.3.0.
+ */
+const uint8_t rfcomm_crc_table[256] PROGMEM = {/* reversed, 8-bit, poly=0x07 */
+ 0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B,
+ 0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67,
+ 0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43,
+ 0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F,
+ 0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B,
+ 0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17,
+ 0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33,
+ 0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F,
+ 0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B,
+ 0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87,
+ 0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3,
+ 0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF,
+ 0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB,
+ 0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7,
+ 0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3,
+ 0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF
+};
+
+SPP::SPP(BTD *p, const char* name, const char* pin) :
+BluetoothService(p) // Pointer to BTD class instance - mandatory
+{
+ pBtd->btdName = name;
+ pBtd->btdPin = pin;
+
+ /* Set device cid for the SDP and RFCOMM channelse */
+ sdp_dcid[0] = 0x50; // 0x0050
+ sdp_dcid[1] = 0x00;
+ rfcomm_dcid[0] = 0x51; // 0x0051
+ rfcomm_dcid[1] = 0x00;
+
+ Reset();
+}
+
+void SPP::Reset() {
+ connected = false;
+ RFCOMMConnected = false;
+ SDPConnected = false;
+ waitForLastCommand = false;
+ l2cap_sdp_state = L2CAP_SDP_WAIT;
+ l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT;
+ l2cap_event_flag = 0;
+ sppIndex = 0;
+ creditSent = false;
+}
+
+void SPP::disconnect() {
+ connected = false;
+ // First the two L2CAP channels has to be disconnected and then the HCI connection
+ if(RFCOMMConnected)
+ pBtd->l2cap_disconnection_request(hci_handle, ++identifier, rfcomm_scid, rfcomm_dcid);
+ if(RFCOMMConnected && SDPConnected)
+ delay(1); // Add delay between commands
+ if(SDPConnected)
+ pBtd->l2cap_disconnection_request(hci_handle, ++identifier, sdp_scid, sdp_dcid);
+ l2cap_sdp_state = L2CAP_DISCONNECT_RESPONSE;
+}
+
+void SPP::ACLData(uint8_t* l2capinbuf) {
+ if(!connected) {
+ if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
+ if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == SDP_PSM && !pBtd->sdpConnectionClaimed) {
+ pBtd->sdpConnectionClaimed = true;
+ hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection
+ l2cap_sdp_state = L2CAP_SDP_WAIT; // Reset state
+ } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == RFCOMM_PSM && !pBtd->rfcommConnectionClaimed) {
+ pBtd->rfcommConnectionClaimed = true;
+ hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection
+ l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT; // Reset state
+ }
+ }
+ }
+
+ if(checkHciHandle(l2capinbuf, hci_handle)) { // acl_handle_ok
+ if((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { // l2cap_control - Channel ID for ACL-U
+ if(l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);
+ Notify(PSTR(" Data: "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[17], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[16], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
+#endif
+ } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
+#ifdef EXTRADEBUG
+ Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);
+ Notify(PSTR(" SCID: "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
+ Notify(PSTR(" Identifier: "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[9], 0x80);
+#endif
+ if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == SDP_PSM) { // It doesn't matter if it receives another reqeust, since it waits for the channel to disconnect in the L2CAP_SDP_DONE state, and the l2cap_event_flag will be cleared if so
+ identifier = l2capinbuf[9];
+ sdp_scid[0] = l2capinbuf[14];
+ sdp_scid[1] = l2capinbuf[15];
+ l2cap_set_flag(L2CAP_FLAG_CONNECTION_SDP_REQUEST);
+ } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == RFCOMM_PSM) { // ----- || -----
+ identifier = l2capinbuf[9];
+ rfcomm_scid[0] = l2capinbuf[14];
+ rfcomm_scid[1] = l2capinbuf[15];
+ l2cap_set_flag(L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST);
+ }
+ } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) {
+ if((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success
+ if(l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) {
+ //Notify(PSTR("\r\nSDP Configuration Complete"), 0x80);
+ l2cap_set_flag(L2CAP_FLAG_CONFIG_SDP_SUCCESS);
+ } else if(l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) {
+ //Notify(PSTR("\r\nRFCOMM Configuration Complete"), 0x80);
+ l2cap_set_flag(L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS);
+ }
+ }
+ } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) {
+ if(l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) {
+ //Notify(PSTR("\r\nSDP Configuration Request"), 0x80);
+ pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], sdp_scid);
+ } else if(l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) {
+ //Notify(PSTR("\r\nRFCOMM Configuration Request"), 0x80);
+ pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], rfcomm_scid);
+ }
+ } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) {
+ if(l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) {
+ //Notify(PSTR("\r\nDisconnect Request: SDP Channel"), 0x80);
+ identifier = l2capinbuf[9];
+ l2cap_set_flag(L2CAP_FLAG_DISCONNECT_SDP_REQUEST);
+ } else if(l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) {
+ //Notify(PSTR("\r\nDisconnect Request: RFCOMM Channel"), 0x80);
+ identifier = l2capinbuf[9];
+ l2cap_set_flag(L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST);
+ }
+ } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) {
+ if(l2capinbuf[12] == sdp_scid[0] && l2capinbuf[13] == sdp_scid[1]) {
+ //Notify(PSTR("\r\nDisconnect Response: SDP Channel"), 0x80);
+ identifier = l2capinbuf[9];
+ l2cap_set_flag(L2CAP_FLAG_DISCONNECT_RESPONSE);
+ } else if(l2capinbuf[12] == rfcomm_scid[0] && l2capinbuf[13] == rfcomm_scid[1]) {
+ //Notify(PSTR("\r\nDisconnect Response: RFCOMM Channel"), 0x80);
+ identifier = l2capinbuf[9];
+ l2cap_set_flag(L2CAP_FLAG_DISCONNECT_RESPONSE);
+ }
+ } else if(l2capinbuf[8] == L2CAP_CMD_INFORMATION_REQUEST) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nInformation request"), 0x80);
+#endif
+ identifier = l2capinbuf[9];
+ pBtd->l2cap_information_response(hci_handle, identifier, l2capinbuf[12], l2capinbuf[13]);
+ }
+#ifdef EXTRADEBUG
+ else {
+ Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[8], 0x80);
+ }
+#endif
+ } else if(l2capinbuf[6] == sdp_dcid[0] && l2capinbuf[7] == sdp_dcid[1]) { // SDP
+ if(l2capinbuf[8] == SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST_PDU) {
+ if(((l2capinbuf[16] << 8 | l2capinbuf[17]) == SERIALPORT_UUID) || ((l2capinbuf[16] << 8 | l2capinbuf[17]) == 0x0000 && (l2capinbuf[18] << 8 | l2capinbuf[19]) == SERIALPORT_UUID)) { // Check if it's sending the full UUID, see: https://www.bluetooth.org/Technical/AssignedNumbers/service_discovery.htm, we will just check the first four bytes
+ if(firstMessage) {
+ serialPortResponse1(l2capinbuf[9], l2capinbuf[10]);
+ firstMessage = false;
+ } else {
+ serialPortResponse2(l2capinbuf[9], l2capinbuf[10]); // Serialport continuation state
+ firstMessage = true;
+ }
+ } else if(((l2capinbuf[16] << 8 | l2capinbuf[17]) == L2CAP_UUID) || ((l2capinbuf[16] << 8 | l2capinbuf[17]) == 0x0000 && (l2capinbuf[18] << 8 | l2capinbuf[19]) == L2CAP_UUID)) {
+ if(firstMessage) {
+ l2capResponse1(l2capinbuf[9], l2capinbuf[10]);
+ firstMessage = false;
+ } else {
+ l2capResponse2(l2capinbuf[9], l2capinbuf[10]); // L2CAP continuation state
+ firstMessage = true;
+ }
+ } else
+ serviceNotSupported(l2capinbuf[9], l2capinbuf[10]); // The service is not supported
+#ifdef EXTRADEBUG
+ Notify(PSTR("\r\nUUID: "), 0x80);
+ uint16_t uuid;
+ if((l2capinbuf[16] << 8 | l2capinbuf[17]) == 0x0000) // Check if it's sending the UUID as a 128-bit UUID
+ uuid = (l2capinbuf[18] << 8 | l2capinbuf[19]);
+ else // Short UUID
+ uuid = (l2capinbuf[16] << 8 | l2capinbuf[17]);
+ D_PrintHex<uint16_t > (uuid, 0x80);
+
+ Notify(PSTR("\r\nLength: "), 0x80);
+ uint16_t length = l2capinbuf[11] << 8 | l2capinbuf[12];
+ D_PrintHex<uint16_t > (length, 0x80);
+ Notify(PSTR("\r\nData: "), 0x80);
+ for(uint8_t i = 0; i < length; i++) {
+ D_PrintHex<uint8_t > (l2capinbuf[13 + i], 0x80);
+ Notify(PSTR(" "), 0x80);
+ }
+#endif
+ }
+#ifdef EXTRADEBUG
+ else {
+ Notify(PSTR("\r\nUnknown PDU: "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[8], 0x80);
+ }
+#endif
+ } else if(l2capinbuf[6] == rfcomm_dcid[0] && l2capinbuf[7] == rfcomm_dcid[1]) { // RFCOMM
+ rfcommChannel = l2capinbuf[8] & 0xF8;
+ rfcommDirection = l2capinbuf[8] & 0x04;
+ rfcommCommandResponse = l2capinbuf[8] & 0x02;
+ rfcommChannelType = l2capinbuf[9] & 0xEF;
+ rfcommPfBit = l2capinbuf[9] & 0x10;
+
+ if(rfcommChannel >> 3 != 0x00)
+ rfcommChannelConnection = rfcommChannel;
+
+#ifdef EXTRADEBUG
+ Notify(PSTR("\r\nRFCOMM Channel: "), 0x80);
+ D_PrintHex<uint8_t > (rfcommChannel >> 3, 0x80);
+ Notify(PSTR(" Direction: "), 0x80);
+ D_PrintHex<uint8_t > (rfcommDirection >> 2, 0x80);
+ Notify(PSTR(" CommandResponse: "), 0x80);
+ D_PrintHex<uint8_t > (rfcommCommandResponse >> 1, 0x80);
+ Notify(PSTR(" ChannelType: "), 0x80);
+ D_PrintHex<uint8_t > (rfcommChannelType, 0x80);
+ Notify(PSTR(" PF_BIT: "), 0x80);
+ D_PrintHex<uint8_t > (rfcommPfBit, 0x80);
+#endif
+ if(rfcommChannelType == RFCOMM_DISC) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nReceived Disconnect RFCOMM Command on channel: "), 0x80);
+ D_PrintHex<uint8_t > (rfcommChannel >> 3, 0x80);
+#endif
+ connected = false;
+ sendRfcomm(rfcommChannel, rfcommDirection, rfcommCommandResponse, RFCOMM_UA, rfcommPfBit, rfcommbuf, 0x00); // UA Command
+ }
+ if(connected) {
+ /* Read the incoming message */
+ if(rfcommChannelType == RFCOMM_UIH && rfcommChannel == rfcommChannelConnection) {
+ uint8_t length = l2capinbuf[10] >> 1; // Get length
+ uint8_t offset = l2capinbuf[4] - length - 4; // Check if there is credit
+ if(checkFcs(&l2capinbuf[8], l2capinbuf[11 + length + offset])) {
+ uint8_t i = 0;
+ for(; i < length; i++) {
+ if(rfcommAvailable + i >= sizeof (rfcommDataBuffer)) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nWarning: Buffer is full!"), 0x80);
+#endif
+ break;
+ }
+ rfcommDataBuffer[rfcommAvailable + i] = l2capinbuf[11 + i + offset];
+ }
+ rfcommAvailable += i;
+#ifdef EXTRADEBUG
+ Notify(PSTR("\r\nRFCOMM Data Available: "), 0x80);
+ Notify(rfcommAvailable, 0x80);
+ if(offset) {
+ Notify(PSTR(" - Credit: 0x"), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[11], 0x80);
+ }
+#endif
+ }
+#ifdef DEBUG_USB_HOST
+ else
+ Notify(PSTR("\r\nError in FCS checksum!"), 0x80);
+#endif
+#ifdef PRINTREPORT // Uncomment "#define PRINTREPORT" to print the report send to the Arduino via Bluetooth
+ for(uint8_t i = 0; i < length; i++)
+ Notifyc(l2capinbuf[i + 11 + offset], 0x80);
+#endif
+ } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_RPN_CMD) { // UIH Remote Port Negotiation Command
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nReceived UIH Remote Port Negotiation Command"), 0x80);
+#endif
+ rfcommbuf[0] = BT_RFCOMM_RPN_RSP; // Command
+ rfcommbuf[1] = l2capinbuf[12]; // Length and shiftet like so: length << 1 | 1
+ rfcommbuf[2] = l2capinbuf[13]; // Channel: channel << 1 | 1
+ rfcommbuf[3] = l2capinbuf[14]; // Pre difined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM
+ rfcommbuf[4] = l2capinbuf[15]; // Priority
+ rfcommbuf[5] = l2capinbuf[16]; // Timer
+ rfcommbuf[6] = l2capinbuf[17]; // Max Fram Size LSB
+ rfcommbuf[7] = l2capinbuf[18]; // Max Fram Size MSB
+ rfcommbuf[8] = l2capinbuf[19]; // MaxRatransm.
+ rfcommbuf[9] = l2capinbuf[20]; // Number of Frames
+ sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x0A); // UIH Remote Port Negotiation Response
+ } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_CMD) { // UIH Modem Status Command
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nSend UIH Modem Status Response"), 0x80);
+#endif
+ rfcommbuf[0] = BT_RFCOMM_MSC_RSP; // UIH Modem Status Response
+ rfcommbuf[1] = 2 << 1 | 1; // Length and shiftet like so: length << 1 | 1
+ rfcommbuf[2] = l2capinbuf[13]; // Channel: (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3)
+ rfcommbuf[3] = l2capinbuf[14];
+ sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x04);
+ }
+ } else {
+ if(rfcommChannelType == RFCOMM_SABM) { // SABM Command - this is sent twice: once for channel 0 and then for the channel to establish
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nReceived SABM Command"), 0x80);
+#endif
+ sendRfcomm(rfcommChannel, rfcommDirection, rfcommCommandResponse, RFCOMM_UA, rfcommPfBit, rfcommbuf, 0x00); // UA Command
+ } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_PN_CMD) { // UIH Parameter Negotiation Command
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nReceived UIH Parameter Negotiation Command"), 0x80);
+#endif
+ rfcommbuf[0] = BT_RFCOMM_PN_RSP; // UIH Parameter Negotiation Response
+ rfcommbuf[1] = l2capinbuf[12]; // Length and shiftet like so: length << 1 | 1
+ rfcommbuf[2] = l2capinbuf[13]; // Channel: channel << 1 | 1
+ rfcommbuf[3] = 0xE0; // Pre difined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM
+ rfcommbuf[4] = 0x00; // Priority
+ rfcommbuf[5] = 0x00; // Timer
+ rfcommbuf[6] = BULK_MAXPKTSIZE - 14; // Max Fram Size LSB - set to the size of received data (50)
+ rfcommbuf[7] = 0x00; // Max Fram Size MSB
+ rfcommbuf[8] = 0x00; // MaxRatransm.
+ rfcommbuf[9] = 0x00; // Number of Frames
+ sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x0A);
+ } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_CMD) { // UIH Modem Status Command
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nSend UIH Modem Status Response"), 0x80);
+#endif
+ rfcommbuf[0] = BT_RFCOMM_MSC_RSP; // UIH Modem Status Response
+ rfcommbuf[1] = 2 << 1 | 1; // Length and shiftet like so: length << 1 | 1
+ rfcommbuf[2] = l2capinbuf[13]; // Channel: (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3)
+ rfcommbuf[3] = l2capinbuf[14];
+ sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x04);
+
+ delay(1);
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nSend UIH Modem Status Command"), 0x80);
+#endif
+ rfcommbuf[0] = BT_RFCOMM_MSC_CMD; // UIH Modem Status Command
+ rfcommbuf[1] = 2 << 1 | 1; // Length and shiftet like so: length << 1 | 1
+ rfcommbuf[2] = l2capinbuf[13]; // Channel: (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3)
+ rfcommbuf[3] = 0x8D; // Can receive frames (YES), Ready to Communicate (YES), Ready to Receive (YES), Incomig Call (NO), Data is Value (YES)
+
+ sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x04);
+ } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_RSP) { // UIH Modem Status Response
+ if(!creditSent) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nSend UIH Command with credit"), 0x80);
+#endif
+ sendRfcommCredit(rfcommChannelConnection, rfcommDirection, 0, RFCOMM_UIH, 0x10, sizeof (rfcommDataBuffer)); // Send credit
+ creditSent = true;
+ timer = millis();
+ waitForLastCommand = true;
+ }
+ } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[10] == 0x01) { // UIH Command with credit
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nReceived UIH Command with credit"), 0x80);
+#endif
+ } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_RPN_CMD) { // UIH Remote Port Negotiation Command
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nReceived UIH Remote Port Negotiation Command"), 0x80);
+#endif
+ rfcommbuf[0] = BT_RFCOMM_RPN_RSP; // Command
+ rfcommbuf[1] = l2capinbuf[12]; // Length and shiftet like so: length << 1 | 1
+ rfcommbuf[2] = l2capinbuf[13]; // Channel: channel << 1 | 1
+ rfcommbuf[3] = l2capinbuf[14]; // Pre difined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM
+ rfcommbuf[4] = l2capinbuf[15]; // Priority
+ rfcommbuf[5] = l2capinbuf[16]; // Timer
+ rfcommbuf[6] = l2capinbuf[17]; // Max Fram Size LSB
+ rfcommbuf[7] = l2capinbuf[18]; // Max Fram Size MSB
+ rfcommbuf[8] = l2capinbuf[19]; // MaxRatransm.
+ rfcommbuf[9] = l2capinbuf[20]; // Number of Frames
+ sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x0A); // UIH Remote Port Negotiation Response
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nRFCOMM Connection is now established\r\n"), 0x80);
+#endif
+ onInit();
+ }
+#ifdef EXTRADEBUG
+ else if(rfcommChannelType != RFCOMM_DISC) {
+ Notify(PSTR("\r\nUnsupported RFCOMM Data - ChannelType: "), 0x80);
+ D_PrintHex<uint8_t > (rfcommChannelType, 0x80);
+ Notify(PSTR(" Command: "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[11], 0x80);
+ }
+#endif
+ }
+ }
+#ifdef EXTRADEBUG
+ else {
+ Notify(PSTR("\r\nUnsupported L2CAP Data - Channel ID: "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[7], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[6], 0x80);
+ }
+#endif
+ SDP_task();
+ RFCOMM_task();
+ }
+}
+
+void SPP::Run() {
+ if(waitForLastCommand && (millis() - timer) > 100) { // We will only wait 100ms and see if the UIH Remote Port Negotiation Command is send, as some deviced don't send it
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nRFCOMM Connection is now established - Automatic\r\n"), 0x80);
+#endif
+ onInit();
+ }
+ send(); // Send all bytes currently in the buffer
+}
+
+void SPP::onInit() {
+ creditSent = false;
+ waitForLastCommand = false;
+ connected = true; // The RFCOMM channel is now established
+ sppIndex = 0;
+ if(pFuncOnInit)
+ pFuncOnInit(); // Call the user function
+};
+
+void SPP::SDP_task() {
+ switch(l2cap_sdp_state) {
+ case L2CAP_SDP_WAIT:
+ if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_SDP_REQUEST)) {
+ l2cap_clear_flag(L2CAP_FLAG_CONNECTION_SDP_REQUEST); // Clear flag
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nSDP Incoming Connection Request"), 0x80);
+#endif
+ pBtd->l2cap_connection_response(hci_handle, identifier, sdp_dcid, sdp_scid, PENDING);
+ delay(1);
+ pBtd->l2cap_connection_response(hci_handle, identifier, sdp_dcid, sdp_scid, SUCCESSFUL);
+ identifier++;
+ delay(1);
+ pBtd->l2cap_config_request(hci_handle, identifier, sdp_scid);
+ l2cap_sdp_state = L2CAP_SDP_SUCCESS;
+ } else if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_SDP_REQUEST)) {
+ l2cap_clear_flag(L2CAP_FLAG_DISCONNECT_SDP_REQUEST); // Clear flag
+ SDPConnected = false;
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nDisconnected SDP Channel"), 0x80);
+#endif
+ pBtd->l2cap_disconnection_response(hci_handle, identifier, sdp_dcid, sdp_scid);
+ }
+ break;
+ case L2CAP_SDP_SUCCESS:
+ if(l2cap_check_flag(L2CAP_FLAG_CONFIG_SDP_SUCCESS)) {
+ l2cap_clear_flag(L2CAP_FLAG_CONFIG_SDP_SUCCESS); // Clear flag
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nSDP Successfully Configured"), 0x80);
+#endif
+ firstMessage = true; // Reset bool
+ SDPConnected = true;
+ l2cap_sdp_state = L2CAP_SDP_WAIT;
+ }
+ break;
+
+ case L2CAP_DISCONNECT_RESPONSE: // This is for both disconnection response from the RFCOMM and SDP channel if they were connected
+ if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_RESPONSE)) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nDisconnected L2CAP Connection"), 0x80);
+#endif
+ pBtd->hci_disconnect(hci_handle);
+ hci_handle = -1; // Reset handle
+ Reset();
+ }
+ break;
+ }
+}
+
+void SPP::RFCOMM_task() {
+ switch(l2cap_rfcomm_state) {
+ case L2CAP_RFCOMM_WAIT:
+ if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST)) {
+ l2cap_clear_flag(L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST); // Clear flag
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nRFCOMM Incoming Connection Request"), 0x80);
+#endif
+ pBtd->l2cap_connection_response(hci_handle, identifier, rfcomm_dcid, rfcomm_scid, PENDING);
+ delay(1);
+ pBtd->l2cap_connection_response(hci_handle, identifier, rfcomm_dcid, rfcomm_scid, SUCCESSFUL);
+ identifier++;
+ delay(1);
+ pBtd->l2cap_config_request(hci_handle, identifier, rfcomm_scid);
+ l2cap_rfcomm_state = L2CAP_RFCOMM_SUCCESS;
+ } else if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST)) {
+ l2cap_clear_flag(L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST); // Clear flag
+ RFCOMMConnected = false;
+ connected = false;
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nDisconnected RFCOMM Channel"), 0x80);
+#endif
+ pBtd->l2cap_disconnection_response(hci_handle, identifier, rfcomm_dcid, rfcomm_scid);
+ }
+ break;
+ case L2CAP_RFCOMM_SUCCESS:
+ if(l2cap_check_flag(L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS)) {
+ l2cap_clear_flag(L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS); // Clear flag
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nRFCOMM Successfully Configured"), 0x80);
+#endif
+ rfcommAvailable = 0; // Reset number of bytes available
+ bytesRead = 0; // Reset number of bytes received
+ RFCOMMConnected = true;
+ l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT;
+ }
+ break;
+ }
+}
+/************************************************************/
+/* SDP Commands */
+
+/************************************************************/
+void SPP::SDP_Command(uint8_t* data, uint8_t nbytes) { // See page 223 in the Bluetooth specs
+ pBtd->L2CAP_Command(hci_handle, data, nbytes, sdp_scid[0], sdp_scid[1]);
+}
+
+void SPP::serviceNotSupported(uint8_t transactionIDHigh, uint8_t transactionIDLow) { // See page 235 in the Bluetooth specs
+ l2capoutbuf[0] = SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU;
+ l2capoutbuf[1] = transactionIDHigh;
+ l2capoutbuf[2] = transactionIDLow;
+ l2capoutbuf[3] = 0x00; // MSB Parameter Length
+ l2capoutbuf[4] = 0x05; // LSB Parameter Length = 5
+ l2capoutbuf[5] = 0x00; // MSB AttributeListsByteCount
+ l2capoutbuf[6] = 0x02; // LSB AttributeListsByteCount = 2
+
+ /* Attribute ID/Value Sequence: */
+ l2capoutbuf[7] = 0x35; // Data element sequence - length in next byte
+ l2capoutbuf[8] = 0x00; // Length = 0
+ l2capoutbuf[9] = 0x00; // No continuation state
+
+ SDP_Command(l2capoutbuf, 10);
+}
+
+void SPP::serialPortResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow) {
+ l2capoutbuf[0] = SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU;
+ l2capoutbuf[1] = transactionIDHigh;
+ l2capoutbuf[2] = transactionIDLow;
+ l2capoutbuf[3] = 0x00; // MSB Parameter Length
+ l2capoutbuf[4] = 0x2B; // LSB Parameter Length = 43
+ l2capoutbuf[5] = 0x00; // MSB AttributeListsByteCount
+ l2capoutbuf[6] = 0x26; // LSB AttributeListsByteCount = 38
+
+ /* Attribute ID/Value Sequence: */
+ l2capoutbuf[7] = 0x36; // Data element sequence - length in next two bytes
+ l2capoutbuf[8] = 0x00; // MSB Length
+ l2capoutbuf[9] = 0x3C; // LSB Length = 60
+
+ l2capoutbuf[10] = 0x36; // Data element sequence - length in next two bytes
+ l2capoutbuf[11] = 0x00; // MSB Length
+ l2capoutbuf[12] = 0x39; // LSB Length = 57
+
+ l2capoutbuf[13] = 0x09; // Unsigned Integer - length 2 bytes
+ l2capoutbuf[14] = 0x00; // MSB ServiceRecordHandle
+ l2capoutbuf[15] = 0x00; // LSB ServiceRecordHandle
+ l2capoutbuf[16] = 0x0A; // Unsigned int - length 4 bytes
+ l2capoutbuf[17] = 0x00; // ServiceRecordHandle value - TODO: Is this related to HCI_Handle?
+ l2capoutbuf[18] = 0x01;
+ l2capoutbuf[19] = 0x00;
+ l2capoutbuf[20] = 0x06;
+
+ l2capoutbuf[21] = 0x09; // Unsigned Integer - length 2 bytes
+ l2capoutbuf[22] = 0x00; // MSB ServiceClassIDList
+ l2capoutbuf[23] = 0x01; // LSB ServiceClassIDList
+ l2capoutbuf[24] = 0x35; // Data element sequence - length in next byte
+ l2capoutbuf[25] = 0x03; // Length = 3
+ l2capoutbuf[26] = 0x19; // UUID (universally unique identifier) - length = 2 bytes
+ l2capoutbuf[27] = 0x11; // MSB SerialPort
+ l2capoutbuf[28] = 0x01; // LSB SerialPort
+
+ l2capoutbuf[29] = 0x09; // Unsigned Integer - length 2 bytes
+ l2capoutbuf[30] = 0x00; // MSB ProtocolDescriptorList
+ l2capoutbuf[31] = 0x04; // LSB ProtocolDescriptorList
+ l2capoutbuf[32] = 0x35; // Data element sequence - length in next byte
+ l2capoutbuf[33] = 0x0C; // Length = 12
+
+ l2capoutbuf[34] = 0x35; // Data element sequence - length in next byte
+ l2capoutbuf[35] = 0x03; // Length = 3
+ l2capoutbuf[36] = 0x19; // UUID (universally unique identifier) - length = 2 bytes
+ l2capoutbuf[37] = 0x01; // MSB L2CAP
+ l2capoutbuf[38] = 0x00; // LSB L2CAP
+
+ l2capoutbuf[39] = 0x35; // Data element sequence - length in next byte
+ l2capoutbuf[40] = 0x05; // Length = 5
+ l2capoutbuf[41] = 0x19; // UUID (universally unique identifier) - length = 2 bytes
+ l2capoutbuf[42] = 0x00; // MSB RFCOMM
+ l2capoutbuf[43] = 0x03; // LSB RFCOMM
+ l2capoutbuf[44] = 0x08; // Unsigned Integer - length 1 byte
+
+ l2capoutbuf[45] = 0x02; // ContinuationState - Two more bytes
+ l2capoutbuf[46] = 0x00; // MSB length
+ l2capoutbuf[47] = 0x19; // LSB length = 25 more bytes to come
+
+ SDP_Command(l2capoutbuf, 48);
+}
+
+void SPP::serialPortResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow) {
+ l2capoutbuf[0] = SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU;
+ l2capoutbuf[1] = transactionIDHigh;
+ l2capoutbuf[2] = transactionIDLow;
+ l2capoutbuf[3] = 0x00; // MSB Parameter Length
+ l2capoutbuf[4] = 0x1C; // LSB Parameter Length = 28
+ l2capoutbuf[5] = 0x00; // MSB AttributeListsByteCount
+ l2capoutbuf[6] = 0x19; // LSB AttributeListsByteCount = 25
+
+ /* Attribute ID/Value Sequence: */
+ l2capoutbuf[7] = 0x01; // Channel 1 - TODO: Try different values, so multiple servers can be used at once
+
+ l2capoutbuf[8] = 0x09; // Unsigned Integer - length 2 bytes
+ l2capoutbuf[9] = 0x00; // MSB LanguageBaseAttributeIDList
+ l2capoutbuf[10] = 0x06; // LSB LanguageBaseAttributeIDList
+ l2capoutbuf[11] = 0x35; // Data element sequence - length in next byte
+ l2capoutbuf[12] = 0x09; // Length = 9
+
+ // Identifier representing the natural language = en = English - see: "ISO 639:1988"
+ l2capoutbuf[13] = 0x09; // Unsigned Integer - length 2 bytes
+ l2capoutbuf[14] = 0x65; // 'e'
+ l2capoutbuf[15] = 0x6E; // 'n'
+
+ // "The second element of each triplet contains an identifier that specifies a character encoding used for the language"
+ // Encoding is set to 106 (UTF-8) - see: http://www.iana.org/assignments/character-sets/character-sets.xhtml
+ l2capoutbuf[16] = 0x09; // Unsigned Integer - length 2 bytes
+ l2capoutbuf[17] = 0x00; // MSB of character encoding
+ l2capoutbuf[18] = 0x6A; // LSB of character encoding (106)
+
+ // Attribute ID that serves as the base attribute ID for the natural language in the service record
+ // "To facilitate the retrieval of human-readable universal attributes in a principal language, the base attribute ID value for the primary language supported by a service record shall be 0x0100"
+ l2capoutbuf[19] = 0x09; // Unsigned Integer - length 2 bytes
+ l2capoutbuf[20] = 0x01;
+ l2capoutbuf[21] = 0x00;
+
+ l2capoutbuf[22] = 0x09; // Unsigned Integer - length 2 bytes
+ l2capoutbuf[23] = 0x01; // MSB ServiceDescription
+ l2capoutbuf[24] = 0x00; // LSB ServiceDescription
+
+ l2capoutbuf[25] = 0x25; // Text string - length in next byte
+ l2capoutbuf[26] = 0x05; // Name length
+ l2capoutbuf[27] = 'T';
+ l2capoutbuf[28] = 'K';
+ l2capoutbuf[29] = 'J';
+ l2capoutbuf[30] = 'S';
+ l2capoutbuf[31] = 'P';
+ l2capoutbuf[32] = 0x00; // No continuation state
+
+ SDP_Command(l2capoutbuf, 33);
+}
+
+void SPP::l2capResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow) {
+ serialPortResponse1(transactionIDHigh, transactionIDLow); // These has to send all the supported functions, since it only supports virtual serialport it just sends the message again
+}
+
+void SPP::l2capResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow) {
+ serialPortResponse2(transactionIDHigh, transactionIDLow); // Same data as serialPortResponse2
+}
+/************************************************************/
+/* RFCOMM Commands */
+
+/************************************************************/
+void SPP::RFCOMM_Command(uint8_t* data, uint8_t nbytes) {
+ pBtd->L2CAP_Command(hci_handle, data, nbytes, rfcomm_scid[0], rfcomm_scid[1]);
+}
+
+void SPP::sendRfcomm(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t* data, uint8_t length) {
+ l2capoutbuf[0] = channel | direction | CR | extendAddress; // RFCOMM Address
+ l2capoutbuf[1] = channelType | pfBit; // RFCOMM Control
+ l2capoutbuf[2] = length << 1 | 0x01; // Length and format (always 0x01 bytes format)
+ uint8_t i = 0;
+ for(; i < length; i++)
+ l2capoutbuf[i + 3] = data[i];
+ l2capoutbuf[i + 3] = calcFcs(l2capoutbuf);
+#ifdef EXTRADEBUG
+ Notify(PSTR(" - RFCOMM Data: "), 0x80);
+ for(i = 0; i < length + 4; i++) {
+ D_PrintHex<uint8_t > (l2capoutbuf[i], 0x80);
+ Notify(PSTR(" "), 0x80);
+ }
+#endif
+ RFCOMM_Command(l2capoutbuf, length + 4);
+}
+
+void SPP::sendRfcommCredit(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t credit) {
+ l2capoutbuf[0] = channel | direction | CR | extendAddress; // RFCOMM Address
+ l2capoutbuf[1] = channelType | pfBit; // RFCOMM Control
+ l2capoutbuf[2] = 0x01; // Length = 0
+ l2capoutbuf[3] = credit; // Credit
+ l2capoutbuf[4] = calcFcs(l2capoutbuf);
+#ifdef EXTRADEBUG
+ Notify(PSTR(" - RFCOMM Credit Data: "), 0x80);
+ for(uint8_t i = 0; i < 5; i++) {
+ D_PrintHex<uint8_t > (l2capoutbuf[i], 0x80);
+ Notify(PSTR(" "), 0x80);
+ }
+#endif
+ RFCOMM_Command(l2capoutbuf, 5);
+}
+
+/* CRC on 2 bytes */
+uint8_t SPP::crc(uint8_t *data) {
+ return (pgm_read_byte(&rfcomm_crc_table[pgm_read_byte(&rfcomm_crc_table[0xFF ^ data[0]]) ^ data[1]]));
+}
+
+/* Calculate FCS */
+uint8_t SPP::calcFcs(uint8_t *data) {
+ uint8_t temp = crc(data);
+ if((data[1] & 0xEF) == RFCOMM_UIH)
+ return (0xFF - temp); // FCS on 2 bytes
+ else
+ return (0xFF - pgm_read_byte(&rfcomm_crc_table[temp ^ data[2]])); // FCS on 3 bytes
+}
+
+/* Check FCS */
+bool SPP::checkFcs(uint8_t *data, uint8_t fcs) {
+ uint8_t temp = crc(data);
+ if((data[1] & 0xEF) != RFCOMM_UIH)
+ temp = pgm_read_byte(&rfcomm_crc_table[temp ^ data[2]]); // FCS on 3 bytes
+ return (pgm_read_byte(&rfcomm_crc_table[temp ^ fcs]) == 0xCF);
+}
+
+/* Serial commands */
+#if defined(ARDUINO) && ARDUINO >=100
+
+size_t SPP::write(uint8_t data) {
+ return write(&data, 1);
+}
+#else
+
+void SPP::write(uint8_t data) {
+ write(&data, 1);
+}
+#endif
+
+#if defined(ARDUINO) && ARDUINO >=100
+
+size_t SPP::write(const uint8_t *data, size_t size) {
+#else
+
+void SPP::write(const uint8_t *data, size_t size) {
+#endif
+ for(uint8_t i = 0; i < size; i++) {
+ if(sppIndex >= sizeof (sppOutputBuffer) / sizeof (sppOutputBuffer[0]))
+ send(); // Send the current data in the buffer
+ sppOutputBuffer[sppIndex++] = data[i]; // All the bytes are put into a buffer and then send using the send() function
+ }
+#if defined(ARDUINO) && ARDUINO >=100
+ return size;
+#endif
+}
+
+void SPP::send() {
+ if(!connected || !sppIndex)
+ return;
+ uint8_t length; // This is the length of the string we are sending
+ uint8_t offset = 0; // This is used to keep track of where we are in the string
+
+ l2capoutbuf[0] = rfcommChannelConnection | 0 | 0 | extendAddress; // RFCOMM Address
+ l2capoutbuf[1] = RFCOMM_UIH; // RFCOMM Control
+
+ while(sppIndex) { // We will run this while loop until this variable is 0
+ if(sppIndex > (sizeof (l2capoutbuf) - 4)) // Check if the string is larger than the outgoing buffer
+ length = sizeof (l2capoutbuf) - 4;
+ else
+ length = sppIndex;
+
+ l2capoutbuf[2] = length << 1 | 1; // Length
+ uint8_t i = 0;
+ for(; i < length; i++)
+ l2capoutbuf[i + 3] = sppOutputBuffer[i + offset];
+ l2capoutbuf[i + 3] = calcFcs(l2capoutbuf); // Calculate checksum
+
+ RFCOMM_Command(l2capoutbuf, length + 4);
+
+ sppIndex -= length;
+ offset += length; // Increment the offset
+ }
+}
+
+int SPP::available(void) {
+ return rfcommAvailable;
+};
+
+void SPP::discard(void) {
+ rfcommAvailable = 0;
+}
+
+int SPP::peek(void) {
+ if(rfcommAvailable == 0) // Don't read if there is nothing in the buffer
+ return -1;
+ return rfcommDataBuffer[0];
+}
+
+int SPP::read(void) {
+ if(rfcommAvailable == 0) // Don't read if there is nothing in the buffer
+ return -1;
+ uint8_t output = rfcommDataBuffer[0];
+ for(uint8_t i = 1; i < rfcommAvailable; i++)
+ rfcommDataBuffer[i - 1] = rfcommDataBuffer[i]; // Shift the buffer one left
+ rfcommAvailable--;
+ bytesRead++;
+ if(bytesRead > (sizeof (rfcommDataBuffer) - 5)) { // We will send the command just before it runs out of credit
+ bytesRead = 0;
+ sendRfcommCredit(rfcommChannelConnection, rfcommDirection, 0, RFCOMM_UIH, 0x10, sizeof (rfcommDataBuffer)); // Send more credit
+#ifdef EXTRADEBUG
+ Notify(PSTR("\r\nSent "), 0x80);
+ Notify((uint8_t)sizeof (rfcommDataBuffer), 0x80);
+ Notify(PSTR(" more credit"), 0x80);
+#endif
+ }
+ return output;
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/SPP.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/SPP.h
new file mode 100644
index 000000000..233ac611f
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/SPP.h
@@ -0,0 +1,225 @@
+/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
+
+ This software may be distributed and modified under the terms of the GNU
+ General Public License version 2 (GPL2) as published by the Free Software
+ Foundation and appearing in the file GPL2.TXT included in the packaging of
+ this file. Please note that GPL2 Section 2[b] requires that all works based
+ on this software must also be made publicly available under the terms of
+ the GPL2 ("Copyleft").
+
+ Contact information
+ -------------------
+
+ Kristian Lauszus, TKJ Electronics
+ Web : http://www.tkjelectronics.com
+ e-mail : kristianl@tkjelectronics.com
+ */
+
+#ifndef _spp_h_
+#define _spp_h_
+
+#include "BTD.h"
+
+/* Used for SDP */
+#define SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST_PDU 0x06 // See the RFCOMM specs
+#define SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU 0x07 // See the RFCOMM specs
+#define SERIALPORT_UUID 0x1101 // See http://www.bluetooth.org/Technical/AssignedNumbers/service_discovery.htm
+#define L2CAP_UUID 0x0100
+
+/* Used for RFCOMM */
+#define RFCOMM_SABM 0x2F
+#define RFCOMM_UA 0x63
+#define RFCOMM_UIH 0xEF
+//#define RFCOMM_DM 0x0F
+#define RFCOMM_DISC 0x43
+
+#define extendAddress 0x01 // Always 1
+
+// Multiplexer message types
+#define BT_RFCOMM_PN_CMD 0x83
+#define BT_RFCOMM_PN_RSP 0x81
+#define BT_RFCOMM_MSC_CMD 0xE3
+#define BT_RFCOMM_MSC_RSP 0xE1
+#define BT_RFCOMM_RPN_CMD 0x93
+#define BT_RFCOMM_RPN_RSP 0x91
+/*
+#define BT_RFCOMM_TEST_CMD 0x23
+#define BT_RFCOMM_TEST_RSP 0x21
+#define BT_RFCOMM_FCON_CMD 0xA3
+#define BT_RFCOMM_FCON_RSP 0xA1
+#define BT_RFCOMM_FCOFF_CMD 0x63
+#define BT_RFCOMM_FCOFF_RSP 0x61
+#define BT_RFCOMM_RLS_CMD 0x53
+#define BT_RFCOMM_RLS_RSP 0x51
+#define BT_RFCOMM_NSC_RSP 0x11
+ */
+
+/**
+ * This BluetoothService class implements the Serial Port Protocol (SPP).
+ * It inherits the Arduino Stream class. This allows it to use all the standard Arduino print and stream functions.
+ */
+class SPP : public BluetoothService, public Stream {
+public:
+ /**
+ * Constructor for the SPP class.
+ * @param p Pointer to BTD class instance.
+ * @param name Set the name to BTD#btdName. If argument is omitted, then "Arduino" will be used.
+ * @param pin Write the pin to BTD#btdPin. If argument is omitted, then "0000" will be used.
+ */
+ SPP(BTD *p, const char *name = "Arduino", const char *pin = "0000");
+
+ /** @name BluetoothService implementation */
+ /** Used this to disconnect the virtual serial port. */
+ void disconnect();
+ /**@}*/
+
+ /**
+ * Used to provide Boolean tests for the class.
+ * @return Return true if SPP communication is connected.
+ */
+ operator bool() {
+ return connected;
+ }
+ /** Variable used to indicate if the connection is established. */
+ bool connected;
+
+ /** @name Serial port profile (SPP) Print functions */
+ /**
+ * Get number of bytes waiting to be read.
+ * @return Return the number of bytes ready to be read.
+ */
+ int available(void);
+
+ /** Send out all bytes in the buffer. */
+ void flush(void) {
+ send();
+ };
+ /**
+ * Used to read the next value in the buffer without advancing to the next one.
+ * @return Return the byte. Will return -1 if no bytes are available.
+ */
+ int peek(void);
+ /**
+ * Used to read the buffer.
+ * @return Return the byte. Will return -1 if no bytes are available.
+ */
+ int read(void);
+
+#if defined(ARDUINO) && ARDUINO >=100
+ /**
+ * Writes the byte to send to a buffer. The message is send when either send() or after Usb.Task() is called.
+ * @param data The byte to write.
+ * @return Return the number of bytes written.
+ */
+ size_t write(uint8_t data);
+ /**
+ * Writes the bytes to send to a buffer. The message is send when either send() or after Usb.Task() is called.
+ * @param data The data array to send.
+ * @param size Size of the data.
+ * @return Return the number of bytes written.
+ */
+ size_t write(const uint8_t* data, size_t size);
+ /** Pull in write(const char *str) from Print */
+ using Print::write;
+#else
+ /**
+ * Writes the byte to send to a buffer. The message is send when either send() or after Usb.Task() is called.
+ * @param data The byte to write.
+ */
+ void write(uint8_t data);
+ /**
+ * Writes the bytes to send to a buffer. The message is send when either send() or after Usb.Task() is called.
+ * @param data The data array to send.
+ * @param size Size of the data.
+ */
+ void write(const uint8_t* data, size_t size);
+#endif
+
+ /** Discard all the bytes in the buffer. */
+ void discard(void);
+ /**
+ * This will send all the bytes in the buffer.
+ * This is called whenever Usb.Task() is called,
+ * but can also be called via this function.
+ */
+ void send(void);
+ /**@}*/
+
+protected:
+ /** @name BluetoothService implementation */
+ /**
+ * Used to pass acldata to the services.
+ * @param ACLData Incoming acldata.
+ */
+ void ACLData(uint8_t* ACLData);
+ /** Used to establish the connection automatically. */
+ void Run();
+ /** Use this to reset the service. */
+ void Reset();
+ /**
+ * Called when a device is successfully initialized.
+ * Use attachOnInit(void (*funcOnInit)(void)) to call your own function.
+ * This is useful for instance if you want to set the LEDs in a specific way.
+ */
+ void onInit();
+ /**@}*/
+
+private:
+ /* Set true when a channel is created */
+ bool SDPConnected;
+ bool RFCOMMConnected;
+
+ /* Variables used by L2CAP state machines */
+ uint8_t l2cap_sdp_state;
+ uint8_t l2cap_rfcomm_state;
+
+ uint8_t l2capoutbuf[BULK_MAXPKTSIZE]; // General purpose buffer for l2cap out data
+ uint8_t rfcommbuf[10]; // Buffer for RFCOMM Commands
+
+ /* L2CAP Channels */
+ uint8_t sdp_scid[2]; // L2CAP source CID for SDP
+ uint8_t sdp_dcid[2]; // 0x0050
+ uint8_t rfcomm_scid[2]; // L2CAP source CID for RFCOMM
+ uint8_t rfcomm_dcid[2]; // 0x0051
+
+ /* RFCOMM Variables */
+ uint8_t rfcommChannel;
+ uint8_t rfcommChannelConnection; // This is the channel the SPP channel will be running at
+ uint8_t rfcommDirection;
+ uint8_t rfcommCommandResponse;
+ uint8_t rfcommChannelType;
+ uint8_t rfcommPfBit;
+
+ uint32_t timer;
+ bool waitForLastCommand;
+ bool creditSent;
+
+ uint8_t rfcommDataBuffer[100]; // Create a 100 sized buffer for incoming data
+ uint8_t sppOutputBuffer[100]; // Create a 100 sized buffer for outgoing SPP data
+ uint8_t sppIndex;
+ uint8_t rfcommAvailable;
+
+ bool firstMessage; // Used to see if it's the first SDP request received
+ uint8_t bytesRead; // Counter to see when it's time to send more credit
+
+ /* State machines */
+ void SDP_task(); // SDP state machine
+ void RFCOMM_task(); // RFCOMM state machine
+
+ /* SDP Commands */
+ void SDP_Command(uint8_t *data, uint8_t nbytes);
+ void serviceNotSupported(uint8_t transactionIDHigh, uint8_t transactionIDLow);
+ void serialPortResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow);
+ void serialPortResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow);
+ void l2capResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow);
+ void l2capResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow);
+
+ /* RFCOMM Commands */
+ void RFCOMM_Command(uint8_t *data, uint8_t nbytes);
+ void sendRfcomm(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t *data, uint8_t length);
+ void sendRfcommCredit(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t credit);
+ uint8_t calcFcs(uint8_t *data);
+ bool checkFcs(uint8_t *data, uint8_t fcs);
+ uint8_t crc(uint8_t *data);
+};
+#endif
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Usb.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Usb.cpp
new file mode 100644
index 000000000..14272588a
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Usb.cpp
@@ -0,0 +1,812 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+/* USB functions */
+
+#include "Usb.h"
+
+static uint8_t usb_error = 0;
+static uint8_t usb_task_state;
+
+/* constructor */
+USB::USB() : bmHubPre(0) {
+ usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE; //set up state machine
+ init();
+}
+
+/* Initialize data structures */
+void USB::init() {
+ //devConfigIndex = 0;
+ bmHubPre = 0;
+}
+
+uint8_t USB::getUsbTaskState(void) {
+ return ( usb_task_state);
+}
+
+void USB::setUsbTaskState(uint8_t state) {
+ usb_task_state = state;
+}
+
+EpInfo* USB::getEpInfoEntry(uint8_t addr, uint8_t ep) {
+ UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
+
+ if(!p || !p->epinfo)
+ return NULL;
+
+ EpInfo *pep = p->epinfo;
+
+ for(uint8_t i = 0; i < p->epcount; i++) {
+ if((pep)->epAddr == ep)
+ return pep;
+
+ pep++;
+ }
+ return NULL;
+}
+
+/* set device table entry */
+
+/* each device is different and has different number of endpoints. This function plugs endpoint record structure, defined in application, to devtable */
+uint8_t USB::setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr) {
+ if(!eprecord_ptr)
+ return USB_ERROR_INVALID_ARGUMENT;
+
+ UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
+
+ if(!p)
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+ p->address.devAddress = addr;
+ p->epinfo = eprecord_ptr;
+ p->epcount = epcount;
+
+ return 0;
+}
+
+uint8_t USB::SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t *nak_limit) {
+ UsbDevice *p = addrPool.GetUsbDevicePtr(addr);
+
+ if(!p)
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+ if(!p->epinfo)
+ return USB_ERROR_EPINFO_IS_NULL;
+
+ *ppep = getEpInfoEntry(addr, ep);
+
+ if(!*ppep)
+ return USB_ERROR_EP_NOT_FOUND_IN_TBL;
+
+ *nak_limit = (0x0001UL << (((*ppep)->bmNakPower > USB_NAK_MAX_POWER) ? USB_NAK_MAX_POWER : (*ppep)->bmNakPower));
+ (*nak_limit)--;
+ /*
+ USBTRACE2("\r\nAddress: ", addr);
+ USBTRACE2(" EP: ", ep);
+ USBTRACE2(" NAK Power: ",(*ppep)->bmNakPower);
+ USBTRACE2(" NAK Limit: ", nak_limit);
+ USBTRACE("\r\n");
+ */
+ regWr(rPERADDR, addr); //set peripheral address
+
+ uint8_t mode = regRd(rMODE);
+
+ //Serial.print("\r\nMode: ");
+ //Serial.println( mode, HEX);
+ //Serial.print("\r\nLS: ");
+ //Serial.println(p->lowspeed, HEX);
+
+
+
+ // Set bmLOWSPEED and bmHUBPRE in case of low-speed device, reset them otherwise
+ regWr(rMODE, (p->lowspeed) ? mode | bmLOWSPEED | bmHubPre : mode & ~(bmHUBPRE | bmLOWSPEED));
+
+ return 0;
+}
+
+/* Control transfer. Sets address, endpoint, fills control packet with necessary data, dispatches control packet, and initiates bulk IN transfer, */
+/* depending on request. Actual requests are defined as inlines */
+/* return codes: */
+/* 00 = success */
+
+/* 01-0f = non-zero HRSLT */
+uint8_t USB::ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi,
+ uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, USBReadParser *p) {
+ bool direction = false; //request direction, IN or OUT
+ uint8_t rcode;
+ SETUP_PKT setup_pkt;
+
+ EpInfo *pep = NULL;
+ uint16_t nak_limit = 0;
+
+ rcode = SetAddress(addr, ep, &pep, &nak_limit);
+
+ if(rcode)
+ return rcode;
+
+ direction = ((bmReqType & 0x80) > 0);
+
+ /* fill in setup packet */
+ setup_pkt.ReqType_u.bmRequestType = bmReqType;
+ setup_pkt.bRequest = bRequest;
+ setup_pkt.wVal_u.wValueLo = wValLo;
+ setup_pkt.wVal_u.wValueHi = wValHi;
+ setup_pkt.wIndex = wInd;
+ setup_pkt.wLength = total;
+
+ bytesWr(rSUDFIFO, 8, (uint8_t*) & setup_pkt); //transfer to setup packet FIFO
+
+ rcode = dispatchPkt(tokSETUP, ep, nak_limit); //dispatch packet
+
+ if(rcode) //return HRSLT if not zero
+ return ( rcode);
+
+ if(dataptr != NULL) //data stage, if present
+ {
+ if(direction) //IN transfer
+ {
+ uint16_t left = total;
+
+ pep->bmRcvToggle = 1; //bmRCVTOG1;
+
+ while(left) {
+ // Bytes read into buffer
+ uint16_t read = nbytes;
+ //uint16_t read = (left<nbytes) ? left : nbytes;
+
+ rcode = InTransfer(pep, nak_limit, &read, dataptr);
+ if(rcode == hrTOGERR) {
+ // yes, we flip it wrong here so that next time it is actually correct!
+ pep->bmRcvToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1;
+ continue;
+ }
+
+ if(rcode)
+ return rcode;
+
+ // Invoke callback function if inTransfer completed successfully and callback function pointer is specified
+ if(!rcode && p)
+ ((USBReadParser*)p)->Parse(read, dataptr, total - left);
+
+ left -= read;
+
+ if(read < nbytes)
+ break;
+ }
+ } else //OUT transfer
+ {
+ pep->bmSndToggle = 1; //bmSNDTOG1;
+ rcode = OutTransfer(pep, nak_limit, nbytes, dataptr);
+ }
+ if(rcode) //return error
+ return ( rcode);
+ }
+ // Status stage
+ return dispatchPkt((direction) ? tokOUTHS : tokINHS, ep, nak_limit); //GET if direction
+}
+
+/* IN transfer to arbitrary endpoint. Assumes PERADDR is set. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
+/* Keep sending INs and writes data to memory area pointed by 'data' */
+
+/* rcode 0 if no errors. rcode 01-0f is relayed from dispatchPkt(). Rcode f0 means RCVDAVIRQ error,
+ fe USB xfer timeout */
+uint8_t USB::inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t* data) {
+ EpInfo *pep = NULL;
+ uint16_t nak_limit = 0;
+
+ uint8_t rcode = SetAddress(addr, ep, &pep, &nak_limit);
+
+ if(rcode) {
+ USBTRACE3("(USB::InTransfer) SetAddress Failed ", rcode, 0x81);
+ USBTRACE3("(USB::InTransfer) addr requested ", addr, 0x81);
+ USBTRACE3("(USB::InTransfer) ep requested ", ep, 0x81);
+ return rcode;
+ }
+ return InTransfer(pep, nak_limit, nbytesptr, data);
+}
+
+uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t* data) {
+ uint8_t rcode = 0;
+ uint8_t pktsize;
+
+ uint16_t nbytes = *nbytesptr;
+ //printf("Requesting %i bytes ", nbytes);
+ uint8_t maxpktsize = pep->maxPktSize;
+
+ *nbytesptr = 0;
+ regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value
+
+ // use a 'break' to exit this loop
+ while(1) {
+ rcode = dispatchPkt(tokIN, pep->epAddr, nak_limit); //IN packet to EP-'endpoint'. Function takes care of NAKS.
+ if(rcode == hrTOGERR) {
+ // yes, we flip it wrong here so that next time it is actually correct!
+ pep->bmRcvToggle = (regRd(rHRSL) & bmRCVTOGRD) ? 0 : 1;
+ regWr(rHCTL, (pep->bmRcvToggle) ? bmRCVTOG1 : bmRCVTOG0); //set toggle value
+ continue;
+ }
+ if(rcode) {
+ //printf(">>>>>>>> Problem! dispatchPkt %2.2x\r\n", rcode);
+ break; //should be 0, indicating ACK. Else return error code.
+ }
+ /* check for RCVDAVIRQ and generate error if not present */
+ /* the only case when absence of RCVDAVIRQ makes sense is when toggle error occurred. Need to add handling for that */
+ if((regRd(rHIRQ) & bmRCVDAVIRQ) == 0) {
+ //printf(">>>>>>>> Problem! NO RCVDAVIRQ!\r\n");
+ rcode = 0xf0; //receive error
+ break;
+ }
+ pktsize = regRd(rRCVBC); //number of received bytes
+ //printf("Got %i bytes \r\n", pktsize);
+ // This would be OK, but...
+ //assert(pktsize <= nbytes);
+ if(pktsize > nbytes) {
+ // This can happen. Use of assert on Arduino locks up the Arduino.
+ // So I will trim the value, and hope for the best.
+ //printf(">>>>>>>> Problem! Wanted %i bytes but got %i.\r\n", nbytes, pktsize);
+ pktsize = nbytes;
+ }
+
+ int16_t mem_left = (int16_t)nbytes - *((int16_t*)nbytesptr);
+
+ if(mem_left < 0)
+ mem_left = 0;
+
+ data = bytesRd(rRCVFIFO, ((pktsize > mem_left) ? mem_left : pktsize), data);
+
+ regWr(rHIRQ, bmRCVDAVIRQ); // Clear the IRQ & free the buffer
+ *nbytesptr += pktsize; // add this packet's byte count to total transfer length
+
+ /* The transfer is complete under two conditions: */
+ /* 1. The device sent a short packet (L.T. maxPacketSize) */
+ /* 2. 'nbytes' have been transferred. */
+ if((pktsize < maxpktsize) || (*nbytesptr >= nbytes)) // have we transferred 'nbytes' bytes?
+ {
+ // Save toggle value
+ pep->bmRcvToggle = ((regRd(rHRSL) & bmRCVTOGRD)) ? 1 : 0;
+ //printf("\r\n");
+ rcode = 0;
+ break;
+ } // if
+ } //while( 1 )
+ return ( rcode);
+}
+
+/* OUT transfer to arbitrary endpoint. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
+/* Handles NAK bug per Maxim Application Note 4000 for single buffer transfer */
+
+/* rcode 0 if no errors. rcode 01-0f is relayed from HRSL */
+uint8_t USB::outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* data) {
+ EpInfo *pep = NULL;
+ uint16_t nak_limit = 0;
+
+ uint8_t rcode = SetAddress(addr, ep, &pep, &nak_limit);
+
+ if(rcode)
+ return rcode;
+
+ return OutTransfer(pep, nak_limit, nbytes, data);
+}
+
+uint8_t USB::OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data) {
+ uint8_t rcode = hrSUCCESS, retry_count;
+ uint8_t *data_p = data; //local copy of the data pointer
+ uint16_t bytes_tosend, nak_count;
+ uint16_t bytes_left = nbytes;
+
+ uint8_t maxpktsize = pep->maxPktSize;
+
+ if(maxpktsize < 1 || maxpktsize > 64)
+ return USB_ERROR_INVALID_MAX_PKT_SIZE;
+
+ unsigned long timeout = millis() + USB_XFER_TIMEOUT;
+
+ regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value
+
+ while(bytes_left) {
+ retry_count = 0;
+ nak_count = 0;
+ bytes_tosend = (bytes_left >= maxpktsize) ? maxpktsize : bytes_left;
+ bytesWr(rSNDFIFO, bytes_tosend, data_p); //filling output FIFO
+ regWr(rSNDBC, bytes_tosend); //set number of bytes
+ regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet
+ while(!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ
+ regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ
+ rcode = (regRd(rHRSL) & 0x0f);
+
+ while(rcode && ((long)(millis() - timeout) < 0L)) {
+ switch(rcode) {
+ case hrNAK:
+ nak_count++;
+ if(nak_limit && (nak_count == nak_limit))
+ goto breakout;
+ //return ( rcode);
+ break;
+ case hrTIMEOUT:
+ retry_count++;
+ if(retry_count == USB_RETRY_LIMIT)
+ goto breakout;
+ //return ( rcode);
+ break;
+ case hrTOGERR:
+ // yes, we flip it wrong here so that next time it is actually correct!
+ pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 0 : 1;
+ regWr(rHCTL, (pep->bmSndToggle) ? bmSNDTOG1 : bmSNDTOG0); //set toggle value
+ break;
+ default:
+ goto breakout;
+ }//switch( rcode
+
+ /* process NAK according to Host out NAK bug */
+ regWr(rSNDBC, 0);
+ regWr(rSNDFIFO, *data_p);
+ regWr(rSNDBC, bytes_tosend);
+ regWr(rHXFR, (tokOUT | pep->epAddr)); //dispatch packet
+ while(!(regRd(rHIRQ) & bmHXFRDNIRQ)); //wait for the completion IRQ
+ regWr(rHIRQ, bmHXFRDNIRQ); //clear IRQ
+ rcode = (regRd(rHRSL) & 0x0f);
+ }//while( rcode && ....
+ bytes_left -= bytes_tosend;
+ data_p += bytes_tosend;
+ }//while( bytes_left...
+breakout:
+
+ pep->bmSndToggle = (regRd(rHRSL) & bmSNDTOGRD) ? 1 : 0; //bmSNDTOG1 : bmSNDTOG0; //update toggle
+ return ( rcode); //should be 0 in all cases
+}
+/* dispatch USB packet. Assumes peripheral address is set and relevant buffer is loaded/empty */
+/* If NAK, tries to re-send up to nak_limit times */
+/* If nak_limit == 0, do not count NAKs, exit after timeout */
+/* If bus timeout, re-sends up to USB_RETRY_LIMIT times */
+
+/* return codes 0x00-0x0f are HRSLT( 0x00 being success ), 0xff means timeout */
+uint8_t USB::dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit) {
+ unsigned long timeout = millis() + USB_XFER_TIMEOUT;
+ uint8_t tmpdata;
+ uint8_t rcode = hrSUCCESS;
+ uint8_t retry_count = 0;
+ uint16_t nak_count = 0;
+
+ while((long)(millis() - timeout) < 0L) {
+ regWr(rHXFR, (token | ep)); //launch the transfer
+ rcode = USB_ERROR_TRANSFER_TIMEOUT;
+
+ while((long)(millis() - timeout) < 0L) //wait for transfer completion
+ {
+ tmpdata = regRd(rHIRQ);
+
+ if(tmpdata & bmHXFRDNIRQ) {
+ regWr(rHIRQ, bmHXFRDNIRQ); //clear the interrupt
+ rcode = 0x00;
+ break;
+ }//if( tmpdata & bmHXFRDNIRQ
+
+ }//while ( millis() < timeout
+
+ //if (rcode != 0x00) //exit if timeout
+ // return ( rcode);
+
+ rcode = (regRd(rHRSL) & 0x0f); //analyze transfer result
+
+ switch(rcode) {
+ case hrNAK:
+ nak_count++;
+ if(nak_limit && (nak_count == nak_limit))
+ return (rcode);
+ break;
+ case hrTIMEOUT:
+ retry_count++;
+ if(retry_count == USB_RETRY_LIMIT)
+ return (rcode);
+ break;
+ default:
+ return (rcode);
+ }//switch( rcode
+
+ }//while( timeout > millis()
+ return ( rcode);
+}
+
+/* USB main task. Performs enumeration/cleanup */
+void USB::Task(void) //USB state machine
+{
+ uint8_t rcode;
+ uint8_t tmpdata;
+ static unsigned long delay = 0;
+ //USB_DEVICE_DESCRIPTOR buf;
+ bool lowspeed = false;
+
+ MAX3421E::Task();
+
+ tmpdata = getVbusState();
+
+ /* modify USB task state if Vbus changed */
+ switch(tmpdata) {
+ case SE1: //illegal state
+ usb_task_state = USB_DETACHED_SUBSTATE_ILLEGAL;
+ lowspeed = false;
+ break;
+ case SE0: //disconnected
+ if((usb_task_state & USB_STATE_MASK) != USB_STATE_DETACHED)
+ usb_task_state = USB_DETACHED_SUBSTATE_INITIALIZE;
+ lowspeed = false;
+ break;
+ case LSHOST:
+
+ lowspeed = true;
+ //intentional fallthrough
+ case FSHOST: //attached
+ if((usb_task_state & USB_STATE_MASK) == USB_STATE_DETACHED) {
+ delay = millis() + USB_SETTLE_DELAY;
+ usb_task_state = USB_ATTACHED_SUBSTATE_SETTLE;
+ }
+ break;
+ }// switch( tmpdata
+
+ for(uint8_t i = 0; i < USB_NUMDEVICES; i++)
+ if(devConfig[i])
+ rcode = devConfig[i]->Poll();
+
+ switch(usb_task_state) {
+ case USB_DETACHED_SUBSTATE_INITIALIZE:
+ init();
+
+ for(uint8_t i = 0; i < USB_NUMDEVICES; i++)
+ if(devConfig[i])
+ rcode = devConfig[i]->Release();
+
+ usb_task_state = USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE;
+ break;
+ case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE: //just sit here
+ break;
+ case USB_DETACHED_SUBSTATE_ILLEGAL: //just sit here
+ break;
+ case USB_ATTACHED_SUBSTATE_SETTLE: //settle time for just attached device
+ if((long)(millis() - delay) >= 0L)
+ usb_task_state = USB_ATTACHED_SUBSTATE_RESET_DEVICE;
+ else break; // don't fall through
+ case USB_ATTACHED_SUBSTATE_RESET_DEVICE:
+ regWr(rHCTL, bmBUSRST); //issue bus reset
+ usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE;
+ break;
+ case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE:
+ if((regRd(rHCTL) & bmBUSRST) == 0) {
+ tmpdata = regRd(rMODE) | bmSOFKAENAB; //start SOF generation
+ regWr(rMODE, tmpdata);
+ usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_SOF;
+ //delay = millis() + 20; //20ms wait after reset per USB spec
+ }
+ break;
+ case USB_ATTACHED_SUBSTATE_WAIT_SOF: //todo: change check order
+ if(regRd(rHIRQ) & bmFRAMEIRQ) {
+ //when first SOF received _and_ 20ms has passed we can continue
+ /*
+ if (delay < millis()) //20ms passed
+ usb_task_state = USB_STATE_CONFIGURING;
+ */
+ usb_task_state = USB_ATTACHED_SUBSTATE_WAIT_RESET;
+ delay = millis() + 20;
+ }
+ break;
+ case USB_ATTACHED_SUBSTATE_WAIT_RESET:
+ if((long)(millis() - delay) >= 0L) usb_task_state = USB_STATE_CONFIGURING;
+ else break; // don't fall through
+ case USB_STATE_CONFIGURING:
+
+ //Serial.print("\r\nConf.LS: ");
+ //Serial.println(lowspeed, HEX);
+
+ rcode = Configuring(0, 0, lowspeed);
+
+ if(rcode) {
+ if(rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE) {
+ usb_error = rcode;
+ usb_task_state = USB_STATE_ERROR;
+ }
+ } else
+ usb_task_state = USB_STATE_RUNNING;
+ break;
+ case USB_STATE_RUNNING:
+ break;
+ case USB_STATE_ERROR:
+ //MAX3421E::Init();
+ break;
+ } // switch( usb_task_state )
+}
+
+uint8_t USB::DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed) {
+ //uint8_t buf[12];
+ uint8_t rcode;
+ UsbDevice *p0 = NULL, *p = NULL;
+
+ // Get pointer to pseudo device with address 0 assigned
+ p0 = addrPool.GetUsbDevicePtr(0);
+
+ if(!p0)
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+ if(!p0->epinfo)
+ return USB_ERROR_EPINFO_IS_NULL;
+
+ p0->lowspeed = (lowspeed) ? true : false;
+
+ // Allocate new address according to device class
+ uint8_t bAddress = addrPool.AllocAddress(parent, false, port);
+
+ if(!bAddress)
+ return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
+
+ p = addrPool.GetUsbDevicePtr(bAddress);
+
+ if(!p)
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+ p->lowspeed = lowspeed;
+
+ // Assign new address to the device
+ rcode = setAddr(0, 0, bAddress);
+
+ if(rcode) {
+ addrPool.FreeAddress(bAddress);
+ bAddress = 0;
+ return rcode;
+ }
+ return 0;
+};
+
+uint8_t USB::AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed) {
+ //printf("AttemptConfig: parent = %i, port = %i\r\n", parent, port);
+ uint8_t retries = 0;
+
+again:
+ uint8_t rcode = devConfig[driver]->ConfigureDevice(parent, port, lowspeed);
+ if(rcode == USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET) {
+ if(parent == 0) {
+ // Send a bus reset on the root interface.
+ regWr(rHCTL, bmBUSRST); //issue bus reset
+ delay(102); // delay 102ms, compensate for clock inaccuracy.
+ } else {
+ // reset parent port
+ devConfig[parent]->ResetHubPort(port);
+ }
+ } else if(rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works
+ delay(100);
+ retries++;
+ goto again;
+ } else if(rcode)
+ return rcode;
+
+ rcode = devConfig[driver]->Init(parent, port, lowspeed);
+ if(rcode == hrJERR && retries < 3) { // Some devices returns this when plugged in - trying to initialize the device again usually works
+ delay(100);
+ retries++;
+ goto again;
+ }
+ if(rcode) {
+ // Issue a bus reset, because the device may be in a limbo state
+ if(parent == 0) {
+ // Send a bus reset on the root interface.
+ regWr(rHCTL, bmBUSRST); //issue bus reset
+ delay(102); // delay 102ms, compensate for clock inaccuracy.
+ } else {
+ // reset parent port
+ devConfig[parent]->ResetHubPort(port);
+ }
+ }
+ return rcode;
+}
+
+/*
+ * This is broken. We need to enumerate differently.
+ * It causes major problems with several devices if detected in an unexpected order.
+ *
+ *
+ * Oleg - I wouldn't do anything before the newly connected device is considered sane.
+ * i.e.(delays are not indicated for brevity):
+ * 1. reset
+ * 2. GetDevDescr();
+ * 3a. If ACK, continue with allocating address, addressing, etc.
+ * 3b. Else reset again, count resets, stop at some number (5?).
+ * 4. When max.number of resets is reached, toggle power/fail
+ * If desired, this could be modified by performing two resets with GetDevDescr() in the middle - however, from my experience, if a device answers to GDD()
+ * it doesn't need to be reset again
+ * New steps proposal:
+ * 1: get address pool instance. exit on fail
+ * 2: pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf). exit on fail.
+ * 3: bus reset, 100ms delay
+ * 4: set address
+ * 5: pUsb->setEpInfoEntry(bAddress, 1, epInfo), exit on fail
+ * 6: while (configurations) {
+ * for(each configuration) {
+ * for (each driver) {
+ * 6a: Ask device if it likes configuration. Returns 0 on OK.
+ * If successful, the driver configured device.
+ * The driver now owns the endpoints, and takes over managing them.
+ * The following will need codes:
+ * Everything went well, instance consumed, exit with success.
+ * Instance already in use, ignore it, try next driver.
+ * Not a supported device, ignore it, try next driver.
+ * Not a supported configuration for this device, ignore it, try next driver.
+ * Could not configure device, fatal, exit with fail.
+ * }
+ * }
+ * }
+ * 7: for(each driver) {
+ * 7a: Ask device if it knows this VID/PID. Acts exactly like 6a, but using VID/PID
+ * 8: if we get here, no driver likes the device plugged in, so exit failure.
+ *
+ */
+uint8_t USB::Configuring(uint8_t parent, uint8_t port, bool lowspeed) {
+ //uint8_t bAddress = 0;
+ //printf("Configuring: parent = %i, port = %i\r\n", parent, port);
+ uint8_t devConfigIndex;
+ uint8_t rcode = 0;
+ uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
+ USB_DEVICE_DESCRIPTOR *udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR *>(buf);
+ UsbDevice *p = NULL;
+ EpInfo *oldep_ptr = NULL;
+ EpInfo epInfo;
+
+ epInfo.epAddr = 0;
+ epInfo.maxPktSize = 8;
+ epInfo.epAttribs = 0;
+ epInfo.bmNakPower = USB_NAK_MAX_POWER;
+
+ //delay(2000);
+ AddressPool &addrPool = GetAddressPool();
+ // Get pointer to pseudo device with address 0 assigned
+ p = addrPool.GetUsbDevicePtr(0);
+ if(!p) {
+ //printf("Configuring error: USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL\r\n");
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+ }
+
+ // Save old pointer to EP_RECORD of address 0
+ oldep_ptr = p->epinfo;
+
+ // Temporary assign new pointer to epInfo to p->epinfo in order to
+ // avoid toggle inconsistence
+
+ p->epinfo = &epInfo;
+
+ p->lowspeed = lowspeed;
+ // Get device descriptor
+ rcode = getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);
+
+ // Restore p->epinfo
+ p->epinfo = oldep_ptr;
+
+ if(rcode) {
+ //printf("Configuring error: Can't get USB_DEVICE_DESCRIPTOR\r\n");
+ return rcode;
+ }
+
+ // to-do?
+ // Allocate new address according to device class
+ //bAddress = addrPool.AllocAddress(parent, false, port);
+
+ uint16_t vid = udd->idVendor;
+ uint16_t pid = udd->idProduct;
+ uint8_t klass = udd->bDeviceClass;
+ uint8_t subklass = udd->bDeviceSubClass;
+ // Attempt to configure if VID/PID or device class matches with a driver
+ // Qualify with subclass too.
+ //
+ // VID/PID & class tests default to false for drivers not yet ported
+ // subclass defaults to true, so you don't have to define it if you don't have to.
+ //
+ for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) {
+ if(!devConfig[devConfigIndex]) continue; // no driver
+ if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed
+ if(devConfig[devConfigIndex]->DEVSUBCLASSOK(subklass) && (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass))) {
+ rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);
+ if(rcode != USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED)
+ break;
+ }
+ }
+
+ if(devConfigIndex < USB_NUMDEVICES) {
+ return rcode;
+ }
+
+
+ // blindly attempt to configure
+ for(devConfigIndex = 0; devConfigIndex < USB_NUMDEVICES; devConfigIndex++) {
+ if(!devConfig[devConfigIndex]) continue;
+ if(devConfig[devConfigIndex]->GetAddress()) continue; // consumed
+ if(devConfig[devConfigIndex]->DEVSUBCLASSOK(subklass) && (devConfig[devConfigIndex]->VIDPIDOK(vid, pid) || devConfig[devConfigIndex]->DEVCLASSOK(klass))) continue; // If this is true it means it must have returned USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED above
+ rcode = AttemptConfig(devConfigIndex, parent, port, lowspeed);
+
+ //printf("ERROR ENUMERATING %2.2x\r\n", rcode);
+ if(!(rcode == USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED || rcode == USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE)) {
+ // in case of an error dev_index should be reset to 0
+ // in order to start from the very beginning the
+ // next time the program gets here
+ //if (rcode != USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE)
+ // devConfigIndex = 0;
+ return rcode;
+ }
+ }
+ // if we get here that means that the device class is not supported by any of registered classes
+ rcode = DefaultAddressing(parent, port, lowspeed);
+
+ return rcode;
+}
+
+uint8_t USB::ReleaseDevice(uint8_t addr) {
+ if(!addr)
+ return 0;
+
+ for(uint8_t i = 0; i < USB_NUMDEVICES; i++) {
+ if(!devConfig[i]) continue;
+ if(devConfig[i]->GetAddress() == addr)
+ return devConfig[i]->Release();
+ }
+ return 0;
+}
+
+#if 1 //!defined(USB_METHODS_INLINE)
+//get device descriptor
+
+uint8_t USB::getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr) {
+ return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, nbytes, dataptr, NULL));
+}
+//get configuration descriptor
+
+uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr) {
+ return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, nbytes, dataptr, NULL));
+}
+
+/* Requests Configuration Descriptor. Sends two Get Conf Descr requests. The first one gets the total length of all descriptors, then the second one requests this
+ total length. The length of the first request can be shorter ( 4 bytes ), however, there are devices which won't work unless this length is set to 9 */
+uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser *p) {
+ const uint8_t bufSize = 64;
+ uint8_t buf[bufSize];
+ USB_CONFIGURATION_DESCRIPTOR *ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR *>(buf);
+
+ uint8_t ret = getConfDescr(addr, ep, 9, conf, buf);
+
+ if(ret)
+ return ret;
+
+ uint16_t total = ucd->wTotalLength;
+
+ //USBTRACE2("\r\ntotal conf.size:", total);
+
+ return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, total, bufSize, buf, p));
+}
+
+//get string descriptor
+
+uint8_t USB::getStrDescr(uint8_t addr, uint8_t ep, uint16_t ns, uint8_t index, uint16_t langid, uint8_t* dataptr) {
+ return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, ns, ns, dataptr, NULL));
+}
+//set address
+
+uint8_t USB::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr) {
+ uint8_t rcode = ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL);
+ //delay(2); //per USB 2.0 sect.9.2.6.3
+ delay(300); // Older spec says you should wait at least 200ms
+ return rcode;
+ //return ( ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL));
+}
+//set configuration
+
+uint8_t USB::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value) {
+ return ( ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, 0x0000, NULL, NULL));
+}
+
+#endif // defined(USB_METHODS_INLINE)
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Usb.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Usb.h
new file mode 100644
index 000000000..47bd626cc
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Usb.h
@@ -0,0 +1,41 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+/* USB functions */
+#ifndef _usb_h_
+#define _usb_h_
+
+// WARNING: Do not change the order of includes, or stuff will break!
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+
+// None of these should ever be included by a driver, or a user's sketch.
+#include "settings.h"
+#include "printhex.h"
+#include "message.h"
+#include "hexdump.h"
+#include "sink_parser.h"
+#include "max3421e.h"
+#include "address.h"
+#include "avrpins.h"
+#include "usb_ch9.h"
+#include "usbhost.h"
+#include "UsbCore.h"
+#include "parsetools.h"
+#include "confdescparser.h"
+
+#endif //_usb_h_
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/UsbCore.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/UsbCore.h
new file mode 100644
index 000000000..5c6c77101
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/UsbCore.h
@@ -0,0 +1,298 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+
+#if !defined(_usb_h_) || defined(USBCORE_H)
+#error "Never include UsbCore.h directly; include Usb.h instead"
+#else
+#define USBCORE_H
+
+// Not used anymore? If anyone uses this, please let us know so that this may be
+// moved to the proper place, settings.h.
+//#define USB_METHODS_INLINE
+
+/* shield pins. First parameter - SS pin, second parameter - INT pin */
+#ifdef BOARD_BLACK_WIDDOW
+typedef MAX3421e<P6, P3> MAX3421E; // Black Widow
+#elif defined(CORE_TEENSY) && (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__))
+#if EXT_RAM
+typedef MAX3421e<P20, P7> MAX3421E; // Teensy++ 2.0 with XMEM2
+#else
+typedef MAX3421e<P9, P8> MAX3421E; // Teensy++ 1.0 and 2.0
+#endif
+#elif defined(BOARD_MEGA_ADK)
+typedef MAX3421e<P53, P54> MAX3421E; // Arduino Mega ADK
+#elif defined(ARDUINO_AVR_BALANDUINO)
+typedef MAX3421e<P20, P19> MAX3421E; // Balanduino
+#elif defined(__ARDUINO_X86__) && PLATFORM_ID == 0x06
+typedef MAX3421e<P3, P2> MAX3421E; // The Intel Galileo supports much faster read and write speed at pin 2 and 3
+#else
+typedef MAX3421e<P10, P9> MAX3421E; // Official Arduinos (UNO, Duemilanove, Mega, 2560, Leonardo, Due etc.), Intel Edison, Intel Galileo 2 or Teensy 2.0 and 3.0
+#endif
+
+/* Common setup data constant combinations */
+#define bmREQ_GET_DESCR USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE //get descriptor request type
+#define bmREQ_SET USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_DEVICE //set request type for all but 'set feature' and 'set interface'
+#define bmREQ_CL_GET_INTF USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE //get interface request type
+
+// D7 data transfer direction (0 - host-to-device, 1 - device-to-host)
+// D6-5 Type (0- standard, 1 - class, 2 - vendor, 3 - reserved)
+// D4-0 Recipient (0 - device, 1 - interface, 2 - endpoint, 3 - other, 4..31 - reserved)
+
+// USB Device Classes
+#define USB_CLASS_USE_CLASS_INFO 0x00 // Use Class Info in the Interface Descriptors
+#define USB_CLASS_AUDIO 0x01 // Audio
+#define USB_CLASS_COM_AND_CDC_CTRL 0x02 // Communications and CDC Control
+#define USB_CLASS_HID 0x03 // HID
+#define USB_CLASS_PHYSICAL 0x05 // Physical
+#define USB_CLASS_IMAGE 0x06 // Image
+#define USB_CLASS_PRINTER 0x07 // Printer
+#define USB_CLASS_MASS_STORAGE 0x08 // Mass Storage
+#define USB_CLASS_HUB 0x09 // Hub
+#define USB_CLASS_CDC_DATA 0x0a // CDC-Data
+#define USB_CLASS_SMART_CARD 0x0b // Smart-Card
+#define USB_CLASS_CONTENT_SECURITY 0x0d // Content Security
+#define USB_CLASS_VIDEO 0x0e // Video
+#define USB_CLASS_PERSONAL_HEALTH 0x0f // Personal Healthcare
+#define USB_CLASS_DIAGNOSTIC_DEVICE 0xdc // Diagnostic Device
+#define USB_CLASS_WIRELESS_CTRL 0xe0 // Wireless Controller
+#define USB_CLASS_MISC 0xef // Miscellaneous
+#define USB_CLASS_APP_SPECIFIC 0xfe // Application Specific
+#define USB_CLASS_VENDOR_SPECIFIC 0xff // Vendor Specific
+
+// Additional Error Codes
+#define USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED 0xD1
+#define USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE 0xD2
+#define USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS 0xD3
+#define USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL 0xD4
+#define USB_ERROR_HUB_ADDRESS_OVERFLOW 0xD5
+#define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL 0xD6
+#define USB_ERROR_EPINFO_IS_NULL 0xD7
+#define USB_ERROR_INVALID_ARGUMENT 0xD8
+#define USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE 0xD9
+#define USB_ERROR_INVALID_MAX_PKT_SIZE 0xDA
+#define USB_ERROR_EP_NOT_FOUND_IN_TBL 0xDB
+#define USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET 0xE0
+#define USB_ERROR_FailGetDevDescr 0xE1
+#define USB_ERROR_FailSetDevTblEntry 0xE2
+#define USB_ERROR_FailGetConfDescr 0xE3
+#define USB_ERROR_TRANSFER_TIMEOUT 0xFF
+
+#define USB_XFER_TIMEOUT 5000 // (5000) USB transfer timeout in milliseconds, per section 9.2.6.1 of USB 2.0 spec
+//#define USB_NAK_LIMIT 32000 // NAK limit for a transfer. 0 means NAKs are not counted
+#define USB_RETRY_LIMIT 3 // 3 retry limit for a transfer
+#define USB_SETTLE_DELAY 200 // settle delay in milliseconds
+
+#define USB_NUMDEVICES 16 //number of USB devices
+//#define HUB_MAX_HUBS 7 // maximum number of hubs that can be attached to the host controller
+#define HUB_PORT_RESET_DELAY 20 // hub port reset delay 10 ms recomended, can be up to 20 ms
+
+/* USB state machine states */
+#define USB_STATE_MASK 0xf0
+
+#define USB_STATE_DETACHED 0x10
+#define USB_DETACHED_SUBSTATE_INITIALIZE 0x11
+#define USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE 0x12
+#define USB_DETACHED_SUBSTATE_ILLEGAL 0x13
+#define USB_ATTACHED_SUBSTATE_SETTLE 0x20
+#define USB_ATTACHED_SUBSTATE_RESET_DEVICE 0x30
+#define USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE 0x40
+#define USB_ATTACHED_SUBSTATE_WAIT_SOF 0x50
+#define USB_ATTACHED_SUBSTATE_WAIT_RESET 0x51
+#define USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE 0x60
+#define USB_STATE_ADDRESSING 0x70
+#define USB_STATE_CONFIGURING 0x80
+#define USB_STATE_RUNNING 0x90
+#define USB_STATE_ERROR 0xa0
+
+class USBDeviceConfig {
+public:
+
+ virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed) {
+ return 0;
+ }
+
+ virtual uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {
+ return 0;
+ }
+
+ virtual uint8_t Release() {
+ return 0;
+ }
+
+ virtual uint8_t Poll() {
+ return 0;
+ }
+
+ virtual uint8_t GetAddress() {
+ return 0;
+ }
+
+ virtual void ResetHubPort(uint8_t port) {
+ return;
+ } // Note used for hubs only!
+
+ virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {
+ return false;
+ }
+
+ virtual bool DEVCLASSOK(uint8_t klass) {
+ return false;
+ }
+
+ virtual bool DEVSUBCLASSOK(uint8_t subklass) {
+ return true;
+ }
+
+};
+
+/* USB Setup Packet Structure */
+typedef struct {
+
+ union { // offset description
+ uint8_t bmRequestType; // 0 Bit-map of request type
+
+ struct {
+ uint8_t recipient : 5; // Recipient of the request
+ uint8_t type : 2; // Type of request
+ uint8_t direction : 1; // Direction of data X-fer
+ } __attribute__((packed));
+ } ReqType_u;
+ uint8_t bRequest; // 1 Request
+
+ union {
+ uint16_t wValue; // 2 Depends on bRequest
+
+ struct {
+ uint8_t wValueLo;
+ uint8_t wValueHi;
+ } __attribute__((packed));
+ } wVal_u;
+ uint16_t wIndex; // 4 Depends on bRequest
+ uint16_t wLength; // 6 Depends on bRequest
+} __attribute__((packed)) SETUP_PKT, *PSETUP_PKT;
+
+
+
+// Base class for incoming data parser
+
+class USBReadParser {
+public:
+ virtual void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) = 0;
+};
+
+class USB : public MAX3421E {
+ AddressPoolImpl<USB_NUMDEVICES> addrPool;
+ USBDeviceConfig* devConfig[USB_NUMDEVICES];
+ uint8_t bmHubPre;
+
+public:
+ USB(void);
+
+ void SetHubPreMask() {
+ bmHubPre |= bmHUBPRE;
+ };
+
+ void ResetHubPreMask() {
+ bmHubPre &= (~bmHUBPRE);
+ };
+
+ AddressPool& GetAddressPool() {
+ return (AddressPool&)addrPool;
+ };
+
+ uint8_t RegisterDeviceClass(USBDeviceConfig *pdev) {
+ for(uint8_t i = 0; i < USB_NUMDEVICES; i++) {
+ if(!devConfig[i]) {
+ devConfig[i] = pdev;
+ return 0;
+ }
+ }
+ return USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS;
+ };
+
+ void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) {
+ addrPool.ForEachUsbDevice(pfunc);
+ };
+ uint8_t getUsbTaskState(void);
+ void setUsbTaskState(uint8_t state);
+
+ EpInfo* getEpInfoEntry(uint8_t addr, uint8_t ep);
+ uint8_t setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo* eprecord_ptr);
+
+ /* Control requests */
+ uint8_t getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr);
+ uint8_t getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr);
+
+ uint8_t getConfDescr(uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser *p);
+
+ uint8_t getStrDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t index, uint16_t langid, uint8_t* dataptr);
+ uint8_t setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr);
+ uint8_t setConf(uint8_t addr, uint8_t ep, uint8_t conf_value);
+ /**/
+ uint8_t ctrlData(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr, bool direction);
+ uint8_t ctrlStatus(uint8_t ep, bool direction, uint16_t nak_limit);
+ uint8_t inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t* data);
+ uint8_t outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* data);
+ uint8_t dispatchPkt(uint8_t token, uint8_t ep, uint16_t nak_limit);
+
+ void Task(void);
+
+ uint8_t DefaultAddressing(uint8_t parent, uint8_t port, bool lowspeed);
+ uint8_t Configuring(uint8_t parent, uint8_t port, bool lowspeed);
+ uint8_t ReleaseDevice(uint8_t addr);
+
+ uint8_t ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi,
+ uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t* dataptr, USBReadParser *p);
+
+private:
+ void init();
+ uint8_t SetAddress(uint8_t addr, uint8_t ep, EpInfo **ppep, uint16_t *nak_limit);
+ uint8_t OutTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t nbytes, uint8_t *data);
+ uint8_t InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, uint8_t *data);
+ uint8_t AttemptConfig(uint8_t driver, uint8_t parent, uint8_t port, bool lowspeed);
+};
+
+#if 0 //defined(USB_METHODS_INLINE)
+//get device descriptor
+
+inline uint8_t USB::getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr) {
+ return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, dataptr));
+}
+//get configuration descriptor
+
+inline uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr) {
+ return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, dataptr));
+}
+//get string descriptor
+
+inline uint8_t USB::getStrDescr(uint8_t addr, uint8_t ep, uint16_t nuint8_ts, uint8_t index, uint16_t langid, uint8_t* dataptr) {
+ return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nuint8_ts, dataptr));
+}
+//set address
+
+inline uint8_t USB::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr) {
+ return ( ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, NULL));
+}
+//set configuration
+
+inline uint8_t USB::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value) {
+ return ( ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, NULL));
+}
+
+#endif // defined(USB_METHODS_INLINE)
+
+#endif /* USBCORE_H */
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Wii.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Wii.cpp
new file mode 100755
index 000000000..4bbf4c91c
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Wii.cpp
@@ -0,0 +1,1268 @@
+/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
+
+ This software may be distributed and modified under the terms of the GNU
+ General Public License version 2 (GPL2) as published by the Free Software
+ Foundation and appearing in the file GPL2.TXT included in the packaging of
+ this file. Please note that GPL2 Section 2[b] requires that all works based
+ on this software must also be made publicly available under the terms of
+ the GPL2 ("Copyleft").
+
+ Contact information
+ -------------------
+
+ Kristian Lauszus, TKJ Electronics
+ Web : http://www.tkjelectronics.com
+ e-mail : kristianl@tkjelectronics.com
+
+ IR camera support added by Allan Glover (adglover9.81@gmail.com) and Kristian Lauszus
+ */
+
+#include "Wii.h"
+// To enable serial debugging see "settings.h"
+//#define EXTRADEBUG // Uncomment to get even more debugging data
+//#define PRINTREPORT // Uncomment to print the report send by the Wii controllers
+
+const uint8_t WII_LEDS[] PROGMEM = {
+ 0x00, // OFF
+ 0x10, // LED1
+ 0x20, // LED2
+ 0x40, // LED3
+ 0x80, // LED4
+
+ 0x90, // LED5
+ 0xA0, // LED6
+ 0xC0, // LED7
+ 0xD0, // LED8
+ 0xE0, // LED9
+ 0xF0, // LED10
+};
+
+const uint32_t WII_BUTTONS[] PROGMEM = {
+ 0x00008, // UP
+ 0x00002, // RIGHT
+ 0x00004, // DOWN
+ 0x00001, // LEFT
+
+ 0, // Skip
+ 0x00010, // PLUS
+ 0x00100, // TWO
+ 0x00200, // ONE
+
+ 0x01000, // MINUS
+ 0x08000, // HOME
+ 0x10000, // Z
+ 0x20000, // C
+
+ 0x00400, // B
+ 0x00800, // A
+};
+const uint32_t WII_PROCONTROLLER_BUTTONS[] PROGMEM = {
+ 0x00100, // UP
+ 0x00080, // RIGHT
+ 0x00040, // DOWN
+ 0x00200, // LEFT
+
+ 0, // Skip
+ 0x00004, // PLUS
+ 0x20000, // L3
+ 0x10000, // R3
+
+ 0x00010, // MINUS
+ 0x00008, // HOME
+ 0, 0, // Skip
+
+ 0x04000, // B
+ 0x01000, // A
+ 0x00800, // X
+ 0x02000, // Y
+
+ 0x00020, // L
+ 0x00002, // R
+ 0x08000, // ZL
+ 0x00400, // ZR
+};
+
+WII::WII(BTD *p, bool pair) :
+BluetoothService(p) // Pointer to USB class instance - mandatory
+{
+ pBtd->pairWithWii = pair;
+
+ HIDBuffer[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
+
+ /* Set device cid for the control and intterrupt channelse - LSB */
+ control_dcid[0] = 0x60; // 0x0060
+ control_dcid[1] = 0x00;
+ interrupt_dcid[0] = 0x61; // 0x0061
+ interrupt_dcid[1] = 0x00;
+
+ Reset();
+}
+
+void WII::Reset() {
+ wiimoteConnected = false;
+ nunchuckConnected = false;
+ motionPlusConnected = false;
+ activateNunchuck = false;
+ motionValuesReset = false;
+ activeConnection = false;
+ motionPlusInside = false;
+ pBtd->wiiUProController = false;
+ wiiUProControllerConnected = false;
+ wiiBalanceBoardConnected = false;
+ l2cap_event_flag = 0; // Reset flags
+ l2cap_state = L2CAP_WAIT;
+}
+
+void WII::disconnect() { // Use this void to disconnect any of the controllers
+ if(!motionPlusInside) { // The old Wiimote needs a delay after the first command or it will automatically reconnect
+ if(motionPlusConnected) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nDeactivating Motion Plus"), 0x80);
+#endif
+ initExtension1(); // This will disable the Motion Plus extension
+ }
+ timer = millis() + 1000; // We have to wait for the message before the rest of the channels can be deactivated
+ } else
+ timer = millis(); // Don't wait
+ // First the HID interrupt channel has to be disconnected, then the HID control channel and finally the HCI connection
+ pBtd->l2cap_disconnection_request(hci_handle, ++identifier, interrupt_scid, interrupt_dcid);
+ Reset();
+ l2cap_state = L2CAP_INTERRUPT_DISCONNECT;
+}
+
+void WII::ACLData(uint8_t* l2capinbuf) {
+ if(!pBtd->l2capConnectionClaimed && pBtd->incomingWii && !wiimoteConnected && !activeConnection) {
+ if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
+ if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) {
+ motionPlusInside = pBtd->motionPlusInside;
+ pBtd->incomingWii = false;
+ pBtd->l2capConnectionClaimed = true; // Claim that the incoming connection belongs to this service
+ activeConnection = true;
+ hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection
+ l2cap_state = L2CAP_WAIT;
+ }
+ }
+ }
+
+ if(checkHciHandle(l2capinbuf, hci_handle)) { // acl_handle_ok
+ if((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { // l2cap_control - Channel ID for ACL-U
+ if(l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[17], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[16], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
+#endif
+ } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_RESPONSE) {
+ if(((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) && ((l2capinbuf[18] | (l2capinbuf[19] << 8)) == SUCCESSFUL)) { // Success
+ if(l2capinbuf[14] == control_dcid[0] && l2capinbuf[15] == control_dcid[1]) {
+ //Notify(PSTR("\r\nHID Control Connection Complete"), 0x80);
+ identifier = l2capinbuf[9];
+ control_scid[0] = l2capinbuf[12];
+ control_scid[1] = l2capinbuf[13];
+ l2cap_set_flag(L2CAP_FLAG_CONTROL_CONNECTED);
+ } else if(l2capinbuf[14] == interrupt_dcid[0] && l2capinbuf[15] == interrupt_dcid[1]) {
+ //Notify(PSTR("\r\nHID Interrupt Connection Complete"), 0x80);
+ identifier = l2capinbuf[9];
+ interrupt_scid[0] = l2capinbuf[12];
+ interrupt_scid[1] = l2capinbuf[13];
+ l2cap_set_flag(L2CAP_FLAG_INTERRUPT_CONNECTED);
+ }
+ }
+ } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
+#ifdef EXTRADEBUG
+ Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);
+ Notify(PSTR(" SCID: "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);
+ Notify(PSTR(" "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
+ Notify(PSTR(" Identifier: "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[9], 0x80);
+#endif
+ if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) {
+ identifier = l2capinbuf[9];
+ control_scid[0] = l2capinbuf[14];
+ control_scid[1] = l2capinbuf[15];
+ l2cap_set_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST);
+ } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM) {
+ identifier = l2capinbuf[9];
+ interrupt_scid[0] = l2capinbuf[14];
+ interrupt_scid[1] = l2capinbuf[15];
+ l2cap_set_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST);
+ }
+ } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) {
+ if((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success
+ if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
+ //Notify(PSTR("\r\nHID Control Configuration Complete"), 0x80);
+ identifier = l2capinbuf[9];
+ l2cap_set_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS);
+ } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
+ //Notify(PSTR("\r\nHID Interrupt Configuration Complete"), 0x80);
+ identifier = l2capinbuf[9];
+ l2cap_set_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS);
+ }
+ }
+ } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) {
+ if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
+ //Notify(PSTR("\r\nHID Control Configuration Request"), 0x80);
+ pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], control_scid);
+ } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
+ //Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80);
+ pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], interrupt_scid);
+ }
+ } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) {
+ if(l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nDisconnect Request: Control Channel"), 0x80);
+#endif
+ identifier = l2capinbuf[9];
+ pBtd->l2cap_disconnection_response(hci_handle, identifier, control_dcid, control_scid);
+ Reset();
+ } else if(l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nDisconnect Request: Interrupt Channel"), 0x80);
+#endif
+ identifier = l2capinbuf[9];
+ pBtd->l2cap_disconnection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid);
+ Reset();
+ }
+ } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) {
+ if(l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) {
+ //Notify(PSTR("\r\nDisconnect Response: Control Channel"), 0x80);
+ identifier = l2capinbuf[9];
+ l2cap_set_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE);
+ } else if(l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) {
+ //Notify(PSTR("\r\nDisconnect Response: Interrupt Channel"), 0x80);
+ identifier = l2capinbuf[9];
+ l2cap_set_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE);
+ }
+ }
+#ifdef EXTRADEBUG
+ else {
+ identifier = l2capinbuf[9];
+ Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[8], 0x80);
+ }
+#endif
+ } else if(l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt
+ //Notify(PSTR("\r\nL2CAP Interrupt"), 0x80);
+ if(l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT
+ if((l2capinbuf[9] >= 0x20 && l2capinbuf[9] <= 0x22) || (l2capinbuf[9] >= 0x30 && l2capinbuf[9] <= 0x37) || l2capinbuf[9] == 0x3e || l2capinbuf[9] == 0x3f) { // These reports include the buttons
+ if((l2capinbuf[9] >= 0x20 && l2capinbuf[9] <= 0x22) || l2capinbuf[9] == 0x31 || l2capinbuf[9] == 0x33) // These reports have no extensions bytes
+ ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8));
+ else if(wiiUProControllerConnected)
+ ButtonState = (uint32_t)(((~l2capinbuf[23]) & 0xFE) | ((uint16_t)(~l2capinbuf[24]) << 8) | ((uint32_t)((~l2capinbuf[25]) & 0x03) << 16));
+ else if(motionPlusConnected) {
+ if(l2capinbuf[20] & 0x02) // Only update the Wiimote buttons, since the extension bytes are from the Motion Plus
+ ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)(ButtonState & 0xFFFF0000)));
+ else if(nunchuckConnected) // Update if it's a report from the Nunchuck
+ ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)((~l2capinbuf[20]) & 0x0C) << 14));
+ //else if(classicControllerConnected) // Update if it's a report from the Classic Controller
+ } else if(nunchuckConnected) // The Nunchuck is directly connected
+ ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8) | ((uint32_t)((~l2capinbuf[20]) & 0x03) << 16));
+ //else if(classicControllerConnected) // The Classic Controller is directly connected
+ else if(!unknownExtensionConnected)
+ ButtonState = (uint32_t)((l2capinbuf[10] & 0x1F) | ((uint16_t)(l2capinbuf[11] & 0x9F) << 8));
+#ifdef PRINTREPORT
+ Notify(PSTR("ButtonState: "), 0x80);
+ D_PrintHex<uint32_t > (ButtonState, 0x80);
+ Notify(PSTR("\r\n"), 0x80);
+#endif
+ if(ButtonState != OldButtonState) {
+ ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable
+ OldButtonState = ButtonState;
+ }
+ }
+ if(l2capinbuf[9] == 0x31 || l2capinbuf[9] == 0x33 || l2capinbuf[9] == 0x35 || l2capinbuf[9] == 0x37) { // Read the accelerometer
+ accXwiimote = ((l2capinbuf[12] << 2) | (l2capinbuf[10] & 0x60 >> 5)) - 500;
+ accYwiimote = ((l2capinbuf[13] << 2) | (l2capinbuf[11] & 0x20 >> 4)) - 500;
+ accZwiimote = ((l2capinbuf[14] << 2) | (l2capinbuf[11] & 0x40 >> 5)) - 500;
+ }
+ switch(l2capinbuf[9]) {
+ case 0x20: // Status Information - (a1) 20 BB BB LF 00 00 VV
+#ifdef EXTRADEBUG
+ Notify(PSTR("\r\nStatus report was received"), 0x80);
+#endif
+ wiiState = l2capinbuf[12]; // (0x01: Battery is nearly empty), (0x02: An Extension Controller is connected), (0x04: Speaker enabled), (0x08: IR enabled), (0x10: LED1, 0x20: LED2, 0x40: LED3, 0x80: LED4)
+ batteryLevel = l2capinbuf[15]; // Update battery level
+
+ if(!checkBatteryLevel) { // If this is true it means that the user must have called getBatteryLevel()
+ if(l2capinbuf[12] & 0x02) { // Check if a extension is connected
+#ifdef DEBUG_USB_HOST
+ if(!unknownExtensionConnected)
+ Notify(PSTR("\r\nExtension connected"), 0x80);
+#endif
+ unknownExtensionConnected = true;
+#ifdef WIICAMERA
+ if(!isIRCameraEnabled()) // Don't activate the Motion Plus if we are trying to initialize the IR camera
+#endif
+ setReportMode(false, 0x35); // Also read the extension
+ } else {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nExtension disconnected"), 0x80);
+#endif
+ if(motionPlusConnected) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR(" - from Motion Plus"), 0x80);
+#endif
+ wii_clear_flag(WII_FLAG_NUNCHUCK_CONNECTED);
+ if(!activateNunchuck) // If it's already trying to initialize the Nunchuck don't set it to false
+ nunchuckConnected = false;
+ //else if(classicControllerConnected)
+ } else if(nunchuckConnected) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR(" - Nunchuck"), 0x80);
+#endif
+ nunchuckConnected = false; // It must be the Nunchuck controller then
+ wii_clear_flag(WII_FLAG_NUNCHUCK_CONNECTED);
+ onInit();
+ setReportMode(false, 0x31); // If there is no extension connected we will read the buttons and accelerometer
+ } else
+ setReportMode(false, 0x31); // If there is no extension connected we will read the buttons and accelerometer
+ }
+ }
+ else {
+#ifdef EXTRADEBUG
+ Notify(PSTR("\r\nChecking battery level"), 0x80);
+#endif
+ checkBatteryLevel = false; // Check for extensions by default
+ }
+#ifdef DEBUG_USB_HOST
+ if(l2capinbuf[12] & 0x01)
+ Notify(PSTR("\r\nWARNING: Battery is nearly empty"), 0x80);
+#endif
+
+ break;
+ case 0x21: // Read Memory Data
+ if((l2capinbuf[12] & 0x0F) == 0) { // No error
+ uint8_t reportLength = (l2capinbuf[12] >> 4) + 1; // // Bit 4-7 is the length - 1
+ // See: http://wiibrew.org/wiki/Wiimote/Extension_Controllers
+ if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x00 && l2capinbuf[20] == 0x00) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nNunchuck connected"), 0x80);
+#endif
+ wii_set_flag(WII_FLAG_NUNCHUCK_CONNECTED);
+ } else if(l2capinbuf[16] == 0x00 && (l2capinbuf[17] == 0xA6 || l2capinbuf[17] == 0xA4) && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x00 && l2capinbuf[20] == 0x05) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nMotion Plus connected"), 0x80);
+#endif
+ wii_set_flag(WII_FLAG_MOTION_PLUS_CONNECTED);
+ } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x04 && l2capinbuf[20] == 0x05) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nMotion Plus activated in normal mode"), 0x80);
+#endif
+ motionPlusConnected = true;
+#ifdef WIICAMERA
+ if(!isIRCameraEnabled()) // Don't activate the Motion Plus if we are trying to initialize the IR camera
+#endif
+ setReportMode(false, 0x35); // Also read the extension
+ } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x05 && l2capinbuf[20] == 0x05) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nMotion Plus activated in Nunchuck pass-through mode"), 0x80);
+#endif
+ activateNunchuck = false;
+ motionPlusConnected = true;
+ nunchuckConnected = true;
+#ifdef WIICAMERA
+ if(!isIRCameraEnabled()) // Don't activate the Motion Plus if we are trying to initialize the IR camera
+#endif
+ setReportMode(false, 0x35); // Also read the extension
+ } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA6 && l2capinbuf[18] == 0x20 && (l2capinbuf[19] == 0x00 || l2capinbuf[19] == 0x04 || l2capinbuf[19] == 0x05 || l2capinbuf[19] == 0x07) && l2capinbuf[20] == 0x05) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nInactive Wii Motion Plus"), 0x80);
+ Notify(PSTR("\r\nPlease unplug the Motion Plus, disconnect the Wiimote and then replug the Motion Plus Extension"), 0x80);
+#endif
+ stateCounter = 300; // Skip the rest in "WII_CHECK_MOTION_PLUS_STATE"
+ } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x01 && l2capinbuf[20] == 0x20) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nWii U Pro Controller connected"), 0x80);
+#endif
+ wiiUProControllerConnected = true;
+ } else if(l2capinbuf[16] == 0x00 && l2capinbuf[17] == 0xA4 && l2capinbuf[18] == 0x20 && l2capinbuf[19] == 0x04 && l2capinbuf[20] == 0x02) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nWii Balance Board connected"), 0x80);
+#endif
+ setReportMode(false, 0x32); // Read the Wii Balance Board extension
+ wii_set_flag(WII_FLAG_CALIBRATE_BALANCE_BOARD);
+ }
+ // Wii Balance Board calibration reports (24 bits in total)
+ else if(l2capinbuf[13] == 0x00 && l2capinbuf[14] == 0x24 && reportLength == 16) { // First 16-bit
+ for(uint8_t i = 0; i < 2; i++) {
+ for(uint8_t j = 0; j < 4; j++)
+ wiiBalanceBoardCal[i][j] = l2capinbuf[16 + 8 * i + 2 * j] | l2capinbuf[15 + 8 * i + 2 * j] << 8;
+ }
+ } else if(l2capinbuf[13] == 0x00 && l2capinbuf[14] == 0x34 && reportLength == 8) { // Last 8-bit
+ for(uint8_t j = 0; j < 4; j++)
+ wiiBalanceBoardCal[2][j] = l2capinbuf[16 + 2 * j] | l2capinbuf[15 + 2 * j] << 8;
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nWii Balance Board calibration values read successfully"), 0x80);
+#endif
+ wii_clear_flag(WII_FLAG_CALIBRATE_BALANCE_BOARD);
+ wiiBalanceBoardConnected = true;
+ }
+#ifdef DEBUG_USB_HOST
+ else {
+ Notify(PSTR("\r\nUnknown Device: "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
+ Notify(PSTR("\r\nData: "), 0x80);
+ for(uint8_t i = 0; i < reportLength; i++) {
+ D_PrintHex<uint8_t > (l2capinbuf[15 + i], 0x80);
+ Notify(PSTR(" "), 0x80);
+ }
+ }
+#endif
+ }
+#ifdef EXTRADEBUG
+ else {
+ Notify(PSTR("\r\nReport Error: "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
+ }
+#endif
+ break;
+ case 0x22: // Acknowledge output report, return function result
+#ifdef DEBUG_USB_HOST
+ if(l2capinbuf[13] != 0x00) { // Check if there is an error
+ Notify(PSTR("\r\nCommand failed: "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);
+ }
+#endif
+ break;
+ case 0x30: // Core buttons - (a1) 30 BB BB
+ break;
+ case 0x31: // Core Buttons and Accelerometer - (a1) 31 BB BB AA AA AA
+ break;
+ case 0x32: // Core Buttons with 8 Extension bytes - (a1) 32 BB BB EE EE EE EE EE EE EE EE
+ // See: http://wiibrew.org/wiki/Wii_Balance_Board#Data_Format
+ wiiBalanceBoardRaw[TopRight] = l2capinbuf[13] | l2capinbuf[12] << 8; // Top right
+ wiiBalanceBoardRaw[BotRight] = l2capinbuf[15] | l2capinbuf[14] << 8; // Bottom right
+ wiiBalanceBoardRaw[TopLeft] = l2capinbuf[17] | l2capinbuf[16] << 8; // Top left
+ wiiBalanceBoardRaw[BotLeft] = l2capinbuf[19] | l2capinbuf[18] << 8; // Bottom left
+ break;
+ case 0x33: // Core Buttons with Accelerometer and 12 IR bytes - (a1) 33 BB BB AA AA AA II II II II II II II II II II II II
+#ifdef WIICAMERA
+ // Read the IR data
+ IR_object_x1 = (l2capinbuf[15] | ((uint16_t)(l2capinbuf[17] & 0x30) << 4)); // x position
+ IR_object_y1 = (l2capinbuf[16] | ((uint16_t)(l2capinbuf[17] & 0xC0) << 2)); // y position
+ IR_object_s1 = (l2capinbuf[17] & 0x0F); // Size value, 0-15
+
+ IR_object_x2 = (l2capinbuf[18] | ((uint16_t)(l2capinbuf[20] & 0x30) << 4));
+ IR_object_y2 = (l2capinbuf[19] | ((uint16_t)(l2capinbuf[20] & 0xC0) << 2));
+ IR_object_s2 = (l2capinbuf[20] & 0x0F);
+
+ IR_object_x3 = (l2capinbuf[21] | ((uint16_t)(l2capinbuf[23] & 0x30) << 4));
+ IR_object_y3 = (l2capinbuf[22] | ((uint16_t)(l2capinbuf[23] & 0xC0) << 2));
+ IR_object_s3 = (l2capinbuf[23] & 0x0F);
+
+ IR_object_x4 = (l2capinbuf[24] | ((uint16_t)(l2capinbuf[26] & 0x30) << 4));
+ IR_object_y4 = (l2capinbuf[25] | ((uint16_t)(l2capinbuf[26] & 0xC0) << 2));
+ IR_object_s4 = (l2capinbuf[26] & 0x0F);
+#endif
+ break;
+ case 0x34: // Core Buttons with 19 Extension bytes - (a1) 34 BB BB EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE
+ break;
+ /* 0x3e and 0x3f both give unknown report types when report mode is 0x3e or 0x3f with mode number 0x05 */
+ case 0x3E: // Core Buttons with Accelerometer and 32 IR bytes
+ // (a1) 31 BB BB AA AA AA II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II II
+ // corresponds to output report mode 0x3e
+
+ /**** for reading in full mode: DOES NOT WORK YET ****/
+ /* When it works it will also have intensity and bounding box data */
+ /*
+ IR_object_x1 = (l2capinbuf[13] | ((uint16_t)(l2capinbuf[15] & 0x30) << 4));
+ IR_object_y1 = (l2capinbuf[14] | ((uint16_t)(l2capinbuf[15] & 0xC0) << 2));
+ IR_object_s1 = (l2capinbuf[15] & 0x0F);
+ */
+ break;
+ case 0x3F:
+ /*
+ IR_object_x1 = (l2capinbuf[13] | ((uint16_t)(l2capinbuf[15] & 0x30) << 4));
+ IR_object_y1 = (l2capinbuf[14] | ((uint16_t)(l2capinbuf[15] & 0xC0) << 2));
+ IR_object_s1 = (l2capinbuf[15] & 0x0F);
+ */
+ break;
+ case 0x35: // Core Buttons and Accelerometer with 16 Extension Bytes
+ // (a1) 35 BB BB AA AA AA EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE
+#if 1 // Set this to 0 if you don't want to use an extension, this reduceds the size of the library a lot!
+ if(motionPlusConnected) {
+ if(l2capinbuf[20] & 0x02) { // Check if it's a report from the Motion controller or the extension
+ if(motionValuesReset) { // We will only use the values when the gyro value has been set
+ gyroYawRaw = ((l2capinbuf[15] | ((l2capinbuf[18] & 0xFC) << 6)) - gyroYawZero);
+ gyroRollRaw = ((l2capinbuf[16] | ((l2capinbuf[19] & 0xFC) << 6)) - gyroRollZero);
+ gyroPitchRaw = ((l2capinbuf[17] | ((l2capinbuf[20] & 0xFC) << 6)) - gyroPitchZero);
+
+ yawGyroSpeed = (double)gyroYawRaw / ((double)gyroYawZero / yawGyroScale);
+ rollGyroSpeed = -(double)gyroRollRaw / ((double)gyroRollZero / rollGyroScale); // We invert these values so they will fit the acc values
+ pitchGyroSpeed = (double)gyroPitchRaw / ((double)gyroPitchZero / pitchGyroScale);
+
+ /* The onboard gyro has two ranges for slow and fast mode */
+ if(!(l2capinbuf[18] & 0x02)) // Check if fast mode is used
+ yawGyroSpeed *= 4.545;
+ if(!(l2capinbuf[18] & 0x01)) // Check if fast mode is used
+ pitchGyroSpeed *= 4.545;
+ if(!(l2capinbuf[19] & 0x02)) // Check if fast mode is used
+ rollGyroSpeed *= 4.545;
+
+ compPitch = (0.93 * (compPitch + (pitchGyroSpeed * (double)(micros() - timer) / 1000000)))+(0.07 * getWiimotePitch()); // Use a complimentary filter to calculate the angle
+ compRoll = (0.93 * (compRoll + (rollGyroSpeed * (double)(micros() - timer) / 1000000)))+(0.07 * getWiimoteRoll());
+
+ gyroYaw += (yawGyroSpeed * ((double)(micros() - timer) / 1000000));
+ gyroRoll += (rollGyroSpeed * ((double)(micros() - timer) / 1000000));
+ gyroPitch += (pitchGyroSpeed * ((double)(micros() - timer) / 1000000));
+ timer = micros();
+ /*
+ // Uncomment these lines to tune the gyro scale variabels
+ Notify(PSTR("\r\ngyroYaw: "), 0x80);
+ Notify(gyroYaw, 0x80);
+ Notify(PSTR("\tgyroRoll: "), 0x80);
+ Notify(gyroRoll, 0x80);
+ Notify(PSTR("\tgyroPitch: "), 0x80);
+ Notify(gyroPitch, 0x80);
+ */
+ /*
+ Notify(PSTR("\twiimoteRoll: "), 0x80);
+ Notify(wiimoteRoll, 0x80);
+ Notify(PSTR("\twiimotePitch: "), 0x80);
+ Notify(wiimotePitch, 0x80);
+ */
+ } else {
+ if((micros() - timer) > 1000000) { // Loop for 1 sec before resetting the values
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nThe gyro values has been reset"), 0x80);
+#endif
+ gyroYawZero = (l2capinbuf[15] | ((l2capinbuf[18] & 0xFC) << 6));
+ gyroRollZero = (l2capinbuf[16] | ((l2capinbuf[19] & 0xFC) << 6));
+ gyroPitchZero = (l2capinbuf[17] | ((l2capinbuf[20] & 0xFC) << 6));
+
+ rollGyroScale = 500; // You might need to adjust these
+ pitchGyroScale = 400;
+ yawGyroScale = 415;
+
+ gyroYaw = 0;
+ gyroRoll = 0;
+ gyroPitch = 0;
+
+ motionValuesReset = true;
+ timer = micros();
+ }
+ }
+ } else {
+ if(nunchuckConnected) {
+ hatValues[HatX] = l2capinbuf[15];
+ hatValues[HatY] = l2capinbuf[16];
+ accXnunchuck = ((l2capinbuf[17] << 2) | (l2capinbuf[20] & 0x10 >> 3)) - 416;
+ accYnunchuck = ((l2capinbuf[18] << 2) | (l2capinbuf[20] & 0x20 >> 4)) - 416;
+ accZnunchuck = (((l2capinbuf[19] & 0xFE) << 2) | (l2capinbuf[20] & 0xC0 >> 5)) - 416;
+ }
+ //else if(classicControllerConnected) { }
+ }
+ if(l2capinbuf[19] & 0x01) {
+ if(!extensionConnected) {
+ extensionConnected = true;
+ unknownExtensionConnected = true;
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nExtension connected to Motion Plus"), 0x80);
+#endif
+ }
+ } else {
+ if(extensionConnected && !unknownExtensionConnected) {
+ extensionConnected = false;
+ unknownExtensionConnected = true;
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nExtension disconnected from Motion Plus"), 0x80);
+#endif
+ nunchuckConnected = false; // There is no extension connected to the Motion Plus if this report is sent
+ }
+ }
+
+ } else if(nunchuckConnected) {
+ hatValues[HatX] = l2capinbuf[15];
+ hatValues[HatY] = l2capinbuf[16];
+ accXnunchuck = ((l2capinbuf[17] << 2) | (l2capinbuf[20] & 0x0C >> 2)) - 416;
+ accYnunchuck = ((l2capinbuf[18] << 2) | (l2capinbuf[20] & 0x30 >> 4)) - 416;
+ accZnunchuck = ((l2capinbuf[19] << 2) | (l2capinbuf[20] & 0xC0 >> 6)) - 416;
+ } else if(wiiUProControllerConnected) {
+ hatValues[LeftHatX] = (l2capinbuf[15] | l2capinbuf[16] << 8);
+ hatValues[RightHatX] = (l2capinbuf[17] | l2capinbuf[18] << 8);
+ hatValues[LeftHatY] = (l2capinbuf[19] | l2capinbuf[20] << 8);
+ hatValues[RightHatY] = (l2capinbuf[21] | l2capinbuf[22] << 8);
+ }
+#endif
+ break;
+#ifdef DEBUG_USB_HOST
+ default:
+ Notify(PSTR("\r\nUnknown Report type: "), 0x80);
+ D_PrintHex<uint8_t > (l2capinbuf[9], 0x80);
+ break;
+#endif
+ }
+ }
+ }
+ L2CAP_task();
+ }
+}
+
+void WII::L2CAP_task() {
+ switch(l2cap_state) {
+ /* These states are used if the Wiimote is the host */
+ case L2CAP_CONTROL_SUCCESS:
+ if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nHID Control Successfully Configured"), 0x80);
+#endif
+ l2cap_state = L2CAP_INTERRUPT_SETUP;
+ }
+ break;
+
+ case L2CAP_INTERRUPT_SETUP:
+ if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_INTERRUPT_REQUEST)) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"), 0x80);
+#endif
+ pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, PENDING);
+ delay(1);
+ pBtd->l2cap_connection_response(hci_handle, identifier, interrupt_dcid, interrupt_scid, SUCCESSFUL);
+ identifier++;
+ delay(1);
+ pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid);
+
+ l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST;
+ }
+ break;
+
+ /* These states are used if the Arduino is the host */
+ case L2CAP_CONTROL_CONNECT_REQUEST:
+ if(l2cap_check_flag(L2CAP_FLAG_CONTROL_CONNECTED)) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nSend HID Control Config Request"), 0x80);
+#endif
+ identifier++;
+ pBtd->l2cap_config_request(hci_handle, identifier, control_scid);
+ l2cap_state = L2CAP_CONTROL_CONFIG_REQUEST;
+ }
+ break;
+
+ case L2CAP_CONTROL_CONFIG_REQUEST:
+ if(l2cap_check_flag(L2CAP_FLAG_CONFIG_CONTROL_SUCCESS)) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nSend HID Interrupt Connection Request"), 0x80);
+#endif
+ identifier++;
+ pBtd->l2cap_connection_request(hci_handle, identifier, interrupt_dcid, HID_INTR_PSM);
+ l2cap_state = L2CAP_INTERRUPT_CONNECT_REQUEST;
+ }
+ break;
+
+ case L2CAP_INTERRUPT_CONNECT_REQUEST:
+ if(l2cap_check_flag(L2CAP_FLAG_INTERRUPT_CONNECTED)) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nSend HID Interrupt Config Request"), 0x80);
+#endif
+ identifier++;
+ pBtd->l2cap_config_request(hci_handle, identifier, interrupt_scid);
+ l2cap_state = L2CAP_INTERRUPT_CONFIG_REQUEST;
+ }
+ break;
+
+ case L2CAP_INTERRUPT_CONFIG_REQUEST:
+ if(l2cap_check_flag(L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS)) { // Now the HID channels is established
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nHID Channels Established"), 0x80);
+#endif
+ pBtd->connectToWii = false;
+ pBtd->pairWithWii = false;
+ stateCounter = 0;
+ l2cap_state = WII_CHECK_MOTION_PLUS_STATE;
+ }
+ break;
+
+ /* The next states are in run() */
+
+ case L2CAP_INTERRUPT_DISCONNECT:
+ if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE) && ((long)(millis() - timer) >= 0L)) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nDisconnected Interrupt Channel"), 0x80);
+#endif
+ identifier++;
+ pBtd->l2cap_disconnection_request(hci_handle, identifier, control_scid, control_dcid);
+ l2cap_state = L2CAP_CONTROL_DISCONNECT;
+ }
+ break;
+
+ case L2CAP_CONTROL_DISCONNECT:
+ if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE)) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nDisconnected Control Channel"), 0x80);
+#endif
+ pBtd->hci_disconnect(hci_handle);
+ hci_handle = -1; // Reset handle
+ l2cap_event_flag = 0; // Reset flags
+ l2cap_state = L2CAP_WAIT;
+ }
+ break;
+ }
+}
+
+void WII::Run() {
+ if(l2cap_state == L2CAP_INTERRUPT_DISCONNECT && ((long)(millis() - timer) >= 0L))
+ L2CAP_task(); // Call the rest of the disconnection routine after we have waited long enough
+
+ switch(l2cap_state) {
+ case L2CAP_WAIT:
+ if(pBtd->connectToWii && !pBtd->l2capConnectionClaimed && !wiimoteConnected && !activeConnection) {
+ pBtd->l2capConnectionClaimed = true;
+ activeConnection = true;
+ motionPlusInside = pBtd->motionPlusInside;
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nSend HID Control Connection Request"), 0x80);
+#endif
+ hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection
+ l2cap_event_flag = 0; // Reset flags
+ identifier = 0;
+ pBtd->l2cap_connection_request(hci_handle, identifier, control_dcid, HID_CTRL_PSM);
+ l2cap_state = L2CAP_CONTROL_CONNECT_REQUEST;
+ } else if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_CONTROL_REQUEST)) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nHID Control Incoming Connection Request"), 0x80);
+#endif
+ pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, PENDING);
+ delay(1);
+ pBtd->l2cap_connection_response(hci_handle, identifier, control_dcid, control_scid, SUCCESSFUL);
+ identifier++;
+ delay(1);
+ pBtd->l2cap_config_request(hci_handle, identifier, control_scid);
+ l2cap_state = L2CAP_CONTROL_SUCCESS;
+ }
+ break;
+
+ case WII_CHECK_MOTION_PLUS_STATE:
+#ifdef DEBUG_USB_HOST
+ if(stateCounter == 0) // Only print onnce
+ Notify(PSTR("\r\nChecking if a Motion Plus is connected"), 0x80);
+#endif
+ stateCounter++;
+ if(stateCounter % 200 == 0)
+ checkMotionPresent(); // Check if there is a motion plus connected
+ if(wii_check_flag(WII_FLAG_MOTION_PLUS_CONNECTED)) {
+ stateCounter = 0;
+ l2cap_state = WII_INIT_MOTION_PLUS_STATE;
+ timer = micros();
+
+ if(unknownExtensionConnected) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nA extension is also connected"), 0x80);
+#endif
+ activateNunchuck = true; // For we will just set this to true as this the only extension supported so far
+ }
+
+ } else if(stateCounter == 601) { // We will try three times to check for the motion plus
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nNo Motion Plus was detected"), 0x80);
+#endif
+ stateCounter = 0;
+ l2cap_state = WII_CHECK_EXTENSION_STATE;
+ }
+ break;
+
+ case WII_CHECK_EXTENSION_STATE: // This is used to check if there is anything plugged in to the extension port
+#ifdef DEBUG_USB_HOST
+ if(stateCounter == 0) // Only print onnce
+ Notify(PSTR("\r\nChecking if there is any extension connected"), 0x80);
+#endif
+ stateCounter++; // We use this counter as there has to be a short delay between the commands
+ if(stateCounter == 1)
+ statusRequest(); // See if a new device has connected
+ if(stateCounter == 100) {
+ if(unknownExtensionConnected) // Check if there is a extension is connected to the port
+ initExtension1();
+ else
+ stateCounter = 499;
+ } else if(stateCounter == 200)
+ initExtension2();
+ else if(stateCounter == 300) {
+ readExtensionType();
+ unknownExtensionConnected = false;
+ } else if(stateCounter == 400) {
+ if(wii_check_flag(WII_FLAG_CALIBRATE_BALANCE_BOARD)) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nReading Wii Balance Board calibration values"), 0x80);
+#endif
+ readWiiBalanceBoardCalibration();
+ } else
+ stateCounter = 499;
+ } else if(stateCounter == 500) {
+ stateCounter = 0;
+ l2cap_state = TURN_ON_LED;
+ }
+ break;
+
+ case WII_INIT_MOTION_PLUS_STATE:
+ stateCounter++;
+ if(stateCounter == 1)
+ initMotionPlus();
+ else if(stateCounter == 100)
+ activateMotionPlus();
+ else if(stateCounter == 200)
+ readExtensionType(); // Check if it has been activated
+ else if(stateCounter == 300) {
+ stateCounter = 0;
+ unknownExtensionConnected = false; // The motion plus will send a status report when it's activated, we will set this to false so it doesn't reinitialize the Motion Plus
+ l2cap_state = TURN_ON_LED;
+ }
+ break;
+
+ case TURN_ON_LED:
+ if(wii_check_flag(WII_FLAG_NUNCHUCK_CONNECTED))
+ nunchuckConnected = true;
+ wiimoteConnected = true;
+ onInit();
+ l2cap_state = L2CAP_DONE;
+ break;
+
+ case L2CAP_DONE:
+ if(unknownExtensionConnected) {
+#ifdef DEBUG_USB_HOST
+ if(stateCounter == 0) // Only print once
+ Notify(PSTR("\r\nChecking extension port"), 0x80);
+#endif
+ stateCounter++; // We will use this counter as there has to be a short delay between the commands
+ if(stateCounter == 50)
+ statusRequest();
+ else if(stateCounter == 100)
+ initExtension1();
+ else if(stateCounter == 150)
+ if((extensionConnected && motionPlusConnected) || (unknownExtensionConnected && !motionPlusConnected))
+ initExtension2();
+ else
+ stateCounter = 299; // There is no extension connected
+ else if(stateCounter == 200)
+ readExtensionType();
+ else if(stateCounter == 250) {
+ if(wii_check_flag(WII_FLAG_NUNCHUCK_CONNECTED)) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nNunchuck was reconnected"), 0x80);
+#endif
+ activateNunchuck = true;
+ nunchuckConnected = true;
+ }
+ if(!motionPlusConnected)
+ stateCounter = 449;
+ } else if(stateCounter == 300) {
+ if(motionPlusConnected) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nReactivating the Motion Plus"), 0x80);
+#endif
+ initMotionPlus();
+ } else
+ stateCounter = 449;
+ } else if(stateCounter == 350)
+ activateMotionPlus();
+ else if(stateCounter == 400)
+ readExtensionType(); // Check if it has been activated
+ else if(stateCounter == 450) {
+ onInit();
+ stateCounter = 0;
+ unknownExtensionConnected = false;
+ }
+ } else
+ stateCounter = 0;
+ break;
+ }
+}
+
+/************************************************************/
+/* HID Commands */
+/************************************************************/
+
+void WII::HID_Command(uint8_t* data, uint8_t nbytes) {
+ if(motionPlusInside)
+ pBtd->L2CAP_Command(hci_handle, data, nbytes, interrupt_scid[0], interrupt_scid[1]); // It's the new Wiimote with the Motion Plus Inside or Wii U Pro controller
+ else
+ pBtd->L2CAP_Command(hci_handle, data, nbytes, control_scid[0], control_scid[1]);
+}
+
+void WII::setAllOff() {
+ HIDBuffer[1] = 0x11;
+ HIDBuffer[2] = 0x00;
+ HID_Command(HIDBuffer, 3);
+}
+
+void WII::setRumbleOff() {
+ HIDBuffer[1] = 0x11;
+ HIDBuffer[2] &= ~0x01; // Bit 0 control the rumble
+ HID_Command(HIDBuffer, 3);
+}
+
+void WII::setRumbleOn() {
+ HIDBuffer[1] = 0x11;
+ HIDBuffer[2] |= 0x01; // Bit 0 control the rumble
+ HID_Command(HIDBuffer, 3);
+}
+
+void WII::setRumbleToggle() {
+ HIDBuffer[1] = 0x11;
+ HIDBuffer[2] ^= 0x01; // Bit 0 control the rumble
+ HID_Command(HIDBuffer, 3);
+}
+
+void WII::setLedRaw(uint8_t value) {
+ HIDBuffer[1] = 0x11;
+ HIDBuffer[2] = value | (HIDBuffer[2] & 0x01); // Keep the rumble bit
+ HID_Command(HIDBuffer, 3);
+}
+
+void WII::setLedOff(LEDEnum a) {
+ HIDBuffer[1] = 0x11;
+ HIDBuffer[2] &= ~(pgm_read_byte(&WII_LEDS[(uint8_t)a]));
+ HID_Command(HIDBuffer, 3);
+}
+
+void WII::setLedOn(LEDEnum a) {
+ if(a == OFF)
+ setLedRaw(0);
+ else {
+ HIDBuffer[1] = 0x11;
+ HIDBuffer[2] |= pgm_read_byte(&WII_LEDS[(uint8_t)a]);
+ HID_Command(HIDBuffer, 3);
+ }
+}
+
+void WII::setLedToggle(LEDEnum a) {
+ HIDBuffer[1] = 0x11;
+ HIDBuffer[2] ^= pgm_read_byte(&WII_LEDS[(uint8_t)a]);
+ HID_Command(HIDBuffer, 3);
+}
+
+void WII::setLedStatus() {
+ HIDBuffer[1] = 0x11;
+ HIDBuffer[2] = (HIDBuffer[2] & 0x01); // Keep the rumble bit
+ if(wiimoteConnected)
+ HIDBuffer[2] |= 0x10; // If it's connected LED1 will light up
+ if(motionPlusConnected)
+ HIDBuffer[2] |= 0x20; // If it's connected LED2 will light up
+ if(nunchuckConnected)
+ HIDBuffer[2] |= 0x40; // If it's connected LED3 will light up
+
+ HID_Command(HIDBuffer, 3);
+}
+
+uint8_t WII::getBatteryLevel() {
+ checkBatteryLevel = true; // This is needed so the library knows that the status response is a response to this function
+ statusRequest(); // This will update the battery level
+ return batteryLevel;
+};
+
+void WII::setReportMode(bool continuous, uint8_t mode) {
+ uint8_t cmd_buf[4];
+ cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
+ cmd_buf[1] = 0x12;
+ if(continuous)
+ cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Keep the rumble bit
+ else
+ cmd_buf[2] = 0x00 | (HIDBuffer[2] & 0x01); // Keep the rumble bit
+ cmd_buf[3] = mode;
+ HID_Command(cmd_buf, 4);
+}
+
+void WII::statusRequest() {
+ uint8_t cmd_buf[3];
+ cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
+ cmd_buf[1] = 0x15;
+ cmd_buf[2] = (HIDBuffer[2] & 0x01); // Keep the rumble bit
+ HID_Command(cmd_buf, 3);
+}
+
+/************************************************************/
+/* Memmory Commands */
+/************************************************************/
+
+void WII::writeData(uint32_t offset, uint8_t size, uint8_t* data) {
+ uint8_t cmd_buf[23];
+ cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
+ cmd_buf[1] = 0x16; // Write data
+ cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Write to memory, clear bit 2 to write to EEPROM
+ cmd_buf[3] = (uint8_t)((offset & 0xFF0000) >> 16);
+ cmd_buf[4] = (uint8_t)((offset & 0xFF00) >> 8);
+ cmd_buf[5] = (uint8_t)(offset & 0xFF);
+ cmd_buf[6] = size;
+ uint8_t i = 0;
+ for(; i < size; i++)
+ cmd_buf[7 + i] = data[i];
+ for(; i < 16; i++) // Set the rest to zero
+ cmd_buf[7 + i] = 0x00;
+ HID_Command(cmd_buf, 23);
+}
+
+void WII::initExtension1() {
+ uint8_t buf[1];
+ buf[0] = 0x55;
+ writeData(0xA400F0, 1, buf);
+}
+
+void WII::initExtension2() {
+ uint8_t buf[1];
+ buf[0] = 0x00;
+ writeData(0xA400FB, 1, buf);
+}
+
+void WII::initMotionPlus() {
+ uint8_t buf[1];
+ buf[0] = 0x55;
+ writeData(0xA600F0, 1, buf);
+}
+
+void WII::activateMotionPlus() {
+ uint8_t buf[1];
+ if(pBtd->wiiUProController) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nActivating Wii U Pro Controller"), 0x80);
+#endif
+ buf[0] = 0x00; // It seems like you can send anything but 0x04, 0x05, and 0x07
+ } else if(activateNunchuck) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nActivating Motion Plus in pass-through mode"), 0x80);
+#endif
+ buf[0] = 0x05; // Activate nunchuck pass-through mode
+ }//else if(classicControllerConnected && extensionConnected)
+ //buf[0] = 0x07;
+ else {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nActivating Motion Plus in normal mode"), 0x80);
+#endif
+ buf[0] = 0x04; // Don't use any extension
+ }
+ writeData(0xA600FE, 1, buf);
+}
+
+void WII::readData(uint32_t offset, uint16_t size, bool EEPROM) {
+ uint8_t cmd_buf[8];
+ cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
+ cmd_buf[1] = 0x17; // Read data
+ if(EEPROM)
+ cmd_buf[2] = 0x00 | (HIDBuffer[2] & 0x01); // Read from EEPROM
+ else
+ cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Read from memory
+ cmd_buf[3] = (uint8_t)((offset & 0xFF0000) >> 16);
+ cmd_buf[4] = (uint8_t)((offset & 0xFF00) >> 8);
+ cmd_buf[5] = (uint8_t)(offset & 0xFF);
+ cmd_buf[6] = (uint8_t)((size & 0xFF00) >> 8);
+ cmd_buf[7] = (uint8_t)(size & 0xFF);
+
+ HID_Command(cmd_buf, 8);
+}
+
+void WII::readExtensionType() {
+ readData(0xA400FA, 6, false);
+}
+
+void WII::readCalData() {
+ readData(0x0016, 8, true);
+}
+
+void WII::checkMotionPresent() {
+ readData(0xA600FA, 6, false);
+}
+
+void WII::readWiiBalanceBoardCalibration() {
+ readData(0xA40024, 24, false);
+}
+
+/************************************************************/
+/* WII Commands */
+/************************************************************/
+
+bool WII::getButtonPress(ButtonEnum b) { // Return true when a button is pressed
+ if(wiiUProControllerConnected)
+ return (ButtonState & pgm_read_dword(&WII_PROCONTROLLER_BUTTONS[(uint8_t)b]));
+ else
+ return (ButtonState & pgm_read_dword(&WII_BUTTONS[(uint8_t)b]));
+}
+
+bool WII::getButtonClick(ButtonEnum b) { // Only return true when a button is clicked
+ uint32_t button;
+ if(wiiUProControllerConnected)
+ button = pgm_read_dword(&WII_PROCONTROLLER_BUTTONS[(uint8_t)b]);
+ else
+ button = pgm_read_dword(&WII_BUTTONS[(uint8_t)b]);
+ bool click = (ButtonClickState & button);
+ ButtonClickState &= ~button; // clear "click" event
+ return click;
+}
+
+uint8_t WII::getAnalogHat(HatEnum a) {
+ if(!nunchuckConnected)
+ return 127; // Return center position
+ else {
+ uint8_t output = hatValues[(uint8_t)a];
+ if(output == 0xFF || output == 0x00) // The joystick will only read 255 or 0 when the cable is unplugged or initializing, so we will just return the center position
+ return 127;
+ else
+ return output;
+ }
+}
+
+uint16_t WII::getAnalogHat(AnalogHatEnum a) {
+ if(!wiiUProControllerConnected)
+ return 2000;
+ else {
+ uint16_t output = hatValues[(uint8_t)a];
+ if(output == 0x00) // The joystick will only read 0 when it is first initializing, so we will just return the center position
+ return 2000;
+ else
+ return output;
+ }
+}
+
+void WII::onInit() {
+ if(pFuncOnInit)
+ pFuncOnInit(); // Call the user function
+ else
+ setLedStatus();
+}
+
+/************************************************************/
+/* Wii Balance Board Commands */
+/************************************************************/
+
+float WII::getWeight(BalanceBoardEnum pos) {
+ // Use interpolating between two points - based on: https://github.com/skorokithakis/gr8w8upd8m8/blob/master/gr8w8upd8m8.py
+ // wiiBalanceBoardCal[pos][0] is calibration values for 0 kg
+ // wiiBalanceBoardCal[pos][1] is calibration values for 17 kg
+ // wiiBalanceBoardCal[pos][2] is calibration values for 34 kg
+ if(wiiBalanceBoardRaw[pos] < wiiBalanceBoardCal[0][pos])
+ return 0.0f; // Below 0 kg
+ else if(wiiBalanceBoardRaw[pos] < wiiBalanceBoardCal[1][pos]) // Between 0 and 17 kg
+ return 17.0f * (float)(wiiBalanceBoardRaw[pos] - wiiBalanceBoardCal[0][pos]) / (float)(wiiBalanceBoardCal[1][pos] - wiiBalanceBoardCal[0][pos]);
+ else // More than 17 kg
+ return 17.0f + 17.0f * (float)(wiiBalanceBoardRaw[pos] - wiiBalanceBoardCal[1][pos]) / (float)(wiiBalanceBoardCal[2][pos] - wiiBalanceBoardCal[1][pos]);
+};
+
+float WII::getTotalWeight() {
+ return getWeight(TopRight) + getWeight(BotRight) + getWeight(TopLeft) + getWeight(BotLeft);
+};
+
+/************************************************************/
+/* The following functions are for the IR camera */
+/************************************************************/
+
+#ifdef WIICAMERA
+
+void WII::IRinitialize() { // Turns on and initialises the IR camera
+
+ enableIRCamera1();
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nEnable IR Camera1 Complete"), 0x80);
+#endif
+ delay(80);
+
+ enableIRCamera2();
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nEnable IR Camera2 Complete"), 0x80);
+#endif
+ delay(80);
+
+ write0x08Value();
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nWrote hex number 0x08"), 0x80);
+#endif
+ delay(80);
+
+ writeSensitivityBlock1();
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nWrote Sensitivity Block 1"), 0x80);
+#endif
+ delay(80);
+
+ writeSensitivityBlock2();
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nWrote Sensitivity Block 2"), 0x80);
+#endif
+ delay(80);
+
+ uint8_t mode_num = 0x03;
+ setWiiModeNumber(mode_num); // Change input for whatever mode you want i.e. 0x01, 0x03, or 0x05
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nSet Wii Mode Number To 0x"), 0x80);
+ D_PrintHex<uint8_t > (mode_num, 0x80);
+#endif
+ delay(80);
+
+ write0x08Value();
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nWrote Hex Number 0x08"), 0x80);
+#endif
+ delay(80);
+
+ setReportMode(false, 0x33);
+ //setReportMode(false, 0x3f); // For full reporting mode, doesn't work yet
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nSet Report Mode to 0x33"), 0x80);
+#endif
+ delay(80);
+
+ statusRequest(); // Used to update wiiState - call isIRCameraEnabled() afterwards to check if it actually worked
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nIR Initialized"), 0x80);
+#endif
+}
+
+void WII::enableIRCamera1() {
+ uint8_t cmd_buf[3];
+ cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
+ cmd_buf[1] = 0x13; // Output report 13
+ cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Keep the rumble bit and sets bit 2
+ HID_Command(cmd_buf, 3);
+}
+
+void WII::enableIRCamera2() {
+ uint8_t cmd_buf[3];
+ cmd_buf[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02)
+ cmd_buf[1] = 0x1A; // Output report 1A
+ cmd_buf[2] = 0x04 | (HIDBuffer[2] & 0x01); // Keep the rumble bit and sets bit 2
+ HID_Command(cmd_buf, 3);
+}
+
+void WII::writeSensitivityBlock1() {
+ uint8_t buf[9];
+ buf[0] = 0x00;
+ buf[1] = 0x00;
+ buf[2] = 0x00;
+ buf[3] = 0x00;
+ buf[4] = 0x00;
+ buf[5] = 0x00;
+ buf[6] = 0x90;
+ buf[7] = 0x00;
+ buf[8] = 0x41;
+
+ writeData(0xB00000, 9, buf);
+}
+
+void WII::writeSensitivityBlock2() {
+ uint8_t buf[2];
+ buf[0] = 0x40;
+ buf[1] = 0x00;
+
+ writeData(0xB0001A, 2, buf);
+}
+
+void WII::write0x08Value() {
+ uint8_t cmd = 0x08;
+ writeData(0xb00030, 1, &cmd);
+}
+
+void WII::setWiiModeNumber(uint8_t mode_number) { // mode_number in hex i.e. 0x03 for extended mode
+ writeData(0xb00033, 1, &mode_number);
+}
+#endif
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Wii.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Wii.h
new file mode 100755
index 000000000..960f2273d
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/Wii.h
@@ -0,0 +1,518 @@
+/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
+
+ This software may be distributed and modified under the terms of the GNU
+ General Public License version 2 (GPL2) as published by the Free Software
+ Foundation and appearing in the file GPL2.TXT included in the packaging of
+ this file. Please note that GPL2 Section 2[b] requires that all works based
+ on this software must also be made publicly available under the terms of
+ the GPL2 ("Copyleft").
+
+ Contact information
+ -------------------
+
+ Kristian Lauszus, TKJ Electronics
+ Web : http://www.tkjelectronics.com
+ e-mail : kristianl@tkjelectronics.com
+
+ IR camera support added by Allan Glover (adglover9.81@gmail.com) and Kristian Lauszus
+ */
+
+#ifndef _wii_h_
+#define _wii_h_
+
+#include "BTD.h"
+#include "controllerEnums.h"
+
+/* Wii event flags */
+#define WII_FLAG_MOTION_PLUS_CONNECTED (1 << 0)
+#define WII_FLAG_NUNCHUCK_CONNECTED (1 << 1)
+#define WII_FLAG_CALIBRATE_BALANCE_BOARD (1 << 2)
+
+#define wii_check_flag(flag) (wii_event_flag & (flag))
+#define wii_set_flag(flag) (wii_event_flag |= (flag))
+#define wii_clear_flag(flag) (wii_event_flag &= ~(flag))
+
+/** Enum used to read the joystick on the Nunchuck. */
+enum HatEnum {
+ /** Read the x-axis on the Nunchuck joystick. */
+ HatX = 0,
+ /** Read the y-axis on the Nunchuck joystick. */
+ HatY = 1,
+};
+
+/** Enum used to read the weight on Wii Balance Board. */
+enum BalanceBoardEnum {
+ TopRight = 0,
+ BotRight = 1,
+ TopLeft = 2,
+ BotLeft = 3,
+};
+
+/**
+ * This BluetoothService class implements support for the Wiimote including the Nunchuck and Motion Plus extension.
+ *
+ * It also support the Wii U Pro Controller.
+ */
+class WII : public BluetoothService {
+public:
+ /**
+ * Constructor for the WII class.
+ * @param p Pointer to BTD class instance.
+ * @param pair Set this to true in order to pair with the Wiimote. If the argument is omitted then it won't pair with it.
+ * One can use ::PAIR to set it to true.
+ */
+ WII(BTD *p, bool pair = false);
+
+ /** @name BluetoothService implementation */
+ /** Used this to disconnect any of the controllers. */
+ void disconnect();
+ /**@}*/
+
+ /** @name Wii Controller functions */
+ /**
+ * getButtonPress(Button b) will return true as long as the button is held down.
+ *
+ * While getButtonClick(Button b) will only return it once.
+ *
+ * So you instance if you need to increase a variable once you would use getButtonClick(Button b),
+ * but if you need to drive a robot forward you would use getButtonPress(Button b).
+ * @param b ::ButtonEnum to read.
+ * @return getButtonPress(ButtonEnum b) will return a true as long as a button is held down, while getButtonClick(ButtonEnum b) will return true once for each button press.
+ */
+ bool getButtonPress(ButtonEnum b);
+ bool getButtonClick(ButtonEnum b);
+ /**@}*/
+
+ /** @name Wii Controller functions */
+
+ /** Call this to start the paring sequence with a controller */
+ void pair(void) {
+ if(pBtd)
+ pBtd->pairWithWiimote();
+ };
+ /**
+ * Used to read the joystick of the Nunchuck.
+ * @param a Either ::HatX or ::HatY.
+ * @return Return the analog value in the range from approximately 25-230.
+ */
+ uint8_t getAnalogHat(HatEnum a);
+ /**
+ * Used to read the joystick of the Wii U Pro Controller.
+ * @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY.
+ * @return Return the analog value in the range from approximately 800-3200.
+ */
+ uint16_t getAnalogHat(AnalogHatEnum a);
+
+ /**
+ * Pitch calculated from the Wiimote. A complimentary filter is used if the Motion Plus is connected.
+ * @return Pitch in the range from 0-360.
+ */
+ double getPitch() {
+ if(motionPlusConnected)
+ return compPitch;
+ return getWiimotePitch();
+ };
+
+ /**
+ * Roll calculated from the Wiimote. A complimentary filter is used if the Motion Plus is connected.
+ * @return Roll in the range from 0-360.
+ */
+ double getRoll() {
+ if(motionPlusConnected)
+ return compRoll;
+ return getWiimoteRoll();
+ };
+
+ /**
+ * This is the yaw calculated by the gyro.
+ *
+ * <B>NOTE:</B> This angle will drift a lot and is only available if the Motion Plus extension is connected.
+ * @return The angle calculated using the gyro.
+ */
+ double getYaw() {
+ return gyroYaw;
+ };
+
+ /** Used to set all LEDs and rumble off. */
+ void setAllOff();
+ /** Turn off rumble. */
+ void setRumbleOff();
+ /** Turn on rumble. */
+ void setRumbleOn();
+ /** Toggle rumble. */
+ void setRumbleToggle();
+
+ /**
+ * Set LED value without using the ::LEDEnum.
+ * @param value See: ::LEDEnum.
+ */
+ void setLedRaw(uint8_t value);
+
+ /** Turn all LEDs off. */
+ void setLedOff() {
+ setLedRaw(0);
+ };
+ /**
+ * Turn the specific ::LEDEnum off.
+ * @param a The ::LEDEnum to turn off.
+ */
+ void setLedOff(LEDEnum a);
+ /**
+ * Turn the specific ::LEDEnum on.
+ * @param a The ::LEDEnum to turn on.
+ */
+ void setLedOn(LEDEnum a);
+ /**
+ * Toggle the specific ::LEDEnum.
+ * @param a The ::LEDEnum to toggle.
+ */
+ void setLedToggle(LEDEnum a);
+ /**
+ * This will set the LEDs, so the user can see which connections are active.
+ *
+ * The first ::LEDEnum indicate that the Wiimote is connected,
+ * the second ::LEDEnum indicate indicate that a Motion Plus is also connected
+ * the third ::LEDEnum will indicate that a Nunchuck controller is also connected.
+ */
+ void setLedStatus();
+
+ /**
+ * Return the battery level of the Wiimote.
+ * @return The battery level in the range 0-255.
+ */
+ uint8_t getBatteryLevel();
+
+ /**
+ * Return the Wiimote state.
+ * @return See: http://wiibrew.org/wiki/Wiimote#0x20:_Status.
+ */
+ uint8_t getWiiState() {
+ return wiiState;
+ };
+ /**@}*/
+
+ /**@{*/
+ /** Variable used to indicate if a Wiimote is connected. */
+ bool wiimoteConnected;
+ /** Variable used to indicate if a Nunchuck controller is connected. */
+ bool nunchuckConnected;
+ /** Variable used to indicate if a Nunchuck controller is connected. */
+ bool motionPlusConnected;
+ /** Variable used to indicate if a Wii U Pro controller is connected. */
+ bool wiiUProControllerConnected;
+ /** Variable used to indicate if a Wii Balance Board is connected. */
+ bool wiiBalanceBoardConnected;
+ /**@}*/
+
+ /* IMU Data, might be usefull if you need to do something more advanced than just calculating the angle */
+
+ /**@{*/
+
+ /** Pitch and roll calculated from the accelerometer inside the Wiimote. */
+ double getWiimotePitch() {
+ return (atan2(accYwiimote, accZwiimote) + PI) * RAD_TO_DEG;
+ };
+
+ double getWiimoteRoll() {
+ return (atan2(accXwiimote, accZwiimote) + PI) * RAD_TO_DEG;
+ };
+ /**@}*/
+
+ /**@{*/
+
+ /** Pitch and roll calculated from the accelerometer inside the Nunchuck. */
+ double getNunchuckPitch() {
+ return (atan2(accYnunchuck, accZnunchuck) + PI) * RAD_TO_DEG;
+ };
+
+ double getNunchuckRoll() {
+ return (atan2(accXnunchuck, accZnunchuck) + PI) * RAD_TO_DEG;
+ };
+ /**@}*/
+
+ /**@{*/
+ /** Accelerometer values used to calculate pitch and roll. */
+ int16_t accXwiimote, accYwiimote, accZwiimote;
+ int16_t accXnunchuck, accYnunchuck, accZnunchuck;
+ /**@}*/
+
+ /* Variables for the gyro inside the Motion Plus */
+ /** This is the pitch calculated by the gyro - use this to tune WII#pitchGyroScale. */
+ double gyroPitch;
+ /** This is the roll calculated by the gyro - use this to tune WII#rollGyroScale. */
+ double gyroRoll;
+ /** This is the yaw calculated by the gyro - use this to tune WII#yawGyroScale. */
+ double gyroYaw;
+
+ /**@{*/
+ /** The speed in deg/s from the gyro. */
+ double pitchGyroSpeed;
+ double rollGyroSpeed;
+ double yawGyroSpeed;
+ /**@}*/
+
+ /**@{*/
+ /** You might need to fine-tune these values. */
+ uint16_t pitchGyroScale;
+ uint16_t rollGyroScale;
+ uint16_t yawGyroScale;
+ /**@}*/
+
+ /**@{*/
+ /** Raw value read directly from the Motion Plus. */
+ int16_t gyroYawRaw;
+ int16_t gyroRollRaw;
+ int16_t gyroPitchRaw;
+ /**@}*/
+
+ /**@{*/
+ /** These values are set when the controller is first initialized. */
+ int16_t gyroYawZero;
+ int16_t gyroRollZero;
+ int16_t gyroPitchZero;
+ /**@}*/
+
+ /** @name Wii Balance Board functions */
+
+ /**
+ * Used to get the weight at the specific position on the Wii Balance Board.
+ * @param ::BalanceBoardEnum to read from.
+ * @return Returns the weight in kg.
+ */
+ float getWeight(BalanceBoardEnum pos);
+
+ /**
+ * Used to get total weight on the Wii Balance Board.
+ * @returnReturns the weight in kg.
+ */
+ float getTotalWeight();
+
+ /**
+ * Used to get the raw reading at the specific position on the Wii Balance Board.
+ * @param ::BalanceBoardEnum to read from.
+ * @return Returns the raw reading.
+ */
+ uint16_t getWeightRaw(BalanceBoardEnum pos) {
+ return wiiBalanceBoardRaw[pos];
+ };
+ /**@}*/
+
+#ifdef WIICAMERA
+ /** @name Wiimote IR camera functions
+ * You will have to set ::ENABLE_WII_IR_CAMERA in settings.h to 1 in order use the IR camera.
+ */
+ /** Initialises the camera as per the steps from: http://wiibrew.org/wiki/Wiimote#IR_Camera */
+ void IRinitialize();
+
+ /**
+ * IR object 1 x-position read from the Wii IR camera.
+ * @return The x-position of the object in the range 0-1023.
+ */
+ uint16_t getIRx1() {
+ return IR_object_x1;
+ };
+
+ /**
+ * IR object 1 y-position read from the Wii IR camera.
+ * @return The y-position of the object in the range 0-767.
+ */
+ uint16_t getIRy1() {
+ return IR_object_y1;
+ };
+
+ /**
+ * IR object 1 size read from the Wii IR camera.
+ * @return The size of the object in the range 0-15.
+ */
+ uint8_t getIRs1() {
+ return IR_object_s1;
+ };
+
+ /**
+ * IR object 2 x-position read from the Wii IR camera.
+ * @return The x-position of the object in the range 0-1023.
+ */
+ uint16_t getIRx2() {
+ return IR_object_x2;
+ };
+
+ /**
+ * IR object 2 y-position read from the Wii IR camera.
+ * @return The y-position of the object in the range 0-767.
+ */
+ uint16_t getIRy2() {
+ return IR_object_y2;
+ };
+
+ /**
+ * IR object 2 size read from the Wii IR camera.
+ * @return The size of the object in the range 0-15.
+ */
+ uint8_t getIRs2() {
+ return IR_object_s2;
+ };
+
+ /**
+ * IR object 3 x-position read from the Wii IR camera.
+ * @return The x-position of the object in the range 0-1023.
+ */
+ uint16_t getIRx3() {
+ return IR_object_x3;
+ };
+
+ /**
+ * IR object 3 y-position read from the Wii IR camera.
+ * @return The y-position of the object in the range 0-767.
+ */
+ uint16_t getIRy3() {
+ return IR_object_y3;
+ };
+
+ /**
+ * IR object 3 size read from the Wii IR camera.
+ * @return The size of the object in the range 0-15.
+ */
+ uint8_t getIRs3() {
+ return IR_object_s3;
+ };
+
+ /**
+ * IR object 4 x-position read from the Wii IR camera.
+ * @return The x-position of the object in the range 0-1023.
+ */
+ uint16_t getIRx4() {
+ return IR_object_x4;
+ };
+
+ /**
+ * IR object 4 y-position read from the Wii IR camera.
+ * @return The y-position of the object in the range 0-767.
+ */
+ uint16_t getIRy4() {
+ return IR_object_y4;
+ };
+
+ /**
+ * IR object 4 size read from the Wii IR camera.
+ * @return The size of the object in the range 0-15.
+ */
+ uint8_t getIRs4() {
+ return IR_object_s4;
+ };
+
+ /**
+ * Use this to check if the camera is enabled or not.
+ * If not call WII#IRinitialize to initialize the IR camera.
+ * @return True if it's enabled, false if not.
+ */
+ bool isIRCameraEnabled() {
+ return (wiiState & 0x08);
+ };
+ /**@}*/
+#endif
+
+protected:
+ /** @name BluetoothService implementation */
+ /**
+ * Used to pass acldata to the services.
+ * @param ACLData Incoming acldata.
+ */
+ void ACLData(uint8_t* ACLData);
+ /** Used to run part of the state machine. */
+ void Run();
+ /** Use this to reset the service. */
+ void Reset();
+ /**
+ * Called when the controller is successfully initialized.
+ * Use attachOnInit(void (*funcOnInit)(void)) to call your own function.
+ * This is useful for instance if you want to set the LEDs in a specific way.
+ */
+ void onInit();
+ /**@}*/
+
+private:
+
+ void L2CAP_task(); // L2CAP state machine
+
+ /* Variables filled from HCI event management */
+ bool activeConnection; // Used to indicate if it's already has established a connection
+
+ /* Variables used by high level L2CAP task */
+ uint8_t l2cap_state;
+ uint8_t wii_event_flag; // Used for Wii flags
+
+ uint32_t ButtonState;
+ uint32_t OldButtonState;
+ uint32_t ButtonClickState;
+ uint16_t hatValues[4];
+
+ uint8_t HIDBuffer[3]; // Used to store HID commands
+
+ uint16_t stateCounter;
+ bool unknownExtensionConnected;
+ bool extensionConnected;
+ bool checkBatteryLevel; // Set to true when getBatteryLevel() is called otherwise if should be false
+ bool motionPlusInside; // True if it's a new Wiimote with the Motion Plus extension build into it
+
+ /* L2CAP Channels */
+ uint8_t control_scid[2]; // L2CAP source CID for HID_Control
+ uint8_t control_dcid[2]; // 0x0060
+ uint8_t interrupt_scid[2]; // L2CAP source CID for HID_Interrupt
+ uint8_t interrupt_dcid[2]; // 0x0061
+
+ /* HID Commands */
+ void HID_Command(uint8_t* data, uint8_t nbytes);
+ void setReportMode(bool continuous, uint8_t mode);
+
+ void writeData(uint32_t offset, uint8_t size, uint8_t* data);
+ void initExtension1();
+ void initExtension2();
+
+ void statusRequest(); // Used to update the Wiimote state and battery level
+
+ void readData(uint32_t offset, uint16_t size, bool EEPROM);
+ void readExtensionType();
+ void readCalData();
+ void readWiiBalanceBoardCalibration(); // Used by the library to read the Wii Balance Board calibration values
+
+ void checkMotionPresent(); // Used to see if a Motion Plus is connected to the Wiimote
+ void initMotionPlus();
+ void activateMotionPlus();
+
+ uint16_t wiiBalanceBoardRaw[4]; // Wii Balance Board raw values
+ uint16_t wiiBalanceBoardCal[3][4]; // Wii Balance Board calibration values
+
+ double compPitch; // Fusioned angle using a complimentary filter if the Motion Plus is connected
+ double compRoll; // Fusioned angle using a complimentary filter if the Motion Plus is connected
+
+ bool activateNunchuck;
+ bool motionValuesReset; // This bool is true when the gyro values has been reset
+ uint32_t timer;
+
+ uint8_t wiiState; // Stores the value in l2capinbuf[12] - (0x01: Battery is nearly empty), (0x02: An Extension Controller is connected), (0x04: Speaker enabled), (0x08: IR enabled), (0x10: LED1, 0x20: LED2, 0x40: LED3, 0x80: LED4)
+ uint8_t batteryLevel;
+
+#ifdef WIICAMERA
+ /* Private function and variables for the readings from the IR Camera */
+ void enableIRCamera1(); // Sets bit 2 of output report 13
+ void enableIRCamera2(); // Sets bit 2 of output report 1A
+ void writeSensitivityBlock1();
+ void writeSensitivityBlock2();
+ void write0x08Value();
+ void setWiiModeNumber(uint8_t mode_number);
+
+ uint16_t IR_object_x1; // IR x position 10 bits
+ uint16_t IR_object_y1; // IR y position 10 bits
+ uint8_t IR_object_s1; // IR size value
+ uint16_t IR_object_x2;
+ uint16_t IR_object_y2;
+ uint8_t IR_object_s2;
+ uint16_t IR_object_x3; // IR x position 10 bits
+ uint16_t IR_object_y3; // IR y position 10 bits
+ uint8_t IR_object_s3; // IR size value
+ uint16_t IR_object_x4;
+ uint16_t IR_object_y4;
+ uint8_t IR_object_s4;
+#endif
+};
+#endif
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/WiiCameraReadme.md b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/WiiCameraReadme.md
new file mode 100644
index 000000000..8577d73fb
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/WiiCameraReadme.md
@@ -0,0 +1,13 @@
+Please see <http://wiibrew.org/wiki/Wiimote#IR_Camera> for the complete capabilities of the Wii camera. The IR camera code was written based on the above website and with support from Kristian Lauszus.
+
+This library is large, if you run into memory problems when uploading to the Arduino, disable serial debugging.
+
+To enable the IR camera code, simply set ```ENABLE_WII_IR_CAMERA``` to 1 in [settings.h](settings.h).
+
+This library implements the following settings:
+
+* Report sensitivity mode: 00 00 00 00 00 00 90 00 41 40 00 Suggested by inio (high sensitivity)
+* Data Format: Extended mode (0x03). Full mode is not working yet. The output reports 0x3e and 0x3f need tampering with
+ * In this mode the camera outputs x and y coordinates and a size dimension for the 4 brightest points.
+
+Again, read through <http://wiibrew.org/wiki/Wiimote#IR_Camera> to get an understanding of the camera and its settings.
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXOLD.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXOLD.cpp
new file mode 100644
index 000000000..78e6e9a5f
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXOLD.cpp
@@ -0,0 +1,337 @@
+/* Copyright (C) 2013 Kristian Lauszus, TKJ Electronics. All rights reserved.
+
+ This software may be distributed and modified under the terms of the GNU
+ General Public License version 2 (GPL2) as published by the Free Software
+ Foundation and appearing in the file GPL2.TXT included in the packaging of
+ this file. Please note that GPL2 Section 2[b] requires that all works based
+ on this software must also be made publicly available under the terms of
+ the GPL2 ("Copyleft").
+
+ Contact information
+ -------------------
+
+ Kristian Lauszus, TKJ Electronics
+ Web : http://www.tkjelectronics.com
+ e-mail : kristianl@tkjelectronics.com
+ */
+
+#include "XBOXOLD.h"
+// To enable serial debugging see "settings.h"
+//#define EXTRADEBUG // Uncomment to get even more debugging data
+//#define PRINTREPORT // Uncomment to print the report send by the Xbox controller
+
+/** Buttons on the controllers */
+const uint8_t XBOXOLD_BUTTONS[] PROGMEM = {
+ 0x01, // UP
+ 0x08, // RIGHT
+ 0x02, // DOWN
+ 0x04, // LEFT
+
+ 0x20, // BACK
+ 0x10, // START
+ 0x40, // L3
+ 0x80, // R3
+
+ // A, B, X, Y, BLACK, WHITE, L1, and R1 are analog buttons
+ 4, // BLACK
+ 5, // WHTIE
+ 6, // L1
+ 7, // R1
+
+ 1, // B
+ 0, // A
+ 2, // X
+ 3, // Y
+};
+
+XBOXOLD::XBOXOLD(USB *p) :
+pUsb(p), // pointer to USB class instance - mandatory
+bAddress(0), // device address - mandatory
+bPollEnable(false) { // don't start polling before dongle is connected
+ for(uint8_t i = 0; i < XBOX_MAX_ENDPOINTS; i++) {
+ epInfo[i].epAddr = 0;
+ epInfo[i].maxPktSize = (i) ? 0 : 8;
+ epInfo[i].epAttribs = 0;
+ epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
+ }
+
+ if(pUsb) // register in USB subsystem
+ pUsb->RegisterDeviceClass(this); //set devConfig[] entry
+}
+
+uint8_t XBOXOLD::Init(uint8_t parent, uint8_t port, bool lowspeed) {
+ uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
+ USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
+ uint8_t rcode;
+ UsbDevice *p = NULL;
+ EpInfo *oldep_ptr = NULL;
+ uint16_t PID;
+ uint16_t VID;
+
+ // get memory address of USB device address pool
+ AddressPool &addrPool = pUsb->GetAddressPool();
+#ifdef EXTRADEBUG
+ Notify(PSTR("\r\nXBOXUSB Init"), 0x80);
+#endif
+ // check if address has already been assigned to an instance
+ if(bAddress) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nAddress in use"), 0x80);
+#endif
+ return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
+ }
+
+ // Get pointer to pseudo device with address 0 assigned
+ p = addrPool.GetUsbDevicePtr(0);
+
+ if(!p) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nAddress not found"), 0x80);
+#endif
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+ }
+
+ if(!p->epinfo) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nepinfo is null"), 0x80);
+#endif
+ return USB_ERROR_EPINFO_IS_NULL;
+ }
+
+ // Save old pointer to EP_RECORD of address 0
+ oldep_ptr = p->epinfo;
+
+ // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
+ p->epinfo = epInfo;
+
+ p->lowspeed = lowspeed;
+
+ // Get device descriptor
+ rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data
+ // Restore p->epinfo
+ p->epinfo = oldep_ptr;
+
+ if(rcode)
+ goto FailGetDevDescr;
+
+ VID = udd->idVendor;
+ PID = udd->idProduct;
+
+ if((VID != XBOX_VID && VID != MADCATZ_VID && VID != JOYTECH_VID) || (PID != XBOX_OLD_PID1 && PID != XBOX_OLD_PID2 && PID != XBOX_OLD_PID3 && PID != XBOX_OLD_PID4)) // Check if VID and PID match
+ goto FailUnknownDevice;
+
+ // Allocate new address according to device class
+ bAddress = addrPool.AllocAddress(parent, false, port);
+
+ if(!bAddress)
+ return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
+
+ // Extract Max Packet Size from device descriptor
+ epInfo[0].maxPktSize = udd->bMaxPacketSize0;
+
+ // Assign new address to the device
+ rcode = pUsb->setAddr(0, 0, bAddress);
+ if(rcode) {
+ p->lowspeed = false;
+ addrPool.FreeAddress(bAddress);
+ bAddress = 0;
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nsetAddr: "), 0x80);
+ D_PrintHex<uint8_t > (rcode, 0x80);
+#endif
+ return rcode;
+ }
+#ifdef EXTRADEBUG
+ Notify(PSTR("\r\nAddr: "), 0x80);
+ D_PrintHex<uint8_t > (bAddress, 0x80);
+#endif
+ //delay(300); // Spec says you should wait at least 200ms
+
+ p->lowspeed = false;
+
+ //get pointer to assigned address record
+ p = addrPool.GetUsbDevicePtr(bAddress);
+ if(!p)
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+ p->lowspeed = lowspeed;
+
+ // Assign epInfo to epinfo pointer - only EP0 is known
+ rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
+ if(rcode)
+ goto FailSetDevTblEntry;
+
+ /* The application will work in reduced host mode, so we can save program and data
+ memory space. After verifying the VID we will use known values for the
+ configuration values for device, interface, endpoints and HID for the XBOX controllers */
+
+ /* Initialize data structures for endpoints of device */
+ epInfo[ XBOX_INPUT_PIPE ].epAddr = 0x01; // XBOX report endpoint
+ epInfo[ XBOX_INPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;
+ epInfo[ XBOX_INPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
+ epInfo[ XBOX_INPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE;
+ epInfo[ XBOX_INPUT_PIPE ].bmSndToggle = 0;
+ epInfo[ XBOX_INPUT_PIPE ].bmRcvToggle = 0;
+ epInfo[ XBOX_OUTPUT_PIPE ].epAddr = 0x02; // XBOX output endpoint
+ epInfo[ XBOX_OUTPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;
+ epInfo[ XBOX_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
+ epInfo[ XBOX_OUTPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE;
+ epInfo[ XBOX_OUTPUT_PIPE ].bmSndToggle = 0;
+ epInfo[ XBOX_OUTPUT_PIPE ].bmRcvToggle = 0;
+
+ rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo);
+ if(rcode)
+ goto FailSetDevTblEntry;
+
+ delay(200); // Give time for address change
+
+ rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1);
+ if(rcode)
+ goto FailSetConfDescr;
+
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nXbox Controller Connected\r\n"), 0x80);
+#endif
+ if(pFuncOnInit)
+ pFuncOnInit(); // Call the user function
+ XboxConnected = true;
+ bPollEnable = true;
+ return 0; // Successful configuration
+
+ /* Diagnostic messages */
+FailGetDevDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailGetDevDescr();
+ goto Fail;
+#endif
+
+FailSetDevTblEntry:
+#ifdef DEBUG_USB_HOST
+ NotifyFailSetDevTblEntry();
+ goto Fail;
+#endif
+
+FailSetConfDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailSetConfDescr();
+#endif
+ goto Fail;
+
+FailUnknownDevice:
+#ifdef DEBUG_USB_HOST
+ NotifyFailUnknownDevice(VID, PID);
+#endif
+ rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
+
+Fail:
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nXbox Init Failed, error code: "), 0x80);
+ NotifyFail(rcode);
+#endif
+ Release();
+ return rcode;
+}
+
+/* Performs a cleanup after failed Init() attempt */
+uint8_t XBOXOLD::Release() {
+ XboxConnected = false;
+ pUsb->GetAddressPool().FreeAddress(bAddress);
+ bAddress = 0;
+ bPollEnable = false;
+ return 0;
+}
+
+uint8_t XBOXOLD::Poll() {
+ if(!bPollEnable)
+ return 0;
+ uint16_t BUFFER_SIZE = EP_MAXPKTSIZE;
+ pUsb->inTransfer(bAddress, epInfo[ XBOX_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1
+ readReport();
+#ifdef PRINTREPORT
+ printReport(BUFFER_SIZE); // Uncomment "#define PRINTREPORT" to print the report send by the Xbox controller
+#endif
+ return 0;
+}
+
+void XBOXOLD::readReport() {
+ ButtonState = readBuf[2];
+
+ for(uint8_t i = 0; i < sizeof (buttonValues); i++)
+ buttonValues[i] = readBuf[i + 4]; // A, B, X, Y, BLACK, WHITE, L1, and R1
+
+ hatValue[LeftHatX] = (int16_t)(((uint16_t)readBuf[12] << 8) | readBuf[13]);
+ hatValue[LeftHatY] = (int16_t)(((uint16_t)readBuf[14] << 8) | readBuf[15]);
+ hatValue[RightHatX] = (int16_t)(((uint16_t)readBuf[16] << 8) | readBuf[17]);
+ hatValue[RightHatY] = (int16_t)(((uint16_t)readBuf[18] << 8) | readBuf[19]);
+
+ //Notify(PSTR("\r\nButtonState"), 0x80);
+ //PrintHex<uint8_t>(ButtonState, 0x80);
+
+ if(ButtonState != OldButtonState || memcmp(buttonValues, oldButtonValues, sizeof (buttonValues)) != 0) {
+ ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable
+ OldButtonState = ButtonState;
+
+ for(uint8_t i = 0; i < sizeof (buttonValues); i++) {
+ if(oldButtonValues[i] == 0 && buttonValues[i] != 0)
+ buttonClicked[i] = true; // Update A, B, X, Y, BLACK, WHITE, L1, and R1 click state
+ oldButtonValues[i] = buttonValues[i];
+ }
+ }
+}
+
+void XBOXOLD::printReport(uint16_t length) { //Uncomment "#define PRINTREPORT" to print the report send by the Xbox controller
+#ifdef PRINTREPORT
+ if(readBuf == NULL)
+ return;
+ for(uint8_t i = 0; i < length; i++) {
+ D_PrintHex<uint8_t > (readBuf[i], 0x80);
+ Notify(PSTR(" "), 0x80);
+ }
+ Notify(PSTR("\r\n"), 0x80);
+#endif
+}
+
+uint8_t XBOXOLD::getButtonPress(ButtonEnum b) {
+ uint8_t button = pgm_read_byte(&XBOXOLD_BUTTONS[(uint8_t)b]);
+ if(b == A || b == B || b == X || b == Y || b == BLACK || b == WHITE || b == L1 || b == R1) // A, B, X, Y, BLACK, WHITE, L1, and R1 are analog buttons
+ return buttonValues[button]; // Analog buttons
+ return (ButtonState & button); // Digital buttons
+}
+
+bool XBOXOLD::getButtonClick(ButtonEnum b) {
+ uint8_t button = pgm_read_byte(&XBOXOLD_BUTTONS[(uint8_t)b]);
+ if(b == A || b == B || b == X || b == Y || b == BLACK || b == WHITE || b == L1 || b == R1) { // A, B, X, Y, BLACK, WHITE, L1, and R1 are analog buttons
+ if(buttonClicked[button]) {
+ buttonClicked[button] = false;
+ return true;
+ }
+ return false;
+ }
+
+ bool click = (ButtonClickState & button);
+ ButtonClickState &= ~button; // clear "click" event
+ return click;
+}
+
+int16_t XBOXOLD::getAnalogHat(AnalogHatEnum a) {
+ return hatValue[a];
+}
+
+/* Xbox Controller commands */
+void XBOXOLD::XboxCommand(uint8_t* data, uint16_t nbytes) {
+ //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x00), Report Type (Output 0x02), interface (0x00), datalength, datalength, data)
+ pUsb->ctrlReq(bAddress, epInfo[XBOX_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL);
+}
+
+void XBOXOLD::setRumbleOn(uint8_t lValue, uint8_t rValue) {
+ uint8_t writeBuf[6];
+
+ writeBuf[0] = 0x00;
+ writeBuf[1] = 0x06;
+ writeBuf[2] = 0x00;
+ writeBuf[3] = rValue; // small weight
+ writeBuf[4] = 0x00;
+ writeBuf[5] = lValue; // big weight
+
+ XboxCommand(writeBuf, 6);
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXOLD.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXOLD.h
new file mode 100644
index 000000000..9a36b5cca
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXOLD.h
@@ -0,0 +1,185 @@
+/* Copyright (C) 2013 Kristian Lauszus, TKJ Electronics. All rights reserved.
+
+ This software may be distributed and modified under the terms of the GNU
+ General Public License version 2 (GPL2) as published by the Free Software
+ Foundation and appearing in the file GPL2.TXT included in the packaging of
+ this file. Please note that GPL2 Section 2[b] requires that all works based
+ on this software must also be made publicly available under the terms of
+ the GPL2 ("Copyleft").
+
+ Contact information
+ -------------------
+
+ Kristian Lauszus, TKJ Electronics
+ Web : http://www.tkjelectronics.com
+ e-mail : kristianl@tkjelectronics.com
+ */
+
+#ifndef _xboxold_h_
+#define _xboxold_h_
+
+#include "Usb.h"
+#include "hid.h"
+#include "controllerEnums.h"
+
+/* Data Xbox taken from descriptors */
+#define EP_MAXPKTSIZE 32 // Max size for data via USB
+
+/* Names we give to the 3 Xbox pipes */
+#define XBOX_CONTROL_PIPE 0
+#define XBOX_INPUT_PIPE 1
+#define XBOX_OUTPUT_PIPE 2
+
+// PID and VID of the different devices
+#define XBOX_VID 0x045E // Microsoft Corporation
+#define MADCATZ_VID 0x1BAD // For unofficial Mad Catz controllers
+#define JOYTECH_VID 0x162E // For unofficial Joytech controllers
+
+#define XBOX_OLD_PID1 0x0202 // Original Microsoft Xbox controller (US)
+#define XBOX_OLD_PID2 0x0285 // Original Microsoft Xbox controller (Japan)
+#define XBOX_OLD_PID3 0x0287 // Microsoft Microsoft Xbox Controller S
+#define XBOX_OLD_PID4 0x0289 // Smaller Microsoft Xbox controller (US)
+
+#define XBOX_MAX_ENDPOINTS 3
+
+/** This class implements support for a the original Xbox controller via USB. */
+class XBOXOLD : public USBDeviceConfig {
+public:
+ /**
+ * Constructor for the XBOXOLD class.
+ * @param pUsb Pointer to USB class instance.
+ */
+ XBOXOLD(USB *pUsb);
+
+ /** @name USBDeviceConfig implementation */
+ /**
+ * Initialize the Xbox Controller.
+ * @param parent Hub number.
+ * @param port Port number on the hub.
+ * @param lowspeed Speed of the device.
+ * @return 0 on success.
+ */
+ uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
+ /**
+ * Release the USB device.
+ * @return 0 on success.
+ */
+ uint8_t Release();
+ /**
+ * Poll the USB Input endpoins and run the state machines.
+ * @return 0 on success.
+ */
+ uint8_t Poll();
+
+ /**
+ * Get the device address.
+ * @return The device address.
+ */
+ virtual uint8_t GetAddress() {
+ return bAddress;
+ };
+
+ /**
+ * Used to check if the controller has been initialized.
+ * @return True if it's ready.
+ */
+ virtual bool isReady() {
+ return bPollEnable;
+ };
+
+ /**
+ * Used by the USB core to check what this driver support.
+ * @param vid The device's VID.
+ * @param pid The device's PID.
+ * @return Returns true if the device's VID and PID matches this driver.
+ */
+ virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {
+ return ((vid == XBOX_VID || vid == MADCATZ_VID || vid == JOYTECH_VID) && (pid == XBOX_OLD_PID1 || pid == XBOX_OLD_PID2 || pid == XBOX_OLD_PID3 || pid == XBOX_OLD_PID4));
+ };
+ /**@}*/
+
+ /** @name Xbox Controller functions */
+ /**
+ * getButtonPress(ButtonEnum b) will return true as long as the button is held down.
+ *
+ * While getButtonClick(ButtonEnum b) will only return it once.
+ *
+ * So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b),
+ * but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b).
+ * @param b ::ButtonEnum to read.
+ * @return getButtonClick(ButtonEnum b) will return a bool, while getButtonPress(ButtonEnum b) will return a byte if reading ::L2 or ::R2.
+ */
+ uint8_t getButtonPress(ButtonEnum b);
+ bool getButtonClick(ButtonEnum b);
+ /**@}*/
+
+ /** @name Xbox Controller functions */
+ /**
+ * Return the analog value from the joysticks on the controller.
+ * @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY.
+ * @return Returns a signed 16-bit integer.
+ */
+ int16_t getAnalogHat(AnalogHatEnum a);
+
+ /** Turn rumble off the controller. */
+ void setRumbleOff() {
+ setRumbleOn(0, 0);
+ };
+ /**
+ * Turn rumble on.
+ * @param lValue Left motor (big weight) inside the controller.
+ * @param rValue Right motor (small weight) inside the controller.
+ */
+ void setRumbleOn(uint8_t lValue, uint8_t rValue);
+
+ /**
+ * Used to call your own function when the controller is successfully initialized.
+ * @param funcOnInit Function to call.
+ */
+ void attachOnInit(void (*funcOnInit)(void)) {
+ pFuncOnInit = funcOnInit;
+ };
+ /**@}*/
+
+ /** True if a Xbox controller is connected. */
+ bool XboxConnected;
+
+protected:
+ /** Pointer to USB class instance. */
+ USB *pUsb;
+ /** Device address. */
+ uint8_t bAddress;
+ /** Endpoint info structure. */
+ EpInfo epInfo[XBOX_MAX_ENDPOINTS];
+
+private:
+ /**
+ * Called when the controller is successfully initialized.
+ * Use attachOnInit(void (*funcOnInit)(void)) to call your own function.
+ * This is useful for instance if you want to set the LEDs in a specific way.
+ */
+ void (*pFuncOnInit)(void); // Pointer to function called in onInit()
+
+ bool bPollEnable;
+
+ /* Variables to store the digital buttons */
+ uint8_t ButtonState;
+ uint8_t OldButtonState;
+ uint8_t ButtonClickState;
+
+ /* Variables to store the analog buttons */
+ uint8_t buttonValues[8]; // A, B, X, Y, BLACK, WHITE, L1, and R1
+ uint8_t oldButtonValues[8];
+ bool buttonClicked[8];
+
+ int16_t hatValue[4]; // Joystick values
+
+ uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data
+
+ void readReport(); // Read incoming data
+ void printReport(uint16_t length); // Print incoming date
+
+ /* Private commands */
+ void XboxCommand(uint8_t* data, uint16_t nbytes);
+};
+#endif
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXONE.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXONE.cpp
new file mode 100644
index 000000000..2159c0528
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXONE.cpp
@@ -0,0 +1,374 @@
+/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
+ Copyright (C) 2015 guruthree
+
+ This software may be distributed and modified under the terms of the GNU
+ General Public License version 2 (GPL2) as published by the Free Software
+ Foundation and appearing in the file GPL2.TXT included in the packaging of
+ this file. Please note that GPL2 Section 2[b] requires that all works based
+ on this software must also be made publicly available under the terms of
+ the GPL2 ("Copyleft").
+
+ Contact information
+ -------------------
+
+ Kristian Lauszus, TKJ Electronics
+ Web : http://www.tkjelectronics.com
+ e-mail : kristianl@tkjelectronics.com
+
+ guruthree
+ Web : https://github.com/guruthree/
+ */
+
+#include "XBOXONE.h"
+// To enable serial debugging see "settings.h"
+//#define EXTRADEBUG // Uncomment to get even more debugging data
+//#define PRINTREPORT // Uncomment to print the report send by the Xbox ONE Controller
+
+XBOXONE::XBOXONE(USB *p) :
+pUsb(p), // pointer to USB class instance - mandatory
+bAddress(0), // device address - mandatory
+bPollEnable(false) { // don't start polling before dongle is connected
+ for(uint8_t i = 0; i < XBOX_MAX_ENDPOINTS; i++) {
+ epInfo[i].epAddr = 0;
+ epInfo[i].maxPktSize = (i) ? 0 : 8;
+ epInfo[i].epAttribs = 0;
+ epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
+ }
+
+ if(pUsb) // register in USB subsystem
+ pUsb->RegisterDeviceClass(this); //set devConfig[] entry
+}
+
+uint8_t XBOXONE::Init(uint8_t parent, uint8_t port, bool lowspeed) {
+ uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
+ USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
+ uint8_t rcode;
+ UsbDevice *p = NULL;
+ EpInfo *oldep_ptr = NULL;
+ uint16_t PID;
+ uint16_t VID;
+
+ // get memory address of USB device address pool
+ AddressPool &addrPool = pUsb->GetAddressPool();
+#ifdef EXTRADEBUG
+ Notify(PSTR("\r\nXBOXONE Init"), 0x80);
+#endif
+ // check if address has already been assigned to an instance
+ if(bAddress) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nAddress in use"), 0x80);
+#endif
+ return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
+ }
+
+ // Get pointer to pseudo device with address 0 assigned
+ p = addrPool.GetUsbDevicePtr(0);
+
+ if(!p) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nAddress not found"), 0x80);
+#endif
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+ }
+
+ if(!p->epinfo) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nepinfo is null"), 0x80);
+#endif
+ return USB_ERROR_EPINFO_IS_NULL;
+ }
+
+ // Save old pointer to EP_RECORD of address 0
+ oldep_ptr = p->epinfo;
+
+ // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
+ p->epinfo = epInfo;
+
+ p->lowspeed = lowspeed;
+
+ // Get device descriptor
+ rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data
+ // Restore p->epinfo
+ p->epinfo = oldep_ptr;
+
+ if(rcode)
+ goto FailGetDevDescr;
+
+ VID = udd->idVendor;
+ PID = udd->idProduct;
+
+ if(!VIDPIDOK(VID, PID)) // Check VID
+ goto FailUnknownDevice;
+
+ // Allocate new address according to device class
+ bAddress = addrPool.AllocAddress(parent, false, port);
+
+ if(!bAddress)
+ return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
+
+ // Extract Max Packet Size from device descriptor
+ epInfo[0].maxPktSize = udd->bMaxPacketSize0;
+
+ // Assign new address to the device
+ rcode = pUsb->setAddr(0, 0, bAddress);
+ if(rcode) {
+ p->lowspeed = false;
+ addrPool.FreeAddress(bAddress);
+ bAddress = 0;
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nsetAddr: "), 0x80);
+ D_PrintHex<uint8_t > (rcode, 0x80);
+#endif
+ return rcode;
+ }
+#ifdef EXTRADEBUG
+ Notify(PSTR("\r\nAddr: "), 0x80);
+ D_PrintHex<uint8_t > (bAddress, 0x80);
+#endif
+ //delay(300); // Spec says you should wait at least 200ms
+
+ p->lowspeed = false;
+
+ //get pointer to assigned address record
+ p = addrPool.GetUsbDevicePtr(bAddress);
+ if(!p)
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+ p->lowspeed = lowspeed;
+
+ // Assign epInfo to epinfo pointer - only EP0 is known
+ rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
+ if(rcode)
+ goto FailSetDevTblEntry;
+
+ /* The application will work in reduced host mode, so we can save program and data
+ memory space. After verifying the VID we will use known values for the
+ configuration values for device, interface, endpoints and HID for the XBOXONE Controllers */
+
+ /* Initialize data structures for endpoints of device */
+ epInfo[ XBOX_OUTPUT_PIPE ].epAddr = 0x01; // XBOX one output endpoint
+ epInfo[ XBOX_OUTPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;
+ epInfo[ XBOX_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
+ epInfo[ XBOX_OUTPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE;
+ epInfo[ XBOX_OUTPUT_PIPE ].bmSndToggle = 0;
+ epInfo[ XBOX_OUTPUT_PIPE ].bmRcvToggle = 0;
+ epInfo[ XBOX_INPUT_PIPE ].epAddr = 0x01; // XBOX one input endpoint
+ epInfo[ XBOX_INPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;
+ epInfo[ XBOX_INPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
+ epInfo[ XBOX_INPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE;
+ epInfo[ XBOX_INPUT_PIPE ].bmSndToggle = 0;
+ epInfo[ XBOX_INPUT_PIPE ].bmRcvToggle = 0;
+
+ rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo);
+ if(rcode)
+ goto FailSetDevTblEntry;
+
+ delay(200); // Give time for address change
+
+ rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1);
+ if(rcode)
+ goto FailSetConfDescr;
+
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nXbox One Controller Connected\r\n"), 0x80);
+#endif
+
+ delay(200); // let things settle
+
+ // initialize the controller for input
+ writeBuf[0] = 0x05;
+ writeBuf[1] = 0x20;
+ rcode = XboxCommand(writeBuf, 2);
+ if (rcode)
+ goto Fail;
+
+ onInit();
+ XboxOneConnected = true;
+ bPollEnable = true;
+ return 0; // Successful configuration
+
+ /* Diagnostic messages */
+FailGetDevDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailGetDevDescr();
+ goto Fail;
+#endif
+
+FailSetDevTblEntry:
+#ifdef DEBUG_USB_HOST
+ NotifyFailSetDevTblEntry();
+ goto Fail;
+#endif
+
+FailSetConfDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailSetConfDescr();
+#endif
+ goto Fail;
+
+FailUnknownDevice:
+#ifdef DEBUG_USB_HOST
+ NotifyFailUnknownDevice(VID, PID);
+#endif
+ rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
+
+Fail:
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nXbox One Init Failed, error code: "), 0x80);
+ NotifyFail(rcode);
+#endif
+ Release();
+ return rcode;
+}
+
+/* Performs a cleanup after failed Init() attempt */
+uint8_t XBOXONE::Release() {
+ XboxOneConnected = false;
+ pUsb->GetAddressPool().FreeAddress(bAddress);
+ bAddress = 0;
+ bPollEnable = false;
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nXbox One Controller Disconnected\r\n"), 0x80);
+#endif
+ return 0;
+}
+
+uint8_t XBOXONE::Poll() {
+ if(!bPollEnable)
+ return 0;
+ uint16_t BUFFER_SIZE = EP_MAXPKTSIZE;
+ uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ XBOX_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf);
+ if (!rcode) {
+ readReport();
+#ifdef PRINTREPORT
+ printReport(); // Uncomment "#define PRINTREPORT" to print the report send by the Xbox ONE Controller
+#endif
+ }
+#ifdef DEBUG_USB_HOST
+ else if (rcode != 0x04) { // not a matter of no update to send
+ Notify(PSTR("\r\nXbox One Poll Failed, error code: "), 0x80);
+ NotifyFail(rcode);
+ }
+#endif
+ return rcode;
+}
+
+void XBOXONE::readReport() {
+ if(readBuf == NULL)
+ return;
+ if(readBuf[0] == 0x07) {
+ // The XBOX button has a separate message
+ if(readBuf[4] == 1)
+ ButtonState |= XBOX_BUTTONS[XBOX];
+ else
+ ButtonState &= ~XBOX_BUTTONS[XBOX];
+ }
+ if(readBuf[0] != 0x20) { // Check if it's the correct report, otherwise return - the controller also sends different status reports
+#ifdef EXTRADEBUG
+ Notify(PSTR("\r\nXbox Poll: "), 0x80);
+ D_PrintHex<uint8_t > (readBuf[0], 0x80); // 0x03 is a heart beat report!
+#endif
+ return;
+ }
+
+ uint16_t xbox = ButtonState & XBOX_BUTTONS[XBOX]; // Since the XBOX button is separate, save it and add it back in
+ // xbox button from before, dpad, abxy, start/back, sync, stick click, shoulder buttons
+ ButtonState = xbox | (((uint16_t)readBuf[5] & 0xF) << 8) | (readBuf[4] & 0xF0) | (((uint16_t)readBuf[4] & 0x0C) << 10) | ((readBuf[4] & 0x01) << 3) | (((uint16_t)readBuf[5] & 0xC0) << 8) | ((readBuf[5] & 0x30) >> 4);
+
+ triggerValue[0] = (uint16_t)(((uint16_t)readBuf[7] << 8) | readBuf[6]);
+ triggerValue[1] = (uint16_t)(((uint16_t)readBuf[9] << 8) | readBuf[8]);
+
+ hatValue[LeftHatX] = (int16_t)(((uint16_t)readBuf[11] << 8) | readBuf[10]);
+ hatValue[LeftHatY] = (int16_t)(((uint16_t)readBuf[13] << 8) | readBuf[12]);
+ hatValue[RightHatX] = (int16_t)(((uint16_t)readBuf[15] << 8) | readBuf[14]);
+ hatValue[RightHatY] = (int16_t)(((uint16_t)readBuf[17] << 8) | readBuf[16]);
+
+ //Notify(PSTR("\r\nButtonState"), 0x80);
+ //PrintHex<uint16_t>(ButtonState, 0x80);
+
+ if(ButtonState != OldButtonState) {
+ ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable
+ OldButtonState = ButtonState;
+ }
+
+ // Handle click detection for triggers
+ if(triggerValue[0] != 0 && triggerValueOld[0] == 0)
+ L2Clicked = true;
+ triggerValueOld[0] = triggerValue[0];
+ if(triggerValue[1] != 0 && triggerValueOld[1] == 0)
+ R2Clicked = true;
+ triggerValueOld[1] = triggerValue[1];
+}
+
+void XBOXONE::printReport() { //Uncomment "#define PRINTREPORT" to print the report send by the Xbox ONE Controller
+#ifdef PRINTREPORT
+ if(readBuf == NULL)
+ return;
+ for(uint8_t i = 0; i < XBOX_REPORT_BUFFER_SIZE; i++) {
+ D_PrintHex<uint8_t > (readBuf[i], 0x80);
+ Notify(PSTR(" "), 0x80);
+ }
+ Notify(PSTR("\r\n"), 0x80);
+#endif
+}
+
+uint16_t XBOXONE::getButtonPress(ButtonEnum b) {
+ if(b == L2) // These are analog buttons
+ return triggerValue[0];
+ else if(b == R2)
+ return triggerValue[1];
+ return (bool)(ButtonState & ((uint16_t)pgm_read_word(&XBOX_BUTTONS[(uint8_t)b])));
+}
+
+bool XBOXONE::getButtonClick(ButtonEnum b) {
+ if(b == L2) {
+ if(L2Clicked) {
+ L2Clicked = false;
+ return true;
+ }
+ return false;
+ } else if(b == R2) {
+ if(R2Clicked) {
+ R2Clicked = false;
+ return true;
+ }
+ return false;
+ }
+ uint16_t button = pgm_read_word(&XBOX_BUTTONS[(uint8_t)b]);
+ bool click = (ButtonClickState & button);
+ ButtonClickState &= ~button; // clear "click" event
+ return click;
+}
+
+int16_t XBOXONE::getAnalogHat(AnalogHatEnum a) {
+ return hatValue[a];
+}
+
+/* Xbox Controller commands */
+uint8_t XBOXONE::XboxCommand(uint8_t* data, uint16_t nbytes) {
+ uint8_t rcode = pUsb->outTransfer(bAddress, epInfo[ XBOX_OUTPUT_PIPE ].epAddr, nbytes, data);
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nXboxCommand, Return: "), 0x80);
+ D_PrintHex<uint8_t > (rcode, 0x80);
+#endif
+ return rcode;
+}
+
+void XBOXONE::onInit() {
+ // a short buzz to show the controller is active
+ writeBuf[0] = 0x09;
+ writeBuf[1] = 0x08;
+ writeBuf[2] = 0x00;
+ writeBuf[3] = 0x09;
+ writeBuf[4] = 0x00;
+ writeBuf[5] = 0x0f;
+ writeBuf[6] = 0x04;
+ writeBuf[7] = 0x04;
+ writeBuf[8] = 0x20;
+ writeBuf[9] = 0x20;
+ writeBuf[10] = 0x80;
+ XboxCommand(writeBuf, 11);
+
+ if(pFuncOnInit)
+ pFuncOnInit(); // Call the user function
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXONE.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXONE.h
new file mode 100644
index 000000000..11710fcf1
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXONE.h
@@ -0,0 +1,172 @@
+/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
+ Copyright (C) 2015 guruthree
+
+ This software may be distributed and modified under the terms of the GNU
+ General Public License version 2 (GPL2) as published by the Free Software
+ Foundation and appearing in the file GPL2.TXT included in the packaging of
+ this file. Please note that GPL2 Section 2[b] requires that all works based
+ on this software must also be made publicly available under the terms of
+ the GPL2 ("Copyleft").
+
+ Contact information
+ -------------------
+
+ Kristian Lauszus, TKJ Electronics
+ Web : http://www.tkjelectronics.com
+ e-mail : kristianl@tkjelectronics.com
+
+ guruthree
+ Web : https://github.com/guruthree/
+ */
+
+
+#ifndef _xboxone_h_
+#define _xboxone_h_
+
+#include "Usb.h"
+#include "xboxEnums.h"
+
+/* Data Xbox ONE taken from descriptors */
+#define EP_MAXPKTSIZE 32 // max size for data via USB
+
+/* Names we give to the 3 XboxONE pipes */
+#define XBOX_CONTROL_PIPE 0
+#define XBOX_OUTPUT_PIPE 1
+#define XBOX_INPUT_PIPE 2
+
+// PID and VID of the different devices
+#define XBOX_VID 0x045E // Microsoft Corporation
+#define XBOX_ONE_PID 0x02D1 // Microsoft One Wired controller
+
+#define XBOX_REPORT_BUFFER_SIZE 14 // Size of the input report buffer
+
+#define XBOX_MAX_ENDPOINTS 3
+
+/** This class implements support for a Xbox ONE controller connected via USB. */
+class XBOXONE : public USBDeviceConfig {
+public:
+ /**
+ * Constructor for the XBOXONE class.
+ * @param pUsb Pointer to USB class instance.
+ */
+ XBOXONE(USB *pUsb);
+
+ /** @name USBDeviceConfig implementation */
+ /**
+ * Initialize the Xbox Controller.
+ * @param parent Hub number.
+ * @param port Port number on the hub.
+ * @param lowspeed Speed of the device.
+ * @return 0 on success.
+ */
+ virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
+ /**
+ * Release the USB device.
+ * @return 0 on success.
+ */
+ virtual uint8_t Release();
+ /**
+ * Poll the USB Input endpoins and run the state machines.
+ * @return 0 on success.
+ */
+ virtual uint8_t Poll();
+
+ /**
+ * Get the device address.
+ * @return The device address.
+ */
+ virtual uint8_t GetAddress() {
+ return bAddress;
+ };
+
+ /**
+ * Used to check if the controller has been initialized.
+ * @return True if it's ready.
+ */
+ virtual bool isReady() {
+ return bPollEnable;
+ };
+
+ /**
+ * Used by the USB core to check what this driver support.
+ * @param vid The device's VID.
+ * @param pid The device's PID.
+ * @return Returns true if the device's VID and PID matches this driver.
+ */
+ virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {
+ return (vid == XBOX_VID && pid == XBOX_ONE_PID);
+ };
+ /**@}*/
+
+ /** @name Xbox Controller functions */
+ /**
+ * getButtonPress(ButtonEnum b) will return true as long as the button is held down.
+ *
+ * While getButtonClick(ButtonEnum b) will only return it once.
+ *
+ * So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b),
+ * but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b).
+ * @param b ::ButtonEnum to read.
+ * @return getButtonClick(ButtonEnum b) will return a bool, while getButtonPress(ButtonEnum b) will return a word if reading ::L2 or ::R2.
+ */
+ uint16_t getButtonPress(ButtonEnum b);
+ bool getButtonClick(ButtonEnum b);
+
+ /**
+ * Return the analog value from the joysticks on the controller.
+ * @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY.
+ * @return Returns a signed 16-bit integer.
+ */
+ int16_t getAnalogHat(AnalogHatEnum a);
+
+ /**
+ * Used to call your own function when the controller is successfully initialized.
+ * @param funcOnInit Function to call.
+ */
+ void attachOnInit(void (*funcOnInit)(void)) {
+ pFuncOnInit = funcOnInit;
+ };
+ /**@}*/
+
+ /** True if a Xbox ONE controller is connected. */
+ bool XboxOneConnected;
+
+protected:
+ /** Pointer to USB class instance. */
+ USB *pUsb;
+ /** Device address. */
+ uint8_t bAddress;
+ /** Endpoint info structure. */
+ EpInfo epInfo[XBOX_MAX_ENDPOINTS];
+
+private:
+ /**
+ * Called when the controller is successfully initialized.
+ * Use attachOnInit(void (*funcOnInit)(void)) to call your own function.
+ */
+ void onInit();
+ void (*pFuncOnInit)(void); // Pointer to function called in onInit()
+
+ bool bPollEnable;
+
+ /* Variables to store the buttons */
+ uint16_t ButtonState;
+ uint16_t OldButtonState;
+ uint16_t ButtonClickState;
+ int16_t hatValue[4];
+ uint16_t triggerValue[2];
+ uint16_t triggerValueOld[2];
+
+ bool L2Clicked; // These buttons are analog, so we use we use these bools to check if they where clicked or not
+ bool R2Clicked;
+
+ uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data
+ uint8_t writeBuf[12]; // General purpose buffer for output data
+
+ void readReport(); // read incoming data
+ void printReport(); // print incoming date - Uncomment for debugging
+
+ /* Private commands */
+ uint8_t XboxCommand(uint8_t* data, uint16_t nbytes);
+};
+#endif
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXRECV.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXRECV.cpp
new file mode 100644
index 000000000..41f1ff581
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXRECV.cpp
@@ -0,0 +1,583 @@
+/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
+
+ This software may be distributed and modified under the terms of the GNU
+ General Public License version 2 (GPL2) as published by the Free Software
+ Foundation and appearing in the file GPL2.TXT included in the packaging of
+ this file. Please note that GPL2 Section 2[b] requires that all works based
+ on this software must also be made publicly available under the terms of
+ the GPL2 ("Copyleft").
+
+ Contact information
+ -------------------
+
+ Kristian Lauszus, TKJ Electronics
+ Web : http://www.tkjelectronics.com
+ e-mail : kristianl@tkjelectronics.com
+
+ getBatteryLevel and checkStatus functions made by timstamp.co.uk found using BusHound from Perisoft.net
+ */
+
+#include "XBOXRECV.h"
+// To enable serial debugging see "settings.h"
+//#define EXTRADEBUG // Uncomment to get even more debugging data
+//#define PRINTREPORT // Uncomment to print the report send by the Xbox 360 Controller
+
+XBOXRECV::XBOXRECV(USB *p) :
+pUsb(p), // pointer to USB class instance - mandatory
+bAddress(0), // device address - mandatory
+bPollEnable(false) { // don't start polling before dongle is connected
+ for(uint8_t i = 0; i < XBOX_MAX_ENDPOINTS; i++) {
+ epInfo[i].epAddr = 0;
+ epInfo[i].maxPktSize = (i) ? 0 : 8;
+ epInfo[i].epAttribs = 0;
+ epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
+ }
+
+ if(pUsb) // register in USB subsystem
+ pUsb->RegisterDeviceClass(this); //set devConfig[] entry
+}
+
+uint8_t XBOXRECV::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {
+ const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
+ uint8_t buf[constBufSize];
+ USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
+ uint8_t rcode;
+ UsbDevice *p = NULL;
+ EpInfo *oldep_ptr = NULL;
+ uint16_t PID, VID;
+
+ AddressPool &addrPool = pUsb->GetAddressPool(); // Get memory address of USB device address pool
+#ifdef EXTRADEBUG
+ Notify(PSTR("\r\nXBOXRECV Init"), 0x80);
+#endif
+
+ if(bAddress) { // Check if address has already been assigned to an instance
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nAddress in use"), 0x80);
+#endif
+ return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
+ }
+
+ p = addrPool.GetUsbDevicePtr(0); // Get pointer to pseudo device with address 0 assigned
+
+ if(!p) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nAddress not found"), 0x80);
+#endif
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+ }
+
+ if(!p->epinfo) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nepinfo is null"), 0x80);
+#endif
+ return USB_ERROR_EPINFO_IS_NULL;
+ }
+
+ oldep_ptr = p->epinfo; // Save old pointer to EP_RECORD of address 0
+ p->epinfo = epInfo; // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
+ p->lowspeed = lowspeed;
+
+ rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data
+
+ p->epinfo = oldep_ptr; // Restore p->epinfo
+
+ if(rcode)
+ goto FailGetDevDescr;
+
+ VID = udd->idVendor;
+ PID = udd->idProduct;
+
+ if((VID != XBOX_VID && VID != MADCATZ_VID && VID != JOYTECH_VID) || (PID != XBOX_WIRELESS_RECEIVER_PID && PID != XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID)) { // Check if it's a Xbox receiver using the Vendor ID and Product ID
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nYou'll need a wireless receiver for this libary to work"), 0x80);
+#endif
+ goto FailUnknownDevice;
+ }
+
+ bAddress = addrPool.AllocAddress(parent, false, port); // Allocate new address according to device class
+
+ if(!bAddress) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nOut of address space"), 0x80);
+#endif
+ return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
+ }
+
+ epInfo[0].maxPktSize = udd->bMaxPacketSize0; // Extract Max Packet Size from device descriptor
+
+ delay(20); // Wait a little before resetting device
+
+ return USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET;
+
+ /* Diagnostic messages */
+FailGetDevDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailGetDevDescr(rcode);
+#endif
+ if(rcode != hrJERR)
+ rcode = USB_ERROR_FailGetDevDescr;
+ goto Fail;
+
+FailUnknownDevice:
+#ifdef DEBUG_USB_HOST
+ NotifyFailUnknownDevice(VID, PID);
+#endif
+ rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
+
+Fail:
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nXbox 360 Init Failed, error code: "), 0x80);
+ NotifyFail(rcode);
+#endif
+ Release();
+ return rcode;
+};
+
+uint8_t XBOXRECV::Init(uint8_t parent, uint8_t port, bool lowspeed) {
+ uint8_t rcode;
+
+ AddressPool &addrPool = pUsb->GetAddressPool();
+#ifdef EXTRADEBUG
+ Notify(PSTR("\r\nBTD Init"), 0x80);
+#endif
+ UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record
+
+ if(!p) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nAddress not found"), 0x80);
+#endif
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+ }
+
+ delay(300); // Assign new address to the device
+
+ rcode = pUsb->setAddr(0, 0, bAddress); // Assign new address to the device
+ if(rcode) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nsetAddr: "), 0x80);
+ D_PrintHex<uint8_t > (rcode, 0x80);
+#endif
+ p->lowspeed = false;
+ goto Fail;
+ }
+#ifdef EXTRADEBUG
+ Notify(PSTR("\r\nAddr: "), 0x80);
+ D_PrintHex<uint8_t > (bAddress, 0x80);
+#endif
+
+ p->lowspeed = false;
+
+ p = addrPool.GetUsbDevicePtr(bAddress); // Get pointer to assigned address record
+ if(!p) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nAddress not found"), 0x80);
+#endif
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+ }
+
+ p->lowspeed = lowspeed;
+
+ rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); // Assign epInfo to epinfo pointer - only EP0 is known
+ if(rcode)
+ goto FailSetDevTblEntry;
+
+ /* The application will work in reduced host mode, so we can save program and data
+ memory space. After verifying the VID we will use known values for the
+ configuration values for device, interface, endpoints and HID for the XBOX360 Wireless receiver */
+
+ /* Initialize data structures for endpoints of device */
+ epInfo[ XBOX_INPUT_PIPE_1 ].epAddr = 0x01; // XBOX 360 report endpoint - poll interval 1ms
+ epInfo[ XBOX_INPUT_PIPE_1 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;
+ epInfo[ XBOX_INPUT_PIPE_1 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
+ epInfo[ XBOX_INPUT_PIPE_1 ].maxPktSize = EP_MAXPKTSIZE;
+ epInfo[ XBOX_INPUT_PIPE_1 ].bmSndToggle = 0;
+ epInfo[ XBOX_INPUT_PIPE_1 ].bmRcvToggle = 0;
+ epInfo[ XBOX_OUTPUT_PIPE_1 ].epAddr = 0x01; // XBOX 360 output endpoint - poll interval 8ms
+ epInfo[ XBOX_OUTPUT_PIPE_1 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;
+ epInfo[ XBOX_OUTPUT_PIPE_1 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
+ epInfo[ XBOX_OUTPUT_PIPE_1 ].maxPktSize = EP_MAXPKTSIZE;
+ epInfo[ XBOX_OUTPUT_PIPE_1 ].bmSndToggle = 0;
+ epInfo[ XBOX_OUTPUT_PIPE_1 ].bmRcvToggle = 0;
+
+ epInfo[ XBOX_INPUT_PIPE_2 ].epAddr = 0x03; // XBOX 360 report endpoint - poll interval 1ms
+ epInfo[ XBOX_INPUT_PIPE_2 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;
+ epInfo[ XBOX_INPUT_PIPE_2 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
+ epInfo[ XBOX_INPUT_PIPE_2 ].maxPktSize = EP_MAXPKTSIZE;
+ epInfo[ XBOX_INPUT_PIPE_2 ].bmSndToggle = 0;
+ epInfo[ XBOX_INPUT_PIPE_2 ].bmRcvToggle = 0;
+ epInfo[ XBOX_OUTPUT_PIPE_2 ].epAddr = 0x03; // XBOX 360 output endpoint - poll interval 8ms
+ epInfo[ XBOX_OUTPUT_PIPE_2 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;
+ epInfo[ XBOX_OUTPUT_PIPE_2 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
+ epInfo[ XBOX_OUTPUT_PIPE_2 ].maxPktSize = EP_MAXPKTSIZE;
+ epInfo[ XBOX_OUTPUT_PIPE_2 ].bmSndToggle = 0;
+ epInfo[ XBOX_OUTPUT_PIPE_2 ].bmRcvToggle = 0;
+
+ epInfo[ XBOX_INPUT_PIPE_3 ].epAddr = 0x05; // XBOX 360 report endpoint - poll interval 1ms
+ epInfo[ XBOX_INPUT_PIPE_3 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;
+ epInfo[ XBOX_INPUT_PIPE_3 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
+ epInfo[ XBOX_INPUT_PIPE_3 ].maxPktSize = EP_MAXPKTSIZE;
+ epInfo[ XBOX_INPUT_PIPE_3 ].bmSndToggle = 0;
+ epInfo[ XBOX_INPUT_PIPE_3 ].bmRcvToggle = 0;
+ epInfo[ XBOX_OUTPUT_PIPE_3 ].epAddr = 0x05; // XBOX 360 output endpoint - poll interval 8ms
+ epInfo[ XBOX_OUTPUT_PIPE_3 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;
+ epInfo[ XBOX_OUTPUT_PIPE_3 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
+ epInfo[ XBOX_OUTPUT_PIPE_3 ].maxPktSize = EP_MAXPKTSIZE;
+ epInfo[ XBOX_OUTPUT_PIPE_3 ].bmSndToggle = 0;
+ epInfo[ XBOX_OUTPUT_PIPE_3 ].bmRcvToggle = 0;
+
+ epInfo[ XBOX_INPUT_PIPE_4 ].epAddr = 0x07; // XBOX 360 report endpoint - poll interval 1ms
+ epInfo[ XBOX_INPUT_PIPE_4 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;
+ epInfo[ XBOX_INPUT_PIPE_4 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
+ epInfo[ XBOX_INPUT_PIPE_4 ].maxPktSize = EP_MAXPKTSIZE;
+ epInfo[ XBOX_INPUT_PIPE_4 ].bmSndToggle = 0;
+ epInfo[ XBOX_INPUT_PIPE_4 ].bmRcvToggle = 0;
+ epInfo[ XBOX_OUTPUT_PIPE_4 ].epAddr = 0x07; // XBOX 360 output endpoint - poll interval 8ms
+ epInfo[ XBOX_OUTPUT_PIPE_4 ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;
+ epInfo[ XBOX_OUTPUT_PIPE_4 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
+ epInfo[ XBOX_OUTPUT_PIPE_4 ].maxPktSize = EP_MAXPKTSIZE;
+ epInfo[ XBOX_OUTPUT_PIPE_4 ].bmSndToggle = 0;
+ epInfo[ XBOX_OUTPUT_PIPE_4 ].bmRcvToggle = 0;
+
+ rcode = pUsb->setEpInfoEntry(bAddress, 9, epInfo);
+ if(rcode)
+ goto FailSetDevTblEntry;
+
+ delay(200); //Give time for address change
+
+ rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1);
+ if(rcode)
+ goto FailSetConfDescr;
+
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nXbox Wireless Receiver Connected\r\n"), 0x80);
+#endif
+ XboxReceiverConnected = true;
+ bPollEnable = true;
+ checkStatusTimer = 0; // Reset timer
+ return 0; // Successful configuration
+
+ /* Diagnostic messages */
+FailSetDevTblEntry:
+#ifdef DEBUG_USB_HOST
+ NotifyFailSetDevTblEntry();
+ goto Fail;
+#endif
+
+FailSetConfDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailSetConfDescr();
+#endif
+
+Fail:
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nXbox 360 Init Failed, error code: "), 0x80);
+ NotifyFail(rcode);
+#endif
+ Release();
+ return rcode;
+}
+
+/* Performs a cleanup after failed Init() attempt */
+uint8_t XBOXRECV::Release() {
+ XboxReceiverConnected = false;
+ for(uint8_t i = 0; i < 4; i++)
+ Xbox360Connected[i] = 0x00;
+ pUsb->GetAddressPool().FreeAddress(bAddress);
+ bAddress = 0;
+ bPollEnable = false;
+ return 0;
+}
+
+uint8_t XBOXRECV::Poll() {
+ if(!bPollEnable)
+ return 0;
+ if(!checkStatusTimer || ((millis() - checkStatusTimer) > 3000)) { // Run checkStatus every 3 seconds
+ checkStatusTimer = millis();
+ checkStatus();
+ }
+
+ uint8_t inputPipe;
+ uint16_t bufferSize;
+ for(uint8_t i = 0; i < 4; i++) {
+ if(i == 0)
+ inputPipe = XBOX_INPUT_PIPE_1;
+ else if(i == 1)
+ inputPipe = XBOX_INPUT_PIPE_2;
+ else if(i == 2)
+ inputPipe = XBOX_INPUT_PIPE_3;
+ else
+ inputPipe = XBOX_INPUT_PIPE_4;
+
+ bufferSize = EP_MAXPKTSIZE; // This is the maximum number of bytes we want to receive
+ pUsb->inTransfer(bAddress, epInfo[ inputPipe ].epAddr, &bufferSize, readBuf);
+ if(bufferSize > 0) { // The number of received bytes
+#ifdef EXTRADEBUG
+ Notify(PSTR("Bytes Received: "), 0x80);
+ D_PrintHex<uint16_t > (bufferSize, 0x80);
+ Notify(PSTR("\r\n"), 0x80);
+#endif
+ readReport(i);
+#ifdef PRINTREPORT
+ printReport(i, bufferSize); // Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller
+#endif
+ }
+ }
+ return 0;
+}
+
+void XBOXRECV::readReport(uint8_t controller) {
+ if(readBuf == NULL)
+ return;
+ // This report is send when a controller is connected and disconnected
+ if(readBuf[0] == 0x08 && readBuf[1] != Xbox360Connected[controller]) {
+ Xbox360Connected[controller] = readBuf[1];
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("Controller "), 0x80);
+ Notify(controller, 0x80);
+#endif
+ if(Xbox360Connected[controller]) {
+#ifdef DEBUG_USB_HOST
+ const char* str = 0;
+ switch(readBuf[1]) {
+ case 0x80: str = PSTR(" as controller\r\n");
+ break;
+ case 0x40: str = PSTR(" as headset\r\n");
+ break;
+ case 0xC0: str = PSTR(" as controller+headset\r\n");
+ break;
+ }
+ Notify(PSTR(": connected"), 0x80);
+ Notify(str, 0x80);
+#endif
+ onInit(controller);
+ }
+#ifdef DEBUG_USB_HOST
+ else
+ Notify(PSTR(": disconnected\r\n"), 0x80);
+#endif
+ return;
+ }
+ // Controller status report
+ if(readBuf[1] == 0x00 && readBuf[3] & 0x13 && readBuf[4] >= 0x22) {
+ controllerStatus[controller] = ((uint16_t)readBuf[3] << 8) | readBuf[4];
+ return;
+ }
+ if(readBuf[1] != 0x01) // Check if it's the correct report - the receiver also sends different status reports
+ return;
+
+ // A controller must be connected if it's sending data
+ if(!Xbox360Connected[controller])
+ Xbox360Connected[controller] |= 0x80;
+
+ ButtonState[controller] = (uint32_t)(readBuf[9] | ((uint16_t)readBuf[8] << 8) | ((uint32_t)readBuf[7] << 16) | ((uint32_t)readBuf[6] << 24));
+
+ hatValue[controller][LeftHatX] = (int16_t)(((uint16_t)readBuf[11] << 8) | readBuf[10]);
+ hatValue[controller][LeftHatY] = (int16_t)(((uint16_t)readBuf[13] << 8) | readBuf[12]);
+ hatValue[controller][RightHatX] = (int16_t)(((uint16_t)readBuf[15] << 8) | readBuf[14]);
+ hatValue[controller][RightHatY] = (int16_t)(((uint16_t)readBuf[17] << 8) | readBuf[16]);
+
+ //Notify(PSTR("\r\nButtonState: "), 0x80);
+ //PrintHex<uint32_t>(ButtonState[controller], 0x80);
+
+ if(ButtonState[controller] != OldButtonState[controller]) {
+ buttonStateChanged[controller] = true;
+ ButtonClickState[controller] = (ButtonState[controller] >> 16) & ((~OldButtonState[controller]) >> 16); // Update click state variable, but don't include the two trigger buttons L2 and R2
+ if(((uint8_t)OldButtonState[controller]) == 0 && ((uint8_t)ButtonState[controller]) != 0) // The L2 and R2 buttons are special as they are analog buttons
+ R2Clicked[controller] = true;
+ if((uint8_t)(OldButtonState[controller] >> 8) == 0 && (uint8_t)(ButtonState[controller] >> 8) != 0)
+ L2Clicked[controller] = true;
+ OldButtonState[controller] = ButtonState[controller];
+ }
+}
+
+void XBOXRECV::printReport(uint8_t controller, uint8_t nBytes) { //Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller
+#ifdef PRINTREPORT
+ if(readBuf == NULL)
+ return;
+ Notify(PSTR("Controller "), 0x80);
+ Notify(controller, 0x80);
+ Notify(PSTR(": "), 0x80);
+ for(uint8_t i = 0; i < nBytes; i++) {
+ D_PrintHex<uint8_t > (readBuf[i], 0x80);
+ Notify(PSTR(" "), 0x80);
+ }
+ Notify(PSTR("\r\n"), 0x80);
+#endif
+}
+
+uint8_t XBOXRECV::getButtonPress(ButtonEnum b, uint8_t controller) {
+ if(b == L2) // These are analog buttons
+ return (uint8_t)(ButtonState[controller] >> 8);
+ else if(b == R2)
+ return (uint8_t)ButtonState[controller];
+ return (bool)(ButtonState[controller] & ((uint32_t)pgm_read_word(&XBOX_BUTTONS[(uint8_t)b]) << 16));
+}
+
+bool XBOXRECV::getButtonClick(ButtonEnum b, uint8_t controller) {
+ if(b == L2) {
+ if(L2Clicked[controller]) {
+ L2Clicked[controller] = false;
+ return true;
+ }
+ return false;
+ } else if(b == R2) {
+ if(R2Clicked[controller]) {
+ R2Clicked[controller] = false;
+ return true;
+ }
+ return false;
+ }
+ uint16_t button = pgm_read_word(&XBOX_BUTTONS[(uint8_t)b]);
+ bool click = (ButtonClickState[controller] & button);
+ ButtonClickState[controller] &= ~button; // clear "click" event
+ return click;
+}
+
+int16_t XBOXRECV::getAnalogHat(AnalogHatEnum a, uint8_t controller) {
+ return hatValue[controller][a];
+}
+
+bool XBOXRECV::buttonChanged(uint8_t controller) {
+ bool state = buttonStateChanged[controller];
+ buttonStateChanged[controller] = false;
+ return state;
+}
+
+/*
+ControllerStatus Breakdown
+ControllerStatus[controller] & 0x0001 // 0
+ControllerStatus[controller] & 0x0002 // normal batteries, no rechargeable battery pack
+ControllerStatus[controller] & 0x0004 // controller starting up / settling
+ControllerStatus[controller] & 0x0008 // headset adapter plugged in, but no headphones connected (mute?)
+ControllerStatus[controller] & 0x0010 // 0
+ControllerStatus[controller] & 0x0020 // 1
+ControllerStatus[controller] & 0x0040 // battery level (high bit)
+ControllerStatus[controller] & 0x0080 // battery level (low bit)
+ControllerStatus[controller] & 0x0100 // 1
+ControllerStatus[controller] & 0x0200 // 1
+ControllerStatus[controller] & 0x0400 // headset adapter plugged in
+ControllerStatus[controller] & 0x0800 // 0
+ControllerStatus[controller] & 0x1000 // 1
+ControllerStatus[controller] & 0x2000 // 0
+ControllerStatus[controller] & 0x4000 // 0
+ControllerStatus[controller] & 0x8000 // 0
+ */
+uint8_t XBOXRECV::getBatteryLevel(uint8_t controller) {
+ return ((controllerStatus[controller] & 0x00C0) >> 6);
+}
+
+void XBOXRECV::XboxCommand(uint8_t controller, uint8_t* data, uint16_t nbytes) {
+#ifdef EXTRADEBUG
+ uint8_t rcode;
+#endif
+ uint8_t outputPipe;
+ switch(controller) {
+ case 0: outputPipe = XBOX_OUTPUT_PIPE_1;
+ break;
+ case 1: outputPipe = XBOX_OUTPUT_PIPE_2;
+ break;
+ case 2: outputPipe = XBOX_OUTPUT_PIPE_3;
+ break;
+ case 3: outputPipe = XBOX_OUTPUT_PIPE_4;
+ break;
+ default:
+ return;
+ }
+#ifdef EXTRADEBUG
+ rcode =
+#endif
+ pUsb->outTransfer(bAddress, epInfo[ outputPipe ].epAddr, nbytes, data);
+#ifdef EXTRADEBUG
+ if(rcode)
+ Notify(PSTR("Error sending Xbox message\r\n"), 0x80);
+#endif
+}
+
+void XBOXRECV::disconnect(uint8_t controller) {
+ writeBuf[0] = 0x00;
+ writeBuf[1] = 0x00;
+ writeBuf[2] = 0x08;
+ writeBuf[3] = 0xC0;
+
+ XboxCommand(controller, writeBuf, 4);
+}
+
+void XBOXRECV::setLedRaw(uint8_t value, uint8_t controller) {
+ writeBuf[0] = 0x00;
+ writeBuf[1] = 0x00;
+ writeBuf[2] = 0x08;
+ writeBuf[3] = value | 0x40;
+
+ XboxCommand(controller, writeBuf, 4);
+}
+
+void XBOXRECV::setLedOn(LEDEnum led, uint8_t controller) {
+ if(led == OFF)
+ setLedRaw(0, controller);
+ else if(led != ALL) // All LEDs can't be on a the same time
+ setLedRaw(pgm_read_byte(&XBOX_LEDS[(uint8_t)led]) + 4, controller);
+}
+
+void XBOXRECV::setLedBlink(LEDEnum led, uint8_t controller) {
+ setLedRaw(pgm_read_byte(&XBOX_LEDS[(uint8_t)led]), controller);
+}
+
+void XBOXRECV::setLedMode(LEDModeEnum ledMode, uint8_t controller) { // This function is used to do some speciel LED stuff the controller supports
+ setLedRaw((uint8_t)ledMode, controller);
+}
+
+/* PC runs this at interval of approx 2 seconds
+Thanks to BusHound from Perisoft.net for the Windows USB Analysis output
+Found by timstamp.co.uk
+ */
+void XBOXRECV::checkStatus() {
+ if(!bPollEnable)
+ return;
+ // Get controller info
+ writeBuf[0] = 0x08;
+ writeBuf[1] = 0x00;
+ writeBuf[2] = 0x0f;
+ writeBuf[3] = 0xc0;
+ for(uint8_t i = 0; i < 4; i++) {
+ XboxCommand(i, writeBuf, 4);
+ }
+ // Get battery status
+ writeBuf[0] = 0x00;
+ writeBuf[1] = 0x00;
+ writeBuf[2] = 0x00;
+ writeBuf[3] = 0x40;
+ for(uint8_t i = 0; i < 4; i++) {
+ if(Xbox360Connected[i])
+ XboxCommand(i, writeBuf, 4);
+ }
+}
+
+void XBOXRECV::setRumbleOn(uint8_t lValue, uint8_t rValue, uint8_t controller) {
+ writeBuf[0] = 0x00;
+ writeBuf[1] = 0x01;
+ writeBuf[2] = 0x0f;
+ writeBuf[3] = 0xc0;
+ writeBuf[4] = 0x00;
+ writeBuf[5] = lValue; // big weight
+ writeBuf[6] = rValue; // small weight
+
+ XboxCommand(controller, writeBuf, 7);
+}
+
+void XBOXRECV::onInit(uint8_t controller) {
+ if(pFuncOnInit)
+ pFuncOnInit(); // Call the user function
+ else {
+ LEDEnum led;
+ if(controller == 0)
+ led = LED1;
+ else if(controller == 1)
+ led = LED2;
+ else if(controller == 2)
+ led = LED3;
+ else
+ led = LED4;
+ setLedOn(led, controller);
+ }
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXRECV.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXRECV.h
new file mode 100644
index 000000000..4f9214653
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXRECV.h
@@ -0,0 +1,276 @@
+/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
+
+ This software may be distributed and modified under the terms of the GNU
+ General Public License version 2 (GPL2) as published by the Free Software
+ Foundation and appearing in the file GPL2.TXT included in the packaging of
+ this file. Please note that GPL2 Section 2[b] requires that all works based
+ on this software must also be made publicly available under the terms of
+ the GPL2 ("Copyleft").
+
+ Contact information
+ -------------------
+
+ Kristian Lauszus, TKJ Electronics
+ Web : http://www.tkjelectronics.com
+ e-mail : kristianl@tkjelectronics.com
+
+ getBatteryLevel and checkStatus functions made by timstamp.co.uk found using BusHound from Perisoft.net
+ */
+
+#ifndef _xboxrecv_h_
+#define _xboxrecv_h_
+
+#include "Usb.h"
+#include "xboxEnums.h"
+
+/* Data Xbox 360 taken from descriptors */
+#define EP_MAXPKTSIZE 32 // max size for data via USB
+
+/* Names we give to the 9 Xbox360 pipes */
+#define XBOX_CONTROL_PIPE 0
+#define XBOX_INPUT_PIPE_1 1
+#define XBOX_OUTPUT_PIPE_1 2
+#define XBOX_INPUT_PIPE_2 3
+#define XBOX_OUTPUT_PIPE_2 4
+#define XBOX_INPUT_PIPE_3 5
+#define XBOX_OUTPUT_PIPE_3 6
+#define XBOX_INPUT_PIPE_4 7
+#define XBOX_OUTPUT_PIPE_4 8
+
+// PID and VID of the different devices
+#define XBOX_VID 0x045E // Microsoft Corporation
+#define MADCATZ_VID 0x1BAD // For unofficial Mad Catz receivers
+#define JOYTECH_VID 0x162E // For unofficial Joytech controllers
+
+#define XBOX_WIRELESS_RECEIVER_PID 0x0719 // Microsoft Wireless Gaming Receiver
+#define XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID 0x0291 // Third party Wireless Gaming Receiver
+
+#define XBOX_MAX_ENDPOINTS 9
+
+/**
+ * This class implements support for a Xbox Wireless receiver.
+ *
+ * Up to four controllers can connect to one receiver, if more is needed one can use a second receiver via the USBHub class.
+ */
+class XBOXRECV : public USBDeviceConfig {
+public:
+ /**
+ * Constructor for the XBOXRECV class.
+ * @param pUsb Pointer to USB class instance.
+ */
+ XBOXRECV(USB *pUsb);
+
+ /** @name USBDeviceConfig implementation */
+ /**
+ * Address assignment and basic initilization is done here.
+ * @param parent Hub number.
+ * @param port Port number on the hub.
+ * @param lowspeed Speed of the device.
+ * @return 0 on success.
+ */
+ uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed);
+ /**
+ * Initialize the Xbox wireless receiver.
+ * @param parent Hub number.
+ * @param port Port number on the hub.
+ * @param lowspeed Speed of the device.
+ * @return 0 on success.
+ */
+ uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
+ /**
+ * Release the USB device.
+ * @return 0 on success.
+ */
+ uint8_t Release();
+ /**
+ * Poll the USB Input endpoins and run the state machines.
+ * @return 0 on success.
+ */
+ uint8_t Poll();
+
+ /**
+ * Get the device address.
+ * @return The device address.
+ */
+ virtual uint8_t GetAddress() {
+ return bAddress;
+ };
+
+ /**
+ * Used to check if the controller has been initialized.
+ * @return True if it's ready.
+ */
+ virtual bool isReady() {
+ return bPollEnable;
+ };
+
+ /**
+ * Used by the USB core to check what this driver support.
+ * @param vid The device's VID.
+ * @param pid The device's PID.
+ * @return Returns true if the device's VID and PID matches this driver.
+ */
+ virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {
+ return ((vid == XBOX_VID || vid == MADCATZ_VID || vid == JOYTECH_VID) && (pid == XBOX_WIRELESS_RECEIVER_PID || pid == XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID));
+ };
+ /**@}*/
+
+ /** @name Xbox Controller functions */
+ /**
+ * getButtonPress(uint8_t controller, ButtonEnum b) will return true as long as the button is held down.
+ *
+ * While getButtonClick(uint8_t controller, ButtonEnum b) will only return it once.
+ *
+ * So you instance if you need to increase a variable once you would use getButtonClick(uint8_t controller, ButtonEnum b),
+ * but if you need to drive a robot forward you would use getButtonPress(uint8_t controller, ButtonEnum b).
+ * @param b ::ButtonEnum to read.
+ * @param controller The controller to read from. Default to 0.
+ * @return getButtonClick(uint8_t controller, ButtonEnum b) will return a bool, while getButtonPress(uint8_t controller, ButtonEnum b) will return a byte if reading ::L2 or ::R2.
+ */
+ uint8_t getButtonPress(ButtonEnum b, uint8_t controller = 0);
+ bool getButtonClick(ButtonEnum b, uint8_t controller = 0);
+ /**@}*/
+
+ /** @name Xbox Controller functions */
+ /**
+ * Return the analog value from the joysticks on the controller.
+ * @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY.
+ * @param controller The controller to read from. Default to 0.
+ * @return Returns a signed 16-bit integer.
+ */
+ int16_t getAnalogHat(AnalogHatEnum a, uint8_t controller = 0);
+
+ /**
+ * Used to disconnect any of the controllers.
+ * @param controller The controller to disconnect. Default to 0.
+ */
+ void disconnect(uint8_t controller = 0);
+
+ /**
+ * Turn rumble off and all the LEDs on the specific controller.
+ * @param controller The controller to write to. Default to 0.
+ */
+ void setAllOff(uint8_t controller = 0) {
+ setRumbleOn(0, 0, controller);
+ setLedOff(controller);
+ };
+
+ /**
+ * Turn rumble off the specific controller.
+ * @param controller The controller to write to. Default to 0.
+ */
+ void setRumbleOff(uint8_t controller = 0) {
+ setRumbleOn(0, 0, controller);
+ };
+ /**
+ * Turn rumble on.
+ * @param lValue Left motor (big weight) inside the controller.
+ * @param rValue Right motor (small weight) inside the controller.
+ * @param controller The controller to write to. Default to 0.
+ */
+ void setRumbleOn(uint8_t lValue, uint8_t rValue, uint8_t controller = 0);
+ /**
+ * Set LED value. Without using the ::LEDEnum or ::LEDModeEnum.
+ * @param value See:
+ * setLedOff(uint8_t controller), setLedOn(uint8_t controller, LED l),
+ * setLedBlink(uint8_t controller, LED l), and setLedMode(uint8_t controller, LEDMode lm).
+ * @param controller The controller to write to. Default to 0.
+ */
+ void setLedRaw(uint8_t value, uint8_t controller = 0);
+
+ /**
+ * Turn all LEDs off the specific controller.
+ * @param controller The controller to write to. Default to 0.
+ */
+ void setLedOff(uint8_t controller = 0) {
+ setLedRaw(0, controller);
+ };
+ /**
+ * Turn on a LED by using ::LEDEnum.
+ * @param l ::OFF, ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller.
+ * @param controller The controller to write to. Default to 0.
+ */
+ void setLedOn(LEDEnum l, uint8_t controller = 0);
+ /**
+ * Turn on a LED by using ::LEDEnum.
+ * @param l ::ALL, ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller.
+ * @param controller The controller to write to. Default to 0.
+ */
+ void setLedBlink(LEDEnum l, uint8_t controller = 0);
+ /**
+ * Used to set special LED modes supported by the Xbox controller.
+ * @param lm See ::LEDModeEnum.
+ * @param controller The controller to write to. Default to 0.
+ */
+ void setLedMode(LEDModeEnum lm, uint8_t controller = 0);
+ /**
+ * Used to get the battery level from the controller.
+ * @param controller The controller to read from. Default to 0.
+ * @return Returns the battery level as an integer in the range of 0-3.
+ */
+ uint8_t getBatteryLevel(uint8_t controller = 0);
+ /**
+ * Used to check if a button has changed.
+ * @param controller The controller to read from. Default to 0.
+ * @return True if a button has changed.
+ */
+ bool buttonChanged(uint8_t controller = 0);
+
+ /**
+ * Used to call your own function when the controller is successfully initialized.
+ * @param funcOnInit Function to call.
+ */
+ void attachOnInit(void (*funcOnInit)(void)) {
+ pFuncOnInit = funcOnInit;
+ };
+ /**@}*/
+
+ /** True if a wireless receiver is connected. */
+ bool XboxReceiverConnected;
+ /** Variable used to indicate if the XBOX 360 controller is successfully connected. */
+ uint8_t Xbox360Connected[4];
+
+protected:
+ /** Pointer to USB class instance. */
+ USB *pUsb;
+ /** Device address. */
+ uint8_t bAddress;
+ /** Endpoint info structure. */
+ EpInfo epInfo[XBOX_MAX_ENDPOINTS];
+
+private:
+ /**
+ * Called when the controller is successfully initialized.
+ * Use attachOnInit(void (*funcOnInit)(void)) to call your own function.
+ * This is useful for instance if you want to set the LEDs in a specific way.
+ * @param controller The initialized controller.
+ */
+ void onInit(uint8_t controller);
+ void (*pFuncOnInit)(void); // Pointer to function called in onInit()
+
+ bool bPollEnable;
+
+ /* Variables to store the buttons */
+ uint32_t ButtonState[4];
+ uint32_t OldButtonState[4];
+ uint16_t ButtonClickState[4];
+ int16_t hatValue[4][4];
+ uint16_t controllerStatus[4];
+ bool buttonStateChanged[4]; // True if a button has changed
+
+ bool L2Clicked[4]; // These buttons are analog, so we use we use these bools to check if they where clicked or not
+ bool R2Clicked[4];
+
+ uint32_t checkStatusTimer; // Timing for checkStatus() signals
+
+ uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data
+ uint8_t writeBuf[7]; // General purpose buffer for output data
+
+ void readReport(uint8_t controller); // read incoming data
+ void printReport(uint8_t controller, uint8_t nBytes); // print incoming date - Uncomment for debugging
+
+ /* Private commands */
+ void XboxCommand(uint8_t controller, uint8_t* data, uint16_t nbytes);
+ void checkStatus();
+};
+#endif
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXUSB.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXUSB.cpp
new file mode 100644
index 000000000..ddece21b4
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXUSB.cpp
@@ -0,0 +1,361 @@
+/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
+
+ This software may be distributed and modified under the terms of the GNU
+ General Public License version 2 (GPL2) as published by the Free Software
+ Foundation and appearing in the file GPL2.TXT included in the packaging of
+ this file. Please note that GPL2 Section 2[b] requires that all works based
+ on this software must also be made publicly available under the terms of
+ the GPL2 ("Copyleft").
+
+ Contact information
+ -------------------
+
+ Kristian Lauszus, TKJ Electronics
+ Web : http://www.tkjelectronics.com
+ e-mail : kristianl@tkjelectronics.com
+ */
+
+#include "XBOXUSB.h"
+// To enable serial debugging see "settings.h"
+//#define EXTRADEBUG // Uncomment to get even more debugging data
+//#define PRINTREPORT // Uncomment to print the report send by the Xbox 360 Controller
+
+XBOXUSB::XBOXUSB(USB *p) :
+pUsb(p), // pointer to USB class instance - mandatory
+bAddress(0), // device address - mandatory
+bPollEnable(false) { // don't start polling before dongle is connected
+ for(uint8_t i = 0; i < XBOX_MAX_ENDPOINTS; i++) {
+ epInfo[i].epAddr = 0;
+ epInfo[i].maxPktSize = (i) ? 0 : 8;
+ epInfo[i].epAttribs = 0;
+ epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
+ }
+
+ if(pUsb) // register in USB subsystem
+ pUsb->RegisterDeviceClass(this); //set devConfig[] entry
+}
+
+uint8_t XBOXUSB::Init(uint8_t parent, uint8_t port, bool lowspeed) {
+ uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
+ USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
+ uint8_t rcode;
+ UsbDevice *p = NULL;
+ EpInfo *oldep_ptr = NULL;
+ uint16_t PID;
+ uint16_t VID;
+
+ // get memory address of USB device address pool
+ AddressPool &addrPool = pUsb->GetAddressPool();
+#ifdef EXTRADEBUG
+ Notify(PSTR("\r\nXBOXUSB Init"), 0x80);
+#endif
+ // check if address has already been assigned to an instance
+ if(bAddress) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nAddress in use"), 0x80);
+#endif
+ return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
+ }
+
+ // Get pointer to pseudo device with address 0 assigned
+ p = addrPool.GetUsbDevicePtr(0);
+
+ if(!p) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nAddress not found"), 0x80);
+#endif
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+ }
+
+ if(!p->epinfo) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nepinfo is null"), 0x80);
+#endif
+ return USB_ERROR_EPINFO_IS_NULL;
+ }
+
+ // Save old pointer to EP_RECORD of address 0
+ oldep_ptr = p->epinfo;
+
+ // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
+ p->epinfo = epInfo;
+
+ p->lowspeed = lowspeed;
+
+ // Get device descriptor
+ rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data
+ // Restore p->epinfo
+ p->epinfo = oldep_ptr;
+
+ if(rcode)
+ goto FailGetDevDescr;
+
+ VID = udd->idVendor;
+ PID = udd->idProduct;
+
+ if(VID != XBOX_VID && VID != MADCATZ_VID && VID != JOYTECH_VID && VID != GAMESTOP_VID) // Check VID
+ goto FailUnknownDevice;
+ if(PID == XBOX_WIRELESS_PID) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nYou have plugged in a wireless Xbox 360 controller - it doesn't support USB communication"), 0x80);
+#endif
+ goto FailUnknownDevice;
+ } else if(PID == XBOX_WIRELESS_RECEIVER_PID || PID == XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID) {
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nThis library only supports Xbox 360 controllers via USB"), 0x80);
+#endif
+ goto FailUnknownDevice;
+ } else if(PID != XBOX_WIRED_PID && PID != MADCATZ_WIRED_PID && PID != GAMESTOP_WIRED_PID && PID != AFTERGLOW_WIRED_PID && PID != JOYTECH_WIRED_PID) // Check PID
+ goto FailUnknownDevice;
+
+ // Allocate new address according to device class
+ bAddress = addrPool.AllocAddress(parent, false, port);
+
+ if(!bAddress)
+ return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
+
+ // Extract Max Packet Size from device descriptor
+ epInfo[0].maxPktSize = udd->bMaxPacketSize0;
+
+ // Assign new address to the device
+ rcode = pUsb->setAddr(0, 0, bAddress);
+ if(rcode) {
+ p->lowspeed = false;
+ addrPool.FreeAddress(bAddress);
+ bAddress = 0;
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nsetAddr: "), 0x80);
+ D_PrintHex<uint8_t > (rcode, 0x80);
+#endif
+ return rcode;
+ }
+#ifdef EXTRADEBUG
+ Notify(PSTR("\r\nAddr: "), 0x80);
+ D_PrintHex<uint8_t > (bAddress, 0x80);
+#endif
+ //delay(300); // Spec says you should wait at least 200ms
+
+ p->lowspeed = false;
+
+ //get pointer to assigned address record
+ p = addrPool.GetUsbDevicePtr(bAddress);
+ if(!p)
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+ p->lowspeed = lowspeed;
+
+ // Assign epInfo to epinfo pointer - only EP0 is known
+ rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
+ if(rcode)
+ goto FailSetDevTblEntry;
+
+ /* The application will work in reduced host mode, so we can save program and data
+ memory space. After verifying the VID we will use known values for the
+ configuration values for device, interface, endpoints and HID for the XBOX360 Controllers */
+
+ /* Initialize data structures for endpoints of device */
+ epInfo[ XBOX_INPUT_PIPE ].epAddr = 0x01; // XBOX 360 report endpoint
+ epInfo[ XBOX_INPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;
+ epInfo[ XBOX_INPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
+ epInfo[ XBOX_INPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE;
+ epInfo[ XBOX_INPUT_PIPE ].bmSndToggle = 0;
+ epInfo[ XBOX_INPUT_PIPE ].bmRcvToggle = 0;
+ epInfo[ XBOX_OUTPUT_PIPE ].epAddr = 0x02; // XBOX 360 output endpoint
+ epInfo[ XBOX_OUTPUT_PIPE ].epAttribs = USB_TRANSFER_TYPE_INTERRUPT;
+ epInfo[ XBOX_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
+ epInfo[ XBOX_OUTPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE;
+ epInfo[ XBOX_OUTPUT_PIPE ].bmSndToggle = 0;
+ epInfo[ XBOX_OUTPUT_PIPE ].bmRcvToggle = 0;
+
+ rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo);
+ if(rcode)
+ goto FailSetDevTblEntry;
+
+ delay(200); // Give time for address change
+
+ rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1);
+ if(rcode)
+ goto FailSetConfDescr;
+
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nXbox 360 Controller Connected\r\n"), 0x80);
+#endif
+ onInit();
+ Xbox360Connected = true;
+ bPollEnable = true;
+ return 0; // Successful configuration
+
+ /* Diagnostic messages */
+FailGetDevDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailGetDevDescr();
+ goto Fail;
+#endif
+
+FailSetDevTblEntry:
+#ifdef DEBUG_USB_HOST
+ NotifyFailSetDevTblEntry();
+ goto Fail;
+#endif
+
+FailSetConfDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailSetConfDescr();
+#endif
+ goto Fail;
+
+FailUnknownDevice:
+#ifdef DEBUG_USB_HOST
+ NotifyFailUnknownDevice(VID, PID);
+#endif
+ rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
+
+Fail:
+#ifdef DEBUG_USB_HOST
+ Notify(PSTR("\r\nXbox 360 Init Failed, error code: "), 0x80);
+ NotifyFail(rcode);
+#endif
+ Release();
+ return rcode;
+}
+
+/* Performs a cleanup after failed Init() attempt */
+uint8_t XBOXUSB::Release() {
+ Xbox360Connected = false;
+ pUsb->GetAddressPool().FreeAddress(bAddress);
+ bAddress = 0;
+ bPollEnable = false;
+ return 0;
+}
+
+uint8_t XBOXUSB::Poll() {
+ if(!bPollEnable)
+ return 0;
+ uint16_t BUFFER_SIZE = EP_MAXPKTSIZE;
+ pUsb->inTransfer(bAddress, epInfo[ XBOX_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1
+ readReport();
+#ifdef PRINTREPORT
+ printReport(); // Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller
+#endif
+ return 0;
+}
+
+void XBOXUSB::readReport() {
+ if(readBuf == NULL)
+ return;
+ if(readBuf[0] != 0x00 || readBuf[1] != 0x14) { // Check if it's the correct report - the controller also sends different status reports
+ return;
+ }
+
+ ButtonState = (uint32_t)(readBuf[5] | ((uint16_t)readBuf[4] << 8) | ((uint32_t)readBuf[3] << 16) | ((uint32_t)readBuf[2] << 24));
+
+ hatValue[LeftHatX] = (int16_t)(((uint16_t)readBuf[7] << 8) | readBuf[6]);
+ hatValue[LeftHatY] = (int16_t)(((uint16_t)readBuf[9] << 8) | readBuf[8]);
+ hatValue[RightHatX] = (int16_t)(((uint16_t)readBuf[11] << 8) | readBuf[10]);
+ hatValue[RightHatY] = (int16_t)(((uint16_t)readBuf[13] << 8) | readBuf[12]);
+
+ //Notify(PSTR("\r\nButtonState"), 0x80);
+ //PrintHex<uint32_t>(ButtonState, 0x80);
+
+ if(ButtonState != OldButtonState) {
+ ButtonClickState = (ButtonState >> 16) & ((~OldButtonState) >> 16); // Update click state variable, but don't include the two trigger buttons L2 and R2
+ if(((uint8_t)OldButtonState) == 0 && ((uint8_t)ButtonState) != 0) // The L2 and R2 buttons are special as they are analog buttons
+ R2Clicked = true;
+ if((uint8_t)(OldButtonState >> 8) == 0 && (uint8_t)(ButtonState >> 8) != 0)
+ L2Clicked = true;
+ OldButtonState = ButtonState;
+ }
+}
+
+void XBOXUSB::printReport() { //Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller
+#ifdef PRINTREPORT
+ if(readBuf == NULL)
+ return;
+ for(uint8_t i = 0; i < XBOX_REPORT_BUFFER_SIZE; i++) {
+ D_PrintHex<uint8_t > (readBuf[i], 0x80);
+ Notify(PSTR(" "), 0x80);
+ }
+ Notify(PSTR("\r\n"), 0x80);
+#endif
+}
+
+uint8_t XBOXUSB::getButtonPress(ButtonEnum b) {
+ if(b == L2) // These are analog buttons
+ return (uint8_t)(ButtonState >> 8);
+ else if(b == R2)
+ return (uint8_t)ButtonState;
+ return (bool)(ButtonState & ((uint32_t)pgm_read_word(&XBOX_BUTTONS[(uint8_t)b]) << 16));
+}
+
+bool XBOXUSB::getButtonClick(ButtonEnum b) {
+ if(b == L2) {
+ if(L2Clicked) {
+ L2Clicked = false;
+ return true;
+ }
+ return false;
+ } else if(b == R2) {
+ if(R2Clicked) {
+ R2Clicked = false;
+ return true;
+ }
+ return false;
+ }
+ uint16_t button = pgm_read_word(&XBOX_BUTTONS[(uint8_t)b]);
+ bool click = (ButtonClickState & button);
+ ButtonClickState &= ~button; // clear "click" event
+ return click;
+}
+
+int16_t XBOXUSB::getAnalogHat(AnalogHatEnum a) {
+ return hatValue[a];
+}
+
+/* Xbox Controller commands */
+void XBOXUSB::XboxCommand(uint8_t* data, uint16_t nbytes) {
+ //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x00), Report Type (Output 0x02), interface (0x00), datalength, datalength, data)
+ pUsb->ctrlReq(bAddress, epInfo[XBOX_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL);
+}
+
+void XBOXUSB::setLedRaw(uint8_t value) {
+ writeBuf[0] = 0x01;
+ writeBuf[1] = 0x03;
+ writeBuf[2] = value;
+
+ XboxCommand(writeBuf, 3);
+}
+
+void XBOXUSB::setLedOn(LEDEnum led) {
+ if(led == OFF)
+ setLedRaw(0);
+ else if(led != ALL) // All LEDs can't be on a the same time
+ setLedRaw(pgm_read_byte(&XBOX_LEDS[(uint8_t)led]) + 4);
+}
+
+void XBOXUSB::setLedBlink(LEDEnum led) {
+ setLedRaw(pgm_read_byte(&XBOX_LEDS[(uint8_t)led]));
+}
+
+void XBOXUSB::setLedMode(LEDModeEnum ledMode) { // This function is used to do some special LED stuff the controller supports
+ setLedRaw((uint8_t)ledMode);
+}
+
+void XBOXUSB::setRumbleOn(uint8_t lValue, uint8_t rValue) {
+ writeBuf[0] = 0x00;
+ writeBuf[1] = 0x08;
+ writeBuf[2] = 0x00;
+ writeBuf[3] = lValue; // big weight
+ writeBuf[4] = rValue; // small weight
+ writeBuf[5] = 0x00;
+ writeBuf[6] = 0x00;
+ writeBuf[7] = 0x00;
+
+ XboxCommand(writeBuf, 8);
+}
+
+void XBOXUSB::onInit() {
+ if(pFuncOnInit)
+ pFuncOnInit(); // Call the user function
+ else
+ setLedOn(LED1);
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXUSB.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXUSB.h
new file mode 100644
index 000000000..1ab37851a
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/XBOXUSB.h
@@ -0,0 +1,225 @@
+/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
+
+ This software may be distributed and modified under the terms of the GNU
+ General Public License version 2 (GPL2) as published by the Free Software
+ Foundation and appearing in the file GPL2.TXT included in the packaging of
+ this file. Please note that GPL2 Section 2[b] requires that all works based
+ on this software must also be made publicly available under the terms of
+ the GPL2 ("Copyleft").
+
+ Contact information
+ -------------------
+
+ Kristian Lauszus, TKJ Electronics
+ Web : http://www.tkjelectronics.com
+ e-mail : kristianl@tkjelectronics.com
+ */
+
+#ifndef _xboxusb_h_
+#define _xboxusb_h_
+
+#include "Usb.h"
+#include "hid.h"
+#include "xboxEnums.h"
+
+/* Data Xbox 360 taken from descriptors */
+#define EP_MAXPKTSIZE 32 // max size for data via USB
+
+/* Names we give to the 3 Xbox360 pipes */
+#define XBOX_CONTROL_PIPE 0
+#define XBOX_INPUT_PIPE 1
+#define XBOX_OUTPUT_PIPE 2
+
+// PID and VID of the different devices
+#define XBOX_VID 0x045E // Microsoft Corporation
+#define MADCATZ_VID 0x1BAD // For unofficial Mad Catz controllers
+#define JOYTECH_VID 0x162E // For unofficial Joytech controllers
+#define GAMESTOP_VID 0x0E6F // Gamestop controller
+
+#define XBOX_WIRED_PID 0x028E // Microsoft 360 Wired controller
+#define XBOX_WIRELESS_PID 0x028F // Wireless controller only support charging
+#define XBOX_WIRELESS_RECEIVER_PID 0x0719 // Microsoft Wireless Gaming Receiver
+#define XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID 0x0291 // Third party Wireless Gaming Receiver
+#define MADCATZ_WIRED_PID 0xF016 // Mad Catz wired controller
+#define JOYTECH_WIRED_PID 0xBEEF // For Joytech wired controller
+#define GAMESTOP_WIRED_PID 0x0401 // Gamestop wired controller
+#define AFTERGLOW_WIRED_PID 0x0213 // Afterglow wired controller - it uses the same VID as a Gamestop controller
+
+#define XBOX_REPORT_BUFFER_SIZE 14 // Size of the input report buffer
+
+#define XBOX_MAX_ENDPOINTS 3
+
+/** This class implements support for a Xbox wired controller via USB. */
+class XBOXUSB : public USBDeviceConfig {
+public:
+ /**
+ * Constructor for the XBOXUSB class.
+ * @param pUsb Pointer to USB class instance.
+ */
+ XBOXUSB(USB *pUsb);
+
+ /** @name USBDeviceConfig implementation */
+ /**
+ * Initialize the Xbox Controller.
+ * @param parent Hub number.
+ * @param port Port number on the hub.
+ * @param lowspeed Speed of the device.
+ * @return 0 on success.
+ */
+ uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
+ /**
+ * Release the USB device.
+ * @return 0 on success.
+ */
+ uint8_t Release();
+ /**
+ * Poll the USB Input endpoins and run the state machines.
+ * @return 0 on success.
+ */
+ uint8_t Poll();
+
+ /**
+ * Get the device address.
+ * @return The device address.
+ */
+ virtual uint8_t GetAddress() {
+ return bAddress;
+ };
+
+ /**
+ * Used to check if the controller has been initialized.
+ * @return True if it's ready.
+ */
+ virtual bool isReady() {
+ return bPollEnable;
+ };
+
+ /**
+ * Used by the USB core to check what this driver support.
+ * @param vid The device's VID.
+ * @param pid The device's PID.
+ * @return Returns true if the device's VID and PID matches this driver.
+ */
+ virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {
+ return ((vid == XBOX_VID || vid == MADCATZ_VID || vid == JOYTECH_VID || vid == GAMESTOP_VID) && (pid == XBOX_WIRED_PID || pid == MADCATZ_WIRED_PID || pid == GAMESTOP_WIRED_PID || pid == AFTERGLOW_WIRED_PID || pid == JOYTECH_WIRED_PID));
+ };
+ /**@}*/
+
+ /** @name Xbox Controller functions */
+ /**
+ * getButtonPress(ButtonEnum b) will return true as long as the button is held down.
+ *
+ * While getButtonClick(ButtonEnum b) will only return it once.
+ *
+ * So you instance if you need to increase a variable once you would use getButtonClick(ButtonEnum b),
+ * but if you need to drive a robot forward you would use getButtonPress(ButtonEnum b).
+ * @param b ::ButtonEnum to read.
+ * @return getButtonClick(ButtonEnum b) will return a bool, while getButtonPress(ButtonEnum b) will return a byte if reading ::L2 or ::R2.
+ */
+ uint8_t getButtonPress(ButtonEnum b);
+ bool getButtonClick(ButtonEnum b);
+ /**@}*/
+
+ /** @name Xbox Controller functions */
+ /**
+ * Return the analog value from the joysticks on the controller.
+ * @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY.
+ * @return Returns a signed 16-bit integer.
+ */
+ int16_t getAnalogHat(AnalogHatEnum a);
+
+ /** Turn rumble off and all the LEDs on the controller. */
+ void setAllOff() {
+ setRumbleOn(0, 0);
+ setLedRaw(0);
+ };
+
+ /** Turn rumble off the controller. */
+ void setRumbleOff() {
+ setRumbleOn(0, 0);
+ };
+ /**
+ * Turn rumble on.
+ * @param lValue Left motor (big weight) inside the controller.
+ * @param rValue Right motor (small weight) inside the controller.
+ */
+ void setRumbleOn(uint8_t lValue, uint8_t rValue);
+ /**
+ * Set LED value. Without using the ::LEDEnum or ::LEDModeEnum.
+ * @param value See:
+ * setLedOff(), setLedOn(LEDEnum l),
+ * setLedBlink(LEDEnum l), and setLedMode(LEDModeEnum lm).
+ */
+ void setLedRaw(uint8_t value);
+
+ /** Turn all LEDs off the controller. */
+ void setLedOff() {
+ setLedRaw(0);
+ };
+ /**
+ * Turn on a LED by using ::LEDEnum.
+ * @param l ::OFF, ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller.
+ */
+ void setLedOn(LEDEnum l);
+ /**
+ * Turn on a LED by using ::LEDEnum.
+ * @param l ::ALL, ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller.
+ */
+ void setLedBlink(LEDEnum l);
+ /**
+ * Used to set special LED modes supported by the Xbox controller.
+ * @param lm See ::LEDModeEnum.
+ */
+ void setLedMode(LEDModeEnum lm);
+
+ /**
+ * Used to call your own function when the controller is successfully initialized.
+ * @param funcOnInit Function to call.
+ */
+ void attachOnInit(void (*funcOnInit)(void)) {
+ pFuncOnInit = funcOnInit;
+ };
+ /**@}*/
+
+ /** True if a Xbox 360 controller is connected. */
+ bool Xbox360Connected;
+
+protected:
+ /** Pointer to USB class instance. */
+ USB *pUsb;
+ /** Device address. */
+ uint8_t bAddress;
+ /** Endpoint info structure. */
+ EpInfo epInfo[XBOX_MAX_ENDPOINTS];
+
+private:
+ /**
+ * Called when the controller is successfully initialized.
+ * Use attachOnInit(void (*funcOnInit)(void)) to call your own function.
+ * This is useful for instance if you want to set the LEDs in a specific way.
+ */
+ void onInit();
+ void (*pFuncOnInit)(void); // Pointer to function called in onInit()
+
+ bool bPollEnable;
+
+ /* Variables to store the buttons */
+ uint32_t ButtonState;
+ uint32_t OldButtonState;
+ uint16_t ButtonClickState;
+ int16_t hatValue[4];
+ uint16_t controllerStatus;
+
+ bool L2Clicked; // These buttons are analog, so we use we use these bools to check if they where clicked or not
+ bool R2Clicked;
+
+ uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data
+ uint8_t writeBuf[8]; // General purpose buffer for output data
+
+ void readReport(); // read incoming data
+ void printReport(); // print incoming date - Uncomment for debugging
+
+ /* Private commands */
+ void XboxCommand(uint8_t* data, uint16_t nbytes);
+};
+#endif
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/address.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/address.h
new file mode 100644
index 000000000..c3e1b3141
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/address.h
@@ -0,0 +1,282 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+
+#if !defined(_usb_h_) || defined(__ADDRESS_H__)
+#error "Never include address.h directly; include Usb.h instead"
+#else
+#define __ADDRESS_H__
+
+
+
+/* NAK powers. To save space in endpoint data structure, amount of retries before giving up and returning 0x4 is stored in */
+/* bmNakPower as a power of 2. The actual nak_limit is then calculated as nak_limit = ( 2^bmNakPower - 1) */
+#define USB_NAK_MAX_POWER 15 //NAK binary order maximum value
+#define USB_NAK_DEFAULT 14 //default 32K-1 NAKs before giving up
+#define USB_NAK_NOWAIT 1 //Single NAK stops transfer
+#define USB_NAK_NONAK 0 //Do not count NAKs, stop retrying after USB Timeout
+
+struct EpInfo {
+ uint8_t epAddr; // Endpoint address
+ uint8_t maxPktSize; // Maximum packet size
+
+ union {
+ uint8_t epAttribs;
+
+ struct {
+ uint8_t bmSndToggle : 1; // Send toggle, when zero bmSNDTOG0, bmSNDTOG1 otherwise
+ uint8_t bmRcvToggle : 1; // Send toggle, when zero bmRCVTOG0, bmRCVTOG1 otherwise
+ uint8_t bmNakPower : 6; // Binary order for NAK_LIMIT value
+ } __attribute__((packed));
+ };
+} __attribute__((packed));
+
+// 7 6 5 4 3 2 1 0
+// ---------------------------------
+// | | H | P | P | P | A | A | A |
+// ---------------------------------
+//
+// H - if 1 the address is a hub address
+// P - parent hub address
+// A - device address / port number in case of hub
+//
+
+struct UsbDeviceAddress {
+
+ union {
+
+ struct {
+ uint8_t bmAddress : 3; // device address/port number
+ uint8_t bmParent : 3; // parent hub address
+ uint8_t bmHub : 1; // hub flag
+ uint8_t bmReserved : 1; // reserved, must be zero
+ } __attribute__((packed));
+ uint8_t devAddress;
+ };
+} __attribute__((packed));
+
+#define bmUSB_DEV_ADDR_ADDRESS 0x07
+#define bmUSB_DEV_ADDR_PARENT 0x38
+#define bmUSB_DEV_ADDR_HUB 0x40
+
+struct UsbDevice {
+ EpInfo *epinfo; // endpoint info pointer
+ UsbDeviceAddress address;
+ uint8_t epcount; // number of endpoints
+ bool lowspeed; // indicates if a device is the low speed one
+ // uint8_t devclass; // device class
+} __attribute__((packed));
+
+class AddressPool {
+public:
+ virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) = 0;
+ virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) = 0;
+ virtual void FreeAddress(uint8_t addr) = 0;
+};
+
+typedef void (*UsbDeviceHandleFunc)(UsbDevice *pdev);
+
+#define ADDR_ERROR_INVALID_INDEX 0xFF
+#define ADDR_ERROR_INVALID_ADDRESS 0xFF
+
+template <const uint8_t MAX_DEVICES_ALLOWED>
+class AddressPoolImpl : public AddressPool {
+ EpInfo dev0ep; //Endpoint data structure used during enumeration for uninitialized device
+
+ uint8_t hubCounter; // hub counter is kept
+ // in order to avoid hub address duplication
+
+ UsbDevice thePool[MAX_DEVICES_ALLOWED];
+
+ // Initializes address pool entry
+
+ void InitEntry(uint8_t index) {
+ thePool[index].address.devAddress = 0;
+ thePool[index].epcount = 1;
+ thePool[index].lowspeed = 0;
+ thePool[index].epinfo = &dev0ep;
+ };
+
+ // Returns thePool index for a given address
+
+ uint8_t FindAddressIndex(uint8_t address = 0) {
+ for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) {
+ if(thePool[i].address.devAddress == address)
+ return i;
+ }
+ return 0;
+ };
+
+ // Returns thePool child index for a given parent
+
+ uint8_t FindChildIndex(UsbDeviceAddress addr, uint8_t start = 1) {
+ for(uint8_t i = (start < 1 || start >= MAX_DEVICES_ALLOWED) ? 1 : start; i < MAX_DEVICES_ALLOWED; i++) {
+ if(thePool[i].address.bmParent == addr.bmAddress)
+ return i;
+ }
+ return 0;
+ };
+
+ // Frees address entry specified by index parameter
+
+ void FreeAddressByIndex(uint8_t index) {
+ // Zero field is reserved and should not be affected
+ if(index == 0)
+ return;
+
+ UsbDeviceAddress uda = thePool[index].address;
+ // If a hub was switched off all port addresses should be freed
+ if(uda.bmHub == 1) {
+ for(uint8_t i = 1; (i = FindChildIndex(uda, i));)
+ FreeAddressByIndex(i);
+
+ // If the hub had the last allocated address, hubCounter should be decremented
+ if(hubCounter == uda.bmAddress)
+ hubCounter--;
+ }
+ InitEntry(index);
+ }
+
+ // Initializes the whole address pool at once
+
+ void InitAllAddresses() {
+ for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
+ InitEntry(i);
+
+ hubCounter = 0;
+ };
+
+public:
+
+ AddressPoolImpl() : hubCounter(0) {
+ // Zero address is reserved
+ InitEntry(0);
+
+ thePool[0].address.devAddress = 0;
+ thePool[0].epinfo = &dev0ep;
+ dev0ep.epAddr = 0;
+ dev0ep.maxPktSize = 8;
+ dev0ep.epAttribs = 0; //set DATA0/1 toggles to 0
+ dev0ep.bmNakPower = USB_NAK_MAX_POWER;
+
+ InitAllAddresses();
+ };
+
+ // Returns a pointer to a specified address entry
+
+ virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) {
+ if(!addr)
+ return thePool;
+
+ uint8_t index = FindAddressIndex(addr);
+
+ return (!index) ? NULL : thePool + index;
+ };
+
+ // Performs an operation specified by pfunc for each addressed device
+
+ void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) {
+ if(!pfunc)
+ return;
+
+ for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
+ if(thePool[i].address.devAddress)
+ pfunc(thePool + i);
+ };
+
+ // Allocates new address
+
+ virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) {
+ /* if (parent != 0 && port == 0)
+ USB_HOST_SERIAL.println("PRT:0"); */
+ UsbDeviceAddress _parent;
+ _parent.devAddress = parent;
+ if(_parent.bmReserved || port > 7)
+ //if(parent > 127 || port > 7)
+ return 0;
+
+ if(is_hub && hubCounter == 7)
+ return 0;
+
+ // finds first empty address entry starting from one
+ uint8_t index = FindAddressIndex(0);
+
+ if(!index) // if empty entry is not found
+ return 0;
+
+ if(_parent.devAddress == 0) {
+ if(is_hub) {
+ thePool[index].address.devAddress = 0x41;
+ hubCounter++;
+ } else
+ thePool[index].address.devAddress = 1;
+
+ return thePool[index].address.devAddress;
+ }
+
+ UsbDeviceAddress addr;
+ addr.devAddress = 0; // Ensure all bits are zero
+ addr.bmParent = _parent.bmAddress;
+ if(is_hub) {
+ addr.bmHub = 1;
+ addr.bmAddress = ++hubCounter;
+ } else {
+ addr.bmHub = 0;
+ addr.bmAddress = port;
+ }
+ thePool[index].address = addr;
+ /*
+ USB_HOST_SERIAL.print("Addr:");
+ USB_HOST_SERIAL.print(addr.bmHub, HEX);
+ USB_HOST_SERIAL.print(".");
+ USB_HOST_SERIAL.print(addr.bmParent, HEX);
+ USB_HOST_SERIAL.print(".");
+ USB_HOST_SERIAL.println(addr.bmAddress, HEX);
+ */
+ return thePool[index].address.devAddress;
+ };
+
+ // Empties pool entry
+
+ virtual void FreeAddress(uint8_t addr) {
+ // if the root hub is disconnected all the addresses should be initialized
+ if(addr == 0x41) {
+ InitAllAddresses();
+ return;
+ }
+ uint8_t index = FindAddressIndex(addr);
+ FreeAddressByIndex(index);
+ };
+
+ // Returns number of hubs attached
+ // It can be rather helpfull to find out if there are hubs attached than getting the exact number of hubs.
+ //uint8_t GetNumHubs()
+ //{
+ // return hubCounter;
+ //};
+ //uint8_t GetNumDevices()
+ //{
+ // uint8_t counter = 0;
+
+ // for (uint8_t i=1; i<MAX_DEVICES_ALLOWED; i++)
+ // if (thePool[i].address != 0);
+ // counter ++;
+
+ // return counter;
+ //};
+};
+
+#endif // __ADDRESS_H__
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/adk.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/adk.cpp
new file mode 100644
index 000000000..9e4e0c8d8
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/adk.cpp
@@ -0,0 +1,371 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+
+/* Google ADK interface */
+
+#include "adk.h"
+
+const uint8_t ADK::epDataInIndex = 1;
+const uint8_t ADK::epDataOutIndex = 2;
+
+ADK::ADK(USB *p, const char* manufacturer,
+ const char* model,
+ const char* description,
+ const char* version,
+ const char* uri,
+ const char* serial) :
+
+/* ADK ID Strings */
+manufacturer(manufacturer),
+model(model),
+description(description),
+version(version),
+uri(uri),
+serial(serial),
+pUsb(p), //pointer to USB class instance - mandatory
+bAddress(0), //device address - mandatory
+bConfNum(0), //configuration number
+bNumEP(1), //if config descriptor needs to be parsed
+ready(false) {
+ // initialize endpoint data structures
+ for(uint8_t i = 0; i < ADK_MAX_ENDPOINTS; i++) {
+ epInfo[i].epAddr = 0;
+ epInfo[i].maxPktSize = (i) ? 0 : 8;
+ epInfo[i].epAttribs = 0;
+ epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
+ }//for(uint8_t i=0; i<ADK_MAX_ENDPOINTS; i++...
+
+ // register in USB subsystem
+ if(pUsb) {
+ pUsb->RegisterDeviceClass(this); //set devConfig[] entry
+ }
+}
+
+uint8_t ADK::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {
+ return Init(parent, port, lowspeed); // Just call Init. Yes, really!
+}
+
+/* Connection initialization of an Android phone */
+uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed) {
+ uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
+ USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
+ uint8_t rcode;
+ uint8_t num_of_conf; // number of configurations
+ UsbDevice *p = NULL;
+ EpInfo *oldep_ptr = NULL;
+
+ // get memory address of USB device address pool
+ AddressPool &addrPool = pUsb->GetAddressPool();
+
+ USBTRACE("\r\nADK Init");
+
+ // check if address has already been assigned to an instance
+ if(bAddress) {
+ USBTRACE("\r\nAddress in use");
+ return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
+ }
+
+ // Get pointer to pseudo device with address 0 assigned
+ p = addrPool.GetUsbDevicePtr(0);
+
+ if(!p) {
+ USBTRACE("\r\nAddress not found");
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+ }
+
+ if(!p->epinfo) {
+ USBTRACE("epinfo is null\r\n");
+ return USB_ERROR_EPINFO_IS_NULL;
+ }
+
+ // Save old pointer to EP_RECORD of address 0
+ oldep_ptr = p->epinfo;
+
+ // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
+ p->epinfo = epInfo;
+
+ p->lowspeed = lowspeed;
+
+ // Get device descriptor
+ rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);
+
+ // Restore p->epinfo
+ p->epinfo = oldep_ptr;
+
+ if(rcode) {
+ goto FailGetDevDescr;
+ }
+
+ // Allocate new address according to device class
+ bAddress = addrPool.AllocAddress(parent, false, port);
+
+ // Extract Max Packet Size from device descriptor
+ epInfo[0].maxPktSize = udd->bMaxPacketSize0;
+
+ // Assign new address to the device
+ rcode = pUsb->setAddr(0, 0, bAddress);
+ if(rcode) {
+ p->lowspeed = false;
+ addrPool.FreeAddress(bAddress);
+ bAddress = 0;
+ //USBTRACE2("setAddr:",rcode);
+ return rcode;
+ }//if (rcode...
+
+ //USBTRACE2("\r\nAddr:", bAddress);
+ // Spec says you should wait at least 200ms.
+ //delay(300);
+
+ p->lowspeed = false;
+
+ //get pointer to assigned address record
+ p = addrPool.GetUsbDevicePtr(bAddress);
+ if(!p) {
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+ }
+
+ p->lowspeed = lowspeed;
+
+ // Assign epInfo to epinfo pointer - only EP0 is known
+ rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
+ if(rcode) {
+ goto FailSetDevTblEntry;
+ }
+
+ //check if ADK device is already in accessory mode; if yes, configure and exit
+ if(udd->idVendor == ADK_VID &&
+ (udd->idProduct == ADK_PID || udd->idProduct == ADB_PID)) {
+ USBTRACE("\r\nAcc.mode device detected");
+ /* go through configurations, find first bulk-IN, bulk-OUT EP, fill epInfo and quit */
+ num_of_conf = udd->bNumConfigurations;
+
+ //USBTRACE2("\r\nNC:",num_of_conf);
+ for(uint8_t i = 0; i < num_of_conf; i++) {
+ ConfigDescParser < 0, 0, 0, 0 > confDescrParser(this);
+ delay(1);
+ rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
+#if defined(XOOM)
+ //added by Jaylen Scott Vanorden
+ if(rcode) {
+ USBTRACE2("\r\nGot 1st bad code for config: ", rcode);
+ // Try once more
+ rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
+ }
+#endif
+ if(rcode) {
+ goto FailGetConfDescr;
+ }
+ if(bNumEP > 2) {
+ break;
+ }
+ } // for (uint8_t i=0; i<num_of_conf; i++...
+
+ if(bNumEP == 3) {
+ // Assign epInfo to epinfo pointer - this time all 3 endpoins
+ rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo);
+ if(rcode) {
+ goto FailSetDevTblEntry;
+ }
+ }
+
+ // Set Configuration Value
+ rcode = pUsb->setConf(bAddress, 0, bConfNum);
+ if(rcode) {
+ goto FailSetConfDescr;
+ }
+ /* print endpoint structure */
+ /*
+ USBTRACE("\r\nEndpoint Structure:");
+ USBTRACE("\r\nEP0:");
+ USBTRACE2("\r\nAddr: ", epInfo[0].epAddr);
+ USBTRACE2("\r\nMax.pkt.size: ", epInfo[0].maxPktSize);
+ USBTRACE2("\r\nAttr: ", epInfo[0].epAttribs);
+ USBTRACE("\r\nEpout:");
+ USBTRACE2("\r\nAddr: ", epInfo[epDataOutIndex].epAddr);
+ USBTRACE2("\r\nMax.pkt.size: ", epInfo[epDataOutIndex].maxPktSize);
+ USBTRACE2("\r\nAttr: ", epInfo[epDataOutIndex].epAttribs);
+ USBTRACE("\r\nEpin:");
+ USBTRACE2("\r\nAddr: ", epInfo[epDataInIndex].epAddr);
+ USBTRACE2("\r\nMax.pkt.size: ", epInfo[epDataInIndex].maxPktSize);
+ USBTRACE2("\r\nAttr: ", epInfo[epDataInIndex].epAttribs);
+ */
+
+ USBTRACE("\r\nConfiguration successful");
+ ready = true;
+ return 0; //successful configuration
+ }//if( buf->idVendor == ADK_VID...
+
+ //probe device - get accessory protocol revision
+ {
+ uint16_t adkproto = -1;
+ delay(1);
+ rcode = getProto((uint8_t*) & adkproto);
+#if defined(XOOM)
+ //added by Jaylen Scott Vanorden
+ if(rcode) {
+ USBTRACE2("\r\nGot 1st bad code for proto: ", rcode);
+ // Try once more
+ rcode = getProto((uint8_t*) & adkproto);
+ }
+#endif
+ if(rcode) {
+ goto FailGetProto; //init fails
+ }
+ USBTRACE2("\r\nADK protocol rev. ", adkproto);
+ }
+
+ delay(100);
+
+ //sending ID strings
+ sendStr(ACCESSORY_STRING_MANUFACTURER, manufacturer);
+ delay(10);
+ sendStr(ACCESSORY_STRING_MODEL, model);
+ delay(10);
+ sendStr(ACCESSORY_STRING_DESCRIPTION, description);
+ delay(10);
+ sendStr(ACCESSORY_STRING_VERSION, version);
+ delay(10);
+ sendStr(ACCESSORY_STRING_URI, uri);
+ delay(10);
+ sendStr(ACCESSORY_STRING_SERIAL, serial);
+
+ delay(100);
+
+ //switch to accessory mode
+ //the Android phone will reset
+ rcode = switchAcc();
+ if(rcode) {
+ goto FailSwAcc; //init fails
+ }
+ rcode = USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET;
+ delay(100); // Give Android a chance to do its reset. This is a guess, and possibly could be lower.
+ goto SwAttempt; //switch to accessory mode attempted
+
+ /* diagnostic messages */
+FailGetDevDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailGetDevDescr(rcode);
+ goto Fail;
+#endif
+
+FailSetDevTblEntry:
+#ifdef DEBUG_USB_HOST
+ NotifyFailSetDevTblEntry(rcode);
+ goto Fail;
+#endif
+
+FailGetConfDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailGetConfDescr(rcode);
+ goto Fail;
+#endif
+
+FailSetConfDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailSetConfDescr(rcode);
+ goto Fail;
+#endif
+
+FailGetProto:
+#ifdef DEBUG_USB_HOST
+ USBTRACE("\r\ngetProto:");
+ goto Fail;
+#endif
+
+FailSwAcc:
+#ifdef DEBUG_USB_HOST
+ USBTRACE("\r\nswAcc:");
+ goto Fail;
+#endif
+
+ //FailOnInit:
+ // USBTRACE("OnInit:");
+ // goto Fail;
+ //
+SwAttempt:
+#ifdef DEBUG_USB_HOST
+ USBTRACE("\r\nAccessory mode switch attempt");
+Fail:
+#endif
+ //USBTRACE2("\r\nADK Init Failed, error code: ", rcode);
+ //NotifyFail(rcode);
+ Release();
+ return rcode;
+}
+
+/* Extracts bulk-IN and bulk-OUT endpoint information from config descriptor */
+void ADK::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {
+ //ErrorMessage<uint8_t>(PSTR("Conf.Val"), conf);
+ //ErrorMessage<uint8_t>(PSTR("Iface Num"), iface);
+ //ErrorMessage<uint8_t>(PSTR("Alt.Set"), alt);
+
+ //added by Yuuichi Akagawa
+ if(bNumEP == 3) {
+ return;
+ }
+
+ bConfNum = conf;
+
+ if((pep->bmAttributes & 0x02) == 2) {
+ uint8_t index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
+ // Fill in the endpoint info structure
+ epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
+ epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
+
+ bNumEP++;
+
+ //PrintEndpointDescriptor(pep);
+ }
+}
+
+/* Performs a cleanup after failed Init() attempt */
+uint8_t ADK::Release() {
+ pUsb->GetAddressPool().FreeAddress(bAddress);
+
+ bNumEP = 1; //must have to be reset to 1
+
+ bAddress = 0;
+ ready = false;
+ return 0;
+}
+
+uint8_t ADK::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr) {
+ //USBTRACE2("\r\nAddr: ", bAddress );
+ //USBTRACE2("\r\nEP: ",epInfo[epDataInIndex].epAddr);
+ return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr);
+}
+
+uint8_t ADK::SndData(uint16_t nbytes, uint8_t *dataptr) {
+ return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr);
+}
+
+void ADK::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) {
+ Notify(PSTR("Endpoint descriptor:"), 0x80);
+ Notify(PSTR("\r\nLength:\t\t"), 0x80);
+ D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
+ Notify(PSTR("\r\nType:\t\t"), 0x80);
+ D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
+ Notify(PSTR("\r\nAddress:\t"), 0x80);
+ D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
+ Notify(PSTR("\r\nAttributes:\t"), 0x80);
+ D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
+ Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
+ D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
+ Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
+ D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
+ Notify(PSTR("\r\n"), 0x80);
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/adk.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/adk.h
new file mode 100644
index 000000000..4a2920b88
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/adk.h
@@ -0,0 +1,140 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+
+/* Google ADK interface support header */
+
+#if !defined(_ADK_H_)
+#define _ADK_H_
+
+#include "Usb.h"
+
+#define ADK_VID 0x18D1
+#define ADK_PID 0x2D00
+#define ADB_PID 0x2D01
+
+#define XOOM //enables repeating getProto() and getConf() attempts
+//necessary for slow devices such as Motorola XOOM
+//defined by default, can be commented out to save memory
+
+/* requests */
+
+#define ADK_GETPROTO 51 //check USB accessory protocol version
+#define ADK_SENDSTR 52 //send identifying string
+#define ADK_ACCSTART 53 //start device in accessory mode
+
+#define bmREQ_ADK_GET USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_VENDOR|USB_SETUP_RECIPIENT_DEVICE
+#define bmREQ_ADK_SEND USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_VENDOR|USB_SETUP_RECIPIENT_DEVICE
+
+#define ACCESSORY_STRING_MANUFACTURER 0
+#define ACCESSORY_STRING_MODEL 1
+#define ACCESSORY_STRING_DESCRIPTION 2
+#define ACCESSORY_STRING_VERSION 3
+#define ACCESSORY_STRING_URI 4
+#define ACCESSORY_STRING_SERIAL 5
+
+#define ADK_MAX_ENDPOINTS 3 //endpoint 0, bulk_IN, bulk_OUT
+
+class ADK;
+
+class ADK : public USBDeviceConfig, public UsbConfigXtracter {
+private:
+ /* ID strings */
+ const char* manufacturer;
+ const char* model;
+ const char* description;
+ const char* version;
+ const char* uri;
+ const char* serial;
+
+ /* ADK proprietary requests */
+ uint8_t getProto(uint8_t* adkproto);
+ uint8_t sendStr(uint8_t index, const char* str);
+ uint8_t switchAcc(void);
+
+protected:
+ static const uint8_t epDataInIndex; // DataIn endpoint index
+ static const uint8_t epDataOutIndex; // DataOUT endpoint index
+
+ /* mandatory members */
+ USB *pUsb;
+ uint8_t bAddress;
+ uint8_t bConfNum; // configuration number
+
+ uint8_t bNumEP; // total number of EP in the configuration
+ bool ready;
+
+ /* Endpoint data structure */
+ EpInfo epInfo[ADK_MAX_ENDPOINTS];
+
+ void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr);
+
+public:
+ ADK(USB *pUsb, const char* manufacturer,
+ const char* model,
+ const char* description,
+ const char* version,
+ const char* uri,
+ const char* serial);
+
+ // Methods for receiving and sending data
+ uint8_t RcvData(uint16_t *nbytesptr, uint8_t *dataptr);
+ uint8_t SndData(uint16_t nbytes, uint8_t *dataptr);
+
+
+ // USBDeviceConfig implementation
+ uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed);
+ uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
+ uint8_t Release();
+
+ virtual uint8_t Poll() {
+ return 0;
+ };
+
+ virtual uint8_t GetAddress() {
+ return bAddress;
+ };
+
+ virtual bool isReady() {
+ return ready;
+ };
+
+ virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {
+ return (vid == ADK_VID && (pid == ADK_PID || pid == ADB_PID));
+ };
+
+ //UsbConfigXtracter implementation
+ void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
+}; //class ADK : public USBDeviceConfig ...
+
+/* get ADK protocol version */
+
+/* returns 2 bytes in *adkproto */
+inline uint8_t ADK::getProto(uint8_t* adkproto) {
+ return ( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_GET, ADK_GETPROTO, 0, 0, 0, 2, 2, adkproto, NULL));
+}
+
+/* send ADK string */
+inline uint8_t ADK::sendStr(uint8_t index, const char* str) {
+ return ( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_SEND, ADK_SENDSTR, 0, 0, index, strlen(str) + 1, strlen(str) + 1, (uint8_t*)str, NULL));
+}
+
+/* switch to accessory mode */
+inline uint8_t ADK::switchAcc(void) {
+ return ( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_SEND, ADK_ACCSTART, 0, 0, 0, 0, 0, NULL, NULL));
+}
+
+#endif // _ADK_H_
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/avrpins.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/avrpins.h
new file mode 100644
index 000000000..4e60e3a22
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/avrpins.h
@@ -0,0 +1,1130 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+
+/* derived from Konstantin Chizhov's AVR port templates */
+
+#if !defined(_usb_h_) || defined(_avrpins_h_)
+#error "Never include avrpins.h directly; include Usb.h instead"
+#else
+#define _avrpins_h_
+
+#if defined(__AVR__)
+
+// pointers are 16 bits on AVR
+#define pgm_read_pointer(p) pgm_read_word(p)
+
+// Support for these boards needs to be manually activated in settings.h or in a makefile
+#if !defined(BOARD_MEGA_ADK) && defined(__AVR_ATmega2560__) && (USE_UHS_MEGA_ADK || defined(ARDUINO_AVR_ADK))
+#define BOARD_MEGA_ADK
+#elif !defined(BOARD_BLACK_WIDDOW) && USE_UHS_BLACK_WIDDOW
+#define BOARD_BLACK_WIDDOW
+#endif
+
+#ifdef PORTA
+#define USE_PORTA
+#endif
+#ifdef PORTB
+#define USE_PORTB
+#endif
+#ifdef PORTC
+#define USE_PORTC
+#endif
+#ifdef PORTD
+#define USE_PORTD
+#endif
+#ifdef PORTE
+#define USE_PORTE
+#endif
+#ifdef PORTF
+#define USE_PORTF
+#endif
+#ifdef PORTG
+#define USE_PORTG
+#endif
+#ifdef PORTH
+#define USE_PORTH
+#endif
+#ifdef PORTJ
+#define USE_PORTJ
+#endif
+#ifdef PORTK
+#define USE_PORTK
+#endif
+#ifdef PORTL
+#define USE_PORTL
+#endif
+#ifdef PORTQ
+#define USE_PORTQ
+#endif
+#ifdef PORTR
+#define USE_PORTR
+#endif
+
+#ifdef TCCR0A
+#define USE_TCCR0A
+#endif
+#ifdef TCCR1A
+#define USE_TCCR1A
+#endif
+#ifdef TCCR2A
+#define USE_TCCR2A
+#endif
+
+//Port definitions for AtTiny, AtMega families.
+
+#define MAKE_PORT(portName, ddrName, pinName, className, ID) \
+ class className{\
+ public:\
+ typedef uint8_t DataT;\
+ public:\
+ static void Write(DataT value){portName = value;}\
+ static void ClearAndSet(DataT clearMask, DataT value){portName = (portName & ~clearMask) | value;}\
+ static DataT Read(){return portName;}\
+ static void DirWrite(DataT value){ddrName = value;}\
+ static DataT DirRead(){return ddrName;}\
+ static void Set(DataT value){portName |= value;}\
+ static void Clear(DataT value){portName &= ~value;}\
+ static void Toggle(DataT value){portName ^= value;}\
+ static void DirSet(DataT value){ddrName |= value;}\
+ static void DirClear(DataT value){ddrName &= ~value;}\
+ static void DirToggle(DataT value){ddrName ^= value;}\
+ static DataT PinRead(){return pinName;}\
+ enum{Id = ID};\
+ enum{Width=sizeof(DataT)*8};\
+ };
+
+// TCCR registers to set/clear Arduino PWM
+#define MAKE_TCCR(TccrName, className) \
+ class className{\
+ public:\
+ typedef uint8_t DataT;\
+ public:\
+ static void Write(DataT value){TccrName = value;}\
+ static void ClearAndSet(DataT clearMask, DataT value){TccrName = (TccrName & ~clearMask) | value;}\
+ static DataT Read(){return TccrName;}\
+ static void Set(DataT value){TccrName |= value;}\
+ static void Clear(DataT value){TccrName &= ~value;}\
+ static void Toggle(DataT value){TccrName ^= value;}\
+ enum{Width=sizeof(DataT)*8};\
+ };
+
+#ifdef USE_PORTA
+
+MAKE_PORT(PORTA, DDRA, PINA, Porta, 'A')
+#endif
+#ifdef USE_PORTB
+MAKE_PORT(PORTB, DDRB, PINB, Portb, 'B')
+#endif
+#ifdef USE_PORTC
+MAKE_PORT(PORTC, DDRC, PINC, Portc, 'C')
+#endif
+#ifdef USE_PORTD
+MAKE_PORT(PORTD, DDRD, PIND, Portd, 'D')
+#endif
+#ifdef USE_PORTE
+MAKE_PORT(PORTE, DDRE, PINE, Porte, 'E')
+#endif
+#ifdef USE_PORTF
+MAKE_PORT(PORTF, DDRF, PINF, Portf, 'F')
+#endif
+#ifdef USE_PORTG
+MAKE_PORT(PORTG, DDRG, PING, Portg, 'G')
+#endif
+#ifdef USE_PORTH
+MAKE_PORT(PORTH, DDRH, PINH, Porth, 'H')
+#endif
+#ifdef USE_PORTJ
+MAKE_PORT(PORTJ, DDRJ, PINJ, Portj, 'J')
+#endif
+#ifdef USE_PORTK
+MAKE_PORT(PORTK, DDRK, PINK, Portk, 'K')
+#endif
+#ifdef USE_PORTL
+MAKE_PORT(PORTL, DDRL, PINL, Portl, 'L')
+#endif
+#ifdef USE_PORTQ
+MAKE_PORT(PORTQ, DDRQ, PINQ, Portq, 'Q')
+#endif
+#ifdef USE_PORTR
+MAKE_PORT(PORTR, DDRR, PINR, Portr, 'R')
+#endif
+
+#ifdef USE_TCCR0A
+MAKE_TCCR(TCCR0A, Tccr0a)
+#endif
+#ifdef USE_TCCR1A
+MAKE_TCCR(TCCR1A, Tccr1a)
+#endif
+#ifdef USE_TCCR2A
+MAKE_TCCR(TCCR2A, Tccr2a)
+#endif
+
+// this class represents one pin in a IO port.
+// It is fully static.
+template<typename PORT, uint8_t PIN>
+class TPin {
+ // BOOST_STATIC_ASSERT(PIN < PORT::Width);
+public:
+ typedef PORT Port;
+
+ enum {
+ Number = PIN
+ };
+
+ static void Set() {
+ PORT::Set(1 << PIN);
+ }
+
+ static void Set(uint8_t val) {
+ if(val)
+ Set();
+ else Clear();
+ }
+
+ static void SetDir(uint8_t val) {
+ if(val)
+ SetDirWrite();
+ else SetDirRead();
+ }
+
+ static void Clear() {
+ PORT::Clear(1 << PIN);
+ }
+
+ static void Toggle() {
+ PORT::Toggle(1 << PIN);
+ }
+
+ static void SetDirRead() {
+ PORT::DirClear(1 << PIN);
+ }
+
+ static void SetDirWrite() {
+ PORT::DirSet(1 << PIN);
+ }
+
+ static uint8_t IsSet() {
+ return PORT::PinRead() & (uint8_t)(1 << PIN);
+ }
+
+ static void WaiteForSet() {
+ while(IsSet() == 0) {
+ }
+ }
+
+ static void WaiteForClear() {
+ while(IsSet()) {
+ }
+ }
+}; //class TPin...
+
+// this class represents one bit in TCCR port.
+// used to set/clear TCCRx bits
+// It is fully static.
+
+template<typename TCCR, uint8_t COM>
+class TCom {
+ // BOOST_STATIC_ASSERT(PIN < PORT::Width);
+public:
+ typedef TCCR Tccr;
+
+ enum {
+ Com = COM
+ };
+
+ static void Set() {
+ TCCR::Set(1 << COM);
+ }
+
+ static void Clear() {
+ TCCR::Clear(1 << COM);
+ }
+
+ static void Toggle() {
+ TCCR::Toggle(1 << COM);
+ }
+}; //class TCom...
+
+//Short pin definitions
+#ifdef USE_PORTA
+typedef TPin<Porta, 0 > Pa0;
+typedef TPin<Porta, 1 > Pa1;
+typedef TPin<Porta, 2 > Pa2;
+typedef TPin<Porta, 3 > Pa3;
+typedef TPin<Porta, 4 > Pa4;
+typedef TPin<Porta, 5 > Pa5;
+typedef TPin<Porta, 6 > Pa6;
+typedef TPin<Porta, 7 > Pa7;
+#endif
+
+#ifdef USE_PORTB
+typedef TPin<Portb, 0 > Pb0;
+typedef TPin<Portb, 1 > Pb1;
+typedef TPin<Portb, 2 > Pb2;
+typedef TPin<Portb, 3 > Pb3;
+typedef TPin<Portb, 4 > Pb4;
+typedef TPin<Portb, 5 > Pb5;
+typedef TPin<Portb, 6 > Pb6;
+typedef TPin<Portb, 7 > Pb7;
+#endif
+
+#ifdef USE_PORTC
+typedef TPin<Portc, 0 > Pc0;
+typedef TPin<Portc, 1 > Pc1;
+typedef TPin<Portc, 2 > Pc2;
+typedef TPin<Portc, 3 > Pc3;
+typedef TPin<Portc, 4 > Pc4;
+typedef TPin<Portc, 5 > Pc5;
+typedef TPin<Portc, 6 > Pc6;
+typedef TPin<Portc, 7 > Pc7;
+#endif
+
+#ifdef USE_PORTD
+typedef TPin<Portd, 0 > Pd0;
+typedef TPin<Portd, 1 > Pd1;
+typedef TPin<Portd, 2 > Pd2;
+typedef TPin<Portd, 3 > Pd3;
+typedef TPin<Portd, 4 > Pd4;
+typedef TPin<Portd, 5 > Pd5;
+typedef TPin<Portd, 6 > Pd6;
+typedef TPin<Portd, 7 > Pd7;
+#endif
+
+#ifdef USE_PORTE
+typedef TPin<Porte, 0 > Pe0;
+typedef TPin<Porte, 1 > Pe1;
+typedef TPin<Porte, 2 > Pe2;
+typedef TPin<Porte, 3 > Pe3;
+typedef TPin<Porte, 4 > Pe4;
+typedef TPin<Porte, 5 > Pe5;
+typedef TPin<Porte, 6 > Pe6;
+typedef TPin<Porte, 7 > Pe7;
+#endif
+
+#ifdef USE_PORTF
+typedef TPin<Portf, 0 > Pf0;
+typedef TPin<Portf, 1 > Pf1;
+typedef TPin<Portf, 2 > Pf2;
+typedef TPin<Portf, 3 > Pf3;
+typedef TPin<Portf, 4 > Pf4;
+typedef TPin<Portf, 5 > Pf5;
+typedef TPin<Portf, 6 > Pf6;
+typedef TPin<Portf, 7 > Pf7;
+#endif
+
+#ifdef USE_PORTG
+typedef TPin<Portg, 0 > Pg0;
+typedef TPin<Portg, 1 > Pg1;
+typedef TPin<Portg, 2 > Pg2;
+typedef TPin<Portg, 3 > Pg3;
+typedef TPin<Portg, 4 > Pg4;
+typedef TPin<Portg, 5 > Pg5;
+typedef TPin<Portg, 6 > Pg6;
+typedef TPin<Portg, 7 > Pg7;
+#endif
+
+#ifdef USE_PORTH
+typedef TPin<Porth, 0 > Ph0;
+typedef TPin<Porth, 1 > Ph1;
+typedef TPin<Porth, 2 > Ph2;
+typedef TPin<Porth, 3 > Ph3;
+typedef TPin<Porth, 4 > Ph4;
+typedef TPin<Porth, 5 > Ph5;
+typedef TPin<Porth, 6 > Ph6;
+typedef TPin<Porth, 7 > Ph7;
+#endif
+
+#ifdef USE_PORTJ
+typedef TPin<Portj, 0 > Pj0;
+typedef TPin<Portj, 1 > Pj1;
+typedef TPin<Portj, 2 > Pj2;
+typedef TPin<Portj, 3 > Pj3;
+typedef TPin<Portj, 4 > Pj4;
+typedef TPin<Portj, 5 > Pj5;
+typedef TPin<Portj, 6 > Pj6;
+typedef TPin<Portj, 7 > Pj7;
+#endif
+
+#ifdef USE_PORTK
+typedef TPin<Portk, 0 > Pk0;
+typedef TPin<Portk, 1 > Pk1;
+typedef TPin<Portk, 2 > Pk2;
+typedef TPin<Portk, 3 > Pk3;
+typedef TPin<Portk, 4 > Pk4;
+typedef TPin<Portk, 5 > Pk5;
+typedef TPin<Portk, 6 > Pk6;
+typedef TPin<Portk, 7 > Pk7;
+#endif
+
+#ifdef USE_PORTL
+typedef TPin<Portl, 0 > Pl0;
+typedef TPin<Portl, 1 > Pl1;
+typedef TPin<Portl, 2 > Pl2;
+typedef TPin<Portl, 3 > Pl3;
+typedef TPin<Portl, 4 > Pl4;
+typedef TPin<Portl, 5 > Pl5;
+typedef TPin<Portl, 6 > Pl6;
+typedef TPin<Portl, 7 > Pl7;
+#endif
+
+#ifdef USE_PORTQ
+typedef TPin<Portq, 0 > Pq0;
+typedef TPin<Portq, 1 > Pq1;
+typedef TPin<Portq, 2 > Pq2;
+typedef TPin<Portq, 3 > Pq3;
+typedef TPin<Portq, 4 > Pq4;
+typedef TPin<Portq, 5 > Pq5;
+typedef TPin<Portq, 6 > Pq6;
+typedef TPin<Portq, 7 > Pq7;
+#endif
+
+#ifdef USE_PORTR
+typedef TPin<Portr, 0 > Pr0;
+typedef TPin<Portr, 1 > Pr1;
+typedef TPin<Portr, 2 > Pr2;
+typedef TPin<Portr, 3 > Pr3;
+typedef TPin<Portr, 4 > Pr4;
+typedef TPin<Portr, 5 > Pr5;
+typedef TPin<Portr, 6 > Pr6;
+typedef TPin<Portr, 7 > Pr7;
+#endif
+
+#ifdef USE_TCCR0A
+typedef TCom<Tccr0a, COM0A1> Tc0a; //P6
+typedef TCom<Tccr0a, COM0B1> Tc0b; //P5
+#endif
+
+#ifdef USE_TCCR1A
+typedef TCom<Tccr1a, COM1A1> Tc1a; //P9
+typedef TCom<Tccr1a, COM1B1> Tc1b; //P10
+#endif
+
+#ifdef USE_TCCR2A
+typedef TCom<Tccr2a, COM2A1> Tc2a; //P11
+typedef TCom<Tccr2a, COM2B1> Tc2b; //P3
+#endif
+
+template<typename Tp_pin, typename Tc_bit>
+class Tp_Tc {
+public:
+
+ static void SetDir(uint8_t val) {
+ if(val)
+ SetDirWrite();
+ else SetDirRead();
+ }
+
+ static void SetDirRead() {
+ Tp_pin::SetDirRead(); //set pin direction
+ Tc_bit::Clear(); //disconnect pin from PWM
+ }
+
+ static void SetDirWrite() {
+ Tp_pin::SetDirWrite();
+ Tc_bit::Clear();
+ }
+};
+
+/* pin definitions for cases where it's necessary to clear compare output mode bits */
+
+//typedef Tp_Tc<Pd3, Tc2b> P3; //Arduino pin 3
+//typedef Tp_Tc<Pd5, Tc0b> P5; //Arduino pin 5
+//typedef Tp_Tc<Pd6, Tc0a> P6; //Arduino pin 6
+//typedef Tp_Tc<Pb1, Tc1a> P9; //Arduino pin 9
+//typedef Tp_Tc<Pb2, Tc1b> P10; //Arduino pin 10
+//typedef Tp_Tc<Pb3, Tc2a> P11; //Arduino pin 11
+
+/* Arduino pin definitions */
+#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
+// "Mega" Arduino pin numbers
+
+#define P0 Pe0
+#define P1 Pe1
+#define P2 Pe4
+#define P3 Pe5
+#define P4 Pg5
+#define P5 Pe3
+#define P6 Ph3
+#define P7 Ph4
+
+#define P8 Ph5
+#define P9 Ph6
+#define P10 Pb4
+#define P11 Pb5
+#define P12 Pb6
+#define P13 Pb7
+
+#define P14 Pj1
+#define P15 Pj0
+#define P16 Ph1
+#define P17 Ph0
+#define P18 Pd3
+#define P19 Pd2
+#define P20 Pd1
+#define P21 Pd0
+
+#define P22 Pa0
+#define P23 Pa1
+#define P24 Pa2
+#define P25 Pa3
+#define P26 Pa4
+#define P27 Pa5
+#define P28 Pa6
+#define P29 Pa7
+#define P30 Pc7
+#define P31 Pc6
+#define P32 Pc5
+#define P33 Pc4
+#define P34 Pc3
+#define P35 Pc2
+#define P36 Pc1
+#define P37 Pc0
+
+#define P38 Pd7
+#define P39 Pg2
+#define P40 Pg1
+#define P41 Pg0
+#define P42 Pl7
+#define P43 Pl6
+#define P44 Pl5
+#define P45 Pl4
+#define P46 Pl3
+#define P47 Pl2
+#define P48 Pl1
+#define P49 Pl0
+#define P50 Pb3
+#define P51 Pb2
+#define P52 Pb1
+#define P53 Pb0
+
+#ifdef BOARD_MEGA_ADK // These pins are not broken out on the Arduino ADK
+#define P54 Pe6 // INT on Arduino ADK
+#define P55 Pj2 // MAX_RESET on Arduino ADK
+#endif
+
+// "Mega" pin numbers
+
+#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
+// "Classic" Arduino pin numbers
+
+#define P0 Pd0
+#define P1 Pd1
+#define P2 Pd2
+#define P3 Pd3
+#define P4 Pd4
+#define P5 Pd5
+#define P6 Pd6
+#define P7 Pd7
+
+#define P8 Pb0
+#define P9 Pb1
+#define P10 Pb2
+#define P11 Pb3
+#define P12 Pb4
+#define P13 Pb5
+
+#define P14 Pc0
+#define P15 Pc1
+#define P16 Pc2
+#define P17 Pc3
+#define P18 Pc4
+#define P19 Pc5
+
+// "Classic" Arduino pin numbers
+
+#elif defined(CORE_TEENSY) && defined(__AVR_ATmega32U4__)
+// Teensy 2.0 pin numbers
+// http://www.pjrc.com/teensy/pinout.html
+#define P0 Pb0
+#define P1 Pb1
+#define P2 Pb2
+#define P3 Pb3
+#define P4 Pb7
+#define P5 Pd0
+#define P6 Pd1
+#define P7 Pd2
+#define P8 Pd3
+#define P9 Pc6
+#define P10 Pc7
+#define P11 Pd6
+#define P12 Pd7
+#define P13 Pb4
+#define P14 Pb5
+#define P15 Pb6
+#define P16 Pf7
+#define P17 Pf6
+#define P18 Pf5
+#define P19 Pf4
+#define P20 Pf1
+#define P21 Pf0
+#define P22 Pd4
+#define P23 Pd5
+#define P24 Pe6
+// Teensy 2.0
+
+#elif defined(__AVR_ATmega32U4__)
+// Arduino Leonardo pin numbers
+
+#define P0 Pd2 // D0 - PD2
+#define P1 Pd3 // D1 - PD3
+#define P2 Pd1 // D2 - PD1
+#define P3 Pd0 // D3 - PD0
+#define P4 Pd4 // D4 - PD4
+#define P5 Pc6 // D5 - PC6
+#define P6 Pd7 // D6 - PD7
+#define P7 Pe6 // D7 - PE6
+
+#define P8 Pb4 // D8 - PB4
+#define P9 Pb5 // D9 - PB5
+#define P10 Pb6 // D10 - PB6
+#define P11 Pb7 // D11 - PB7
+#define P12 Pd6 // D12 - PD6
+#define P13 Pc7 // D13 - PC7
+
+#define P14 Pb3 // D14 - MISO - PB3
+#define P15 Pb1 // D15 - SCK - PB1
+#define P16 Pb2 // D16 - MOSI - PB2
+#define P17 Pb0 // D17 - SS - PB0
+
+#define P18 Pf7 // D18 - A0 - PF7
+#define P19 Pf6 // D19 - A1 - PF6
+#define P20 Pf5 // D20 - A2 - PF5
+#define P21 Pf4 // D21 - A3 - PF4
+#define P22 Pf1 // D22 - A4 - PF1
+#define P23 Pf0 // D23 - A5 - PF0
+
+#define P24 Pd4 // D24 / D4 - A6 - PD4
+#define P25 Pd7 // D25 / D6 - A7 - PD7
+#define P26 Pb4 // D26 / D8 - A8 - PB4
+#define P27 Pb5 // D27 / D9 - A9 - PB5
+#define P28 Pb6 // D28 / D10 - A10 - PB6
+#define P29 Pd6 // D29 / D12 - A11 - PD6
+
+// Arduino Leonardo pin numbers
+
+#elif defined(CORE_TEENSY) && (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__))
+// Teensy++ 1.0 and 2.0 pin numbers
+// http://www.pjrc.com/teensy/pinout.html
+#define P0 Pd0
+#define P1 Pd1
+#define P2 Pd2
+#define P3 Pd3
+#define P4 Pd4
+#define P5 Pd5
+#define P6 Pd6
+#define P7 Pd7
+#define P8 Pe0
+#define P9 Pe1
+#define P10 Pc0
+#define P11 Pc1
+#define P12 Pc2
+#define P13 Pc3
+#define P14 Pc4
+#define P15 Pc5
+#define P16 Pc6
+#define P17 Pc7
+#define P18 Pe6
+#define P19 Pe7
+#define P20 Pb0
+#define P21 Pb1
+#define P22 Pb2
+#define P23 Pb3
+#define P24 Pb4
+#define P25 Pb5
+#define P26 Pb6
+#define P27 Pb7
+#define P28 Pa0
+#define P29 Pa1
+#define P30 Pa2
+#define P31 Pa3
+#define P32 Pa4
+#define P33 Pa5
+#define P34 Pa6
+#define P35 Pa7
+#define P36 Pe4
+#define P37 Pe5
+#define P38 Pf0
+#define P39 Pf1
+#define P40 Pf2
+#define P41 Pf3
+#define P42 Pf4
+#define P43 Pf5
+#define P44 Pf6
+#define P45 Pf7
+// Teensy++ 1.0 and 2.0
+
+#elif defined(ARDUINO_AVR_BALANDUINO) && (defined(__AVR_ATmega644__) || defined(__AVR_ATmega1284P__))
+// Balanduino pin numbers
+// http://balanduino.net/
+#define P0 Pd0 /* 0 - PD0 */
+#define P1 Pd1 /* 1 - PD1 */
+
+#if BALANDUINO_REVISION < 13
+ #define P2 Pb2 /* 2 - PB2 */
+ #define P3 Pd6 /* 3 - PD6 */
+ #define P4 Pd7 /* 4 - PD7 */
+ #define P5 Pb3 /* 5 - PB3 */
+#else
+ #define P2 Pd2 /* 2 - PD2 */
+ #define P3 Pd3 /* 3 - PD3 */
+ #define P4 Pd6 /* 4 - PD6 */
+ #define P5 Pd7 /* 5 - PD7 */
+#endif
+
+#define P6 Pb4 /* 6 - PB4 */
+#define P7 Pa0 /* 7 - PA0 */
+#define P8 Pa1 /* 8 - PA1 */
+#define P9 Pa2 /* 9 - PA2 */
+#define P10 Pa3 /* 10 - PA3 */
+#define P11 Pa4 /* 11 - PA4 */
+#define P12 Pa5 /* 12 - PA5 */
+#define P13 Pc1 /* 13 - PC1 */
+#define P14 Pc0 /* 14 - PC0 */
+
+#if BALANDUINO_REVISION < 13
+ #define P15 Pd2 /* 15 - PD2 */
+ #define P16 Pd3 /* 16 - PD3 */
+#else
+ #define P15 Pb2 /* 15 - PB2 */
+ #define P16 Pb3 /* 16 - PB2 */
+#endif
+
+#define P17 Pd4 /* 17 - PD4 */
+#define P18 Pd5 /* 18 - PD5 */
+#define P19 Pc2 /* 19 - PC2 */
+#define P20 Pc3 /* 20 - PC3 */
+#define P21 Pc4 /* 21 - PC4 */
+#define P22 Pc5 /* 22 - PC5 */
+#define P23 Pc6 /* 23 - PC6 */
+#define P24 Pc7 /* 24 - PC7 */
+#define P25 Pb0 /* 25 - PB0 */
+#define P26 Pb1 /* 26 - PB1 */
+#define P27 Pb5 /* 27 - PB5 */
+#define P28 Pb6 /* 28 - PB6 */
+#define P29 Pb7 /* 29 - PB7 */
+#define P30 Pa6 /* 30 - PA6 */
+#define P31 Pa7 /* 31 - PA7 */
+// Balanduino
+
+#elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__)
+// Sanguino pin numbers
+// Homepage: http://sanguino.cc/hardware
+// Hardware add-on: https://github.com/Lauszus/Sanguino
+#define P0 Pb0
+#define P1 Pb1
+#define P2 Pb2
+#define P3 Pb3
+#define P4 Pb4
+#define P5 Pb5
+#define P6 Pb6
+#define P7 Pb7
+#define P8 Pd0
+#define P9 Pd1
+#define P10 Pd2
+#define P11 Pd3
+#define P12 Pd4
+#define P13 Pd5
+#define P14 Pd6
+#define P15 Pd7
+#define P16 Pc0
+#define P17 Pc1
+#define P18 Pc2
+#define P19 Pc3
+#define P20 Pc4
+#define P21 Pc5
+#define P22 Pc6
+#define P23 Pc7
+#define P24 Pa0
+#define P25 Pa1
+#define P26 Pa2
+#define P27 Pa3
+#define P28 Pa4
+#define P29 Pa5
+#define P30 Pa6
+#define P31 Pa7
+// Sanguino
+
+#else
+#error "Please define board in avrpins.h"
+
+#endif // Arduino pin definitions
+
+#elif defined(__arm__)
+
+// pointers are 32 bits on ARM
+#define pgm_read_pointer(p) pgm_read_dword(p)
+
+#if defined(CORE_TEENSY) && (defined(__MK20DX128__) || defined(__MK20DX256__))
+
+#include "core_pins.h"
+#include "avr_emulation.h"
+
+#define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000)
+#define GPIO_BITBAND_PTR(reg, bit) ((uint8_t *)GPIO_BITBAND_ADDR((reg), (bit)))
+
+#define MAKE_PIN(className, baseReg, pinNum, configReg) \
+class className { \
+public: \
+ static void Set() { \
+ *GPIO_BITBAND_PTR(baseReg, pinNum) = 1; \
+ } \
+ static void Clear() { \
+ *GPIO_BITBAND_PTR(baseReg, pinNum) = 0; \
+ } \
+ static void SetDirRead() { \
+ configReg = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); \
+ *(GPIO_BITBAND_PTR(baseReg, pinNum) + 640) = 0; \
+ } \
+ static void SetDirWrite() { \
+ configReg = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); \
+ *(GPIO_BITBAND_PTR(baseReg, pinNum) + 640) = 1; \
+ } \
+ static uint8_t IsSet() { \
+ return *(GPIO_BITBAND_PTR(baseReg, pinNum) + 512); \
+ } \
+};
+
+MAKE_PIN(P0, CORE_PIN0_PORTREG, CORE_PIN0_BIT, CORE_PIN0_CONFIG);
+MAKE_PIN(P1, CORE_PIN1_PORTREG, CORE_PIN1_BIT, CORE_PIN1_CONFIG);
+MAKE_PIN(P2, CORE_PIN2_PORTREG, CORE_PIN2_BIT, CORE_PIN2_CONFIG);
+MAKE_PIN(P3, CORE_PIN3_PORTREG, CORE_PIN3_BIT, CORE_PIN3_CONFIG);
+MAKE_PIN(P4, CORE_PIN4_PORTREG, CORE_PIN4_BIT, CORE_PIN4_CONFIG);
+MAKE_PIN(P5, CORE_PIN5_PORTREG, CORE_PIN5_BIT, CORE_PIN5_CONFIG);
+MAKE_PIN(P6, CORE_PIN6_PORTREG, CORE_PIN6_BIT, CORE_PIN6_CONFIG);
+MAKE_PIN(P7, CORE_PIN7_PORTREG, CORE_PIN7_BIT, CORE_PIN7_CONFIG);
+MAKE_PIN(P8, CORE_PIN8_PORTREG, CORE_PIN8_BIT, CORE_PIN8_CONFIG);
+MAKE_PIN(P9, CORE_PIN9_PORTREG, CORE_PIN9_BIT, CORE_PIN9_CONFIG);
+MAKE_PIN(P10, CORE_PIN10_PORTREG, CORE_PIN10_BIT, CORE_PIN10_CONFIG);
+MAKE_PIN(P11, CORE_PIN11_PORTREG, CORE_PIN11_BIT, CORE_PIN11_CONFIG);
+MAKE_PIN(P12, CORE_PIN12_PORTREG, CORE_PIN12_BIT, CORE_PIN12_CONFIG);
+MAKE_PIN(P13, CORE_PIN13_PORTREG, CORE_PIN13_BIT, CORE_PIN13_CONFIG);
+MAKE_PIN(P14, CORE_PIN14_PORTREG, CORE_PIN14_BIT, CORE_PIN14_CONFIG);
+MAKE_PIN(P15, CORE_PIN15_PORTREG, CORE_PIN15_BIT, CORE_PIN15_CONFIG);
+MAKE_PIN(P16, CORE_PIN16_PORTREG, CORE_PIN16_BIT, CORE_PIN16_CONFIG);
+MAKE_PIN(P17, CORE_PIN17_PORTREG, CORE_PIN17_BIT, CORE_PIN17_CONFIG);
+MAKE_PIN(P18, CORE_PIN18_PORTREG, CORE_PIN18_BIT, CORE_PIN18_CONFIG);
+MAKE_PIN(P19, CORE_PIN19_PORTREG, CORE_PIN19_BIT, CORE_PIN19_CONFIG);
+MAKE_PIN(P20, CORE_PIN20_PORTREG, CORE_PIN20_BIT, CORE_PIN20_CONFIG);
+MAKE_PIN(P21, CORE_PIN21_PORTREG, CORE_PIN21_BIT, CORE_PIN21_CONFIG);
+MAKE_PIN(P22, CORE_PIN22_PORTREG, CORE_PIN22_BIT, CORE_PIN22_CONFIG);
+MAKE_PIN(P23, CORE_PIN23_PORTREG, CORE_PIN23_BIT, CORE_PIN23_CONFIG);
+MAKE_PIN(P24, CORE_PIN24_PORTREG, CORE_PIN24_BIT, CORE_PIN24_CONFIG);
+MAKE_PIN(P25, CORE_PIN25_PORTREG, CORE_PIN25_BIT, CORE_PIN25_CONFIG);
+MAKE_PIN(P26, CORE_PIN26_PORTREG, CORE_PIN26_BIT, CORE_PIN26_CONFIG);
+MAKE_PIN(P27, CORE_PIN27_PORTREG, CORE_PIN27_BIT, CORE_PIN27_CONFIG);
+MAKE_PIN(P28, CORE_PIN28_PORTREG, CORE_PIN28_BIT, CORE_PIN28_CONFIG);
+MAKE_PIN(P29, CORE_PIN29_PORTREG, CORE_PIN29_BIT, CORE_PIN29_CONFIG);
+MAKE_PIN(P30, CORE_PIN30_PORTREG, CORE_PIN30_BIT, CORE_PIN30_CONFIG);
+MAKE_PIN(P31, CORE_PIN31_PORTREG, CORE_PIN31_BIT, CORE_PIN31_CONFIG);
+MAKE_PIN(P32, CORE_PIN32_PORTREG, CORE_PIN32_BIT, CORE_PIN32_CONFIG);
+MAKE_PIN(P33, CORE_PIN33_PORTREG, CORE_PIN33_BIT, CORE_PIN33_CONFIG);
+
+#undef MAKE_PIN
+
+#elif defined(ARDUINO_SAM_DUE) && defined(__SAM3X8E__)
+
+// SetDirRead:
+// Disable interrupts
+// Disable the pull up resistor
+// Set to INPUT
+// Enable PIO
+
+// SetDirWrite:
+// Disable interrupts
+// Disable the pull up resistor
+// Set to OUTPUT
+// Enable PIO
+
+#define MAKE_PIN(className, pio, pinMask) \
+class className { \
+public: \
+ static void Set() { \
+ pio->PIO_SODR = pinMask; \
+ } \
+ static void Clear() { \
+ pio->PIO_CODR = pinMask; \
+ } \
+ static void SetDirRead() { \
+ pio->PIO_IDR = pinMask ; \
+ pio->PIO_PUDR = pinMask; \
+ pio->PIO_ODR = pinMask; \
+ pio->PIO_PER = pinMask; \
+ } \
+ static void SetDirWrite() { \
+ pio->PIO_IDR = pinMask ; \
+ pio->PIO_PUDR = pinMask; \
+ pio->PIO_OER = pinMask; \
+ pio->PIO_PER = pinMask; \
+ } \
+ static uint8_t IsSet() { \
+ return pio->PIO_PDSR & pinMask; \
+ } \
+};
+
+// See: http://arduino.cc/en/Hacking/PinMappingSAM3X and variant.cpp
+
+MAKE_PIN(P0, PIOA, PIO_PA8);
+MAKE_PIN(P1, PIOA, PIO_PA9);
+MAKE_PIN(P2, PIOB, PIO_PB25);
+MAKE_PIN(P3, PIOC, PIO_PC28);
+MAKE_PIN(P4, PIOC, PIO_PC26);
+MAKE_PIN(P5, PIOC, PIO_PC25);
+MAKE_PIN(P6, PIOC, PIO_PC24);
+MAKE_PIN(P7, PIOC, PIO_PC23);
+MAKE_PIN(P8, PIOC, PIO_PC22);
+MAKE_PIN(P9, PIOC, PIO_PC21);
+MAKE_PIN(P10, PIOC, PIO_PC29);
+MAKE_PIN(P11, PIOD, PIO_PD7);
+MAKE_PIN(P12, PIOD, PIO_PD8);
+MAKE_PIN(P13, PIOB, PIO_PB27);
+MAKE_PIN(P14, PIOD, PIO_PD4);
+MAKE_PIN(P15, PIOD, PIO_PD5);
+MAKE_PIN(P16, PIOA, PIO_PA13);
+MAKE_PIN(P17, PIOA, PIO_PA12);
+MAKE_PIN(P18, PIOA, PIO_PA11);
+MAKE_PIN(P19, PIOA, PIO_PA10);
+MAKE_PIN(P20, PIOB, PIO_PB12);
+MAKE_PIN(P21, PIOB, PIO_PB13);
+MAKE_PIN(P22, PIOB, PIO_PB26);
+MAKE_PIN(P23, PIOA, PIO_PA14);
+MAKE_PIN(P24, PIOA, PIO_PA15);
+MAKE_PIN(P25, PIOD, PIO_PD0);
+MAKE_PIN(P26, PIOD, PIO_PD1);
+MAKE_PIN(P27, PIOD, PIO_PD2);
+MAKE_PIN(P28, PIOD, PIO_PD3);
+MAKE_PIN(P29, PIOD, PIO_PD6);
+MAKE_PIN(P30, PIOD, PIO_PD9);
+MAKE_PIN(P31, PIOA, PIO_PA7);
+MAKE_PIN(P32, PIOD, PIO_PD10);
+MAKE_PIN(P33, PIOC, PIO_PC1);
+MAKE_PIN(P34, PIOC, PIO_PC2);
+MAKE_PIN(P35, PIOC, PIO_PC3);
+MAKE_PIN(P36, PIOC, PIO_PC4);
+MAKE_PIN(P37, PIOC, PIO_PC5);
+MAKE_PIN(P38, PIOC, PIO_PC6);
+MAKE_PIN(P39, PIOC, PIO_PC7);
+MAKE_PIN(P40, PIOC, PIO_PC8);
+MAKE_PIN(P41, PIOC, PIO_PC9);
+MAKE_PIN(P42, PIOA, PIO_PA19);
+MAKE_PIN(P43, PIOA, PIO_PA20);
+MAKE_PIN(P44, PIOC, PIO_PC19);
+MAKE_PIN(P45, PIOC, PIO_PC18);
+MAKE_PIN(P46, PIOC, PIO_PC17);
+MAKE_PIN(P47, PIOC, PIO_PC16);
+MAKE_PIN(P48, PIOC, PIO_PC15);
+MAKE_PIN(P49, PIOC, PIO_PC14);
+MAKE_PIN(P50, PIOC, PIO_PC13);
+MAKE_PIN(P51, PIOC, PIO_PC12);
+MAKE_PIN(P52, PIOB, PIO_PB21);
+MAKE_PIN(P53, PIOB, PIO_PB14);
+MAKE_PIN(P54, PIOA, PIO_PA16);
+MAKE_PIN(P55, PIOA, PIO_PA24);
+MAKE_PIN(P56, PIOA, PIO_PA23);
+MAKE_PIN(P57, PIOA, PIO_PA22);
+MAKE_PIN(P58, PIOA, PIO_PA6);
+MAKE_PIN(P59, PIOA, PIO_PA4);
+MAKE_PIN(P60, PIOA, PIO_PA3);
+MAKE_PIN(P61, PIOA, PIO_PA2);
+MAKE_PIN(P62, PIOB, PIO_PB17);
+MAKE_PIN(P63, PIOB, PIO_PB18);
+MAKE_PIN(P64, PIOB, PIO_PB19);
+MAKE_PIN(P65, PIOB, PIO_PB20);
+MAKE_PIN(P66, PIOB, PIO_PB15);
+MAKE_PIN(P67, PIOB, PIO_PB16);
+MAKE_PIN(P68, PIOA, PIO_PA1);
+MAKE_PIN(P69, PIOA, PIO_PA0);
+MAKE_PIN(P70, PIOA, PIO_PA17);
+MAKE_PIN(P71, PIOA, PIO_PA18);
+MAKE_PIN(P72, PIOC, PIO_PC30);
+MAKE_PIN(P73, PIOA, PIO_PA21);
+MAKE_PIN(P74, PIOA, PIO_PA25); // MISO
+MAKE_PIN(P75, PIOA, PIO_PA26); // MOSI
+MAKE_PIN(P76, PIOA, PIO_PA27); // CLK
+MAKE_PIN(P77, PIOA, PIO_PA28);
+MAKE_PIN(P78, PIOB, PIO_PB23); // Unconnected
+
+#undef MAKE_PIN
+
+#elif defined(RBL_NRF51822)
+
+#define MAKE_PIN(className, pin) \
+class className { \
+public: \
+ static void Set() { \
+ nrf_gpio_pin_set(pin); \
+ } \
+ static void Clear() { \
+ nrf_gpio_pin_clear(pin); \
+ } \
+ static void SetDirRead() { \
+ nrf_gpio_cfg_input(pin, NRF_GPIO_PIN_NOPULL); \
+ } \
+ static void SetDirWrite() { \
+ nrf_gpio_cfg_output(pin); \
+ } \
+ static uint8_t IsSet() { \
+ return (uint8_t)nrf_gpio_pin_read(pin); \
+ } \
+};
+
+// See: pin_transform.c in RBL nRF51822 SDK
+MAKE_PIN(P0, Pin_nRF51822_to_Arduino(D0));
+MAKE_PIN(P1, Pin_nRF51822_to_Arduino(D1));
+MAKE_PIN(P2, Pin_nRF51822_to_Arduino(D2));
+MAKE_PIN(P3, Pin_nRF51822_to_Arduino(D3));
+MAKE_PIN(P4, Pin_nRF51822_to_Arduino(D4));
+MAKE_PIN(P5, Pin_nRF51822_to_Arduino(D5));
+MAKE_PIN(P6, Pin_nRF51822_to_Arduino(D6));
+MAKE_PIN(P7, Pin_nRF51822_to_Arduino(D7));
+MAKE_PIN(P8, Pin_nRF51822_to_Arduino(D8));
+MAKE_PIN(P9, Pin_nRF51822_to_Arduino(D9)); // INT
+MAKE_PIN(P10, Pin_nRF51822_to_Arduino(D10)); // SS
+MAKE_PIN(P11, Pin_nRF51822_to_Arduino(D11));
+MAKE_PIN(P12, Pin_nRF51822_to_Arduino(D12));
+MAKE_PIN(P13, Pin_nRF51822_to_Arduino(D13));
+MAKE_PIN(P14, Pin_nRF51822_to_Arduino(D14));
+MAKE_PIN(P15, Pin_nRF51822_to_Arduino(D15));
+MAKE_PIN(P17, Pin_nRF51822_to_Arduino(D17)); // MISO
+MAKE_PIN(P18, Pin_nRF51822_to_Arduino(D18)); // MOSI
+MAKE_PIN(P16, Pin_nRF51822_to_Arduino(D16)); // CLK
+MAKE_PIN(P19, Pin_nRF51822_to_Arduino(D19));
+MAKE_PIN(P20, Pin_nRF51822_to_Arduino(D20));
+MAKE_PIN(P21, Pin_nRF51822_to_Arduino(D21));
+MAKE_PIN(P22, Pin_nRF51822_to_Arduino(D22));
+MAKE_PIN(P23, Pin_nRF51822_to_Arduino(D23));
+MAKE_PIN(P24, Pin_nRF51822_to_Arduino(D24));
+
+#undef MAKE_PIN
+
+#else
+#error "Please define board in avrpins.h"
+
+#endif
+
+#elif defined(__ARDUINO_X86__) // Intel Galileo, Intel Galileo 2 and Intel Edison
+
+#include <avr/pgmspace.h>
+
+// Pointers are 32 bits on x86
+#define pgm_read_pointer(p) pgm_read_dword(p)
+
+#if PLATFORM_ID == 0xE1 // Edison platform id
+#define pinToFastPin(pin) 1 // As far as I can tell all pins can be used as fast pins
+#endif
+
+// Pin 2 and 3 on the Intel Galileo supports a higher rate,
+// so it is recommended to use one of these as the SS pin.
+
+#define MAKE_PIN(className, pin) \
+class className { \
+public: \
+ static void Set() { \
+ fastDigitalWrite(pin, HIGH); \
+ } \
+ static void Clear() { \
+ fastDigitalWrite(pin, LOW); \
+ } \
+ static void SetDirRead() { \
+ if (pinToFastPin(pin)) \
+ pinMode(pin, INPUT_FAST); \
+ else \
+ pinMode(pin, INPUT); \
+ } \
+ static void SetDirWrite() { \
+ if (pinToFastPin(pin)) \
+ pinMode(pin, OUTPUT_FAST); \
+ else \
+ pinMode(pin, OUTPUT); \
+ } \
+ static uint8_t IsSet() { \
+ return fastDigitalRead(pin); \
+ } \
+};
+
+MAKE_PIN(P0, 0);
+MAKE_PIN(P1, 1);
+MAKE_PIN(P2, 2);
+MAKE_PIN(P3, 3);
+MAKE_PIN(P4, 4);
+MAKE_PIN(P5, 5);
+MAKE_PIN(P6, 6);
+MAKE_PIN(P7, 7);
+MAKE_PIN(P8, 8);
+MAKE_PIN(P9, 9);
+MAKE_PIN(P10, 10);
+MAKE_PIN(P11, 11);
+MAKE_PIN(P12, 12);
+MAKE_PIN(P13, 13);
+MAKE_PIN(P14, 14); // A0
+MAKE_PIN(P15, 15); // A1
+MAKE_PIN(P16, 16); // A2
+MAKE_PIN(P17, 17); // A3
+MAKE_PIN(P18, 18); // A4
+MAKE_PIN(P19, 19); // A5
+
+#undef MAKE_PIN
+
+#elif defined(__MIPSEL__)
+// MIPSEL (MIPS architecture using a little endian byte order)
+
+// MIPS size_t = 4
+#define pgm_read_pointer(p) pgm_read_dword(p)
+
+#define MAKE_PIN(className, pin) \
+class className { \
+public: \
+ static void Set() { \
+ digitalWrite(pin, HIGH);\
+ } \
+ static void Clear() { \
+ digitalWrite(pin, LOW); \
+ } \
+ static void SetDirRead() { \
+ pinMode(pin, INPUT); \
+ } \
+ static void SetDirWrite() { \
+ pinMode(pin, OUTPUT); \
+ } \
+ static uint8_t IsSet() { \
+ return digitalRead(pin); \
+ } \
+};
+
+// 0 .. 13 - Digital pins
+MAKE_PIN(P0, 0); // RX
+MAKE_PIN(P1, 1); // TX
+MAKE_PIN(P2, 2); //
+MAKE_PIN(P3, 3); //
+MAKE_PIN(P4, 4); //
+MAKE_PIN(P5, 5); //
+MAKE_PIN(P6, 6); //
+MAKE_PIN(P7, 7); //
+MAKE_PIN(P8, 8); //
+MAKE_PIN(P9, 9); //
+MAKE_PIN(P10, 10); //
+MAKE_PIN(P11, 11); //
+MAKE_PIN(P12, 12); //
+MAKE_PIN(P13, 13); //
+
+#undef MAKE_PIN
+
+#else
+#error "Please define board in avrpins.h"
+
+#endif
+
+#endif //_avrpins_h_
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdc_XR21B1411.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdc_XR21B1411.cpp
new file mode 100644
index 000000000..74df8c3bd
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdc_XR21B1411.cpp
@@ -0,0 +1,211 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+#include "cdc_XR21B1411.h"
+
+XR21B1411::XR21B1411(USB *p, CDCAsyncOper *pasync) :
+ACM(p, pasync) {
+ // Is this needed??
+ _enhanced_status = enhanced_features(); // Set up features
+}
+
+uint8_t XR21B1411::Init(uint8_t parent, uint8_t port, bool lowspeed) {
+ const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
+
+ uint8_t buf[constBufSize];
+ USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
+
+ uint8_t rcode;
+ UsbDevice *p = NULL;
+ EpInfo *oldep_ptr = NULL;
+ uint8_t num_of_conf; // number of configurations
+
+ AddressPool &addrPool = pUsb->GetAddressPool();
+
+ USBTRACE("XR Init\r\n");
+
+ if(bAddress)
+ return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
+
+ // Get pointer to pseudo device with address 0 assigned
+ p = addrPool.GetUsbDevicePtr(0);
+
+ if(!p)
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+ if(!p->epinfo) {
+ USBTRACE("epinfo\r\n");
+ return USB_ERROR_EPINFO_IS_NULL;
+ }
+
+ // Save old pointer to EP_RECORD of address 0
+ oldep_ptr = p->epinfo;
+
+ // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
+ p->epinfo = epInfo;
+
+ p->lowspeed = lowspeed;
+
+ // Get device descriptor
+ rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf);
+
+ // Restore p->epinfo
+ p->epinfo = oldep_ptr;
+
+ if(rcode)
+ goto FailGetDevDescr;
+
+ // Allocate new address according to device class
+ bAddress = addrPool.AllocAddress(parent, false, port);
+
+ if(!bAddress)
+ return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
+
+ // Extract Max Packet Size from the device descriptor
+ epInfo[0].maxPktSize = udd->bMaxPacketSize0;
+
+ // Assign new address to the device
+ rcode = pUsb->setAddr(0, 0, bAddress);
+
+ if(rcode) {
+ p->lowspeed = false;
+ addrPool.FreeAddress(bAddress);
+ bAddress = 0;
+ USBTRACE2("setAddr:", rcode);
+ return rcode;
+ }
+
+ USBTRACE2("Addr:", bAddress);
+
+ p->lowspeed = false;
+
+ p = addrPool.GetUsbDevicePtr(bAddress);
+
+ if(!p)
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+ p->lowspeed = lowspeed;
+
+ num_of_conf = udd->bNumConfigurations;
+
+ if((((udd->idVendor != 0x2890U) || (udd->idProduct != 0x0201U)) && ((udd->idVendor != 0x04e2U) || (udd->idProduct != 0x1411U))))
+ return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
+
+ // Assign epInfo to epinfo pointer
+ rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
+
+ if(rcode)
+ goto FailSetDevTblEntry;
+
+ USBTRACE2("NC:", num_of_conf);
+
+ for(uint8_t i = 0; i < num_of_conf; i++) {
+ ConfigDescParser< USB_CLASS_COM_AND_CDC_CTRL,
+ CDC_SUBCLASS_ACM,
+ CDC_PROTOCOL_ITU_T_V_250,
+ CP_MASK_COMPARE_CLASS |
+ CP_MASK_COMPARE_SUBCLASS |
+ CP_MASK_COMPARE_PROTOCOL > CdcControlParser(this);
+
+ ConfigDescParser<USB_CLASS_CDC_DATA, 0, 0,
+ CP_MASK_COMPARE_CLASS> CdcDataParser(this);
+
+ rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcControlParser);
+
+ if(rcode)
+ goto FailGetConfDescr;
+
+ rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcDataParser);
+
+ if(rcode)
+ goto FailGetConfDescr;
+
+ if(bNumEP > 1)
+ break;
+ } // for
+
+ if(bNumEP < 4)
+ return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
+
+ // Assign epInfo to epinfo pointer
+ rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
+
+ USBTRACE2("Conf:", bConfNum);
+
+ // Set Configuration Value
+ rcode = pUsb->setConf(bAddress, 0, bConfNum);
+
+ if(rcode)
+ goto FailSetConfDescr;
+
+ // Set up features status
+ _enhanced_status = enhanced_features();
+ half_duplex(false);
+ autoflowRTS(false);
+ autoflowDSR(false);
+ autoflowXON(false);
+ wide(false); // Always false, because this is only available in custom mode.
+
+ rcode = pAsync->OnInit(this);
+
+ if(rcode)
+ goto FailOnInit;
+
+ USBTRACE("XR configured\r\n");
+
+ ready = true;
+
+ //bPollEnable = true;
+
+ //USBTRACE("Poll enabled\r\n");
+ return 0;
+
+FailGetDevDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailGetDevDescr();
+ goto Fail;
+#endif
+
+FailSetDevTblEntry:
+#ifdef DEBUG_USB_HOST
+ NotifyFailSetDevTblEntry();
+ goto Fail;
+#endif
+
+FailGetConfDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailGetConfDescr();
+ goto Fail;
+#endif
+
+FailSetConfDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailSetConfDescr();
+ goto Fail;
+#endif
+
+FailOnInit:
+#ifdef DEBUG_USB_HOST
+ USBTRACE("OnInit:");
+#endif
+
+#ifdef DEBUG_USB_HOST
+Fail:
+ NotifyFail(rcode);
+#endif
+ Release();
+ return rcode;
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdc_XR21B1411.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdc_XR21B1411.h
new file mode 100644
index 000000000..c32627544
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdc_XR21B1411.h
@@ -0,0 +1,272 @@
+/* Copyright (C) 2015 Andrew J. Kroll
+ and
+ Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+#if !defined(__CDC_XR21B1411_H__)
+#define __CDC_XR21B1411_H__
+
+#include "cdcacm.h"
+
+#define XR_REG_CUSTOM_DRIVER (0x020DU) // DRIVER SELECT
+#define XR_REG_CUSTOM_DRIVER_ACTIVE (0x0001U) // 0: CDC 1: CUSTOM
+
+#define XR_REG_ACM_FLOW_CTL (0x0216U) // FLOW CONTROL REGISTER CDCACM MODE
+#define XR_REG_FLOW_CTL (0x0C06U) // FLOW CONTROL REGISTER CUSTOM MODE
+#define XR_REG_FLOW_CTL_HALF_DPLX (0x0008U) // 0:FULL DUPLEX 1:HALF DUPLEX
+#define XR_REG_FLOW_CTL_MODE_MASK (0x0007U) // MODE BITMASK
+#define XR_REG_FLOW_CTL_NONE (0x0000U) // NO FLOW CONTROL
+#define XR_REG_FLOW_CTL_HW (0x0001U) // HARDWARE FLOW CONTROL
+#define XR_REG_FLOW_CTL_SW (0x0002U) // SOFTWARE FLOW CONTROL
+#define XR_REG_FLOW_CTL_MMMRX (0x0003U) // MULTIDROP RX UPON ADDRESS MATCH
+#define XR_REG_FLOW_CTL_MMMRXTX (0x0004U) // MULTIDROP RX/TX UPON ADDRESS MATCH
+
+#define XR_REG_ACM_GPIO_MODE (0x0217U) // GPIO MODE REGISTER IN CDCACM MODE
+#define XR_REG_GPIO_MODE (0x0C0CU) // GPIO MODE REGISTER IN CUSTOM MODE
+#define XR_REG_GPIO_MODE_GPIO (0x0000U) // ALL GPIO PINS ACM PROGRAMMABLE
+#define XR_REG_GPIO_MODE_FC_RTSCTS (0x0001U) // AUTO RTSCTS HW FC (GPIO 4/5)
+#define XR_REG_GPIO_MODE_FC_DTRDSR (0x0002U) // AUTO DTRDSR HW FC (GPIO 2/3)
+#define XR_REG_GPIO_MODE_ATE (0x0003U) // AUTO TRANSCEIVER ENABLE DURING TX (GPIO 5)
+#define XR_REG_GPIO_MODE_ATE_ADDRESS (0x0004U) // AUTO TRANSCEIVER ENABLE ON ADDRESS MATCH (GPIO 5)
+
+#define XR_REG_ACM_GPIO_DIR (0x0218U) // GPIO DIRECTION REGISTER CDCACM MODE, 0:IN 1:OUT
+#define XR_REG_GPIO_DIR (0x0C0DU) // GPIO DIRECTION REGISTER CUSTOM MODE, 0:IN 1:OUT
+
+#define XR_REG_ACM_GPIO_INT (0x0219U) // GPIO PIN CHANGE INTERRUPT ENABLE CDCACM MODE, 0: ENABLED 1: DISABLED
+#define XR_REG_GPIO_INT (0x0C11U) // GPIO PIN CHANGE INTERRUPT ENABLE CUSTOM MODE, 0: ENABLED 1: DISABLED
+#define XR_REG_GPIO_MASK (0x001FU) // GPIO REGISTERS BITMASK
+
+#define XR_REG_UART_ENABLE (0x0C00U) // UART I/O ENABLE REGISTER
+#define XR_REG_UART_ENABLE_RX (0x0002U) // 0:DISABLED 1:ENABLED
+#define XR_REG_UART_ENABLE_TX (0x0001U) // 0:DISABLED 1:ENABLED
+
+#define XR_REG_ERROR_STATUS (0x0C09U) // ERROR STATUS REGISTER
+#define XR_REG_ERROR_STATUS_MASK (0x00F8U) // ERROR STATUS BITMASK
+#define XR_REG_ERROR_STATUS_ERROR (0x0078U) // ERROR STATUS ERROR BITMASK
+#define XR_REG_ERROR_STATUS_BREAK (0x0008U) // BREAK ERROR HAS BEEN DETECTED
+#define XR_REG_ERROR_STATUS_FRAME (0x0010U) // FRAMING ERROR HAS BEEN DETECTED
+#define XR_REG_ERROR_STATUS_PARITY (0x0020U) // PARITY ERROR HAS BEEN DETECTED
+#define XR_REG_ERROR_STATUS_OVERRUN (0x0040U) // RX OVERRUN ERROR HAS BEEN DETECTED
+#define XR_REG_ERROR_STATUS_BREAK_STATUS (0x0080U) // BREAK CONDITION IS CURRENTLY BEING DETECTED
+
+#define XR_REG_TX_BREAK (0x0C0AU) // TRANSMIT BREAK. 0X0001-0XFFE TIME IN MS, 0X0000 STOP, 0X0FFF BREAK ON
+
+#define XR_REG_XCVR_EN_DELAY (0x0C0BU) // TURN-ARROUND DELAY IN BIT-TIMES 0X0000-0X000F
+
+#define XR_REG_GPIO_SET (0x0C0EU) // 1:SET GPIO PIN
+
+#define XR_REG_GPIO_CLR (0x0C0FU) // 1:CLEAR GPIO PIN
+
+#define XR_REG_GPIO_STATUS (0x0C10U) // READ GPIO PINS
+
+#define XR_REG_CUSTOMISED_INT (0x0C12U) // 0:STANDARD 1:CUSTOM SEE DATA SHEET
+
+#define XR_REG_PIN_PULLUP_ENABLE (0x0C14U) // 0:DISABLE 1:ENABLE, BITS 0-5:GPIO, 6:RX 7:TX
+
+#define XR_REG_PIN_PULLDOWN_ENABLE (0x0C15U) // 0:DISABLE 1:ENABLE, BITS 0-5:GPIO, 6:RX 7:TX
+
+#define XR_REG_LOOPBACK (0x0C16U) // 0:DISABLE 1:ENABLE, SEE DATA SHEET
+
+#define XR_REG_RX_FIFO_LATENCY (0x0CC2U) // FIFO LATENCY REGISTER
+#define XR_REG_RX_FIFO_LATENCY_ENABLE (0x0001U) //
+
+#define XR_REG_WIDE_MODE (0x0D02U)
+#define XR_REG_WIDE_MODE_ENABLE (0x0001U)
+
+#define XR_REG_XON_CHAR (0x0C07U)
+#define XR_REG_XOFF_CHAR (0x0C08U)
+
+#define XR_REG_TX_FIFO_RESET (0x0C80U) // 1: RESET, SELF-CLEARING
+#define XR_REG_TX_FIFO_COUNT (0x0C81U) // READ-ONLY
+#define XR_REG_RX_FIFO_RESET (0x0CC0U) // 1: RESET, SELF-CLEARING
+#define XR_REG_RX_FIFO_COUNT (0x0CC1U) // READ-ONLY
+
+#define XR_WRITE_REQUEST_TYPE (0x40U)
+
+#define XR_READ_REQUEST_TYPE (0xC0U)
+
+#define XR_MAX_ENDPOINTS 4
+
+class XR21B1411 : public ACM {
+protected:
+
+public:
+ XR21B1411(USB *pusb, CDCAsyncOper *pasync);
+
+ /**
+ * Used by the USB core to check what this driver support.
+ * @param vid The device's VID.
+ * @param pid The device's PID.
+ * @return Returns true if the device's VID and PID matches this driver.
+ */
+ virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {
+ return (((vid == 0x2890U) && (pid == 0x0201U)) || ((vid == 0x04e2U) && (pid == 0x1411U)));
+ };
+
+ uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
+
+ virtual tty_features enhanced_features(void) {
+ tty_features rv;
+ rv.enhanced = true;
+ rv.autoflow_RTS = true;
+ rv.autoflow_DSR = true;
+ rv.autoflow_XON = true;
+ rv.half_duplex = true;
+ rv.wide = true;
+ return rv;
+ };
+
+ uint8_t read_register(uint16_t reg, uint16_t *val) {
+ return (pUsb->ctrlReq(bAddress, 0, XR_READ_REQUEST_TYPE, 1, 0, 0, reg, 2, 2, (uint8_t *)val, NULL));
+ }
+
+ uint8_t write_register(uint16_t reg, uint16_t val) {
+ return (pUsb->ctrlReq(bAddress, 0, XR_WRITE_REQUEST_TYPE, 0, BGRAB0(val), BGRAB1(val), reg, 0, 0, NULL, NULL));
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ // The following methods set the CDC-ACM defaults.
+ ////////////////////////////////////////////////////////////////////////
+
+ virtual void autoflowRTS(bool s) {
+ uint16_t val;
+ uint8_t rval;
+ rval = read_register(XR_REG_ACM_FLOW_CTL, &val);
+ if(!rval) {
+ if(s) {
+ val &= XR_REG_FLOW_CTL_HALF_DPLX;
+ val |= XR_REG_FLOW_CTL_HW;
+ } else {
+ val &= XR_REG_FLOW_CTL_HALF_DPLX;
+ }
+ rval = write_register(XR_REG_ACM_FLOW_CTL, val);
+ if(!rval) {
+ rval = write_register(XR_REG_ACM_GPIO_MODE, XR_REG_GPIO_MODE_GPIO);
+ if(!rval) {
+ // ACM commands apply the new settings.
+ LINE_CODING LCT;
+ rval = GetLineCoding(&LCT);
+ if(!rval) {
+ rval = SetLineCoding(&LCT);
+ if(!rval) {
+ _enhanced_status.autoflow_XON = false;
+ _enhanced_status.autoflow_DSR = false;
+ _enhanced_status.autoflow_RTS = s;
+ }
+ }
+ }
+ }
+ }
+ };
+
+ virtual void autoflowDSR(bool s) {
+ uint16_t val;
+ uint8_t rval;
+ rval = read_register(XR_REG_ACM_FLOW_CTL, &val);
+ if(!rval) {
+ if(s) {
+ val &= XR_REG_FLOW_CTL_HALF_DPLX;
+ val |= XR_REG_FLOW_CTL_HW;
+ } else {
+ val &= XR_REG_FLOW_CTL_HALF_DPLX;
+ }
+ rval = write_register(XR_REG_ACM_FLOW_CTL, val);
+ if(!rval) {
+ if(s) {
+ rval = write_register(XR_REG_ACM_GPIO_MODE, XR_REG_GPIO_MODE_FC_DTRDSR);
+ } else {
+ rval = write_register(XR_REG_ACM_GPIO_MODE, XR_REG_GPIO_MODE_GPIO);
+ }
+ if(!rval) {
+ // ACM commands apply the new settings.
+ LINE_CODING LCT;
+ rval = GetLineCoding(&LCT);
+ if(!rval) {
+ rval = SetLineCoding(&LCT);
+ if(!rval) {
+ _enhanced_status.autoflow_XON = false;
+ _enhanced_status.autoflow_RTS = false;
+ _enhanced_status.autoflow_DSR = s;
+ }
+ }
+ }
+ }
+ }
+ };
+
+ virtual void autoflowXON(bool s) {
+ // NOTE: hardware defaults to the normal XON/XOFF
+ uint16_t val;
+ uint8_t rval;
+ rval = read_register(XR_REG_ACM_FLOW_CTL, &val);
+ if(!rval) {
+ if(s) {
+ val &= XR_REG_FLOW_CTL_HALF_DPLX;
+ val |= XR_REG_FLOW_CTL_SW;
+ } else {
+ val &= XR_REG_FLOW_CTL_HALF_DPLX;
+ }
+ rval = write_register(XR_REG_ACM_FLOW_CTL, val);
+ if(!rval) {
+ rval = write_register(XR_REG_ACM_GPIO_MODE, XR_REG_GPIO_MODE_GPIO);
+ if(!rval) {
+ // ACM commands apply the new settings.
+ LINE_CODING LCT;
+ rval = GetLineCoding(&LCT);
+ if(!rval) {
+ rval = SetLineCoding(&LCT);
+ if(!rval) {
+ _enhanced_status.autoflow_RTS = false;
+ _enhanced_status.autoflow_DSR = false;
+ _enhanced_status.autoflow_XON = s;
+ }
+ }
+ }
+ }
+ }
+ };
+
+ virtual void half_duplex(bool s) {
+ uint16_t val;
+ uint8_t rval;
+ rval = read_register(XR_REG_ACM_FLOW_CTL, &val);
+ if(!rval) {
+ if(s) {
+ val |= XR_REG_FLOW_CTL_HALF_DPLX;
+ } else {
+ val &= XR_REG_FLOW_CTL_MODE_MASK;
+ }
+ rval = write_register(XR_REG_ACM_FLOW_CTL, val);
+ if(!rval) {
+ // ACM commands apply the new settings.
+ LINE_CODING LCT;
+ rval = GetLineCoding(&LCT);
+ if(!rval) {
+ rval = SetLineCoding(&LCT);
+ if(!rval) {
+ _enhanced_status.half_duplex = s;
+ }
+ }
+ }
+ }
+ };
+
+
+
+};
+
+#endif // __CDCPROLIFIC_H__
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcacm.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcacm.cpp
new file mode 100644
index 000000000..2cd2c9a82
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcacm.cpp
@@ -0,0 +1,331 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+#include "cdcacm.h"
+
+const uint8_t ACM::epDataInIndex = 1;
+const uint8_t ACM::epDataOutIndex = 2;
+const uint8_t ACM::epInterruptInIndex = 3;
+
+ACM::ACM(USB *p, CDCAsyncOper *pasync) :
+pUsb(p),
+pAsync(pasync),
+bAddress(0),
+bControlIface(0),
+bDataIface(0),
+bNumEP(1),
+qNextPollTime(0),
+bPollEnable(false),
+ready(false) {
+ _enhanced_status = enhanced_features(); // Set up features
+ for(uint8_t i = 0; i < ACM_MAX_ENDPOINTS; i++) {
+ epInfo[i].epAddr = 0;
+ epInfo[i].maxPktSize = (i) ? 0 : 8;
+ epInfo[i].epAttribs = 0;
+ epInfo[i].bmNakPower = (i == epDataInIndex) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
+
+ }
+ if(pUsb)
+ pUsb->RegisterDeviceClass(this);
+}
+
+uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed) {
+
+ const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
+
+ uint8_t buf[constBufSize];
+ USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
+
+ uint8_t rcode;
+ UsbDevice *p = NULL;
+ EpInfo *oldep_ptr = NULL;
+ uint8_t num_of_conf; // number of configurations
+
+ AddressPool &addrPool = pUsb->GetAddressPool();
+
+ USBTRACE("ACM Init\r\n");
+
+ if(bAddress)
+ return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
+
+ // Get pointer to pseudo device with address 0 assigned
+ p = addrPool.GetUsbDevicePtr(0);
+
+ if(!p)
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+ if(!p->epinfo) {
+ USBTRACE("epinfo\r\n");
+ return USB_ERROR_EPINFO_IS_NULL;
+ }
+
+ // Save old pointer to EP_RECORD of address 0
+ oldep_ptr = p->epinfo;
+
+ // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
+ p->epinfo = epInfo;
+
+ p->lowspeed = lowspeed;
+
+ // Get device descriptor
+ rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf);
+
+ // Restore p->epinfo
+ p->epinfo = oldep_ptr;
+
+ if(rcode)
+ goto FailGetDevDescr;
+
+ // Allocate new address according to device class
+ bAddress = addrPool.AllocAddress(parent, false, port);
+
+ if(!bAddress)
+ return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
+
+ // Extract Max Packet Size from the device descriptor
+ epInfo[0].maxPktSize = udd->bMaxPacketSize0;
+
+ // Assign new address to the device
+ rcode = pUsb->setAddr(0, 0, bAddress);
+
+ if(rcode) {
+ p->lowspeed = false;
+ addrPool.FreeAddress(bAddress);
+ bAddress = 0;
+ USBTRACE2("setAddr:", rcode);
+ return rcode;
+ }
+
+ USBTRACE2("Addr:", bAddress);
+
+ p->lowspeed = false;
+
+ p = addrPool.GetUsbDevicePtr(bAddress);
+
+ if(!p)
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+ p->lowspeed = lowspeed;
+
+ num_of_conf = udd->bNumConfigurations;
+
+ // Assign epInfo to epinfo pointer
+ rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
+
+ if(rcode)
+ goto FailSetDevTblEntry;
+
+ USBTRACE2("NC:", num_of_conf);
+
+ for(uint8_t i = 0; i < num_of_conf; i++) {
+ ConfigDescParser< USB_CLASS_COM_AND_CDC_CTRL,
+ CDC_SUBCLASS_ACM,
+ CDC_PROTOCOL_ITU_T_V_250,
+ CP_MASK_COMPARE_CLASS |
+ CP_MASK_COMPARE_SUBCLASS |
+ CP_MASK_COMPARE_PROTOCOL > CdcControlParser(this);
+
+ ConfigDescParser<USB_CLASS_CDC_DATA, 0, 0,
+ CP_MASK_COMPARE_CLASS> CdcDataParser(this);
+
+ rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcControlParser);
+
+ if(rcode)
+ goto FailGetConfDescr;
+
+ rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcDataParser);
+
+ if(rcode)
+ goto FailGetConfDescr;
+
+ if(bNumEP > 1)
+ break;
+ } // for
+
+ if(bNumEP < 4)
+ return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
+
+ // Assign epInfo to epinfo pointer
+ rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
+
+ USBTRACE2("Conf:", bConfNum);
+
+ // Set Configuration Value
+ rcode = pUsb->setConf(bAddress, 0, bConfNum);
+
+ if(rcode)
+ goto FailSetConfDescr;
+
+ // Set up features status
+ _enhanced_status = enhanced_features();
+ half_duplex(false);
+ autoflowRTS(false);
+ autoflowDSR(false);
+ autoflowXON(false);
+ wide(false); // Always false, because this is only available in custom mode.
+ rcode = pAsync->OnInit(this);
+
+ if(rcode)
+ goto FailOnInit;
+
+ USBTRACE("ACM configured\r\n");
+
+ ready = true;
+
+ //bPollEnable = true;
+
+ //USBTRACE("Poll enabled\r\n");
+ return 0;
+
+FailGetDevDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailGetDevDescr();
+ goto Fail;
+#endif
+
+FailSetDevTblEntry:
+#ifdef DEBUG_USB_HOST
+ NotifyFailSetDevTblEntry();
+ goto Fail;
+#endif
+
+FailGetConfDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailGetConfDescr();
+ goto Fail;
+#endif
+
+FailSetConfDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailSetConfDescr();
+ goto Fail;
+#endif
+
+FailOnInit:
+#ifdef DEBUG_USB_HOST
+ USBTRACE("OnInit:");
+#endif
+
+#ifdef DEBUG_USB_HOST
+Fail:
+ NotifyFail(rcode);
+#endif
+ Release();
+ return rcode;
+}
+
+void ACM::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {
+ //ErrorMessage<uint8_t > (PSTR("Conf.Val"), conf);
+ //ErrorMessage<uint8_t > (PSTR("Iface Num"), iface);
+ //ErrorMessage<uint8_t > (PSTR("Alt.Set"), alt);
+
+ bConfNum = conf;
+
+ uint8_t index;
+
+ if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80)
+ index = epInterruptInIndex;
+ else
+ if((pep->bmAttributes & 0x02) == 2)
+ index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
+ else
+ return;
+
+ // Fill in the endpoint info structure
+ epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
+ epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
+ epInfo[index].epAttribs = 0;
+
+ bNumEP++;
+
+ PrintEndpointDescriptor(pep);
+}
+
+uint8_t ACM::Release() {
+ ready = false;
+ pUsb->GetAddressPool().FreeAddress(bAddress);
+
+ bControlIface = 0;
+ bDataIface = 0;
+ bNumEP = 1;
+
+ bAddress = 0;
+ qNextPollTime = 0;
+ bPollEnable = false;
+ return 0;
+}
+
+uint8_t ACM::Poll() {
+ uint8_t rcode = 0;
+
+ if(!bPollEnable)
+ return 0;
+
+ return rcode;
+}
+
+uint8_t ACM::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr) {
+ return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr);
+}
+
+uint8_t ACM::SndData(uint16_t nbytes, uint8_t *dataptr) {
+ return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr);
+}
+
+uint8_t ACM::SetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr) {
+ return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, nbytes, nbytes, dataptr, NULL));
+}
+
+uint8_t ACM::GetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr) {
+ return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCIN, CDC_GET_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, nbytes, nbytes, dataptr, NULL));
+}
+
+uint8_t ACM::ClearCommFeature(uint16_t fid) {
+ return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_CLEAR_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, 0, 0, NULL, NULL));
+}
+
+uint8_t ACM::SetLineCoding(const LINE_CODING *dataptr) {
+ return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_LINE_CODING, 0x00, 0x00, bControlIface, sizeof (LINE_CODING), sizeof (LINE_CODING), (uint8_t*)dataptr, NULL));
+}
+
+uint8_t ACM::GetLineCoding(LINE_CODING *dataptr) {
+ return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCIN, CDC_GET_LINE_CODING, 0x00, 0x00, bControlIface, sizeof (LINE_CODING), sizeof (LINE_CODING), (uint8_t*)dataptr, NULL));
+}
+
+uint8_t ACM::SetControlLineState(uint8_t state) {
+ return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_CONTROL_LINE_STATE, state, 0, bControlIface, 0, 0, NULL, NULL));
+}
+
+uint8_t ACM::SendBreak(uint16_t duration) {
+ return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SEND_BREAK, (duration & 0xff), (duration >> 8), bControlIface, 0, 0, NULL, NULL));
+}
+
+void ACM::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) {
+ Notify(PSTR("Endpoint descriptor:"), 0x80);
+ Notify(PSTR("\r\nLength:\t\t"), 0x80);
+ D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
+ Notify(PSTR("\r\nType:\t\t"), 0x80);
+ D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
+ Notify(PSTR("\r\nAddress:\t"), 0x80);
+ D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
+ Notify(PSTR("\r\nAttributes:\t"), 0x80);
+ D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
+ Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
+ D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
+ Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
+ D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
+ Notify(PSTR("\r\n"), 0x80);
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcacm.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcacm.h
new file mode 100644
index 000000000..2a38524d8
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcacm.h
@@ -0,0 +1,252 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+#if !defined(__CDCACM_H__)
+#define __CDCACM_H__
+
+#include "Usb.h"
+
+#define bmREQ_CDCOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
+#define bmREQ_CDCIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
+
+// CDC Subclass Constants
+#define CDC_SUBCLASS_DLCM 0x01 // Direct Line Control Model
+#define CDC_SUBCLASS_ACM 0x02 // Abstract Control Model
+#define CDC_SUBCLASS_TCM 0x03 // Telephone Control Model
+#define CDC_SUBCLASS_MCCM 0x04 // Multi Channel Control Model
+#define CDC_SUBCLASS_CAPI 0x05 // CAPI Control Model
+#define CDC_SUBCLASS_ETHERNET 0x06 // Ethernet Network Control Model
+#define CDC_SUBCLASS_ATM 0x07 // ATM Network Control Model
+#define CDC_SUBCLASS_WIRELESS_HANDSET 0x08 // Wireless Handset Control Model
+#define CDC_SUBCLASS_DEVICE_MANAGEMENT 0x09 // Device Management
+#define CDC_SUBCLASS_MOBILE_DIRECT_LINE 0x0A // Mobile Direct Line Model
+#define CDC_SUBCLASS_OBEX 0x0B // OBEX
+#define CDC_SUBCLASS_ETHERNET_EMU 0x0C // Ethernet Emulation Model
+
+// Communication Interface Class Control Protocol Codes
+#define CDC_PROTOCOL_ITU_T_V_250 0x01 // AT Commands defined by ITU-T V.250
+#define CDC_PROTOCOL_PCCA_101 0x02 // AT Commands defined by PCCA-101
+#define CDC_PROTOCOL_PCCA_101_O 0x03 // AT Commands defined by PCCA-101 & Annex O
+#define CDC_PROTOCOL_GSM_7_07 0x04 // AT Commands defined by GSM 7.07
+#define CDC_PROTOCOL_3GPP_27_07 0x05 // AT Commands defined by 3GPP 27.007
+#define CDC_PROTOCOL_C_S0017_0 0x06 // AT Commands defined by TIA for CDMA
+#define CDC_PROTOCOL_USB_EEM 0x07 // Ethernet Emulation Model
+
+// CDC Commands defined by CDC 1.2
+#define CDC_SEND_ENCAPSULATED_COMMAND 0x00
+#define CDC_GET_ENCAPSULATED_RESPONSE 0x01
+
+// CDC Commands defined by PSTN 1.2
+#define CDC_SET_COMM_FEATURE 0x02
+#define CDC_GET_COMM_FEATURE 0x03
+#define CDC_CLEAR_COMM_FEATURE 0x04
+#define CDC_SET_AUX_LINE_STATE 0x10
+#define CDC_SET_HOOK_STATE 0x11
+#define CDC_PULSE_SETUP 0x12
+#define CDC_SEND_PULSE 0x13
+#define CDC_SET_PULSE_TIME 0x14
+#define CDC_RING_AUX_JACK 0x15
+#define CDC_SET_LINE_CODING 0x20
+#define CDC_GET_LINE_CODING 0x21
+#define CDC_SET_CONTROL_LINE_STATE 0x22
+#define CDC_SEND_BREAK 0x23
+#define CDC_SET_RINGER_PARMS 0x30
+#define CDC_GET_RINGER_PARMS 0x31
+#define CDC_SET_OPERATION_PARMS 0x32
+#define CDC_GET_OPERATION_PARMS 0x33
+#define CDC_SET_LINE_PARMS 0x34
+#define CDC_GET_LINE_PARMS 0x35
+#define CDC_DIAL_DIGITS 0x36
+
+//Class-Specific Notification Codes
+#define NETWORK_CONNECTION 0x00
+#define RESPONSE_AVAILABLE 0x01
+#define AUX_JACK_HOOK_STATE 0x08
+#define RING_DETECT 0x09
+#define SERIAL_STATE 0x20
+#define CALL_STATE_CHANGE 0x28
+#define LINE_STATE_CHANGE 0x29
+#define CONNECTION_SPEED_CHANGE 0x2a
+
+// CDC Functional Descriptor Structures
+
+typedef struct {
+ uint8_t bFunctionLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ uint8_t bmCapabilities;
+ uint8_t bDataInterface;
+} CALL_MGMNT_FUNC_DESCR;
+
+typedef struct {
+ uint8_t bFunctionLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ uint8_t bmCapabilities;
+} ACM_FUNC_DESCR, DLM_FUNC_DESCR, TEL_OPER_MODES_FUNC_DESCR,
+TEL_CALL_STATE_REP_CPBL_FUNC_DESCR;
+
+typedef struct {
+ uint8_t bFunctionLength;
+ uint8_t bDescriptorType;
+ uint8_t bDescriptorSubtype;
+ uint8_t bRingerVolSteps;
+ uint8_t bNumRingerPatterns;
+} TEL_RINGER_FUNC_DESCR;
+
+typedef struct {
+ uint32_t dwDTERate; // Data Terminal Rate in bits per second
+ uint8_t bCharFormat; // 0 - 1 stop bit, 1 - 1.5 stop bits, 2 - 2 stop bits
+ uint8_t bParityType; // 0 - None, 1 - Odd, 2 - Even, 3 - Mark, 4 - Space
+ uint8_t bDataBits; // Data bits (5, 6, 7, 8 or 16)
+} LINE_CODING;
+
+typedef struct {
+ uint8_t bmRequestType; // 0xa1 for class-specific notifications
+ uint8_t bNotification;
+ uint16_t wValue;
+ uint16_t wIndex;
+ uint16_t wLength;
+ uint16_t bmState; //UART state bitmap for SERIAL_STATE, other notifications variable length
+} CLASS_NOTIFICATION;
+
+class ACM;
+
+class CDCAsyncOper {
+public:
+
+ virtual uint8_t OnInit(ACM *pacm) {
+ return 0;
+ };
+ //virtual void OnDataRcvd(ACM *pacm, uint8_t nbytes, uint8_t *dataptr) = 0;
+ //virtual void OnDisconnected(ACM *pacm) = 0;
+};
+
+/**
+ * This structure is used to report the extended capabilities of the connected device.
+ * It is also used to report the current status.
+ * Regular CDC-ACM reports all as false.
+ */
+typedef struct {
+
+ union {
+ uint8_t tty;
+
+ struct {
+ bool enhanced : 1; // Do we have the ability to set/clear any features?
+ // Status and 8th bit in data stream.
+ // Presence only indicates feature is available, but this isn't used for CDC-ACM.
+ bool wide : 1;
+ bool autoflow_RTS : 1; // Has autoflow on RTS/CTS
+ bool autoflow_DSR : 1; // Has autoflow on DTR/DSR
+ bool autoflow_XON : 1; // Has autoflow XON/XOFF
+ bool half_duplex : 1; // Has half-duplex capability.
+ } __attribute__((packed));
+ };
+} tty_features;
+
+#define ACM_MAX_ENDPOINTS 4
+
+class ACM : public USBDeviceConfig, public UsbConfigXtracter {
+protected:
+ static const uint8_t epDataInIndex; // DataIn endpoint index
+ static const uint8_t epDataOutIndex; // DataOUT endpoint index
+ static const uint8_t epInterruptInIndex; // InterruptIN endpoint index
+
+ USB *pUsb;
+ CDCAsyncOper *pAsync;
+ uint8_t bAddress;
+ uint8_t bConfNum; // configuration number
+ uint8_t bControlIface; // Control interface value
+ uint8_t bDataIface; // Data interface value
+ uint8_t bNumEP; // total number of EP in the configuration
+ uint32_t qNextPollTime; // next poll time
+ volatile bool bPollEnable; // poll enable flag
+ volatile bool ready; //device ready indicator
+ tty_features _enhanced_status; // current status
+
+ EpInfo epInfo[ACM_MAX_ENDPOINTS];
+
+ void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr);
+
+public:
+ ACM(USB *pusb, CDCAsyncOper *pasync);
+
+ uint8_t SetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr);
+ uint8_t GetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr);
+ uint8_t ClearCommFeature(uint16_t fid);
+ uint8_t SetLineCoding(const LINE_CODING *dataptr);
+ uint8_t GetLineCoding(LINE_CODING *dataptr);
+ uint8_t SetControlLineState(uint8_t state);
+ uint8_t SendBreak(uint16_t duration);
+ uint8_t GetNotif(uint16_t *bytes_rcvd, uint8_t *dataptr);
+
+ // Methods for receiving and sending data
+ uint8_t RcvData(uint16_t *nbytesptr, uint8_t *dataptr);
+ uint8_t SndData(uint16_t nbytes, uint8_t *dataptr);
+
+ // USBDeviceConfig implementation
+ uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
+ uint8_t Release();
+ uint8_t Poll();
+
+ bool available(void) {
+ return false;
+ };
+
+ virtual uint8_t GetAddress() {
+ return bAddress;
+ };
+
+ virtual bool isReady() {
+ return ready;
+ };
+
+ virtual tty_features enhanced_status(void) {
+ return _enhanced_status;
+ };
+
+ virtual tty_features enhanced_features(void) {
+ tty_features rv;
+ rv.enhanced = false;
+ rv.autoflow_RTS = false;
+ rv.autoflow_DSR = false;
+ rv.autoflow_XON = false;
+ rv.half_duplex = false;
+ rv.wide = false;
+ return rv;
+ };
+
+ virtual void autoflowRTS(bool s) {
+ };
+
+ virtual void autoflowDSR(bool s) {
+ };
+
+ virtual void autoflowXON(bool s) {
+ };
+
+ virtual void half_duplex(bool s) {
+ };
+
+ virtual void wide(bool s) {
+ };
+
+ // UsbConfigXtracter implementation
+ void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
+};
+
+#endif // __CDCACM_H__
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcftdi.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcftdi.cpp
new file mode 100644
index 000000000..80d21d16e
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcftdi.cpp
@@ -0,0 +1,334 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+#include "cdcftdi.h"
+
+const uint8_t FTDI::epDataInIndex = 1;
+const uint8_t FTDI::epDataOutIndex = 2;
+const uint8_t FTDI::epInterruptInIndex = 3;
+
+FTDI::FTDI(USB *p, FTDIAsyncOper *pasync) :
+pAsync(pasync),
+pUsb(p),
+bAddress(0),
+bNumEP(1),
+wFTDIType(0) {
+ for(uint8_t i = 0; i < FTDI_MAX_ENDPOINTS; i++) {
+ epInfo[i].epAddr = 0;
+ epInfo[i].maxPktSize = (i) ? 0 : 8;
+ epInfo[i].epAttribs = 0;
+ epInfo[i].bmNakPower = (i==epDataInIndex) ? USB_NAK_NOWAIT: USB_NAK_MAX_POWER;
+ }
+ if(pUsb)
+ pUsb->RegisterDeviceClass(this);
+}
+
+uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed) {
+ const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
+
+ uint8_t buf[constBufSize];
+ USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
+ uint8_t rcode;
+ UsbDevice *p = NULL;
+ EpInfo *oldep_ptr = NULL;
+
+ uint8_t num_of_conf; // number of configurations
+
+ AddressPool &addrPool = pUsb->GetAddressPool();
+
+ USBTRACE("FTDI Init\r\n");
+
+ if(bAddress)
+ return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
+
+ // Get pointer to pseudo device with address 0 assigned
+ p = addrPool.GetUsbDevicePtr(0);
+
+ if(!p)
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+ if(!p->epinfo) {
+ USBTRACE("epinfo\r\n");
+ return USB_ERROR_EPINFO_IS_NULL;
+ }
+
+ // Save old pointer to EP_RECORD of address 0
+ oldep_ptr = p->epinfo;
+
+ // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
+ p->epinfo = epInfo;
+
+ p->lowspeed = lowspeed;
+
+ // Get device descriptor
+ rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), buf);
+
+ // Restore p->epinfo
+ p->epinfo = oldep_ptr;
+
+ if(rcode)
+ goto FailGetDevDescr;
+ if(udd->idVendor != FTDI_VID || udd->idProduct != FTDI_PID)
+ return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
+
+ // Save type of FTDI chip
+ wFTDIType = udd->bcdDevice;
+
+ // Allocate new address according to device class
+ bAddress = addrPool.AllocAddress(parent, false, port);
+
+ if(!bAddress)
+ return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
+
+ // Extract Max Packet Size from the device descriptor
+ epInfo[0].maxPktSize = udd->bMaxPacketSize0;
+
+ // Assign new address to the device
+ rcode = pUsb->setAddr(0, 0, bAddress);
+
+ if(rcode) {
+ p->lowspeed = false;
+ addrPool.FreeAddress(bAddress);
+ bAddress = 0;
+ USBTRACE2("setAddr:", rcode);
+ return rcode;
+ }
+
+ USBTRACE2("Addr:", bAddress);
+
+ p->lowspeed = false;
+
+ p = addrPool.GetUsbDevicePtr(bAddress);
+
+ if(!p)
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+ p->lowspeed = lowspeed;
+
+ num_of_conf = udd->bNumConfigurations;
+
+ // Assign epInfo to epinfo pointer
+ rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
+
+ if(rcode)
+ goto FailSetDevTblEntry;
+
+ USBTRACE2("NC:", num_of_conf);
+
+ for(uint8_t i = 0; i < num_of_conf; i++) {
+ HexDumper<USBReadParser, uint16_t, uint16_t> HexDump;
+ ConfigDescParser < 0xFF, 0xFF, 0xFF, CP_MASK_COMPARE_ALL> confDescrParser(this);
+
+ rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump);
+
+ if(rcode)
+ goto FailGetConfDescr;
+
+ rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
+
+ if(rcode)
+ goto FailGetConfDescr;
+
+ if(bNumEP > 1)
+ break;
+ } // for
+
+ if(bNumEP < 2)
+ return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
+
+ USBTRACE2("NumEP:", bNumEP);
+
+ // Assign epInfo to epinfo pointer
+ rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
+
+ USBTRACE2("Conf:", bConfNum);
+
+ // Set Configuration Value
+ rcode = pUsb->setConf(bAddress, 0, bConfNum);
+
+ if(rcode)
+ goto FailSetConfDescr;
+
+ rcode = pAsync->OnInit(this);
+
+ if(rcode)
+ goto FailOnInit;
+
+ USBTRACE("FTDI configured\r\n");
+
+ bPollEnable = true;
+ return 0;
+
+FailGetDevDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailGetDevDescr();
+ goto Fail;
+#endif
+
+FailSetDevTblEntry:
+#ifdef DEBUG_USB_HOST
+ NotifyFailSetDevTblEntry();
+ goto Fail;
+#endif
+
+FailGetConfDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailGetConfDescr();
+ goto Fail;
+#endif
+
+FailSetConfDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailSetConfDescr();
+ goto Fail;
+#endif
+
+FailOnInit:
+#ifdef DEBUG_USB_HOST
+ USBTRACE("OnInit:");
+
+Fail:
+ NotifyFail(rcode);
+#endif
+ Release();
+ return rcode;
+}
+
+void FTDI::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {
+ ErrorMessage<uint8_t > (PSTR("Conf.Val"), conf);
+ ErrorMessage<uint8_t > (PSTR("Iface Num"), iface);
+ ErrorMessage<uint8_t > (PSTR("Alt.Set"), alt);
+
+ bConfNum = conf;
+
+ uint8_t index;
+
+ if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80)
+ index = epInterruptInIndex;
+ else
+ if((pep->bmAttributes & 0x02) == 2)
+ index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
+ else
+ return;
+
+ // Fill in the endpoint info structure
+ epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
+ epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
+ epInfo[index].epAttribs = 0;
+
+ bNumEP++;
+
+ PrintEndpointDescriptor(pep);
+}
+
+uint8_t FTDI::Release() {
+ pUsb->GetAddressPool().FreeAddress(bAddress);
+
+ bAddress = 0;
+ bNumEP = 1;
+ qNextPollTime = 0;
+ bPollEnable = false;
+ return pAsync->OnRelease(this);
+}
+
+uint8_t FTDI::Poll() {
+ uint8_t rcode = 0;
+
+ //if (!bPollEnable)
+ // return 0;
+
+ //if (qNextPollTime <= millis())
+ //{
+ // USB_HOST_SERIAL.println(bAddress, HEX);
+
+ // qNextPollTime = millis() + 100;
+ //}
+ return rcode;
+}
+
+uint8_t FTDI::SetBaudRate(uint32_t baud) {
+ uint16_t baud_value, baud_index = 0;
+ uint32_t divisor3;
+
+ divisor3 = 48000000 / 2 / baud; // divisor shifted 3 bits to the left
+
+ if(wFTDIType == FT232AM) {
+ if((divisor3 & 0x7) == 7)
+ divisor3++; // round x.7/8 up to x+1
+
+ baud_value = divisor3 >> 3;
+ divisor3 &= 0x7;
+
+ if(divisor3 == 1) baud_value |= 0xc000;
+ else // 0.125
+ if(divisor3 >= 4) baud_value |= 0x4000;
+ else // 0.5
+ if(divisor3 != 0) baud_value |= 0x8000; // 0.25
+ if(baud_value == 1) baud_value = 0; /* special case for maximum baud rate */
+ } else {
+ static const unsigned char divfrac [8] = {0, 3, 2, 0, 1, 1, 2, 3};
+ static const unsigned char divindex[8] = {0, 0, 0, 1, 0, 1, 1, 1};
+
+ baud_value = divisor3 >> 3;
+ baud_value |= divfrac [divisor3 & 0x7] << 14;
+ baud_index = divindex[divisor3 & 0x7];
+
+ /* Deal with special cases for highest baud rates. */
+ if(baud_value == 1) baud_value = 0;
+ else // 1.0
+ if(baud_value == 0x4001) baud_value = 1; // 1.5
+ }
+ USBTRACE2("baud_value:", baud_value);
+ USBTRACE2("baud_index:", baud_index);
+ return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_SET_BAUD_RATE, baud_value & 0xff, baud_value >> 8, baud_index, 0, 0, NULL, NULL);
+}
+
+uint8_t FTDI::SetModemControl(uint16_t signal) {
+ return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_MODEM_CTRL, signal & 0xff, signal >> 8, 0, 0, 0, NULL, NULL);
+}
+
+uint8_t FTDI::SetFlowControl(uint8_t protocol, uint8_t xon, uint8_t xoff) {
+ return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_SET_FLOW_CTRL, xon, xoff, protocol << 8, 0, 0, NULL, NULL);
+}
+
+uint8_t FTDI::SetData(uint16_t databm) {
+ return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_SET_DATA, databm & 0xff, databm >> 8, 0, 0, 0, NULL, NULL);
+}
+
+uint8_t FTDI::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr) {
+ return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr);
+}
+
+uint8_t FTDI::SndData(uint16_t nbytes, uint8_t *dataptr) {
+ return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr);
+}
+
+void FTDI::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) {
+ Notify(PSTR("Endpoint descriptor:"), 0x80);
+ Notify(PSTR("\r\nLength:\t\t"), 0x80);
+ D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
+ Notify(PSTR("\r\nType:\t\t"), 0x80);
+ D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
+ Notify(PSTR("\r\nAddress:\t"), 0x80);
+ D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
+ Notify(PSTR("\r\nAttributes:\t"), 0x80);
+ D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
+ Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
+ D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
+ Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
+ D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
+ Notify(PSTR("\r\n"), 0x80);
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcftdi.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcftdi.h
new file mode 100644
index 000000000..b73125262
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcftdi.h
@@ -0,0 +1,145 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+#if !defined(__CDCFTDI_H__)
+#define __CDCFTDI_H__
+
+#include "Usb.h"
+
+#define bmREQ_FTDI_OUT 0x40
+#define bmREQ_FTDI_IN 0xc0
+
+//#define bmREQ_FTDI_OUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
+//#define bmREQ_FTDI_IN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
+
+#define FTDI_VID 0x0403 // FTDI VID
+#define FTDI_PID 0x6001 // FTDI PID
+
+#define FT232AM 0x0200
+#define FT232BM 0x0400
+#define FT2232 0x0500
+#define FT232R 0x0600
+
+// Commands
+#define FTDI_SIO_RESET 0 /* Reset the port */
+#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */
+#define FTDI_SIO_SET_FLOW_CTRL 2 /* Set flow control register */
+#define FTDI_SIO_SET_BAUD_RATE 3 /* Set baud rate */
+#define FTDI_SIO_SET_DATA 4 /* Set the data characteristics of the port */
+#define FTDI_SIO_GET_MODEM_STATUS 5 /* Retrieve current value of modem status register */
+#define FTDI_SIO_SET_EVENT_CHAR 6 /* Set the event character */
+#define FTDI_SIO_SET_ERROR_CHAR 7 /* Set the error character */
+
+#define FTDI_SIO_RESET_SIO 0
+#define FTDI_SIO_RESET_PURGE_RX 1
+#define FTDI_SIO_RESET_PURGE_TX 2
+
+#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8 )
+#define FTDI_SIO_SET_DATA_PARITY_ODD (0x1 << 8 )
+#define FTDI_SIO_SET_DATA_PARITY_EVEN (0x2 << 8 )
+#define FTDI_SIO_SET_DATA_PARITY_MARK (0x3 << 8 )
+#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8 )
+#define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11)
+#define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11)
+#define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11)
+#define FTDI_SIO_SET_BREAK (0x1 << 14)
+
+#define FTDI_SIO_SET_DTR_MASK 0x1
+#define FTDI_SIO_SET_DTR_HIGH ( 1 | ( FTDI_SIO_SET_DTR_MASK << 8))
+#define FTDI_SIO_SET_DTR_LOW ( 0 | ( FTDI_SIO_SET_DTR_MASK << 8))
+#define FTDI_SIO_SET_RTS_MASK 0x2
+#define FTDI_SIO_SET_RTS_HIGH ( 2 | ( FTDI_SIO_SET_RTS_MASK << 8 ))
+#define FTDI_SIO_SET_RTS_LOW ( 0 | ( FTDI_SIO_SET_RTS_MASK << 8 ))
+
+#define FTDI_SIO_DISABLE_FLOW_CTRL 0x0
+#define FTDI_SIO_RTS_CTS_HS (0x1 << 8)
+#define FTDI_SIO_DTR_DSR_HS (0x2 << 8)
+#define FTDI_SIO_XON_XOFF_HS (0x4 << 8)
+
+#define FTDI_SIO_CTS_MASK 0x10
+#define FTDI_SIO_DSR_MASK 0x20
+#define FTDI_SIO_RI_MASK 0x40
+#define FTDI_SIO_RLSD_MASK 0x80
+
+class FTDI;
+
+class FTDIAsyncOper {
+public:
+
+ virtual uint8_t OnInit(FTDI *pftdi) {
+ return 0;
+ };
+
+ virtual uint8_t OnRelease(FTDI *pftdi) {
+ return 0;
+ };
+};
+
+
+// Only single port chips are currently supported by the library,
+// so only three endpoints are allocated.
+#define FTDI_MAX_ENDPOINTS 3
+
+class FTDI : public USBDeviceConfig, public UsbConfigXtracter {
+ static const uint8_t epDataInIndex; // DataIn endpoint index
+ static const uint8_t epDataOutIndex; // DataOUT endpoint index
+ static const uint8_t epInterruptInIndex; // InterruptIN endpoint index
+
+ FTDIAsyncOper *pAsync;
+ USB *pUsb;
+ uint8_t bAddress;
+ uint8_t bConfNum; // configuration number
+ uint8_t bNumIface; // number of interfaces in the configuration
+ uint8_t bNumEP; // total number of EP in the configuration
+ uint32_t qNextPollTime; // next poll time
+ bool bPollEnable; // poll enable flag
+ uint16_t wFTDIType; // Type of FTDI chip
+
+ EpInfo epInfo[FTDI_MAX_ENDPOINTS];
+
+ void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr);
+
+public:
+ FTDI(USB *pusb, FTDIAsyncOper *pasync);
+
+ uint8_t SetBaudRate(uint32_t baud);
+ uint8_t SetModemControl(uint16_t control);
+ uint8_t SetFlowControl(uint8_t protocol, uint8_t xon = 0x11, uint8_t xoff = 0x13);
+ uint8_t SetData(uint16_t databm);
+
+ // Methods for recieving and sending data
+ uint8_t RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr);
+ uint8_t SndData(uint16_t nbytes, uint8_t *dataptr);
+
+ // USBDeviceConfig implementation
+ uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
+ uint8_t Release();
+ uint8_t Poll();
+
+ virtual uint8_t GetAddress() {
+ return bAddress;
+ };
+
+ // UsbConfigXtracter implementation
+ void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
+
+ virtual bool VIDPIDOK(uint16_t vid, uint16_t pid) {
+ return (vid == FTDI_VID && pid == FTDI_PID);
+ }
+
+};
+
+#endif // __CDCFTDI_H__
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcprolific.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcprolific.cpp
new file mode 100644
index 000000000..eceb1df9f
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcprolific.cpp
@@ -0,0 +1,247 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+#include "cdcprolific.h"
+
+PL2303::PL2303(USB *p, CDCAsyncOper *pasync) :
+ACM(p, pasync),
+wPLType(0) {
+}
+
+uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) {
+ const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
+
+ uint8_t buf[constBufSize];
+ USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
+ uint8_t rcode;
+ UsbDevice *p = NULL;
+ EpInfo *oldep_ptr = NULL;
+ uint8_t num_of_conf; // number of configurations
+#ifdef PL2303_COMPAT
+ enum pl2303_type pltype = unknown;
+#endif
+
+ AddressPool &addrPool = pUsb->GetAddressPool();
+
+ USBTRACE("PL Init\r\n");
+
+ if(bAddress)
+ return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
+
+ // Get pointer to pseudo device with address 0 assigned
+ p = addrPool.GetUsbDevicePtr(0);
+
+ if(!p)
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+ if(!p->epinfo) {
+ USBTRACE("epinfo\r\n");
+ return USB_ERROR_EPINFO_IS_NULL;
+ }
+
+ // Save old pointer to EP_RECORD of address 0
+ oldep_ptr = p->epinfo;
+
+ // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
+ p->epinfo = epInfo;
+
+ p->lowspeed = lowspeed;
+
+ // Get device descriptor
+ rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);
+
+ // Restore p->epinfo
+ p->epinfo = oldep_ptr;
+
+ if(rcode)
+ goto FailGetDevDescr;
+
+ if(udd->idVendor != PL_VID && CHECK_PID(udd->idProduct))
+ return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
+
+ /* determine chip variant */
+#ifdef PL2303_COMPAT
+ if(udd->bDeviceClass == 0x02 )
+ pltype = type_0;
+ else if(udd->bMaxPacketSize0 == 0x40 )
+ pltype = rev_HX;
+ else if(udd->bDeviceClass == 0x00)
+ pltype = type_1;
+ else if(udd->bDeviceClass == 0xff)
+ pltype = type_1;
+#endif
+
+ // Save type of PL chip
+ wPLType = udd->bcdDevice;
+
+ // Allocate new address according to device class
+ bAddress = addrPool.AllocAddress(parent, false, port);
+
+ if(!bAddress)
+ return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
+
+ // Extract Max Packet Size from the device descriptor
+ epInfo[0].maxPktSize = udd->bMaxPacketSize0;
+
+ // Assign new address to the device
+ rcode = pUsb->setAddr(0, 0, bAddress);
+
+ if(rcode) {
+ p->lowspeed = false;
+ addrPool.FreeAddress(bAddress);
+ bAddress = 0;
+ USBTRACE2("setAddr:", rcode);
+ return rcode;
+ }
+
+ USBTRACE2("Addr:", bAddress);
+
+ p->lowspeed = false;
+
+ p = addrPool.GetUsbDevicePtr(bAddress);
+
+ if(!p)
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+ p->lowspeed = lowspeed;
+
+ num_of_conf = udd->bNumConfigurations;
+
+ // Assign epInfo to epinfo pointer
+ rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
+
+ if(rcode)
+ goto FailSetDevTblEntry;
+
+ USBTRACE2("NC:", num_of_conf);
+
+ for(uint8_t i = 0; i < num_of_conf; i++) {
+ HexDumper<USBReadParser, uint16_t, uint16_t> HexDump;
+ ConfigDescParser < 0xFF, 0, 0, CP_MASK_COMPARE_CLASS> confDescrParser(this);
+
+ rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump);
+
+ if(rcode)
+ goto FailGetConfDescr;
+
+ rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
+
+ if(rcode)
+ goto FailGetConfDescr;
+
+ if(bNumEP > 1)
+ break;
+ } // for
+
+ if(bNumEP < 2)
+ return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
+
+ // Assign epInfo to epinfo pointer
+ rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
+
+ USBTRACE2("Conf:", bConfNum);
+
+ // Set Configuration Value
+ rcode = pUsb->setConf(bAddress, 0, bConfNum);
+
+ if(rcode)
+ goto FailSetConfDescr;
+
+#ifdef PL2303_COMPAT
+ /* Shamanic dance - sending Prolific init data as-is */
+ vendorRead( 0x84, 0x84, 0, buf );
+ vendorWrite( 0x04, 0x04, 0 );
+ vendorRead( 0x84, 0x84, 0, buf );
+ vendorRead( 0x83, 0x83, 0, buf );
+ vendorRead( 0x84, 0x84, 0, buf );
+ vendorWrite( 0x04, 0x04, 1 );
+ vendorRead( 0x84, 0x84, 0, buf);
+ vendorRead( 0x83, 0x83, 0, buf);
+ vendorWrite( 0, 0, 1 );
+ vendorWrite( 1, 0, 0 );
+ if( pltype == rev_HX ) {
+ vendorWrite( 2, 0, 0x44 );
+ vendorWrite( 0x06, 0x06, 0 ); // From W7 init
+ }
+ else {
+ vendorWrite( 2, 0, 0x24 );
+ }
+ /* Shamanic dance end */
+#endif
+ /* Calling post-init callback */
+ rcode = pAsync->OnInit(this);
+
+ if(rcode)
+ goto FailOnInit;
+
+ USBTRACE("PL configured\r\n");
+
+ //bPollEnable = true;
+ ready = true;
+ return 0;
+
+FailGetDevDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailGetDevDescr();
+ goto Fail;
+#endif
+
+FailSetDevTblEntry:
+#ifdef DEBUG_USB_HOST
+ NotifyFailSetDevTblEntry();
+ goto Fail;
+#endif
+
+FailGetConfDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailGetConfDescr();
+ goto Fail;
+#endif
+
+FailSetConfDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailSetConfDescr();
+ goto Fail;
+#endif
+
+FailOnInit:
+#ifdef DEBUG_USB_HOST
+ USBTRACE("OnInit:");
+#endif
+
+#ifdef DEBUG_USB_HOST
+Fail:
+ NotifyFail(rcode);
+#endif
+ Release();
+ return rcode;
+}
+
+//uint8_t PL::Poll()
+//{
+// uint8_t rcode = 0;
+//
+// //if (!bPollEnable)
+// // return 0;
+//
+// //if (qNextPollTime <= millis())
+// //{
+// // USB_HOST_SERIAL.println(bAddress, HEX);
+//
+// // qNextPollTime = millis() + 100;
+// //}
+// return rcode;
+//}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcprolific.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcprolific.h
new file mode 100644
index 000000000..499146641
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/cdcprolific.h
@@ -0,0 +1,159 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+#if !defined(__CDCPROLIFIC_H__)
+#define __CDCPROLIFIC_H__
+
+#include "cdcacm.h"
+
+//#define PL2303_COMPAT // Uncomment it if you have compatibility problems
+
+#define PL_VID 0x067B
+#define CHECK_PID(pid) ( pid != 0x2303 && pid != 0x0609 )
+
+//#define PL_PID 0x0609
+
+#define PROLIFIC_REV_H 0x0202
+#define PROLIFIC_REV_X 0x0300
+#define PROLIFIC_REV_HX_CHIP_D 0x0400
+#define PROLIFIC_REV_1 0x0001
+
+#define kXOnChar '\x11'
+#define kXOffChar '\x13'
+
+#define SPECIAL_SHIFT (5)
+#define SPECIAL_MASK ((1<<SPECIAL_SHIFT) - 1)
+#define STATE_ALL ( PD_RS232_S_MASK | PD_S_MASK )
+#define FLOW_RX_AUTO ( PD_RS232_A_RFR | PD_RS232_A_DTR | PD_RS232_A_RXO )
+#define FLOW_TX_AUTO ( PD_RS232_A_CTS | PD_RS232_A_DSR | PD_RS232_A_TXO | PD_RS232_A_DCD )
+#define CAN_BE_AUTO ( FLOW_RX_AUTO | FLOW_TX_AUTO )
+#define CAN_NOTIFY ( PD_RS232_N_MASK )
+#define EXTERNAL_MASK ( PD_S_MASK | (PD_RS232_S_MASK & ~PD_RS232_S_LOOP) )
+#define INTERNAL_DELAY ( PD_RS232_S_LOOP )
+#define DEFAULT_AUTO ( PD_RS232_A_DTR | PD_RS232_A_RFR | PD_RS232_A_CTS | PD_RS232_A_DSR )
+#define DEFAULT_NOTIFY 0x00
+#define DEFAULT_STATE ( PD_S_TX_ENABLE | PD_S_RX_ENABLE | PD_RS232_A_TXO | PD_RS232_A_RXO )
+
+#define CONTINUE_SEND 1
+#define PAUSE_SEND 2
+
+#define kRxAutoFlow ((UInt32)( PD_RS232_A_RFR | PD_RS232_A_DTR | PD_RS232_A_RXO ))
+#define kTxAutoFlow ((UInt32)( PD_RS232_A_CTS | PD_RS232_A_DSR | PD_RS232_A_TXO | PD_RS232_A_DCD ))
+#define kControl_StateMask ((UInt32)( PD_RS232_S_CTS | PD_RS232_S_DSR | PD_RS232_S_CAR | PD_RS232_S_RI ))
+#define kRxQueueState ((UInt32)( PD_S_RXQ_EMPTY | PD_S_RXQ_LOW_WATER | PD_S_RXQ_HIGH_WATER | PD_S_RXQ_FULL ))
+#define kTxQueueState ((UInt32)( PD_S_TXQ_EMPTY | PD_S_TXQ_LOW_WATER | PD_S_TXQ_HIGH_WATER | PD_S_TXQ_FULL ))
+
+#define kCONTROL_DTR 0x01
+#define kCONTROL_RTS 0x02
+
+#define kStateTransientMask 0x74
+#define kBreakError 0x04
+#define kFrameError 0x10
+#define kParityError 0x20
+#define kOverrunError 0x40
+
+#define kCTS 0x80
+#define kDSR 0x02
+#define kRI 0x08
+#define kDCD 0x01
+#define kHandshakeInMask ((UInt32)( PD_RS232_S_CTS | PD_RS232_S_DSR | PD_RS232_S_CAR | PD_RS232_S_RI ))
+
+#define VENDOR_WRITE_REQUEST_TYPE 0x40
+#define VENDOR_WRITE_REQUEST 0x01
+
+#define VENDOR_READ_REQUEST_TYPE 0xc0
+#define VENDOR_READ_REQUEST 0x01
+
+// Device Configuration Registers (DCR0, DCR1, DCR2)
+#define SET_DCR0 0x00
+#define GET_DCR0 0x80
+#define DCR0_INIT 0x01
+#define DCR0_INIT_H 0x41
+#define DCR0_INIT_X 0x61
+
+#define SET_DCR1 0x01
+#define GET_DCR1 0x81
+#define DCR1_INIT_H 0x80
+#define DCR1_INIT_X 0x00
+
+#define SET_DCR2 0x02
+#define GET_DCR2 0x82
+#define DCR2_INIT_H 0x24
+#define DCR2_INIT_X 0x44
+
+// On-chip Data Buffers:
+#define RESET_DOWNSTREAM_DATA_PIPE 0x08
+#define RESET_UPSTREAM_DATA_PIPE 0x09
+
+
+#define PL_MAX_ENDPOINTS 4
+
+enum tXO_State {
+ kXOnSent = -2,
+ kXOffSent = -1,
+ kXO_Idle = 0,
+ kXOffNeeded = 1,
+ kXOnNeeded = 2
+};
+
+enum pl2303_type {
+ unknown,
+ type_0, /* don't know the difference between type 0 and */
+ type_1, /* type 1, until someone from prolific tells us... */
+ rev_X,
+ rev_HX, /* HX version of the pl2303 chip */
+ rev_H
+};
+
+
+class PL2303 : public ACM {
+ uint16_t wPLType; // Type of chip
+
+public:
+ PL2303(USB *pusb, CDCAsyncOper *pasync);
+
+ // USBDeviceConfig implementation
+ uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
+ //virtual uint8_t Release();
+ //virtual uint8_t Poll();
+ //virtual uint8_t GetAddress() { return bAddress; };
+
+ //// UsbConfigXtracter implementation
+ //virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
+
+#ifdef PL2303_COMPAT
+private:
+ /* Prolific proprietary requests */
+ uint8_t vendorRead( uint8_t val_lo, uint8_t val_hi, uint16_t index, uint8_t* buf );
+ uint8_t vendorWrite( uint8_t val_lo, uint8_t val_hi, uint8_t index );
+#endif
+};
+
+#ifdef PL2303_COMPAT
+/* vendor read request */
+inline uint8_t PL2303::vendorRead( uint8_t val_lo, uint8_t val_hi, uint16_t index, uint8_t* buf )
+{
+ return( pUsb->ctrlReq(bAddress, 0, VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, val_lo, val_hi, index, 1, 1, buf, NULL ));
+}
+
+/* vendor write request */
+inline uint8_t PL2303::vendorWrite( uint8_t val_lo, uint8_t val_hi, uint8_t index )
+{
+ return( pUsb->ctrlReq(bAddress, 0, VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, val_lo, val_hi, index, 0, 0, NULL, NULL ));
+}
+#endif
+
+#endif // __CDCPROLIFIC_H__
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/confdescparser.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/confdescparser.h
new file mode 100644
index 000000000..a6806f2ea
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/confdescparser.h
@@ -0,0 +1,213 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+#if !defined(_usb_h_) || defined(__CONFDESCPARSER_H__)
+#error "Never include confdescparser.h directly; include Usb.h instead"
+#else
+
+#define __CONFDESCPARSER_H__
+
+class UsbConfigXtracter {
+public:
+ //virtual void ConfigXtract(const USB_CONFIGURATION_DESCRIPTOR *conf) = 0;
+ //virtual void InterfaceXtract(uint8_t conf, const USB_INTERFACE_DESCRIPTOR *iface) = 0;
+
+ virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep) {
+ };
+};
+
+#define CP_MASK_COMPARE_CLASS 1
+#define CP_MASK_COMPARE_SUBCLASS 2
+#define CP_MASK_COMPARE_PROTOCOL 4
+#define CP_MASK_COMPARE_ALL 7
+
+// Configuration Descriptor Parser Class Template
+
+template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
+class ConfigDescParser : public USBReadParser {
+ UsbConfigXtracter *theXtractor;
+ MultiValueBuffer theBuffer;
+ MultiByteValueParser valParser;
+ ByteSkipper theSkipper;
+ uint8_t varBuffer[16 /*sizeof(USB_CONFIGURATION_DESCRIPTOR)*/];
+
+ uint8_t stateParseDescr; // ParseDescriptor state
+
+ uint8_t dscrLen; // Descriptor length
+ uint8_t dscrType; // Descriptor type
+
+ bool isGoodInterface; // Apropriate interface flag
+ uint8_t confValue; // Configuration value
+ uint8_t protoValue; // Protocol value
+ uint8_t ifaceNumber; // Interface number
+ uint8_t ifaceAltSet; // Interface alternate settings
+
+ bool UseOr;
+ bool ParseDescriptor(uint8_t **pp, uint16_t *pcntdn);
+ void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc);
+
+public:
+
+ void SetOR(void) {
+ UseOr = true;
+ }
+ ConfigDescParser(UsbConfigXtracter *xtractor);
+ void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset);
+};
+
+template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
+ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ConfigDescParser(UsbConfigXtracter *xtractor) :
+theXtractor(xtractor),
+stateParseDescr(0),
+dscrLen(0),
+dscrType(0),
+UseOr(false) {
+ theBuffer.pValue = varBuffer;
+ valParser.Initialize(&theBuffer);
+ theSkipper.Initialize(&theBuffer);
+};
+
+template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
+void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) {
+ uint16_t cntdn = (uint16_t)len;
+ uint8_t *p = (uint8_t*)pbuf;
+
+ while(cntdn)
+ if(!ParseDescriptor(&p, &cntdn))
+ return;
+}
+
+/* Parser for the configuration descriptor. Takes values for class, subclass, protocol fields in interface descriptor and
+ compare masks for them. When the match is found, calls EndpointXtract passing buffer containing endpoint descriptor */
+template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
+bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor(uint8_t **pp, uint16_t *pcntdn) {
+ USB_CONFIGURATION_DESCRIPTOR* ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR*>(varBuffer);
+ USB_INTERFACE_DESCRIPTOR* uid = reinterpret_cast<USB_INTERFACE_DESCRIPTOR*>(varBuffer);
+ switch(stateParseDescr) {
+ case 0:
+ theBuffer.valueSize = 2;
+ valParser.Initialize(&theBuffer);
+ stateParseDescr = 1;
+ case 1:
+ if(!valParser.Parse(pp, pcntdn))
+ return false;
+ dscrLen = *((uint8_t*)theBuffer.pValue);
+ dscrType = *((uint8_t*)theBuffer.pValue + 1);
+ stateParseDescr = 2;
+ case 2:
+ // This is a sort of hack. Assuming that two bytes are all ready in the buffer
+ // the pointer is positioned two bytes ahead in order for the rest of descriptor
+ // to be read right after the size and the type fields.
+ // This should be used carefully. varBuffer should be used directly to handle data
+ // in the buffer.
+ theBuffer.pValue = varBuffer + 2;
+ stateParseDescr = 3;
+ case 3:
+ switch(dscrType) {
+ case USB_DESCRIPTOR_INTERFACE:
+ isGoodInterface = false;
+ case USB_DESCRIPTOR_CONFIGURATION:
+ theBuffer.valueSize = sizeof (USB_CONFIGURATION_DESCRIPTOR) - 2;
+ break;
+ case USB_DESCRIPTOR_ENDPOINT:
+ theBuffer.valueSize = sizeof (USB_ENDPOINT_DESCRIPTOR) - 2;
+ break;
+ case HID_DESCRIPTOR_HID:
+ theBuffer.valueSize = dscrLen - 2;
+ break;
+ }
+ valParser.Initialize(&theBuffer);
+ stateParseDescr = 4;
+ case 4:
+ switch(dscrType) {
+ case USB_DESCRIPTOR_CONFIGURATION:
+ if(!valParser.Parse(pp, pcntdn))
+ return false;
+ confValue = ucd->bConfigurationValue;
+ break;
+ case USB_DESCRIPTOR_INTERFACE:
+ if(!valParser.Parse(pp, pcntdn))
+ return false;
+ if((MASK & CP_MASK_COMPARE_CLASS) && uid->bInterfaceClass != CLASS_ID)
+ break;
+ if((MASK & CP_MASK_COMPARE_SUBCLASS) && uid->bInterfaceSubClass != SUBCLASS_ID)
+ break;
+ if(UseOr) {
+ if((!((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol)))
+ break;
+ } else {
+ if((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol != PROTOCOL_ID)
+ break;
+ }
+ isGoodInterface = true;
+ ifaceNumber = uid->bInterfaceNumber;
+ ifaceAltSet = uid->bAlternateSetting;
+ protoValue = uid->bInterfaceProtocol;
+ break;
+ case USB_DESCRIPTOR_ENDPOINT:
+ if(!valParser.Parse(pp, pcntdn))
+ return false;
+ if(isGoodInterface)
+ if(theXtractor)
+ theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_ENDPOINT_DESCRIPTOR*)varBuffer);
+ break;
+ //case HID_DESCRIPTOR_HID:
+ // if (!valParser.Parse(pp, pcntdn))
+ // return false;
+ // PrintHidDescriptor((const USB_HID_DESCRIPTOR*)varBuffer);
+ // break;
+ default:
+ if(!theSkipper.Skip(pp, pcntdn, dscrLen - 2))
+ return false;
+ }
+ theBuffer.pValue = varBuffer;
+ stateParseDescr = 0;
+ }
+ return true;
+}
+
+template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
+void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc) {
+ Notify(PSTR("\r\n\r\nHID Descriptor:\r\n"), 0x80);
+ Notify(PSTR("bDescLength:\t\t"), 0x80);
+ PrintHex<uint8_t > (pDesc->bLength, 0x80);
+
+ Notify(PSTR("\r\nbDescriptorType:\t"), 0x80);
+ PrintHex<uint8_t > (pDesc->bDescriptorType, 0x80);
+
+ Notify(PSTR("\r\nbcdHID:\t\t\t"), 0x80);
+ PrintHex<uint16_t > (pDesc->bcdHID, 0x80);
+
+ Notify(PSTR("\r\nbCountryCode:\t\t"), 0x80);
+ PrintHex<uint8_t > (pDesc->bCountryCode, 0x80);
+
+ Notify(PSTR("\r\nbNumDescriptors:\t"), 0x80);
+ PrintHex<uint8_t > (pDesc->bNumDescriptors, 0x80);
+
+ for(uint8_t i = 0; i < pDesc->bNumDescriptors; i++) {
+ HID_CLASS_DESCRIPTOR_LEN_AND_TYPE *pLT = (HID_CLASS_DESCRIPTOR_LEN_AND_TYPE*)&(pDesc->bDescrType);
+
+ Notify(PSTR("\r\nbDescrType:\t\t"), 0x80);
+ PrintHex<uint8_t > (pLT[i].bDescrType, 0x80);
+
+ Notify(PSTR("\r\nwDescriptorLength:\t"), 0x80);
+ PrintHex<uint16_t > (pLT[i].wDescriptorLength, 0x80);
+ }
+ Notify(PSTR("\r\n"), 0x80);
+}
+
+
+#endif // __CONFDESCPARSER_H__
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/controllerEnums.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/controllerEnums.h
new file mode 100644
index 000000000..0169c763c
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/controllerEnums.h
@@ -0,0 +1,204 @@
+/* Copyright (C) 2013 Kristian Lauszus, TKJ Electronics. All rights reserved.
+
+ This software may be distributed and modified under the terms of the GNU
+ General Public License version 2 (GPL2) as published by the Free Software
+ Foundation and appearing in the file GPL2.TXT included in the packaging of
+ this file. Please note that GPL2 Section 2[b] requires that all works based
+ on this software must also be made publicly available under the terms of
+ the GPL2 ("Copyleft").
+
+ Contact information
+ -------------------
+
+ Kristian Lauszus, TKJ Electronics
+ Web : http://www.tkjelectronics.com
+ e-mail : kristianl@tkjelectronics.com
+ */
+
+#ifndef _controllerenums_h
+#define _controllerenums_h
+
+/**
+ * This header file is used to store different enums for the controllers,
+ * This is necessary so all the different libraries can be used at once.
+ */
+
+/** Enum used to turn on the LEDs on the different controllers. */
+enum LEDEnum {
+ OFF = 0,
+ LED1 = 1,
+ LED2 = 2,
+ LED3 = 3,
+ LED4 = 4,
+
+ LED5 = 5,
+ LED6 = 6,
+ LED7 = 7,
+ LED8 = 8,
+ LED9 = 9,
+ LED10 = 10,
+ /** Used to blink all LEDs on the Xbox controller */
+ ALL = 5,
+};
+
+/** Used to set the colors of the Move and PS4 controller. */
+enum ColorsEnum {
+ /** r = 255, g = 0, b = 0 */
+ Red = 0xFF0000,
+ /** r = 0, g = 255, b = 0 */
+ Green = 0xFF00,
+ /** r = 0, g = 0, b = 255 */
+ Blue = 0xFF,
+
+ /** r = 255, g = 235, b = 4 */
+ Yellow = 0xFFEB04,
+ /** r = 0, g = 255, b = 255 */
+ Lightblue = 0xFFFF,
+ /** r = 255, g = 0, b = 255 */
+ Purble = 0xFF00FF,
+
+ /** r = 255, g = 255, b = 255 */
+ White = 0xFFFFFF,
+ /** r = 0, g = 0, b = 0 */
+ Off = 0x00,
+};
+
+enum RumbleEnum {
+ RumbleHigh = 0x10,
+ RumbleLow = 0x20,
+};
+
+/** This enum is used to read all the different buttons on the different controllers */
+enum ButtonEnum {
+ /**@{*/
+ /** These buttons are available on all the the controllers */
+ UP = 0,
+ RIGHT = 1,
+ DOWN = 2,
+ LEFT = 3,
+ /**@}*/
+
+ /**@{*/
+ /** Wii buttons */
+ PLUS = 5,
+ TWO = 6,
+ ONE = 7,
+ MINUS = 8,
+ HOME = 9,
+ Z = 10,
+ C = 11,
+ B = 12,
+ A = 13,
+ /**@}*/
+
+ /**@{*/
+ /** These are only available on the Wii U Pro Controller */
+ L = 16,
+ R = 17,
+ ZL = 18,
+ ZR = 19,
+ /**@}*/
+
+ /**@{*/
+ /** PS3 controllers buttons */
+ SELECT = 4,
+ START = 5,
+ L3 = 6,
+ R3 = 7,
+
+ L2 = 8,
+ R2 = 9,
+ L1 = 10,
+ R1 = 11,
+ TRIANGLE = 12,
+ CIRCLE = 13,
+ CROSS = 14,
+ SQUARE = 15,
+
+ PS = 16,
+
+ MOVE = 17, // Covers 12 bits - we only need to read the top 8
+ T = 18, // Covers 12 bits - we only need to read the top 8
+ /**@}*/
+
+ /** PS4 controllers buttons - SHARE and OPTIONS are present instead of SELECT and START */
+ SHARE = 4,
+ OPTIONS = 5,
+ TOUCHPAD = 17,
+ /**@}*/
+
+ /**@{*/
+ /** Xbox buttons */
+ BACK = 4,
+ X = 14,
+ Y = 15,
+ XBOX = 16,
+ SYNC = 17,
+ BLACK = 8, // Available on the original Xbox controller
+ WHITE = 9, // Available on the original Xbox controller
+ /**@}*/
+
+ /** PS Buzz controllers */
+ RED = 0,
+ YELLOW = 1,
+ GREEN = 2,
+ ORANGE = 3,
+ BLUE = 4,
+ /**@}*/
+};
+
+/** Joysticks on the PS3 and Xbox controllers. */
+enum AnalogHatEnum {
+ /** Left joystick x-axis */
+ LeftHatX = 0,
+ /** Left joystick y-axis */
+ LeftHatY = 1,
+ /** Right joystick x-axis */
+ RightHatX = 2,
+ /** Right joystick y-axis */
+ RightHatY = 3,
+};
+
+/**
+ * Sensors inside the Sixaxis Dualshock 3, Move controller and PS4 controller.
+ * <B>Note:</B> that the location is shifted 9 when it's connected via USB on the PS3 controller.
+ */
+enum SensorEnum {
+ /** Accelerometer values */
+ aX = 50, aY = 52, aZ = 54,
+ /** Gyro z-axis */
+ gZ = 56,
+ gX, gY, // These are not available on the PS3 controller
+
+ /** Accelerometer x-axis */
+ aXmove = 28,
+ /** Accelerometer z-axis */
+ aZmove = 30,
+ /** Accelerometer y-axis */
+ aYmove = 32,
+
+ /** Gyro x-axis */
+ gXmove = 40,
+ /** Gyro z-axis */
+ gZmove = 42,
+ /** Gyro y-axis */
+ gYmove = 44,
+
+ /** Temperature sensor */
+ tempMove = 46,
+
+ /** Magnetometer x-axis */
+ mXmove = 47,
+ /** Magnetometer z-axis */
+ mZmove = 49,
+ /** Magnetometer y-axis */
+ mYmove = 50,
+};
+
+/** Used to get the angle calculated using the PS3 controller and PS4 controller. */
+enum AngleEnum {
+ Pitch = 0x01,
+ Roll = 0x02,
+};
+
+#endif
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/BTHID.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/BTHID.ino
new file mode 100644
index 000000000..919a56468
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/BTHID.ino
@@ -0,0 +1,55 @@
+/*
+ Example sketch for the HID Bluetooth library - developed by Kristian Lauszus
+ For more information visit my blog: http://blog.tkjelectronics.dk/ or
+ send me an e-mail: kristianl@tkjelectronics.com
+ */
+
+#include <BTHID.h>
+#include <usbhub.h>
+#include "KeyboardParser.h"
+#include "MouseParser.h"
+
+// Satisfy the IDE, which needs to see the include statment in the ino too.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+USB Usb;
+//USBHub Hub1(&Usb); // Some dongles have a hub inside
+BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so
+
+/* You can create the instance of the class in two ways */
+// This will start an inquiry and then pair with your device - you only have to do this once
+// If you are using a Bluetooth keyboard, then you should type in the password on the keypad and then press enter
+BTHID bthid(&Btd, PAIR, "0000");
+
+// After that you can simply create the instance like so and then press any button on the device
+//BTHID hid(&Btd);
+
+KbdRptParser keyboardPrs;
+MouseRptParser mousePrs;
+
+void setup() {
+ Serial.begin(115200);
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ if (Usb.Init() == -1) {
+ Serial.print(F("\r\nOSC did not start"));
+ while (1); // Halt
+ }
+
+ bthid.SetReportParser(KEYBOARD_PARSER_ID, (HIDReportParser*)&keyboardPrs);
+ bthid.SetReportParser(MOUSE_PARSER_ID, (HIDReportParser*)&mousePrs);
+
+ // If "Boot Protocol Mode" does not work, then try "Report Protocol Mode"
+ // If that does not work either, then uncomment PRINTREPORT in BTHID.cpp to see the raw report
+ bthid.setProtocolMode(HID_BOOT_PROTOCOL); // Boot Protocol Mode
+ //bthid.setProtocolMode(HID_RPT_PROTOCOL); // Report Protocol Mode
+
+ Serial.print(F("\r\nHID Bluetooth Library Started"));
+}
+void loop() {
+ Usb.Task();
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/KeyboardParser.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/KeyboardParser.h
new file mode 100644
index 000000000..c5394331d
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/KeyboardParser.h
@@ -0,0 +1,105 @@
+#ifndef __kbdrptparser_h_
+#define __kbdrptparser_h_
+
+class KbdRptParser : public KeyboardReportParser {
+ protected:
+ virtual uint8_t HandleLockingKeys(HID *hid, uint8_t key);
+ virtual void OnControlKeysChanged(uint8_t before, uint8_t after);
+ virtual void OnKeyDown(uint8_t mod, uint8_t key);
+ virtual void OnKeyUp(uint8_t mod, uint8_t key);
+ virtual void OnKeyPressed(uint8_t key);
+
+ private:
+ void PrintKey(uint8_t mod, uint8_t key);
+};
+
+uint8_t KbdRptParser::HandleLockingKeys(HID *hid, uint8_t key) {
+ uint8_t old_keys = kbdLockingKeys.bLeds;
+
+ switch (key) {
+ case UHS_HID_BOOT_KEY_NUM_LOCK:
+ Serial.println(F("Num lock"));
+ kbdLockingKeys.kbdLeds.bmNumLock = ~kbdLockingKeys.kbdLeds.bmNumLock;
+ break;
+ case UHS_HID_BOOT_KEY_CAPS_LOCK:
+ Serial.println(F("Caps lock"));
+ kbdLockingKeys.kbdLeds.bmCapsLock = ~kbdLockingKeys.kbdLeds.bmCapsLock;
+ break;
+ case UHS_HID_BOOT_KEY_SCROLL_LOCK:
+ Serial.println(F("Scroll lock"));
+ kbdLockingKeys.kbdLeds.bmScrollLock = ~kbdLockingKeys.kbdLeds.bmScrollLock;
+ break;
+ }
+
+ if (old_keys != kbdLockingKeys.bLeds && hid) {
+ BTHID *pBTHID = reinterpret_cast<BTHID *> (hid); // A cast the other way around is done in BTHID.cpp
+ pBTHID->setLeds(kbdLockingKeys.bLeds); // Update the LEDs on the keyboard
+ }
+
+ return 0;
+};
+
+void KbdRptParser::PrintKey(uint8_t m, uint8_t key) {
+ MODIFIERKEYS mod;
+ *((uint8_t*)&mod) = m;
+ Serial.print((mod.bmLeftCtrl == 1) ? F("C") : F(" "));
+ Serial.print((mod.bmLeftShift == 1) ? F("S") : F(" "));
+ Serial.print((mod.bmLeftAlt == 1) ? F("A") : F(" "));
+ Serial.print((mod.bmLeftGUI == 1) ? F("G") : F(" "));
+
+ Serial.print(F(" >"));
+ PrintHex<uint8_t>(key, 0x80);
+ Serial.print(F("< "));
+
+ Serial.print((mod.bmRightCtrl == 1) ? F("C") : F(" "));
+ Serial.print((mod.bmRightShift == 1) ? F("S") : F(" "));
+ Serial.print((mod.bmRightAlt == 1) ? F("A") : F(" "));
+ Serial.println((mod.bmRightGUI == 1) ? F("G") : F(" "));
+};
+
+void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key) {
+ Serial.print(F("DN "));
+ PrintKey(mod, key);
+ uint8_t c = OemToAscii(mod, key);
+
+ if (c)
+ OnKeyPressed(c);
+};
+
+void KbdRptParser::OnControlKeysChanged(uint8_t before, uint8_t after) {
+ MODIFIERKEYS beforeMod;
+ *((uint8_t*)&beforeMod) = before;
+
+ MODIFIERKEYS afterMod;
+ *((uint8_t*)&afterMod) = after;
+
+ if (beforeMod.bmLeftCtrl != afterMod.bmLeftCtrl)
+ Serial.println(F("LeftCtrl changed"));
+ if (beforeMod.bmLeftShift != afterMod.bmLeftShift)
+ Serial.println(F("LeftShift changed"));
+ if (beforeMod.bmLeftAlt != afterMod.bmLeftAlt)
+ Serial.println(F("LeftAlt changed"));
+ if (beforeMod.bmLeftGUI != afterMod.bmLeftGUI)
+ Serial.println(F("LeftGUI changed"));
+
+ if (beforeMod.bmRightCtrl != afterMod.bmRightCtrl)
+ Serial.println(F("RightCtrl changed"));
+ if (beforeMod.bmRightShift != afterMod.bmRightShift)
+ Serial.println(F("RightShift changed"));
+ if (beforeMod.bmRightAlt != afterMod.bmRightAlt)
+ Serial.println(F("RightAlt changed"));
+ if (beforeMod.bmRightGUI != afterMod.bmRightGUI)
+ Serial.println(F("RightGUI changed"));
+};
+
+void KbdRptParser::OnKeyUp(uint8_t mod, uint8_t key) {
+ Serial.print(F("UP "));
+ PrintKey(mod, key);
+};
+
+void KbdRptParser::OnKeyPressed(uint8_t key) {
+ Serial.print(F("ASCII: "));
+ Serial.println((char)key);
+};
+
+#endif
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/MouseParser.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/MouseParser.h
new file mode 100644
index 000000000..a9245ded9
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/BTHID/MouseParser.h
@@ -0,0 +1,46 @@
+#ifndef __mouserptparser_h__
+#define __mouserptparser_h__
+
+class MouseRptParser : public MouseReportParser {
+ protected:
+ virtual void OnMouseMove(MOUSEINFO *mi);
+ virtual void OnLeftButtonUp(MOUSEINFO *mi);
+ virtual void OnLeftButtonDown(MOUSEINFO *mi);
+ virtual void OnRightButtonUp(MOUSEINFO *mi);
+ virtual void OnRightButtonDown(MOUSEINFO *mi);
+ virtual void OnMiddleButtonUp(MOUSEINFO *mi);
+ virtual void OnMiddleButtonDown(MOUSEINFO *mi);
+};
+
+void MouseRptParser::OnMouseMove(MOUSEINFO *mi) {
+ Serial.print(F("dx="));
+ Serial.print(mi->dX, DEC);
+ Serial.print(F(" dy="));
+ Serial.println(mi->dY, DEC);
+};
+
+void MouseRptParser::OnLeftButtonUp(MOUSEINFO *mi) {
+ Serial.println(F("L Butt Up"));
+};
+
+void MouseRptParser::OnLeftButtonDown(MOUSEINFO *mi) {
+ Serial.println(F("L Butt Dn"));
+};
+
+void MouseRptParser::OnRightButtonUp(MOUSEINFO *mi) {
+ Serial.println(F("R Butt Up"));
+};
+
+void MouseRptParser::OnRightButtonDown(MOUSEINFO *mi) {
+ Serial.println(F("R Butt Dn"));
+};
+
+void MouseRptParser::OnMiddleButtonUp(MOUSEINFO *mi) {
+ Serial.println(F("M Butt Up"));
+};
+
+void MouseRptParser::OnMiddleButtonDown(MOUSEINFO *mi) {
+ Serial.println(F("M Butt Dn"));
+};
+
+#endif
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS3BT/PS3BT.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS3BT/PS3BT.ino
new file mode 100644
index 000000000..b89673440
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS3BT/PS3BT.ino
@@ -0,0 +1,188 @@
+/*
+ Example sketch for the PS3 Bluetooth library - developed by Kristian Lauszus
+ For more information visit my blog: http://blog.tkjelectronics.dk/ or
+ send me an e-mail: kristianl@tkjelectronics.com
+ */
+
+#include <PS3BT.h>
+#include <usbhub.h>
+
+// Satisfy the IDE, which needs to see the include statment in the ino too.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+USB Usb;
+//USBHub Hub1(&Usb); // Some dongles have a hub inside
+
+BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so
+/* You can create the instance of the class in two ways */
+PS3BT PS3(&Btd); // This will just create the instance
+//PS3BT PS3(&Btd, 0x00, 0x15, 0x83, 0x3D, 0x0A, 0x57); // This will also store the bluetooth address - this can be obtained from the dongle when running the sketch
+
+bool printTemperature;
+bool printAngle;
+
+void setup() {
+ Serial.begin(115200);
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ if (Usb.Init() == -1) {
+ Serial.print(F("\r\nOSC did not start"));
+ while (1); //halt
+ }
+ Serial.print(F("\r\nPS3 Bluetooth Library Started"));
+}
+void loop() {
+ Usb.Task();
+
+ if (PS3.PS3Connected || PS3.PS3NavigationConnected) {
+ if (PS3.getAnalogHat(LeftHatX) > 137 || PS3.getAnalogHat(LeftHatX) < 117 || PS3.getAnalogHat(LeftHatY) > 137 || PS3.getAnalogHat(LeftHatY) < 117 || PS3.getAnalogHat(RightHatX) > 137 || PS3.getAnalogHat(RightHatX) < 117 || PS3.getAnalogHat(RightHatY) > 137 || PS3.getAnalogHat(RightHatY) < 117) {
+ Serial.print(F("\r\nLeftHatX: "));
+ Serial.print(PS3.getAnalogHat(LeftHatX));
+ Serial.print(F("\tLeftHatY: "));
+ Serial.print(PS3.getAnalogHat(LeftHatY));
+ if (PS3.PS3Connected) { // The Navigation controller only have one joystick
+ Serial.print(F("\tRightHatX: "));
+ Serial.print(PS3.getAnalogHat(RightHatX));
+ Serial.print(F("\tRightHatY: "));
+ Serial.print(PS3.getAnalogHat(RightHatY));
+ }
+ }
+
+ // Analog button values can be read from almost all buttons
+ if (PS3.getAnalogButton(L2) || PS3.getAnalogButton(R2)) {
+ Serial.print(F("\r\nL2: "));
+ Serial.print(PS3.getAnalogButton(L2));
+ if (PS3.PS3Connected) {
+ Serial.print(F("\tR2: "));
+ Serial.print(PS3.getAnalogButton(R2));
+ }
+ }
+ if (PS3.getButtonClick(PS)) {
+ Serial.print(F("\r\nPS"));
+ PS3.disconnect();
+ }
+ else {
+ if (PS3.getButtonClick(TRIANGLE))
+ Serial.print(F("\r\nTraingle"));
+ if (PS3.getButtonClick(CIRCLE))
+ Serial.print(F("\r\nCircle"));
+ if (PS3.getButtonClick(CROSS))
+ Serial.print(F("\r\nCross"));
+ if (PS3.getButtonClick(SQUARE))
+ Serial.print(F("\r\nSquare"));
+
+ if (PS3.getButtonClick(UP)) {
+ Serial.print(F("\r\nUp"));
+ if (PS3.PS3Connected) {
+ PS3.setLedOff();
+ PS3.setLedOn(LED4);
+ }
+ }
+ if (PS3.getButtonClick(RIGHT)) {
+ Serial.print(F("\r\nRight"));
+ if (PS3.PS3Connected) {
+ PS3.setLedOff();
+ PS3.setLedOn(LED1);
+ }
+ }
+ if (PS3.getButtonClick(DOWN)) {
+ Serial.print(F("\r\nDown"));
+ if (PS3.PS3Connected) {
+ PS3.setLedOff();
+ PS3.setLedOn(LED2);
+ }
+ }
+ if (PS3.getButtonClick(LEFT)) {
+ Serial.print(F("\r\nLeft"));
+ if (PS3.PS3Connected) {
+ PS3.setLedOff();
+ PS3.setLedOn(LED3);
+ }
+ }
+
+ if (PS3.getButtonClick(L1))
+ Serial.print(F("\r\nL1"));
+ if (PS3.getButtonClick(L3))
+ Serial.print(F("\r\nL3"));
+ if (PS3.getButtonClick(R1))
+ Serial.print(F("\r\nR1"));
+ if (PS3.getButtonClick(R3))
+ Serial.print(F("\r\nR3"));
+
+ if (PS3.getButtonClick(SELECT)) {
+ Serial.print(F("\r\nSelect - "));
+ PS3.printStatusString();
+ }
+ if (PS3.getButtonClick(START)) {
+ Serial.print(F("\r\nStart"));
+ printAngle = !printAngle;
+ }
+ }
+#if 0 // Set this to 1 in order to see the angle of the controller
+ if (printAngle) {
+ Serial.print(F("\r\nPitch: "));
+ Serial.print(PS3.getAngle(Pitch));
+ Serial.print(F("\tRoll: "));
+ Serial.print(PS3.getAngle(Roll));
+ }
+#endif
+ }
+#if 0 // Set this to 1 in order to enable support for the Playstation Move controller
+ else if (PS3.PS3MoveConnected) {
+ if (PS3.getAnalogButton(T)) {
+ Serial.print(F("\r\nT: "));
+ Serial.print(PS3.getAnalogButton(T));
+ }
+ if (PS3.getButtonClick(PS)) {
+ Serial.print(F("\r\nPS"));
+ PS3.disconnect();
+ }
+ else {
+ if (PS3.getButtonClick(SELECT)) {
+ Serial.print(F("\r\nSelect"));
+ printTemperature = !printTemperature;
+ }
+ if (PS3.getButtonClick(START)) {
+ Serial.print(F("\r\nStart"));
+ printAngle = !printAngle;
+ }
+ if (PS3.getButtonClick(TRIANGLE)) {
+ Serial.print(F("\r\nTriangle"));
+ PS3.moveSetBulb(Red);
+ }
+ if (PS3.getButtonClick(CIRCLE)) {
+ Serial.print(F("\r\nCircle"));
+ PS3.moveSetBulb(Green);
+ }
+ if (PS3.getButtonClick(SQUARE)) {
+ Serial.print(F("\r\nSquare"));
+ PS3.moveSetBulb(Blue);
+ }
+ if (PS3.getButtonClick(CROSS)) {
+ Serial.print(F("\r\nCross"));
+ PS3.moveSetBulb(Yellow);
+ }
+ if (PS3.getButtonClick(MOVE)) {
+ PS3.moveSetBulb(Off);
+ Serial.print(F("\r\nMove"));
+ Serial.print(F(" - "));
+ PS3.printStatusString();
+ }
+ }
+ if (printAngle) {
+ Serial.print(F("\r\nPitch: "));
+ Serial.print(PS3.getAngle(Pitch));
+ Serial.print(F("\tRoll: "));
+ Serial.print(PS3.getAngle(Roll));
+ }
+ else if (printTemperature) {
+ Serial.print(F("\r\nTemperature: "));
+ Serial.print(PS3.getTemperature());
+ }
+ }
+#endif
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS3Multi/PS3Multi.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS3Multi/PS3Multi.ino
new file mode 100644
index 000000000..5ebfd7819
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS3Multi/PS3Multi.ino
@@ -0,0 +1,149 @@
+/*
+ Example sketch for the PS3 Bluetooth library - developed by Kristian Lauszus
+ This example show how one can use multiple controllers with the library
+ For more information visit my blog: http://blog.tkjelectronics.dk/ or
+ send me an e-mail: kristianl@tkjelectronics.com
+ */
+
+#include <PS3BT.h>
+#include <usbhub.h>
+
+// Satisfy the IDE, which needs to see the include statment in the ino too.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+USB Usb;
+//USBHub Hub1(&Usb); // Some dongles have a hub inside
+
+BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so
+PS3BT *PS3[2]; // We will use this pointer to store the two instance, you can easily make it larger if you like, but it will use a lot of RAM!
+const uint8_t length = sizeof(PS3) / sizeof(PS3[0]); // Get the lenght of the array
+bool printAngle[length];
+bool oldControllerState[length];
+
+void setup() {
+ for (uint8_t i = 0; i < length; i++) {
+ PS3[i] = new PS3BT(&Btd); // Create the instances
+ PS3[i]->attachOnInit(onInit); // onInit() is called upon a new connection - you can call the function whatever you like
+ }
+
+ Serial.begin(115200);
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ if (Usb.Init() == -1) {
+ Serial.print(F("\r\nOSC did not start"));
+ while (1); //halt
+ }
+ Serial.print(F("\r\nPS3 Bluetooth Library Started"));
+}
+void loop() {
+ Usb.Task();
+
+ for (uint8_t i = 0; i < length; i++) {
+ if (PS3[i]->PS3Connected || PS3[i]->PS3NavigationConnected) {
+ if (PS3[i]->getAnalogHat(LeftHatX) > 137 || PS3[i]->getAnalogHat(LeftHatX) < 117 || PS3[i]->getAnalogHat(LeftHatY) > 137 || PS3[i]->getAnalogHat(LeftHatY) < 117 || PS3[i]->getAnalogHat(RightHatX) > 137 || PS3[i]->getAnalogHat(RightHatX) < 117 || PS3[i]->getAnalogHat(RightHatY) > 137 || PS3[i]->getAnalogHat(RightHatY) < 117) {
+ Serial.print(F("\r\nLeftHatX: "));
+ Serial.print(PS3[i]->getAnalogHat(LeftHatX));
+ Serial.print(F("\tLeftHatY: "));
+ Serial.print(PS3[i]->getAnalogHat(LeftHatY));
+ if (PS3[i]->PS3Connected) { // The Navigation controller only have one joystick
+ Serial.print(F("\tRightHatX: "));
+ Serial.print(PS3[i]->getAnalogHat(RightHatX));
+ Serial.print(F("\tRightHatY: "));
+ Serial.print(PS3[i]->getAnalogHat(RightHatY));
+ }
+ }
+ //Analog button values can be read from almost all buttons
+ if (PS3[i]->getAnalogButton(L2) || PS3[i]->getAnalogButton(R2)) {
+ Serial.print(F("\r\nL2: "));
+ Serial.print(PS3[i]->getAnalogButton(L2));
+ if (PS3[i]->PS3Connected) {
+ Serial.print(F("\tR2: "));
+ Serial.print(PS3[i]->getAnalogButton(R2));
+ }
+ }
+ if (PS3[i]->getButtonClick(PS)) {
+ Serial.print(F("\r\nPS"));
+ PS3[i]->disconnect();
+ oldControllerState[i] = false; // Reset value
+ }
+ else {
+ if (PS3[i]->getButtonClick(TRIANGLE))
+ Serial.print(F("\r\nTraingle"));
+ if (PS3[i]->getButtonClick(CIRCLE))
+ Serial.print(F("\r\nCircle"));
+ if (PS3[i]->getButtonClick(CROSS))
+ Serial.print(F("\r\nCross"));
+ if (PS3[i]->getButtonClick(SQUARE))
+ Serial.print(F("\r\nSquare"));
+
+ if (PS3[i]->getButtonClick(UP)) {
+ Serial.print(F("\r\nUp"));
+ if (PS3[i]->PS3Connected) {
+ PS3[i]->setLedOff();
+ PS3[i]->setLedOn(LED4);
+ }
+ }
+ if (PS3[i]->getButtonClick(RIGHT)) {
+ Serial.print(F("\r\nRight"));
+ if (PS3[i]->PS3Connected) {
+ PS3[i]->setLedOff();
+ PS3[i]->setLedOn(LED1);
+ }
+ }
+ if (PS3[i]->getButtonClick(DOWN)) {
+ Serial.print(F("\r\nDown"));
+ if (PS3[i]->PS3Connected) {
+ PS3[i]->setLedOff();
+ PS3[i]->setLedOn(LED2);
+ }
+ }
+ if (PS3[i]->getButtonClick(LEFT)) {
+ Serial.print(F("\r\nLeft"));
+ if (PS3[i]->PS3Connected) {
+ PS3[i]->setLedOff();
+ PS3[i]->setLedOn(LED3);
+ }
+ }
+
+ if (PS3[i]->getButtonClick(L1))
+ Serial.print(F("\r\nL1"));
+ if (PS3[i]->getButtonClick(L3))
+ Serial.print(F("\r\nL3"));
+ if (PS3[i]->getButtonClick(R1))
+ Serial.print(F("\r\nR1"));
+ if (PS3[i]->getButtonClick(R3))
+ Serial.print(F("\r\nR3"));
+
+ if (PS3[i]->getButtonClick(SELECT)) {
+ Serial.print(F("\r\nSelect - "));
+ PS3[i]->printStatusString();
+ }
+ if (PS3[i]->getButtonClick(START)) {
+ Serial.print(F("\r\nStart"));
+ printAngle[i] = !printAngle[i];
+ }
+ }
+ if (printAngle[i]) {
+ Serial.print(F("\r\nPitch: "));
+ Serial.print(PS3[i]->getAngle(Pitch));
+ Serial.print(F("\tRoll: "));
+ Serial.print(PS3[i]->getAngle(Roll));
+ }
+ }
+ /* I have removed the PS3 Move code as an Uno will run out of RAM if it's included */
+ //else if(PS3[i]->PS3MoveConnected) {
+ }
+}
+
+void onInit() {
+ for (uint8_t i = 0; i < length; i++) {
+ if ((PS3[i]->PS3Connected || PS3[i]->PS3NavigationConnected) && !oldControllerState[i]) {
+ oldControllerState[i] = true; // Used to check which is the new controller
+ PS3[i]->setLedOn((LEDEnum)(i + 1)); // Cast directly to LEDEnum - see: "controllerEnums.h"
+ }
+ }
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS3SPP/PS3SPP.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS3SPP/PS3SPP.ino
new file mode 100644
index 000000000..8f234cbd8
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS3SPP/PS3SPP.ino
@@ -0,0 +1,162 @@
+/*
+ Example sketch for the Bluetooth library - developed by Kristian Lauszus
+ For more information visit my blog: http://blog.tkjelectronics.dk/ or
+ send me an e-mail: kristianl@tkjelectronics.com
+
+ This example show how one can combine all the difference Bluetooth services in one single code.
+ Note:
+ You will need a Arduino Mega 1280/2560 to run this sketch,
+ as a normal Arduino (Uno, Duemilanove etc.) doesn't have enough SRAM and FLASH
+ */
+
+#include <PS3BT.h>
+#include <SPP.h>
+#include <usbhub.h>
+
+// Satisfy the IDE, which needs to see the include statment in the ino too.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+USB Usb;
+//USBHub Hub1(&Usb); // Some dongles have a hub inside
+
+BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so
+
+/* You can create the instances of the bluetooth services in two ways */
+SPP SerialBT(&Btd); // This will set the name to the defaults: "Arduino" and the pin to "0000"
+//SPP SerialBTBT(&Btd,"Lauszus's Arduino","0000"); // You can also set the name and pin like so
+PS3BT PS3(&Btd); // This will just create the instance
+//PS3BT PS3(&Btd, 0x00, 0x15, 0x83, 0x3D, 0x0A, 0x57); // This will also store the bluetooth address - this can be obtained from the dongle when running the sketch
+
+bool firstMessage = true;
+String output = ""; // We will store the data in this string
+
+void setup() {
+ Serial.begin(115200); // This wil lprint the debugging from the libraries
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ if (Usb.Init() == -1) {
+ Serial.print(F("\r\nOSC did not start"));
+ while (1); //halt
+ }
+ Serial.print(F("\r\nBluetooth Library Started"));
+ output.reserve(200); // Reserve 200 bytes for the output string
+}
+void loop() {
+ Usb.Task(); // The SPP data is actually not send until this is called, one could call SerialBT.send() directly as well
+
+ if (SerialBT.connected) {
+ if (firstMessage) {
+ firstMessage = false;
+ SerialBT.println(F("Hello from Arduino")); // Send welcome message
+ }
+ if (Serial.available())
+ SerialBT.write(Serial.read());
+ if (SerialBT.available())
+ Serial.write(SerialBT.read());
+ }
+ else
+ firstMessage = true;
+
+ if (PS3.PS3Connected || PS3.PS3NavigationConnected) {
+ output = ""; // Reset output string
+ if (PS3.getAnalogHat(LeftHatX) > 137 || PS3.getAnalogHat(LeftHatX) < 117 || PS3.getAnalogHat(LeftHatY) > 137 || PS3.getAnalogHat(LeftHatY) < 117 || PS3.getAnalogHat(RightHatX) > 137 || PS3.getAnalogHat(RightHatX) < 117 || PS3.getAnalogHat(RightHatY) > 137 || PS3.getAnalogHat(RightHatY) < 117) {
+ output += "LeftHatX: ";
+ output += PS3.getAnalogHat(LeftHatX);
+ output += "\tLeftHatY: ";
+ output += PS3.getAnalogHat(LeftHatY);
+ if (PS3.PS3Connected) { // The Navigation controller only have one joystick
+ output += "\tRightHatX: ";
+ output += PS3.getAnalogHat(RightHatX);
+ output += "\tRightHatY: ";
+ output += PS3.getAnalogHat(RightHatY);
+ }
+ }
+ //Analog button values can be read from almost all buttons
+ if (PS3.getAnalogButton(L2) || PS3.getAnalogButton(R2)) {
+ if (output != "")
+ output += "\r\n";
+ output += "L2: ";
+ output += PS3.getAnalogButton(L2);
+ if (PS3.PS3Connected) {
+ output += "\tR2: ";
+ output += PS3.getAnalogButton(R2);
+ }
+ }
+ if (output != "") {
+ Serial.println(output);
+ if (SerialBT.connected)
+ SerialBT.println(output);
+ output = ""; // Reset output string
+ }
+ if (PS3.getButtonClick(PS)) {
+ output += " - PS";
+ PS3.disconnect();
+ }
+ else {
+ if (PS3.getButtonClick(TRIANGLE))
+ output += " - Traingle";
+ if (PS3.getButtonClick(CIRCLE))
+ output += " - Circle";
+ if (PS3.getButtonClick(CROSS))
+ output += " - Cross";
+ if (PS3.getButtonClick(SQUARE))
+ output += " - Square";
+
+ if (PS3.getButtonClick(UP)) {
+ output += " - Up";
+ if (PS3.PS3Connected) {
+ PS3.setLedOff();
+ PS3.setLedOn(LED4);
+ }
+ }
+ if (PS3.getButtonClick(RIGHT)) {
+ output += " - Right";
+ if (PS3.PS3Connected) {
+ PS3.setLedOff();
+ PS3.setLedOn(LED1);
+ }
+ }
+ if (PS3.getButtonClick(DOWN)) {
+ output += " - Down";
+ if (PS3.PS3Connected) {
+ PS3.setLedOff();
+ PS3.setLedOn(LED2);
+ }
+ }
+ if (PS3.getButtonClick(LEFT)) {
+ output += " - Left";
+ if (PS3.PS3Connected) {
+ PS3.setLedOff();
+ PS3.setLedOn(LED3);
+ }
+ }
+
+ if (PS3.getButtonClick(L1))
+ output += " - L1";
+ if (PS3.getButtonClick(L3))
+ output += " - L3";
+ if (PS3.getButtonClick(R1))
+ output += " - R1";
+ if (PS3.getButtonClick(R3))
+ output += " - R3";
+
+ if (PS3.getButtonClick(SELECT)) {
+ output += " - Select";
+ }
+ if (PS3.getButtonClick(START))
+ output += " - Start";
+
+ if (output != "") {
+ String string = "PS3 Controller" + output;
+ Serial.println(string);
+ if (SerialBT.connected)
+ SerialBT.println(string);
+ }
+ }
+ delay(10);
+ }
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS4BT/PS4BT.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS4BT/PS4BT.ino
new file mode 100644
index 000000000..c3ba696bd
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/PS4BT/PS4BT.ino
@@ -0,0 +1,146 @@
+/*
+ Example sketch for the PS4 Bluetooth library - developed by Kristian Lauszus
+ For more information visit my blog: http://blog.tkjelectronics.dk/ or
+ send me an e-mail: kristianl@tkjelectronics.com
+ */
+
+#include <PS4BT.h>
+#include <usbhub.h>
+
+// Satisfy the IDE, which needs to see the include statment in the ino too.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+USB Usb;
+//USBHub Hub1(&Usb); // Some dongles have a hub inside
+BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so
+
+/* You can create the instance of the PS4BT class in two ways */
+// This will start an inquiry and then pair with the PS4 controller - you only have to do this once
+// You will need to hold down the PS and Share button at the same time, the PS4 controller will then start to blink rapidly indicating that it is in paring mode
+PS4BT PS4(&Btd, PAIR);
+
+// After that you can simply create the instance like so and then press the PS button on the device
+//PS4BT PS4(&Btd);
+
+bool printAngle, printTouch;
+uint8_t oldL2Value, oldR2Value;
+
+void setup() {
+ Serial.begin(115200);
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ if (Usb.Init() == -1) {
+ Serial.print(F("\r\nOSC did not start"));
+ while (1); // Halt
+ }
+ Serial.print(F("\r\nPS4 Bluetooth Library Started"));
+}
+void loop() {
+ Usb.Task();
+
+ if (PS4.connected()) {
+ if (PS4.getAnalogHat(LeftHatX) > 137 || PS4.getAnalogHat(LeftHatX) < 117 || PS4.getAnalogHat(LeftHatY) > 137 || PS4.getAnalogHat(LeftHatY) < 117 || PS4.getAnalogHat(RightHatX) > 137 || PS4.getAnalogHat(RightHatX) < 117 || PS4.getAnalogHat(RightHatY) > 137 || PS4.getAnalogHat(RightHatY) < 117) {
+ Serial.print(F("\r\nLeftHatX: "));
+ Serial.print(PS4.getAnalogHat(LeftHatX));
+ Serial.print(F("\tLeftHatY: "));
+ Serial.print(PS4.getAnalogHat(LeftHatY));
+ Serial.print(F("\tRightHatX: "));
+ Serial.print(PS4.getAnalogHat(RightHatX));
+ Serial.print(F("\tRightHatY: "));
+ Serial.print(PS4.getAnalogHat(RightHatY));
+ }
+
+ if (PS4.getAnalogButton(L2) || PS4.getAnalogButton(R2)) { // These are the only analog buttons on the PS4 controller
+ Serial.print(F("\r\nL2: "));
+ Serial.print(PS4.getAnalogButton(L2));
+ Serial.print(F("\tR2: "));
+ Serial.print(PS4.getAnalogButton(R2));
+ }
+ if (PS4.getAnalogButton(L2) != oldL2Value || PS4.getAnalogButton(R2) != oldR2Value) // Only write value if it's different
+ PS4.setRumbleOn(PS4.getAnalogButton(L2), PS4.getAnalogButton(R2));
+ oldL2Value = PS4.getAnalogButton(L2);
+ oldR2Value = PS4.getAnalogButton(R2);
+
+ if (PS4.getButtonClick(PS)) {
+ Serial.print(F("\r\nPS"));
+ PS4.disconnect();
+ }
+ else {
+ if (PS4.getButtonClick(TRIANGLE)) {
+ Serial.print(F("\r\nTraingle"));
+ PS4.setRumbleOn(RumbleLow);
+ }
+ if (PS4.getButtonClick(CIRCLE)) {
+ Serial.print(F("\r\nCircle"));
+ PS4.setRumbleOn(RumbleHigh);
+ }
+ if (PS4.getButtonClick(CROSS)) {
+ Serial.print(F("\r\nCross"));
+ PS4.setLedFlash(10, 10); // Set it to blink rapidly
+ }
+ if (PS4.getButtonClick(SQUARE)) {
+ Serial.print(F("\r\nSquare"));
+ PS4.setLedFlash(0, 0); // Turn off blinking
+ }
+
+ if (PS4.getButtonClick(UP)) {
+ Serial.print(F("\r\nUp"));
+ PS4.setLed(Red);
+ } if (PS4.getButtonClick(RIGHT)) {
+ Serial.print(F("\r\nRight"));
+ PS4.setLed(Blue);
+ } if (PS4.getButtonClick(DOWN)) {
+ Serial.print(F("\r\nDown"));
+ PS4.setLed(Yellow);
+ } if (PS4.getButtonClick(LEFT)) {
+ Serial.print(F("\r\nLeft"));
+ PS4.setLed(Green);
+ }
+
+ if (PS4.getButtonClick(L1))
+ Serial.print(F("\r\nL1"));
+ if (PS4.getButtonClick(L3))
+ Serial.print(F("\r\nL3"));
+ if (PS4.getButtonClick(R1))
+ Serial.print(F("\r\nR1"));
+ if (PS4.getButtonClick(R3))
+ Serial.print(F("\r\nR3"));
+
+ if (PS4.getButtonClick(SHARE))
+ Serial.print(F("\r\nShare"));
+ if (PS4.getButtonClick(OPTIONS)) {
+ Serial.print(F("\r\nOptions"));
+ printAngle = !printAngle;
+ }
+ if (PS4.getButtonClick(TOUCHPAD)) {
+ Serial.print(F("\r\nTouchpad"));
+ printTouch = !printTouch;
+ }
+
+ if (printAngle) { // Print angle calculated using the accelerometer only
+ Serial.print(F("\r\nPitch: "));
+ Serial.print(PS4.getAngle(Pitch));
+ Serial.print(F("\tRoll: "));
+ Serial.print(PS4.getAngle(Roll));
+ }
+
+ if (printTouch) { // Print the x, y coordinates of the touchpad
+ if (PS4.isTouching(0) || PS4.isTouching(1)) // Print newline and carriage return if any of the fingers are touching the touchpad
+ Serial.print(F("\r\n"));
+ for (uint8_t i = 0; i < 2; i++) { // The touchpad track two fingers
+ if (PS4.isTouching(i)) { // Print the position of the finger if it is touching the touchpad
+ Serial.print(F("X")); Serial.print(i + 1); Serial.print(F(": "));
+ Serial.print(PS4.getX(i));
+ Serial.print(F("\tY")); Serial.print(i + 1); Serial.print(F(": "));
+ Serial.print(PS4.getY(i));
+ Serial.print(F("\t"));
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/SPP/SPP.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/SPP/SPP.ino
new file mode 100644
index 000000000..8fb9c4eca
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/SPP/SPP.ino
@@ -0,0 +1,52 @@
+/*
+ Example sketch for the RFCOMM/SPP Bluetooth library - developed by Kristian Lauszus
+ For more information visit my blog: http://blog.tkjelectronics.dk/ or
+ send me an e-mail: kristianl@tkjelectronics.com
+ */
+
+#include <SPP.h>
+#include <usbhub.h>
+
+// Satisfy the IDE, which needs to see the include statment in the ino too.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+USB Usb;
+//USBHub Hub1(&Usb); // Some dongles have a hub inside
+
+BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so
+/* You can create the instance of the class in two ways */
+SPP SerialBT(&Btd); // This will set the name to the defaults: "Arduino" and the pin to "0000"
+//SPP SerialBT(&Btd, "Lauszus's Arduino", "1234"); // You can also set the name and pin like so
+
+bool firstMessage = true;
+
+void setup() {
+ Serial.begin(115200);
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ if (Usb.Init() == -1) {
+ Serial.print(F("\r\nOSC did not start"));
+ while (1); //halt
+ }
+ Serial.print(F("\r\nSPP Bluetooth Library Started"));
+}
+void loop() {
+ Usb.Task(); // The SPP data is actually not send until this is called, one could call SerialBT.send() directly as well
+
+ if (SerialBT.connected) {
+ if (firstMessage) {
+ firstMessage = false;
+ SerialBT.println(F("Hello from Arduino")); // Send welcome message
+ }
+ if (Serial.available())
+ SerialBT.write(Serial.read());
+ if (SerialBT.available())
+ Serial.write(SerialBT.read());
+ }
+ else
+ firstMessage = true;
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/SPPMulti/SPPMulti.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/SPPMulti/SPPMulti.ino
new file mode 100644
index 000000000..df521d8e1
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/SPPMulti/SPPMulti.ino
@@ -0,0 +1,67 @@
+/*
+ Example sketch for the RFCOMM/SPP Bluetooth library - developed by Kristian Lauszus
+ For more information visit my blog: http://blog.tkjelectronics.dk/ or
+ send me an e-mail: kristianl@tkjelectronics.com
+ */
+
+#include <SPP.h>
+#include <usbhub.h>
+
+// Satisfy IDE, which only needs to see the include statment in the ino.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+USB Usb;
+//USBHub Hub1(&Usb); // Some dongles have a hub inside
+
+BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so
+
+const uint8_t length = 2; // Set the number of instances here
+SPP *SerialBT[length]; // We will use this pointer to store the instances, you can easily make it larger if you like, but it will use a lot of RAM!
+
+bool firstMessage[length] = { true }; // Set all to true
+
+void setup() {
+ for (uint8_t i = 0; i < length; i++)
+ SerialBT[i] = new SPP(&Btd); // This will set the name to the default: "Arduino" and the pin to "0000" for all connections
+
+ Serial.begin(115200);
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ if (Usb.Init() == -1) {
+ Serial.print(F("\r\nOSC did not start"));
+ while (1); // Halt
+ }
+ Serial.print(F("\r\nSPP Bluetooth Library Started"));
+}
+
+void loop() {
+ Usb.Task(); // The SPP data is actually not send until this is called, one could call SerialBT.send() directly as well
+
+ for (uint8_t i = 0; i < length; i++) {
+ if (SerialBT[i]->connected) {
+ if (firstMessage[i]) {
+ firstMessage[i] = false;
+ SerialBT[i]->println(F("Hello from Arduino")); // Send welcome message
+ }
+ if (SerialBT[i]->available())
+ Serial.write(SerialBT[i]->read());
+ }
+ else
+ firstMessage[i] = true;
+ }
+
+ // Set the connection you want to send to using the first character
+ // For instance "0Hello World" would send "Hello World" to connection 0
+ if (Serial.available()) {
+ delay(10); // Wait for the rest of the data to arrive
+ uint8_t id = Serial.read() - '0'; // Convert from ASCII
+ if (id < length && SerialBT[id]->connected) { // Make sure that the id is valid and make sure that a device is actually connected
+ while (Serial.available()) // Check if data is available
+ SerialBT[id]->write(Serial.read()); // Send the data
+ }
+ }
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/Wii/Wii.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/Wii/Wii.ino
new file mode 100644
index 000000000..b19356816
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/Wii/Wii.ino
@@ -0,0 +1,118 @@
+/*
+ Example sketch for the Wiimote Bluetooth library - developed by Kristian Lauszus
+ For more information visit my blog: http://blog.tkjelectronics.dk/ or
+ send me an e-mail: kristianl@tkjelectronics.com
+ */
+
+#include <Wii.h>
+#include <usbhub.h>
+
+// Satisfy the IDE, which needs to see the include statment in the ino too.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+USB Usb;
+//USBHub Hub1(&Usb); // Some dongles have a hub inside
+
+BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so
+/* You can create the instance of the class in two ways */
+WII Wii(&Btd, PAIR); // This will start an inquiry and then pair with your Wiimote - you only have to do this once
+//WII Wii(&Btd); // After that you can simply create the instance like so and then press any button on the Wiimote
+
+bool printAngle;
+
+void setup() {
+ Serial.begin(115200);
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ if (Usb.Init() == -1) {
+ Serial.print(F("\r\nOSC did not start"));
+ while (1); //halt
+ }
+ Serial.print(F("\r\nWiimote Bluetooth Library Started"));
+}
+void loop() {
+ Usb.Task();
+ if (Wii.wiimoteConnected) {
+ if (Wii.getButtonClick(HOME)) { // You can use getButtonPress to see if the button is held down
+ Serial.print(F("\r\nHOME"));
+ Wii.disconnect();
+ }
+ else {
+ if (Wii.getButtonClick(LEFT)) {
+ Wii.setLedOff();
+ Wii.setLedOn(LED1);
+ Serial.print(F("\r\nLeft"));
+ }
+ if (Wii.getButtonClick(RIGHT)) {
+ Wii.setLedOff();
+ Wii.setLedOn(LED3);
+ Serial.print(F("\r\nRight"));
+ }
+ if (Wii.getButtonClick(DOWN)) {
+ Wii.setLedOff();
+ Wii.setLedOn(LED4);
+ Serial.print(F("\r\nDown"));
+ }
+ if (Wii.getButtonClick(UP)) {
+ Wii.setLedOff();
+ Wii.setLedOn(LED2);
+ Serial.print(F("\r\nUp"));
+ }
+
+ if (Wii.getButtonClick(PLUS))
+ Serial.print(F("\r\nPlus"));
+ if (Wii.getButtonClick(MINUS))
+ Serial.print(F("\r\nMinus"));
+
+ if (Wii.getButtonClick(ONE))
+ Serial.print(F("\r\nOne"));
+ if (Wii.getButtonClick(TWO))
+ Serial.print(F("\r\nTwo"));
+
+ if (Wii.getButtonClick(A)) {
+ printAngle = !printAngle;
+ Serial.print(F("\r\nA"));
+ }
+ if (Wii.getButtonClick(B)) {
+ Wii.setRumbleToggle();
+ Serial.print(F("\r\nB"));
+ }
+ }
+#if 0 // Set this to 1 in order to see the angle of the controllers
+ if (printAngle) {
+ Serial.print(F("\r\nPitch: "));
+ Serial.print(Wii.getPitch());
+ Serial.print(F("\tRoll: "));
+ Serial.print(Wii.getRoll());
+ if (Wii.motionPlusConnected) {
+ Serial.print(F("\tYaw: "));
+ Serial.print(Wii.getYaw());
+ }
+ if (Wii.nunchuckConnected) {
+ Serial.print(F("\tNunchuck Pitch: "));
+ Serial.print(Wii.getNunchuckPitch());
+ Serial.print(F("\tNunchuck Roll: "));
+ Serial.print(Wii.getNunchuckRoll());
+ }
+ }
+#endif
+ }
+#if 0 // Set this to 1 if you are using a Nunchuck controller
+ if (Wii.nunchuckConnected) {
+ if (Wii.getButtonClick(Z))
+ Serial.print(F("\r\nZ"));
+ if (Wii.getButtonClick(C))
+ Serial.print(F("\r\nC"));
+ if (Wii.getAnalogHat(HatX) > 137 || Wii.getAnalogHat(HatX) < 117 || Wii.getAnalogHat(HatY) > 137 || Wii.getAnalogHat(HatY) < 117) {
+ Serial.print(F("\r\nHatX: "));
+ Serial.print(Wii.getAnalogHat(HatX));
+ Serial.print(F("\tHatY: "));
+ Serial.print(Wii.getAnalogHat(HatY));
+ }
+ }
+#endif
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiBalanceBoard/WiiBalanceBoard.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiBalanceBoard/WiiBalanceBoard.ino
new file mode 100644
index 000000000..18c5b411e
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiBalanceBoard/WiiBalanceBoard.ino
@@ -0,0 +1,51 @@
+/*
+ Example sketch for the Wii Balance Board Bluetooth library - developed by Kristian Lauszus
+ For more information visit my blog: http://blog.tkjelectronics.dk/ or
+ send me an e-mail: kristianl@tkjelectronics.com
+ */
+
+#include <Wii.h>
+#include <usbhub.h>
+
+// Satisfy the IDE, which needs to see the include statment in the ino too.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+USB Usb;
+//USBHub Hub1(&Usb); // Some dongles have a hub inside
+
+BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so
+/* You can create the instance of the class in two ways */
+WII Wii(&Btd, PAIR); // This will start an inquiry and then pair with your Wii Balance Board - you only have to do this once
+//WII Wii(&Btd); // After that you can simply create the instance like so and then press the power button on the Wii Balance Board
+
+void setup() {
+ Serial.begin(115200);
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ if (Usb.Init() == -1) {
+ Serial.print(F("\r\nOSC did not start"));
+ while (1); //halt
+ }
+ Serial.print(F("\r\nWii Balance Board Bluetooth Library Started"));
+}
+void loop() {
+ Usb.Task();
+ if (Wii.wiiBalanceBoardConnected) {
+ Serial.print(F("\r\nWeight: "));
+ for (uint8_t i = 0; i < 4; i++) {
+ Serial.print(Wii.getWeight((BalanceBoardEnum)i));
+ Serial.print(F("\t"));
+ }
+ Serial.print(F("Total Weight: "));
+ Serial.print(Wii.getTotalWeight());
+ if (Wii.getButtonClick(A)) {
+ Serial.print(F("\r\nA"));
+ //Wii.setLedToggle(LED1); // The Wii Balance Board has one LED as well
+ Wii.disconnect();
+ }
+ }
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiIRCamera/WiiIRCamera.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiIRCamera/WiiIRCamera.ino
new file mode 100644
index 000000000..573b8bd48
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiIRCamera/WiiIRCamera.ino
@@ -0,0 +1,133 @@
+/*
+Example sketch for the Wii libary showing the IR camera functionality. This example
+is for the Bluetooth Wii library developed for the USB shield from Circuits@Home
+
+Created by Allan Glover and Kristian Lauszus.
+Contact Kristian: http://blog.tkjelectronics.dk/ or send an email at kristianl@tkjelectronics.com.
+Contact Allan at adglover9.81@gmail.com
+
+To test the Wiimote IR camera, you will need access to an IR source. Sunlight will work but is not ideal.
+The simpleist solution is to use the Wii sensor bar, i.e. emitter bar, supplied by the Wii system.
+Otherwise, wire up a IR LED yourself.
+*/
+
+#include <Wii.h>
+#include <usbhub.h>
+
+// Satisfy the IDE, which needs to see the include statment in the ino too.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+#ifndef WIICAMERA // Used to check if WIICAMERA is defined
+#error "Please set ENABLE_WII_IR_CAMERA to 1 in settings.h"
+#endif
+
+USB Usb;
+//USBHub Hub1(&Usb); // Some dongles have a hub inside
+
+BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so
+/* You can create the instance of the class in two ways */
+WII Wii(&Btd, PAIR); // This will start an inquiry and then pair with your Wiimote - you only have to do this once
+//WII Wii(&Btd); // After the Wiimote pairs once with the line of code above, you can simply create the instance like so and re upload and then press any button on the Wiimote
+
+bool printAngle;
+uint8_t printObjects;
+
+void setup() {
+ Serial.begin(115200);
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ if (Usb.Init() == -1) {
+ Serial.print(F("\r\nOSC did not start"));
+ while (1); //halt
+ }
+ Serial.print(F("\r\nWiimote Bluetooth Library Started"));
+}
+
+void loop() {
+ Usb.Task();
+ if (Wii.wiimoteConnected) {
+ if (Wii.getButtonClick(HOME)) { // You can use getButtonPress to see if the button is held down
+ Serial.print(F("\r\nHOME"));
+ Wii.disconnect();
+ }
+ else {
+ if (Wii.getButtonClick(ONE))
+ Wii.IRinitialize(); // Run the initialisation sequence
+ if (Wii.getButtonClick(MINUS) || Wii.getButtonClick(PLUS)) {
+ if (!Wii.isIRCameraEnabled())
+ Serial.print(F("\r\nEnable IR camera first"));
+ else {
+ if (Wii.getButtonPress(MINUS)) { // getButtonClick will only return true once
+ if (printObjects > 0)
+ printObjects--;
+ }
+ else {
+ if (printObjects < 4)
+ printObjects++;
+ }
+ Serial.print(F("\r\nTracking "));
+ Serial.print(printObjects);
+ Serial.print(F(" objects"));
+ }
+ }
+ if (Wii.getButtonClick(A)) {
+ printAngle = !printAngle;
+ Serial.print(F("\r\nA"));
+ }
+ if (Wii.getButtonClick(B)) {
+ Serial.print(F("\r\nBattery level: "));
+ Serial.print(Wii.getBatteryLevel()); // You can get the battery level as well
+ }
+ }
+ if (printObjects > 0) {
+ if (Wii.getIRx1() != 0x3FF || Wii.getIRy1() != 0x3FF || Wii.getIRs1() != 0) { // Only print if the IR camera is actually seeing something
+ Serial.print(F("\r\nx1: "));
+ Serial.print(Wii.getIRx1());
+ Serial.print(F("\ty1: "));
+ Serial.print(Wii.getIRy1());
+ Serial.print(F("\ts1:"));
+ Serial.print(Wii.getIRs1());
+ }
+ if (printObjects > 1) {
+ if (Wii.getIRx2() != 0x3FF || Wii.getIRy2() != 0x3FF || Wii.getIRs2() != 0) {
+ Serial.print(F("\r\nx2: "));
+ Serial.print(Wii.getIRx2());
+ Serial.print(F("\ty2: "));
+ Serial.print(Wii.getIRy2());
+ Serial.print(F("\ts2:"));
+ Serial.print(Wii.getIRs2());
+ }
+ if (printObjects > 2) {
+ if (Wii.getIRx3() != 0x3FF || Wii.getIRy3() != 0x3FF || Wii.getIRs3() != 0) {
+ Serial.print(F("\r\nx3: "));
+ Serial.print(Wii.getIRx3());
+ Serial.print(F("\ty3: "));
+ Serial.print(Wii.getIRy3());
+ Serial.print(F("\ts3:"));
+ Serial.print(Wii.getIRs3());
+ }
+ if (printObjects > 3) {
+ if (Wii.getIRx4() != 0x3FF || Wii.getIRy4() != 0x3FF || Wii.getIRs4() != 0) {
+ Serial.print(F("\r\nx4: "));
+ Serial.print(Wii.getIRx4());
+ Serial.print(F("\ty4: "));
+ Serial.print(Wii.getIRy4());
+ Serial.print(F("\ts4:"));
+ Serial.print(Wii.getIRs4());
+ }
+ }
+ }
+ }
+ }
+ if (printAngle) { // There is no extension bytes available, so the MotionPlus or Nunchuck can't be read
+ Serial.print(F("\r\nPitch: "));
+ Serial.print(Wii.getPitch());
+ Serial.print(F("\tRoll: "));
+ Serial.print(Wii.getRoll());
+ }
+ }
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiMulti/WiiMulti.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiMulti/WiiMulti.ino
new file mode 100644
index 000000000..07c6f13d2
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiMulti/WiiMulti.ino
@@ -0,0 +1,132 @@
+/*
+ Example sketch for the Wiimote Bluetooth library - developed by Kristian Lauszus
+ This example show how one can use multiple controllers with the library
+ For more information visit my blog: http://blog.tkjelectronics.dk/ or
+ send me an e-mail: kristianl@tkjelectronics.com
+ */
+
+#include <Wii.h>
+#include <usbhub.h>
+
+// Satisfy the IDE, which needs to see the include statment in the ino too.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+USB Usb;
+//USBHub Hub1(&Usb); // Some dongles have a hub inside
+
+BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so
+WII *Wii[2]; // We will use this pointer to store the two instance, you can easily make it larger if you like, but it will use a lot of RAM!
+const uint8_t length = sizeof(Wii) / sizeof(Wii[0]); // Get the lenght of the array
+bool printAngle[length];
+bool oldControllerState[length];
+
+void setup() {
+ for (uint8_t i = 0; i < length; i++) {
+ Wii[i] = new WII(&Btd); // You will have to pair each controller with the dongle before you can define the instances like so, just add PAIR as the second argument
+ Wii[i]->attachOnInit(onInit); // onInit() is called upon a new connection - you can call the function whatever you like
+ }
+
+ Serial.begin(115200);
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ if (Usb.Init() == -1) {
+ Serial.print(F("\r\nOSC did not start"));
+ while (1); //halt
+ }
+ Serial.print(F("\r\nWiimote Bluetooth Library Started"));
+}
+void loop() {
+ Usb.Task();
+
+ for (uint8_t i = 0; i < length; i++) {
+ if (Wii[i]->wiimoteConnected) {
+ if (Wii[i]->getButtonClick(HOME)) { // You can use getButtonPress to see if the button is held down
+ Serial.print(F("\r\nHOME"));
+ Wii[i]->disconnect();
+ oldControllerState[i] = false; // Reset value
+ }
+ else {
+ if (Wii[i]->getButtonClick(LEFT)) {
+ Wii[i]->setLedOff();
+ Wii[i]->setLedOn(LED1);
+ Serial.print(F("\r\nLeft"));
+ }
+ if (Wii[i]->getButtonClick(RIGHT)) {
+ Wii[i]->setLedOff();
+ Wii[i]->setLedOn(LED3);
+ Serial.print(F("\r\nRight"));
+ }
+ if (Wii[i]->getButtonClick(DOWN)) {
+ Wii[i]->setLedOff();
+ Wii[i]->setLedOn(LED4);
+ Serial.print(F("\r\nDown"));
+ }
+ if (Wii[i]->getButtonClick(UP)) {
+ Wii[i]->setLedOff();
+ Wii[i]->setLedOn(LED2);
+ Serial.print(F("\r\nUp"));
+ }
+
+ if (Wii[i]->getButtonClick(PLUS))
+ Serial.print(F("\r\nPlus"));
+ if (Wii[i]->getButtonClick(MINUS))
+ Serial.print(F("\r\nMinus"));
+
+ if (Wii[i]->getButtonClick(ONE))
+ Serial.print(F("\r\nOne"));
+ if (Wii[i]->getButtonClick(TWO))
+ Serial.print(F("\r\nTwo"));
+
+ if (Wii[i]->getButtonClick(A)) {
+ printAngle[i] = !printAngle[i];
+ Serial.print(F("\r\nA"));
+ }
+ if (Wii[i]->getButtonClick(B)) {
+ Wii[i]->setRumbleToggle();
+ Serial.print(F("\r\nB"));
+ }
+ }
+ if (printAngle[i]) {
+ Serial.print(F("\r\nPitch: "));
+ Serial.print(Wii[i]->getPitch());
+ Serial.print(F("\tRoll: "));
+ Serial.print(Wii[i]->getRoll());
+ if (Wii[i]->motionPlusConnected) {
+ Serial.print(F("\tYaw: "));
+ Serial.print(Wii[i]->getYaw());
+ }
+ if (Wii[i]->nunchuckConnected) {
+ Serial.print(F("\tNunchuck Pitch: "));
+ Serial.print(Wii[i]->getNunchuckPitch());
+ Serial.print(F("\tNunchuck Roll: "));
+ Serial.print(Wii[i]->getNunchuckRoll());
+ }
+ }
+ }
+ if (Wii[i]->nunchuckConnected) {
+ if (Wii[i]->getButtonClick(Z))
+ Serial.print(F("\r\nZ"));
+ if (Wii[i]->getButtonClick(C))
+ Serial.print(F("\r\nC"));
+ if (Wii[i]->getAnalogHat(HatX) > 137 || Wii[i]->getAnalogHat(HatX) < 117 || Wii[i]->getAnalogHat(HatY) > 137 || Wii[i]->getAnalogHat(HatY) < 117) {
+ Serial.print(F("\r\nHatX: "));
+ Serial.print(Wii[i]->getAnalogHat(HatX));
+ Serial.print(F("\tHatY: "));
+ Serial.print(Wii[i]->getAnalogHat(HatY));
+ }
+ }
+ }
+}
+
+void onInit() {
+ for (uint8_t i = 0; i < length; i++) {
+ if (Wii[i]->wiimoteConnected && !oldControllerState[i]) {
+ oldControllerState[i] = true; // Used to check which is the new controller
+ Wii[i]->setLedOn((LEDEnum)(i + 1)); // Cast directly to LEDEnum - see: "controllerEnums.h"
+ }
+ }
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiUProController/WiiUProController.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiUProController/WiiUProController.ino
new file mode 100644
index 000000000..ab35a2747
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Bluetooth/WiiUProController/WiiUProController.ino
@@ -0,0 +1,104 @@
+/*
+ Example sketch for the Wiimote Bluetooth library - developed by Kristian Lauszus
+ For more information visit my blog: http://blog.tkjelectronics.dk/ or
+ send me an e-mail: kristianl@tkjelectronics.com
+ */
+
+#include <Wii.h>
+#include <usbhub.h>
+
+// Satisfy the IDE, which needs to see the include statment in the ino too.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+USB Usb;
+//USBHub Hub1(&Usb); // Some dongles have a hub inside
+
+BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so
+/* You can create the instance of the class in two ways */
+WII Wii(&Btd, PAIR); // This will start an inquiry and then pair with your Wiimote - you only have to do this once
+//WII Wii(&Btd); // After that you can simply create the instance like so and then press any button on the Wiimote
+
+void setup() {
+ Serial.begin(115200);
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ if (Usb.Init() == -1) {
+ Serial.print(F("\r\nOSC did not start"));
+ while (1); //halt
+ }
+ Serial.print(F("\r\nWiimote Bluetooth Library Started"));
+}
+void loop() {
+ Usb.Task();
+ if (Wii.wiiUProControllerConnected) {
+ if (Wii.getButtonClick(HOME)) { // You can use getButtonPress to see if the button is held down
+ Serial.print(F("\r\nHome"));
+ Wii.disconnect();
+ }
+ else {
+ if (Wii.getButtonClick(LEFT)) {
+ Wii.setLedOff();
+ Wii.setLedOn(LED1);
+ Serial.print(F("\r\nLeft"));
+ }
+ if (Wii.getButtonClick(RIGHT)) {
+ Wii.setLedOff();
+ Wii.setLedOn(LED3);
+ Serial.print(F("\r\nRight"));
+ }
+ if (Wii.getButtonClick(DOWN)) {
+ Wii.setLedOff();
+ Wii.setLedOn(LED4);
+ Serial.print(F("\r\nDown"));
+ }
+ if (Wii.getButtonClick(UP)) {
+ Wii.setLedOff();
+ Wii.setLedOn(LED2);
+ Serial.print(F("\r\nUp"));
+ }
+
+ if (Wii.getButtonClick(PLUS))
+ Serial.print(F("\r\nPlus"));
+ if (Wii.getButtonClick(MINUS))
+ Serial.print(F("\r\nMinus"));
+
+ if (Wii.getButtonClick(A))
+ Serial.print(F("\r\nA"));
+ if (Wii.getButtonClick(B)) {
+ Wii.setRumbleToggle();
+ Serial.print(F("\r\nB"));
+ }
+ if (Wii.getButtonClick(X))
+ Serial.print(F("\r\nX"));
+ if (Wii.getButtonClick(Y))
+ Serial.print(F("\r\nY"));
+
+ if (Wii.getButtonClick(L))
+ Serial.print(F("\r\nL"));
+ if (Wii.getButtonClick(R))
+ Serial.print(F("\r\nR"));
+ if (Wii.getButtonClick(ZL))
+ Serial.print(F("\r\nZL"));
+ if (Wii.getButtonClick(ZR))
+ Serial.print(F("\r\nZR"));
+ if (Wii.getButtonClick(L3))
+ Serial.print(F("\r\nL3"));
+ if (Wii.getButtonClick(R3))
+ Serial.print(F("\r\nR3"));
+ }
+ if (Wii.getAnalogHat(LeftHatX) > 2200 || Wii.getAnalogHat(LeftHatX) < 1800 || Wii.getAnalogHat(LeftHatY) > 2200 || Wii.getAnalogHat(LeftHatY) < 1800 || Wii.getAnalogHat(RightHatX) > 2200 || Wii.getAnalogHat(RightHatX) < 1800 || Wii.getAnalogHat(RightHatY) > 2200 || Wii.getAnalogHat(RightHatY) < 1800) {
+ Serial.print(F("\r\nLeftHatX: "));
+ Serial.print(Wii.getAnalogHat(LeftHatX));
+ Serial.print(F("\tLeftHatY: "));
+ Serial.print(Wii.getAnalogHat(LeftHatY));
+ Serial.print(F("\tRightHatX: "));
+ Serial.print(Wii.getAnalogHat(RightHatX));
+ Serial.print(F("\tRightHatY: "));
+ Serial.print(Wii.getAnalogHat(RightHatY));
+ }
+ }
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDBootKbd/USBHIDBootKbd.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDBootKbd/USBHIDBootKbd.ino
new file mode 100644
index 000000000..48b33abfd
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDBootKbd/USBHIDBootKbd.ino
@@ -0,0 +1,129 @@
+#include <hidboot.h>
+#include <usbhub.h>
+
+// Satisfy the IDE, which needs to see the include statment in the ino too.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+class KbdRptParser : public KeyboardReportParser
+{
+ void PrintKey(uint8_t mod, uint8_t key);
+
+ protected:
+ void OnControlKeysChanged(uint8_t before, uint8_t after);
+
+ void OnKeyDown (uint8_t mod, uint8_t key);
+ void OnKeyUp (uint8_t mod, uint8_t key);
+ void OnKeyPressed(uint8_t key);
+};
+
+void KbdRptParser::PrintKey(uint8_t m, uint8_t key)
+{
+ MODIFIERKEYS mod;
+ *((uint8_t*)&mod) = m;
+ Serial.print((mod.bmLeftCtrl == 1) ? "C" : " ");
+ Serial.print((mod.bmLeftShift == 1) ? "S" : " ");
+ Serial.print((mod.bmLeftAlt == 1) ? "A" : " ");
+ Serial.print((mod.bmLeftGUI == 1) ? "G" : " ");
+
+ Serial.print(" >");
+ PrintHex<uint8_t>(key, 0x80);
+ Serial.print("< ");
+
+ Serial.print((mod.bmRightCtrl == 1) ? "C" : " ");
+ Serial.print((mod.bmRightShift == 1) ? "S" : " ");
+ Serial.print((mod.bmRightAlt == 1) ? "A" : " ");
+ Serial.println((mod.bmRightGUI == 1) ? "G" : " ");
+};
+
+void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key)
+{
+ Serial.print("DN ");
+ PrintKey(mod, key);
+ uint8_t c = OemToAscii(mod, key);
+
+ if (c)
+ OnKeyPressed(c);
+}
+
+void KbdRptParser::OnControlKeysChanged(uint8_t before, uint8_t after) {
+
+ MODIFIERKEYS beforeMod;
+ *((uint8_t*)&beforeMod) = before;
+
+ MODIFIERKEYS afterMod;
+ *((uint8_t*)&afterMod) = after;
+
+ if (beforeMod.bmLeftCtrl != afterMod.bmLeftCtrl) {
+ Serial.println("LeftCtrl changed");
+ }
+ if (beforeMod.bmLeftShift != afterMod.bmLeftShift) {
+ Serial.println("LeftShift changed");
+ }
+ if (beforeMod.bmLeftAlt != afterMod.bmLeftAlt) {
+ Serial.println("LeftAlt changed");
+ }
+ if (beforeMod.bmLeftGUI != afterMod.bmLeftGUI) {
+ Serial.println("LeftGUI changed");
+ }
+
+ if (beforeMod.bmRightCtrl != afterMod.bmRightCtrl) {
+ Serial.println("RightCtrl changed");
+ }
+ if (beforeMod.bmRightShift != afterMod.bmRightShift) {
+ Serial.println("RightShift changed");
+ }
+ if (beforeMod.bmRightAlt != afterMod.bmRightAlt) {
+ Serial.println("RightAlt changed");
+ }
+ if (beforeMod.bmRightGUI != afterMod.bmRightGUI) {
+ Serial.println("RightGUI changed");
+ }
+
+}
+
+void KbdRptParser::OnKeyUp(uint8_t mod, uint8_t key)
+{
+ Serial.print("UP ");
+ PrintKey(mod, key);
+}
+
+void KbdRptParser::OnKeyPressed(uint8_t key)
+{
+ Serial.print("ASCII: ");
+ Serial.println((char)key);
+};
+
+USB Usb;
+//USBHub Hub(&Usb);
+HIDBoot<HID_PROTOCOL_KEYBOARD> HidKeyboard(&Usb);
+
+uint32_t next_time;
+
+KbdRptParser Prs;
+
+void setup()
+{
+ Serial.begin( 115200 );
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ Serial.println("Start");
+
+ if (Usb.Init() == -1)
+ Serial.println("OSC did not start.");
+
+ delay( 200 );
+
+ next_time = millis() + 5000;
+
+ HidKeyboard.SetReportParser(0, (HIDReportParser*)&Prs);
+}
+
+void loop()
+{
+ Usb.Task();
+}
+
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDBootKbdAndMouse/USBHIDBootKbdAndMouse.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDBootKbdAndMouse/USBHIDBootKbdAndMouse.ino
new file mode 100644
index 000000000..5fc8c96fc
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDBootKbdAndMouse/USBHIDBootKbdAndMouse.ino
@@ -0,0 +1,178 @@
+#include <hidboot.h>
+#include <usbhub.h>
+
+// Satisfy IDE, which only needs to see the include statment in the ino.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+class MouseRptParser : public MouseReportParser
+{
+ protected:
+ void OnMouseMove(MOUSEINFO *mi);
+ void OnLeftButtonUp(MOUSEINFO *mi);
+ void OnLeftButtonDown(MOUSEINFO *mi);
+ void OnRightButtonUp(MOUSEINFO *mi);
+ void OnRightButtonDown(MOUSEINFO *mi);
+ void OnMiddleButtonUp(MOUSEINFO *mi);
+ void OnMiddleButtonDown(MOUSEINFO *mi);
+};
+void MouseRptParser::OnMouseMove(MOUSEINFO *mi)
+{
+ Serial.print("dx=");
+ Serial.print(mi->dX, DEC);
+ Serial.print(" dy=");
+ Serial.println(mi->dY, DEC);
+};
+void MouseRptParser::OnLeftButtonUp (MOUSEINFO *mi)
+{
+ Serial.println("L Butt Up");
+};
+void MouseRptParser::OnLeftButtonDown (MOUSEINFO *mi)
+{
+ Serial.println("L Butt Dn");
+};
+void MouseRptParser::OnRightButtonUp (MOUSEINFO *mi)
+{
+ Serial.println("R Butt Up");
+};
+void MouseRptParser::OnRightButtonDown (MOUSEINFO *mi)
+{
+ Serial.println("R Butt Dn");
+};
+void MouseRptParser::OnMiddleButtonUp (MOUSEINFO *mi)
+{
+ Serial.println("M Butt Up");
+};
+void MouseRptParser::OnMiddleButtonDown (MOUSEINFO *mi)
+{
+ Serial.println("M Butt Dn");
+};
+
+class KbdRptParser : public KeyboardReportParser
+{
+ void PrintKey(uint8_t mod, uint8_t key);
+
+ protected:
+ void OnControlKeysChanged(uint8_t before, uint8_t after);
+ void OnKeyDown (uint8_t mod, uint8_t key);
+ void OnKeyUp (uint8_t mod, uint8_t key);
+ void OnKeyPressed(uint8_t key);
+};
+
+void KbdRptParser::PrintKey(uint8_t m, uint8_t key)
+{
+ MODIFIERKEYS mod;
+ *((uint8_t*)&mod) = m;
+ Serial.print((mod.bmLeftCtrl == 1) ? "C" : " ");
+ Serial.print((mod.bmLeftShift == 1) ? "S" : " ");
+ Serial.print((mod.bmLeftAlt == 1) ? "A" : " ");
+ Serial.print((mod.bmLeftGUI == 1) ? "G" : " ");
+
+ Serial.print(" >");
+ PrintHex<uint8_t>(key, 0x80);
+ Serial.print("< ");
+
+ Serial.print((mod.bmRightCtrl == 1) ? "C" : " ");
+ Serial.print((mod.bmRightShift == 1) ? "S" : " ");
+ Serial.print((mod.bmRightAlt == 1) ? "A" : " ");
+ Serial.println((mod.bmRightGUI == 1) ? "G" : " ");
+};
+
+void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key)
+{
+ Serial.print("DN ");
+ PrintKey(mod, key);
+ uint8_t c = OemToAscii(mod, key);
+
+ if (c)
+ OnKeyPressed(c);
+}
+
+void KbdRptParser::OnControlKeysChanged(uint8_t before, uint8_t after) {
+
+ MODIFIERKEYS beforeMod;
+ *((uint8_t*)&beforeMod) = before;
+
+ MODIFIERKEYS afterMod;
+ *((uint8_t*)&afterMod) = after;
+
+ if (beforeMod.bmLeftCtrl != afterMod.bmLeftCtrl) {
+ Serial.println("LeftCtrl changed");
+ }
+ if (beforeMod.bmLeftShift != afterMod.bmLeftShift) {
+ Serial.println("LeftShift changed");
+ }
+ if (beforeMod.bmLeftAlt != afterMod.bmLeftAlt) {
+ Serial.println("LeftAlt changed");
+ }
+ if (beforeMod.bmLeftGUI != afterMod.bmLeftGUI) {
+ Serial.println("LeftGUI changed");
+ }
+
+ if (beforeMod.bmRightCtrl != afterMod.bmRightCtrl) {
+ Serial.println("RightCtrl changed");
+ }
+ if (beforeMod.bmRightShift != afterMod.bmRightShift) {
+ Serial.println("RightShift changed");
+ }
+ if (beforeMod.bmRightAlt != afterMod.bmRightAlt) {
+ Serial.println("RightAlt changed");
+ }
+ if (beforeMod.bmRightGUI != afterMod.bmRightGUI) {
+ Serial.println("RightGUI changed");
+ }
+
+}
+
+void KbdRptParser::OnKeyUp(uint8_t mod, uint8_t key)
+{
+ Serial.print("UP ");
+ PrintKey(mod, key);
+}
+
+void KbdRptParser::OnKeyPressed(uint8_t key)
+{
+ Serial.print("ASCII: ");
+ Serial.println((char)key);
+};
+
+USB Usb;
+USBHub Hub(&Usb);
+
+HIDBoot < HID_PROTOCOL_KEYBOARD | HID_PROTOCOL_MOUSE > HidComposite(&Usb);
+HIDBoot<HID_PROTOCOL_KEYBOARD> HidKeyboard(&Usb);
+HIDBoot<HID_PROTOCOL_MOUSE> HidMouse(&Usb);
+
+//uint32_t next_time;
+
+KbdRptParser KbdPrs;
+MouseRptParser MousePrs;
+
+void setup()
+{
+ Serial.begin( 115200 );
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ Serial.println("Start");
+
+ if (Usb.Init() == -1)
+ Serial.println("OSC did not start.");
+
+ delay( 200 );
+
+ //next_time = millis() + 5000;
+
+ HidComposite.SetReportParser(0, (HIDReportParser*)&KbdPrs);
+ HidComposite.SetReportParser(1, (HIDReportParser*)&MousePrs);
+ HidKeyboard.SetReportParser(0, (HIDReportParser*)&KbdPrs);
+ HidMouse.SetReportParser(0, (HIDReportParser*)&MousePrs);
+}
+
+void loop()
+{
+ Usb.Task();
+}
+
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDBootMouse/USBHIDBootMouse.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDBootMouse/USBHIDBootMouse.ino
new file mode 100644
index 000000000..53102512b
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDBootMouse/USBHIDBootMouse.ino
@@ -0,0 +1,83 @@
+#include <hidboot.h>
+#include <usbhub.h>
+
+// Satisfy the IDE, which needs to see the include statment in the ino too.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+class MouseRptParser : public MouseReportParser
+{
+protected:
+ void OnMouseMove (MOUSEINFO *mi);
+ void OnLeftButtonUp (MOUSEINFO *mi);
+ void OnLeftButtonDown (MOUSEINFO *mi);
+ void OnRightButtonUp (MOUSEINFO *mi);
+ void OnRightButtonDown (MOUSEINFO *mi);
+ void OnMiddleButtonUp (MOUSEINFO *mi);
+ void OnMiddleButtonDown (MOUSEINFO *mi);
+};
+void MouseRptParser::OnMouseMove(MOUSEINFO *mi)
+{
+ Serial.print("dx=");
+ Serial.print(mi->dX, DEC);
+ Serial.print(" dy=");
+ Serial.println(mi->dY, DEC);
+};
+void MouseRptParser::OnLeftButtonUp (MOUSEINFO *mi)
+{
+ Serial.println("L Butt Up");
+};
+void MouseRptParser::OnLeftButtonDown (MOUSEINFO *mi)
+{
+ Serial.println("L Butt Dn");
+};
+void MouseRptParser::OnRightButtonUp (MOUSEINFO *mi)
+{
+ Serial.println("R Butt Up");
+};
+void MouseRptParser::OnRightButtonDown (MOUSEINFO *mi)
+{
+ Serial.println("R Butt Dn");
+};
+void MouseRptParser::OnMiddleButtonUp (MOUSEINFO *mi)
+{
+ Serial.println("M Butt Up");
+};
+void MouseRptParser::OnMiddleButtonDown (MOUSEINFO *mi)
+{
+ Serial.println("M Butt Dn");
+};
+
+USB Usb;
+USBHub Hub(&Usb);
+HIDBoot<HID_PROTOCOL_MOUSE> HidMouse(&Usb);
+
+uint32_t next_time;
+
+MouseRptParser Prs;
+
+void setup()
+{
+ Serial.begin( 115200 );
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ Serial.println("Start");
+
+ if (Usb.Init() == -1)
+ Serial.println("OSC did not start.");
+
+ delay( 200 );
+
+ next_time = millis() + 5000;
+
+ HidMouse.SetReportParser(0,(HIDReportParser*)&Prs);
+}
+
+void loop()
+{
+ Usb.Task();
+}
+
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/USBHIDJoystick.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/USBHIDJoystick.ino
new file mode 100644
index 000000000..956441d67
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/USBHIDJoystick.ino
@@ -0,0 +1,38 @@
+#include <hid.h>
+#include <hiduniversal.h>
+#include <usbhub.h>
+
+// Satisfy IDE, which only needs to see the include statment in the ino.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+#include "hidjoystickrptparser.h"
+
+USB Usb;
+USBHub Hub(&Usb);
+HIDUniversal Hid(&Usb);
+JoystickEvents JoyEvents;
+JoystickReportParser Joy(&JoyEvents);
+
+void setup() {
+ Serial.begin(115200);
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ Serial.println("Start");
+
+ if (Usb.Init() == -1)
+ Serial.println("OSC did not start.");
+
+ delay(200);
+
+ if (!Hid.SetReportParser(0, &Joy))
+ ErrorMessage<uint8_t > (PSTR("SetReportParser"), 1);
+}
+
+void loop() {
+ Usb.Task();
+}
+
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/hidjoystickrptparser.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/hidjoystickrptparser.cpp
new file mode 100644
index 000000000..083b95cac
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/hidjoystickrptparser.cpp
@@ -0,0 +1,84 @@
+#include "hidjoystickrptparser.h"
+
+JoystickReportParser::JoystickReportParser(JoystickEvents *evt) :
+joyEvents(evt),
+oldHat(0xDE),
+oldButtons(0) {
+ for (uint8_t i = 0; i < RPT_GEMEPAD_LEN; i++)
+ oldPad[i] = 0xD;
+}
+
+void JoystickReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
+ bool match = true;
+
+ // Checking if there are changes in report since the method was last called
+ for (uint8_t i = 0; i < RPT_GEMEPAD_LEN; i++)
+ if (buf[i] != oldPad[i]) {
+ match = false;
+ break;
+ }
+
+ // Calling Game Pad event handler
+ if (!match && joyEvents) {
+ joyEvents->OnGamePadChanged((const GamePadEventData*)buf);
+
+ for (uint8_t i = 0; i < RPT_GEMEPAD_LEN; i++) oldPad[i] = buf[i];
+ }
+
+ uint8_t hat = (buf[5] & 0xF);
+
+ // Calling Hat Switch event handler
+ if (hat != oldHat && joyEvents) {
+ joyEvents->OnHatSwitch(hat);
+ oldHat = hat;
+ }
+
+ uint16_t buttons = (0x0000 | buf[6]);
+ buttons <<= 4;
+ buttons |= (buf[5] >> 4);
+ uint16_t changes = (buttons ^ oldButtons);
+
+ // Calling Button Event Handler for every button changed
+ if (changes) {
+ for (uint8_t i = 0; i < 0x0C; i++) {
+ uint16_t mask = (0x0001 << i);
+
+ if (((mask & changes) > 0) && joyEvents)
+ if ((buttons & mask) > 0)
+ joyEvents->OnButtonDn(i + 1);
+ else
+ joyEvents->OnButtonUp(i + 1);
+ }
+ oldButtons = buttons;
+ }
+}
+
+void JoystickEvents::OnGamePadChanged(const GamePadEventData *evt) {
+ Serial.print("X1: ");
+ PrintHex<uint8_t > (evt->X, 0x80);
+ Serial.print("\tY1: ");
+ PrintHex<uint8_t > (evt->Y, 0x80);
+ Serial.print("\tX2: ");
+ PrintHex<uint8_t > (evt->Z1, 0x80);
+ Serial.print("\tY2: ");
+ PrintHex<uint8_t > (evt->Z2, 0x80);
+ Serial.print("\tRz: ");
+ PrintHex<uint8_t > (evt->Rz, 0x80);
+ Serial.println("");
+}
+
+void JoystickEvents::OnHatSwitch(uint8_t hat) {
+ Serial.print("Hat Switch: ");
+ PrintHex<uint8_t > (hat, 0x80);
+ Serial.println("");
+}
+
+void JoystickEvents::OnButtonUp(uint8_t but_id) {
+ Serial.print("Up: ");
+ Serial.println(but_id, DEC);
+}
+
+void JoystickEvents::OnButtonDn(uint8_t but_id) {
+ Serial.print("Dn: ");
+ Serial.println(but_id, DEC);
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/hidjoystickrptparser.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/hidjoystickrptparser.h
new file mode 100644
index 000000000..733b8f8da
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHIDJoystick/hidjoystickrptparser.h
@@ -0,0 +1,33 @@
+#if !defined(__HIDJOYSTICKRPTPARSER_H__)
+#define __HIDJOYSTICKRPTPARSER_H__
+
+#include <hid.h>
+
+struct GamePadEventData {
+ uint8_t X, Y, Z1, Z2, Rz;
+};
+
+class JoystickEvents {
+public:
+ virtual void OnGamePadChanged(const GamePadEventData *evt);
+ virtual void OnHatSwitch(uint8_t hat);
+ virtual void OnButtonUp(uint8_t but_id);
+ virtual void OnButtonDn(uint8_t but_id);
+};
+
+#define RPT_GEMEPAD_LEN 5
+
+class JoystickReportParser : public HIDReportParser {
+ JoystickEvents *joyEvents;
+
+ uint8_t oldPad[RPT_GEMEPAD_LEN];
+ uint8_t oldHat;
+ uint16_t oldButtons;
+
+public:
+ JoystickReportParser(JoystickEvents *evt);
+
+ virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
+};
+
+#endif // __HIDJOYSTICKRPTPARSER_H__
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHID_desc/USBHID_desc.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHID_desc/USBHID_desc.ino
new file mode 100644
index 000000000..85cfc19a2
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHID_desc/USBHID_desc.ino
@@ -0,0 +1,77 @@
+#include <hid.h>
+#include <hiduniversal.h>
+#include <hidescriptorparser.h>
+#include <usbhub.h>
+#include "pgmstrings.h"
+
+// Satisfy the IDE, which needs to see the include statment in the ino too.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+class HIDUniversal2 : public HIDUniversal
+{
+public:
+ HIDUniversal2(USB *usb) : HIDUniversal(usb) {};
+
+protected:
+ uint8_t OnInitSuccessful();
+};
+
+uint8_t HIDUniversal2::OnInitSuccessful()
+{
+ uint8_t rcode;
+
+ HexDumper<USBReadParser, uint16_t, uint16_t> Hex;
+ ReportDescParser Rpt;
+
+ if ((rcode = GetReportDescr(0, &Hex)))
+ goto FailGetReportDescr1;
+
+ if ((rcode = GetReportDescr(0, &Rpt)))
+ goto FailGetReportDescr2;
+
+ return 0;
+
+FailGetReportDescr1:
+ USBTRACE("GetReportDescr1:");
+ goto Fail;
+
+FailGetReportDescr2:
+ USBTRACE("GetReportDescr2:");
+ goto Fail;
+
+Fail:
+ Serial.println(rcode, HEX);
+ Release();
+ return rcode;
+}
+
+USB Usb;
+//USBHub Hub(&Usb);
+HIDUniversal2 Hid(&Usb);
+UniversalReportParser Uni;
+
+void setup()
+{
+ Serial.begin( 115200 );
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ Serial.println("Start");
+
+ if (Usb.Init() == -1)
+ Serial.println("OSC did not start.");
+
+ delay( 200 );
+
+ if (!Hid.SetReportParser(0, &Uni))
+ ErrorMessage<uint8_t>(PSTR("SetReportParser"), 1 );
+}
+
+void loop()
+{
+ Usb.Task();
+}
+
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHID_desc/pgmstrings.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHID_desc/pgmstrings.h
new file mode 100644
index 000000000..bdb0077ec
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/USBHID_desc/pgmstrings.h
@@ -0,0 +1,52 @@
+#if !defined(__PGMSTRINGS_H__)
+#define __PGMSTRINGS_H__
+
+#define LOBYTE(x) ((char*)(&(x)))[0]
+#define HIBYTE(x) ((char*)(&(x)))[1]
+#define BUFSIZE 256 //buffer size
+
+
+/* Print strings in Program Memory */
+const char Gen_Error_str[] PROGMEM = "\r\nRequest error. Error code:\t";
+const char Dev_Header_str[] PROGMEM ="\r\nDevice descriptor: ";
+const char Dev_Length_str[] PROGMEM ="\r\nDescriptor Length:\t";
+const char Dev_Type_str[] PROGMEM ="\r\nDescriptor type:\t";
+const char Dev_Version_str[] PROGMEM ="\r\nUSB version:\t\t";
+const char Dev_Class_str[] PROGMEM ="\r\nDevice class:\t\t";
+const char Dev_Subclass_str[] PROGMEM ="\r\nDevice Subclass:\t";
+const char Dev_Protocol_str[] PROGMEM ="\r\nDevice Protocol:\t";
+const char Dev_Pktsize_str[] PROGMEM ="\r\nMax.packet size:\t";
+const char Dev_Vendor_str[] PROGMEM ="\r\nVendor ID:\t\t";
+const char Dev_Product_str[] PROGMEM ="\r\nProduct ID:\t\t";
+const char Dev_Revision_str[] PROGMEM ="\r\nRevision ID:\t\t";
+const char Dev_Mfg_str[] PROGMEM ="\r\nMfg.string index:\t";
+const char Dev_Prod_str[] PROGMEM ="\r\nProd.string index:\t";
+const char Dev_Serial_str[] PROGMEM ="\r\nSerial number index:\t";
+const char Dev_Nconf_str[] PROGMEM ="\r\nNumber of conf.:\t";
+const char Conf_Trunc_str[] PROGMEM ="Total length truncated to 256 bytes";
+const char Conf_Header_str[] PROGMEM ="\r\nConfiguration descriptor:";
+const char Conf_Totlen_str[] PROGMEM ="\r\nTotal length:\t\t";
+const char Conf_Nint_str[] PROGMEM ="\r\nNum.intf:\t\t";
+const char Conf_Value_str[] PROGMEM ="\r\nConf.value:\t\t";
+const char Conf_String_str[] PROGMEM ="\r\nConf.string:\t\t";
+const char Conf_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t";
+const char Conf_Pwr_str[] PROGMEM ="\r\nMax.pwr:\t\t";
+const char Int_Header_str[] PROGMEM ="\r\n\r\nInterface descriptor:";
+const char Int_Number_str[] PROGMEM ="\r\nIntf.number:\t\t";
+const char Int_Alt_str[] PROGMEM ="\r\nAlt.:\t\t\t";
+const char Int_Endpoints_str[] PROGMEM ="\r\nEndpoints:\t\t";
+const char Int_Class_str[] PROGMEM ="\r\nIntf. Class:\t\t";
+const char Int_Subclass_str[] PROGMEM ="\r\nIntf. Subclass:\t\t";
+const char Int_Protocol_str[] PROGMEM ="\r\nIntf. Protocol:\t\t";
+const char Int_String_str[] PROGMEM ="\r\nIntf.string:\t\t";
+const char End_Header_str[] PROGMEM ="\r\n\r\nEndpoint descriptor:";
+const char End_Address_str[] PROGMEM ="\r\nEndpoint address:\t";
+const char End_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t";
+const char End_Pktsize_str[] PROGMEM ="\r\nMax.pkt size:\t\t";
+const char End_Interval_str[] PROGMEM ="\r\nPolling interval:\t";
+const char Unk_Header_str[] PROGMEM = "\r\nUnknown descriptor:";
+const char Unk_Length_str[] PROGMEM ="\r\nLength:\t\t";
+const char Unk_Type_str[] PROGMEM ="\r\nType:\t\t";
+const char Unk_Contents_str[] PROGMEM ="\r\nContents:\t";
+
+#endif // __PGMSTRINGS_H__ \ No newline at end of file
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp.ino
new file mode 100644
index 000000000..837d7f5a7
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp.ino
@@ -0,0 +1,42 @@
+/* Simplified Logitech Extreme 3D Pro Joystick Report Parser */
+
+#include <hid.h>
+#include <hiduniversal.h>
+#include <usbhub.h>
+
+#include "le3dp_rptparser.h"
+
+// Satisfy the IDE, which needs to see the include statment in the ino too.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+USB Usb;
+USBHub Hub(&Usb);
+HIDUniversal Hid(&Usb);
+JoystickEvents JoyEvents;
+JoystickReportParser Joy(&JoyEvents);
+
+void setup()
+{
+ Serial.begin( 115200 );
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ Serial.println("Start");
+
+ if (Usb.Init() == -1)
+ Serial.println("OSC did not start.");
+
+ delay( 200 );
+
+ if (!Hid.SetReportParser(0, &Joy))
+ ErrorMessage<uint8_t>(PSTR("SetReportParser"), 1 );
+}
+
+void loop()
+{
+ Usb.Task();
+}
+
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp_rptparser.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp_rptparser.cpp
new file mode 100644
index 000000000..baece13b2
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp_rptparser.cpp
@@ -0,0 +1,43 @@
+#include "le3dp_rptparser.h"
+
+JoystickReportParser::JoystickReportParser(JoystickEvents *evt) :
+ joyEvents(evt)
+{}
+
+void JoystickReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf)
+{
+ bool match = true;
+
+ // Checking if there are changes in report since the method was last called
+ for (uint8_t i=0; i<RPT_GAMEPAD_LEN; i++) {
+ if( buf[i] != oldPad[i] ) {
+ match = false;
+ break;
+ }
+ }
+ // Calling Game Pad event handler
+ if (!match && joyEvents) {
+ joyEvents->OnGamePadChanged((const GamePadEventData*)buf);
+
+ for (uint8_t i=0; i<RPT_GAMEPAD_LEN; i++) oldPad[i] = buf[i];
+ }
+}
+
+void JoystickEvents::OnGamePadChanged(const GamePadEventData *evt)
+{
+ Serial.print("X: ");
+ PrintHex<uint16_t>(evt->x, 0x80);
+ Serial.print(" Y: ");
+ PrintHex<uint16_t>(evt->y, 0x80);
+ Serial.print(" Hat Switch: ");
+ PrintHex<uint8_t>(evt->hat, 0x80);
+ Serial.print(" Twist: ");
+ PrintHex<uint8_t>(evt->twist, 0x80);
+ Serial.print(" Slider: ");
+ PrintHex<uint8_t>(evt->slider, 0x80);
+ Serial.print(" Buttons A: ");
+ PrintHex<uint8_t>(evt->buttons_a, 0x80);
+ Serial.print(" Buttons B: ");
+ PrintHex<uint8_t>(evt->buttons_b, 0x80);
+ Serial.println("");
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp_rptparser.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp_rptparser.h
new file mode 100644
index 000000000..2400364e6
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/le3dp/le3dp_rptparser.h
@@ -0,0 +1,42 @@
+#if !defined(__HIDJOYSTICKRPTPARSER_H__)
+#define __HIDJOYSTICKRPTPARSER_H__
+
+#include <hid.h>
+
+struct GamePadEventData
+{
+ union { //axes and hut switch
+ uint32_t axes;
+ struct {
+ uint32_t x : 10;
+ uint32_t y : 10;
+ uint32_t hat : 4;
+ uint32_t twist : 8;
+ };
+ };
+ uint8_t buttons_a;
+ uint8_t slider;
+ uint8_t buttons_b;
+};
+
+class JoystickEvents
+{
+public:
+ virtual void OnGamePadChanged(const GamePadEventData *evt);
+};
+
+#define RPT_GAMEPAD_LEN sizeof(GamePadEventData)/sizeof(uint8_t)
+
+class JoystickReportParser : public HIDReportParser
+{
+ JoystickEvents *joyEvents;
+
+ uint8_t oldPad[RPT_GAMEPAD_LEN];
+
+public:
+ JoystickReportParser(JoystickEvents *evt);
+
+ virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
+};
+
+#endif // __HIDJOYSTICKRPTPARSER_H__
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/scale/scale.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/scale/scale.ino
new file mode 100644
index 000000000..f26ff964d
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/scale/scale.ino
@@ -0,0 +1,51 @@
+/* Digital Scale Output. Written for Stamps.com Model 510 */
+/* 5lb Digital Scale; any HID scale with Usage page 0x8d should work */
+
+#include <hid.h>
+#include <hiduniversal.h>
+#include <usbhub.h>
+
+#include "scale_rptparser.h"
+
+// Satisfy the IDE, which needs to see the include statment in the ino too.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+USB Usb;
+USBHub Hub(&Usb);
+HIDUniversal Hid(&Usb);
+Max_LCD LCD(&Usb);
+ScaleEvents ScaleEvents(&LCD);
+ScaleReportParser Scale(&ScaleEvents);
+
+void setup()
+{
+ Serial.begin( 115200 );
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ Serial.println("Start");
+
+ if (Usb.Init() == -1)
+ Serial.println("OSC did not start.");
+
+ // set up the LCD's number of rows and columns:
+ LCD.begin(16, 2);
+ LCD.clear();
+ LCD.home();
+ LCD.setCursor(0,0);
+ LCD.write('R');
+
+ delay( 200 );
+
+ if (!Hid.SetReportParser(0, &Scale))
+ ErrorMessage<uint8_t>(PSTR("SetReportParser"), 1 );
+}
+
+void loop()
+{
+ Usb.Task();
+}
+
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/scale/scale_rptparser.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/scale/scale_rptparser.cpp
new file mode 100644
index 000000000..01ed980cf
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/scale/scale_rptparser.cpp
@@ -0,0 +1,150 @@
+/* Parser for standard HID scale (usage page 0x8d) data input report (ID 3) */
+#include "scale_rptparser.h"
+
+const char* UNITS[13] = {
+ "units", // unknown unit
+ "mg", // milligram
+ "g", // gram
+ "kg", // kilogram
+ "cd", // carat
+ "taels", // lian
+ "gr", // grain
+ "dwt", // pennyweight
+ "tonnes", // metric tons
+ "tons", // avoir ton
+ "ozt", // troy ounce
+ "oz", // ounce
+ "lbs" // pound
+};
+
+ScaleReportParser::ScaleReportParser(ScaleEvents *evt) :
+ scaleEvents(evt)
+{}
+
+void ScaleReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf)
+{
+ bool match = true;
+
+ // Checking if there are changes in report since the method was last called
+ for (uint8_t i=0; i<RPT_SCALE_LEN; i++) {
+ if( buf[i] != oldScale[i] ) {
+ match = false;
+ break;
+ }
+ }
+ // Calling Game Pad event handler
+ if (!match && scaleEvents) {
+ scaleEvents->OnScaleChanged((const ScaleEventData*)buf);
+
+ for (uint8_t i=0; i<RPT_SCALE_LEN; i++) oldScale[i] = buf[i];
+ }
+}
+
+ScaleEvents::ScaleEvents( Max_LCD* pLCD ) :
+
+ pLcd( pLCD )
+
+{}
+
+void ScaleEvents::LcdPrint( const char* str )
+{
+
+ while( *str ) {
+
+ pLcd->write( *str++ );
+
+ }
+}
+
+void ScaleEvents::OnScaleChanged(const ScaleEventData *evt)
+{
+
+ pLcd->clear();
+ pLcd->home();
+ pLcd->setCursor(0,0);
+
+ if( evt->reportID != 3 ) {
+
+ const char inv_report[]="Invalid report!";
+
+ Serial.println(inv_report);
+ LcdPrint(inv_report);
+
+ return;
+
+ }//if( evt->reportID != 3...
+
+ switch( evt->status ) {
+
+ case REPORT_FAULT:
+ Serial.println(F("Report fault"));
+ break;
+
+ case ZEROED:
+ Serial.println(F("Scale zero set"));
+ break;
+
+ case WEIGHING: {
+
+ const char progress[] = "Weighing...";
+ Serial.println(progress);
+ LcdPrint(progress);
+ break;
+ }
+
+ case WEIGHT_VALID: {
+
+ char buf[10];
+ double weight = evt->weight * pow( 10, evt->exp );
+
+
+
+ Serial.print(F("Weight: "));
+ Serial.print( weight );
+ Serial.print(F(" "));
+ Serial.println( UNITS[ evt->unit ]);
+
+ LcdPrint("Weight: ");
+ dtostrf( weight, 4, 2, buf );
+ LcdPrint( buf );
+ LcdPrint( UNITS[ evt->unit ]);
+
+ break;
+
+ }//case WEIGHT_VALID...
+
+ case WEIGHT_NEGATIVE: {
+
+ const char negweight[] = "Negative weight";
+ Serial.println(negweight);
+ LcdPrint(negweight);
+ break;
+ }
+
+ case OVERWEIGHT: {
+
+ const char overweight[] = "Max.weight reached";
+ Serial.println(overweight);
+ LcdPrint( overweight );
+ break;
+ }
+
+ case CALIBRATE_ME:
+
+ Serial.println(F("Scale calibration required"));
+ break;
+
+ case ZERO_ME:
+
+ Serial.println(F("Scale zeroing required"));
+ break;
+
+ default:
+
+ Serial.print(F("Undefined status code: "));
+ Serial.println( evt->status );
+ break;
+
+ }//switch( evt->status...
+
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/scale/scale_rptparser.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/scale/scale_rptparser.h
new file mode 100644
index 000000000..57fbb033b
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/HID/scale/scale_rptparser.h
@@ -0,0 +1,55 @@
+#if !defined(__SCALERPTPARSER_H__)
+#define __SCALERPTPARSER_H__
+
+#include <max_LCD.h>
+#include <hid.h>
+
+/* Scale status constants */
+#define REPORT_FAULT 0x01
+#define ZEROED 0x02
+#define WEIGHING 0x03
+#define WEIGHT_VALID 0x04
+#define WEIGHT_NEGATIVE 0x05
+#define OVERWEIGHT 0x06
+#define CALIBRATE_ME 0x07
+#define ZERO_ME 0x08
+
+/* input data report */
+struct ScaleEventData
+{
+ uint8_t reportID; //must be 3
+ uint8_t status;
+ uint8_t unit;
+ int8_t exp; //scale factor for the weight
+ uint16_t weight; //
+};
+
+class ScaleEvents
+{
+
+ Max_LCD* pLcd;
+
+ void LcdPrint( const char* str );
+
+public:
+
+ ScaleEvents( Max_LCD* pLCD );
+
+ virtual void OnScaleChanged(const ScaleEventData *evt);
+};
+
+#define RPT_SCALE_LEN sizeof(ScaleEventData)/sizeof(uint8_t)
+
+class ScaleReportParser : public HIDReportParser
+{
+ ScaleEvents *scaleEvents;
+
+ uint8_t oldScale[RPT_SCALE_LEN];
+
+public:
+ ScaleReportParser(ScaleEvents *evt);
+
+ virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
+};
+
+#endif // __SCALERPTPARSER_H__
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/PS3USB/PS3USB.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/PS3USB/PS3USB.ino
new file mode 100644
index 000000000..a53dcfbe6
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/PS3USB/PS3USB.ino
@@ -0,0 +1,148 @@
+/*
+ Example sketch for the PS3 USB library - developed by Kristian Lauszus
+ For more information visit my blog: http://blog.tkjelectronics.dk/ or
+ send me an e-mail: kristianl@tkjelectronics.com
+ */
+
+#include <PS3USB.h>
+
+// Satisfy the IDE, which needs to see the include statment in the ino too.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+USB Usb;
+/* You can create the instance of the class in two ways */
+PS3USB PS3(&Usb); // This will just create the instance
+//PS3USB PS3(&Usb,0x00,0x15,0x83,0x3D,0x0A,0x57); // This will also store the bluetooth address - this can be obtained from the dongle when running the sketch
+
+bool printAngle;
+uint8_t state = 0;
+
+void setup() {
+ Serial.begin(115200);
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ if (Usb.Init() == -1) {
+ Serial.print(F("\r\nOSC did not start"));
+ while (1); //halt
+ }
+ Serial.print(F("\r\nPS3 USB Library Started"));
+}
+void loop() {
+ Usb.Task();
+
+ if (PS3.PS3Connected || PS3.PS3NavigationConnected) {
+ if (PS3.getAnalogHat(LeftHatX) > 137 || PS3.getAnalogHat(LeftHatX) < 117 || PS3.getAnalogHat(LeftHatY) > 137 || PS3.getAnalogHat(LeftHatY) < 117 || PS3.getAnalogHat(RightHatX) > 137 || PS3.getAnalogHat(RightHatX) < 117 || PS3.getAnalogHat(RightHatY) > 137 || PS3.getAnalogHat(RightHatY) < 117) {
+ Serial.print(F("\r\nLeftHatX: "));
+ Serial.print(PS3.getAnalogHat(LeftHatX));
+ Serial.print(F("\tLeftHatY: "));
+ Serial.print(PS3.getAnalogHat(LeftHatY));
+ if (PS3.PS3Connected) { // The Navigation controller only have one joystick
+ Serial.print(F("\tRightHatX: "));
+ Serial.print(PS3.getAnalogHat(RightHatX));
+ Serial.print(F("\tRightHatY: "));
+ Serial.print(PS3.getAnalogHat(RightHatY));
+ }
+ }
+ // Analog button values can be read from almost all buttons
+ if (PS3.getAnalogButton(L2) || PS3.getAnalogButton(R2)) {
+ Serial.print(F("\r\nL2: "));
+ Serial.print(PS3.getAnalogButton(L2));
+ if (!PS3.PS3NavigationConnected) {
+ Serial.print(F("\tR2: "));
+ Serial.print(PS3.getAnalogButton(R2));
+ }
+ }
+ if (PS3.getButtonClick(PS))
+ Serial.print(F("\r\nPS"));
+
+ if (PS3.getButtonClick(TRIANGLE))
+ Serial.print(F("\r\nTraingle"));
+ if (PS3.getButtonClick(CIRCLE))
+ Serial.print(F("\r\nCircle"));
+ if (PS3.getButtonClick(CROSS))
+ Serial.print(F("\r\nCross"));
+ if (PS3.getButtonClick(SQUARE))
+ Serial.print(F("\r\nSquare"));
+
+ if (PS3.getButtonClick(UP)) {
+ Serial.print(F("\r\nUp"));
+ PS3.setLedOff();
+ PS3.setLedOn(LED4);
+ }
+ if (PS3.getButtonClick(RIGHT)) {
+ Serial.print(F("\r\nRight"));
+ PS3.setLedOff();
+ PS3.setLedOn(LED1);
+ }
+ if (PS3.getButtonClick(DOWN)) {
+ Serial.print(F("\r\nDown"));
+ PS3.setLedOff();
+ PS3.setLedOn(LED2);
+ }
+ if (PS3.getButtonClick(LEFT)) {
+ Serial.print(F("\r\nLeft"));
+ PS3.setLedOff();
+ PS3.setLedOn(LED3);
+ }
+
+ if (PS3.getButtonClick(L1))
+ Serial.print(F("\r\nL1"));
+ if (PS3.getButtonClick(L3))
+ Serial.print(F("\r\nL3"));
+ if (PS3.getButtonClick(R1))
+ Serial.print(F("\r\nR1"));
+ if (PS3.getButtonClick(R3))
+ Serial.print(F("\r\nR3"));
+
+ if (PS3.getButtonClick(SELECT)) {
+ Serial.print(F("\r\nSelect - "));
+ PS3.printStatusString();
+ }
+ if (PS3.getButtonClick(START)) {
+ Serial.print(F("\r\nStart"));
+ printAngle = !printAngle;
+ }
+ if (printAngle) {
+ Serial.print(F("\r\nPitch: "));
+ Serial.print(PS3.getAngle(Pitch));
+ Serial.print(F("\tRoll: "));
+ Serial.print(PS3.getAngle(Roll));
+ }
+ }
+ else if (PS3.PS3MoveConnected) { // One can only set the color of the bulb, set the rumble, set and get the bluetooth address and calibrate the magnetometer via USB
+ if (state == 0) {
+ PS3.moveSetRumble(0);
+ PS3.moveSetBulb(Off);
+ } else if (state == 1) {
+ PS3.moveSetRumble(75);
+ PS3.moveSetBulb(Red);
+ } else if (state == 2) {
+ PS3.moveSetRumble(125);
+ PS3.moveSetBulb(Green);
+ } else if (state == 3) {
+ PS3.moveSetRumble(150);
+ PS3.moveSetBulb(Blue);
+ } else if (state == 4) {
+ PS3.moveSetRumble(175);
+ PS3.moveSetBulb(Yellow);
+ } else if (state == 5) {
+ PS3.moveSetRumble(200);
+ PS3.moveSetBulb(Lightblue);
+ } else if (state == 6) {
+ PS3.moveSetRumble(225);
+ PS3.moveSetBulb(Purble);
+ } else if (state == 7) {
+ PS3.moveSetRumble(250);
+ PS3.moveSetBulb(White);
+ }
+
+ state++;
+ if (state > 7)
+ state = 0;
+ delay(1000);
+ }
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/PS4USB/PS4USB.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/PS4USB/PS4USB.ino
new file mode 100644
index 000000000..d0d76790e
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/PS4USB/PS4USB.ino
@@ -0,0 +1,133 @@
+/*
+ Example sketch for the PS4 USB library - developed by Kristian Lauszus
+ For more information visit my blog: http://blog.tkjelectronics.dk/ or
+ send me an e-mail: kristianl@tkjelectronics.com
+ */
+
+#include <PS4USB.h>
+
+// Satisfy the IDE, which needs to see the include statment in the ino too.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+USB Usb;
+PS4USB PS4(&Usb);
+
+bool printAngle, printTouch;
+uint8_t oldL2Value, oldR2Value;
+
+void setup() {
+ Serial.begin(115200);
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ if (Usb.Init() == -1) {
+ Serial.print(F("\r\nOSC did not start"));
+ while (1); // Halt
+ }
+ Serial.print(F("\r\nPS4 USB Library Started"));
+}
+
+void loop() {
+ Usb.Task();
+
+ if (PS4.connected()) {
+ if (PS4.getAnalogHat(LeftHatX) > 137 || PS4.getAnalogHat(LeftHatX) < 117 || PS4.getAnalogHat(LeftHatY) > 137 || PS4.getAnalogHat(LeftHatY) < 117 || PS4.getAnalogHat(RightHatX) > 137 || PS4.getAnalogHat(RightHatX) < 117 || PS4.getAnalogHat(RightHatY) > 137 || PS4.getAnalogHat(RightHatY) < 117) {
+ Serial.print(F("\r\nLeftHatX: "));
+ Serial.print(PS4.getAnalogHat(LeftHatX));
+ Serial.print(F("\tLeftHatY: "));
+ Serial.print(PS4.getAnalogHat(LeftHatY));
+ Serial.print(F("\tRightHatX: "));
+ Serial.print(PS4.getAnalogHat(RightHatX));
+ Serial.print(F("\tRightHatY: "));
+ Serial.print(PS4.getAnalogHat(RightHatY));
+ }
+
+ if (PS4.getAnalogButton(L2) || PS4.getAnalogButton(R2)) { // These are the only analog buttons on the PS4 controller
+ Serial.print(F("\r\nL2: "));
+ Serial.print(PS4.getAnalogButton(L2));
+ Serial.print(F("\tR2: "));
+ Serial.print(PS4.getAnalogButton(R2));
+ }
+ if (PS4.getAnalogButton(L2) != oldL2Value || PS4.getAnalogButton(R2) != oldR2Value) // Only write value if it's different
+ PS4.setRumbleOn(PS4.getAnalogButton(L2), PS4.getAnalogButton(R2));
+ oldL2Value = PS4.getAnalogButton(L2);
+ oldR2Value = PS4.getAnalogButton(R2);
+
+ if (PS4.getButtonClick(PS))
+ Serial.print(F("\r\nPS"));
+ if (PS4.getButtonClick(TRIANGLE)) {
+ Serial.print(F("\r\nTraingle"));
+ PS4.setRumbleOn(RumbleLow);
+ }
+ if (PS4.getButtonClick(CIRCLE)) {
+ Serial.print(F("\r\nCircle"));
+ PS4.setRumbleOn(RumbleHigh);
+ }
+ if (PS4.getButtonClick(CROSS)) {
+ Serial.print(F("\r\nCross"));
+ PS4.setLedFlash(10, 10); // Set it to blink rapidly
+ }
+ if (PS4.getButtonClick(SQUARE)) {
+ Serial.print(F("\r\nSquare"));
+ PS4.setLedFlash(0, 0); // Turn off blinking
+ }
+
+ if (PS4.getButtonClick(UP)) {
+ Serial.print(F("\r\nUp"));
+ PS4.setLed(Red);
+ } if (PS4.getButtonClick(RIGHT)) {
+ Serial.print(F("\r\nRight"));
+ PS4.setLed(Blue);
+ } if (PS4.getButtonClick(DOWN)) {
+ Serial.print(F("\r\nDown"));
+ PS4.setLed(Yellow);
+ } if (PS4.getButtonClick(LEFT)) {
+ Serial.print(F("\r\nLeft"));
+ PS4.setLed(Green);
+ }
+
+ if (PS4.getButtonClick(L1))
+ Serial.print(F("\r\nL1"));
+ if (PS4.getButtonClick(L3))
+ Serial.print(F("\r\nL3"));
+ if (PS4.getButtonClick(R1))
+ Serial.print(F("\r\nR1"));
+ if (PS4.getButtonClick(R3))
+ Serial.print(F("\r\nR3"));
+
+ if (PS4.getButtonClick(SHARE))
+ Serial.print(F("\r\nShare"));
+ if (PS4.getButtonClick(OPTIONS)) {
+ Serial.print(F("\r\nOptions"));
+ printAngle = !printAngle;
+ }
+ if (PS4.getButtonClick(TOUCHPAD)) {
+ Serial.print(F("\r\nTouchpad"));
+ printTouch = !printTouch;
+ }
+
+ if (printAngle) { // Print angle calculated using the accelerometer only
+ Serial.print(F("\r\nPitch: "));
+ Serial.print(PS4.getAngle(Pitch));
+ Serial.print(F("\tRoll: "));
+ Serial.print(PS4.getAngle(Roll));
+ }
+
+ if (printTouch) { // Print the x, y coordinates of the touchpad
+ if (PS4.isTouching(0) || PS4.isTouching(1)) // Print newline and carriage return if any of the fingers are touching the touchpad
+ Serial.print(F("\r\n"));
+ for (uint8_t i = 0; i < 2; i++) { // The touchpad track two fingers
+ if (PS4.isTouching(i)) { // Print the position of the finger if it is touching the touchpad
+ Serial.print(F("X")); Serial.print(i + 1); Serial.print(F(": "));
+ Serial.print(PS4.getX(i));
+ Serial.print(F("\tY")); Serial.print(i + 1); Serial.print(F(": "));
+ Serial.print(PS4.getY(i));
+ Serial.print(F("\t"));
+ }
+ }
+ }
+ }
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/PSBuzz/PSBuzz.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/PSBuzz/PSBuzz.ino
new file mode 100644
index 000000000..6ee462c1e
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/PSBuzz/PSBuzz.ino
@@ -0,0 +1,49 @@
+/*
+ Example sketch for the Playstation Buzz library - developed by Kristian Lauszus
+ For more information visit my blog: http://blog.tkjelectronics.dk/ or
+ send me an e-mail: kristianl@tkjelectronics.com
+ */
+
+#include <PSBuzz.h>
+
+// Satisfy the IDE, which needs to see the include statment in the ino too.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+USB Usb;
+PSBuzz Buzz(&Usb);
+
+void setup() {
+ Serial.begin(115200);
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ if (Usb.Init() == -1) {
+ Serial.print(F("\r\nOSC did not start"));
+ while (1); // Halt
+ }
+ Serial.println(F("\r\nPS Buzz Library Started"));
+}
+
+void loop() {
+ Usb.Task();
+
+ if (Buzz.connected()) {
+ for (uint8_t i = 0; i < 4; i++) {
+ if (Buzz.getButtonClick(RED, i)) {
+ Buzz.setLedToggle(i); // Toggle the LED
+ Serial.println(F("RED"));
+ }
+ if (Buzz.getButtonClick(YELLOW, i))
+ Serial.println(F("YELLOW"));
+ if (Buzz.getButtonClick(GREEN, i))
+ Serial.println(F("GREEN"));
+ if (Buzz.getButtonClick(ORANGE, i))
+ Serial.println(F("ORANGE"));
+ if (Buzz.getButtonClick(BLUE, i))
+ Serial.println(F("BLUE"));
+ }
+ }
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/USB_desc/USB_desc.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/USB_desc/USB_desc.ino
new file mode 100644
index 000000000..acfe57d37
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/USB_desc/USB_desc.ino
@@ -0,0 +1,349 @@
+#include <usbhub.h>
+
+#include "pgmstrings.h"
+
+// Satisfy the IDE, which needs to see the include statment in the ino too.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+USB Usb;
+//USBHub Hub1(&Usb);
+//USBHub Hub2(&Usb);
+//USBHub Hub3(&Usb);
+//USBHub Hub4(&Usb);
+//USBHub Hub5(&Usb);
+//USBHub Hub6(&Usb);
+//USBHub Hub7(&Usb);
+
+uint32_t next_time;
+
+void PrintAllAddresses(UsbDevice *pdev)
+{
+ UsbDeviceAddress adr;
+ adr.devAddress = pdev->address.devAddress;
+ Serial.print("\r\nAddr:");
+ Serial.print(adr.devAddress, HEX);
+ Serial.print("(");
+ Serial.print(adr.bmHub, HEX);
+ Serial.print(".");
+ Serial.print(adr.bmParent, HEX);
+ Serial.print(".");
+ Serial.print(adr.bmAddress, HEX);
+ Serial.println(")");
+}
+
+void PrintAddress(uint8_t addr)
+{
+ UsbDeviceAddress adr;
+ adr.devAddress = addr;
+ Serial.print("\r\nADDR:\t");
+ Serial.println(adr.devAddress, HEX);
+ Serial.print("DEV:\t");
+ Serial.println(adr.bmAddress, HEX);
+ Serial.print("PRNT:\t");
+ Serial.println(adr.bmParent, HEX);
+ Serial.print("HUB:\t");
+ Serial.println(adr.bmHub, HEX);
+}
+
+void setup()
+{
+ Serial.begin( 115200 );
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ Serial.println("Start");
+
+ if (Usb.Init() == -1)
+ Serial.println("OSC did not start.");
+
+ delay( 200 );
+
+ next_time = millis() + 10000;
+}
+
+byte getdevdescr( byte addr, byte &num_conf );
+
+void PrintDescriptors(uint8_t addr)
+{
+ uint8_t rcode = 0;
+ byte num_conf = 0;
+
+ rcode = getdevdescr( (byte)addr, num_conf );
+ if ( rcode )
+ {
+ printProgStr(Gen_Error_str);
+ print_hex( rcode, 8 );
+ }
+ Serial.print("\r\n");
+
+ for (int i = 0; i < num_conf; i++)
+ {
+ rcode = getconfdescr( addr, i ); // get configuration descriptor
+ if ( rcode )
+ {
+ printProgStr(Gen_Error_str);
+ print_hex(rcode, 8);
+ }
+ Serial.println("\r\n");
+ }
+}
+
+void PrintAllDescriptors(UsbDevice *pdev)
+{
+ Serial.println("\r\n");
+ print_hex(pdev->address.devAddress, 8);
+ Serial.println("\r\n--");
+ PrintDescriptors( pdev->address.devAddress );
+}
+
+void loop()
+{
+ Usb.Task();
+
+ if ( Usb.getUsbTaskState() == USB_STATE_RUNNING )
+ {
+ //if (millis() >= next_time)
+ {
+ Usb.ForEachUsbDevice(&PrintAllDescriptors);
+ Usb.ForEachUsbDevice(&PrintAllAddresses);
+
+ while ( 1 ); //stop
+ }
+ }
+}
+
+byte getdevdescr( byte addr, byte &num_conf )
+{
+ USB_DEVICE_DESCRIPTOR buf;
+ byte rcode;
+ rcode = Usb.getDevDescr( addr, 0, 0x12, ( uint8_t *)&buf );
+ if ( rcode ) {
+ return ( rcode );
+ }
+ printProgStr(Dev_Header_str);
+ printProgStr(Dev_Length_str);
+ print_hex( buf.bLength, 8 );
+ printProgStr(Dev_Type_str);
+ print_hex( buf.bDescriptorType, 8 );
+ printProgStr(Dev_Version_str);
+ print_hex( buf.bcdUSB, 16 );
+ printProgStr(Dev_Class_str);
+ print_hex( buf.bDeviceClass, 8 );
+ printProgStr(Dev_Subclass_str);
+ print_hex( buf.bDeviceSubClass, 8 );
+ printProgStr(Dev_Protocol_str);
+ print_hex( buf.bDeviceProtocol, 8 );
+ printProgStr(Dev_Pktsize_str);
+ print_hex( buf.bMaxPacketSize0, 8 );
+ printProgStr(Dev_Vendor_str);
+ print_hex( buf.idVendor, 16 );
+ printProgStr(Dev_Product_str);
+ print_hex( buf.idProduct, 16 );
+ printProgStr(Dev_Revision_str);
+ print_hex( buf.bcdDevice, 16 );
+ printProgStr(Dev_Mfg_str);
+ print_hex( buf.iManufacturer, 8 );
+ printProgStr(Dev_Prod_str);
+ print_hex( buf.iProduct, 8 );
+ printProgStr(Dev_Serial_str);
+ print_hex( buf.iSerialNumber, 8 );
+ printProgStr(Dev_Nconf_str);
+ print_hex( buf.bNumConfigurations, 8 );
+ num_conf = buf.bNumConfigurations;
+ return ( 0 );
+}
+
+void printhubdescr(uint8_t *descrptr, uint8_t addr)
+{
+ HubDescriptor *pHub = (HubDescriptor*) descrptr;
+ uint8_t len = *((uint8_t*)descrptr);
+
+ printProgStr(PSTR("\r\n\r\nHub Descriptor:\r\n"));
+ printProgStr(PSTR("bDescLength:\t\t"));
+ Serial.println(pHub->bDescLength, HEX);
+
+ printProgStr(PSTR("bDescriptorType:\t"));
+ Serial.println(pHub->bDescriptorType, HEX);
+
+ printProgStr(PSTR("bNbrPorts:\t\t"));
+ Serial.println(pHub->bNbrPorts, HEX);
+
+ printProgStr(PSTR("LogPwrSwitchMode:\t"));
+ Serial.println(pHub->LogPwrSwitchMode, BIN);
+
+ printProgStr(PSTR("CompoundDevice:\t\t"));
+ Serial.println(pHub->CompoundDevice, BIN);
+
+ printProgStr(PSTR("OverCurrentProtectMode:\t"));
+ Serial.println(pHub->OverCurrentProtectMode, BIN);
+
+ printProgStr(PSTR("TTThinkTime:\t\t"));
+ Serial.println(pHub->TTThinkTime, BIN);
+
+ printProgStr(PSTR("PortIndicatorsSupported:"));
+ Serial.println(pHub->PortIndicatorsSupported, BIN);
+
+ printProgStr(PSTR("Reserved:\t\t"));
+ Serial.println(pHub->Reserved, HEX);
+
+ printProgStr(PSTR("bPwrOn2PwrGood:\t\t"));
+ Serial.println(pHub->bPwrOn2PwrGood, HEX);
+
+ printProgStr(PSTR("bHubContrCurrent:\t"));
+ Serial.println(pHub->bHubContrCurrent, HEX);
+
+ for (uint8_t i = 7; i < len; i++)
+ print_hex(descrptr[i], 8);
+
+ //for (uint8_t i=1; i<=pHub->bNbrPorts; i++)
+ // PrintHubPortStatus(&Usb, addr, i, 1);
+}
+
+byte getconfdescr( byte addr, byte conf )
+{
+ uint8_t buf[ BUFSIZE ];
+ uint8_t* buf_ptr = buf;
+ byte rcode;
+ byte descr_length;
+ byte descr_type;
+ unsigned int total_length;
+ rcode = Usb.getConfDescr( addr, 0, 4, conf, buf ); //get total length
+ LOBYTE( total_length ) = buf[ 2 ];
+ HIBYTE( total_length ) = buf[ 3 ];
+ if ( total_length > 256 ) { //check if total length is larger than buffer
+ printProgStr(Conf_Trunc_str);
+ total_length = 256;
+ }
+ rcode = Usb.getConfDescr( addr, 0, total_length, conf, buf ); //get the whole descriptor
+ while ( buf_ptr < buf + total_length ) { //parsing descriptors
+ descr_length = *( buf_ptr );
+ descr_type = *( buf_ptr + 1 );
+ switch ( descr_type ) {
+ case ( USB_DESCRIPTOR_CONFIGURATION ):
+ printconfdescr( buf_ptr );
+ break;
+ case ( USB_DESCRIPTOR_INTERFACE ):
+ printintfdescr( buf_ptr );
+ break;
+ case ( USB_DESCRIPTOR_ENDPOINT ):
+ printepdescr( buf_ptr );
+ break;
+ case 0x29:
+ printhubdescr( buf_ptr, addr );
+ break;
+ default:
+ printunkdescr( buf_ptr );
+ break;
+ }//switch( descr_type
+ buf_ptr = ( buf_ptr + descr_length ); //advance buffer pointer
+ }//while( buf_ptr <=...
+ return ( rcode );
+}
+/* prints hex numbers with leading zeroes */
+// copyright, Peter H Anderson, Baltimore, MD, Nov, '07
+// source: http://www.phanderson.com/arduino/arduino_display.html
+void print_hex(int v, int num_places)
+{
+ int mask = 0, n, num_nibbles, digit;
+
+ for (n = 1; n <= num_places; n++) {
+ mask = (mask << 1) | 0x0001;
+ }
+ v = v & mask; // truncate v to specified number of places
+
+ num_nibbles = num_places / 4;
+ if ((num_places % 4) != 0) {
+ ++num_nibbles;
+ }
+ do {
+ digit = ((v >> (num_nibbles - 1) * 4)) & 0x0f;
+ Serial.print(digit, HEX);
+ }
+ while (--num_nibbles);
+}
+/* function to print configuration descriptor */
+void printconfdescr( uint8_t* descr_ptr )
+{
+ USB_CONFIGURATION_DESCRIPTOR* conf_ptr = ( USB_CONFIGURATION_DESCRIPTOR* )descr_ptr;
+ printProgStr(Conf_Header_str);
+ printProgStr(Conf_Totlen_str);
+ print_hex( conf_ptr->wTotalLength, 16 );
+ printProgStr(Conf_Nint_str);
+ print_hex( conf_ptr->bNumInterfaces, 8 );
+ printProgStr(Conf_Value_str);
+ print_hex( conf_ptr->bConfigurationValue, 8 );
+ printProgStr(Conf_String_str);
+ print_hex( conf_ptr->iConfiguration, 8 );
+ printProgStr(Conf_Attr_str);
+ print_hex( conf_ptr->bmAttributes, 8 );
+ printProgStr(Conf_Pwr_str);
+ print_hex( conf_ptr->bMaxPower, 8 );
+ return;
+}
+/* function to print interface descriptor */
+void printintfdescr( uint8_t* descr_ptr )
+{
+ USB_INTERFACE_DESCRIPTOR* intf_ptr = ( USB_INTERFACE_DESCRIPTOR* )descr_ptr;
+ printProgStr(Int_Header_str);
+ printProgStr(Int_Number_str);
+ print_hex( intf_ptr->bInterfaceNumber, 8 );
+ printProgStr(Int_Alt_str);
+ print_hex( intf_ptr->bAlternateSetting, 8 );
+ printProgStr(Int_Endpoints_str);
+ print_hex( intf_ptr->bNumEndpoints, 8 );
+ printProgStr(Int_Class_str);
+ print_hex( intf_ptr->bInterfaceClass, 8 );
+ printProgStr(Int_Subclass_str);
+ print_hex( intf_ptr->bInterfaceSubClass, 8 );
+ printProgStr(Int_Protocol_str);
+ print_hex( intf_ptr->bInterfaceProtocol, 8 );
+ printProgStr(Int_String_str);
+ print_hex( intf_ptr->iInterface, 8 );
+ return;
+}
+/* function to print endpoint descriptor */
+void printepdescr( uint8_t* descr_ptr )
+{
+ USB_ENDPOINT_DESCRIPTOR* ep_ptr = ( USB_ENDPOINT_DESCRIPTOR* )descr_ptr;
+ printProgStr(End_Header_str);
+ printProgStr(End_Address_str);
+ print_hex( ep_ptr->bEndpointAddress, 8 );
+ printProgStr(End_Attr_str);
+ print_hex( ep_ptr->bmAttributes, 8 );
+ printProgStr(End_Pktsize_str);
+ print_hex( ep_ptr->wMaxPacketSize, 16 );
+ printProgStr(End_Interval_str);
+ print_hex( ep_ptr->bInterval, 8 );
+
+ return;
+}
+/*function to print unknown descriptor */
+void printunkdescr( uint8_t* descr_ptr )
+{
+ byte length = *descr_ptr;
+ byte i;
+ printProgStr(Unk_Header_str);
+ printProgStr(Unk_Length_str);
+ print_hex( *descr_ptr, 8 );
+ printProgStr(Unk_Type_str);
+ print_hex( *(descr_ptr + 1 ), 8 );
+ printProgStr(Unk_Contents_str);
+ descr_ptr += 2;
+ for ( i = 0; i < length; i++ ) {
+ print_hex( *descr_ptr, 8 );
+ descr_ptr++;
+ }
+}
+
+
+/* Print a string from Program Memory directly to save RAM */
+void printProgStr(const char* str)
+{
+ char c;
+ if (!str) return;
+ while ((c = pgm_read_byte(str++)))
+ Serial.print(c);
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/USB_desc/pgmstrings.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/USB_desc/pgmstrings.h
new file mode 100644
index 000000000..bdb0077ec
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/USB_desc/pgmstrings.h
@@ -0,0 +1,52 @@
+#if !defined(__PGMSTRINGS_H__)
+#define __PGMSTRINGS_H__
+
+#define LOBYTE(x) ((char*)(&(x)))[0]
+#define HIBYTE(x) ((char*)(&(x)))[1]
+#define BUFSIZE 256 //buffer size
+
+
+/* Print strings in Program Memory */
+const char Gen_Error_str[] PROGMEM = "\r\nRequest error. Error code:\t";
+const char Dev_Header_str[] PROGMEM ="\r\nDevice descriptor: ";
+const char Dev_Length_str[] PROGMEM ="\r\nDescriptor Length:\t";
+const char Dev_Type_str[] PROGMEM ="\r\nDescriptor type:\t";
+const char Dev_Version_str[] PROGMEM ="\r\nUSB version:\t\t";
+const char Dev_Class_str[] PROGMEM ="\r\nDevice class:\t\t";
+const char Dev_Subclass_str[] PROGMEM ="\r\nDevice Subclass:\t";
+const char Dev_Protocol_str[] PROGMEM ="\r\nDevice Protocol:\t";
+const char Dev_Pktsize_str[] PROGMEM ="\r\nMax.packet size:\t";
+const char Dev_Vendor_str[] PROGMEM ="\r\nVendor ID:\t\t";
+const char Dev_Product_str[] PROGMEM ="\r\nProduct ID:\t\t";
+const char Dev_Revision_str[] PROGMEM ="\r\nRevision ID:\t\t";
+const char Dev_Mfg_str[] PROGMEM ="\r\nMfg.string index:\t";
+const char Dev_Prod_str[] PROGMEM ="\r\nProd.string index:\t";
+const char Dev_Serial_str[] PROGMEM ="\r\nSerial number index:\t";
+const char Dev_Nconf_str[] PROGMEM ="\r\nNumber of conf.:\t";
+const char Conf_Trunc_str[] PROGMEM ="Total length truncated to 256 bytes";
+const char Conf_Header_str[] PROGMEM ="\r\nConfiguration descriptor:";
+const char Conf_Totlen_str[] PROGMEM ="\r\nTotal length:\t\t";
+const char Conf_Nint_str[] PROGMEM ="\r\nNum.intf:\t\t";
+const char Conf_Value_str[] PROGMEM ="\r\nConf.value:\t\t";
+const char Conf_String_str[] PROGMEM ="\r\nConf.string:\t\t";
+const char Conf_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t";
+const char Conf_Pwr_str[] PROGMEM ="\r\nMax.pwr:\t\t";
+const char Int_Header_str[] PROGMEM ="\r\n\r\nInterface descriptor:";
+const char Int_Number_str[] PROGMEM ="\r\nIntf.number:\t\t";
+const char Int_Alt_str[] PROGMEM ="\r\nAlt.:\t\t\t";
+const char Int_Endpoints_str[] PROGMEM ="\r\nEndpoints:\t\t";
+const char Int_Class_str[] PROGMEM ="\r\nIntf. Class:\t\t";
+const char Int_Subclass_str[] PROGMEM ="\r\nIntf. Subclass:\t\t";
+const char Int_Protocol_str[] PROGMEM ="\r\nIntf. Protocol:\t\t";
+const char Int_String_str[] PROGMEM ="\r\nIntf.string:\t\t";
+const char End_Header_str[] PROGMEM ="\r\n\r\nEndpoint descriptor:";
+const char End_Address_str[] PROGMEM ="\r\nEndpoint address:\t";
+const char End_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t";
+const char End_Pktsize_str[] PROGMEM ="\r\nMax.pkt size:\t\t";
+const char End_Interval_str[] PROGMEM ="\r\nPolling interval:\t";
+const char Unk_Header_str[] PROGMEM = "\r\nUnknown descriptor:";
+const char Unk_Length_str[] PROGMEM ="\r\nLength:\t\t";
+const char Unk_Type_str[] PROGMEM ="\r\nType:\t\t";
+const char Unk_Contents_str[] PROGMEM ="\r\nContents:\t";
+
+#endif // __PGMSTRINGS_H__ \ No newline at end of file
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXOLD/XBOXOLD.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXOLD/XBOXOLD.ino
new file mode 100644
index 000000000..64a3ed612
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXOLD/XBOXOLD.ino
@@ -0,0 +1,110 @@
+/*
+ Example sketch for the original Xbox library - developed by Kristian Lauszus
+ For more information visit my blog: http://blog.tkjelectronics.dk/ or
+ send me an e-mail: kristianl@tkjelectronics.com
+ */
+
+#include <XBOXOLD.h>
+#include <usbhub.h>
+
+// Satisfy the IDE, which needs to see the include statment in the ino too.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+USB Usb;
+USBHub Hub1(&Usb); // The controller has a built in hub, so this instance is needed
+XBOXOLD Xbox(&Usb);
+
+void setup() {
+ Serial.begin(115200);
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ if (Usb.Init() == -1) {
+ Serial.print(F("\r\nOSC did not start"));
+ while (1); // halt
+ }
+ Serial.print(F("\r\nXBOX Library Started"));
+}
+void loop() {
+ Usb.Task();
+ if (Xbox.XboxConnected) {
+ if (Xbox.getButtonPress(BLACK) || Xbox.getButtonPress(WHITE)) {
+ Serial.print("BLACK: ");
+ Serial.print(Xbox.getButtonPress(BLACK));
+ Serial.print("\tWHITE: ");
+ Serial.println(Xbox.getButtonPress(WHITE));
+ Xbox.setRumbleOn(Xbox.getButtonPress(BLACK), Xbox.getButtonPress(WHITE));
+ } else
+ Xbox.setRumbleOn(0, 0);
+
+ if (Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500 || Xbox.getAnalogHat(LeftHatY) > 7500 || Xbox.getAnalogHat(LeftHatY) < -7500 || Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500 || Xbox.getAnalogHat(RightHatY) > 7500 || Xbox.getAnalogHat(RightHatY) < -7500) {
+ if (Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500) {
+ Serial.print(F("LeftHatX: "));
+ Serial.print(Xbox.getAnalogHat(LeftHatX));
+ Serial.print("\t");
+ }
+ if (Xbox.getAnalogHat(LeftHatY) > 7500 || Xbox.getAnalogHat(LeftHatY) < -7500) {
+ Serial.print(F("LeftHatY: "));
+ Serial.print(Xbox.getAnalogHat(LeftHatY));
+ Serial.print("\t");
+ }
+ if (Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500) {
+ Serial.print(F("RightHatX: "));
+ Serial.print(Xbox.getAnalogHat(RightHatX));
+ Serial.print("\t");
+ }
+ if (Xbox.getAnalogHat(RightHatY) > 7500 || Xbox.getAnalogHat(RightHatY) < -7500) {
+ Serial.print(F("RightHatY: "));
+ Serial.print(Xbox.getAnalogHat(RightHatY));
+ }
+ Serial.println();
+ }
+
+ if (Xbox.getButtonClick(UP))
+ Serial.println(F("Up"));
+ if (Xbox.getButtonClick(DOWN))
+ Serial.println(F("Down"));
+ if (Xbox.getButtonClick(LEFT))
+ Serial.println(F("Left"));
+ if (Xbox.getButtonClick(RIGHT))
+ Serial.println(F("Right"));
+
+ if (Xbox.getButtonClick(START))
+ Serial.println(F("Start"));
+ if (Xbox.getButtonClick(BACK))
+ Serial.println(F("Back"));
+ if (Xbox.getButtonClick(L3))
+ Serial.println(F("L3"));
+ if (Xbox.getButtonClick(R3))
+ Serial.println(F("R3"));
+
+ if (Xbox.getButtonPress(A)) {
+ Serial.print(F("A: "));
+ Serial.println(Xbox.getButtonPress(A));
+ }
+ if (Xbox.getButtonPress(B)) {
+ Serial.print(F("B: "));
+ Serial.println(Xbox.getButtonPress(B));
+ }
+ if (Xbox.getButtonPress(X)) {
+ Serial.print(F("X: "));
+ Serial.println(Xbox.getButtonPress(X));
+ }
+ if (Xbox.getButtonPress(Y)) {
+ Serial.print(F("Y: "));
+ Serial.println(Xbox.getButtonPress(Y));
+ }
+ if (Xbox.getButtonPress(L1)) {
+ Serial.print(F("L1: "));
+ Serial.println(Xbox.getButtonPress(L1));
+ }
+ if (Xbox.getButtonPress(R1)) {
+ Serial.print(F("R1: "));
+ Serial.println(Xbox.getButtonPress(R1));
+ }
+ }
+ delay(1);
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXONE/XBOXONE.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXONE/XBOXONE.ino
new file mode 100644
index 000000000..9526f53d1
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXONE/XBOXONE.ino
@@ -0,0 +1,106 @@
+/*
+ Example sketch for the Xbox ONE USB library - by guruthree, based on work by
+ Kristian Lauszus.
+ */
+
+#include <XBOXONE.h>
+// Satisfy IDE, which only needs to see the include statment in the ino.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#endif
+
+USB Usb;
+XBOXONE Xbox(&Usb);
+
+void setup() {
+ Serial.begin(115200);
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+ if (Usb.Init() == -1) {
+ Serial.print(F("\r\nOSC did not start"));
+ while (1); //halt
+ }
+ Serial.print(F("\r\nXBOX USB Library Started"));
+}
+void loop() {
+ Usb.Task();
+ if (Xbox.XboxOneConnected) {
+ if (Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500 || Xbox.getAnalogHat(LeftHatY) > 7500 || Xbox.getAnalogHat(LeftHatY) < -7500 || Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500 || Xbox.getAnalogHat(RightHatY) > 7500 || Xbox.getAnalogHat(RightHatY) < -7500) {
+ if (Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500) {
+ Serial.print(F("LeftHatX: "));
+ Serial.print(Xbox.getAnalogHat(LeftHatX));
+ Serial.print("\t");
+ }
+ if (Xbox.getAnalogHat(LeftHatY) > 7500 || Xbox.getAnalogHat(LeftHatY) < -7500) {
+ Serial.print(F("LeftHatY: "));
+ Serial.print(Xbox.getAnalogHat(LeftHatY));
+ Serial.print("\t");
+ }
+ if (Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500) {
+ Serial.print(F("RightHatX: "));
+ Serial.print(Xbox.getAnalogHat(RightHatX));
+ Serial.print("\t");
+ }
+ if (Xbox.getAnalogHat(RightHatY) > 7500 || Xbox.getAnalogHat(RightHatY) < -7500) {
+ Serial.print(F("RightHatY: "));
+ Serial.print(Xbox.getAnalogHat(RightHatY));
+ }
+ Serial.println();
+ }
+
+ if (Xbox.getButtonPress(L2) > 0 || Xbox.getButtonPress(R2) > 0) {
+ if (Xbox.getButtonPress(L2) > 0) {
+ Serial.print(F("L2: "));
+ Serial.print(Xbox.getButtonPress(L2));
+ Serial.print("\t");
+ }
+ if (Xbox.getButtonPress(R2) > 0) {
+ Serial.print(F("R2: "));
+ Serial.print(Xbox.getButtonPress(R2));
+ Serial.print("\t");
+ }
+ Serial.println();
+ }
+
+ if (Xbox.getButtonClick(UP))
+ Serial.println(F("Up"));
+ if (Xbox.getButtonClick(DOWN))
+ Serial.println(F("Down"));
+ if (Xbox.getButtonClick(LEFT))
+ Serial.println(F("Left"));
+ if (Xbox.getButtonClick(RIGHT))
+ Serial.println(F("Right"));
+
+ if (Xbox.getButtonClick(START))
+ Serial.println(F("Start"));
+ if (Xbox.getButtonClick(BACK))
+ Serial.println(F("Back"));
+ if (Xbox.getButtonClick(XBOX))
+ Serial.println(F("Xbox"));
+ if (Xbox.getButtonClick(SYNC))
+ Serial.println(F("Sync"));
+
+ if (Xbox.getButtonClick(L1))
+ Serial.println(F("L1"));
+ if (Xbox.getButtonClick(R1))
+ Serial.println(F("R1"));
+ if (Xbox.getButtonClick(L2))
+ Serial.println(F("L2"));
+ if (Xbox.getButtonClick(R2))
+ Serial.println(F("R2"));
+ if (Xbox.getButtonClick(L3))
+ Serial.println(F("L3"));
+ if (Xbox.getButtonClick(R3))
+ Serial.println(F("R3"));
+
+
+ if (Xbox.getButtonClick(A))
+ Serial.println(F("A"));
+ if (Xbox.getButtonClick(B))
+ Serial.println(F("B"));
+ if (Xbox.getButtonClick(X))
+ Serial.println(F("X"));
+ if (Xbox.getButtonClick(Y))
+ Serial.println(F("Y"));
+ }
+ delay(1);
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXRECV/XBOXRECV.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXRECV/XBOXRECV.ino
new file mode 100644
index 000000000..491b287e4
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXRECV/XBOXRECV.ino
@@ -0,0 +1,122 @@
+/*
+ Example sketch for the Xbox Wireless Reciver library - developed by Kristian Lauszus
+ It supports up to four controllers wirelessly
+ For more information see the blog post: http://blog.tkjelectronics.dk/2012/12/xbox-360-receiver-added-to-the-usb-host-library/ or
+ send me an e-mail: kristianl@tkjelectronics.com
+ */
+
+#include <XBOXRECV.h>
+
+// Satisfy the IDE, which needs to see the include statment in the ino too.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+USB Usb;
+XBOXRECV Xbox(&Usb);
+
+void setup() {
+ Serial.begin(115200);
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ if (Usb.Init() == -1) {
+ Serial.print(F("\r\nOSC did not start"));
+ while (1); //halt
+ }
+ Serial.print(F("\r\nXbox Wireless Receiver Library Started"));
+}
+void loop() {
+ Usb.Task();
+ if (Xbox.XboxReceiverConnected) {
+ for (uint8_t i = 0; i < 4; i++) {
+ if (Xbox.Xbox360Connected[i]) {
+ if (Xbox.getButtonPress(L2, i) || Xbox.getButtonPress(R2, i)) {
+ Serial.print("L2: ");
+ Serial.print(Xbox.getButtonPress(L2, i));
+ Serial.print("\tR2: ");
+ Serial.println(Xbox.getButtonPress(R2, i));
+ Xbox.setRumbleOn(Xbox.getButtonPress(L2, i), Xbox.getButtonPress(R2, i), i);
+ }
+
+ if (Xbox.getAnalogHat(LeftHatX, i) > 7500 || Xbox.getAnalogHat(LeftHatX, i) < -7500 || Xbox.getAnalogHat(LeftHatY, i) > 7500 || Xbox.getAnalogHat(LeftHatY, i) < -7500 || Xbox.getAnalogHat(RightHatX, i) > 7500 || Xbox.getAnalogHat(RightHatX, i) < -7500 || Xbox.getAnalogHat(RightHatY, i) > 7500 || Xbox.getAnalogHat(RightHatY, i) < -7500) {
+ if (Xbox.getAnalogHat(LeftHatX, i) > 7500 || Xbox.getAnalogHat(LeftHatX, i) < -7500) {
+ Serial.print(F("LeftHatX: "));
+ Serial.print(Xbox.getAnalogHat(LeftHatX, i));
+ Serial.print("\t");
+ }
+ if (Xbox.getAnalogHat(LeftHatY, i) > 7500 || Xbox.getAnalogHat(LeftHatY, i) < -7500) {
+ Serial.print(F("LeftHatY: "));
+ Serial.print(Xbox.getAnalogHat(LeftHatY, i));
+ Serial.print("\t");
+ }
+ if (Xbox.getAnalogHat(RightHatX, i) > 7500 || Xbox.getAnalogHat(RightHatX, i) < -7500) {
+ Serial.print(F("RightHatX: "));
+ Serial.print(Xbox.getAnalogHat(RightHatX, i));
+ Serial.print("\t");
+ }
+ if (Xbox.getAnalogHat(RightHatY, i) > 7500 || Xbox.getAnalogHat(RightHatY, i) < -7500) {
+ Serial.print(F("RightHatY: "));
+ Serial.print(Xbox.getAnalogHat(RightHatY, i));
+ }
+ Serial.println();
+ }
+
+ if (Xbox.getButtonClick(UP, i)) {
+ Xbox.setLedOn(LED1, i);
+ Serial.println(F("Up"));
+ }
+ if (Xbox.getButtonClick(DOWN, i)) {
+ Xbox.setLedOn(LED4, i);
+ Serial.println(F("Down"));
+ }
+ if (Xbox.getButtonClick(LEFT, i)) {
+ Xbox.setLedOn(LED3, i);
+ Serial.println(F("Left"));
+ }
+ if (Xbox.getButtonClick(RIGHT, i)) {
+ Xbox.setLedOn(LED2, i);
+ Serial.println(F("Right"));
+ }
+
+ if (Xbox.getButtonClick(START, i)) {
+ Xbox.setLedMode(ALTERNATING, i);
+ Serial.println(F("Start"));
+ }
+ if (Xbox.getButtonClick(BACK, i)) {
+ Xbox.setLedBlink(ALL, i);
+ Serial.println(F("Back"));
+ }
+ if (Xbox.getButtonClick(L3, i))
+ Serial.println(F("L3"));
+ if (Xbox.getButtonClick(R3, i))
+ Serial.println(F("R3"));
+
+ if (Xbox.getButtonClick(L1, i))
+ Serial.println(F("L1"));
+ if (Xbox.getButtonClick(R1, i))
+ Serial.println(F("R1"));
+ if (Xbox.getButtonClick(XBOX, i)) {
+ Xbox.setLedMode(ROTATING, i);
+ Serial.print(F("Xbox (Battery: "));
+ Serial.print(Xbox.getBatteryLevel(i)); // The battery level in the range 0-3
+ Serial.println(F(")"));
+ }
+ if (Xbox.getButtonClick(SYNC, i)) {
+ Serial.println(F("Sync"));
+ Xbox.disconnect(i);
+ }
+
+ if (Xbox.getButtonClick(A, i))
+ Serial.println(F("A"));
+ if (Xbox.getButtonClick(B, i))
+ Serial.println(F("B"));
+ if (Xbox.getButtonClick(X, i))
+ Serial.println(F("X"));
+ if (Xbox.getButtonClick(Y, i))
+ Serial.println(F("Y"));
+ }
+ }
+ }
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXUSB/XBOXUSB.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXUSB/XBOXUSB.ino
new file mode 100644
index 000000000..8a5691c6e
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/Xbox/XBOXUSB/XBOXUSB.ino
@@ -0,0 +1,113 @@
+/*
+ Example sketch for the Xbox 360 USB library - developed by Kristian Lauszus
+ For more information visit my blog: http://blog.tkjelectronics.dk/ or
+ send me an e-mail: kristianl@tkjelectronics.com
+ */
+
+#include <XBOXUSB.h>
+
+// Satisfy the IDE, which needs to see the include statment in the ino too.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+USB Usb;
+XBOXUSB Xbox(&Usb);
+
+void setup() {
+ Serial.begin(115200);
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ if (Usb.Init() == -1) {
+ Serial.print(F("\r\nOSC did not start"));
+ while (1); //halt
+ }
+ Serial.print(F("\r\nXBOX USB Library Started"));
+}
+void loop() {
+ Usb.Task();
+ if (Xbox.Xbox360Connected) {
+ if (Xbox.getButtonPress(L2) || Xbox.getButtonPress(R2)) {
+ Serial.print("L2: ");
+ Serial.print(Xbox.getButtonPress(L2));
+ Serial.print("\tR2: ");
+ Serial.println(Xbox.getButtonPress(R2));
+ Xbox.setRumbleOn(Xbox.getButtonPress(L2), Xbox.getButtonPress(R2));
+ } else
+ Xbox.setRumbleOn(0, 0);
+
+ if (Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500 || Xbox.getAnalogHat(LeftHatY) > 7500 || Xbox.getAnalogHat(LeftHatY) < -7500 || Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500 || Xbox.getAnalogHat(RightHatY) > 7500 || Xbox.getAnalogHat(RightHatY) < -7500) {
+ if (Xbox.getAnalogHat(LeftHatX) > 7500 || Xbox.getAnalogHat(LeftHatX) < -7500) {
+ Serial.print(F("LeftHatX: "));
+ Serial.print(Xbox.getAnalogHat(LeftHatX));
+ Serial.print("\t");
+ }
+ if (Xbox.getAnalogHat(LeftHatY) > 7500 || Xbox.getAnalogHat(LeftHatY) < -7500) {
+ Serial.print(F("LeftHatY: "));
+ Serial.print(Xbox.getAnalogHat(LeftHatY));
+ Serial.print("\t");
+ }
+ if (Xbox.getAnalogHat(RightHatX) > 7500 || Xbox.getAnalogHat(RightHatX) < -7500) {
+ Serial.print(F("RightHatX: "));
+ Serial.print(Xbox.getAnalogHat(RightHatX));
+ Serial.print("\t");
+ }
+ if (Xbox.getAnalogHat(RightHatY) > 7500 || Xbox.getAnalogHat(RightHatY) < -7500) {
+ Serial.print(F("RightHatY: "));
+ Serial.print(Xbox.getAnalogHat(RightHatY));
+ }
+ Serial.println();
+ }
+
+ if (Xbox.getButtonClick(UP)) {
+ Xbox.setLedOn(LED1);
+ Serial.println(F("Up"));
+ }
+ if (Xbox.getButtonClick(DOWN)) {
+ Xbox.setLedOn(LED4);
+ Serial.println(F("Down"));
+ }
+ if (Xbox.getButtonClick(LEFT)) {
+ Xbox.setLedOn(LED3);
+ Serial.println(F("Left"));
+ }
+ if (Xbox.getButtonClick(RIGHT)) {
+ Xbox.setLedOn(LED2);
+ Serial.println(F("Right"));
+ }
+
+ if (Xbox.getButtonClick(START)) {
+ Xbox.setLedMode(ALTERNATING);
+ Serial.println(F("Start"));
+ }
+ if (Xbox.getButtonClick(BACK)) {
+ Xbox.setLedBlink(ALL);
+ Serial.println(F("Back"));
+ }
+ if (Xbox.getButtonClick(L3))
+ Serial.println(F("L3"));
+ if (Xbox.getButtonClick(R3))
+ Serial.println(F("R3"));
+
+ if (Xbox.getButtonClick(L1))
+ Serial.println(F("L1"));
+ if (Xbox.getButtonClick(R1))
+ Serial.println(F("R1"));
+ if (Xbox.getButtonClick(XBOX)) {
+ Xbox.setLedMode(ROTATING);
+ Serial.println(F("Xbox"));
+ }
+
+ if (Xbox.getButtonClick(A))
+ Serial.println(F("A"));
+ if (Xbox.getButtonClick(B))
+ Serial.println(F("B"));
+ if (Xbox.getButtonClick(X))
+ Serial.println(F("X"));
+ if (Xbox.getButtonClick(Y))
+ Serial.println(F("Y"));
+ }
+ delay(1);
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/acm/acm_terminal/acm_terminal.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/acm/acm_terminal/acm_terminal.ino
new file mode 100644
index 000000000..f509cda89
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/acm/acm_terminal/acm_terminal.ino
@@ -0,0 +1,100 @@
+#include <cdcacm.h>
+#include <usbhub.h>
+
+#include "pgmstrings.h"
+
+// Satisfy the IDE, which needs to see the include statment in the ino too.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+class ACMAsyncOper : public CDCAsyncOper
+{
+public:
+ uint8_t OnInit(ACM *pacm);
+};
+
+uint8_t ACMAsyncOper::OnInit(ACM *pacm)
+{
+ uint8_t rcode;
+ // Set DTR = 1 RTS=1
+ rcode = pacm->SetControlLineState(3);
+
+ if (rcode)
+ {
+ ErrorMessage<uint8_t>(PSTR("SetControlLineState"), rcode);
+ return rcode;
+ }
+
+ LINE_CODING lc;
+ lc.dwDTERate = 115200;
+ lc.bCharFormat = 0;
+ lc.bParityType = 0;
+ lc.bDataBits = 8;
+
+ rcode = pacm->SetLineCoding(&lc);
+
+ if (rcode)
+ ErrorMessage<uint8_t>(PSTR("SetLineCoding"), rcode);
+
+ return rcode;
+}
+
+USB Usb;
+//USBHub Hub(&Usb);
+ACMAsyncOper AsyncOper;
+ACM Acm(&Usb, &AsyncOper);
+
+void setup()
+{
+ Serial.begin( 115200 );
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ Serial.println("Start");
+
+ if (Usb.Init() == -1)
+ Serial.println("OSCOKIRQ failed to assert");
+
+ delay( 200 );
+}
+
+void loop()
+{
+ Usb.Task();
+
+ if( Acm.isReady()) {
+ uint8_t rcode;
+
+ /* reading the keyboard */
+ if(Serial.available()) {
+ uint8_t data= Serial.read();
+ /* sending to the phone */
+ rcode = Acm.SndData(1, &data);
+ if (rcode)
+ ErrorMessage<uint8_t>(PSTR("SndData"), rcode);
+ }//if(Serial.available()...
+
+ delay(50);
+
+ /* reading the phone */
+ /* buffer size must be greater or equal to max.packet size */
+ /* it it set to 64 (largest possible max.packet size) here, can be tuned down
+ for particular endpoint */
+ uint8_t buf[64];
+ uint16_t rcvd = 64;
+ rcode = Acm.RcvData(&rcvd, buf);
+ if (rcode && rcode != hrNAK)
+ ErrorMessage<uint8_t>(PSTR("Ret"), rcode);
+
+ if( rcvd ) { //more than zero bytes received
+ for(uint16_t i=0; i < rcvd; i++ ) {
+ Serial.print((char)buf[i]); //printing on the screen
+ }
+ }
+ delay(10);
+ }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING..
+}
+
+
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/acm/acm_terminal/pgmstrings.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/acm/acm_terminal/pgmstrings.h
new file mode 100644
index 000000000..bdb0077ec
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/acm/acm_terminal/pgmstrings.h
@@ -0,0 +1,52 @@
+#if !defined(__PGMSTRINGS_H__)
+#define __PGMSTRINGS_H__
+
+#define LOBYTE(x) ((char*)(&(x)))[0]
+#define HIBYTE(x) ((char*)(&(x)))[1]
+#define BUFSIZE 256 //buffer size
+
+
+/* Print strings in Program Memory */
+const char Gen_Error_str[] PROGMEM = "\r\nRequest error. Error code:\t";
+const char Dev_Header_str[] PROGMEM ="\r\nDevice descriptor: ";
+const char Dev_Length_str[] PROGMEM ="\r\nDescriptor Length:\t";
+const char Dev_Type_str[] PROGMEM ="\r\nDescriptor type:\t";
+const char Dev_Version_str[] PROGMEM ="\r\nUSB version:\t\t";
+const char Dev_Class_str[] PROGMEM ="\r\nDevice class:\t\t";
+const char Dev_Subclass_str[] PROGMEM ="\r\nDevice Subclass:\t";
+const char Dev_Protocol_str[] PROGMEM ="\r\nDevice Protocol:\t";
+const char Dev_Pktsize_str[] PROGMEM ="\r\nMax.packet size:\t";
+const char Dev_Vendor_str[] PROGMEM ="\r\nVendor ID:\t\t";
+const char Dev_Product_str[] PROGMEM ="\r\nProduct ID:\t\t";
+const char Dev_Revision_str[] PROGMEM ="\r\nRevision ID:\t\t";
+const char Dev_Mfg_str[] PROGMEM ="\r\nMfg.string index:\t";
+const char Dev_Prod_str[] PROGMEM ="\r\nProd.string index:\t";
+const char Dev_Serial_str[] PROGMEM ="\r\nSerial number index:\t";
+const char Dev_Nconf_str[] PROGMEM ="\r\nNumber of conf.:\t";
+const char Conf_Trunc_str[] PROGMEM ="Total length truncated to 256 bytes";
+const char Conf_Header_str[] PROGMEM ="\r\nConfiguration descriptor:";
+const char Conf_Totlen_str[] PROGMEM ="\r\nTotal length:\t\t";
+const char Conf_Nint_str[] PROGMEM ="\r\nNum.intf:\t\t";
+const char Conf_Value_str[] PROGMEM ="\r\nConf.value:\t\t";
+const char Conf_String_str[] PROGMEM ="\r\nConf.string:\t\t";
+const char Conf_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t";
+const char Conf_Pwr_str[] PROGMEM ="\r\nMax.pwr:\t\t";
+const char Int_Header_str[] PROGMEM ="\r\n\r\nInterface descriptor:";
+const char Int_Number_str[] PROGMEM ="\r\nIntf.number:\t\t";
+const char Int_Alt_str[] PROGMEM ="\r\nAlt.:\t\t\t";
+const char Int_Endpoints_str[] PROGMEM ="\r\nEndpoints:\t\t";
+const char Int_Class_str[] PROGMEM ="\r\nIntf. Class:\t\t";
+const char Int_Subclass_str[] PROGMEM ="\r\nIntf. Subclass:\t\t";
+const char Int_Protocol_str[] PROGMEM ="\r\nIntf. Protocol:\t\t";
+const char Int_String_str[] PROGMEM ="\r\nIntf.string:\t\t";
+const char End_Header_str[] PROGMEM ="\r\n\r\nEndpoint descriptor:";
+const char End_Address_str[] PROGMEM ="\r\nEndpoint address:\t";
+const char End_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t";
+const char End_Pktsize_str[] PROGMEM ="\r\nMax.pkt size:\t\t";
+const char End_Interval_str[] PROGMEM ="\r\nPolling interval:\t";
+const char Unk_Header_str[] PROGMEM = "\r\nUnknown descriptor:";
+const char Unk_Length_str[] PROGMEM ="\r\nLength:\t\t";
+const char Unk_Type_str[] PROGMEM ="\r\nType:\t\t";
+const char Unk_Contents_str[] PROGMEM ="\r\nContents:\t";
+
+#endif // __PGMSTRINGS_H__ \ No newline at end of file
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/ArduinoBlinkLED/ArduinoBlinkLED.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/ArduinoBlinkLED/ArduinoBlinkLED.ino
new file mode 100644
index 000000000..d59b9bb3d
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/ArduinoBlinkLED/ArduinoBlinkLED.ino
@@ -0,0 +1,89 @@
+// The source for the Android application can be found at the following link: https://github.com/Lauszus/ArduinoBlinkLED
+// The code for the Android application is heavily based on this guide: http://allaboutee.com/2011/12/31/arduino-adk-board-blink-an-led-with-your-phone-code-and-explanation/ by Miguel
+#include <adk.h>
+
+//
+// CAUTION! WARNING! ATTENTION! VORSICHT! ADVARSEL! ¡CUIDADO! ВНИМАНИЕ!
+//
+// Pin 13 is occupied by the SCK pin on various Arduino boards,
+// including Uno, Duemilanove, etc., so use a different pin for those boards.
+//
+// CAUTION! WARNING! ATTENTION! VORSICHT! ADVARSEL! ¡CUIDADO! ВНИМАНИЕ!
+//
+#if defined(LED_BUILTIN)
+#define LED LED_BUILTIN // Use built in LED
+#else
+#define LED 9 // Set to something here that makes sense for your board.
+#endif
+
+
+// Satisfy IDE, which only needs to see the include statment in the ino.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+USB Usb;
+ADK adk(&Usb, "TKJElectronics", // Manufacturer Name
+ "ArduinoBlinkLED", // Model Name
+ "Example sketch for the USB Host Shield", // Description (user-visible string)
+ "1.0", // Version
+ "http://www.tkjelectronics.dk/uploads/ArduinoBlinkLED.apk", // URL (web page to visit if no installed apps support the accessory)
+ "123456789"); // Serial Number (optional)
+
+uint32_t timer;
+bool connected;
+
+void setup() {
+ Serial.begin(115200);
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ if (Usb.Init() == -1) {
+ Serial.print("\r\nOSCOKIRQ failed to assert");
+ while (1); // halt
+ }
+ pinMode(LED, OUTPUT);
+ Serial.print("\r\nArduino Blink LED Started");
+}
+
+void loop() {
+ Usb.Task();
+
+ if (adk.isReady()) {
+ if (!connected) {
+ connected = true;
+ Serial.print(F("\r\nConnected to accessory"));
+ }
+
+ uint8_t msg[1];
+ uint16_t len = sizeof(msg);
+ uint8_t rcode = adk.RcvData(&len, msg);
+ if (rcode && rcode != hrNAK) {
+ Serial.print(F("\r\nData rcv: "));
+ Serial.print(rcode, HEX);
+ } else if (len > 0) {
+ Serial.print(F("\r\nData Packet: "));
+ Serial.print(msg[0]);
+ digitalWrite(LED, msg[0] ? HIGH : LOW);
+ }
+
+ if (millis() - timer >= 1000) { // Send data every 1s
+ timer = millis();
+ rcode = adk.SndData(sizeof(timer), (uint8_t*)&timer);
+ if (rcode && rcode != hrNAK) {
+ Serial.print(F("\r\nData send: "));
+ Serial.print(rcode, HEX);
+ } else if (rcode != hrNAK) {
+ Serial.print(F("\r\nTimer: "));
+ Serial.print(timer);
+ }
+ }
+ } else {
+ if (connected) {
+ connected = false;
+ Serial.print(F("\r\nDisconnected from accessory"));
+ digitalWrite(LED, LOW);
+ }
+ }
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/adk_barcode/adk_barcode.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/adk_barcode/adk_barcode.ino
new file mode 100644
index 000000000..a308ff0f8
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/adk_barcode/adk_barcode.ino
@@ -0,0 +1,91 @@
+/**/
+/* A sketch demonstrating data exchange between two USB devices - a HID barcode scanner and ADK-compatible Android phone */
+/**/
+#include <adk.h>
+#include <hidboot.h>
+#include <usbhub.h>
+
+// Satisfy IDE, which only needs to see the include statment in the ino.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+USB Usb;
+USBHub Hub1(&Usb);
+USBHub Hub2(&Usb);
+HIDBoot<HID_PROTOCOL_KEYBOARD> Keyboard(&Usb);
+
+ADK adk(&Usb,"Circuits@Home, ltd.",
+ "USB Host Shield",
+ "Arduino Terminal for Android",
+ "1.0",
+ "http://www.circuitsathome.com",
+ "0000000000000001");
+
+
+class KbdRptParser : public KeyboardReportParser
+{
+
+protected:
+ void OnKeyDown (uint8_t mod, uint8_t key);
+ void OnKeyPressed(uint8_t key);
+};
+
+void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key)
+{
+ uint8_t c = OemToAscii(mod, key);
+
+ if (c)
+ OnKeyPressed(c);
+}
+
+/* what to do when symbol arrives */
+void KbdRptParser::OnKeyPressed(uint8_t key)
+{
+const char* new_line = "\n";
+uint8_t rcode;
+uint8_t keylcl;
+
+ if( adk.isReady() == false ) {
+ return;
+ }
+
+ keylcl = key;
+
+ if( keylcl == 0x13 ) {
+ rcode = adk.SndData( strlen( new_line ), (uint8_t *)new_line );
+ }
+ else {
+ rcode = adk.SndData( 1, &keylcl );
+ }
+
+ Serial.print((char) keylcl );
+ Serial.print(" : ");
+ Serial.println( keylcl, HEX );
+};
+
+KbdRptParser Prs;
+
+void setup()
+{
+ Serial.begin(115200);
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ Serial.println("\r\nADK demo start");
+
+ if (Usb.Init() == -1) {
+ Serial.println("OSCOKIRQ failed to assert");
+ while(1); //halt
+ }//if (Usb.Init() == -1...
+
+ Keyboard.SetReportParser(0, (HIDReportParser*)&Prs);
+
+ delay( 200 );
+}
+
+void loop()
+{
+ Usb.Task();
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/demokit_20/demokit_20.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/demokit_20/demokit_20.ino
new file mode 100644
index 000000000..f65adf57b
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/demokit_20/demokit_20.ino
@@ -0,0 +1,103 @@
+#include <adk.h>
+#include <usbhub.h>
+
+// Satisfy IDE, which only needs to see the include statment in the ino.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+USB Usb;
+USBHub hub0(&Usb);
+USBHub hub1(&Usb);
+ADK adk(&Usb,"Google, Inc.",
+ "DemoKit",
+ "DemoKit Arduino Board",
+ "1.0",
+ "http://www.android.com",
+ "0000000012345678");
+uint8_t b, b1;
+
+
+#define LED1_RED 3
+#define BUTTON1 2
+
+void init_buttons()
+{
+ pinMode(BUTTON1, INPUT);
+
+ // enable the internal pullups
+ digitalWrite(BUTTON1, HIGH);
+}
+
+void init_leds()
+{
+ digitalWrite(LED1_RED, 0);
+
+ pinMode(LED1_RED, OUTPUT);
+}
+
+void setup()
+{
+ Serial.begin(115200);
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ Serial.println("\r\nADK demo start");
+
+ if (Usb.Init() == -1) {
+ Serial.println("OSCOKIRQ failed to assert");
+ while(1); //halt
+ }//if (Usb.Init() == -1...
+
+
+ init_leds();
+ init_buttons();
+ b1 = digitalRead(BUTTON1);
+}
+
+void loop()
+{
+ uint8_t rcode;
+ uint8_t msg[3] = { 0x00 };
+ Usb.Task();
+
+ if( adk.isReady() == false ) {
+ analogWrite(LED1_RED, 255);
+ return;
+ }
+ uint16_t len = sizeof(msg);
+
+ rcode = adk.RcvData(&len, msg);
+ if( rcode ) {
+ USBTRACE2("Data rcv. :", rcode );
+ }
+ if(len > 0) {
+ USBTRACE("\r\nData Packet.");
+ // assumes only one command per packet
+ if (msg[0] == 0x2) {
+ switch( msg[1] ) {
+ case 0:
+ analogWrite(LED1_RED, 255 - msg[2]);
+ break;
+ }//switch( msg[1]...
+ }//if (msg[0] == 0x2...
+ }//if( len > 0...
+
+ msg[0] = 0x1;
+
+ b = digitalRead(BUTTON1);
+ if (b != b1) {
+ USBTRACE("\r\nButton state changed");
+ msg[1] = 0;
+ msg[2] = b ? 0 : 1;
+ rcode = adk.SndData( 3, msg );
+ if( rcode ) {
+ USBTRACE2("Button send: ", rcode );
+ }
+ b1 = b;
+ }//if (b != b1...
+
+
+ delay( 10 );
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/term_test/term_test.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/term_test/term_test.ino
new file mode 100644
index 000000000..db681c3b5
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/term_test/term_test.ino
@@ -0,0 +1,65 @@
+#include <adk.h>
+#include <usbhub.h>
+
+// Satisfy IDE, which only needs to see the include statment in the ino.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+USB Usb;
+//USBHub Hub(&Usb);
+
+ADK adk(&Usb,"Circuits@Home, ltd.",
+ "USB Host Shield",
+ "Arduino Terminal for Android",
+ "1.0",
+ "http://www.circuitsathome.com",
+ "0000000000000001");
+
+void setup()
+{
+ Serial.begin(115200);
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ Serial.println("\r\nADK demo start");
+
+ if (Usb.Init() == -1) {
+ Serial.println("OSCOKIRQ failed to assert");
+ while(1); //halt
+ }//if (Usb.Init() == -1...
+}
+
+void loop()
+{
+ uint8_t rcode;
+ uint8_t msg[64] = { 0x00 };
+ const char* recv = "Received: ";
+
+ Usb.Task();
+
+ if( adk.isReady() == false ) {
+ return;
+ }
+ uint16_t len = 64;
+
+ rcode = adk.RcvData(&len, msg);
+ if( rcode & ( rcode != hrNAK )) {
+ USBTRACE2("Data rcv. :", rcode );
+ }
+ if(len > 0) {
+ USBTRACE("\r\nData Packet.");
+
+ for( uint8_t i = 0; i < len; i++ ) {
+ Serial.print((char)msg[i]);
+ }
+ /* sending back what was received */
+ rcode = adk.SndData( strlen( recv ), (uint8_t *)recv );
+ rcode = adk.SndData( strlen(( char * )msg ), msg );
+
+ }//if( len > 0 )...
+
+ delay( 1000 );
+}
+
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/term_time/term_time.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/term_time/term_time.ino
new file mode 100644
index 000000000..a3f1dbc8c
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/adk/term_time/term_time.ino
@@ -0,0 +1,50 @@
+#include <adk.h>
+#include <usbhub.h>
+
+// Satisfy IDE, which only needs to see the include statment in the ino.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+USB Usb;
+
+ADK adk(&Usb,"Circuits@Home, ltd.",
+ "USB Host Shield",
+ "Arduino Terminal for Android",
+ "1.0",
+ "http://www.circuitsathome.com",
+ "0000000000000001");
+
+void setup()
+{
+ Serial.begin(115200);
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ Serial.println("\r\nADK demo start");
+
+ if (Usb.Init() == -1) {
+ Serial.println("OSCOKIRQ failed to assert");
+ while(1); //halt
+ }//if (Usb.Init() == -1...
+}
+
+void loop()
+{
+ uint8_t buf[ 12 ] = { 0 }; //buffer to convert unsigned long to ASCII
+ const char* sec_ela = " seconds elapsed\r";
+ uint8_t rcode;
+
+ Usb.Task();
+ if( adk.isReady() == false ) {
+ return;
+ }
+
+ ultoa( millis()/1000, (char *)buf, 10 );
+
+ rcode = adk.SndData( strlen((char *)buf), buf );
+ rcode = adk.SndData( strlen( sec_ela), (uint8_t *)sec_ela );
+
+ delay( 1000 );
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/board_qc/board_qc.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/board_qc/board_qc.ino
new file mode 100644
index 000000000..573c3ce08
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/board_qc/board_qc.ino
@@ -0,0 +1,259 @@
+/* USB Host Shield 2.0 board quality control routine */
+/* To see the output set your terminal speed to 115200 */
+/* for GPIO test to pass you need to connect GPIN0 to GPOUT7, GPIN1 to GPOUT6, etc. */
+/* otherwise press any key after getting GPIO error to complete the test */
+/**/
+#include <usbhub.h>
+
+// Satisfy the IDE, which needs to see the include statment in the ino too.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <../../../../hardware/pic32/libraries/SPI/SPI.h> // Hack to use the SPI library
+#include <SPI.h> // Hack to use the SPI library
+#endif
+
+/* variables */
+uint8_t rcode;
+uint8_t usbstate;
+uint8_t laststate;
+//uint8_t buf[sizeof(USB_DEVICE_DESCRIPTOR)];
+USB_DEVICE_DESCRIPTOR buf;
+
+/* objects */
+USB Usb;
+//USBHub hub(&Usb);
+
+void setup() {
+ laststate = 0;
+ Serial.begin(115200);
+#if !defined(__MIPSEL__)
+ while(!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ E_Notify(PSTR("\r\nCircuits At Home 2011"), 0x80);
+ E_Notify(PSTR("\r\nUSB Host Shield Quality Control Routine"), 0x80);
+ /* SPI quick test - check revision register */
+ E_Notify(PSTR("\r\nReading REVISION register... Die revision "), 0x80);
+ Usb.Init(); // Initializes SPI, we don't care about the return value here
+ {
+ uint8_t tmpbyte = Usb.regRd(rREVISION);
+ switch(tmpbyte) {
+ case( 0x01): //rev.01
+ E_Notify(PSTR("01"), 0x80);
+ break;
+ case( 0x12): //rev.02
+ E_Notify(PSTR("02"), 0x80);
+ break;
+ case( 0x13): //rev.03
+ E_Notify(PSTR("03"), 0x80);
+ break;
+ default:
+ E_Notify(PSTR("invalid. Value returned: "), 0x80);
+ print_hex(tmpbyte, 8);
+ halt55();
+ break;
+ }//switch( tmpbyte...
+ }//check revision register
+ /* SPI long test */
+ {
+ E_Notify(PSTR("\r\nSPI long test. Transfers 1MB of data. Each dot is 64K"), 0x80);
+ uint8_t sample_wr = 0;
+ uint8_t sample_rd = 0;
+ uint8_t gpinpol_copy = Usb.regRd(rGPINPOL);
+ for(uint8_t i = 0; i < 16; i++) {
+ for(uint16_t j = 0; j < 65535; j++) {
+ Usb.regWr(rGPINPOL, sample_wr);
+ sample_rd = Usb.regRd(rGPINPOL);
+ if(sample_rd != sample_wr) {
+ E_Notify(PSTR("\r\nTest failed. "), 0x80);
+ E_Notify(PSTR("Value written: "), 0x80);
+ print_hex(sample_wr, 8);
+ E_Notify(PSTR(" read: "), 0x80);
+ print_hex(sample_rd, 8);
+ halt55();
+ }//if( sample_rd != sample_wr..
+ sample_wr++;
+ }//for( uint16_t j...
+ E_Notify(PSTR("."), 0x80);
+ }//for( uint8_t i...
+ Usb.regWr(rGPINPOL, gpinpol_copy);
+ E_Notify(PSTR(" SPI long test passed"), 0x80);
+ }//SPI long test
+ /* GPIO test */
+ /* in order to simplify board layout, GPIN pins on text fixture are connected to GPOUT */
+ /* in reverse order, i.e, GPIN0 is connected to GPOUT7, GPIN1 to GPOUT6, etc. */
+ {
+ uint8_t tmpbyte;
+ E_Notify(PSTR("\r\nGPIO test. Connect GPIN0 to GPOUT7, GPIN1 to GPOUT6, and so on"), 0x80);
+ for(uint8_t sample_gpio = 0; sample_gpio < 255; sample_gpio++) {
+ Usb.gpioWr(sample_gpio);
+ tmpbyte = Usb.gpioRd();
+ /* bit reversing code copied vetbatim from http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious */
+ tmpbyte = ((tmpbyte * 0x0802LU & 0x22110LU) | (tmpbyte * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
+ if(sample_gpio != tmpbyte) {
+ E_Notify(PSTR("\r\nTest failed. Value written: "), 0x80);
+ print_hex(sample_gpio, 8);
+ E_Notify(PSTR(" Value read: "), 0x80);
+ print_hex(tmpbyte, 8);
+ E_Notify(PSTR(" "), 0x80);
+ press_any_key();
+ break;
+ }//if( sample_gpio != tmpbyte...
+ }//for( uint8_t sample_gpio...
+ E_Notify(PSTR("\r\nGPIO test passed."), 0x80);
+ }//GPIO test
+ /* PLL test. Stops/starts MAX3421E oscillator several times */
+ {
+ E_Notify(PSTR("\r\nPLL test. 100 chip resets will be performed"), 0x80);
+ /* check current state of the oscillator */
+ if(!(Usb.regRd(rUSBIRQ) & bmOSCOKIRQ)) { //wrong state - should be on
+ E_Notify(PSTR("\r\nCurrent oscillator state unexpected."), 0x80);
+ press_any_key();
+ }
+ /* Restart oscillator */
+ E_Notify(PSTR("\r\nResetting oscillator\r\n"), 0x80);
+ for(uint16_t i = 0; i < 100; i++) {
+ E_Notify(PSTR("\rReset number "), 0x80);
+ Serial.print(i, DEC);
+ Usb.regWr(rUSBCTL, bmCHIPRES); //reset
+ if(Usb.regRd(rUSBIRQ) & bmOSCOKIRQ) { //wrong state - should be off
+ E_Notify(PSTR("\r\nCurrent oscillator state unexpected."), 0x80);
+ halt55();
+ }
+ Usb.regWr(rUSBCTL, 0x00); //release from reset
+ uint16_t j = 0;
+ for(j = 1; j < 65535; j++) { //tracking off to on time
+ if(Usb.regRd(rUSBIRQ) & bmOSCOKIRQ) {
+ E_Notify(PSTR(" Time to stabilize - "), 0x80);
+ Serial.print(j, DEC);
+ E_Notify(PSTR(" cycles\r\n"), 0x80);
+ break;
+ }
+ }//for( uint16_t j = 0; j < 65535; j++
+ if(j == 0) {
+ E_Notify(PSTR("PLL failed to stabilize"), 0x80);
+ press_any_key();
+ }
+ }//for( uint8_t i = 0; i < 255; i++
+
+ }//PLL test
+ /* initializing USB stack */
+ if(Usb.Init() == -1) {
+ E_Notify(PSTR("\r\nOSCOKIRQ failed to assert"), 0x80);
+ halt55();
+ }
+ E_Notify(PSTR("\r\nChecking USB device communication.\r\n"), 0x80);
+}
+
+void loop() {
+ delay(200);
+ Usb.Task();
+ usbstate = Usb.getUsbTaskState();
+ if(usbstate != laststate) {
+ laststate = usbstate;
+ /**/
+ switch(usbstate) {
+ case( USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE):
+ E_Notify(PSTR("\r\nWaiting for device..."), 0x80);
+ break;
+ case( USB_ATTACHED_SUBSTATE_RESET_DEVICE):
+ E_Notify(PSTR("\r\nDevice connected. Resetting..."), 0x80);
+ break;
+ case( USB_ATTACHED_SUBSTATE_WAIT_SOF):
+ E_Notify(PSTR("\r\nReset complete. Waiting for the first SOF..."), 0x80);
+ break;
+ case( USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE):
+ E_Notify(PSTR("\r\nSOF generation started. Enumerating device..."), 0x80);
+ break;
+ case( USB_STATE_ADDRESSING):
+ E_Notify(PSTR("\r\nSetting device address..."), 0x80);
+ break;
+ case( USB_STATE_RUNNING):
+ E_Notify(PSTR("\r\nGetting device descriptor"), 0x80);
+ rcode = Usb.getDevDescr(1, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*) & buf);
+
+ if(rcode) {
+ E_Notify(PSTR("\r\nError reading device descriptor. Error code "), 0x80);
+ print_hex(rcode, 8);
+ } else {
+ /**/
+ E_Notify(PSTR("\r\nDescriptor Length:\t"), 0x80);
+ print_hex(buf.bLength, 8);
+ E_Notify(PSTR("\r\nDescriptor type:\t"), 0x80);
+ print_hex(buf.bDescriptorType, 8);
+ E_Notify(PSTR("\r\nUSB version:\t\t"), 0x80);
+ print_hex(buf.bcdUSB, 16);
+ E_Notify(PSTR("\r\nDevice class:\t\t"), 0x80);
+ print_hex(buf.bDeviceClass, 8);
+ E_Notify(PSTR("\r\nDevice Subclass:\t"), 0x80);
+ print_hex(buf.bDeviceSubClass, 8);
+ E_Notify(PSTR("\r\nDevice Protocol:\t"), 0x80);
+ print_hex(buf.bDeviceProtocol, 8);
+ E_Notify(PSTR("\r\nMax.packet size:\t"), 0x80);
+ print_hex(buf.bMaxPacketSize0, 8);
+ E_Notify(PSTR("\r\nVendor ID:\t\t"), 0x80);
+ print_hex(buf.idVendor, 16);
+ E_Notify(PSTR("\r\nProduct ID:\t\t"), 0x80);
+ print_hex(buf.idProduct, 16);
+ E_Notify(PSTR("\r\nRevision ID:\t\t"), 0x80);
+ print_hex(buf.bcdDevice, 16);
+ E_Notify(PSTR("\r\nMfg.string index:\t"), 0x80);
+ print_hex(buf.iManufacturer, 8);
+ E_Notify(PSTR("\r\nProd.string index:\t"), 0x80);
+ print_hex(buf.iProduct, 8);
+ E_Notify(PSTR("\r\nSerial number index:\t"), 0x80);
+ print_hex(buf.iSerialNumber, 8);
+ E_Notify(PSTR("\r\nNumber of conf.:\t"), 0x80);
+ print_hex(buf.bNumConfigurations, 8);
+ /**/
+ E_Notify(PSTR("\r\n\nAll tests passed. Press RESET to restart test"), 0x80);
+ while(1);
+ }
+ break;
+ case( USB_STATE_ERROR):
+ E_Notify(PSTR("\r\nUSB state machine reached error state"), 0x80);
+ break;
+
+ default:
+ break;
+ }//switch( usbstate...
+ }
+}//loop()...
+
+/* constantly transmits 0x55 via SPI to aid probing */
+void halt55() {
+
+ E_Notify(PSTR("\r\nUnrecoverable error - test halted!!"), 0x80);
+ E_Notify(PSTR("\r\n0x55 pattern is transmitted via SPI"), 0x80);
+ E_Notify(PSTR("\r\nPress RESET to restart test"), 0x80);
+
+ while(1) {
+ Usb.regWr(0x55, 0x55);
+ }
+}
+
+/* prints hex numbers with leading zeroes */
+void print_hex(int v, int num_places) {
+ int mask = 0, n, num_nibbles, digit;
+
+ for(n = 1; n <= num_places; n++) {
+ mask = (mask << 1) | 0x0001;
+ }
+ v = v & mask; // truncate v to specified number of places
+
+ num_nibbles = num_places / 4;
+ if((num_places % 4) != 0) {
+ ++num_nibbles;
+ }
+ do {
+ digit = ((v >> (num_nibbles - 1) * 4)) & 0x0f;
+ Serial.print(digit, HEX);
+ } while(--num_nibbles);
+}
+
+/* prints "Press any key" and returns when key is pressed */
+void press_any_key() {
+ E_Notify(PSTR("\r\nPress any key to continue..."), 0x80);
+ while(Serial.available() <= 0); //wait for input
+ Serial.read(); //empty input buffer
+ return;
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/cdc_XR21B1411/XR_terminal/XR_terminal.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/cdc_XR21B1411/XR_terminal/XR_terminal.ino
new file mode 100644
index 000000000..0173a08b5
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/cdc_XR21B1411/XR_terminal/XR_terminal.ino
@@ -0,0 +1,83 @@
+#include <cdc_XR21B1411.h>
+
+// Satisfy IDE, which only needs to see the include statment in the ino.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+class ACMAsyncOper : public CDCAsyncOper
+{
+public:
+ uint8_t OnInit(ACM *pacm);
+};
+
+uint8_t ACMAsyncOper::OnInit(ACM *pacm)
+{
+ uint8_t rcode;
+ // Set DTR = 1 RTS=1
+ rcode = pacm->SetControlLineState(3);
+
+ if (rcode)
+ {
+ ErrorMessage<uint8_t>(PSTR("SetControlLineState"), rcode);
+ return rcode;
+ }
+
+ LINE_CODING lc;
+ lc.dwDTERate = 115200;
+ lc.bCharFormat = 0;
+ lc.bParityType = 0;
+ lc.bDataBits = 8;
+
+ rcode = pacm->SetLineCoding(&lc);
+
+ if (rcode)
+ ErrorMessage<uint8_t>(PSTR("SetLineCoding"), rcode);
+
+ return rcode;
+}
+
+USB Usb;
+ACMAsyncOper AsyncOper;
+XR21B1411 Acm(&Usb, &AsyncOper);
+
+void setup() {
+ Serial.begin( 115200 );
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ Serial.println("\r\n\r\nStart");
+
+ if (Usb.Init() == -1) Serial.println("OSCOKIRQ failed to assert");
+}
+
+void loop() {
+ Usb.Task();
+ if( Acm.isReady()) {
+ uint8_t rcode;
+ uint8_t buf[1];
+ uint16_t rcvd = 1;
+
+ /* read keyboard */
+ if(Serial.available()) {
+ uint8_t data = Serial.read();
+ /* send */
+ rcode = Acm.SndData(1, &data);
+ if (rcode)
+ ErrorMessage<uint8_t>(PSTR("SndData"), rcode);
+ }
+
+ /* read XR serial */
+ rcode = Acm.RcvData(&rcvd, buf);
+ if (rcode && rcode != hrNAK)
+ ErrorMessage<uint8_t>(PSTR("Ret"), rcode);
+
+ if( rcvd ) { //more than zero bytes received
+ for(uint16_t i=0; i < rcvd; i++ ) {
+ Serial.print((char)buf[i]);
+ }
+ }
+ }
+}
+
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/ftdi/USBFTDILoopback/USBFTDILoopback.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/ftdi/USBFTDILoopback/USBFTDILoopback.ino
new file mode 100644
index 000000000..5be7adc2f
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/ftdi/USBFTDILoopback/USBFTDILoopback.ino
@@ -0,0 +1,98 @@
+#include <cdcftdi.h>
+#include <usbhub.h>
+
+#include "pgmstrings.h"
+
+// Satisfy the IDE, which needs to see the include statment in the ino too.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+class FTDIAsync : public FTDIAsyncOper
+{
+public:
+ uint8_t OnInit(FTDI *pftdi);
+};
+
+uint8_t FTDIAsync::OnInit(FTDI *pftdi)
+{
+ uint8_t rcode = 0;
+
+ rcode = pftdi->SetBaudRate(115200);
+
+ if (rcode)
+ {
+ ErrorMessage<uint8_t>(PSTR("SetBaudRate"), rcode);
+ return rcode;
+ }
+ rcode = pftdi->SetFlowControl(FTDI_SIO_DISABLE_FLOW_CTRL);
+
+ if (rcode)
+ ErrorMessage<uint8_t>(PSTR("SetFlowControl"), rcode);
+
+ return rcode;
+}
+
+USB Usb;
+//USBHub Hub(&Usb);
+FTDIAsync FtdiAsync;
+FTDI Ftdi(&Usb, &FtdiAsync);
+
+uint32_t next_time;
+
+void setup()
+{
+ Serial.begin( 115200 );
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ Serial.println("Start");
+
+ if (Usb.Init() == -1)
+ Serial.println("OSC did not start.");
+
+ delay( 200 );
+
+ next_time = millis() + 5000;
+}
+
+void loop()
+{
+ Usb.Task();
+
+ if( Usb.getUsbTaskState() == USB_STATE_RUNNING )
+ {
+ uint8_t rcode;
+ char strbuf[] = "DEADBEEF";
+ //char strbuf[] = "The quick brown fox jumps over the lazy dog";
+ //char strbuf[] = "This string contains 61 character to demonstrate FTDI buffers"; //add one symbol to it to see some garbage
+ Serial.print(".");
+
+ rcode = Ftdi.SndData(strlen(strbuf), (uint8_t*)strbuf);
+
+ if (rcode)
+ ErrorMessage<uint8_t>(PSTR("SndData"), rcode);
+
+ delay(50);
+
+ uint8_t buf[64];
+
+ for (uint8_t i=0; i<64; i++)
+ buf[i] = 0;
+
+ uint16_t rcvd = 64;
+ rcode = Ftdi.RcvData(&rcvd, buf);
+
+ if (rcode && rcode != hrNAK)
+ ErrorMessage<uint8_t>(PSTR("Ret"), rcode);
+
+ // The device reserves the first two bytes of data
+ // to contain the current values of the modem and line status registers.
+ if (rcvd > 2)
+ Serial.print((char*)(buf+2));
+
+ delay(10);
+ }
+}
+
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/ftdi/USBFTDILoopback/pgmstrings.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/ftdi/USBFTDILoopback/pgmstrings.h
new file mode 100644
index 000000000..bdb0077ec
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/ftdi/USBFTDILoopback/pgmstrings.h
@@ -0,0 +1,52 @@
+#if !defined(__PGMSTRINGS_H__)
+#define __PGMSTRINGS_H__
+
+#define LOBYTE(x) ((char*)(&(x)))[0]
+#define HIBYTE(x) ((char*)(&(x)))[1]
+#define BUFSIZE 256 //buffer size
+
+
+/* Print strings in Program Memory */
+const char Gen_Error_str[] PROGMEM = "\r\nRequest error. Error code:\t";
+const char Dev_Header_str[] PROGMEM ="\r\nDevice descriptor: ";
+const char Dev_Length_str[] PROGMEM ="\r\nDescriptor Length:\t";
+const char Dev_Type_str[] PROGMEM ="\r\nDescriptor type:\t";
+const char Dev_Version_str[] PROGMEM ="\r\nUSB version:\t\t";
+const char Dev_Class_str[] PROGMEM ="\r\nDevice class:\t\t";
+const char Dev_Subclass_str[] PROGMEM ="\r\nDevice Subclass:\t";
+const char Dev_Protocol_str[] PROGMEM ="\r\nDevice Protocol:\t";
+const char Dev_Pktsize_str[] PROGMEM ="\r\nMax.packet size:\t";
+const char Dev_Vendor_str[] PROGMEM ="\r\nVendor ID:\t\t";
+const char Dev_Product_str[] PROGMEM ="\r\nProduct ID:\t\t";
+const char Dev_Revision_str[] PROGMEM ="\r\nRevision ID:\t\t";
+const char Dev_Mfg_str[] PROGMEM ="\r\nMfg.string index:\t";
+const char Dev_Prod_str[] PROGMEM ="\r\nProd.string index:\t";
+const char Dev_Serial_str[] PROGMEM ="\r\nSerial number index:\t";
+const char Dev_Nconf_str[] PROGMEM ="\r\nNumber of conf.:\t";
+const char Conf_Trunc_str[] PROGMEM ="Total length truncated to 256 bytes";
+const char Conf_Header_str[] PROGMEM ="\r\nConfiguration descriptor:";
+const char Conf_Totlen_str[] PROGMEM ="\r\nTotal length:\t\t";
+const char Conf_Nint_str[] PROGMEM ="\r\nNum.intf:\t\t";
+const char Conf_Value_str[] PROGMEM ="\r\nConf.value:\t\t";
+const char Conf_String_str[] PROGMEM ="\r\nConf.string:\t\t";
+const char Conf_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t";
+const char Conf_Pwr_str[] PROGMEM ="\r\nMax.pwr:\t\t";
+const char Int_Header_str[] PROGMEM ="\r\n\r\nInterface descriptor:";
+const char Int_Number_str[] PROGMEM ="\r\nIntf.number:\t\t";
+const char Int_Alt_str[] PROGMEM ="\r\nAlt.:\t\t\t";
+const char Int_Endpoints_str[] PROGMEM ="\r\nEndpoints:\t\t";
+const char Int_Class_str[] PROGMEM ="\r\nIntf. Class:\t\t";
+const char Int_Subclass_str[] PROGMEM ="\r\nIntf. Subclass:\t\t";
+const char Int_Protocol_str[] PROGMEM ="\r\nIntf. Protocol:\t\t";
+const char Int_String_str[] PROGMEM ="\r\nIntf.string:\t\t";
+const char End_Header_str[] PROGMEM ="\r\n\r\nEndpoint descriptor:";
+const char End_Address_str[] PROGMEM ="\r\nEndpoint address:\t";
+const char End_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t";
+const char End_Pktsize_str[] PROGMEM ="\r\nMax.pkt size:\t\t";
+const char End_Interval_str[] PROGMEM ="\r\nPolling interval:\t";
+const char Unk_Header_str[] PROGMEM = "\r\nUnknown descriptor:";
+const char Unk_Length_str[] PROGMEM ="\r\nLength:\t\t";
+const char Unk_Type_str[] PROGMEM ="\r\nType:\t\t";
+const char Unk_Contents_str[] PROGMEM ="\r\nContents:\t";
+
+#endif // __PGMSTRINGS_H__ \ No newline at end of file
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/hub_demo/hub_demo.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/hub_demo/hub_demo.ino
new file mode 100644
index 000000000..d8b2d4bb7
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/hub_demo/hub_demo.ino
@@ -0,0 +1,345 @@
+#include <usbhub.h>
+#include "pgmstrings.h"
+
+// Satisfy the IDE, which needs to see the include statment in the ino too.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+USB Usb;
+USBHub Hub1(&Usb);
+USBHub Hub2(&Usb);
+USBHub Hub3(&Usb);
+USBHub Hub4(&Usb);
+
+uint32_t next_time;
+
+void PrintAllAddresses(UsbDevice *pdev)
+{
+ UsbDeviceAddress adr;
+ adr.devAddress = pdev->address.devAddress;
+ Serial.print("\r\nAddr:");
+ Serial.print(adr.devAddress, HEX);
+ Serial.print("(");
+ Serial.print(adr.bmHub, HEX);
+ Serial.print(".");
+ Serial.print(adr.bmParent, HEX);
+ Serial.print(".");
+ Serial.print(adr.bmAddress, HEX);
+ Serial.println(")");
+}
+
+void PrintAddress(uint8_t addr)
+{
+ UsbDeviceAddress adr;
+ adr.devAddress = addr;
+ Serial.print("\r\nADDR:\t");
+ Serial.println(adr.devAddress, HEX);
+ Serial.print("DEV:\t");
+ Serial.println(adr.bmAddress, HEX);
+ Serial.print("PRNT:\t");
+ Serial.println(adr.bmParent, HEX);
+ Serial.print("HUB:\t");
+ Serial.println(adr.bmHub, HEX);
+}
+
+void setup()
+{
+ Serial.begin( 115200 );
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ Serial.println("Start");
+
+ if (Usb.Init() == -1)
+ Serial.println("OSC did not start.");
+
+ delay( 200 );
+
+ next_time = millis() + 10000;
+}
+
+byte getdevdescr( byte addr, byte &num_conf );
+
+void PrintDescriptors(uint8_t addr)
+{
+ uint8_t rcode = 0;
+ byte num_conf = 0;
+
+ rcode = getdevdescr( (byte)addr, num_conf );
+ if ( rcode )
+ {
+ printProgStr(Gen_Error_str);
+ print_hex( rcode, 8 );
+ }
+ Serial.print("\r\n");
+
+ for (int i = 0; i < num_conf; i++)
+ {
+ rcode = getconfdescr( addr, i ); // get configuration descriptor
+ if ( rcode )
+ {
+ printProgStr(Gen_Error_str);
+ print_hex(rcode, 8);
+ }
+ Serial.println("\r\n");
+ }
+}
+
+void PrintAllDescriptors(UsbDevice *pdev)
+{
+ Serial.println("\r\n");
+ print_hex(pdev->address.devAddress, 8);
+ Serial.println("\r\n--");
+ PrintDescriptors( pdev->address.devAddress );
+}
+
+void loop()
+{
+ Usb.Task();
+
+ if ( Usb.getUsbTaskState() == USB_STATE_RUNNING )
+ {
+ if ((millis() - next_time) >= 0L)
+ {
+ Usb.ForEachUsbDevice(&PrintAllDescriptors);
+ Usb.ForEachUsbDevice(&PrintAllAddresses);
+
+ while ( 1 ); //stop
+ }
+ }
+}
+
+byte getdevdescr( byte addr, byte &num_conf )
+{
+ USB_DEVICE_DESCRIPTOR buf;
+ byte rcode;
+ rcode = Usb.getDevDescr( addr, 0, 0x12, ( uint8_t *)&buf );
+ if ( rcode ) {
+ return ( rcode );
+ }
+ printProgStr(Dev_Header_str);
+ printProgStr(Dev_Length_str);
+ print_hex( buf.bLength, 8 );
+ printProgStr(Dev_Type_str);
+ print_hex( buf.bDescriptorType, 8 );
+ printProgStr(Dev_Version_str);
+ print_hex( buf.bcdUSB, 16 );
+ printProgStr(Dev_Class_str);
+ print_hex( buf.bDeviceClass, 8 );
+ printProgStr(Dev_Subclass_str);
+ print_hex( buf.bDeviceSubClass, 8 );
+ printProgStr(Dev_Protocol_str);
+ print_hex( buf.bDeviceProtocol, 8 );
+ printProgStr(Dev_Pktsize_str);
+ print_hex( buf.bMaxPacketSize0, 8 );
+ printProgStr(Dev_Vendor_str);
+ print_hex( buf.idVendor, 16 );
+ printProgStr(Dev_Product_str);
+ print_hex( buf.idProduct, 16 );
+ printProgStr(Dev_Revision_str);
+ print_hex( buf.bcdDevice, 16 );
+ printProgStr(Dev_Mfg_str);
+ print_hex( buf.iManufacturer, 8 );
+ printProgStr(Dev_Prod_str);
+ print_hex( buf.iProduct, 8 );
+ printProgStr(Dev_Serial_str);
+ print_hex( buf.iSerialNumber, 8 );
+ printProgStr(Dev_Nconf_str);
+ print_hex( buf.bNumConfigurations, 8 );
+ num_conf = buf.bNumConfigurations;
+ return ( 0 );
+}
+
+void printhubdescr(uint8_t *descrptr, uint8_t addr)
+{
+ HubDescriptor *pHub = (HubDescriptor*) descrptr;
+ uint8_t len = *((uint8_t*)descrptr);
+
+ printProgStr(PSTR("\r\n\r\nHub Descriptor:\r\n"));
+ printProgStr(PSTR("bDescLength:\t\t"));
+ Serial.println(pHub->bDescLength, HEX);
+
+ printProgStr(PSTR("bDescriptorType:\t"));
+ Serial.println(pHub->bDescriptorType, HEX);
+
+ printProgStr(PSTR("bNbrPorts:\t\t"));
+ Serial.println(pHub->bNbrPorts, HEX);
+
+ printProgStr(PSTR("LogPwrSwitchMode:\t"));
+ Serial.println(pHub->LogPwrSwitchMode, BIN);
+
+ printProgStr(PSTR("CompoundDevice:\t\t"));
+ Serial.println(pHub->CompoundDevice, BIN);
+
+ printProgStr(PSTR("OverCurrentProtectMode:\t"));
+ Serial.println(pHub->OverCurrentProtectMode, BIN);
+
+ printProgStr(PSTR("TTThinkTime:\t\t"));
+ Serial.println(pHub->TTThinkTime, BIN);
+
+ printProgStr(PSTR("PortIndicatorsSupported:"));
+ Serial.println(pHub->PortIndicatorsSupported, BIN);
+
+ printProgStr(PSTR("Reserved:\t\t"));
+ Serial.println(pHub->Reserved, HEX);
+
+ printProgStr(PSTR("bPwrOn2PwrGood:\t\t"));
+ Serial.println(pHub->bPwrOn2PwrGood, HEX);
+
+ printProgStr(PSTR("bHubContrCurrent:\t"));
+ Serial.println(pHub->bHubContrCurrent, HEX);
+
+ for (uint8_t i = 7; i < len; i++)
+ print_hex(descrptr[i], 8);
+
+ //for (uint8_t i=1; i<=pHub->bNbrPorts; i++)
+ // PrintHubPortStatus(&Usb, addr, i, 1);
+}
+
+byte getconfdescr( byte addr, byte conf )
+{
+ uint8_t buf[ BUFSIZE ];
+ uint8_t* buf_ptr = buf;
+ byte rcode;
+ byte descr_length;
+ byte descr_type;
+ unsigned int total_length;
+ rcode = Usb.getConfDescr( addr, 0, 4, conf, buf ); //get total length
+ LOBYTE( total_length ) = buf[ 2 ];
+ HIBYTE( total_length ) = buf[ 3 ];
+ if ( total_length > 256 ) { //check if total length is larger than buffer
+ printProgStr(Conf_Trunc_str);
+ total_length = 256;
+ }
+ rcode = Usb.getConfDescr( addr, 0, total_length, conf, buf ); //get the whole descriptor
+ while ( buf_ptr < buf + total_length ) { //parsing descriptors
+ descr_length = *( buf_ptr );
+ descr_type = *( buf_ptr + 1 );
+ switch ( descr_type ) {
+ case ( USB_DESCRIPTOR_CONFIGURATION ):
+ printconfdescr( buf_ptr );
+ break;
+ case ( USB_DESCRIPTOR_INTERFACE ):
+ printintfdescr( buf_ptr );
+ break;
+ case ( USB_DESCRIPTOR_ENDPOINT ):
+ printepdescr( buf_ptr );
+ break;
+ case 0x29:
+ printhubdescr( buf_ptr, addr );
+ break;
+ default:
+ printunkdescr( buf_ptr );
+ break;
+ }//switch( descr_type
+ buf_ptr = ( buf_ptr + descr_length ); //advance buffer pointer
+ }//while( buf_ptr <=...
+ return ( rcode );
+}
+/* prints hex numbers with leading zeroes */
+// copyright, Peter H Anderson, Baltimore, MD, Nov, '07
+// source: http://www.phanderson.com/arduino/arduino_display.html
+void print_hex(int v, int num_places)
+{
+ int mask = 0, n, num_nibbles, digit;
+
+ for (n = 1; n <= num_places; n++) {
+ mask = (mask << 1) | 0x0001;
+ }
+ v = v & mask; // truncate v to specified number of places
+
+ num_nibbles = num_places / 4;
+ if ((num_places % 4) != 0) {
+ ++num_nibbles;
+ }
+ do {
+ digit = ((v >> (num_nibbles - 1) * 4)) & 0x0f;
+ Serial.print(digit, HEX);
+ }
+ while (--num_nibbles);
+}
+/* function to print configuration descriptor */
+void printconfdescr( uint8_t* descr_ptr )
+{
+ USB_CONFIGURATION_DESCRIPTOR* conf_ptr = ( USB_CONFIGURATION_DESCRIPTOR* )descr_ptr;
+ printProgStr(Conf_Header_str);
+ printProgStr(Conf_Totlen_str);
+ print_hex( conf_ptr->wTotalLength, 16 );
+ printProgStr(Conf_Nint_str);
+ print_hex( conf_ptr->bNumInterfaces, 8 );
+ printProgStr(Conf_Value_str);
+ print_hex( conf_ptr->bConfigurationValue, 8 );
+ printProgStr(Conf_String_str);
+ print_hex( conf_ptr->iConfiguration, 8 );
+ printProgStr(Conf_Attr_str);
+ print_hex( conf_ptr->bmAttributes, 8 );
+ printProgStr(Conf_Pwr_str);
+ print_hex( conf_ptr->bMaxPower, 8 );
+ return;
+}
+/* function to print interface descriptor */
+void printintfdescr( uint8_t* descr_ptr )
+{
+ USB_INTERFACE_DESCRIPTOR* intf_ptr = ( USB_INTERFACE_DESCRIPTOR* )descr_ptr;
+ printProgStr(Int_Header_str);
+ printProgStr(Int_Number_str);
+ print_hex( intf_ptr->bInterfaceNumber, 8 );
+ printProgStr(Int_Alt_str);
+ print_hex( intf_ptr->bAlternateSetting, 8 );
+ printProgStr(Int_Endpoints_str);
+ print_hex( intf_ptr->bNumEndpoints, 8 );
+ printProgStr(Int_Class_str);
+ print_hex( intf_ptr->bInterfaceClass, 8 );
+ printProgStr(Int_Subclass_str);
+ print_hex( intf_ptr->bInterfaceSubClass, 8 );
+ printProgStr(Int_Protocol_str);
+ print_hex( intf_ptr->bInterfaceProtocol, 8 );
+ printProgStr(Int_String_str);
+ print_hex( intf_ptr->iInterface, 8 );
+ return;
+}
+/* function to print endpoint descriptor */
+void printepdescr( uint8_t* descr_ptr )
+{
+ USB_ENDPOINT_DESCRIPTOR* ep_ptr = ( USB_ENDPOINT_DESCRIPTOR* )descr_ptr;
+ printProgStr(End_Header_str);
+ printProgStr(End_Address_str);
+ print_hex( ep_ptr->bEndpointAddress, 8 );
+ printProgStr(End_Attr_str);
+ print_hex( ep_ptr->bmAttributes, 8 );
+ printProgStr(End_Pktsize_str);
+ print_hex( ep_ptr->wMaxPacketSize, 16 );
+ printProgStr(End_Interval_str);
+ print_hex( ep_ptr->bInterval, 8 );
+
+ return;
+}
+/*function to print unknown descriptor */
+void printunkdescr( uint8_t* descr_ptr )
+{
+ byte length = *descr_ptr;
+ byte i;
+ printProgStr(Unk_Header_str);
+ printProgStr(Unk_Length_str);
+ print_hex( *descr_ptr, 8 );
+ printProgStr(Unk_Type_str);
+ print_hex( *(descr_ptr + 1 ), 8 );
+ printProgStr(Unk_Contents_str);
+ descr_ptr += 2;
+ for ( i = 0; i < length; i++ ) {
+ print_hex( *descr_ptr, 8 );
+ descr_ptr++;
+ }
+}
+
+
+/* Print a string from Program Memory directly to save RAM */
+void printProgStr(const char* str)
+{
+ char c;
+ if (!str) return;
+ while ((c = pgm_read_byte(str++)))
+ Serial.print(c);
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/hub_demo/pgmstrings.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/hub_demo/pgmstrings.h
new file mode 100644
index 000000000..bdb0077ec
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/hub_demo/pgmstrings.h
@@ -0,0 +1,52 @@
+#if !defined(__PGMSTRINGS_H__)
+#define __PGMSTRINGS_H__
+
+#define LOBYTE(x) ((char*)(&(x)))[0]
+#define HIBYTE(x) ((char*)(&(x)))[1]
+#define BUFSIZE 256 //buffer size
+
+
+/* Print strings in Program Memory */
+const char Gen_Error_str[] PROGMEM = "\r\nRequest error. Error code:\t";
+const char Dev_Header_str[] PROGMEM ="\r\nDevice descriptor: ";
+const char Dev_Length_str[] PROGMEM ="\r\nDescriptor Length:\t";
+const char Dev_Type_str[] PROGMEM ="\r\nDescriptor type:\t";
+const char Dev_Version_str[] PROGMEM ="\r\nUSB version:\t\t";
+const char Dev_Class_str[] PROGMEM ="\r\nDevice class:\t\t";
+const char Dev_Subclass_str[] PROGMEM ="\r\nDevice Subclass:\t";
+const char Dev_Protocol_str[] PROGMEM ="\r\nDevice Protocol:\t";
+const char Dev_Pktsize_str[] PROGMEM ="\r\nMax.packet size:\t";
+const char Dev_Vendor_str[] PROGMEM ="\r\nVendor ID:\t\t";
+const char Dev_Product_str[] PROGMEM ="\r\nProduct ID:\t\t";
+const char Dev_Revision_str[] PROGMEM ="\r\nRevision ID:\t\t";
+const char Dev_Mfg_str[] PROGMEM ="\r\nMfg.string index:\t";
+const char Dev_Prod_str[] PROGMEM ="\r\nProd.string index:\t";
+const char Dev_Serial_str[] PROGMEM ="\r\nSerial number index:\t";
+const char Dev_Nconf_str[] PROGMEM ="\r\nNumber of conf.:\t";
+const char Conf_Trunc_str[] PROGMEM ="Total length truncated to 256 bytes";
+const char Conf_Header_str[] PROGMEM ="\r\nConfiguration descriptor:";
+const char Conf_Totlen_str[] PROGMEM ="\r\nTotal length:\t\t";
+const char Conf_Nint_str[] PROGMEM ="\r\nNum.intf:\t\t";
+const char Conf_Value_str[] PROGMEM ="\r\nConf.value:\t\t";
+const char Conf_String_str[] PROGMEM ="\r\nConf.string:\t\t";
+const char Conf_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t";
+const char Conf_Pwr_str[] PROGMEM ="\r\nMax.pwr:\t\t";
+const char Int_Header_str[] PROGMEM ="\r\n\r\nInterface descriptor:";
+const char Int_Number_str[] PROGMEM ="\r\nIntf.number:\t\t";
+const char Int_Alt_str[] PROGMEM ="\r\nAlt.:\t\t\t";
+const char Int_Endpoints_str[] PROGMEM ="\r\nEndpoints:\t\t";
+const char Int_Class_str[] PROGMEM ="\r\nIntf. Class:\t\t";
+const char Int_Subclass_str[] PROGMEM ="\r\nIntf. Subclass:\t\t";
+const char Int_Protocol_str[] PROGMEM ="\r\nIntf. Protocol:\t\t";
+const char Int_String_str[] PROGMEM ="\r\nIntf.string:\t\t";
+const char End_Header_str[] PROGMEM ="\r\n\r\nEndpoint descriptor:";
+const char End_Address_str[] PROGMEM ="\r\nEndpoint address:\t";
+const char End_Attr_str[] PROGMEM ="\r\nAttr.:\t\t\t";
+const char End_Pktsize_str[] PROGMEM ="\r\nMax.pkt size:\t\t";
+const char End_Interval_str[] PROGMEM ="\r\nPolling interval:\t";
+const char Unk_Header_str[] PROGMEM = "\r\nUnknown descriptor:";
+const char Unk_Length_str[] PROGMEM ="\r\nLength:\t\t";
+const char Unk_Type_str[] PROGMEM ="\r\nType:\t\t";
+const char Unk_Contents_str[] PROGMEM ="\r\nContents:\t";
+
+#endif // __PGMSTRINGS_H__ \ No newline at end of file
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/max_LCD/max_LCD.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/max_LCD/max_LCD.ino
new file mode 100644
index 000000000..6603ab90d
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/max_LCD/max_LCD.ino
@@ -0,0 +1,29 @@
+// Just a copy of the HelloWorld example bundled with the LiquidCrystal library in the Arduino IDE
+
+// HD44780 compatible LCD display via MAX3421E GPOUT support header
+// pinout: D[4-7] -> GPOUT[4-7], RS-> GPOUT[2], E ->GPOUT[3]
+
+#include <max_LCD.h>
+
+// Satisfy IDE, which only needs to see the include statment in the ino.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+USB Usb;
+Max_LCD lcd(&Usb);
+
+void setup() {
+ // Set up the LCD's number of columns and rows:
+ lcd.begin(16, 2);
+ // Print a message to the LCD.
+ lcd.print("Hello, World!");
+}
+
+void loop() {
+ // Set the cursor to column 0, line 1 (note: line 1 is the second row, since counting begins with 0):
+ lcd.setCursor(0, 1);
+ // Print the number of seconds since reset:
+ lcd.print(millis() / 1000);
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_gprs_terminal/pl2303_gprs_terminal.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_gprs_terminal/pl2303_gprs_terminal.ino
new file mode 100644
index 000000000..7c4c9f6cb
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_gprs_terminal/pl2303_gprs_terminal.ino
@@ -0,0 +1,101 @@
+/* Arduino terminal for PL2303 USB to serial converter and DealeXtreme GPRS modem. */
+/* USB support */
+#include <usbhub.h>
+/* CDC support */
+#include <cdcacm.h>
+#include <cdcprolific.h>
+
+// Satisfy the IDE, which needs to see the include statment in the ino too.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+class PLAsyncOper : public CDCAsyncOper
+{
+public:
+ uint8_t OnInit(ACM *pacm);
+};
+
+uint8_t PLAsyncOper::OnInit(ACM *pacm)
+{
+ uint8_t rcode;
+
+ // Set DTR = 1
+ rcode = pacm->SetControlLineState(1);
+
+ if (rcode)
+ {
+ ErrorMessage<uint8_t>(PSTR("SetControlLineState"), rcode);
+ return rcode;
+ }
+
+ LINE_CODING lc;
+ //lc.dwDTERate = 9600;
+ lc.dwDTERate = 115200;
+ lc.bCharFormat = 0;
+ lc.bParityType = 0;
+ lc.bDataBits = 8;
+
+ rcode = pacm->SetLineCoding(&lc);
+
+ if (rcode)
+ ErrorMessage<uint8_t>(PSTR("SetLineCoding"), rcode);
+
+ return rcode;
+}
+USB Usb;
+//USBHub Hub(&Usb);
+PLAsyncOper AsyncOper;
+PL2303 Pl(&Usb, &AsyncOper);
+
+void setup()
+{
+ Serial.begin( 115200 );
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ Serial.println("Start");
+
+ if (Usb.Init() == -1)
+ Serial.println("OSCOKIRQ failed to assert");
+
+ delay( 200 );
+}
+
+void loop()
+{
+ Usb.Task();
+
+ if( Usb.getUsbTaskState() == USB_STATE_RUNNING )
+ {
+ uint8_t rcode;
+
+ /* reading the keyboard */
+ if(Serial.available()) {
+ uint8_t data= Serial.read();
+
+ /* sending to the phone */
+ rcode = Pl.SndData(1, &data);
+ if (rcode)
+ ErrorMessage<uint8_t>(PSTR("SndData"), rcode);
+ }//if(Serial.available()...
+
+ /* reading the converter */
+ /* buffer size must be greater or equal to max.packet size */
+ /* it it set to 64 (largest possible max.packet size) here, can be tuned down
+ for particular endpoint */
+ uint8_t buf[64];
+ uint16_t rcvd = 64;
+ rcode = Pl.RcvData(&rcvd, buf);
+ if (rcode && rcode != hrNAK)
+ ErrorMessage<uint8_t>(PSTR("Ret"), rcode);
+
+ if( rcvd ) { //more than zero bytes received
+ for(uint16_t i=0; i < rcvd; i++ ) {
+ Serial.print((char)buf[i]); //printing on the screen
+ }
+ }//if( rcvd ...
+ }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING..
+}
+
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_gps/pl2303_gps.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_gps/pl2303_gps.ino
new file mode 100644
index 000000000..e8c8a0223
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_gps/pl2303_gps.ino
@@ -0,0 +1,88 @@
+/* USB Host to PL2303-based USB GPS unit interface */
+/* Navibee GM720 receiver - Sirf Star III */
+/* USB support */
+#include <usbhub.h>
+/* CDC support */
+#include <cdcacm.h>
+#include <cdcprolific.h>
+
+// Satisfy the IDE, which needs to see the include statment in the ino too.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+class PLAsyncOper : public CDCAsyncOper {
+public:
+ uint8_t OnInit(ACM *pacm);
+};
+
+uint8_t PLAsyncOper::OnInit(ACM *pacm) {
+ uint8_t rcode;
+
+ // Set DTR = 1
+ rcode = pacm->SetControlLineState(1);
+
+ if(rcode) {
+ ErrorMessage<uint8_t>(PSTR("SetControlLineState"), rcode);
+ return rcode;
+ }
+
+ LINE_CODING lc;
+ lc.dwDTERate = 4800; //default serial speed of GPS unit
+ lc.bCharFormat = 0;
+ lc.bParityType = 0;
+ lc.bDataBits = 8;
+
+ rcode = pacm->SetLineCoding(&lc);
+
+ if(rcode)
+ ErrorMessage<uint8_t>(PSTR("SetLineCoding"), rcode);
+
+ return rcode;
+}
+
+USB Usb;
+USBHub Hub(&Usb);
+PLAsyncOper AsyncOper;
+PL2303 Pl(&Usb, &AsyncOper);
+uint32_t read_delay;
+#define READ_DELAY 100
+
+void setup() {
+ Serial.begin(115200);
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ Serial.println("Start");
+
+ if(Usb.Init() == -1)
+ Serial.println("OSCOKIRQ failed to assert");
+
+ delay(200);
+}
+
+void loop() {
+ uint8_t rcode;
+ uint8_t buf[64]; //serial buffer equals Max.packet size of bulk-IN endpoint
+ uint16_t rcvd = 64;
+
+ Usb.Task();
+
+ if(Pl.isReady()) {
+ /* reading the GPS */
+ if((long)(millis() - read_delay) >= 0L) {
+ read_delay += READ_DELAY;
+ rcode = Pl.RcvData(&rcvd, buf);
+ if(rcode && rcode != hrNAK)
+ ErrorMessage<uint8_t>(PSTR("Ret"), rcode);
+ if(rcvd) { //more than zero bytes received
+ for(uint16_t i = 0; i < rcvd; i++) {
+ Serial.print((char)buf[i]); //printing on the screen
+ }//for( uint16_t i=0; i < rcvd; i++...
+ }//if( rcvd
+ }//if( read_delay > millis()...
+ }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING..
+}
+
+
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_tinygps/pl2303_tinygps.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_tinygps/pl2303_tinygps.ino
new file mode 100644
index 000000000..d527eabe0
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_tinygps/pl2303_tinygps.ino
@@ -0,0 +1,217 @@
+/* USB Host to PL2303-based USB GPS unit interface */
+/* Navibee GM720 receiver - Sirf Star III */
+/* Mikal Hart's TinyGPS library */
+/* test_with_gps_device library example modified for PL2302 access */
+
+/* USB support */
+#include <usbhub.h>
+
+/* CDC support */
+#include <cdcacm.h>
+#include <cdcprolific.h>
+
+#include <TinyGPS.h>
+
+// Satisfy the IDE, which needs to see the include statment in the ino too.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+/* This sample code demonstrates the normal use of a TinyGPS object.
+ Modified to be used with USB Host Shield Library r2.0
+ and USB Host Shield 2.0
+*/
+
+class PLAsyncOper : public CDCAsyncOper
+{
+public:
+ uint8_t OnInit(ACM *pacm);
+};
+
+uint8_t PLAsyncOper::OnInit(ACM *pacm)
+{
+ uint8_t rcode;
+
+ // Set DTR = 1
+ rcode = pacm->SetControlLineState(1);
+
+ if (rcode) {
+ ErrorMessage<uint8_t>(PSTR("SetControlLineState"), rcode);
+ return rcode;
+ }
+
+ LINE_CODING lc;
+ lc.dwDTERate = 4800; //default serial speed of GPS unit
+ lc.bCharFormat = 0;
+ lc.bParityType = 0;
+ lc.bDataBits = 8;
+
+ rcode = pacm->SetLineCoding(&lc);
+
+ if (rcode) {
+ ErrorMessage<uint8_t>(PSTR("SetLineCoding"), rcode);
+ }
+
+ return rcode;
+}
+
+USB Usb;
+//USBHub Hub(&Usb);
+PLAsyncOper AsyncOper;
+PL2303 Pl(&Usb, &AsyncOper);
+TinyGPS gps;
+
+void gpsdump(TinyGPS &gps);
+bool feedgps();
+void printFloat(double f, int digits = 2);
+
+void setup()
+{
+
+ Serial.begin(115200);
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+
+ Serial.print("Testing TinyGPS library v. "); Serial.println(TinyGPS::library_version());
+ Serial.println("by Mikal Hart");
+ Serial.println();
+ Serial.print("Sizeof(gpsobject) = "); Serial.println(sizeof(TinyGPS));
+ Serial.println();
+ /* USB Initialization */
+ if (Usb.Init() == -1) {
+ Serial.println("OSCOKIRQ failed to assert");
+ }
+
+ delay( 200 );
+}
+
+void loop()
+{
+ Usb.Task();
+
+ if( Pl.isReady()) {
+
+ bool newdata = false;
+ unsigned long start = millis();
+
+ // Every 5 seconds we print an update
+ while (millis() - start < 5000) {
+ if( feedgps()) {
+ newdata = true;
+ }
+ }//while (millis()...
+
+ if (newdata) {
+ Serial.println("Acquired Data");
+ Serial.println("-------------");
+ gpsdump(gps);
+ Serial.println("-------------");
+ Serial.println();
+ }//if( newdata...
+ }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING...
+}
+
+void printFloat(double number, int digits)
+{
+ // Handle negative numbers
+ if (number < 0.0)
+ {
+ Serial.print('-');
+ number = -number;
+ }
+
+ // Round correctly so that print(1.999, 2) prints as "2.00"
+ double rounding = 0.5;
+ for (uint8_t i=0; i<digits; ++i)
+ rounding /= 10.0;
+
+ number += rounding;
+
+ // Extract the integer part of the number and print it
+ unsigned long int_part = (unsigned long)number;
+ double remainder = number - (double)int_part;
+ Serial.print(int_part);
+
+ // Print the decimal point, but only if there are digits beyond
+ if (digits > 0)
+ Serial.print(".");
+
+ // Extract digits from the remainder one at a time
+ while (digits-- > 0)
+ {
+ remainder *= 10.0;
+ int toPrint = int(remainder);
+ Serial.print(toPrint);
+ remainder -= toPrint;
+ }
+}
+
+void gpsdump(TinyGPS &gps)
+{
+ long lat, lon;
+ float flat, flon;
+ unsigned long age, date, time, chars;
+ int year;
+ byte month, day, hour, minute, second, hundredths;
+ unsigned short sentences, failed;
+
+ gps.get_position(&lat, &lon, &age);
+ Serial.print("Lat/Long(10^-5 deg): "); Serial.print(lat); Serial.print(", "); Serial.print(lon);
+ Serial.print(" Fix age: "); Serial.print(age); Serial.println("ms.");
+
+ feedgps(); // If we don't feed the gps during this long routine, we may drop characters and get checksum errors
+
+ gps.f_get_position(&flat, &flon, &age);
+ Serial.print("Lat/Long(float): "); printFloat(flat, 5); Serial.print(", "); printFloat(flon, 5);
+ Serial.print(" Fix age: "); Serial.print(age); Serial.println("ms.");
+
+ feedgps();
+
+ gps.get_datetime(&date, &time, &age);
+ Serial.print("Date(ddmmyy): "); Serial.print(date); Serial.print(" Time(hhmmsscc): "); Serial.print(time);
+ Serial.print(" Fix age: "); Serial.print(age); Serial.println("ms.");
+
+ feedgps();
+
+ gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
+ Serial.print("Date: "); Serial.print(static_cast<int>(month)); Serial.print("/"); Serial.print(static_cast<int>(day)); Serial.print("/"); Serial.print(year);
+ Serial.print(" Time: "); Serial.print(static_cast<int>(hour)); Serial.print(":"); Serial.print(static_cast<int>(minute)); Serial.print(":"); Serial.print(static_cast<int>(second)); Serial.print("."); Serial.print(static_cast<int>(hundredths));
+ Serial.print(" Fix age: "); Serial.print(age); Serial.println("ms.");
+
+ feedgps();
+
+ Serial.print("Alt(cm): "); Serial.print(gps.altitude()); Serial.print(" Course(10^-2 deg): "); Serial.print(gps.course()); Serial.print(" Speed(10^-2 knots): "); Serial.println(gps.speed());
+ Serial.print("Alt(float): "); printFloat(gps.f_altitude()); Serial.print(" Course(float): "); printFloat(gps.f_course()); Serial.println();
+ Serial.print("Speed(knots): "); printFloat(gps.f_speed_knots()); Serial.print(" (mph): "); printFloat(gps.f_speed_mph());
+ Serial.print(" (mps): "); printFloat(gps.f_speed_mps()); Serial.print(" (kmph): "); printFloat(gps.f_speed_kmph()); Serial.println();
+
+ feedgps();
+
+ gps.stats(&chars, &sentences, &failed);
+ Serial.print("Stats: characters: "); Serial.print(chars); Serial.print(" sentences: "); Serial.print(sentences); Serial.print(" failed checksum: "); Serial.println(failed);
+}
+
+bool feedgps()
+{
+ uint8_t rcode;
+ uint8_t buf[64]; //serial buffer equals Max.packet size of bulk-IN endpoint
+ uint16_t rcvd = 64;
+ {
+ /* reading the GPS */
+ rcode = Pl.RcvData(&rcvd, buf);
+ if (rcode && rcode != hrNAK)
+ ErrorMessage<uint8_t>(PSTR("Ret"), rcode);
+ rcode = false;
+ if( rcvd ) { //more than zero bytes received
+ for( uint16_t i=0; i < rcvd; i++ ) {
+ if( gps.encode((char)buf[i])) { //feed a character to gps object
+ rcode = true;
+ }//if( gps.encode(buf[i]...
+ }//for( uint16_t i=0; i < rcvd; i++...
+ }//if( rcvd...
+ }
+ return( rcode );
+}
+
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_xbee_terminal/pl2303_xbee_terminal.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_xbee_terminal/pl2303_xbee_terminal.ino
new file mode 100644
index 000000000..67b7dab60
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/pl2303/pl2303_xbee_terminal/pl2303_xbee_terminal.ino
@@ -0,0 +1,117 @@
+/* Arduino terminal for PL2303 USB to serial converter and XBee radio. */
+/* Inserts linefeed after carriage return in data sent to and received from Xbee */
+/* USB support */
+#include <usbhub.h>
+/* CDC support */
+#include <cdcacm.h>
+#include <cdcprolific.h>
+
+// Satisfy the IDE, which needs to see the include statment in the ino too.
+#ifdef dobogusinclude
+#include <spi4teensy3.h>
+#include <SPI.h>
+#endif
+
+class PLAsyncOper : public CDCAsyncOper
+{
+public:
+ uint8_t OnInit(ACM *pacm);
+};
+
+uint8_t PLAsyncOper::OnInit(ACM *pacm)
+{
+ uint8_t rcode;
+
+ // Set DTR = 1
+ rcode = pacm->SetControlLineState(1);
+
+ if (rcode)
+ {
+ ErrorMessage<uint8_t>(PSTR("SetControlLineState"), rcode);
+ return rcode;
+ }
+
+ LINE_CODING lc;
+ lc.dwDTERate = 115200;
+ lc.bCharFormat = 0;
+ lc.bParityType = 0;
+ lc.bDataBits = 8;
+
+ rcode = pacm->SetLineCoding(&lc);
+
+ if (rcode)
+ ErrorMessage<uint8_t>(PSTR("SetLineCoding"), rcode);
+
+ return rcode;
+}
+USB Usb;
+//USBHub Hub(&Usb);
+PLAsyncOper AsyncOper;
+PL2303 Pl(&Usb, &AsyncOper);
+
+void setup()
+{
+ Serial.begin( 115200 );
+#if !defined(__MIPSEL__)
+ while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
+#endif
+ Serial.println("Start");
+
+ if (Usb.Init() == -1)
+ Serial.println("OSCOKIRQ failed to assert");
+
+ delay( 200 );
+}
+
+void loop()
+{
+ Usb.Task();
+
+ if( Usb.getUsbTaskState() == USB_STATE_RUNNING )
+ {
+ uint8_t rcode;
+
+ /* reading the keyboard */
+ if(Serial.available()) {
+ uint8_t data= Serial.read();
+
+ if ( data == '\r' ) {
+ Serial.print("\r\n"); //insert linefeed
+ }
+ else {
+ Serial.print( data ); //echo back to the screen
+ }
+
+ /* sending to the phone */
+ rcode = Pl.SndData(1, &data);
+ if (rcode)
+ ErrorMessage<uint8_t>(PSTR("SndData"), rcode);
+ }//if(Serial.available()...
+
+ delay(50);
+
+ /* reading the converter */
+ /* buffer size must be greater or equal to max.packet size */
+ /* it it set to 64 (largest possible max.packet size) here, can be tuned down
+ for particular endpoint */
+ uint8_t buf[64];
+ uint16_t rcvd = 64;
+ rcode = Pl.RcvData(&rcvd, buf);
+ if (rcode && rcode != hrNAK)
+ ErrorMessage<uint8_t>(PSTR("Ret"), rcode);
+
+ if( rcvd ) { //more than zero bytes received
+ for(uint16_t i=0; i < rcvd; i++ ) {
+ if( buf[i] =='\r' ) {
+ Serial.print("\r\n"); //insert linefeed
+ }
+ else {
+ Serial.print((char)buf[i]); //printing on the screen
+ }
+ }
+ }
+ delay(10);
+ }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING..
+}
+
+
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/testusbhostFAT/Makefile b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/testusbhostFAT/Makefile
new file mode 100644
index 000000000..8a12ddc04
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/testusbhostFAT/Makefile
@@ -0,0 +1,64 @@
+#
+# These are set for a mega 1280 + quadram plus my serial patch.
+# If you lack quadram, or want to disable LFN, just change _FS_TINY=1 _USE_LFN=0
+#
+# If your board is a mega 2560 comment out the following two lines
+BOARD = mega
+
+BOARD_SUB = mega.menu.cpu.atmega1280
+PROGRAMMER = arduino
+
+# ...and then uncomment out the following two lines
+#BOARD_SUB = mega.menu.cpu.atmega2560
+#PROGRAMMER = wiring
+
+#BOARD = teensypp2
+#BOARD = teensy3
+#BOARD = teensy31
+
+# set your Arduino tty port here
+PORT = /dev/ttyUSB0
+
+EXTRA_FLAGS = -D _USE_LFN=3
+
+# change to 0 if you have quadram to take advantage of caching FAT
+EXTRA_FLAGS += -D _FS_TINY=1
+
+
+EXTRA_FLAGS += -D _MAX_SS=512
+
+
+# Don't worry if you don't have external RAM, xmem2 detects this situation.
+# You *WILL* be wanting to get some kind of external ram on your mega in order to
+# do anything that is intense.
+EXTRA_FLAGS += -D EXT_RAM_STACK=1
+EXTRA_FLAGS += -D EXT_RAM_HEAP=1
+
+
+# These are no longer needed for the demo to work.
+# In the event you need more ram, uncomment these 3 lines.
+#EXTRA_FLAGS += -D DISABLE_SERIAL1
+#EXTRA_FLAGS += -D DISABLE_SERIAL2
+#EXTRA_FLAGS += -D DISABLE_SERIAL3
+
+#
+# Advanced debug on Serial3
+#
+
+# uncomment the next two to enable debug on Serial3
+EXTRA_FLAGS += -D USB_HOST_SERIAL=Serial3
+#EXTRA_FLAGS += -D DEBUG_USB_HOST
+
+# The following are the libraries used.
+LIB_DIRS += ../../
+LIB_DIRS += ../testusbhostFAT/xmem2
+LIB_DIRS += ../testusbhostFAT/generic_storage
+LIB_DIRS += ../testusbhostFAT/RTClib
+LIB_DIRS += $(ARD_HOME)/libraries/Wire
+LIB_DIRS += $(ARD_HOME)/libraries/Wire/utility
+LIB_DIRS += $(ARD_HOME)/hardware/arduino/$(BUILD_ARCH)/libraries/Wire
+LIB_DIRS += $(ARD_HOME)/hardware/arduino/$(BUILD_ARCH)/libraries/Wire/utility
+LIB_DIRS += $(ARD_HOME)/hardware/arduino/$(BUILD_ARCH)/libraries/SPI
+
+# And finally, the part that brings everything together for you.
+include Arduino_Makefile_master/_Makefile.master
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/testusbhostFAT/readme.md b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/testusbhostFAT/readme.md
new file mode 100644
index 000000000..d8b4296b1
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/testusbhostFAT/readme.md
@@ -0,0 +1,29 @@
+This small sketch tests the USB host shield mass storage library.
+
+__Note:__ This will not run a Arduino Uno due to the limited ram available in the ATmega328p.
+
+The Arduino Mega (ATmega1280) and the Arduino Mega 2560 (ATmega2560) are confirmed to work with this test code.
+
+To compile this example you will need the following libraries as well:
+
+* [xmem2](https://github.com/xxxajk/xmem2)
+* [generic_storage FATfs](https://github.com/xxxajk/generic_storage)
+* [RTClib](https://github.com/xxxajk/RTClib)
+
+The following shield is recommended for larger projects: <http://ruggedcircuits.com/html/quadram.html>.
+
+You may use the bundled [Makefile](Makefile) to compile the code instead of the Arduino IDE if you have problems or want a smaller binary. The master makefile is bundled as a submodule, but can also be downloaded manually at the following link: <https://github.com/xxxajk/Arduino_Makefile_master>.
+
+To download the USB Host library and all the needed libraries for this test.
+
+Run the following command in a terminal application:
+
+```
+git clone --recursive https://github.com/felis/USB_Host_Shield_2.0
+```
+
+If you want to update all the submodules run:
+
+```
+git submodule foreach --recursive git pull origin master
+```
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/testusbhostFAT/testusbhostFAT.ino b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/testusbhostFAT/testusbhostFAT.ino
new file mode 100644
index 000000000..e8b9cd359
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/examples/testusbhostFAT/testusbhostFAT.ino
@@ -0,0 +1,736 @@
+/*
+ * Mega + USB storage + optional DS1307 + optional expansion RAM + funky status LED,
+ * Includes interactive debug level setting, and supports hot-plug.
+ *
+ * IMPORTANT! PLEASE USE Arduino 1.0.5 or better!
+ * Older versions HAVE MAJOR BUGS AND WILL NOT WORK AT ALL!
+ * Use of gcc-avr and lib-c that is newer than the Arduino version is even better.
+ * If you experience random crashes, use make.
+ * The options that the IDE use can generate bad code and cause the AVR to crash.
+ *
+ * This sketch requires the following libraries:
+ * https://github.com/felis/USB_Host_Shield_2.0 Install as 'USB_Host_Shield_2_0'
+ * https://github.com/xxxajk/xmem2 Install as 'xmem', provides memory services.
+ * https://github.com/xxxajk/generic_storage provides access to FAT file system.
+ * https://github.com/xxxajk/RTClib provides access to DS1307, or fake clock.
+ *
+ * Optional, to use the Makefile (Recommended! See above!):
+ * https://github.com/xxxajk/Arduino_Makefile_master
+ *
+ */
+
+/////////////////////////////////////////////////////////////
+// Please Note: //
+// This section is for info with the Arduino IDE ONLY. //
+// Unfortunately due to short sightedness of the Arduino //
+// code team, that you must set the following in the //
+// respective libraries. //
+// Changing them here will have _NO_ effect! //
+/////////////////////////////////////////////////////////////
+
+// Uncomment to enable debugging
+//#define DEBUG_USB_HOST
+// This is where stderr/USB debugging goes to
+//#define USB_HOST_SERIAL Serial3
+
+// If you have external memory, setting this to 0 enables FAT table caches.
+// The 0 setting is recommended only if you have external memory.
+//#define _FS_TINY 1
+
+//#define _USE_LFN 3
+//#define _MAX_SS 512
+
+
+/////////////////////////////////////////////////////////////
+// End of Arduino IDE specific information //
+/////////////////////////////////////////////////////////////
+
+// You can set this to 0 if you are not using a USB hub.
+// It will save a little bit of flash and RAM.
+// Set to 1 if you want to use a hub.
+#define WANT_HUB_TEST 1
+
+// this is for XMEM2
+#define EXT_RAM_STACK 1
+#define EXT_RAM_HEAP 1
+#define LOAD_XMEM
+
+#if defined(CORE_TEENSY) && !defined(_AVR_)
+#include <xmem.h>
+#include <spi4teensy3.h>
+#endif
+
+#if defined(__AVR__)
+#include <xmem.h>
+#include <SPI.h>
+#elif defined(ARDUINO_ARCH_SAM)
+#include <SPI.h>
+#endif
+
+#if WANT_HUB_TEST
+#include <usbhub.h>
+#endif
+#include <Wire.h>
+#define LOAD_RTCLIB
+#include <RTClib.h>
+#include <masstorage.h>
+#include <Storage.h>
+#include <PCpartition/PCPartition.h>
+#include <avr/interrupt.h>
+#include <FAT/FAT.h>
+#include <stdio.h>
+#if defined(__AVR__)
+static FILE tty_stdio;
+static FILE tty_stderr;
+volatile uint32_t LEDnext_time; // fade timeout
+volatile uint32_t HEAPnext_time; // when to print out next heap report
+volatile int brightness = 0; // how bright the LED is
+volatile int fadeAmount = 80; // how many points to fade the LED by
+#endif
+
+USB Usb;
+
+volatile uint8_t current_state = 1;
+volatile uint8_t last_state = 0;
+volatile bool fatready = false;
+volatile bool partsready = false;
+volatile bool notified = false;
+volatile bool runtest = false;
+volatile bool usbon = false;
+volatile uint32_t usbon_time;
+volatile bool change = false;
+volatile bool reportlvl = false;
+int cpart = 0;
+PCPartition *PT;
+
+#if WANT_HUB_TEST
+#define MAX_HUBS 1
+USBHub *Hubs[MAX_HUBS];
+#endif
+
+static PFAT *Fats[_VOLUMES];
+static part_t parts[_VOLUMES];
+static storage_t sto[_VOLUMES];
+
+/*make sure this is a power of two. */
+#define mbxs 128
+static uint8_t My_Buff_x[mbxs]; /* File read buffer */
+
+#if defined(__AVR__)
+
+#define prescale1 ((1 << WGM12) | (1 << CS10))
+#define prescale8 ((1 << WGM12) | (1 << CS11))
+#define prescale64 ((1 << WGM12) | (1 << CS10) | (1 << CS11))
+#define prescale256 ((1 << WGM12) | (1 << CS12))
+#define prescale1024 ((1 << WGM12) | (1 << CS12) | (1 << CS10))
+
+extern "C" {
+ extern unsigned int freeHeap();
+}
+static int tty_stderr_putc(char c, FILE *t) {
+ USB_HOST_SERIAL.write(c);
+ return 0;
+}
+
+static int __attribute__((unused)) tty_stderr_flush(FILE *t) {
+ USB_HOST_SERIAL.flush();
+ return 0;
+}
+
+static int tty_std_putc(char c, FILE *t) {
+ Serial.write(c);
+ return 0;
+}
+
+static int tty_std_getc(FILE *t) {
+ while(!Serial.available());
+ return Serial.read();
+}
+
+static int __attribute__((unused)) tty_std_flush(FILE *t) {
+ Serial.flush();
+ return 0;
+}
+
+#else
+// Supposedly the DUE has stdio already pointing to serial...
+#if !defined(ARDUINO_ARCH_SAM)
+// But newlib needs this...
+extern "C" {
+ int _write(int fd, const char *ptr, int len) {
+ int j;
+ for(j = 0; j < len; j++) {
+ if(fd == 1)
+ Serial.write(*ptr++);
+ else if(fd == 2)
+ USB_HOST_SERIAL.write(*ptr++);
+ }
+ return len;
+ }
+
+ int _read(int fd, char *ptr, int len) {
+ if(len > 0 && fd == 0) {
+ while(!Serial.available());
+ *ptr = Serial.read();
+ return 1;
+ }
+ return 0;
+ }
+
+#include <sys/stat.h>
+
+ int _fstat(int fd, struct stat *st) {
+ memset(st, 0, sizeof (*st));
+ st->st_mode = S_IFCHR;
+ st->st_blksize = 1024;
+ return 0;
+ }
+
+ int _isatty(int fd) {
+ return (fd < 3) ? 1 : 0;
+ }
+}
+#endif // !defined(ARDUINO_ARCH_SAM)
+#endif
+
+void setup() {
+ bool serr = false;
+ for(int i = 0; i < _VOLUMES; i++) {
+ Fats[i] = NULL;
+ sto[i].private_data = new pvt_t;
+ ((pvt_t *)sto[i].private_data)->B = 255; // impossible
+ }
+ // Set this to higher values to enable more debug information
+ // minimum 0x00, maximum 0xff
+ UsbDEBUGlvl = 0x81;
+
+#if !defined(CORE_TEENSY) && defined(__AVR__)
+ // make LED pin as an output:
+ pinMode(LED_BUILTIN, OUTPUT);
+ pinMode(2, OUTPUT);
+ // Ensure TX is off
+ _SFR_BYTE(UCSR0B) &= ~_BV(TXEN0);
+ // Initialize 'debug' serial port
+ USB_HOST_SERIAL.begin(115200);
+ // Do not start primary Serial port if already started.
+ if(bit_is_clear(UCSR0B, TXEN0)) {
+ Serial.begin(115200);
+ serr = true;
+ }
+
+
+ // Blink LED
+ delay(500);
+ analogWrite(LED_BUILTIN, 255);
+ delay(500);
+ analogWrite(LED_BUILTIN, 0);
+ delay(500);
+#else
+ while(!Serial);
+ Serial.begin(115200); // On the Teensy 3.x we get a delay at least!
+#endif
+#if defined(__AVR__)
+ // Set up stdio/stderr
+ tty_stdio.put = tty_std_putc;
+ tty_stdio.get = tty_std_getc;
+ tty_stdio.flags = _FDEV_SETUP_RW;
+ tty_stdio.udata = 0;
+
+ tty_stderr.put = tty_stderr_putc;
+ tty_stderr.get = NULL;
+ tty_stderr.flags = _FDEV_SETUP_WRITE;
+ tty_stderr.udata = 0;
+
+ stdout = &tty_stdio;
+ stdin = &tty_stdio;
+ stderr = &tty_stderr;
+#endif
+ printf_P(PSTR("\r\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nStart\r\n"));
+ printf_P(PSTR("Current UsbDEBUGlvl %02x\r\n"), UsbDEBUGlvl);
+ printf_P(PSTR("'+' and '-' increase/decrease by 0x01\r\n"));
+ printf_P(PSTR("'.' and ',' increase/decrease by 0x10\r\n"));
+ printf_P(PSTR("'t' will run a 10MB write/read test and print out the time it took.\r\n"));
+ printf_P(PSTR("'e' will toggle vbus off for a few moments.\r\n\r\n"));
+ printf_P(PSTR("Long filename support: "
+#if _USE_LFN
+ "Enabled"
+#else
+ "Disabled"
+#endif
+ "\r\n"));
+ if(serr) {
+ fprintf_P(stderr, PSTR("\r\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nStart\r\n"));
+ fprintf_P(stderr, PSTR("Current UsbDEBUGlvl %02x\r\n"), UsbDEBUGlvl);
+ fprintf_P(stderr, PSTR("Long filename support: "
+#if _USE_LFN
+ "Enabled"
+#else
+ "Disabled"
+#endif
+ "\r\n"));
+ }
+
+#if !defined(CORE_TEENSY) && defined(__AVR__)
+ analogWrite(LED_BUILTIN, 255);
+ delay(500);
+ analogWrite(LED_BUILTIN, 0);
+ delay(500);
+ analogWrite(LED_BUILTIN, 255);
+ delay(500);
+ analogWrite(LED_BUILTIN, 0);
+ delay(500);
+ analogWrite(LED_BUILTIN, 255);
+ delay(500);
+ analogWrite(LED_BUILTIN, 0);
+ delay(500);
+
+ LEDnext_time = millis() + 1;
+#if EXT_RAM
+ printf_P(PSTR("Total EXT RAM banks %i\r\n"), xmem::getTotalBanks());
+#endif
+ printf_P(PSTR("Available heap: %u Bytes\r\n"), freeHeap());
+ printf_P(PSTR("SP %x\r\n"), (uint8_t *)(SP));
+#endif
+
+ // Even though I'm not going to actually be deleting,
+ // I want to be able to have slightly more control.
+ // Besides, it is easier to initialize stuff...
+#if WANT_HUB_TEST
+ for(int i = 0; i < MAX_HUBS; i++) {
+ Hubs[i] = new USBHub(&Usb);
+#if defined(__AVR__)
+ printf_P(PSTR("Available heap: %u Bytes\r\n"), freeHeap());
+#endif
+ }
+#endif
+ // Initialize generic storage. This must be done before USB starts.
+ Init_Generic_Storage();
+
+ while(Usb.Init(1000) == -1) {
+ printf_P(PSTR("No USB HOST Shield?\r\n"));
+ Notify(PSTR("OSC did not start."), 0x40);
+ }
+
+#if !defined(CORE_TEENSY) && defined(__AVR__)
+ cli();
+ TCCR3A = 0;
+ TCCR3B = 0;
+ // (0.01/(1/((16 *(10^6)) / 8))) - 1 = 19999
+ OCR3A = 19999;
+ TCCR3B |= prescale8;
+ TIMSK3 |= (1 << OCIE1A);
+ sei();
+
+ HEAPnext_time = millis() + 10000;
+#endif
+#if defined(__AVR__)
+ HEAPnext_time = millis() + 10000;
+#endif
+}
+
+void serialEvent() {
+ // Adjust UsbDEBUGlvl level on-the-fly.
+ // + to increase, - to decrease, * to display current level.
+ // . to increase by 16, , to decrease by 16
+ // e to flick VBUS
+ // * to report debug level
+ if(Serial.available()) {
+ int inByte = Serial.read();
+ switch(inByte) {
+ case '+':
+ if(UsbDEBUGlvl < 0xff) UsbDEBUGlvl++;
+ reportlvl = true;
+ break;
+ case '-':
+ if(UsbDEBUGlvl > 0x00) UsbDEBUGlvl--;
+ reportlvl = true;
+ break;
+ case '.':
+ if(UsbDEBUGlvl < 0xf0) UsbDEBUGlvl += 16;
+ reportlvl = true;
+ break;
+ case ',':
+ if(UsbDEBUGlvl > 0x0f) UsbDEBUGlvl -= 16;
+ reportlvl = true;
+ break;
+ case '*':
+ reportlvl = true;
+ break;
+ case 't':
+ runtest = true;
+ break;
+ case 'e':
+ change = true;
+ usbon = false;
+ break;
+ }
+ }
+}
+
+#if !defined(CORE_TEENSY) && defined(__AVR__)
+// ALL teensy versions LACK PWM ON LED
+
+ISR(TIMER3_COMPA_vect) {
+ if((long)(millis() - LEDnext_time) >= 0L) {
+ LEDnext_time = millis() + 30;
+
+ // set the brightness of LED
+ analogWrite(LED_BUILTIN, brightness);
+
+ // change the brightness for next time through the loop:
+ brightness = brightness + fadeAmount;
+
+ // reverse the direction of the fading at the ends of the fade:
+ if(brightness <= 0) {
+ brightness = 0;
+ fadeAmount = -fadeAmount;
+ }
+ if(brightness >= 255) {
+ brightness = 255;
+ fadeAmount = -fadeAmount;
+ }
+ }
+}
+#endif
+
+bool isfat(uint8_t t) {
+ return (t == 0x01 || t == 0x04 || t == 0x06 || t == 0x0b || t == 0x0c || t == 0x0e || t == 0x1);
+}
+
+void die(FRESULT rc) {
+ printf_P(PSTR("Failed with rc=%u.\r\n"), rc);
+ //for (;;);
+}
+
+void loop() {
+ FIL My_File_Object_x; /* File object */
+
+#if defined(__AVR__)
+ // Print a heap status report about every 10 seconds.
+ if((long)(millis() - HEAPnext_time) >= 0L) {
+ if(UsbDEBUGlvl > 0x50) {
+ printf_P(PSTR("Available heap: %u Bytes\r\n"), freeHeap());
+ }
+ HEAPnext_time = millis() + 10000;
+ }
+ TCCR3B = 0;
+#endif
+#if defined(CORE_TEENSY)
+ // Teensy suffers here, oh well...
+ serialEvent();
+#endif
+ // Horrid! This sort of thing really belongs in an ISR, not here!
+ // We also will be needing to test each hub port, we don't do this yet!
+ if(!change && !usbon && (long)(millis() - usbon_time) >= 0L) {
+ change = true;
+ usbon = true;
+ }
+
+ if(change) {
+ change = false;
+ if(usbon) {
+ Usb.vbusPower(vbus_on);
+ printf_P(PSTR("VBUS on\r\n"));
+ } else {
+ Usb.vbusPower(vbus_off);
+ usbon_time = millis() + 2000;
+ }
+ }
+ Usb.Task();
+ current_state = Usb.getUsbTaskState();
+ if(current_state != last_state) {
+ if(UsbDEBUGlvl > 0x50)
+ printf_P(PSTR("USB state = %x\r\n"), current_state);
+#if !defined(CORE_TEENSY) && defined(__AVR__)
+ if(current_state == USB_STATE_RUNNING) {
+ fadeAmount = 30;
+ }
+#endif
+ if(current_state == USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE) {
+#if !defined(CORE_TEENSY) && defined(__AVR__)
+ fadeAmount = 80;
+#endif
+ partsready = false;
+ for(int i = 0; i < cpart; i++) {
+ if(Fats[i] != NULL)
+ delete Fats[i];
+ Fats[i] = NULL;
+ }
+ fatready = false;
+ notified = false;
+ cpart = 0;
+ }
+ last_state = current_state;
+ }
+
+ // only do any of this if usb is on
+ if(usbon) {
+ if(partsready && !fatready) {
+ if(cpart > 0) fatready = true;
+ }
+ // This is horrible, and needs to be moved elsewhere!
+ for(int B = 0; B < MAX_USB_MS_DRIVERS; B++) {
+ if((!partsready) && (UHS_USB_BulkOnly[B]->GetAddress())) {
+
+ // Build a list.
+ int ML = UHS_USB_BulkOnly[B]->GetbMaxLUN();
+ //printf("MAXLUN = %i\r\n", ML);
+ ML++;
+ for(int i = 0; i < ML; i++) {
+ if(UHS_USB_BulkOnly[B]->LUNIsGood(i)) {
+ partsready = true;
+ ((pvt_t *)(sto[i].private_data))->lun = i;
+ ((pvt_t *)(sto[i].private_data))->B = B;
+ sto[i].Reads = *UHS_USB_BulkOnly_Read;
+ sto[i].Writes = *UHS_USB_BulkOnly_Write;
+ sto[i].Status = *UHS_USB_BulkOnly_Status;
+ sto[i].Initialize = *UHS_USB_BulkOnly_Initialize;
+ sto[i].Commit = *UHS_USB_BulkOnly_Commit;
+ sto[i].TotalSectors = UHS_USB_BulkOnly[B]->GetCapacity(i);
+ sto[i].SectorSize = UHS_USB_BulkOnly[B]->GetSectorSize(i);
+ printf_P(PSTR("LUN:\t\t%u\r\n"), i);
+ printf_P(PSTR("Total Sectors:\t%08lx\t%lu\r\n"), sto[i].TotalSectors, sto[i].TotalSectors);
+ printf_P(PSTR("Sector Size:\t%04x\t\t%u\r\n"), sto[i].SectorSize, sto[i].SectorSize);
+ // get the partition data...
+ PT = new PCPartition;
+
+ if(!PT->Init(&sto[i])) {
+ part_t *apart;
+ for(int j = 0; j < 4; j++) {
+ apart = PT->GetPart(j);
+ if(apart != NULL && apart->type != 0x00) {
+ memcpy(&(parts[cpart]), apart, sizeof (part_t));
+ printf_P(PSTR("Partition %u type %#02x\r\n"), j, parts[cpart].type);
+ // for now
+ if(isfat(parts[cpart].type)) {
+ Fats[cpart] = new PFAT(&sto[i], cpart, parts[cpart].firstSector);
+ //int r = Fats[cpart]->Good();
+ if(Fats[cpart]->MountStatus()) {
+ delete Fats[cpart];
+ Fats[cpart] = NULL;
+ } else cpart++;
+ }
+ }
+ }
+ } else {
+ // try superblock
+ Fats[cpart] = new PFAT(&sto[i], cpart, 0);
+ //int r = Fats[cpart]->Good();
+ if(Fats[cpart]->MountStatus()) {
+ //printf_P(PSTR("Superblock error %x\r\n"), r);
+ delete Fats[cpart];
+ Fats[cpart] = NULL;
+ } else cpart++;
+
+ }
+ delete PT;
+ } else {
+ sto[i].Writes = NULL;
+ sto[i].Reads = NULL;
+ sto[i].Initialize = NULL;
+ sto[i].TotalSectors = 0UL;
+ sto[i].SectorSize = 0;
+ }
+ }
+
+ }
+ }
+
+ if(fatready) {
+ if(Fats[0] != NULL) {
+ struct Pvt * p;
+ p = ((struct Pvt *)(Fats[0]->storage->private_data));
+ if(!UHS_USB_BulkOnly[p->B]->LUNIsGood(p->lun)) {
+ // media change
+#if !defined(CORE_TEENSY) && defined(__AVR__)
+ fadeAmount = 80;
+#endif
+ partsready = false;
+ for(int i = 0; i < cpart; i++) {
+ if(Fats[i] != NULL)
+ delete Fats[i];
+ Fats[cpart] = NULL;
+ }
+ fatready = false;
+ notified = false;
+ cpart = 0;
+ }
+
+ }
+ }
+ if(fatready) {
+ FRESULT rc; /* Result code */
+ UINT bw, br, i;
+ if(!notified) {
+#if !defined(CORE_TEENSY) && defined(__AVR__)
+ fadeAmount = 5;
+#endif
+ notified = true;
+ FATFS *fs = NULL;
+ for(int zz = 0; zz < _VOLUMES; zz++) {
+ if(Fats[zz]->volmap == 0) fs = Fats[zz]->ffs;
+ }
+ printf_P(PSTR("\r\nOpen an existing file (message.txt).\r\n"));
+ rc = f_open(&My_File_Object_x, "0:/MESSAGE.TXT", FA_READ);
+ if(rc) printf_P(PSTR("Error %i, message.txt not found.\r\n"), rc);
+ else {
+ printf_P(PSTR("\r\nType the file content.\r\n"));
+ for(;;) {
+ rc = f_read(&My_File_Object_x, My_Buff_x, mbxs, &br); /* Read a chunk of file */
+ if(rc || !br) break; /* Error or end of file */
+ for(i = 0; i < br; i++) {
+ /* Type the data */
+ if(My_Buff_x[i] == '\n')
+ Serial.write('\r');
+ if(My_Buff_x[i] != '\r')
+ Serial.write(My_Buff_x[i]);
+ Serial.flush();
+ }
+ }
+ if(rc) {
+ f_close(&My_File_Object_x);
+ goto out;
+ }
+
+ printf_P(PSTR("\r\nClose the file.\r\n"));
+ rc = f_close(&My_File_Object_x);
+ if(rc) goto out;
+ }
+ printf_P(PSTR("\r\nCreate a new file (hello.txt).\r\n"));
+ rc = f_open(&My_File_Object_x, "0:/Hello.TxT", FA_WRITE | FA_CREATE_ALWAYS);
+ if(rc) {
+ die(rc);
+ goto outdir;
+ }
+ printf_P(PSTR("\r\nWrite a text data. (Hello world!)\r\n"));
+ rc = f_write(&My_File_Object_x, "Hello world!\r\n", 14, &bw);
+ if(rc) {
+ goto out;
+ }
+ printf_P(PSTR("%u bytes written.\r\n"), bw);
+
+ printf_P(PSTR("\r\nClose the file.\r\n"));
+ rc = f_close(&My_File_Object_x);
+ if(rc) {
+ die(rc);
+ goto out;
+ }
+outdir:{
+#if _USE_LFN
+ char lfn[_MAX_LFN + 1];
+ FILINFO My_File_Info_Object_x; /* File information object */
+ My_File_Info_Object_x.lfname = lfn;
+#endif
+ DIR My_Dir_Object_x; /* Directory object */
+ printf_P(PSTR("\r\nOpen root directory.\r\n"));
+ rc = f_opendir(&My_Dir_Object_x, "0:/");
+ if(rc) {
+ die(rc);
+ goto out;
+ }
+
+ printf_P(PSTR("\r\nDirectory listing...\r\n"));
+#if defined(__AVR__)
+ printf_P(PSTR("Available heap: %u Bytes\r\n"), freeHeap());
+#endif
+ for(;;) {
+#if _USE_LFN
+ My_File_Info_Object_x.lfsize = _MAX_LFN;
+#endif
+
+ rc = f_readdir(&My_Dir_Object_x, &My_File_Info_Object_x); /* Read a directory item */
+ if(rc || !My_File_Info_Object_x.fname[0]) break; /* Error or end of dir */
+
+ if(My_File_Info_Object_x.fattrib & AM_DIR) {
+ Serial.write('d');
+ } else {
+ Serial.write('-');
+ }
+ Serial.write('r');
+
+ if(My_File_Info_Object_x.fattrib & AM_RDO) {
+ Serial.write('-');
+ } else {
+ Serial.write('w');
+ }
+ if(My_File_Info_Object_x.fattrib & AM_HID) {
+ Serial.write('h');
+ } else {
+ Serial.write('-');
+ }
+
+ if(My_File_Info_Object_x.fattrib & AM_SYS) {
+ Serial.write('s');
+ } else {
+ Serial.write('-');
+ }
+
+ if(My_File_Info_Object_x.fattrib & AM_ARC) {
+ Serial.write('a');
+ } else {
+ Serial.write('-');
+ }
+
+#if _USE_LFN
+ if(*My_File_Info_Object_x.lfname)
+ printf_P(PSTR(" %8lu %s (%s)\r\n"), My_File_Info_Object_x.fsize, My_File_Info_Object_x.fname, My_File_Info_Object_x.lfname);
+ else
+#endif
+ printf_P(PSTR(" %8lu %s\r\n"), My_File_Info_Object_x.fsize, &(My_File_Info_Object_x.fname[0]));
+ }
+ }
+out:
+ if(rc) die(rc);
+
+ DISK_IOCTL(fs->drv, CTRL_COMMIT, 0);
+ printf_P(PSTR("\r\nTest completed.\r\n"));
+
+ }
+
+ if(runtest) {
+ ULONG ii, wt, rt, start, end;
+ FATFS *fs = NULL;
+ for(int zz = 0; zz < _VOLUMES; zz++) {
+ if(Fats[zz]->volmap == 0) fs = Fats[zz]->ffs;
+ }
+ runtest = false;
+ f_unlink("0:/10MB.bin");
+ printf_P(PSTR("\r\nCreate a new 10MB test file (10MB.bin).\r\n"));
+ rc = f_open(&My_File_Object_x, "0:/10MB.bin", FA_WRITE | FA_CREATE_ALWAYS);
+ if(rc) goto failed;
+ for(bw = 0; bw < mbxs; bw++) My_Buff_x[bw] = bw & 0xff;
+ fflush(stdout);
+ start = millis();
+ while(start == millis());
+ for(ii = 10485760LU / mbxs; ii > 0LU; ii--) {
+ rc = f_write(&My_File_Object_x, My_Buff_x, mbxs, &bw);
+ if(rc || !bw) goto failed;
+ }
+ rc = f_close(&My_File_Object_x);
+ if(rc) goto failed;
+ end = millis();
+ wt = (end - start) - 1;
+ printf_P(PSTR("Time to write 10485760 bytes: %lu ms (%lu sec) \r\n"), wt, (500 + wt) / 1000UL);
+ rc = f_open(&My_File_Object_x, "0:/10MB.bin", FA_READ);
+ fflush(stdout);
+ start = millis();
+ while(start == millis());
+ if(rc) goto failed;
+ for(;;) {
+ rc = f_read(&My_File_Object_x, My_Buff_x, mbxs, &bw); /* Read a chunk of file */
+ if(rc || !bw) break; /* Error or end of file */
+ }
+ end = millis();
+ if(rc) goto failed;
+ rc = f_close(&My_File_Object_x);
+ if(rc) goto failed;
+ rt = (end - start) - 1;
+ printf_P(PSTR("Time to read 10485760 bytes: %lu ms (%lu sec)\r\nDelete test file\r\n"), rt, (500 + rt) / 1000UL);
+failed:
+ if(rc) die(rc);
+ DISK_IOCTL(fs->drv, CTRL_COMMIT, 0);
+ printf_P(PSTR("10MB timing test finished.\r\n"));
+ }
+ }
+ }
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/gpl2.txt b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/gpl2.txt
new file mode 100644
index 000000000..5b6e7c66c
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/gpl2.txt
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hexdump.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hexdump.h
new file mode 100644
index 000000000..ffa7248b7
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hexdump.h
@@ -0,0 +1,61 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+#if !defined(_usb_h_) || defined(__HEXDUMP_H__)
+#error "Never include hexdump.h directly; include Usb.h instead"
+#else
+#define __HEXDUMP_H__
+
+extern int UsbDEBUGlvl;
+
+template <class BASE_CLASS, class LEN_TYPE, class OFFSET_TYPE>
+class HexDumper : public BASE_CLASS {
+ uint8_t byteCount;
+ OFFSET_TYPE byteTotal;
+
+public:
+
+ HexDumper() : byteCount(0), byteTotal(0) {
+ };
+
+ void Initialize() {
+ byteCount = 0;
+ byteTotal = 0;
+ };
+
+ void Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset);
+};
+
+template <class BASE_CLASS, class LEN_TYPE, class OFFSET_TYPE>
+void HexDumper<BASE_CLASS, LEN_TYPE, OFFSET_TYPE>::Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset) {
+ if(UsbDEBUGlvl >= 0x80) { // Fully bypass this block of code if we do not debug.
+ for(LEN_TYPE j = 0; j < len; j++, byteCount++, byteTotal++) {
+ if(!byteCount) {
+ PrintHex<OFFSET_TYPE > (byteTotal, 0x80);
+ E_Notify(PSTR(": "), 0x80);
+ }
+ PrintHex<uint8_t > (pbuf[j], 0x80);
+ E_Notify(PSTR(" "), 0x80);
+
+ if(byteCount == 15) {
+ E_Notify(PSTR("\r\n"), 0x80);
+ byteCount = 0xFF;
+ }
+ }
+ }
+}
+
+#endif // __HEXDUMP_H__
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hid.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hid.cpp
new file mode 100644
index 000000000..e4c7721a3
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hid.cpp
@@ -0,0 +1,112 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+
+#include "hid.h"
+
+//get HID report descriptor
+
+/* WRONG! Endpoint is _ALWAYS_ ZERO for HID! We want the _INTERFACE_ value here!
+uint8_t HID::GetReportDescr(uint8_t ep, USBReadParser *parser) {
+ const uint8_t constBufLen = 64;
+ uint8_t buf[constBufLen];
+
+ uint8_t rcode = pUsb->ctrlReq(bAddress, ep, bmREQ_HID_REPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00,
+ HID_DESCRIPTOR_REPORT, 0x0000, 128, constBufLen, buf, (USBReadParser*)parser);
+
+ //return ((rcode != hrSTALL) ? rcode : 0);
+ return rcode;
+}
+ */
+uint8_t HID::GetReportDescr(uint16_t wIndex, USBReadParser *parser) {
+ const uint8_t constBufLen = 64;
+ uint8_t buf[constBufLen];
+
+ uint8_t rcode = pUsb->ctrlReq(bAddress, 0x00, bmREQ_HID_REPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00,
+ HID_DESCRIPTOR_REPORT, wIndex, 128, constBufLen, buf, (USBReadParser*)parser);
+
+ //return ((rcode != hrSTALL) ? rcode : 0);
+ return rcode;
+}
+
+//uint8_t HID::getHidDescr( uint8_t ep, uint16_t nbytes, uint8_t* dataptr )
+//{
+// return( pUsb->ctrlReq( bAddress, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, HID_DESCRIPTOR_HID, 0x0000, nbytes, dataptr ));
+//}
+
+uint8_t HID::SetReport(uint8_t ep, uint8_t iface, uint8_t report_type, uint8_t report_id, uint16_t nbytes, uint8_t* dataptr) {
+ return ( pUsb->ctrlReq(bAddress, ep, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, report_id, report_type, iface, nbytes, nbytes, dataptr, NULL));
+}
+
+uint8_t HID::GetReport(uint8_t ep, uint8_t iface, uint8_t report_type, uint8_t report_id, uint16_t nbytes, uint8_t* dataptr) {
+ return ( pUsb->ctrlReq(bAddress, ep, bmREQ_HID_IN, HID_REQUEST_GET_REPORT, report_id, report_type, iface, nbytes, nbytes, dataptr, NULL));
+}
+
+uint8_t HID::GetIdle(uint8_t iface, uint8_t reportID, uint8_t* dataptr) {
+ return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HID_IN, HID_REQUEST_GET_IDLE, reportID, 0, iface, 0x0001, 0x0001, dataptr, NULL));
+}
+
+uint8_t HID::SetIdle(uint8_t iface, uint8_t reportID, uint8_t duration) {
+ return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HID_OUT, HID_REQUEST_SET_IDLE, reportID, duration, iface, 0x0000, 0x0000, NULL, NULL));
+}
+
+uint8_t HID::SetProtocol(uint8_t iface, uint8_t protocol) {
+ return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HID_OUT, HID_REQUEST_SET_PROTOCOL, protocol, 0x00, iface, 0x0000, 0x0000, NULL, NULL));
+}
+
+uint8_t HID::GetProtocol(uint8_t iface, uint8_t* dataptr) {
+ return ( pUsb->ctrlReq(bAddress, 0, bmREQ_HID_IN, HID_REQUEST_GET_PROTOCOL, 0x00, 0x00, iface, 0x0001, 0x0001, dataptr, NULL));
+}
+
+void HID::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) {
+ Notify(PSTR("Endpoint descriptor:"), 0x80);
+ Notify(PSTR("\r\nLength:\t\t"), 0x80);
+ D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
+ Notify(PSTR("\r\nType:\t\t"), 0x80);
+ D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
+ Notify(PSTR("\r\nAddress:\t"), 0x80);
+ D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
+ Notify(PSTR("\r\nAttributes:\t"), 0x80);
+ D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
+ Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
+ D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
+ Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
+ D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
+}
+
+void HID::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc) {
+ Notify(PSTR("\r\n\r\nHID Descriptor:\r\n"), 0x80);
+ Notify(PSTR("bDescLength:\t\t"), 0x80);
+ D_PrintHex<uint8_t > (pDesc->bLength, 0x80);
+
+ Notify(PSTR("\r\nbDescriptorType:\t"), 0x80);
+ D_PrintHex<uint8_t > (pDesc->bDescriptorType, 0x80);
+
+ Notify(PSTR("\r\nbcdHID:\t\t\t"), 0x80);
+ D_PrintHex<uint16_t > (pDesc->bcdHID, 0x80);
+
+ Notify(PSTR("\r\nbCountryCode:\t\t"), 0x80);
+ D_PrintHex<uint8_t > (pDesc->bCountryCode, 0x80);
+
+ Notify(PSTR("\r\nbNumDescriptors:\t"), 0x80);
+ D_PrintHex<uint8_t > (pDesc->bNumDescriptors, 0x80);
+
+ Notify(PSTR("\r\nbDescrType:\t\t"), 0x80);
+ D_PrintHex<uint8_t > (pDesc->bDescrType, 0x80);
+
+ Notify(PSTR("\r\nwDescriptorLength:\t"), 0x80);
+ D_PrintHex<uint16_t > (pDesc->wDescriptorLength, 0x80);
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hid.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hid.h
new file mode 100644
index 000000000..72942ebc9
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hid.h
@@ -0,0 +1,188 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+#if !defined(__HID_H__)
+#define __HID_H__
+
+#include "Usb.h"
+#include "hidusagestr.h"
+
+#define MAX_REPORT_PARSERS 2
+#define HID_MAX_HID_CLASS_DESCRIPTORS 5
+
+#define DATA_SIZE_MASK 0x03
+#define TYPE_MASK 0x0C
+#define TAG_MASK 0xF0
+
+#define DATA_SIZE_0 0x00
+#define DATA_SIZE_1 0x01
+#define DATA_SIZE_2 0x02
+#define DATA_SIZE_4 0x03
+
+#define TYPE_MAIN 0x00
+#define TYPE_GLOBAL 0x04
+#define TYPE_LOCAL 0x08
+
+#define TAG_MAIN_INPUT 0x80
+#define TAG_MAIN_OUTPUT 0x90
+#define TAG_MAIN_COLLECTION 0xA0
+#define TAG_MAIN_FEATURE 0xB0
+#define TAG_MAIN_ENDCOLLECTION 0xC0
+
+#define TAG_GLOBAL_USAGEPAGE 0x00
+#define TAG_GLOBAL_LOGICALMIN 0x10
+#define TAG_GLOBAL_LOGICALMAX 0x20
+#define TAG_GLOBAL_PHYSMIN 0x30
+#define TAG_GLOBAL_PHYSMAX 0x40
+#define TAG_GLOBAL_UNITEXP 0x50
+#define TAG_GLOBAL_UNIT 0x60
+#define TAG_GLOBAL_REPORTSIZE 0x70
+#define TAG_GLOBAL_REPORTID 0x80
+#define TAG_GLOBAL_REPORTCOUNT 0x90
+#define TAG_GLOBAL_PUSH 0xA0
+#define TAG_GLOBAL_POP 0xB0
+
+#define TAG_LOCAL_USAGE 0x00
+#define TAG_LOCAL_USAGEMIN 0x10
+#define TAG_LOCAL_USAGEMAX 0x20
+
+/* HID requests */
+#define bmREQ_HID_OUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
+#define bmREQ_HID_IN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
+#define bmREQ_HID_REPORT USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_INTERFACE
+
+/* HID constants. Not part of chapter 9 */
+/* Class-Specific Requests */
+#define HID_REQUEST_GET_REPORT 0x01
+#define HID_REQUEST_GET_IDLE 0x02
+#define HID_REQUEST_GET_PROTOCOL 0x03
+#define HID_REQUEST_SET_REPORT 0x09
+#define HID_REQUEST_SET_IDLE 0x0A
+#define HID_REQUEST_SET_PROTOCOL 0x0B
+
+/* Class Descriptor Types */
+#define HID_DESCRIPTOR_HID 0x21
+#define HID_DESCRIPTOR_REPORT 0x22
+#define HID_DESRIPTOR_PHY 0x23
+
+/* Protocol Selection */
+#define HID_BOOT_PROTOCOL 0x00
+#define HID_RPT_PROTOCOL 0x01
+
+/* HID Interface Class Code */
+#define HID_INTF 0x03
+
+/* HID Interface Class SubClass Codes */
+#define HID_BOOT_INTF_SUBCLASS 0x01
+
+/* HID Interface Class Protocol Codes */
+#define HID_PROTOCOL_NONE 0x00
+#define HID_PROTOCOL_KEYBOARD 0x01
+#define HID_PROTOCOL_MOUSE 0x02
+
+#define HID_ITEM_TYPE_MAIN 0
+#define HID_ITEM_TYPE_GLOBAL 1
+#define HID_ITEM_TYPE_LOCAL 2
+#define HID_ITEM_TYPE_RESERVED 3
+
+#define HID_LONG_ITEM_PREFIX 0xfe // Long item prefix value
+
+#define bmHID_MAIN_ITEM_TAG 0xfc // Main item tag mask
+
+#define bmHID_MAIN_ITEM_INPUT 0x80 // Main item Input tag value
+#define bmHID_MAIN_ITEM_OUTPUT 0x90 // Main item Output tag value
+#define bmHID_MAIN_ITEM_FEATURE 0xb0 // Main item Feature tag value
+#define bmHID_MAIN_ITEM_COLLECTION 0xa0 // Main item Collection tag value
+#define bmHID_MAIN_ITEM_END_COLLECTION 0xce // Main item End Collection tag value
+
+#define HID_MAIN_ITEM_COLLECTION_PHYSICAL 0
+#define HID_MAIN_ITEM_COLLECTION_APPLICATION 1
+#define HID_MAIN_ITEM_COLLECTION_LOGICAL 2
+#define HID_MAIN_ITEM_COLLECTION_REPORT 3
+#define HID_MAIN_ITEM_COLLECTION_NAMED_ARRAY 4
+#define HID_MAIN_ITEM_COLLECTION_USAGE_SWITCH 5
+#define HID_MAIN_ITEM_COLLECTION_USAGE_MODIFIER 6
+
+struct HidItemPrefix {
+ uint8_t bSize : 2;
+ uint8_t bType : 2;
+ uint8_t bTag : 4;
+};
+
+struct MainItemIOFeature {
+ uint8_t bmIsConstantOrData : 1;
+ uint8_t bmIsArrayOrVariable : 1;
+ uint8_t bmIsRelativeOrAbsolute : 1;
+ uint8_t bmIsWrapOrNoWrap : 1;
+ uint8_t bmIsNonLonearOrLinear : 1;
+ uint8_t bmIsNoPreferedOrPrefered : 1;
+ uint8_t bmIsNullOrNoNull : 1;
+ uint8_t bmIsVolatileOrNonVolatile : 1;
+};
+
+class HID;
+
+class HIDReportParser {
+public:
+ virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) = 0;
+};
+
+class HID : public USBDeviceConfig, public UsbConfigXtracter {
+protected:
+ USB *pUsb; // USB class instance pointer
+ uint8_t bAddress; // address
+
+protected:
+ static const uint8_t epInterruptInIndex = 1; // InterruptIN endpoint index
+ static const uint8_t epInterruptOutIndex = 2; // InterruptOUT endpoint index
+
+ static const uint8_t maxHidInterfaces = 3;
+ static const uint8_t maxEpPerInterface = 2;
+ static const uint8_t totalEndpoints = (maxHidInterfaces * maxEpPerInterface + 1);
+
+ void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr);
+ void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc);
+
+ virtual HIDReportParser* GetReportParser(uint8_t id) {
+ return NULL;
+ };
+
+public:
+
+ HID(USB *pusb) : pUsb(pusb) {
+ };
+
+ const USB* GetUsb() {
+ return pUsb;
+ };
+
+ virtual bool SetReportParser(uint8_t id, HIDReportParser *prs) {
+ return false;
+ };
+
+ uint8_t SetProtocol(uint8_t iface, uint8_t protocol);
+ uint8_t GetProtocol(uint8_t iface, uint8_t* dataptr);
+ uint8_t GetIdle(uint8_t iface, uint8_t reportID, uint8_t* dataptr);
+ uint8_t SetIdle(uint8_t iface, uint8_t reportID, uint8_t duration);
+
+ uint8_t GetReportDescr(uint16_t wIndex, USBReadParser *parser = NULL);
+
+ uint8_t GetHidDescr(uint8_t ep, uint16_t nbytes, uint8_t* dataptr);
+ uint8_t GetReport(uint8_t ep, uint8_t iface, uint8_t report_type, uint8_t report_id, uint16_t nbytes, uint8_t* dataptr);
+ uint8_t SetReport(uint8_t ep, uint8_t iface, uint8_t report_type, uint8_t report_id, uint16_t nbytes, uint8_t* dataptr);
+};
+
+#endif // __HID_H__
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidboot.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidboot.cpp
new file mode 100644
index 000000000..280b2f978
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidboot.cpp
@@ -0,0 +1,201 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+#include "hidboot.h"
+
+void MouseReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
+ MOUSEINFO *pmi = (MOUSEINFO*)buf;
+ // Future:
+ // bool event;
+
+#if 0
+ if (prevState.mouseInfo.bmLeftButton == 0 && pmi->bmLeftButton == 1)
+ OnLeftButtonDown(pmi);
+
+ if (prevState.mouseInfo.bmLeftButton == 1 && pmi->bmLeftButton == 0)
+ OnLeftButtonUp(pmi);
+
+ if (prevState.mouseInfo.bmRightButton == 0 && pmi->bmRightButton == 1)
+ OnRightButtonDown(pmi);
+
+ if (prevState.mouseInfo.bmRightButton == 1 && pmi->bmRightButton == 0)
+ OnRightButtonUp(pmi);
+
+ if (prevState.mouseInfo.bmMiddleButton == 0 && pmi->bmMiddleButton == 1)
+ OnMiddleButtonDown(pmi);
+
+ if (prevState.mouseInfo.bmMiddleButton == 1 && pmi->bmMiddleButton == 0)
+ OnMiddleButtonUp(pmi);
+
+ if (prevState.mouseInfo.dX != pmi->dX || prevState.mouseInfo.dY != pmi->dY)
+ OnMouseMove(pmi);
+
+ if (len > sizeof (MOUSEINFO))
+ for (uint8_t i = 0; i<sizeof (MOUSEINFO); i++)
+ prevState.bInfo[i] = buf[i];
+#else
+ //
+ // Optimization idea:
+ //
+ // 1: Don't pass the structure on every event. Buttons would not need it.
+ // 2: Only pass x/y values in the movement routine.
+ //
+ // These two changes (with the ones I have made) will save extra flash.
+ // The only "bad" thing is that it could break old code.
+ //
+ // Future thoughts:
+ //
+ // The extra space gained can be used for a generic mouse event that can be called
+ // when there are _ANY_ changes. This one you _MAY_ want to pass everything, however the
+ // sketch could already have noted these facts to support drag/drop scroll wheel stuff, etc.
+ //
+
+ // Why do we need to pass the structure for buttons?
+ // The function call not enough of a hint for what is happening?
+ if(prevState.mouseInfo.bmLeftButton != pmi->bmLeftButton ) {
+ if(pmi->bmLeftButton) {
+ OnLeftButtonDown(pmi);
+ } else {
+ OnLeftButtonUp(pmi);
+ }
+ // Future:
+ // event = true;
+ }
+
+ if(prevState.mouseInfo.bmRightButton != pmi->bmRightButton) {
+ if(pmi->bmRightButton) {
+ OnRightButtonDown(pmi);
+ } else {
+ OnRightButtonUp(pmi);
+ }
+ // Future:
+ // event = true;
+ }
+
+ if(prevState.mouseInfo.bmMiddleButton != pmi->bmMiddleButton) {
+ if(pmi->bmMiddleButton) {
+ OnMiddleButtonDown(pmi);
+ } else {
+ OnMiddleButtonUp(pmi);
+ }
+ // Future:
+ // event = true;
+ }
+
+ //
+ // Scroll wheel(s), are not part of the spec, but we could support it.
+ // Logitech wireless keyboard and mouse combo reports scroll wheel in byte 4
+ // We wouldn't even need to save this information.
+ //if(len > 3) {
+ //}
+ //
+
+ // Mice only report motion when they actually move!
+ // Why not just pass the x/y values to simplify things??
+ if(pmi->dX || pmi->dY) {
+ OnMouseMove(pmi);
+ // Future:
+ // event = true;
+ }
+
+ //
+ // Future:
+ // Provide a callback that operates on the gathered events from above.
+ //
+ // if(event) OnMouse();
+ //
+
+ // Only the first byte matters (buttons). We do NOT need to save position info.
+ prevState.bInfo[0] = buf[0];
+#endif
+
+};
+
+void KeyboardReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
+ // On error - return
+ if (buf[2] == 1)
+ return;
+
+ //KBDINFO *pki = (KBDINFO*)buf;
+
+ // provide event for changed control key state
+ if (prevState.bInfo[0x00] != buf[0x00]) {
+ OnControlKeysChanged(prevState.bInfo[0x00], buf[0x00]);
+ }
+
+ for (uint8_t i = 2; i < 8; i++) {
+ bool down = false;
+ bool up = false;
+
+ for (uint8_t j = 2; j < 8; j++) {
+ if (buf[i] == prevState.bInfo[j] && buf[i] != 1)
+ down = true;
+ if (buf[j] == prevState.bInfo[i] && prevState.bInfo[i] != 1)
+ up = true;
+ }
+ if (!down) {
+ HandleLockingKeys(hid, buf[i]);
+ OnKeyDown(*buf, buf[i]);
+ }
+ if (!up)
+ OnKeyUp(prevState.bInfo[0], prevState.bInfo[i]);
+ }
+ for (uint8_t i = 0; i < 8; i++)
+ prevState.bInfo[i] = buf[i];
+};
+
+const uint8_t KeyboardReportParser::numKeys[10] PROGMEM = {'!', '@', '#', '$', '%', '^', '&', '*', '(', ')'};
+const uint8_t KeyboardReportParser::symKeysUp[12] PROGMEM = {'_', '+', '{', '}', '|', '~', ':', '"', '~', '<', '>', '?'};
+const uint8_t KeyboardReportParser::symKeysLo[12] PROGMEM = {'-', '=', '[', ']', '\\', ' ', ';', '\'', '`', ',', '.', '/'};
+const uint8_t KeyboardReportParser::padKeys[5] PROGMEM = {'/', '*', '-', '+', 0x13};
+
+uint8_t KeyboardReportParser::OemToAscii(uint8_t mod, uint8_t key) {
+ uint8_t shift = (mod & 0x22);
+
+ // [a-z]
+ if (VALUE_WITHIN(key, 0x04, 0x1d)) {
+ // Upper case letters
+ if ((kbdLockingKeys.kbdLeds.bmCapsLock == 0 && shift) ||
+ (kbdLockingKeys.kbdLeds.bmCapsLock == 1 && shift == 0))
+ return (key - 4 + 'A');
+
+ // Lower case letters
+ else
+ return (key - 4 + 'a');
+ }// Numbers
+ else if (VALUE_WITHIN(key, 0x1e, 0x27)) {
+ if (shift)
+ return ((uint8_t)pgm_read_byte(&getNumKeys()[key - 0x1e]));
+ else
+ return ((key == UHS_HID_BOOT_KEY_ZERO) ? '0' : key - 0x1e + '1');
+ }// Keypad Numbers
+ else if(VALUE_WITHIN(key, 0x59, 0x61)) {
+ if(kbdLockingKeys.kbdLeds.bmNumLock == 1)
+ return (key - 0x59 + '1');
+ } else if(VALUE_WITHIN(key, 0x2d, 0x38))
+ return ((shift) ? (uint8_t)pgm_read_byte(&getSymKeysUp()[key - 0x2d]) : (uint8_t)pgm_read_byte(&getSymKeysLo()[key - 0x2d]));
+ else if(VALUE_WITHIN(key, 0x54, 0x58))
+ return (uint8_t)pgm_read_byte(&getPadKeys()[key - 0x54]);
+ else {
+ switch(key) {
+ case UHS_HID_BOOT_KEY_SPACE: return (0x20);
+ case UHS_HID_BOOT_KEY_ENTER: return (0x13);
+ case UHS_HID_BOOT_KEY_ZERO2: return ((kbdLockingKeys.kbdLeds.bmNumLock == 1) ? '0': 0);
+ case UHS_HID_BOOT_KEY_PERIOD: return ((kbdLockingKeys.kbdLeds.bmNumLock == 1) ? '.': 0);
+ }
+ }
+ return ( 0);
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidboot.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidboot.h
new file mode 100644
index 000000000..fb63ec5e5
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidboot.h
@@ -0,0 +1,618 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+#if !defined(__HIDBOOT_H__)
+#define __HIDBOOT_H__
+
+#include "hid.h"
+
+#define UHS_HID_BOOT_KEY_ZERO 0x27
+#define UHS_HID_BOOT_KEY_ENTER 0x28
+#define UHS_HID_BOOT_KEY_SPACE 0x2c
+#define UHS_HID_BOOT_KEY_CAPS_LOCK 0x39
+#define UHS_HID_BOOT_KEY_SCROLL_LOCK 0x47
+#define UHS_HID_BOOT_KEY_NUM_LOCK 0x53
+#define UHS_HID_BOOT_KEY_ZERO2 0x62
+#define UHS_HID_BOOT_KEY_PERIOD 0x63
+
+// Don't worry, GCC will optimize the result to a final value.
+#define bitsEndpoints(p) ((((p) & HID_PROTOCOL_KEYBOARD)? 2 : 0) | (((p) & HID_PROTOCOL_MOUSE)? 1 : 0))
+#define totalEndpoints(p) ((bitsEndpoints(p) == 3) ? 3 : 2)
+#define epMUL(p) ((((p) & HID_PROTOCOL_KEYBOARD)? 1 : 0) + (((p) & HID_PROTOCOL_MOUSE)? 1 : 0))
+
+// Already defined in hid.h
+// #define HID_MAX_HID_CLASS_DESCRIPTORS 5
+
+struct MOUSEINFO {
+
+ struct {
+ uint8_t bmLeftButton : 1;
+ uint8_t bmRightButton : 1;
+ uint8_t bmMiddleButton : 1;
+ uint8_t bmDummy : 5;
+ };
+ int8_t dX;
+ int8_t dY;
+};
+
+class MouseReportParser : public HIDReportParser {
+
+ union {
+ MOUSEINFO mouseInfo;
+ uint8_t bInfo[sizeof (MOUSEINFO)];
+ } prevState;
+
+public:
+ void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
+
+protected:
+
+ virtual void OnMouseMove(MOUSEINFO *mi) {
+ };
+
+ virtual void OnLeftButtonUp(MOUSEINFO *mi) {
+ };
+
+ virtual void OnLeftButtonDown(MOUSEINFO *mi) {
+ };
+
+ virtual void OnRightButtonUp(MOUSEINFO *mi) {
+ };
+
+ virtual void OnRightButtonDown(MOUSEINFO *mi) {
+ };
+
+ virtual void OnMiddleButtonUp(MOUSEINFO *mi) {
+ };
+
+ virtual void OnMiddleButtonDown(MOUSEINFO *mi) {
+ };
+};
+
+struct MODIFIERKEYS {
+ uint8_t bmLeftCtrl : 1;
+ uint8_t bmLeftShift : 1;
+ uint8_t bmLeftAlt : 1;
+ uint8_t bmLeftGUI : 1;
+ uint8_t bmRightCtrl : 1;
+ uint8_t bmRightShift : 1;
+ uint8_t bmRightAlt : 1;
+ uint8_t bmRightGUI : 1;
+};
+
+struct KBDINFO {
+
+ struct {
+ uint8_t bmLeftCtrl : 1;
+ uint8_t bmLeftShift : 1;
+ uint8_t bmLeftAlt : 1;
+ uint8_t bmLeftGUI : 1;
+ uint8_t bmRightCtrl : 1;
+ uint8_t bmRightShift : 1;
+ uint8_t bmRightAlt : 1;
+ uint8_t bmRightGUI : 1;
+ };
+ uint8_t bReserved;
+ uint8_t Keys[6];
+};
+
+struct KBDLEDS {
+ uint8_t bmNumLock : 1;
+ uint8_t bmCapsLock : 1;
+ uint8_t bmScrollLock : 1;
+ uint8_t bmCompose : 1;
+ uint8_t bmKana : 1;
+ uint8_t bmReserved : 3;
+};
+
+class KeyboardReportParser : public HIDReportParser {
+ static const uint8_t numKeys[10];
+ static const uint8_t symKeysUp[12];
+ static const uint8_t symKeysLo[12];
+ static const uint8_t padKeys[5];
+
+protected:
+
+ union {
+ KBDINFO kbdInfo;
+ uint8_t bInfo[sizeof (KBDINFO)];
+ } prevState;
+
+ union {
+ KBDLEDS kbdLeds;
+ uint8_t bLeds;
+ } kbdLockingKeys;
+
+ uint8_t OemToAscii(uint8_t mod, uint8_t key);
+
+public:
+
+ KeyboardReportParser() {
+ kbdLockingKeys.bLeds = 0;
+ };
+
+ void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
+
+protected:
+
+ virtual uint8_t HandleLockingKeys(HID* hid, uint8_t key) {
+ uint8_t old_keys = kbdLockingKeys.bLeds;
+
+ switch(key) {
+ case UHS_HID_BOOT_KEY_NUM_LOCK:
+ kbdLockingKeys.kbdLeds.bmNumLock = ~kbdLockingKeys.kbdLeds.bmNumLock;
+ break;
+ case UHS_HID_BOOT_KEY_CAPS_LOCK:
+ kbdLockingKeys.kbdLeds.bmCapsLock = ~kbdLockingKeys.kbdLeds.bmCapsLock;
+ break;
+ case UHS_HID_BOOT_KEY_SCROLL_LOCK:
+ kbdLockingKeys.kbdLeds.bmScrollLock = ~kbdLockingKeys.kbdLeds.bmScrollLock;
+ break;
+ }
+
+ if(old_keys != kbdLockingKeys.bLeds && hid)
+ return (hid->SetReport(0, 0/*hid->GetIface()*/, 2, 0, 1, &kbdLockingKeys.bLeds));
+
+ return 0;
+ };
+
+ virtual void OnControlKeysChanged(uint8_t before, uint8_t after) {
+ };
+
+ virtual void OnKeyDown(uint8_t mod, uint8_t key) {
+ };
+
+ virtual void OnKeyUp(uint8_t mod, uint8_t key) {
+ };
+
+ virtual const uint8_t *getNumKeys() {
+ return numKeys;
+ };
+
+ virtual const uint8_t *getSymKeysUp() {
+ return symKeysUp;
+ };
+
+ virtual const uint8_t *getSymKeysLo() {
+ return symKeysLo;
+ };
+
+ virtual const uint8_t *getPadKeys() {
+ return padKeys;
+ };
+};
+
+template <const uint8_t BOOT_PROTOCOL>
+class HIDBoot : public HID //public USBDeviceConfig, public UsbConfigXtracter
+{
+ EpInfo epInfo[totalEndpoints(BOOT_PROTOCOL)];
+ HIDReportParser *pRptParser[epMUL(BOOT_PROTOCOL)];
+
+ uint8_t bConfNum; // configuration number
+ uint8_t bIfaceNum; // Interface Number
+ uint8_t bNumIface; // number of interfaces in the configuration
+ uint8_t bNumEP; // total number of EP in the configuration
+ uint32_t qNextPollTime; // next poll time
+ bool bPollEnable; // poll enable flag
+ uint8_t bInterval; // largest interval
+
+ void Initialize();
+
+ virtual HIDReportParser* GetReportParser(uint8_t id) {
+ return pRptParser[id];
+ };
+
+public:
+ HIDBoot(USB *p);
+
+ virtual bool SetReportParser(uint8_t id, HIDReportParser *prs) {
+ pRptParser[id] = prs;
+ return true;
+ };
+
+ // USBDeviceConfig implementation
+ uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
+ uint8_t Release();
+ uint8_t Poll();
+
+ virtual uint8_t GetAddress() {
+ return bAddress;
+ };
+
+ virtual bool isReady() {
+ return bPollEnable;
+ };
+
+ // UsbConfigXtracter implementation
+ // Method should be defined here if virtual.
+ virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
+
+ virtual bool DEVCLASSOK(uint8_t klass) {
+ return (klass == USB_CLASS_HID);
+ }
+
+ virtual bool DEVSUBCLASSOK(uint8_t subklass) {
+ return (subklass == BOOT_PROTOCOL);
+ }
+};
+
+template <const uint8_t BOOT_PROTOCOL>
+HIDBoot<BOOT_PROTOCOL>::HIDBoot(USB *p) :
+HID(p),
+qNextPollTime(0),
+bPollEnable(false) {
+ Initialize();
+
+ for(int i = 0; i < epMUL(BOOT_PROTOCOL); i++) {
+ pRptParser[i] = NULL;
+ }
+ if(pUsb)
+ pUsb->RegisterDeviceClass(this);
+}
+
+template <const uint8_t BOOT_PROTOCOL>
+void HIDBoot<BOOT_PROTOCOL>::Initialize() {
+ for(int i = 0; i < totalEndpoints(BOOT_PROTOCOL); i++) {
+ epInfo[i].epAddr = 0;
+ epInfo[i].maxPktSize = (i) ? 0 : 8;
+ epInfo[i].epAttribs = 0;
+ epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
+ }
+ bNumEP = 1;
+ bNumIface = 0;
+ bConfNum = 0;
+}
+
+template <const uint8_t BOOT_PROTOCOL>
+uint8_t HIDBoot<BOOT_PROTOCOL>::Init(uint8_t parent, uint8_t port, bool lowspeed) {
+ const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
+
+ uint8_t buf[constBufSize];
+ uint8_t rcode;
+ UsbDevice *p = NULL;
+ EpInfo *oldep_ptr = NULL;
+ uint8_t len = 0;
+ //uint16_t cd_len = 0;
+
+ uint8_t num_of_conf; // number of configurations
+ //uint8_t num_of_intf; // number of interfaces
+
+ AddressPool &addrPool = pUsb->GetAddressPool();
+
+ USBTRACE("BM Init\r\n");
+ //USBTRACE2("totalEndpoints:", (uint8_t) (totalEndpoints(BOOT_PROTOCOL)));
+ //USBTRACE2("epMUL:", epMUL(BOOT_PROTOCOL));
+
+ if(bAddress)
+ return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
+
+ bInterval = 0;
+ // Get pointer to pseudo device with address 0 assigned
+ p = addrPool.GetUsbDevicePtr(0);
+
+ if(!p)
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+ if(!p->epinfo) {
+ USBTRACE("epinfo\r\n");
+ return USB_ERROR_EPINFO_IS_NULL;
+ }
+
+ // Save old pointer to EP_RECORD of address 0
+ oldep_ptr = p->epinfo;
+
+ // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
+ p->epinfo = epInfo;
+
+ p->lowspeed = lowspeed;
+
+ // Get device descriptor
+ rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf);
+
+ if(!rcode)
+ len = (buf[0] > constBufSize) ? constBufSize : buf[0];
+
+ if(rcode) {
+ // Restore p->epinfo
+ p->epinfo = oldep_ptr;
+
+ goto FailGetDevDescr;
+ }
+
+ // Restore p->epinfo
+ p->epinfo = oldep_ptr;
+
+ // Allocate new address according to device class
+ bAddress = addrPool.AllocAddress(parent, false, port);
+
+ if(!bAddress)
+ return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
+
+ // Extract Max Packet Size from the device descriptor
+ epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0;
+
+ // Assign new address to the device
+ rcode = pUsb->setAddr(0, 0, bAddress);
+
+ if(rcode) {
+ p->lowspeed = false;
+ addrPool.FreeAddress(bAddress);
+ bAddress = 0;
+ USBTRACE2("setAddr:", rcode);
+ return rcode;
+ }
+ //delay(2); //per USB 2.0 sect.9.2.6.3
+
+ USBTRACE2("Addr:", bAddress);
+
+ p->lowspeed = false;
+
+ p = addrPool.GetUsbDevicePtr(bAddress);
+
+ if(!p)
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+ p->lowspeed = lowspeed;
+
+ if(len)
+ rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf);
+
+ if(rcode)
+ goto FailGetDevDescr;
+
+ num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations;
+
+ USBTRACE2("NC:", num_of_conf);
+
+ // GCC will optimize unused stuff away.
+ if((BOOT_PROTOCOL & (HID_PROTOCOL_KEYBOARD | HID_PROTOCOL_MOUSE)) == (HID_PROTOCOL_KEYBOARD | HID_PROTOCOL_MOUSE)) {
+ USBTRACE("HID_PROTOCOL_KEYBOARD AND MOUSE\r\n");
+ ConfigDescParser<
+ USB_CLASS_HID,
+ HID_BOOT_INTF_SUBCLASS,
+ HID_PROTOCOL_KEYBOARD | HID_PROTOCOL_MOUSE,
+ CP_MASK_COMPARE_ALL > confDescrParser(this);
+ confDescrParser.SetOR(); // Use the OR variant.
+ for(uint8_t i = 0; i < num_of_conf; i++) {
+ pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
+ if(bNumEP == (uint8_t)(totalEndpoints(BOOT_PROTOCOL)))
+ break;
+ }
+ } else {
+ // GCC will optimize unused stuff away.
+ if(BOOT_PROTOCOL & HID_PROTOCOL_KEYBOARD) {
+ USBTRACE("HID_PROTOCOL_KEYBOARD\r\n");
+ for(uint8_t i = 0; i < num_of_conf; i++) {
+ ConfigDescParser<
+ USB_CLASS_HID,
+ HID_BOOT_INTF_SUBCLASS,
+ HID_PROTOCOL_KEYBOARD,
+ CP_MASK_COMPARE_ALL> confDescrParserA(this);
+
+ pUsb->getConfDescr(bAddress, 0, i, &confDescrParserA);
+ if(bNumEP == (uint8_t)(totalEndpoints(BOOT_PROTOCOL)))
+ break;
+ }
+ }
+
+ // GCC will optimize unused stuff away.
+ if(BOOT_PROTOCOL & HID_PROTOCOL_MOUSE) {
+ USBTRACE("HID_PROTOCOL_MOUSE\r\n");
+ for(uint8_t i = 0; i < num_of_conf; i++) {
+ ConfigDescParser<
+ USB_CLASS_HID,
+ HID_BOOT_INTF_SUBCLASS,
+ HID_PROTOCOL_MOUSE,
+ CP_MASK_COMPARE_ALL> confDescrParserB(this);
+
+ pUsb->getConfDescr(bAddress, 0, i, &confDescrParserB);
+ if(bNumEP == ((uint8_t)(totalEndpoints(BOOT_PROTOCOL))))
+ break;
+
+ }
+ }
+ }
+ USBTRACE2("bNumEP:", bNumEP);
+
+ if(bNumEP != (uint8_t)(totalEndpoints(BOOT_PROTOCOL))) {
+ rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
+ goto Fail;
+ }
+
+ // Assign epInfo to epinfo pointer
+ rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
+ //USBTRACE2("setEpInfoEntry returned ", rcode);
+ USBTRACE2("Cnf:", bConfNum);
+
+ delay(1000);
+
+ // Set Configuration Value
+ rcode = pUsb->setConf(bAddress, 0, bConfNum);
+
+ if(rcode)
+ goto FailSetConfDescr;
+
+ delay(1000);
+
+ USBTRACE2("bIfaceNum:", bIfaceNum);
+ USBTRACE2("bNumIface:", bNumIface);
+
+ // Yes, mouse wants SetProtocol and SetIdle too!
+ for(uint8_t i = 0; i < epMUL(BOOT_PROTOCOL); i++) {
+ USBTRACE2("\r\nInterface:", i);
+ rcode = SetProtocol(i, HID_BOOT_PROTOCOL);
+ if(rcode) goto FailSetProtocol;
+ USBTRACE2("PROTOCOL SET HID_BOOT rcode:", rcode);
+ rcode = SetIdle(i, 0, 0);
+ USBTRACE2("SET_IDLE rcode:", rcode);
+ // if(rcode) goto FailSetIdle; This can fail.
+ // Get the RPIPE and just throw it away.
+ SinkParser<USBReadParser, uint16_t, uint16_t> sink;
+ rcode = GetReportDescr(i, &sink);
+ USBTRACE2("RPIPE rcode:", rcode);
+ }
+
+ // Get RPIPE and throw it away.
+
+ if(BOOT_PROTOCOL & HID_PROTOCOL_KEYBOARD) {
+ // Wake keyboard interface by twinkling up to 5 LEDs that are in the spec.
+ // kana, compose, scroll, caps, num
+ rcode = 0x20; // Reuse rcode.
+ while(rcode) {
+ rcode >>= 1;
+ // Ignore any error returned, we don't care if LED is not supported
+ SetReport(0, 0, 2, 0, 1, &rcode); // Eventually becomes zero (All off)
+ delay(25);
+ }
+ }
+ USBTRACE("BM configured\r\n");
+
+ bPollEnable = true;
+ return 0;
+
+FailGetDevDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailGetDevDescr();
+ goto Fail;
+#endif
+
+ //FailSetDevTblEntry:
+ //#ifdef DEBUG_USB_HOST
+ // NotifyFailSetDevTblEntry();
+ // goto Fail;
+ //#endif
+
+ //FailGetConfDescr:
+ //#ifdef DEBUG_USB_HOST
+ // NotifyFailGetConfDescr();
+ // goto Fail;
+ //#endif
+
+FailSetConfDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailSetConfDescr();
+ goto Fail;
+#endif
+
+FailSetProtocol:
+#ifdef DEBUG_USB_HOST
+ USBTRACE("SetProto:");
+ goto Fail;
+#endif
+
+ //FailSetIdle:
+ //#ifdef DEBUG_USB_HOST
+ // USBTRACE("SetIdle:");
+ //#endif
+
+Fail:
+#ifdef DEBUG_USB_HOST
+ NotifyFail(rcode);
+#endif
+ Release();
+
+ return rcode;
+}
+
+template <const uint8_t BOOT_PROTOCOL>
+void HIDBoot<BOOT_PROTOCOL>::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {
+
+ // If the first configuration satisfies, the others are not considered.
+ //if(bNumEP > 1 && conf != bConfNum)
+ if(bNumEP == totalEndpoints(BOOT_PROTOCOL))
+ return;
+
+ bConfNum = conf;
+ bIfaceNum = iface;
+
+ if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) {
+ if(pep->bInterval > bInterval) bInterval = pep->bInterval;
+
+ // Fill in the endpoint info structure
+ epInfo[bNumEP].epAddr = (pep->bEndpointAddress & 0x0F);
+ epInfo[bNumEP].maxPktSize = (uint8_t)pep->wMaxPacketSize;
+ epInfo[bNumEP].epAttribs = 0;
+ epInfo[bNumEP].bmNakPower = USB_NAK_NOWAIT;
+ bNumEP++;
+
+ }
+}
+
+template <const uint8_t BOOT_PROTOCOL>
+uint8_t HIDBoot<BOOT_PROTOCOL>::Release() {
+ pUsb->GetAddressPool().FreeAddress(bAddress);
+
+ bConfNum = 0;
+ bIfaceNum = 0;
+ bNumEP = 1;
+ bAddress = 0;
+ qNextPollTime = 0;
+ bPollEnable = false;
+
+ return 0;
+}
+
+template <const uint8_t BOOT_PROTOCOL>
+uint8_t HIDBoot<BOOT_PROTOCOL>::Poll() {
+ uint8_t rcode = 0;
+
+ if(bPollEnable && ((long)(millis() - qNextPollTime) >= 0L)) {
+
+ // To-do: optimize manually, using the for loop only if needed.
+ for(int i = 0; i < epMUL(BOOT_PROTOCOL); i++) {
+ const uint16_t const_buff_len = 16;
+ uint8_t buf[const_buff_len];
+
+ USBTRACE3("(hidboot.h) i=", i, 0x81);
+ USBTRACE3("(hidboot.h) epInfo[epInterruptInIndex + i].epAddr=", epInfo[epInterruptInIndex + i].epAddr, 0x81);
+ USBTRACE3("(hidboot.h) epInfo[epInterruptInIndex + i].maxPktSize=", epInfo[epInterruptInIndex + i].maxPktSize, 0x81);
+ uint16_t read = (uint16_t)epInfo[epInterruptInIndex + i].maxPktSize;
+
+ rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex + i].epAddr, &read, buf);
+ // SOME buggy dongles report extra keys (like sleep) using a 2 byte packet on the wrong endpoint.
+ // Since keyboard and mice must report at least 3 bytes, we ignore the extra data.
+ if(!rcode && read > 2) {
+ if(pRptParser[i])
+ pRptParser[i]->Parse((HID*)this, 0, (uint8_t)read, buf);
+#ifdef DEBUG_USB_HOST
+ // We really don't care about errors and anomalies unless we are debugging.
+ } else {
+ if(rcode != hrNAK) {
+ USBTRACE3("(hidboot.h) Poll:", rcode, 0x81);
+ }
+ if(!rcode && read) {
+ USBTRACE3("(hidboot.h) Strange read count: ", read, 0x80);
+ USBTRACE3("(hidboot.h) Interface:", i, 0x80);
+ }
+ }
+
+ if(!rcode && read && (UsbDEBUGlvl > 0x7f)) {
+ for(uint8_t i = 0; i < read; i++) {
+ PrintHex<uint8_t > (buf[i], 0x80);
+ USBTRACE1(" ", 0x80);
+ }
+ if(read)
+ USBTRACE1("\r\n", 0x80);
+#endif
+ }
+
+ }
+ qNextPollTime = millis() + bInterval;
+ }
+ return rcode;
+}
+
+#endif // __HIDBOOTMOUSE_H__
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidescriptorparser.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidescriptorparser.cpp
new file mode 100644
index 000000000..e4491b4e9
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidescriptorparser.cpp
@@ -0,0 +1,1588 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+
+#include "hidescriptorparser.h"
+
+const char * const ReportDescParserBase::usagePageTitles0[] PROGMEM = {
+ pstrUsagePageGenericDesktopControls,
+ pstrUsagePageSimulationControls,
+ pstrUsagePageVRControls,
+ pstrUsagePageSportControls,
+ pstrUsagePageGameControls,
+ pstrUsagePageGenericDeviceControls,
+ pstrUsagePageKeyboardKeypad,
+ pstrUsagePageLEDs,
+ pstrUsagePageButton,
+ pstrUsagePageOrdinal,
+ pstrUsagePageTelephone,
+ pstrUsagePageConsumer,
+ pstrUsagePageDigitizer,
+ pstrUsagePagePID,
+ pstrUsagePageUnicode
+};
+
+const char * const ReportDescParserBase::usagePageTitles1[] PROGMEM = {
+ pstrUsagePageBarCodeScanner,
+ pstrUsagePageScale,
+ pstrUsagePageMSRDevices,
+ pstrUsagePagePointOfSale,
+ pstrUsagePageCameraControl,
+ pstrUsagePageArcade
+};
+const char * const ReportDescParserBase::genDesktopTitles0[] PROGMEM = {
+ pstrUsagePointer,
+ pstrUsageMouse,
+ pstrUsageJoystick,
+ pstrUsageGamePad,
+ pstrUsageKeyboard,
+ pstrUsageKeypad,
+ pstrUsageMultiAxisController,
+ pstrUsageTabletPCSystemControls
+
+};
+const char * const ReportDescParserBase::genDesktopTitles1[] PROGMEM = {
+ pstrUsageX,
+ pstrUsageY,
+ pstrUsageZ,
+ pstrUsageRx,
+ pstrUsageRy,
+ pstrUsageRz,
+ pstrUsageSlider,
+ pstrUsageDial,
+ pstrUsageWheel,
+ pstrUsageHatSwitch,
+ pstrUsageCountedBuffer,
+ pstrUsageByteCount,
+ pstrUsageMotionWakeup,
+ pstrUsageStart,
+ pstrUsageSelect,
+ pstrUsagePageReserved,
+ pstrUsageVx,
+ pstrUsageVy,
+ pstrUsageVz,
+ pstrUsageVbrx,
+ pstrUsageVbry,
+ pstrUsageVbrz,
+ pstrUsageVno,
+ pstrUsageFeatureNotification,
+ pstrUsageResolutionMultiplier
+};
+const char * const ReportDescParserBase::genDesktopTitles2[] PROGMEM = {
+ pstrUsageSystemControl,
+ pstrUsageSystemPowerDown,
+ pstrUsageSystemSleep,
+ pstrUsageSystemWakeup,
+ pstrUsageSystemContextMenu,
+ pstrUsageSystemMainMenu,
+ pstrUsageSystemAppMenu,
+ pstrUsageSystemMenuHelp,
+ pstrUsageSystemMenuExit,
+ pstrUsageSystemMenuSelect,
+ pstrUsageSystemMenuRight,
+ pstrUsageSystemMenuLeft,
+ pstrUsageSystemMenuUp,
+ pstrUsageSystemMenuDown,
+ pstrUsageSystemColdRestart,
+ pstrUsageSystemWarmRestart,
+ pstrUsageDPadUp,
+ pstrUsageDPadDown,
+ pstrUsageDPadRight,
+ pstrUsageDPadLeft
+};
+const char * const ReportDescParserBase::genDesktopTitles3[] PROGMEM = {
+ pstrUsageSystemDock,
+ pstrUsageSystemUndock,
+ pstrUsageSystemSetup,
+ pstrUsageSystemBreak,
+ pstrUsageSystemDebuggerBreak,
+ pstrUsageApplicationBreak,
+ pstrUsageApplicationDebuggerBreak,
+ pstrUsageSystemSpeakerMute,
+ pstrUsageSystemHibernate
+};
+const char * const ReportDescParserBase::genDesktopTitles4[] PROGMEM = {
+ pstrUsageSystemDisplayInvert,
+ pstrUsageSystemDisplayInternal,
+ pstrUsageSystemDisplayExternal,
+ pstrUsageSystemDisplayBoth,
+ pstrUsageSystemDisplayDual,
+ pstrUsageSystemDisplayToggleIntExt,
+ pstrUsageSystemDisplaySwapPriSec,
+ pstrUsageSystemDisplayLCDAutoscale
+};
+const char * const ReportDescParserBase::simuTitles0[] PROGMEM = {
+ pstrUsageFlightSimulationDevice,
+ pstrUsageAutomobileSimulationDevice,
+ pstrUsageTankSimulationDevice,
+ pstrUsageSpaceshipSimulationDevice,
+ pstrUsageSubmarineSimulationDevice,
+ pstrUsageSailingSimulationDevice,
+ pstrUsageMotocicleSimulationDevice,
+ pstrUsageSportsSimulationDevice,
+ pstrUsageAirplaneSimulationDevice,
+ pstrUsageHelicopterSimulationDevice,
+ pstrUsageMagicCarpetSimulationDevice,
+ pstrUsageBicycleSimulationDevice
+};
+const char * const ReportDescParserBase::simuTitles1[] PROGMEM = {
+ pstrUsageFlightControlStick,
+ pstrUsageFlightStick,
+ pstrUsageCyclicControl,
+ pstrUsageCyclicTrim,
+ pstrUsageFlightYoke,
+ pstrUsageTrackControl
+};
+const char * const ReportDescParserBase::simuTitles2[] PROGMEM = {
+ pstrUsageAileron,
+ pstrUsageAileronTrim,
+ pstrUsageAntiTorqueControl,
+ pstrUsageAutopilotEnable,
+ pstrUsageChaffRelease,
+ pstrUsageCollectiveControl,
+ pstrUsageDiveBrake,
+ pstrUsageElectronicCountermeasures,
+ pstrUsageElevator,
+ pstrUsageElevatorTrim,
+ pstrUsageRudder,
+ pstrUsageThrottle,
+ pstrUsageFlightCommunications,
+ pstrUsageFlareRelease,
+ pstrUsageLandingGear,
+ pstrUsageToeBrake,
+ pstrUsageTrigger,
+ pstrUsageWeaponsArm,
+ pstrUsageWeaponsSelect,
+ pstrUsageWingFlaps,
+ pstrUsageAccelerator,
+ pstrUsageBrake,
+ pstrUsageClutch,
+ pstrUsageShifter,
+ pstrUsageSteering,
+ pstrUsageTurretDirection,
+ pstrUsageBarrelElevation,
+ pstrUsageDivePlane,
+ pstrUsageBallast,
+ pstrUsageBicycleCrank,
+ pstrUsageHandleBars,
+ pstrUsageFrontBrake,
+ pstrUsageRearBrake
+};
+const char * const ReportDescParserBase::vrTitles0[] PROGMEM = {
+ pstrUsageBelt,
+ pstrUsageBodySuit,
+ pstrUsageFlexor,
+ pstrUsageGlove,
+ pstrUsageHeadTracker,
+ pstrUsageHeadMountedDisplay,
+ pstrUsageHandTracker,
+ pstrUsageOculometer,
+ pstrUsageVest,
+ pstrUsageAnimatronicDevice
+};
+const char * const ReportDescParserBase::vrTitles1[] PROGMEM = {
+ pstrUsageStereoEnable,
+ pstrUsageDisplayEnable
+};
+const char * const ReportDescParserBase::sportsCtrlTitles0[] PROGMEM = {
+ pstrUsageBaseballBat,
+ pstrUsageGolfClub,
+ pstrUsageRowingMachine,
+ pstrUsageTreadmill
+};
+const char * const ReportDescParserBase::sportsCtrlTitles1[] PROGMEM = {
+ pstrUsageOar,
+ pstrUsageSlope,
+ pstrUsageRate,
+ pstrUsageStickSpeed,
+ pstrUsageStickFaceAngle,
+ pstrUsageStickHeelToe,
+ pstrUsageStickFollowThough,
+ pstrUsageStickTempo,
+ pstrUsageStickType,
+ pstrUsageStickHeight
+};
+const char * const ReportDescParserBase::sportsCtrlTitles2[] PROGMEM = {
+ pstrUsagePutter,
+ pstrUsage1Iron,
+ pstrUsage2Iron,
+ pstrUsage3Iron,
+ pstrUsage4Iron,
+ pstrUsage5Iron,
+ pstrUsage6Iron,
+ pstrUsage7Iron,
+ pstrUsage8Iron,
+ pstrUsage9Iron,
+ pstrUsage10Iron,
+ pstrUsage11Iron,
+ pstrUsageSandWedge,
+ pstrUsageLoftWedge,
+ pstrUsagePowerWedge,
+ pstrUsage1Wood,
+ pstrUsage3Wood,
+ pstrUsage5Wood,
+ pstrUsage7Wood,
+ pstrUsage9Wood
+};
+const char * const ReportDescParserBase::gameTitles0[] PROGMEM = {
+ pstrUsage3DGameController,
+ pstrUsagePinballDevice,
+ pstrUsageGunDevice
+};
+const char * const ReportDescParserBase::gameTitles1[] PROGMEM = {
+ pstrUsagePointOfView,
+ pstrUsageTurnRightLeft,
+ pstrUsagePitchForwardBackward,
+ pstrUsageRollRightLeft,
+ pstrUsageMoveRightLeft,
+ pstrUsageMoveForwardBackward,
+ pstrUsageMoveUpDown,
+ pstrUsageLeanRightLeft,
+ pstrUsageLeanForwardBackward,
+ pstrUsageHeightOfPOV,
+ pstrUsageFlipper,
+ pstrUsageSecondaryFlipper,
+ pstrUsageBump,
+ pstrUsageNewGame,
+ pstrUsageShootBall,
+ pstrUsagePlayer,
+ pstrUsageGunBolt,
+ pstrUsageGunClip,
+ pstrUsageGunSelector,
+ pstrUsageGunSingleShot,
+ pstrUsageGunBurst,
+ pstrUsageGunAutomatic,
+ pstrUsageGunSafety,
+ pstrUsageGamepadFireJump,
+ pstrUsageGamepadTrigger
+};
+const char * const ReportDescParserBase::genDevCtrlTitles[] PROGMEM = {
+ pstrUsageBatteryStrength,
+ pstrUsageWirelessChannel,
+ pstrUsageWirelessID,
+ pstrUsageDiscoverWirelessControl,
+ pstrUsageSecurityCodeCharEntered,
+ pstrUsageSecurityCodeCharErased,
+ pstrUsageSecurityCodeCleared
+};
+const char * const ReportDescParserBase::ledTitles[] PROGMEM = {
+ pstrUsageNumLock,
+ pstrUsageCapsLock,
+ pstrUsageScrollLock,
+ pstrUsageCompose,
+ pstrUsageKana,
+ pstrUsagePower,
+ pstrUsageShift,
+ pstrUsageDoNotDisturb,
+ pstrUsageMute,
+ pstrUsageToneEnable,
+ pstrUsageHighCutFilter,
+ pstrUsageLowCutFilter,
+ pstrUsageEqualizerEnable,
+ pstrUsageSoundFieldOn,
+ pstrUsageSurroundOn,
+ pstrUsageRepeat,
+ pstrUsageStereo,
+ pstrUsageSamplingRateDetect,
+ pstrUsageSpinning,
+ pstrUsageCAV,
+ pstrUsageCLV,
+ pstrUsageRecordingFormatDetect,
+ pstrUsageOffHook,
+ pstrUsageRing,
+ pstrUsageMessageWaiting,
+ pstrUsageDataMode,
+ pstrUsageBatteryOperation,
+ pstrUsageBatteryOK,
+ pstrUsageBatteryLow,
+ pstrUsageSpeaker,
+ pstrUsageHeadSet,
+ pstrUsageHold,
+ pstrUsageMicrophone,
+ pstrUsageCoverage,
+ pstrUsageNightMode,
+ pstrUsageSendCalls,
+ pstrUsageCallPickup,
+ pstrUsageConference,
+ pstrUsageStandBy,
+ pstrUsageCameraOn,
+ pstrUsageCameraOff,
+ pstrUsageOnLine,
+ pstrUsageOffLine,
+ pstrUsageBusy,
+ pstrUsageReady,
+ pstrUsagePaperOut,
+ pstrUsagePaperJam,
+ pstrUsageRemote,
+ pstrUsageForward,
+ pstrUsageReverse,
+ pstrUsageStop,
+ pstrUsageRewind,
+ pstrUsageFastForward,
+ pstrUsagePlay,
+ pstrUsagePause,
+ pstrUsageRecord,
+ pstrUsageError,
+ pstrUsageSelectedIndicator,
+ pstrUsageInUseIndicator,
+ pstrUsageMultiModeIndicator,
+ pstrUsageIndicatorOn,
+ pstrUsageIndicatorFlash,
+ pstrUsageIndicatorSlowBlink,
+ pstrUsageIndicatorFastBlink,
+ pstrUsageIndicatorOff,
+ pstrUsageFlashOnTime,
+ pstrUsageSlowBlinkOnTime,
+ pstrUsageSlowBlinkOffTime,
+ pstrUsageFastBlinkOnTime,
+ pstrUsageFastBlinkOffTime,
+ pstrUsageIndicatorColor,
+ pstrUsageIndicatorRed,
+ pstrUsageIndicatorGreen,
+ pstrUsageIndicatorAmber,
+ pstrUsageGenericIndicator,
+ pstrUsageSystemSuspend,
+ pstrUsageExternalPowerConnected
+};
+const char * const ReportDescParserBase::telTitles0 [] PROGMEM = {
+ pstrUsagePhone,
+ pstrUsageAnsweringMachine,
+ pstrUsageMessageControls,
+ pstrUsageHandset,
+ pstrUsageHeadset,
+ pstrUsageTelephonyKeyPad,
+ pstrUsageProgrammableButton
+};
+const char * const ReportDescParserBase::telTitles1 [] PROGMEM = {
+ pstrUsageHookSwitch,
+ pstrUsageFlash,
+ pstrUsageFeature,
+ pstrUsageHold,
+ pstrUsageRedial,
+ pstrUsageTransfer,
+ pstrUsageDrop,
+ pstrUsagePark,
+ pstrUsageForwardCalls,
+ pstrUsageAlternateFunction,
+ pstrUsageLine,
+ pstrUsageSpeakerPhone,
+ pstrUsageConference,
+ pstrUsageRingEnable,
+ pstrUsageRingSelect,
+ pstrUsagePhoneMute,
+ pstrUsageCallerID,
+ pstrUsageSend
+};
+const char * const ReportDescParserBase::telTitles2 [] PROGMEM = {
+ pstrUsageSpeedDial,
+ pstrUsageStoreNumber,
+ pstrUsageRecallNumber,
+ pstrUsagePhoneDirectory
+};
+const char * const ReportDescParserBase::telTitles3 [] PROGMEM = {
+ pstrUsageVoiceMail,
+ pstrUsageScreenCalls,
+ pstrUsageDoNotDisturb,
+ pstrUsageMessage,
+ pstrUsageAnswerOnOff
+};
+const char * const ReportDescParserBase::telTitles4 [] PROGMEM = {
+ pstrUsageInsideDialTone,
+ pstrUsageOutsideDialTone,
+ pstrUsageInsideRingTone,
+ pstrUsageOutsideRingTone,
+ pstrUsagePriorityRingTone,
+ pstrUsageInsideRingback,
+ pstrUsagePriorityRingback,
+ pstrUsageLineBusyTone,
+ pstrUsageReorderTone,
+ pstrUsageCallWaitingTone,
+ pstrUsageConfirmationTone1,
+ pstrUsageConfirmationTone2,
+ pstrUsageTonesOff,
+ pstrUsageOutsideRingback,
+ pstrUsageRinger
+};
+const char * const ReportDescParserBase::telTitles5 [] PROGMEM = {
+ pstrUsagePhoneKey0,
+ pstrUsagePhoneKey1,
+ pstrUsagePhoneKey2,
+ pstrUsagePhoneKey3,
+ pstrUsagePhoneKey4,
+ pstrUsagePhoneKey5,
+ pstrUsagePhoneKey6,
+ pstrUsagePhoneKey7,
+ pstrUsagePhoneKey8,
+ pstrUsagePhoneKey9,
+ pstrUsagePhoneKeyStar,
+ pstrUsagePhoneKeyPound,
+ pstrUsagePhoneKeyA,
+ pstrUsagePhoneKeyB,
+ pstrUsagePhoneKeyC,
+ pstrUsagePhoneKeyD
+};
+const char * const ReportDescParserBase::consTitles0[] PROGMEM = {
+ pstrUsageConsumerControl,
+ pstrUsageNumericKeyPad,
+ pstrUsageProgrammableButton,
+ pstrUsageMicrophone,
+ pstrUsageHeadphone,
+ pstrUsageGraphicEqualizer
+};
+const char * const ReportDescParserBase::consTitles1[] PROGMEM = {
+ pstrUsagePlus10,
+ pstrUsagePlus100,
+ pstrUsageAMPM
+};
+const char * const ReportDescParserBase::consTitles2[] PROGMEM = {
+ pstrUsagePower,
+ pstrUsageReset,
+ pstrUsageSleep,
+ pstrUsageSleepAfter,
+ pstrUsageSleepMode,
+ pstrUsageIllumination,
+ pstrUsageFunctionButtons
+
+};
+const char * const ReportDescParserBase::consTitles3[] PROGMEM = {
+ pstrUsageMenu,
+ pstrUsageMenuPick,
+ pstrUsageMenuUp,
+ pstrUsageMenuDown,
+ pstrUsageMenuLeft,
+ pstrUsageMenuRight,
+ pstrUsageMenuEscape,
+ pstrUsageMenuValueIncrease,
+ pstrUsageMenuValueDecrease
+};
+const char * const ReportDescParserBase::consTitles4[] PROGMEM = {
+ pstrUsageDataOnScreen,
+ pstrUsageClosedCaption,
+ pstrUsageClosedCaptionSelect,
+ pstrUsageVCRTV,
+ pstrUsageBroadcastMode,
+ pstrUsageSnapshot,
+ pstrUsageStill
+};
+const char * const ReportDescParserBase::consTitles5[] PROGMEM = {
+ pstrUsageSelection,
+ pstrUsageAssignSelection,
+ pstrUsageModeStep,
+ pstrUsageRecallLast,
+ pstrUsageEnterChannel,
+ pstrUsageOrderMovie,
+ pstrUsageChannel,
+ pstrUsageMediaSelection,
+ pstrUsageMediaSelectComputer,
+ pstrUsageMediaSelectTV,
+ pstrUsageMediaSelectWWW,
+ pstrUsageMediaSelectDVD,
+ pstrUsageMediaSelectTelephone,
+ pstrUsageMediaSelectProgramGuide,
+ pstrUsageMediaSelectVideoPhone,
+ pstrUsageMediaSelectGames,
+ pstrUsageMediaSelectMessages,
+ pstrUsageMediaSelectCD,
+ pstrUsageMediaSelectVCR,
+ pstrUsageMediaSelectTuner,
+ pstrUsageQuit,
+ pstrUsageHelp,
+ pstrUsageMediaSelectTape,
+ pstrUsageMediaSelectCable,
+ pstrUsageMediaSelectSatellite,
+ pstrUsageMediaSelectSecurity,
+ pstrUsageMediaSelectHome,
+ pstrUsageMediaSelectCall,
+ pstrUsageChannelIncrement,
+ pstrUsageChannelDecrement,
+ pstrUsageMediaSelectSAP,
+ pstrUsagePageReserved,
+ pstrUsageVCRPlus,
+ pstrUsageOnce,
+ pstrUsageDaily,
+ pstrUsageWeekly,
+ pstrUsageMonthly
+};
+const char * const ReportDescParserBase::consTitles6[] PROGMEM = {
+ pstrUsagePlay,
+ pstrUsagePause,
+ pstrUsageRecord,
+ pstrUsageFastForward,
+ pstrUsageRewind,
+ pstrUsageScanNextTrack,
+ pstrUsageScanPreviousTrack,
+ pstrUsageStop,
+ pstrUsageEject,
+ pstrUsageRandomPlay,
+ pstrUsageSelectDisk,
+ pstrUsageEnterDisk,
+ pstrUsageRepeat,
+ pstrUsageTracking,
+ pstrUsageTrackNormal,
+ pstrUsageSlowTracking,
+ pstrUsageFrameForward,
+ pstrUsageFrameBackwards,
+ pstrUsageMark,
+ pstrUsageClearMark,
+ pstrUsageRepeatFromMark,
+ pstrUsageReturnToMark,
+ pstrUsageSearchMarkForward,
+ pstrUsageSearchMarkBackwards,
+ pstrUsageCounterReset,
+ pstrUsageShowCounter,
+ pstrUsageTrackingIncrement,
+ pstrUsageTrackingDecrement,
+ pstrUsageStopEject,
+ pstrUsagePlayPause,
+ pstrUsagePlaySkip
+};
+const char * const ReportDescParserBase::consTitles7[] PROGMEM = {
+ pstrUsageVolume,
+ pstrUsageBalance,
+ pstrUsageMute,
+ pstrUsageBass,
+ pstrUsageTreble,
+ pstrUsageBassBoost,
+ pstrUsageSurroundMode,
+ pstrUsageLoudness,
+ pstrUsageMPX,
+ pstrUsageVolumeIncrement,
+ pstrUsageVolumeDecrement
+};
+const char * const ReportDescParserBase::consTitles8[] PROGMEM = {
+ pstrUsageSpeedSelect,
+ pstrUsagePlaybackSpeed,
+ pstrUsageStandardPlay,
+ pstrUsageLongPlay,
+ pstrUsageExtendedPlay,
+ pstrUsageSlow
+};
+const char * const ReportDescParserBase::consTitles9[] PROGMEM = {
+ pstrUsageFanEnable,
+ pstrUsageFanSpeed,
+ pstrUsageLightEnable,
+ pstrUsageLightIlluminationLevel,
+ pstrUsageClimateControlEnable,
+ pstrUsageRoomTemperature,
+ pstrUsageSecurityEnable,
+ pstrUsageFireAlarm,
+ pstrUsagePoliceAlarm,
+ pstrUsageProximity,
+ pstrUsageMotion,
+ pstrUsageDuresAlarm,
+ pstrUsageHoldupAlarm,
+ pstrUsageMedicalAlarm
+};
+const char * const ReportDescParserBase::consTitlesA[] PROGMEM = {
+ pstrUsageBalanceRight,
+ pstrUsageBalanceLeft,
+ pstrUsageBassIncrement,
+ pstrUsageBassDecrement,
+ pstrUsageTrebleIncrement,
+ pstrUsageTrebleDecrement
+};
+const char * const ReportDescParserBase::consTitlesB[] PROGMEM = {
+ pstrUsageSpeakerSystem,
+ pstrUsageChannelLeft,
+ pstrUsageChannelRight,
+ pstrUsageChannelCenter,
+ pstrUsageChannelFront,
+ pstrUsageChannelCenterFront,
+ pstrUsageChannelSide,
+ pstrUsageChannelSurround,
+ pstrUsageChannelLowFreqEnhancement,
+ pstrUsageChannelTop,
+ pstrUsageChannelUnknown
+};
+const char * const ReportDescParserBase::consTitlesC[] PROGMEM = {
+ pstrUsageSubChannel,
+ pstrUsageSubChannelIncrement,
+ pstrUsageSubChannelDecrement,
+ pstrUsageAlternateAudioIncrement,
+ pstrUsageAlternateAudioDecrement
+};
+const char * const ReportDescParserBase::consTitlesD[] PROGMEM = {
+ pstrUsageApplicationLaunchButtons,
+ pstrUsageALLaunchButtonConfigTool,
+ pstrUsageALProgrammableButton,
+ pstrUsageALConsumerControlConfig,
+ pstrUsageALWordProcessor,
+ pstrUsageALTextEditor,
+ pstrUsageALSpreadsheet,
+ pstrUsageALGraphicsEditor,
+ pstrUsageALPresentationApp,
+ pstrUsageALDatabaseApp,
+ pstrUsageALEmailReader,
+ pstrUsageALNewsreader,
+ pstrUsageALVoicemail,
+ pstrUsageALContactsAddressBook,
+ pstrUsageALCalendarSchedule,
+ pstrUsageALTaskProjectManager,
+ pstrUsageALLogJournalTimecard,
+ pstrUsageALCheckbookFinance,
+ pstrUsageALCalculator,
+ pstrUsageALAVCapturePlayback,
+ pstrUsageALLocalMachineBrowser,
+ pstrUsageALLANWANBrow,
+ pstrUsageALInternetBrowser,
+ pstrUsageALRemoteNetISPConnect,
+ pstrUsageALNetworkConference,
+ pstrUsageALNetworkChat,
+ pstrUsageALTelephonyDialer,
+ pstrUsageALLogon,
+ pstrUsageALLogoff,
+ pstrUsageALLogonLogoff,
+ pstrUsageALTermLockScrSav,
+ pstrUsageALControlPannel,
+ pstrUsageALCommandLineProcessorRun,
+ pstrUsageALProcessTaskManager,
+ pstrUsageALSelectTaskApplication,
+ pstrUsageALNextTaskApplication,
+ pstrUsageALPreviousTaskApplication,
+ pstrUsageALPreemptiveHaltTaskApp,
+ pstrUsageALIntegratedHelpCenter,
+ pstrUsageALDocuments,
+ pstrUsageALThesaurus,
+ pstrUsageALDictionary,
+ pstrUsageALDesktop,
+ pstrUsageALSpellCheck,
+ pstrUsageALGrammarCheck,
+ pstrUsageALWirelessStatus,
+ pstrUsageALKeyboardLayout,
+ pstrUsageALVirusProtection,
+ pstrUsageALEncryption,
+ pstrUsageALScreenSaver,
+ pstrUsageALAlarms,
+ pstrUsageALClock,
+ pstrUsageALFileBrowser,
+ pstrUsageALPowerStatus,
+ pstrUsageALImageBrowser,
+ pstrUsageALAudioBrowser,
+ pstrUsageALMovieBrowser,
+ pstrUsageALDigitalRightsManager,
+ pstrUsageALDigitalWallet,
+ pstrUsagePageReserved,
+ pstrUsageALInstantMessaging,
+ pstrUsageALOEMFeaturesBrowser,
+ pstrUsageALOEMHelp,
+ pstrUsageALOnlineCommunity,
+ pstrUsageALEntertainmentContentBrow,
+ pstrUsageALOnlineShoppingBrowser,
+ pstrUsageALSmartCardInfoHelp,
+ pstrUsageALMarketMonitorFinBrowser,
+ pstrUsageALCustomCorpNewsBrowser,
+ pstrUsageALOnlineActivityBrowser,
+ pstrUsageALResearchSearchBrowser,
+ pstrUsageALAudioPlayer
+};
+const char * const ReportDescParserBase::consTitlesE[] PROGMEM = {
+ pstrUsageGenericGUIAppControls,
+ pstrUsageACNew,
+ pstrUsageACOpen,
+ pstrUsageACClose,
+ pstrUsageACExit,
+ pstrUsageACMaximize,
+ pstrUsageACMinimize,
+ pstrUsageACSave,
+ pstrUsageACPrint,
+ pstrUsageACProperties,
+ pstrUsageACUndo,
+ pstrUsageACCopy,
+ pstrUsageACCut,
+ pstrUsageACPaste,
+ pstrUsageACSelectAll,
+ pstrUsageACFind,
+ pstrUsageACFindAndReplace,
+ pstrUsageACSearch,
+ pstrUsageACGoto,
+ pstrUsageACHome,
+ pstrUsageACBack,
+ pstrUsageACForward,
+ pstrUsageACStop,
+ pstrUsageACRefresh,
+ pstrUsageACPreviousLink,
+ pstrUsageACNextLink,
+ pstrUsageACBookmarks,
+ pstrUsageACHistory,
+ pstrUsageACSubscriptions,
+ pstrUsageACZoomIn,
+ pstrUsageACZoomOut,
+ pstrUsageACZoom,
+ pstrUsageACFullScreenView,
+ pstrUsageACNormalView,
+ pstrUsageACViewToggle,
+ pstrUsageACScrollUp,
+ pstrUsageACScrollDown,
+ pstrUsageACScroll,
+ pstrUsageACPanLeft,
+ pstrUsageACPanRight,
+ pstrUsageACPan,
+ pstrUsageACNewWindow,
+ pstrUsageACTileHoriz,
+ pstrUsageACTileVert,
+ pstrUsageACFormat,
+ pstrUsageACEdit,
+ pstrUsageACBold,
+ pstrUsageACItalics,
+ pstrUsageACUnderline,
+ pstrUsageACStrikethrough,
+ pstrUsageACSubscript,
+ pstrUsageACSuperscript,
+ pstrUsageACAllCaps,
+ pstrUsageACRotate,
+ pstrUsageACResize,
+ pstrUsageACFlipHorizontal,
+ pstrUsageACFlipVertical,
+ pstrUsageACMirrorHorizontal,
+ pstrUsageACMirrorVertical,
+ pstrUsageACFontSelect,
+ pstrUsageACFontColor,
+ pstrUsageACFontSize,
+ pstrUsageACJustifyLeft,
+ pstrUsageACJustifyCenterH,
+ pstrUsageACJustifyRight,
+ pstrUsageACJustifyBlockH,
+ pstrUsageACJustifyTop,
+ pstrUsageACJustifyCenterV,
+ pstrUsageACJustifyBottom,
+ pstrUsageACJustifyBlockV,
+ pstrUsageACIndentDecrease,
+ pstrUsageACIndentIncrease,
+ pstrUsageACNumberedList,
+ pstrUsageACRestartNumbering,
+ pstrUsageACBulletedList,
+ pstrUsageACPromote,
+ pstrUsageACDemote,
+ pstrUsageACYes,
+ pstrUsageACNo,
+ pstrUsageACCancel,
+ pstrUsageACCatalog,
+ pstrUsageACBuyChkout,
+ pstrUsageACAddToCart,
+ pstrUsageACExpand,
+ pstrUsageACExpandAll,
+ pstrUsageACCollapse,
+ pstrUsageACCollapseAll,
+ pstrUsageACPrintPreview,
+ pstrUsageACPasteSpecial,
+ pstrUsageACInsertMode,
+ pstrUsageACDelete,
+ pstrUsageACLock,
+ pstrUsageACUnlock,
+ pstrUsageACProtect,
+ pstrUsageACUnprotect,
+ pstrUsageACAttachComment,
+ pstrUsageACDeleteComment,
+ pstrUsageACViewComment,
+ pstrUsageACSelectWord,
+ pstrUsageACSelectSentence,
+ pstrUsageACSelectParagraph,
+ pstrUsageACSelectColumn,
+ pstrUsageACSelectRow,
+ pstrUsageACSelectTable,
+ pstrUsageACSelectObject,
+ pstrUsageACRedoRepeat,
+ pstrUsageACSort,
+ pstrUsageACSortAscending,
+ pstrUsageACSortDescending,
+ pstrUsageACFilter,
+ pstrUsageACSetClock,
+ pstrUsageACViewClock,
+ pstrUsageACSelectTimeZone,
+ pstrUsageACEditTimeZone,
+ pstrUsageACSetAlarm,
+ pstrUsageACClearAlarm,
+ pstrUsageACSnoozeAlarm,
+ pstrUsageACResetAlarm,
+ pstrUsageACSyncronize,
+ pstrUsageACSendReceive,
+ pstrUsageACSendTo,
+ pstrUsageACReply,
+ pstrUsageACReplyAll,
+ pstrUsageACForwardMessage,
+ pstrUsageACSend,
+ pstrUsageACAttachFile,
+ pstrUsageACUpload,
+ pstrUsageACDownload,
+ pstrUsageACSetBorders,
+ pstrUsageACInsertRow,
+ pstrUsageACInsertColumn,
+ pstrUsageACInsertFile,
+ pstrUsageACInsertPicture,
+ pstrUsageACInsertObject,
+ pstrUsageACInsertSymbol,
+ pstrUsageACSaveAndClose,
+ pstrUsageACRename,
+ pstrUsageACMerge,
+ pstrUsageACSplit,
+ pstrUsageACDistributeHorizontaly,
+ pstrUsageACDistributeVerticaly
+};
+const char * const ReportDescParserBase::digitTitles0[] PROGMEM = {
+ pstrUsageDigitizer,
+ pstrUsagePen,
+ pstrUsageLightPen,
+ pstrUsageTouchScreen,
+ pstrUsageTouchPad,
+ pstrUsageWhiteBoard,
+ pstrUsageCoordinateMeasuringMachine,
+ pstrUsage3DDigitizer,
+ pstrUsageStereoPlotter,
+ pstrUsageArticulatedArm,
+ pstrUsageArmature,
+ pstrUsageMultiplePointDigitizer,
+ pstrUsageFreeSpaceWand
+};
+const char * const ReportDescParserBase::digitTitles1[] PROGMEM = {
+ pstrUsageStylus,
+ pstrUsagePuck,
+ pstrUsageFinger
+
+};
+const char * const ReportDescParserBase::digitTitles2[] PROGMEM = {
+ pstrUsageTipPressure,
+ pstrUsageBarrelPressure,
+ pstrUsageInRange,
+ pstrUsageTouch,
+ pstrUsageUntouch,
+ pstrUsageTap,
+ pstrUsageQuality,
+ pstrUsageDataValid,
+ pstrUsageTransducerIndex,
+ pstrUsageTabletFunctionKeys,
+ pstrUsageProgramChangeKeys,
+ pstrUsageBatteryStrength,
+ pstrUsageInvert,
+ pstrUsageXTilt,
+ pstrUsageYTilt,
+ pstrUsageAzimuth,
+ pstrUsageAltitude,
+ pstrUsageTwist,
+ pstrUsageTipSwitch,
+ pstrUsageSecondaryTipSwitch,
+ pstrUsageBarrelSwitch,
+ pstrUsageEraser,
+ pstrUsageTabletPick
+};
+const char * const ReportDescParserBase::aplphanumTitles0[] PROGMEM = {
+ pstrUsageAlphanumericDisplay,
+ pstrUsageBitmappedDisplay
+};
+const char * const ReportDescParserBase::aplphanumTitles1[] PROGMEM = {
+ pstrUsageDisplayAttributesReport,
+ pstrUsageASCIICharacterSet,
+ pstrUsageDataReadBack,
+ pstrUsageFontReadBack,
+ pstrUsageDisplayControlReport,
+ pstrUsageClearDisplay,
+ pstrUsageDisplayEnable,
+ pstrUsageScreenSaverDelay,
+ pstrUsageScreenSaverEnable,
+ pstrUsageVerticalScroll,
+ pstrUsageHorizontalScroll,
+ pstrUsageCharacterReport,
+ pstrUsageDisplayData,
+ pstrUsageDisplayStatus,
+ pstrUsageStatusNotReady,
+ pstrUsageStatusReady,
+ pstrUsageErrorNotALoadableCharacter,
+ pstrUsageErrorFotDataCanNotBeRead,
+ pstrUsageCursorPositionReport,
+ pstrUsageRow,
+ pstrUsageColumn,
+ pstrUsageRows,
+ pstrUsageColumns,
+ pstrUsageCursorPixelPosition,
+ pstrUsageCursorMode,
+ pstrUsageCursorEnable,
+ pstrUsageCursorBlink,
+ pstrUsageFontReport,
+ pstrUsageFontData,
+ pstrUsageCharacterWidth,
+ pstrUsageCharacterHeight,
+ pstrUsageCharacterSpacingHorizontal,
+ pstrUsageCharacterSpacingVertical,
+ pstrUsageUnicodeCharset,
+ pstrUsageFont7Segment,
+ pstrUsage7SegmentDirectMap,
+ pstrUsageFont14Segment,
+ pstrUsage14SegmentDirectMap,
+ pstrUsageDisplayBrightness,
+ pstrUsageDisplayContrast,
+ pstrUsageCharacterAttribute,
+ pstrUsageAttributeReadback,
+ pstrUsageAttributeData,
+ pstrUsageCharAttributeEnhance,
+ pstrUsageCharAttributeUnderline,
+ pstrUsageCharAttributeBlink
+};
+const char * const ReportDescParserBase::aplphanumTitles2[] PROGMEM = {
+ pstrUsageBitmapSizeX,
+ pstrUsageBitmapSizeY,
+ pstrUsagePageReserved,
+ pstrUsageBitDepthFormat,
+ pstrUsageDisplayOrientation,
+ pstrUsagePaletteReport,
+ pstrUsagePaletteDataSize,
+ pstrUsagePaletteDataOffset,
+ pstrUsagePaletteData,
+ pstrUsageBlitReport,
+ pstrUsageBlitRectangleX1,
+ pstrUsageBlitRectangleY1,
+ pstrUsageBlitRectangleX2,
+ pstrUsageBlitRectangleY2,
+ pstrUsageBlitData,
+ pstrUsageSoftButton,
+ pstrUsageSoftButtonID,
+ pstrUsageSoftButtonSide,
+ pstrUsageSoftButtonOffset1,
+ pstrUsageSoftButtonOffset2,
+ pstrUsageSoftButtonReport
+};
+const char * const ReportDescParserBase::medInstrTitles0[] PROGMEM = {
+ pstrUsageVCRAcquisition,
+ pstrUsageFreezeThaw,
+ pstrUsageClipStore,
+ pstrUsageUpdate,
+ pstrUsageNext,
+ pstrUsageSave,
+ pstrUsagePrint,
+ pstrUsageMicrophoneEnable
+};
+const char * const ReportDescParserBase::medInstrTitles1[] PROGMEM = {
+ pstrUsageCine,
+ pstrUsageTransmitPower,
+ pstrUsageVolume,
+ pstrUsageFocus,
+ pstrUsageDepth
+};
+const char * const ReportDescParserBase::medInstrTitles2[] PROGMEM = {
+ pstrUsageSoftStepPrimary,
+ pstrUsageSoftStepSecondary
+};
+const char * const ReportDescParserBase::medInstrTitles3[] PROGMEM = {
+ pstrUsageZoomSelect,
+ pstrUsageZoomAdjust,
+ pstrUsageSpectralDopplerModeSelect,
+ pstrUsageSpectralDopplerModeAdjust,
+ pstrUsageColorDopplerModeSelect,
+ pstrUsageColorDopplerModeAdjust,
+ pstrUsageMotionModeSelect,
+ pstrUsageMotionModeAdjust,
+ pstrUsage2DModeSelect,
+ pstrUsage2DModeAdjust
+};
+const char * const ReportDescParserBase::medInstrTitles4[] PROGMEM = {
+ pstrUsageSoftControlSelect,
+ pstrUsageSoftControlAdjust
+};
+
+void ReportDescParserBase::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) {
+ uint16_t cntdn = (uint16_t)len;
+ uint8_t *p = (uint8_t*)pbuf;
+
+
+ totalSize = 0;
+
+ while(cntdn) {
+ //USB_HOST_SERIAL.println("");
+ //PrintHex<uint16_t>(offset + len - cntdn);
+ //USB_HOST_SERIAL.print(":");
+
+ ParseItem(&p, &cntdn);
+
+ //if (ParseItem(&p, &cntdn))
+ // return;
+ }
+ //USBTRACE2("Total:", totalSize);
+}
+
+void ReportDescParserBase::PrintValue(uint8_t *p, uint8_t len) {
+ E_Notify(PSTR("("), 0x80);
+ for(; len; p++, len--)
+ PrintHex<uint8_t > (*p, 0x80);
+ E_Notify(PSTR(")"), 0x80);
+}
+
+void ReportDescParserBase::PrintByteValue(uint8_t data) {
+ E_Notify(PSTR("("), 0x80);
+ PrintHex<uint8_t > (data, 0x80);
+ E_Notify(PSTR(")"), 0x80);
+}
+
+void ReportDescParserBase::PrintItemTitle(uint8_t prefix) {
+ switch(prefix & (TYPE_MASK | TAG_MASK)) {
+ case (TYPE_GLOBAL | TAG_GLOBAL_PUSH):
+ E_Notify(PSTR("\r\nPush"), 0x80);
+ break;
+ case (TYPE_GLOBAL | TAG_GLOBAL_POP):
+ E_Notify(PSTR("\r\nPop"), 0x80);
+ break;
+ case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE):
+ E_Notify(PSTR("\r\nUsage Page"), 0x80);
+ break;
+ case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMIN):
+ E_Notify(PSTR("\r\nLogical Min"), 0x80);
+ break;
+ case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMAX):
+ E_Notify(PSTR("\r\nLogical Max"), 0x80);
+ break;
+ case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMIN):
+ E_Notify(PSTR("\r\nPhysical Min"), 0x80);
+ break;
+ case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMAX):
+ E_Notify(PSTR("\r\nPhysical Max"), 0x80);
+ break;
+ case (TYPE_GLOBAL | TAG_GLOBAL_UNITEXP):
+ E_Notify(PSTR("\r\nUnit Exp"), 0x80);
+ break;
+ case (TYPE_GLOBAL | TAG_GLOBAL_UNIT):
+ E_Notify(PSTR("\r\nUnit"), 0x80);
+ break;
+ case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE):
+ E_Notify(PSTR("\r\nReport Size"), 0x80);
+ break;
+ case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT):
+ E_Notify(PSTR("\r\nReport Count"), 0x80);
+ break;
+ case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID):
+ E_Notify(PSTR("\r\nReport Id"), 0x80);
+ break;
+ case (TYPE_LOCAL | TAG_LOCAL_USAGE):
+ E_Notify(PSTR("\r\nUsage"), 0x80);
+ break;
+ case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN):
+ E_Notify(PSTR("\r\nUsage Min"), 0x80);
+ break;
+ case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX):
+ E_Notify(PSTR("\r\nUsage Max"), 0x80);
+ break;
+ case (TYPE_MAIN | TAG_MAIN_COLLECTION):
+ E_Notify(PSTR("\r\nCollection"), 0x80);
+ break;
+ case (TYPE_MAIN | TAG_MAIN_ENDCOLLECTION):
+ E_Notify(PSTR("\r\nEnd Collection"), 0x80);
+ break;
+ case (TYPE_MAIN | TAG_MAIN_INPUT):
+ E_Notify(PSTR("\r\nInput"), 0x80);
+ break;
+ case (TYPE_MAIN | TAG_MAIN_OUTPUT):
+ E_Notify(PSTR("\r\nOutput"), 0x80);
+ break;
+ case (TYPE_MAIN | TAG_MAIN_FEATURE):
+ E_Notify(PSTR("\r\nFeature"), 0x80);
+ break;
+ } // switch (**pp & (TYPE_MASK | TAG_MASK))
+}
+
+uint8_t ReportDescParserBase::ParseItem(uint8_t **pp, uint16_t *pcntdn) {
+ //uint8_t ret = enErrorSuccess;
+ //reinterpret_cast<>(varBuffer);
+ switch(itemParseState) {
+ case 0:
+ if(**pp == HID_LONG_ITEM_PREFIX)
+ USBTRACE("\r\nLONG\r\n");
+ else {
+ uint8_t size = ((**pp) & DATA_SIZE_MASK);
+
+ itemPrefix = (**pp);
+ itemSize = 1 + ((size == DATA_SIZE_4) ? 4 : size);
+
+ PrintItemTitle(itemPrefix);
+ }
+ (*pp)++;
+ (*pcntdn)--;
+ itemSize--;
+ itemParseState = 1;
+
+ if(!itemSize)
+ break;
+
+ if(!pcntdn)
+ return enErrorIncomplete;
+ case 1:
+ //USBTRACE2("\r\niSz:",itemSize);
+
+ theBuffer.valueSize = itemSize;
+ valParser.Initialize(&theBuffer);
+ itemParseState = 2;
+ case 2:
+ if(!valParser.Parse(pp, pcntdn))
+ return enErrorIncomplete;
+ itemParseState = 3;
+ case 3:
+ {
+ uint8_t data = *((uint8_t*)varBuffer);
+
+ switch(itemPrefix & (TYPE_MASK | TAG_MASK)) {
+ case (TYPE_LOCAL | TAG_LOCAL_USAGE):
+ if(pfUsage) {
+ if(theBuffer.valueSize > 1) {
+ uint16_t* ui16 = reinterpret_cast<uint16_t *>(varBuffer);
+ pfUsage(*ui16);
+ } else
+ pfUsage(data);
+ }
+ break;
+ case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE):
+ rptSize = data;
+ PrintByteValue(data);
+ break;
+ case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT):
+ rptCount = data;
+ PrintByteValue(data);
+ break;
+ case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMIN):
+ case (TYPE_GLOBAL | TAG_GLOBAL_LOGICALMAX):
+ case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMIN):
+ case (TYPE_GLOBAL | TAG_GLOBAL_PHYSMAX):
+ case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID):
+ case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN):
+ case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX):
+ case (TYPE_GLOBAL | TAG_GLOBAL_UNITEXP):
+ case (TYPE_GLOBAL | TAG_GLOBAL_UNIT):
+ PrintValue(varBuffer, theBuffer.valueSize);
+ break;
+ case (TYPE_GLOBAL | TAG_GLOBAL_PUSH):
+ case (TYPE_GLOBAL | TAG_GLOBAL_POP):
+ break;
+ case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE):
+ SetUsagePage(data);
+ PrintUsagePage(data);
+ PrintByteValue(data);
+ break;
+ case (TYPE_MAIN | TAG_MAIN_COLLECTION):
+ case (TYPE_MAIN | TAG_MAIN_ENDCOLLECTION):
+ switch(data) {
+ case 0x00:
+ E_Notify(PSTR(" Physical"), 0x80);
+ break;
+ case 0x01:
+ E_Notify(PSTR(" Application"), 0x80);
+ break;
+ case 0x02:
+ E_Notify(PSTR(" Logical"), 0x80);
+ break;
+ case 0x03:
+ E_Notify(PSTR(" Report"), 0x80);
+ break;
+ case 0x04:
+ E_Notify(PSTR(" Named Array"), 0x80);
+ break;
+ case 0x05:
+ E_Notify(PSTR(" Usage Switch"), 0x80);
+ break;
+ case 0x06:
+ E_Notify(PSTR(" Usage Modifier"), 0x80);
+ break;
+ default:
+ E_Notify(PSTR(" Vendor Defined("), 0x80);
+ PrintHex<uint8_t > (data, 0x80);
+ E_Notify(PSTR(")"), 0x80);
+ }
+ break;
+ case (TYPE_MAIN | TAG_MAIN_INPUT):
+ case (TYPE_MAIN | TAG_MAIN_OUTPUT):
+ case (TYPE_MAIN | TAG_MAIN_FEATURE):
+ totalSize += (uint16_t)rptSize * (uint16_t)rptCount;
+ rptSize = 0;
+ rptCount = 0;
+ E_Notify(PSTR("("), 0x80);
+ PrintBin<uint8_t > (data, 0x80);
+ E_Notify(PSTR(")"), 0x80);
+ break;
+ } // switch (**pp & (TYPE_MASK | TAG_MASK))
+ }
+ } // switch (itemParseState)
+ itemParseState = 0;
+ return enErrorSuccess;
+}
+
+ReportDescParserBase::UsagePageFunc ReportDescParserBase::usagePageFunctions[] /*PROGMEM*/ = {
+ &ReportDescParserBase::PrintGenericDesktopPageUsage,
+ &ReportDescParserBase::PrintSimulationControlsPageUsage,
+ &ReportDescParserBase::PrintVRControlsPageUsage,
+ &ReportDescParserBase::PrintSportsControlsPageUsage,
+ &ReportDescParserBase::PrintGameControlsPageUsage,
+ &ReportDescParserBase::PrintGenericDeviceControlsPageUsage,
+ NULL, // Keyboard/Keypad
+ &ReportDescParserBase::PrintLEDPageUsage,
+ &ReportDescParserBase::PrintButtonPageUsage,
+ &ReportDescParserBase::PrintOrdinalPageUsage,
+ &ReportDescParserBase::PrintTelephonyPageUsage,
+ &ReportDescParserBase::PrintConsumerPageUsage,
+ &ReportDescParserBase::PrintDigitizerPageUsage,
+ NULL, // Reserved
+ NULL, // PID
+ NULL // Unicode
+};
+
+void ReportDescParserBase::SetUsagePage(uint16_t page) {
+ pfUsage = NULL;
+
+ if(VALUE_BETWEEN(page, 0x00, 0x11)) {
+ pfUsage = (usagePageFunctions[page - 1]);
+
+ } else {
+ switch(page) {
+ case 0x14:
+ pfUsage = &ReportDescParserBase::PrintAlphanumDisplayPageUsage;
+ break;
+ case 0x40:
+ pfUsage = &ReportDescParserBase::PrintMedicalInstrumentPageUsage;
+ break;
+ }
+ }
+}
+
+void ReportDescParserBase::PrintUsagePage(uint16_t page) {
+ const char * const * w;
+ E_Notify(pstrSpace, 0x80);
+
+ output_if_between(page, 0x00, 0x11, w, E_Notify, usagePageTitles0, 0x80)
+ else output_if_between(page, 0x8b, 0x92, w, E_Notify, usagePageTitles1, 0x80)
+ else if(VALUE_BETWEEN(page, 0x7f, 0x84))
+ E_Notify(pstrUsagePageMonitor, 0x80);
+ else if(VALUE_BETWEEN(page, 0x83, 0x8c))
+ E_Notify(pstrUsagePagePower, 0x80);
+ else if(page > 0xfeff /* && page <= 0xffff */)
+ E_Notify(pstrUsagePageVendorDefined, 0x80);
+ else
+ switch(page) {
+ case 0x14:
+ E_Notify(pstrUsagePageAlphaNumericDisplay, 0x80);
+ break;
+ case 0x40:
+ E_Notify(pstrUsagePageMedicalInstruments, 0x80);
+ break;
+ default:
+ E_Notify(pstrUsagePageUndefined, 0x80);
+ }
+}
+
+void ReportDescParserBase::PrintButtonPageUsage(uint16_t usage) {
+ E_Notify(pstrSpace, 0x80);
+ E_Notify(PSTR("Btn"), 0x80);
+ PrintHex<uint16_t > (usage, 0x80);
+ E_Notify(PSTR("\r\n"), 0x80);
+ //USB_HOST_SERIAL.print(usage, HEX);
+}
+
+void ReportDescParserBase::PrintOrdinalPageUsage(uint16_t usage) {
+ E_Notify(pstrSpace, 0x80);
+ E_Notify(PSTR("Inst"), 0x80);
+ // Sorry, HEX for now...
+ PrintHex<uint16_t > (usage, 0x80);
+ E_Notify(PSTR("\r\n"), 0x80);
+ //USB_HOST_SERIAL.print(usage, DEC);
+}
+
+void ReportDescParserBase::PrintGenericDesktopPageUsage(uint16_t usage) {
+ const char * const * w;
+ E_Notify(pstrSpace, 0x80);
+
+ output_if_between(usage, 0x00, 0x0a, w, E_Notify, genDesktopTitles0, 0x80)
+ else output_if_between(usage, 0x2f, 0x49, w, E_Notify, genDesktopTitles1, 0x80)
+ else output_if_between(usage, 0x7f, 0x94, w, E_Notify, genDesktopTitles2, 0x80)
+ else output_if_between(usage, 0x9f, 0xa9, w, E_Notify, genDesktopTitles3, 0x80)
+ else output_if_between(usage, 0xaf, 0xb8, w, E_Notify, genDesktopTitles4, 0x80)
+ else E_Notify(pstrUsagePageUndefined, 0x80);
+}
+
+void ReportDescParserBase::PrintSimulationControlsPageUsage(uint16_t usage) {
+ const char * const * w;
+ E_Notify(pstrSpace, 0x80);
+
+ output_if_between(usage, 0x00, 0x0d, w, E_Notify, simuTitles0, 0x80)
+ else output_if_between(usage, 0x1f, 0x26, w, E_Notify, simuTitles1, 0x80)
+ else output_if_between(usage, 0xaf, 0xd1, w, E_Notify, simuTitles2, 0x80)
+ else E_Notify(pstrUsagePageUndefined, 0x80);
+}
+
+void ReportDescParserBase::PrintVRControlsPageUsage(uint16_t usage) {
+ const char * const * w;
+ E_Notify(pstrSpace, 0x80);
+
+ output_if_between(usage, 0x00, 0x0b, w, E_Notify, vrTitles0, 0x80)
+ else output_if_between(usage, 0x1f, 0x22, w, E_Notify, vrTitles1, 0x80)
+ else E_Notify(pstrUsagePageUndefined, 0x80);
+}
+
+void ReportDescParserBase::PrintSportsControlsPageUsage(uint16_t usage) {
+ const char * const * w;
+ E_Notify(pstrSpace, 0x80);
+
+ output_if_between(usage, 0x00, 0x05, w, E_Notify, sportsCtrlTitles0, 0x80)
+ else output_if_between(usage, 0x2f, 0x3a, w, E_Notify, sportsCtrlTitles1, 0x80)
+ else output_if_between(usage, 0x4f, 0x64, w, E_Notify, sportsCtrlTitles2, 0x80)
+ else E_Notify(pstrUsagePageUndefined, 0x80);
+}
+
+void ReportDescParserBase::PrintGameControlsPageUsage(uint16_t usage) {
+ const char * const * w;
+ E_Notify(pstrSpace, 0x80);
+
+ output_if_between(usage, 0x00, 0x04, w, E_Notify, gameTitles0, 0x80)
+ else output_if_between(usage, 0x1f, 0x3a, w, E_Notify, gameTitles1, 0x80)
+ else E_Notify(pstrUsagePageUndefined, 0x80);
+}
+
+void ReportDescParserBase::PrintGenericDeviceControlsPageUsage(uint16_t usage) {
+ const char * const * w;
+ E_Notify(pstrSpace, 0x80);
+
+ output_if_between(usage, 0x1f, 0x27, w, E_Notify, genDevCtrlTitles, 0x80)
+ else E_Notify(pstrUsagePageUndefined, 0x80);
+}
+
+void ReportDescParserBase::PrintLEDPageUsage(uint16_t usage) {
+ const char * const * w;
+ E_Notify(pstrSpace, 0x80);
+
+ output_if_between(usage, 0x00, 0x4e, w, E_Notify, ledTitles, 0x80)
+ else E_Notify(pstrUsagePageUndefined, 0x80);
+}
+
+void ReportDescParserBase::PrintTelephonyPageUsage(uint16_t usage) {
+ const char * const * w;
+ E_Notify(pstrSpace, 0x80);
+
+ output_if_between(usage, 0x00, 0x08, w, E_Notify, telTitles0, 0x80)
+ else output_if_between(usage, 0x1f, 0x32, w, E_Notify, telTitles1, 0x80)
+ else output_if_between(usage, 0x4f, 0x54, w, E_Notify, telTitles2, 0x80)
+ else output_if_between(usage, 0x6f, 0x75, w, E_Notify, telTitles3, 0x80)
+ else output_if_between(usage, 0x8f, 0x9f, w, E_Notify, telTitles4, 0x80)
+ else output_if_between(usage, 0xaf, 0xc0, w, E_Notify, telTitles5, 0x80)
+ else E_Notify(pstrUsagePageUndefined, 0x80);
+}
+
+void ReportDescParserBase::PrintConsumerPageUsage(uint16_t usage) {
+ const char * const * w;
+ E_Notify(pstrSpace, 0x80);
+
+ output_if_between(usage, 0x00, 0x07, w, E_Notify, consTitles0, 0x80)
+ else output_if_between(usage, 0x1f, 0x23, w, E_Notify, consTitles1, 0x80)
+ else output_if_between(usage, 0x2f, 0x37, w, E_Notify, consTitles2, 0x80)
+ else output_if_between(usage, 0x3f, 0x49, w, E_Notify, consTitles3, 0x80)
+ else output_if_between(usage, 0x5f, 0x67, w, E_Notify, consTitles4, 0x80)
+ else output_if_between(usage, 0x7f, 0xa5, w, E_Notify, consTitles5, 0x80)
+ else output_if_between(usage, 0xaf, 0xcf, w, E_Notify, consTitles6, 0x80)
+ else output_if_between(usage, 0xdf, 0xeb, w, E_Notify, consTitles7, 0x80)
+ else output_if_between(usage, 0xef, 0xf6, w, E_Notify, consTitles8, 0x80)
+ else output_if_between(usage, 0xff, 0x10e, w, E_Notify, consTitles9, 0x80)
+ else output_if_between(usage, 0x14f, 0x156, w, E_Notify, consTitlesA, 0x80)
+ else output_if_between(usage, 0x15f, 0x16b, w, E_Notify, consTitlesB, 0x80)
+ else output_if_between(usage, 0x16f, 0x175, w, E_Notify, consTitlesC, 0x80)
+ else output_if_between(usage, 0x17f, 0x1c8, w, E_Notify, consTitlesD, 0x80)
+ else output_if_between(usage, 0x1ff, 0x29d, w, E_Notify, consTitlesE, 0x80)
+ else E_Notify(pstrUsagePageUndefined, 0x80);
+}
+
+void ReportDescParserBase::PrintDigitizerPageUsage(uint16_t usage) {
+ const char * const * w;
+ E_Notify(pstrSpace, 0x80);
+
+ output_if_between(usage, 0x00, 0x0e, w, E_Notify, digitTitles0, 0x80)
+ else output_if_between(usage, 0x1f, 0x23, w, E_Notify, digitTitles1, 0x80)
+ else output_if_between(usage, 0x2f, 0x47, w, E_Notify, digitTitles2, 0x80)
+ else E_Notify(pstrUsagePageUndefined, 0x80);
+}
+
+void ReportDescParserBase::PrintAlphanumDisplayPageUsage(uint16_t usage) {
+ const char * const * w;
+ E_Notify(pstrSpace, 0x80);
+
+ output_if_between(usage, 0x00, 0x03, w, E_Notify, aplphanumTitles0, 0x80)
+ else output_if_between(usage, 0x1f, 0x4e, w, E_Notify, aplphanumTitles1, 0x80)
+ else output_if_between(usage, 0x7f, 0x96, w, E_Notify, digitTitles2, 0x80)
+ else E_Notify(pstrUsagePageUndefined, 0x80);
+}
+
+void ReportDescParserBase::PrintMedicalInstrumentPageUsage(uint16_t usage) {
+ const char * const * w;
+ E_Notify(pstrSpace, 0x80);
+
+ if(usage == 1) E_Notify(pstrUsageMedicalUltrasound, 0x80);
+ else if(usage == 0x70)
+ E_Notify(pstrUsageDepthGainCompensation, 0x80);
+ else output_if_between(usage, 0x1f, 0x28, w, E_Notify, medInstrTitles0, 0x80)
+ else output_if_between(usage, 0x3f, 0x45, w, E_Notify, medInstrTitles1, 0x80)
+ else output_if_between(usage, 0x5f, 0x62, w, E_Notify, medInstrTitles2, 0x80)
+ else output_if_between(usage, 0x7f, 0x8a, w, E_Notify, medInstrTitles3, 0x80)
+ else output_if_between(usage, 0x9f, 0xa2, w, E_Notify, medInstrTitles4, 0x80)
+ else E_Notify(pstrUsagePageUndefined, 0x80);
+}
+
+uint8_t ReportDescParser2::ParseItem(uint8_t **pp, uint16_t *pcntdn) {
+ //uint8_t ret = enErrorSuccess;
+
+ switch(itemParseState) {
+ case 0:
+ if(**pp == HID_LONG_ITEM_PREFIX)
+ USBTRACE("\r\nLONG\r\n");
+ else {
+ uint8_t size = ((**pp) & DATA_SIZE_MASK);
+ itemPrefix = (**pp);
+ itemSize = 1 + ((size == DATA_SIZE_4) ? 4 : size);
+ }
+ (*pp)++;
+ (*pcntdn)--;
+ itemSize--;
+ itemParseState = 1;
+
+ if(!itemSize)
+ break;
+
+ if(!pcntdn)
+ return enErrorIncomplete;
+ case 1:
+ theBuffer.valueSize = itemSize;
+ valParser.Initialize(&theBuffer);
+ itemParseState = 2;
+ case 2:
+ if(!valParser.Parse(pp, pcntdn))
+ return enErrorIncomplete;
+ itemParseState = 3;
+ case 3:
+ {
+ uint8_t data = *((uint8_t*)varBuffer);
+
+ switch(itemPrefix & (TYPE_MASK | TAG_MASK)) {
+ case (TYPE_LOCAL | TAG_LOCAL_USAGE):
+ if(pfUsage) {
+ if(theBuffer.valueSize > 1) {
+ uint16_t* ui16 = reinterpret_cast<uint16_t *>(varBuffer);
+ pfUsage(*ui16);
+ } else
+ pfUsage(data);
+ }
+ break;
+ case (TYPE_GLOBAL | TAG_GLOBAL_REPORTSIZE):
+ rptSize = data;
+ break;
+ case (TYPE_GLOBAL | TAG_GLOBAL_REPORTCOUNT):
+ rptCount = data;
+ break;
+ case (TYPE_GLOBAL | TAG_GLOBAL_REPORTID):
+ rptId = data;
+ break;
+ case (TYPE_LOCAL | TAG_LOCAL_USAGEMIN):
+ useMin = data;
+ break;
+ case (TYPE_LOCAL | TAG_LOCAL_USAGEMAX):
+ useMax = data;
+ break;
+ case (TYPE_GLOBAL | TAG_GLOBAL_USAGEPAGE):
+ SetUsagePage(data);
+ break;
+ case (TYPE_MAIN | TAG_MAIN_OUTPUT):
+ case (TYPE_MAIN | TAG_MAIN_FEATURE):
+ rptSize = 0;
+ rptCount = 0;
+ useMin = 0;
+ useMax = 0;
+ break;
+ case (TYPE_MAIN | TAG_MAIN_INPUT):
+ OnInputItem(data);
+
+ totalSize += (uint16_t)rptSize * (uint16_t)rptCount;
+
+ rptSize = 0;
+ rptCount = 0;
+ useMin = 0;
+ useMax = 0;
+ break;
+ } // switch (**pp & (TYPE_MASK | TAG_MASK))
+ }
+ } // switch (itemParseState)
+ itemParseState = 0;
+ return enErrorSuccess;
+}
+
+void ReportDescParser2::OnInputItem(uint8_t itm) {
+ uint8_t byte_offset = (totalSize >> 3); // calculate offset to the next unhandled byte i = (int)(totalCount / 8);
+ uint32_t tmp = (byte_offset << 3);
+ uint8_t bit_offset = totalSize - tmp; // number of bits in the current byte already handled
+ uint8_t *p = pBuf + byte_offset; // current byte pointer
+
+ if(bit_offset)
+ *p >>= bit_offset;
+
+ uint8_t usage = useMin;
+
+ bool print_usemin_usemax = ((useMin < useMax) && ((itm & 3) == 2) && pfUsage) ? true : false;
+
+ uint8_t bits_of_byte = 8;
+
+ // for each field in field array defined by rptCount
+ for(uint8_t field = 0; field < rptCount; field++, usage++) {
+
+ union {
+ uint8_t bResult[4];
+ uint16_t wResult[2];
+ uint32_t dwResult;
+ } result;
+
+ result.dwResult = 0;
+ uint8_t mask = 0;
+
+ if(print_usemin_usemax)
+ pfUsage(usage);
+
+ // bits_left - number of bits in the field(array of fields, depending on Report Count) left to process
+ // bits_of_byte - number of bits in current byte left to process
+ // bits_to_copy - number of bits to copy to result buffer
+
+ // for each bit in a field
+ for(uint8_t bits_left = rptSize, bits_to_copy = 0; bits_left;
+ bits_left -= bits_to_copy) {
+ bits_to_copy = (bits_left > bits_of_byte) ? bits_of_byte : bits_left;
+
+ result.dwResult <<= bits_to_copy; // Result buffer is shifted by the number of bits to be copied into it
+
+ uint8_t val = *p;
+
+ val >>= (8 - bits_of_byte); // Shift by the number of bits already processed
+
+ mask = 0;
+
+ for(uint8_t j = bits_to_copy; j; j--) {
+ mask <<= 1;
+ mask |= 1;
+ }
+
+ result.bResult[0] = (result.bResult[0] | (val & mask));
+
+ bits_of_byte -= bits_to_copy;
+
+ if(bits_of_byte < 1) {
+ bits_of_byte = 8;
+ p++;
+ }
+ }
+ PrintByteValue(result.dwResult);
+ }
+ E_Notify(PSTR("\r\n"), 0x80);
+}
+
+void UniversalReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
+ ReportDescParser2 prs(len, buf);
+
+ uint8_t ret = hid->GetReportDescr(0, &prs);
+
+ if(ret)
+ ErrorMessage<uint8_t > (PSTR("GetReportDescr-2"), ret);
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidescriptorparser.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidescriptorparser.h
new file mode 100644
index 000000000..f3b496ffa
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidescriptorparser.h
@@ -0,0 +1,176 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+#if !defined(__HIDDESCRIPTORPARSER_H__)
+#define __HIDDESCRIPTORPARSER_H__
+
+#include "hid.h"
+
+class ReportDescParserBase : public USBReadParser {
+public:
+ typedef void (*UsagePageFunc)(uint16_t usage);
+
+ static void PrintGenericDesktopPageUsage(uint16_t usage);
+ static void PrintSimulationControlsPageUsage(uint16_t usage);
+ static void PrintVRControlsPageUsage(uint16_t usage);
+ static void PrintSportsControlsPageUsage(uint16_t usage);
+ static void PrintGameControlsPageUsage(uint16_t usage);
+ static void PrintGenericDeviceControlsPageUsage(uint16_t usage);
+ static void PrintLEDPageUsage(uint16_t usage);
+ static void PrintButtonPageUsage(uint16_t usage);
+ static void PrintOrdinalPageUsage(uint16_t usage);
+ static void PrintTelephonyPageUsage(uint16_t usage);
+ static void PrintConsumerPageUsage(uint16_t usage);
+ static void PrintDigitizerPageUsage(uint16_t usage);
+ static void PrintAlphanumDisplayPageUsage(uint16_t usage);
+ static void PrintMedicalInstrumentPageUsage(uint16_t usage);
+
+ static void PrintValue(uint8_t *p, uint8_t len);
+ static void PrintByteValue(uint8_t data);
+
+ static void PrintItemTitle(uint8_t prefix);
+
+ static const char * const usagePageTitles0[];
+ static const char * const usagePageTitles1[];
+ static const char * const genDesktopTitles0[];
+ static const char * const genDesktopTitles1[];
+ static const char * const genDesktopTitles2[];
+ static const char * const genDesktopTitles3[];
+ static const char * const genDesktopTitles4[];
+ static const char * const simuTitles0[];
+ static const char * const simuTitles1[];
+ static const char * const simuTitles2[];
+ static const char * const vrTitles0[];
+ static const char * const vrTitles1[];
+ static const char * const sportsCtrlTitles0[];
+ static const char * const sportsCtrlTitles1[];
+ static const char * const sportsCtrlTitles2[];
+ static const char * const gameTitles0[];
+ static const char * const gameTitles1[];
+ static const char * const genDevCtrlTitles[];
+ static const char * const ledTitles[];
+ static const char * const telTitles0[];
+ static const char * const telTitles1[];
+ static const char * const telTitles2[];
+ static const char * const telTitles3[];
+ static const char * const telTitles4[];
+ static const char * const telTitles5[];
+ static const char * const consTitles0[];
+ static const char * const consTitles1[];
+ static const char * const consTitles2[];
+ static const char * const consTitles3[];
+ static const char * const consTitles4[];
+ static const char * const consTitles5[];
+ static const char * const consTitles6[];
+ static const char * const consTitles7[];
+ static const char * const consTitles8[];
+ static const char * const consTitles9[];
+ static const char * const consTitlesA[];
+ static const char * const consTitlesB[];
+ static const char * const consTitlesC[];
+ static const char * const consTitlesD[];
+ static const char * const consTitlesE[];
+ static const char * const digitTitles0[];
+ static const char * const digitTitles1[];
+ static const char * const digitTitles2[];
+ static const char * const aplphanumTitles0[];
+ static const char * const aplphanumTitles1[];
+ static const char * const aplphanumTitles2[];
+ static const char * const medInstrTitles0[];
+ static const char * const medInstrTitles1[];
+ static const char * const medInstrTitles2[];
+ static const char * const medInstrTitles3[];
+ static const char * const medInstrTitles4[];
+
+protected:
+ static UsagePageFunc usagePageFunctions[];
+
+ MultiValueBuffer theBuffer;
+ MultiByteValueParser valParser;
+ ByteSkipper theSkipper;
+ uint8_t varBuffer[sizeof (USB_CONFIGURATION_DESCRIPTOR)];
+
+ uint8_t itemParseState; // Item parser state variable
+ uint8_t itemSize; // Item size
+ uint8_t itemPrefix; // Item prefix (first byte)
+ uint8_t rptSize; // Report Size
+ uint8_t rptCount; // Report Count
+
+ uint16_t totalSize; // Report size in bits
+
+ // Method should be defined here if virtual.
+ virtual uint8_t ParseItem(uint8_t **pp, uint16_t *pcntdn);
+
+ UsagePageFunc pfUsage;
+
+ static void PrintUsagePage(uint16_t page);
+ void SetUsagePage(uint16_t page);
+
+public:
+
+ ReportDescParserBase() :
+ itemParseState(0),
+ itemSize(0),
+ itemPrefix(0),
+ rptSize(0),
+ rptCount(0),
+ pfUsage(NULL) {
+ theBuffer.pValue = varBuffer;
+ valParser.Initialize(&theBuffer);
+ theSkipper.Initialize(&theBuffer);
+ };
+
+ void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset);
+
+ enum {
+ enErrorSuccess = 0
+ , enErrorIncomplete // value or record is partialy read in buffer
+ , enErrorBufferTooSmall
+ };
+};
+
+class ReportDescParser : public ReportDescParserBase {
+};
+
+class ReportDescParser2 : public ReportDescParserBase {
+ uint8_t rptId; // Report ID
+ uint8_t useMin; // Usage Minimum
+ uint8_t useMax; // Usage Maximum
+ uint8_t fieldCount; // Number of field being currently processed
+
+ void OnInputItem(uint8_t itm); // Method which is called every time Input item is found
+
+ uint8_t *pBuf; // Report buffer pointer
+ uint8_t bLen; // Report length
+
+protected:
+ // Method should be defined here if virtual.
+ virtual uint8_t ParseItem(uint8_t **pp, uint16_t *pcntdn);
+
+public:
+
+ ReportDescParser2(uint16_t len, uint8_t *pbuf) :
+ ReportDescParserBase(), rptId(0), useMin(0), useMax(0), fieldCount(0), pBuf(pbuf), bLen(len) {
+ };
+};
+
+class UniversalReportParser : public HIDReportParser {
+public:
+ // Method should be defined here if virtual.
+ virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
+};
+
+#endif // __HIDDESCRIPTORPARSER_H__
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hiduniversal.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hiduniversal.cpp
new file mode 100644
index 000000000..395aa69e3
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hiduniversal.cpp
@@ -0,0 +1,425 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+
+#include "hiduniversal.h"
+
+HIDUniversal::HIDUniversal(USB *p) :
+HID(p),
+qNextPollTime(0),
+pollInterval(0),
+bPollEnable(false),
+bHasReportId(false) {
+ Initialize();
+
+ if(pUsb)
+ pUsb->RegisterDeviceClass(this);
+}
+
+uint16_t HIDUniversal::GetHidClassDescrLen(uint8_t type, uint8_t num) {
+ for(uint8_t i = 0, n = 0; i < HID_MAX_HID_CLASS_DESCRIPTORS; i++) {
+ if(descrInfo[i].bDescrType == type) {
+ if(n == num)
+ return descrInfo[i].wDescriptorLength;
+ n++;
+ }
+ }
+ return 0;
+}
+
+void HIDUniversal::Initialize() {
+ for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) {
+ rptParsers[i].rptId = 0;
+ rptParsers[i].rptParser = NULL;
+ }
+ for(uint8_t i = 0; i < HID_MAX_HID_CLASS_DESCRIPTORS; i++) {
+ descrInfo[i].bDescrType = 0;
+ descrInfo[i].wDescriptorLength = 0;
+ }
+ for(uint8_t i = 0; i < maxHidInterfaces; i++) {
+ hidInterfaces[i].bmInterface = 0;
+ hidInterfaces[i].bmProtocol = 0;
+
+ for(uint8_t j = 0; j < maxEpPerInterface; j++)
+ hidInterfaces[i].epIndex[j] = 0;
+ }
+ for(uint8_t i = 0; i < totalEndpoints; i++) {
+ epInfo[i].epAddr = 0;
+ epInfo[i].maxPktSize = (i) ? 0 : 8;
+ epInfo[i].epAttribs = 0;
+ epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
+ }
+ bNumEP = 1;
+ bNumIface = 0;
+ bConfNum = 0;
+ pollInterval = 0;
+
+ ZeroMemory(constBuffLen, prevBuf);
+}
+
+bool HIDUniversal::SetReportParser(uint8_t id, HIDReportParser *prs) {
+ for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) {
+ if(rptParsers[i].rptId == 0 && rptParsers[i].rptParser == NULL) {
+ rptParsers[i].rptId = id;
+ rptParsers[i].rptParser = prs;
+ return true;
+ }
+ }
+ return false;
+}
+
+HIDReportParser* HIDUniversal::GetReportParser(uint8_t id) {
+ if(!bHasReportId)
+ return ((rptParsers[0].rptParser) ? rptParsers[0].rptParser : NULL);
+
+ for(uint8_t i = 0; i < MAX_REPORT_PARSERS; i++) {
+ if(rptParsers[i].rptId == id)
+ return rptParsers[i].rptParser;
+ }
+ return NULL;
+}
+
+uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed) {
+ const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
+
+ uint8_t buf[constBufSize];
+ USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
+ uint8_t rcode;
+ UsbDevice *p = NULL;
+ EpInfo *oldep_ptr = NULL;
+ uint8_t len = 0;
+
+ uint8_t num_of_conf; // number of configurations
+ //uint8_t num_of_intf; // number of interfaces
+
+ AddressPool &addrPool = pUsb->GetAddressPool();
+
+ USBTRACE("HU Init\r\n");
+
+ if(bAddress)
+ return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
+
+ // Get pointer to pseudo device with address 0 assigned
+ p = addrPool.GetUsbDevicePtr(0);
+
+ if(!p)
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+ if(!p->epinfo) {
+ USBTRACE("epinfo\r\n");
+ return USB_ERROR_EPINFO_IS_NULL;
+ }
+
+ // Save old pointer to EP_RECORD of address 0
+ oldep_ptr = p->epinfo;
+
+ // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
+ p->epinfo = epInfo;
+
+ p->lowspeed = lowspeed;
+
+ // Get device descriptor
+ rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf);
+
+ if(!rcode)
+ len = (buf[0] > constBufSize) ? constBufSize : buf[0];
+
+ if(rcode) {
+ // Restore p->epinfo
+ p->epinfo = oldep_ptr;
+
+ goto FailGetDevDescr;
+ }
+
+ // Restore p->epinfo
+ p->epinfo = oldep_ptr;
+
+ // Allocate new address according to device class
+ bAddress = addrPool.AllocAddress(parent, false, port);
+
+ if(!bAddress)
+ return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
+
+ // Extract Max Packet Size from the device descriptor
+ epInfo[0].maxPktSize = udd->bMaxPacketSize0;
+
+ // Assign new address to the device
+ rcode = pUsb->setAddr(0, 0, bAddress);
+
+ if(rcode) {
+ p->lowspeed = false;
+ addrPool.FreeAddress(bAddress);
+ bAddress = 0;
+ USBTRACE2("setAddr:", rcode);
+ return rcode;
+ }
+
+ //delay(2); //per USB 2.0 sect.9.2.6.3
+
+ USBTRACE2("Addr:", bAddress);
+
+ p->lowspeed = false;
+
+ p = addrPool.GetUsbDevicePtr(bAddress);
+
+ if(!p)
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+ p->lowspeed = lowspeed;
+
+ if(len)
+ rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf);
+
+ if(rcode)
+ goto FailGetDevDescr;
+
+ VID = udd->idVendor; // Can be used by classes that inherits this class to check the VID and PID of the connected device
+ PID = udd->idProduct;
+
+ num_of_conf = udd->bNumConfigurations;
+
+ // Assign epInfo to epinfo pointer
+ rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
+
+ if(rcode)
+ goto FailSetDevTblEntry;
+
+ USBTRACE2("NC:", num_of_conf);
+
+ for(uint8_t i = 0; i < num_of_conf; i++) {
+ //HexDumper<USBReadParser, uint16_t, uint16_t> HexDump;
+ ConfigDescParser<USB_CLASS_HID, 0, 0,
+ CP_MASK_COMPARE_CLASS> confDescrParser(this);
+
+ //rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump);
+ rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
+
+ if(rcode)
+ goto FailGetConfDescr;
+
+ if(bNumEP > 1)
+ break;
+ } // for
+
+ if(bNumEP < 2)
+ return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
+
+ // Assign epInfo to epinfo pointer
+ rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
+
+ USBTRACE2("Cnf:", bConfNum);
+
+ // Set Configuration Value
+ rcode = pUsb->setConf(bAddress, 0, bConfNum);
+
+ if(rcode)
+ goto FailSetConfDescr;
+
+ for(uint8_t i = 0; i < bNumIface; i++) {
+ if(hidInterfaces[i].epIndex[epInterruptInIndex] == 0)
+ continue;
+
+ rcode = SetIdle(hidInterfaces[i].bmInterface, 0, 0);
+
+ if(rcode && rcode != hrSTALL)
+ goto FailSetIdle;
+ }
+
+ USBTRACE("HU configured\r\n");
+
+ OnInitSuccessful();
+
+ bPollEnable = true;
+ return 0;
+
+FailGetDevDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailGetDevDescr();
+ goto Fail;
+#endif
+
+FailSetDevTblEntry:
+#ifdef DEBUG_USB_HOST
+ NotifyFailSetDevTblEntry();
+ goto Fail;
+#endif
+
+FailGetConfDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailGetConfDescr();
+ goto Fail;
+#endif
+
+FailSetConfDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailSetConfDescr();
+ goto Fail;
+#endif
+
+
+FailSetIdle:
+#ifdef DEBUG_USB_HOST
+ USBTRACE("SetIdle:");
+#endif
+
+#ifdef DEBUG_USB_HOST
+Fail:
+ NotifyFail(rcode);
+#endif
+ Release();
+ return rcode;
+}
+
+HIDUniversal::HIDInterface* HIDUniversal::FindInterface(uint8_t iface, uint8_t alt, uint8_t proto) {
+ for(uint8_t i = 0; i < bNumIface && i < maxHidInterfaces; i++)
+ if(hidInterfaces[i].bmInterface == iface && hidInterfaces[i].bmAltSet == alt
+ && hidInterfaces[i].bmProtocol == proto)
+ return hidInterfaces + i;
+ return NULL;
+}
+
+void HIDUniversal::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {
+ // If the first configuration satisfies, the others are not concidered.
+ if(bNumEP > 1 && conf != bConfNum)
+ return;
+
+ //ErrorMessage<uint8_t>(PSTR("\r\nConf.Val"), conf);
+ //ErrorMessage<uint8_t>(PSTR("Iface Num"), iface);
+ //ErrorMessage<uint8_t>(PSTR("Alt.Set"), alt);
+
+ bConfNum = conf;
+
+ uint8_t index = 0;
+ HIDInterface *piface = FindInterface(iface, alt, proto);
+
+ // Fill in interface structure in case of new interface
+ if(!piface) {
+ piface = hidInterfaces + bNumIface;
+ piface->bmInterface = iface;
+ piface->bmAltSet = alt;
+ piface->bmProtocol = proto;
+ bNumIface++;
+ }
+
+ if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80)
+ index = epInterruptInIndex;
+ else
+ index = epInterruptOutIndex;
+
+ if(index) {
+ // Fill in the endpoint info structure
+ epInfo[bNumEP].epAddr = (pep->bEndpointAddress & 0x0F);
+ epInfo[bNumEP].maxPktSize = (uint8_t)pep->wMaxPacketSize;
+ epInfo[bNumEP].epAttribs = 0;
+ epInfo[bNumEP].bmNakPower = USB_NAK_NOWAIT;
+
+ // Fill in the endpoint index list
+ piface->epIndex[index] = bNumEP; //(pep->bEndpointAddress & 0x0F);
+
+ if(pollInterval < pep->bInterval) // Set the polling interval as the largest polling interval obtained from endpoints
+ pollInterval = pep->bInterval;
+
+ bNumEP++;
+ }
+ //PrintEndpointDescriptor(pep);
+}
+
+uint8_t HIDUniversal::Release() {
+ pUsb->GetAddressPool().FreeAddress(bAddress);
+
+ bNumEP = 1;
+ bAddress = 0;
+ qNextPollTime = 0;
+ bPollEnable = false;
+ return 0;
+}
+
+bool HIDUniversal::BuffersIdentical(uint8_t len, uint8_t *buf1, uint8_t *buf2) {
+ for(uint8_t i = 0; i < len; i++)
+ if(buf1[i] != buf2[i])
+ return false;
+ return true;
+}
+
+void HIDUniversal::ZeroMemory(uint8_t len, uint8_t *buf) {
+ for(uint8_t i = 0; i < len; i++)
+ buf[i] = 0;
+}
+
+void HIDUniversal::SaveBuffer(uint8_t len, uint8_t *src, uint8_t *dest) {
+ for(uint8_t i = 0; i < len; i++)
+ dest[i] = src[i];
+}
+
+uint8_t HIDUniversal::Poll() {
+ uint8_t rcode = 0;
+
+ if(!bPollEnable)
+ return 0;
+
+ if((long)(millis() - qNextPollTime) >= 0L) {
+ qNextPollTime = millis() + pollInterval;
+
+ uint8_t buf[constBuffLen];
+
+ for(uint8_t i = 0; i < bNumIface; i++) {
+ uint8_t index = hidInterfaces[i].epIndex[epInterruptInIndex];
+ uint16_t read = (uint16_t)epInfo[index].maxPktSize;
+
+ ZeroMemory(constBuffLen, buf);
+
+ uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[index].epAddr, &read, buf);
+
+ if(rcode) {
+ if(rcode != hrNAK)
+ USBTRACE3("(hiduniversal.h) Poll:", rcode, 0x81);
+ return rcode;
+ }
+
+ if(read > constBuffLen)
+ read = constBuffLen;
+
+ bool identical = BuffersIdentical(read, buf, prevBuf);
+
+ SaveBuffer(read, buf, prevBuf);
+
+ if(identical)
+ return 0;
+#if 0
+ Notify(PSTR("\r\nBuf: "), 0x80);
+
+ for(uint8_t i = 0; i < read; i++) {
+ D_PrintHex<uint8_t > (buf[i], 0x80);
+ Notify(PSTR(" "), 0x80);
+ }
+
+ Notify(PSTR("\r\n"), 0x80);
+#endif
+ ParseHIDData(this, bHasReportId, (uint8_t)read, buf);
+
+ HIDReportParser *prs = GetReportParser(((bHasReportId) ? *buf : 0));
+
+ if(prs)
+ prs->Parse(this, bHasReportId, (uint8_t)read, buf);
+ }
+ }
+ return rcode;
+}
+
+// Send a report to interrupt out endpoint. This is NOT SetReport() request!
+uint8_t HIDUniversal::SndRpt(uint16_t nbytes, uint8_t *dataptr) {
+ return pUsb->outTransfer(bAddress, epInfo[epInterruptOutIndex].epAddr, nbytes, dataptr);
+} \ No newline at end of file
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hiduniversal.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hiduniversal.h
new file mode 100644
index 000000000..d7af38406
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hiduniversal.h
@@ -0,0 +1,108 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+
+#if !defined(__HIDUNIVERSAL_H__)
+#define __HIDUNIVERSAL_H__
+
+#include "hid.h"
+//#include "hidescriptorparser.h"
+
+class HIDUniversal : public HID {
+
+ struct ReportParser {
+ uint8_t rptId;
+ HIDReportParser *rptParser;
+ } rptParsers[MAX_REPORT_PARSERS];
+
+ // HID class specific descriptor type and length info obtained from HID descriptor
+ HID_CLASS_DESCRIPTOR_LEN_AND_TYPE descrInfo[HID_MAX_HID_CLASS_DESCRIPTORS];
+
+ // Returns HID class specific descriptor length by its type and order number
+ uint16_t GetHidClassDescrLen(uint8_t type, uint8_t num);
+
+ struct HIDInterface {
+ struct {
+ uint8_t bmInterface : 3;
+ uint8_t bmAltSet : 3;
+ uint8_t bmProtocol : 2;
+ };
+ uint8_t epIndex[maxEpPerInterface];
+ };
+
+ uint8_t bConfNum; // configuration number
+ uint8_t bNumIface; // number of interfaces in the configuration
+ uint8_t bNumEP; // total number of EP in the configuration
+ uint32_t qNextPollTime; // next poll time
+ uint8_t pollInterval;
+ bool bPollEnable; // poll enable flag
+
+ static const uint16_t constBuffLen = 64; // event buffer length
+ uint8_t prevBuf[constBuffLen]; // previous event buffer
+
+ void Initialize();
+ HIDInterface* FindInterface(uint8_t iface, uint8_t alt, uint8_t proto);
+
+ void ZeroMemory(uint8_t len, uint8_t *buf);
+ bool BuffersIdentical(uint8_t len, uint8_t *buf1, uint8_t *buf2);
+ void SaveBuffer(uint8_t len, uint8_t *src, uint8_t *dest);
+
+protected:
+ EpInfo epInfo[totalEndpoints];
+ HIDInterface hidInterfaces[maxHidInterfaces];
+
+ bool bHasReportId;
+
+ uint16_t PID, VID; // PID and VID of connected device
+
+ // HID implementation
+ HIDReportParser* GetReportParser(uint8_t id);
+
+ virtual uint8_t OnInitSuccessful() {
+ return 0;
+ };
+
+ virtual void ParseHIDData(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
+ return;
+ };
+
+public:
+ HIDUniversal(USB *p);
+
+ // HID implementation
+ bool SetReportParser(uint8_t id, HIDReportParser *prs);
+
+ // USBDeviceConfig implementation
+ uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
+ uint8_t Release();
+ uint8_t Poll();
+
+ virtual uint8_t GetAddress() {
+ return bAddress;
+ };
+
+ virtual bool isReady() {
+ return bPollEnable;
+ };
+
+ // UsbConfigXtracter implementation
+ void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
+
+ // Send report - do not mix with SetReport()!
+ uint8_t SndRpt(uint16_t nbytes, uint8_t *dataptr);
+};
+
+#endif // __HIDUNIVERSAL_H__
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidusagestr.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidusagestr.h
new file mode 100644
index 000000000..5ef48f925
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidusagestr.h
@@ -0,0 +1,977 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+#if !defined( __HIDUSAGESTR_H__)
+#define __HIDUSAGESTR_H__
+
+#include "Usb.h"
+
+const char pstrSpace [] PROGMEM = " ";
+const char pstrCRLF [] PROGMEM = "\r\n";
+const char pstrSingleTab [] PROGMEM = "\t";
+const char pstrDoubleTab [] PROGMEM = "\t\t";
+const char pstrTripleTab [] PROGMEM = "\t\t\t";
+
+// Usage Page String Titles
+const char pstrUsagePageUndefined [] PROGMEM = "Undef";
+const char pstrUsagePageGenericDesktopControls [] PROGMEM = "Gen Desktop Ctrls";
+const char pstrUsagePageSimulationControls [] PROGMEM = "Simu Ctrls";
+const char pstrUsagePageVRControls [] PROGMEM = "VR Ctrls";
+const char pstrUsagePageSportControls [] PROGMEM = "Sport Ctrls";
+const char pstrUsagePageGameControls [] PROGMEM = "Game Ctrls";
+const char pstrUsagePageGenericDeviceControls [] PROGMEM = "Gen Dev Ctrls";
+const char pstrUsagePageKeyboardKeypad [] PROGMEM = "Kbrd/Keypad";
+const char pstrUsagePageLEDs [] PROGMEM = "LEDs";
+const char pstrUsagePageButton [] PROGMEM = "Button";
+const char pstrUsagePageOrdinal [] PROGMEM = "Ordinal";
+const char pstrUsagePageTelephone [] PROGMEM = "Tel";
+const char pstrUsagePageConsumer [] PROGMEM = "Consumer";
+const char pstrUsagePageDigitizer [] PROGMEM = "Digitizer";
+const char pstrUsagePagePID [] PROGMEM = "PID";
+const char pstrUsagePageUnicode [] PROGMEM = "Unicode";
+const char pstrUsagePageAlphaNumericDisplay [] PROGMEM = "Alpha Num Disp";
+const char pstrUsagePageMedicalInstruments [] PROGMEM = "Medical Instr";
+const char pstrUsagePageMonitor [] PROGMEM = "Monitor";
+const char pstrUsagePagePower [] PROGMEM = "Power";
+const char pstrUsagePageBarCodeScanner [] PROGMEM = "Bar Code Scan";
+const char pstrUsagePageScale [] PROGMEM = "Scale";
+const char pstrUsagePageMSRDevices [] PROGMEM = "Magn Stripe Read Dev";
+const char pstrUsagePagePointOfSale [] PROGMEM = "POS";
+const char pstrUsagePageCameraControl [] PROGMEM = "Cam Ctrl";
+const char pstrUsagePageArcade [] PROGMEM = "Arcade";
+const char pstrUsagePageReserved [] PROGMEM = "Reserved";
+const char pstrUsagePageVendorDefined [] PROGMEM = "Vendor Def";
+
+// Generic Desktop Controls Page
+const char pstrUsagePointer [] PROGMEM = "Pointer";
+const char pstrUsageMouse [] PROGMEM = "Mouse";
+const char pstrUsageJoystick [] PROGMEM = "Joystick";
+const char pstrUsageGamePad [] PROGMEM = "Game Pad";
+const char pstrUsageKeyboard [] PROGMEM = "Kbrd";
+const char pstrUsageKeypad [] PROGMEM = "Keypad";
+const char pstrUsageMultiAxisController [] PROGMEM = "Multi-axis Ctrl";
+const char pstrUsageTabletPCSystemControls [] PROGMEM = "Tablet PC Sys Ctrls";
+const char pstrUsageX [] PROGMEM = "X";
+const char pstrUsageY [] PROGMEM = "Y";
+const char pstrUsageZ [] PROGMEM = "Z";
+const char pstrUsageRx [] PROGMEM = "Rx";
+const char pstrUsageRy [] PROGMEM = "Ry";
+const char pstrUsageRz [] PROGMEM = "Rz";
+const char pstrUsageSlider [] PROGMEM = "Slider";
+const char pstrUsageDial [] PROGMEM = "Dial";
+const char pstrUsageWheel [] PROGMEM = "Wheel";
+const char pstrUsageHatSwitch [] PROGMEM = "Hat Switch";
+const char pstrUsageCountedBuffer [] PROGMEM = "Counted Buf";
+const char pstrUsageByteCount [] PROGMEM = "Byte Count";
+const char pstrUsageMotionWakeup [] PROGMEM = "Motion Wakeup";
+const char pstrUsageStart [] PROGMEM = "Start";
+const char pstrUsageSelect [] PROGMEM = "Sel";
+const char pstrUsageVx [] PROGMEM = "Vx";
+const char pstrUsageVy [] PROGMEM = "Vy";
+const char pstrUsageVz [] PROGMEM = "Vz";
+const char pstrUsageVbrx [] PROGMEM = "Vbrx";
+const char pstrUsageVbry [] PROGMEM = "Vbry";
+const char pstrUsageVbrz [] PROGMEM = "Vbrz";
+const char pstrUsageVno [] PROGMEM = "Vno";
+const char pstrUsageFeatureNotification [] PROGMEM = "Feature Notif";
+const char pstrUsageResolutionMultiplier [] PROGMEM = "Res Mult";
+const char pstrUsageSystemControl [] PROGMEM = "Sys Ctrl";
+const char pstrUsageSystemPowerDown [] PROGMEM = "Sys Pwr Down";
+const char pstrUsageSystemSleep [] PROGMEM = "Sys Sleep";
+const char pstrUsageSystemWakeup [] PROGMEM = "Sys Wakeup";
+const char pstrUsageSystemContextMenu [] PROGMEM = "Sys Context Menu";
+const char pstrUsageSystemMainMenu [] PROGMEM = "Sys Main Menu";
+const char pstrUsageSystemAppMenu [] PROGMEM = "Sys App Menu";
+const char pstrUsageSystemMenuHelp [] PROGMEM = "Sys Menu Help";
+const char pstrUsageSystemMenuExit [] PROGMEM = "Sys Menu Exit";
+const char pstrUsageSystemMenuSelect [] PROGMEM = "Sys Menu Select";
+const char pstrUsageSystemMenuRight [] PROGMEM = "Sys Menu Right";
+const char pstrUsageSystemMenuLeft [] PROGMEM = "Sys Menu Left";
+const char pstrUsageSystemMenuUp [] PROGMEM = "Sys Menu Up";
+const char pstrUsageSystemMenuDown [] PROGMEM = "Sys Menu Down";
+const char pstrUsageSystemColdRestart [] PROGMEM = "Sys Cold Restart";
+const char pstrUsageSystemWarmRestart [] PROGMEM = "Sys Warm Restart";
+const char pstrUsageDPadUp [] PROGMEM = "D-pad Up";
+const char pstrUsageDPadDown [] PROGMEM = "D-pad Down";
+const char pstrUsageDPadRight [] PROGMEM = "D-pad Right";
+const char pstrUsageDPadLeft [] PROGMEM = "D-pad Left";
+const char pstrUsageSystemDock [] PROGMEM = "Sys Dock";
+const char pstrUsageSystemUndock [] PROGMEM = "Sys Undock";
+const char pstrUsageSystemSetup [] PROGMEM = "Sys Setup";
+const char pstrUsageSystemBreak [] PROGMEM = "Sys Break";
+const char pstrUsageSystemDebuggerBreak [] PROGMEM = "Sys Dbg Brk";
+const char pstrUsageApplicationBreak [] PROGMEM = "App Break";
+const char pstrUsageApplicationDebuggerBreak [] PROGMEM = "App Dbg Brk";
+const char pstrUsageSystemSpeakerMute [] PROGMEM = "Sys Spk Mute";
+const char pstrUsageSystemHibernate [] PROGMEM = "Sys Hiber";
+const char pstrUsageSystemDisplayInvert [] PROGMEM = "Sys Disp Inv";
+const char pstrUsageSystemDisplayInternal [] PROGMEM = "Sys Disp Int";
+const char pstrUsageSystemDisplayExternal [] PROGMEM = "Sys Disp Ext";
+const char pstrUsageSystemDisplayBoth [] PROGMEM = "Sys Disp Both";
+const char pstrUsageSystemDisplayDual [] PROGMEM = "Sys Disp Dual";
+const char pstrUsageSystemDisplayToggleIntExt [] PROGMEM = "Sys Disp Tgl Int/Ext";
+const char pstrUsageSystemDisplaySwapPriSec [] PROGMEM = "Sys Disp Swap Pri/Sec";
+const char pstrUsageSystemDisplayLCDAutoscale [] PROGMEM = "Sys Disp LCD Autoscale";
+
+// Simulation Controls Page
+const char pstrUsageFlightSimulationDevice [] PROGMEM = "Flight Simu Dev";
+const char pstrUsageAutomobileSimulationDevice [] PROGMEM = "Auto Simu Dev";
+const char pstrUsageTankSimulationDevice [] PROGMEM = "Tank Simu Dev";
+const char pstrUsageSpaceshipSimulationDevice [] PROGMEM = "Space Simu Dev";
+const char pstrUsageSubmarineSimulationDevice [] PROGMEM = "Subm Simu Dev";
+const char pstrUsageSailingSimulationDevice [] PROGMEM = "Sail Simu Dev";
+const char pstrUsageMotocicleSimulationDevice [] PROGMEM = "Moto Simu Dev";
+const char pstrUsageSportsSimulationDevice [] PROGMEM = "Sport Simu Dev";
+const char pstrUsageAirplaneSimulationDevice [] PROGMEM = "Airp Simu Dev";
+const char pstrUsageHelicopterSimulationDevice [] PROGMEM = "Heli Simu Dev";
+const char pstrUsageMagicCarpetSimulationDevice [] PROGMEM = "Magic Carpet Simu Dev";
+const char pstrUsageBicycleSimulationDevice [] PROGMEM = "Bike Simu Dev";
+const char pstrUsageFlightControlStick [] PROGMEM = "Flight Ctrl Stick";
+const char pstrUsageFlightStick [] PROGMEM = "Flight Stick";
+const char pstrUsageCyclicControl [] PROGMEM = "Cyclic Ctrl";
+const char pstrUsageCyclicTrim [] PROGMEM = "Cyclic Trim";
+const char pstrUsageFlightYoke [] PROGMEM = "Flight Yoke";
+const char pstrUsageTrackControl [] PROGMEM = "Track Ctrl";
+const char pstrUsageAileron [] PROGMEM = "Aileron";
+const char pstrUsageAileronTrim [] PROGMEM = "Aileron Trim";
+const char pstrUsageAntiTorqueControl [] PROGMEM = "Anti-Torque Ctrl";
+const char pstrUsageAutopilotEnable [] PROGMEM = "Autopilot Enable";
+const char pstrUsageChaffRelease [] PROGMEM = "Chaff Release";
+const char pstrUsageCollectiveControl [] PROGMEM = "Collective Ctrl";
+const char pstrUsageDiveBrake [] PROGMEM = "Dive Brake";
+const char pstrUsageElectronicCountermeasures [] PROGMEM = "El Countermeasures";
+const char pstrUsageElevator [] PROGMEM = "Elevator";
+const char pstrUsageElevatorTrim [] PROGMEM = "Elevator Trim";
+const char pstrUsageRudder [] PROGMEM = "Rudder";
+const char pstrUsageThrottle [] PROGMEM = "Throttle";
+const char pstrUsageFlightCommunications [] PROGMEM = "Flight Comm";
+const char pstrUsageFlareRelease [] PROGMEM = "Flare Release";
+const char pstrUsageLandingGear [] PROGMEM = "Landing Gear";
+const char pstrUsageToeBrake [] PROGMEM = "Toe Brake";
+const char pstrUsageTrigger [] PROGMEM = "Trigger";
+const char pstrUsageWeaponsArm [] PROGMEM = "Weapons Arm";
+const char pstrUsageWeaponsSelect [] PROGMEM = "Weapons Sel";
+const char pstrUsageWingFlaps [] PROGMEM = "Wing Flaps";
+const char pstrUsageAccelerator [] PROGMEM = "Accel";
+const char pstrUsageBrake [] PROGMEM = "Brake";
+const char pstrUsageClutch [] PROGMEM = "Clutch";
+const char pstrUsageShifter [] PROGMEM = "Shifter";
+const char pstrUsageSteering [] PROGMEM = "Steering";
+const char pstrUsageTurretDirection [] PROGMEM = "Turret Dir";
+const char pstrUsageBarrelElevation [] PROGMEM = "Barrel Ele";
+const char pstrUsageDivePlane [] PROGMEM = "Dive Plane";
+const char pstrUsageBallast [] PROGMEM = "Ballast";
+const char pstrUsageBicycleCrank [] PROGMEM = "Bicycle Crank";
+const char pstrUsageHandleBars [] PROGMEM = "Handle Bars";
+const char pstrUsageFrontBrake [] PROGMEM = "Front Brake";
+const char pstrUsageRearBrake [] PROGMEM = "Rear Brake";
+
+// VR Controls Page
+const char pstrUsageBelt [] PROGMEM = "Belt";
+const char pstrUsageBodySuit [] PROGMEM = "Body Suit";
+const char pstrUsageFlexor [] PROGMEM = "Flexor";
+const char pstrUsageGlove [] PROGMEM = "Glove";
+const char pstrUsageHeadTracker [] PROGMEM = "Head Track";
+const char pstrUsageHeadMountedDisplay [] PROGMEM = "Head Disp";
+const char pstrUsageHandTracker [] PROGMEM = "Hand Track";
+const char pstrUsageOculometer [] PROGMEM = "Oculometer";
+const char pstrUsageVest [] PROGMEM = "Vest";
+const char pstrUsageAnimatronicDevice [] PROGMEM = "Animat Dev";
+const char pstrUsageStereoEnable [] PROGMEM = "Stereo Enbl";
+const char pstrUsageDisplayEnable [] PROGMEM = "Display Enbl";
+
+// Sport Controls Page
+const char pstrUsageBaseballBat [] PROGMEM = "Baseball Bat";
+const char pstrUsageGolfClub [] PROGMEM = "Golf Club";
+const char pstrUsageRowingMachine [] PROGMEM = "Rowing Mach";
+const char pstrUsageTreadmill [] PROGMEM = "Treadmill";
+const char pstrUsageOar [] PROGMEM = "Oar";
+const char pstrUsageSlope [] PROGMEM = "Slope";
+const char pstrUsageRate [] PROGMEM = "Rate";
+const char pstrUsageStickSpeed [] PROGMEM = "Stick Speed";
+const char pstrUsageStickFaceAngle [] PROGMEM = "Stick Face Ang";
+const char pstrUsageStickHeelToe [] PROGMEM = "Stick Heel/Toe";
+const char pstrUsageStickFollowThough [] PROGMEM = "Stick Flw Thru";
+const char pstrUsageStickTempo [] PROGMEM = "Stick Tempo";
+const char pstrUsageStickType [] PROGMEM = "Stick Type";
+const char pstrUsageStickHeight [] PROGMEM = "Stick Hght";
+const char pstrUsagePutter [] PROGMEM = "Putter";
+const char pstrUsage1Iron [] PROGMEM = "1 Iron";
+const char pstrUsage2Iron [] PROGMEM = "2 Iron";
+const char pstrUsage3Iron [] PROGMEM = "3 Iron";
+const char pstrUsage4Iron [] PROGMEM = "4 Iron";
+const char pstrUsage5Iron [] PROGMEM = "5 Iron";
+const char pstrUsage6Iron [] PROGMEM = "6 Iron";
+const char pstrUsage7Iron [] PROGMEM = "7 Iron";
+const char pstrUsage8Iron [] PROGMEM = "8 Iron";
+const char pstrUsage9Iron [] PROGMEM = "9 Iron";
+const char pstrUsage10Iron [] PROGMEM = "10 Iron";
+const char pstrUsage11Iron [] PROGMEM = "11 Iron";
+const char pstrUsageSandWedge [] PROGMEM = "Sand Wedge";
+const char pstrUsageLoftWedge [] PROGMEM = "Loft Wedge";
+const char pstrUsagePowerWedge [] PROGMEM = "Pwr Wedge";
+const char pstrUsage1Wood [] PROGMEM = "1 Wood";
+const char pstrUsage3Wood [] PROGMEM = "3 Wood";
+const char pstrUsage5Wood [] PROGMEM = "5 Wood";
+const char pstrUsage7Wood [] PROGMEM = "7 Wood";
+const char pstrUsage9Wood [] PROGMEM = "9 Wood";
+
+// Game Controls Page
+const char pstrUsage3DGameController [] PROGMEM = "3D Game Ctrl";
+const char pstrUsagePinballDevice [] PROGMEM = "Pinball Dev";
+const char pstrUsageGunDevice [] PROGMEM = "Gun Dev";
+const char pstrUsagePointOfView [] PROGMEM = "POV";
+const char pstrUsageTurnRightLeft [] PROGMEM = "Turn Right Left";
+const char pstrUsagePitchForwardBackward [] PROGMEM = "Pitch Fwd/Back";
+const char pstrUsageRollRightLeft [] PROGMEM = "Roll Right/Left";
+const char pstrUsageMoveRightLeft [] PROGMEM = "Move Right/Left";
+const char pstrUsageMoveForwardBackward [] PROGMEM = "Move Fwd/Back";
+const char pstrUsageMoveUpDown [] PROGMEM = "Move Up/Down";
+const char pstrUsageLeanRightLeft [] PROGMEM = "Lean Right/Left";
+const char pstrUsageLeanForwardBackward [] PROGMEM = "Lean Fwd/Back";
+const char pstrUsageHeightOfPOV [] PROGMEM = "Height of POV";
+const char pstrUsageFlipper [] PROGMEM = "Flipper";
+const char pstrUsageSecondaryFlipper [] PROGMEM = "Second Flipper";
+const char pstrUsageBump [] PROGMEM = "Bump";
+const char pstrUsageNewGame [] PROGMEM = "New Game";
+const char pstrUsageShootBall [] PROGMEM = "Shoot Ball";
+const char pstrUsagePlayer [] PROGMEM = "Player";
+const char pstrUsageGunBolt [] PROGMEM = "Gun Bolt";
+const char pstrUsageGunClip [] PROGMEM = "Gun Clip";
+const char pstrUsageGunSelector [] PROGMEM = "Gun Sel";
+const char pstrUsageGunSingleShot [] PROGMEM = "Gun Sngl Shot";
+const char pstrUsageGunBurst [] PROGMEM = "Gun Burst";
+const char pstrUsageGunAutomatic [] PROGMEM = "Gun Auto";
+const char pstrUsageGunSafety [] PROGMEM = "Gun Safety";
+const char pstrUsageGamepadFireJump [] PROGMEM = "Gamepad Fire/Jump";
+const char pstrUsageGamepadTrigger [] PROGMEM = "Gamepad Trig";
+
+// Generic Device Controls Page
+const char pstrUsageBatteryStrength [] PROGMEM = "Bat Strength";
+const char pstrUsageWirelessChannel [] PROGMEM = "Wireless Ch";
+const char pstrUsageWirelessID [] PROGMEM = "Wireless ID";
+const char pstrUsageDiscoverWirelessControl [] PROGMEM = "Discover Wireless Ctrl";
+const char pstrUsageSecurityCodeCharEntered [] PROGMEM = "Sec Code Char Entrd";
+const char pstrUsageSecurityCodeCharErased [] PROGMEM = "Sec Code Char Erased";
+const char pstrUsageSecurityCodeCleared [] PROGMEM = "Sec Code Cleared";
+
+// LED Page
+const char pstrUsageNumLock [] PROGMEM = "Num Lock";
+const char pstrUsageCapsLock [] PROGMEM = "Caps Lock";
+const char pstrUsageScrollLock [] PROGMEM = "Scroll Lock";
+const char pstrUsageCompose [] PROGMEM = "Compose";
+const char pstrUsageKana [] PROGMEM = "Kana";
+const char pstrUsagePower [] PROGMEM = "Pwr";
+const char pstrUsageShift [] PROGMEM = "Shift";
+const char pstrUsageDoNotDisturb [] PROGMEM = "DND";
+const char pstrUsageMute [] PROGMEM = "Mute";
+const char pstrUsageToneEnable [] PROGMEM = "Tone Enbl";
+const char pstrUsageHighCutFilter [] PROGMEM = "High Cut Fltr";
+const char pstrUsageLowCutFilter [] PROGMEM = "Low Cut Fltr";
+const char pstrUsageEqualizerEnable [] PROGMEM = "Eq Enbl";
+const char pstrUsageSoundFieldOn [] PROGMEM = "Sound Field On";
+const char pstrUsageSurroundOn [] PROGMEM = "Surround On";
+const char pstrUsageRepeat [] PROGMEM = "Repeat";
+const char pstrUsageStereo [] PROGMEM = "Stereo";
+const char pstrUsageSamplingRateDetect [] PROGMEM = "Smpl Rate Detect";
+const char pstrUsageSpinning [] PROGMEM = "Spinning";
+const char pstrUsageCAV [] PROGMEM = "CAV";
+const char pstrUsageCLV [] PROGMEM = "CLV";
+const char pstrUsageRecordingFormatDetect [] PROGMEM = "Rec Format Detect";
+const char pstrUsageOffHook [] PROGMEM = "Off Hook";
+const char pstrUsageRing [] PROGMEM = "Ring";
+const char pstrUsageMessageWaiting [] PROGMEM = "Msg Wait";
+const char pstrUsageDataMode [] PROGMEM = "Data Mode";
+const char pstrUsageBatteryOperation [] PROGMEM = "Bat Op";
+const char pstrUsageBatteryOK [] PROGMEM = "Bat OK";
+const char pstrUsageBatteryLow [] PROGMEM = "Bat Low";
+const char pstrUsageSpeaker [] PROGMEM = "Speaker";
+const char pstrUsageHeadSet [] PROGMEM = "Head Set";
+const char pstrUsageHold [] PROGMEM = "Hold";
+const char pstrUsageMicrophone [] PROGMEM = "Mic";
+const char pstrUsageCoverage [] PROGMEM = "Coverage";
+const char pstrUsageNightMode [] PROGMEM = "Night Mode";
+const char pstrUsageSendCalls [] PROGMEM = "Send Calls";
+const char pstrUsageCallPickup [] PROGMEM = "Call Pickup";
+const char pstrUsageConference [] PROGMEM = "Conf";
+const char pstrUsageStandBy [] PROGMEM = "Stand-by";
+const char pstrUsageCameraOn [] PROGMEM = "Cam On";
+const char pstrUsageCameraOff [] PROGMEM = "Cam Off";
+const char pstrUsageOnLine [] PROGMEM = "On-Line";
+const char pstrUsageOffLine [] PROGMEM = "Off-Line";
+const char pstrUsageBusy [] PROGMEM = "Busy";
+const char pstrUsageReady [] PROGMEM = "Ready";
+const char pstrUsagePaperOut [] PROGMEM = "Paper Out";
+const char pstrUsagePaperJam [] PROGMEM = "Paper Jam";
+const char pstrUsageRemote [] PROGMEM = "Remote";
+const char pstrUsageForward [] PROGMEM = "Fwd";
+const char pstrUsageReverse [] PROGMEM = "Rev";
+const char pstrUsageStop [] PROGMEM = "Stop";
+const char pstrUsageRewind [] PROGMEM = "Rewind";
+const char pstrUsageFastForward [] PROGMEM = "Fast Fwd";
+const char pstrUsagePlay [] PROGMEM = "Play";
+const char pstrUsagePause [] PROGMEM = "Pause";
+const char pstrUsageRecord [] PROGMEM = "Rec";
+const char pstrUsageError [] PROGMEM = "Error";
+const char pstrUsageSelectedIndicator [] PROGMEM = "Usage Sel Ind";
+const char pstrUsageInUseIndicator [] PROGMEM = "Usage In Use Ind";
+const char pstrUsageMultiModeIndicator [] PROGMEM = "Usage Multi Mode Ind";
+const char pstrUsageIndicatorOn [] PROGMEM = "Ind On";
+const char pstrUsageIndicatorFlash [] PROGMEM = "Ind Flash";
+const char pstrUsageIndicatorSlowBlink [] PROGMEM = "Ind Slow Blk";
+const char pstrUsageIndicatorFastBlink [] PROGMEM = "Ind Fast Blk";
+const char pstrUsageIndicatorOff [] PROGMEM = "Ind Off";
+const char pstrUsageFlashOnTime [] PROGMEM = "Flash On Time";
+const char pstrUsageSlowBlinkOnTime [] PROGMEM = "Slow Blk On Time";
+const char pstrUsageSlowBlinkOffTime [] PROGMEM = "Slow Blk Off Time";
+const char pstrUsageFastBlinkOnTime [] PROGMEM = "Fast Blk On Time";
+const char pstrUsageFastBlinkOffTime [] PROGMEM = "Fast Blk Off Time";
+const char pstrUsageIndicatorColor [] PROGMEM = "Usage Ind Color";
+const char pstrUsageIndicatorRed [] PROGMEM = "Ind Red";
+const char pstrUsageIndicatorGreen [] PROGMEM = "Ind Green";
+const char pstrUsageIndicatorAmber [] PROGMEM = "Ind Amber";
+const char pstrUsageGenericIndicator [] PROGMEM = "Gen Ind";
+const char pstrUsageSystemSuspend [] PROGMEM = "Sys Suspend";
+const char pstrUsageExternalPowerConnected [] PROGMEM = "Ext Pwr Conn";
+
+// Telephony Usage Page
+const char pstrUsagePhone [] PROGMEM = "Phone";
+const char pstrUsageAnsweringMachine [] PROGMEM = "Answ Mach";
+const char pstrUsageMessageControls [] PROGMEM = "Msg Ctrls";
+const char pstrUsageHandset [] PROGMEM = "Handset";
+const char pstrUsageHeadset [] PROGMEM = "Headset";
+const char pstrUsageTelephonyKeyPad [] PROGMEM = "Tel Key Pad";
+const char pstrUsageProgrammableButton [] PROGMEM = "Prog Button";
+const char pstrUsageHookSwitch [] PROGMEM = "Hook Sw";
+const char pstrUsageFlash [] PROGMEM = "Flash";
+const char pstrUsageFeature [] PROGMEM = "Feature";
+//const char pstrUsageHold [] PROGMEM = "Hold";
+const char pstrUsageRedial [] PROGMEM = "Redial";
+const char pstrUsageTransfer [] PROGMEM = "Transfer";
+const char pstrUsageDrop [] PROGMEM = "Drop";
+const char pstrUsagePark [] PROGMEM = "Park";
+const char pstrUsageForwardCalls [] PROGMEM = "Fwd Calls";
+const char pstrUsageAlternateFunction [] PROGMEM = "Alt Func";
+const char pstrUsageLine [] PROGMEM = "Line";
+const char pstrUsageSpeakerPhone [] PROGMEM = "Spk Phone";
+//const char pstrUsageConference [] PROGMEM = "Conference";
+const char pstrUsageRingEnable [] PROGMEM = "Ring Enbl";
+const char pstrUsageRingSelect [] PROGMEM = "Ring Sel";
+const char pstrUsagePhoneMute [] PROGMEM = "Phone Mute";
+const char pstrUsageCallerID [] PROGMEM = "Caller ID";
+const char pstrUsageSend [] PROGMEM = "Send";
+const char pstrUsageSpeedDial [] PROGMEM = "Speed Dial";
+const char pstrUsageStoreNumber [] PROGMEM = "Store Num";
+const char pstrUsageRecallNumber [] PROGMEM = "Recall Num";
+const char pstrUsagePhoneDirectory [] PROGMEM = "Phone Dir";
+const char pstrUsageVoiceMail [] PROGMEM = "Voice Mail";
+const char pstrUsageScreenCalls [] PROGMEM = "Screen Calls";
+//const char pstrUsageDoNotDisturb [] PROGMEM = "Do Not Disturb";
+const char pstrUsageMessage [] PROGMEM = "Msg";
+const char pstrUsageAnswerOnOff [] PROGMEM = "Answer On/Off";
+const char pstrUsageInsideDialTone [] PROGMEM = "Inside Dial Tone";
+const char pstrUsageOutsideDialTone [] PROGMEM = "Outside Dial Tone";
+const char pstrUsageInsideRingTone [] PROGMEM = "Inside Ring Tone";
+const char pstrUsageOutsideRingTone [] PROGMEM = "Outside Ring Tone";
+const char pstrUsagePriorityRingTone [] PROGMEM = "Prior Ring Tone";
+const char pstrUsageInsideRingback [] PROGMEM = "Inside Ringback";
+const char pstrUsagePriorityRingback [] PROGMEM = "Priority Ringback";
+const char pstrUsageLineBusyTone [] PROGMEM = "Ln Busy Tone";
+const char pstrUsageReorderTone [] PROGMEM = "Reorder Tone";
+const char pstrUsageCallWaitingTone [] PROGMEM = "Call Wait Tone";
+const char pstrUsageConfirmationTone1 [] PROGMEM = "Cnfrm Tone1";
+const char pstrUsageConfirmationTone2 [] PROGMEM = "Cnfrm Tone2";
+const char pstrUsageTonesOff [] PROGMEM = "Tones Off";
+const char pstrUsageOutsideRingback [] PROGMEM = "Outside Ringback";
+const char pstrUsageRinger [] PROGMEM = "Ringer";
+const char pstrUsagePhoneKey0 [] PROGMEM = "0";
+const char pstrUsagePhoneKey1 [] PROGMEM = "1";
+const char pstrUsagePhoneKey2 [] PROGMEM = "2";
+const char pstrUsagePhoneKey3 [] PROGMEM = "3";
+const char pstrUsagePhoneKey4 [] PROGMEM = "4";
+const char pstrUsagePhoneKey5 [] PROGMEM = "5";
+const char pstrUsagePhoneKey6 [] PROGMEM = "6";
+const char pstrUsagePhoneKey7 [] PROGMEM = "7";
+const char pstrUsagePhoneKey8 [] PROGMEM = "8";
+const char pstrUsagePhoneKey9 [] PROGMEM = "9";
+const char pstrUsagePhoneKeyStar [] PROGMEM = "*";
+const char pstrUsagePhoneKeyPound [] PROGMEM = "#";
+const char pstrUsagePhoneKeyA [] PROGMEM = "A";
+const char pstrUsagePhoneKeyB [] PROGMEM = "B";
+const char pstrUsagePhoneKeyC [] PROGMEM = "C";
+const char pstrUsagePhoneKeyD [] PROGMEM = "D";
+
+// Consumer Usage Page
+const char pstrUsageConsumerControl [] PROGMEM = "Consumer Ctrl";
+const char pstrUsageNumericKeyPad [] PROGMEM = "Num Key Pad";
+//const char pstrUsageProgrammableButton [] PROGMEM = "Prog Btn";
+//const char pstrUsageMicrophone [] PROGMEM = "Mic";
+const char pstrUsageHeadphone [] PROGMEM = "Headphone";
+const char pstrUsageGraphicEqualizer [] PROGMEM = "Graph Eq";
+const char pstrUsagePlus10 [] PROGMEM = "+10";
+const char pstrUsagePlus100 [] PROGMEM = "+100";
+const char pstrUsageAMPM [] PROGMEM = "AM/PM";
+//const char pstrUsagePower [] PROGMEM = "Pwr";
+const char pstrUsageReset [] PROGMEM = "Reset";
+const char pstrUsageSleep [] PROGMEM = "Sleep";
+const char pstrUsageSleepAfter [] PROGMEM = "Sleep After";
+const char pstrUsageSleepMode [] PROGMEM = "Sleep Mode";
+const char pstrUsageIllumination [] PROGMEM = "Illumin";
+const char pstrUsageFunctionButtons [] PROGMEM = "Func Btns";
+const char pstrUsageMenu [] PROGMEM = "Menu";
+const char pstrUsageMenuPick [] PROGMEM = "Menu Pick";
+const char pstrUsageMenuUp [] PROGMEM = "Menu Up";
+const char pstrUsageMenuDown [] PROGMEM = "Menu Down";
+const char pstrUsageMenuLeft [] PROGMEM = "Menu Left";
+const char pstrUsageMenuRight [] PROGMEM = "Menu Right";
+const char pstrUsageMenuEscape [] PROGMEM = "Menu Esc";
+const char pstrUsageMenuValueIncrease [] PROGMEM = "Menu Val Inc";
+const char pstrUsageMenuValueDecrease [] PROGMEM = "Menu Val Dec";
+const char pstrUsageDataOnScreen [] PROGMEM = "Data On Scr";
+const char pstrUsageClosedCaption [] PROGMEM = "Closed Cptn";
+const char pstrUsageClosedCaptionSelect [] PROGMEM = "Closed Cptn Sel";
+const char pstrUsageVCRTV [] PROGMEM = "VCR/TV";
+const char pstrUsageBroadcastMode [] PROGMEM = "Brdcast Mode";
+const char pstrUsageSnapshot [] PROGMEM = "Snapshot";
+const char pstrUsageStill [] PROGMEM = "Still";
+const char pstrUsageSelection [] PROGMEM = "Sel";
+const char pstrUsageAssignSelection [] PROGMEM = "Assign Sel";
+const char pstrUsageModeStep [] PROGMEM = "Mode Step";
+const char pstrUsageRecallLast [] PROGMEM = "Recall Last";
+const char pstrUsageEnterChannel [] PROGMEM = "Entr Channel";
+const char pstrUsageOrderMovie [] PROGMEM = "Ord Movie";
+const char pstrUsageChannel [] PROGMEM = "Channel";
+const char pstrUsageMediaSelection [] PROGMEM = "Med Sel";
+const char pstrUsageMediaSelectComputer [] PROGMEM = "Med Sel Comp";
+const char pstrUsageMediaSelectTV [] PROGMEM = "Med Sel TV";
+const char pstrUsageMediaSelectWWW [] PROGMEM = "Med Sel WWW";
+const char pstrUsageMediaSelectDVD [] PROGMEM = "Med Sel DVD";
+const char pstrUsageMediaSelectTelephone [] PROGMEM = "Med Sel Tel";
+const char pstrUsageMediaSelectProgramGuide [] PROGMEM = "Med Sel PG";
+const char pstrUsageMediaSelectVideoPhone [] PROGMEM = "Med Sel Vid";
+const char pstrUsageMediaSelectGames [] PROGMEM = "Med Sel Games";
+const char pstrUsageMediaSelectMessages [] PROGMEM = "Med Sel Msg";
+const char pstrUsageMediaSelectCD [] PROGMEM = "Med Sel CD";
+const char pstrUsageMediaSelectVCR [] PROGMEM = "Med Sel VCR";
+const char pstrUsageMediaSelectTuner [] PROGMEM = "Med Sel Tuner";
+const char pstrUsageQuit [] PROGMEM = "Quit";
+const char pstrUsageHelp [] PROGMEM = "Help";
+const char pstrUsageMediaSelectTape [] PROGMEM = "Med Sel Tape";
+const char pstrUsageMediaSelectCable [] PROGMEM = "Med Sel Cbl";
+const char pstrUsageMediaSelectSatellite [] PROGMEM = "Med Sel Sat";
+const char pstrUsageMediaSelectSecurity [] PROGMEM = "Med Sel Secur";
+const char pstrUsageMediaSelectHome [] PROGMEM = "Med Sel Home";
+const char pstrUsageMediaSelectCall [] PROGMEM = "Med Sel Call";
+const char pstrUsageChannelIncrement [] PROGMEM = "Ch Inc";
+const char pstrUsageChannelDecrement [] PROGMEM = "Ch Dec";
+const char pstrUsageMediaSelectSAP [] PROGMEM = "Med Sel SAP";
+const char pstrUsageVCRPlus [] PROGMEM = "VCR+";
+const char pstrUsageOnce [] PROGMEM = "Once";
+const char pstrUsageDaily [] PROGMEM = "Daily";
+const char pstrUsageWeekly [] PROGMEM = "Weekly";
+const char pstrUsageMonthly [] PROGMEM = "Monthly";
+//const char pstrUsagePlay [] PROGMEM = "Play";
+//const char pstrUsagePause [] PROGMEM = "Pause";
+//const char pstrUsageRecord [] PROGMEM = "Rec";
+//const char pstrUsageFastForward [] PROGMEM = "FF";
+//const char pstrUsageRewind [] PROGMEM = "Rewind";
+const char pstrUsageScanNextTrack [] PROGMEM = "Next Track";
+const char pstrUsageScanPreviousTrack [] PROGMEM = "Prev Track";
+//const char pstrUsageStop [] PROGMEM = "Stop";
+const char pstrUsageEject [] PROGMEM = "Eject";
+const char pstrUsageRandomPlay [] PROGMEM = "Random";
+const char pstrUsageSelectDisk [] PROGMEM = "Sel Disk";
+const char pstrUsageEnterDisk [] PROGMEM = "Ent Disk";
+//const char pstrUsageRepeat [] PROGMEM = "Repeat";
+const char pstrUsageTracking [] PROGMEM = "Tracking";
+const char pstrUsageTrackNormal [] PROGMEM = "Trk Norm";
+const char pstrUsageSlowTracking [] PROGMEM = "Slow Trk";
+const char pstrUsageFrameForward [] PROGMEM = "Frm Fwd";
+const char pstrUsageFrameBackwards [] PROGMEM = "Frm Back";
+const char pstrUsageMark [] PROGMEM = "Mark";
+const char pstrUsageClearMark [] PROGMEM = "Clr Mark";
+const char pstrUsageRepeatFromMark [] PROGMEM = "Rpt Mark";
+const char pstrUsageReturnToMark [] PROGMEM = "Ret to Mark";
+const char pstrUsageSearchMarkForward [] PROGMEM = "Search Mark Fwd";
+const char pstrUsageSearchMarkBackwards [] PROGMEM = "Search Mark Back";
+const char pstrUsageCounterReset [] PROGMEM = "Counter Reset";
+const char pstrUsageShowCounter [] PROGMEM = "Show Counter";
+const char pstrUsageTrackingIncrement [] PROGMEM = "Track Inc";
+const char pstrUsageTrackingDecrement [] PROGMEM = "Track Dec";
+const char pstrUsageStopEject [] PROGMEM = "Stop/Eject";
+const char pstrUsagePlayPause [] PROGMEM = "Play/Pause";
+const char pstrUsagePlaySkip [] PROGMEM = "Play/Skip";
+const char pstrUsageVolume [] PROGMEM = "Vol";
+const char pstrUsageBalance [] PROGMEM = "Balance";
+//const char pstrUsageMute [] PROGMEM = "Mute";
+const char pstrUsageBass [] PROGMEM = "Bass";
+const char pstrUsageTreble [] PROGMEM = "Treble";
+const char pstrUsageBassBoost [] PROGMEM = "Bass Boost";
+const char pstrUsageSurroundMode [] PROGMEM = "Surround";
+const char pstrUsageLoudness [] PROGMEM = "Loud";
+const char pstrUsageMPX [] PROGMEM = "MPX";
+const char pstrUsageVolumeIncrement [] PROGMEM = "Vol Inc";
+const char pstrUsageVolumeDecrement [] PROGMEM = "Vol Dec";
+const char pstrUsageSpeedSelect [] PROGMEM = "Speed";
+const char pstrUsagePlaybackSpeed [] PROGMEM = "Play Speed";
+const char pstrUsageStandardPlay [] PROGMEM = "Std Play";
+const char pstrUsageLongPlay [] PROGMEM = "Long Play";
+const char pstrUsageExtendedPlay [] PROGMEM = "Ext Play";
+const char pstrUsageSlow [] PROGMEM = "Slow";
+const char pstrUsageFanEnable [] PROGMEM = "Fan Enbl";
+const char pstrUsageFanSpeed [] PROGMEM = "Fan Speed";
+const char pstrUsageLightEnable [] PROGMEM = "Light Enbl";
+const char pstrUsageLightIlluminationLevel [] PROGMEM = "Light Illum Lev";
+const char pstrUsageClimateControlEnable [] PROGMEM = "Climate Enbl";
+const char pstrUsageRoomTemperature [] PROGMEM = "Room Temp";
+const char pstrUsageSecurityEnable [] PROGMEM = "Secur Enbl";
+const char pstrUsageFireAlarm [] PROGMEM = "Fire Alm";
+const char pstrUsagePoliceAlarm [] PROGMEM = "Police Alm";
+const char pstrUsageProximity [] PROGMEM = "Prox";
+const char pstrUsageMotion [] PROGMEM = "Motion";
+const char pstrUsageDuresAlarm [] PROGMEM = "Dures Alm";
+const char pstrUsageHoldupAlarm [] PROGMEM = "Holdup Alm";
+const char pstrUsageMedicalAlarm [] PROGMEM = "Med Alm";
+const char pstrUsageBalanceRight [] PROGMEM = "Balance Right";
+const char pstrUsageBalanceLeft [] PROGMEM = "Balance Left";
+const char pstrUsageBassIncrement [] PROGMEM = "Bass Inc";
+const char pstrUsageBassDecrement [] PROGMEM = "Bass Dec";
+const char pstrUsageTrebleIncrement [] PROGMEM = "Treble Inc";
+const char pstrUsageTrebleDecrement [] PROGMEM = "Treble Dec";
+const char pstrUsageSpeakerSystem [] PROGMEM = "Spk Sys";
+const char pstrUsageChannelLeft [] PROGMEM = "Ch Left";
+const char pstrUsageChannelRight [] PROGMEM = "Ch Right";
+const char pstrUsageChannelCenter [] PROGMEM = "Ch Center";
+const char pstrUsageChannelFront [] PROGMEM = "Ch Front";
+const char pstrUsageChannelCenterFront [] PROGMEM = "Ch Cntr Front";
+const char pstrUsageChannelSide [] PROGMEM = "Ch Side";
+const char pstrUsageChannelSurround [] PROGMEM = "Ch Surround";
+const char pstrUsageChannelLowFreqEnhancement [] PROGMEM = "Ch Low Freq Enh";
+const char pstrUsageChannelTop [] PROGMEM = "Ch Top";
+const char pstrUsageChannelUnknown [] PROGMEM = "Ch Unk";
+const char pstrUsageSubChannel [] PROGMEM = "Sub-ch";
+const char pstrUsageSubChannelIncrement [] PROGMEM = "Sub-ch Inc";
+const char pstrUsageSubChannelDecrement [] PROGMEM = "Sub-ch Dec";
+const char pstrUsageAlternateAudioIncrement [] PROGMEM = "Alt Aud Inc";
+const char pstrUsageAlternateAudioDecrement [] PROGMEM = "Alt Aud Dec";
+const char pstrUsageApplicationLaunchButtons [] PROGMEM = "App Launch Btns";
+const char pstrUsageALLaunchButtonConfigTool [] PROGMEM = "AL Launch Conf Tl";
+const char pstrUsageALProgrammableButton [] PROGMEM = "AL Pgm Btn";
+const char pstrUsageALConsumerControlConfig [] PROGMEM = "AL Cons Ctrl Cfg";
+const char pstrUsageALWordProcessor [] PROGMEM = "AL Word Proc";
+const char pstrUsageALTextEditor [] PROGMEM = "AL Txt Edtr";
+const char pstrUsageALSpreadsheet [] PROGMEM = "AL Sprdsheet";
+const char pstrUsageALGraphicsEditor [] PROGMEM = "AL Graph Edtr";
+const char pstrUsageALPresentationApp [] PROGMEM = "AL Present App";
+const char pstrUsageALDatabaseApp [] PROGMEM = "AL DB App";
+const char pstrUsageALEmailReader [] PROGMEM = "AL E-mail Rdr";
+const char pstrUsageALNewsreader [] PROGMEM = "AL Newsrdr";
+const char pstrUsageALVoicemail [] PROGMEM = "AL Voicemail";
+const char pstrUsageALContactsAddressBook [] PROGMEM = "AL Addr Book";
+const char pstrUsageALCalendarSchedule [] PROGMEM = "AL Clndr/Schdlr";
+const char pstrUsageALTaskProjectManager [] PROGMEM = "AL Task/Prj Mgr";
+const char pstrUsageALLogJournalTimecard [] PROGMEM = "AL Log/Jrnl/Tmcrd";
+const char pstrUsageALCheckbookFinance [] PROGMEM = "AL Chckbook/Fin";
+const char pstrUsageALCalculator [] PROGMEM = "AL Calc";
+const char pstrUsageALAVCapturePlayback [] PROGMEM = "AL A/V Capt/Play";
+const char pstrUsageALLocalMachineBrowser [] PROGMEM = "AL Loc Mach Brow";
+const char pstrUsageALLANWANBrow [] PROGMEM = "AL LAN/WAN Brow";
+const char pstrUsageALInternetBrowser [] PROGMEM = "AL I-net Brow";
+const char pstrUsageALRemoteNetISPConnect [] PROGMEM = "AL Rem Net Con";
+const char pstrUsageALNetworkConference [] PROGMEM = "AL Net Conf";
+const char pstrUsageALNetworkChat [] PROGMEM = "AL Net Chat";
+const char pstrUsageALTelephonyDialer [] PROGMEM = "AL Tel/Dial";
+const char pstrUsageALLogon [] PROGMEM = "AL Logon";
+const char pstrUsageALLogoff [] PROGMEM = "AL Logoff";
+const char pstrUsageALLogonLogoff [] PROGMEM = "AL Logon/Logoff";
+const char pstrUsageALTermLockScrSav [] PROGMEM = "AL Term Lock/Scr Sav";
+const char pstrUsageALControlPannel [] PROGMEM = "AL Ctrl Pan";
+const char pstrUsageALCommandLineProcessorRun [] PROGMEM = "AL Cmd/Run";
+const char pstrUsageALProcessTaskManager [] PROGMEM = "AL Task Mgr";
+const char pstrUsageALSelectTaskApplication [] PROGMEM = "AL Sel App";
+const char pstrUsageALNextTaskApplication [] PROGMEM = "AL Next App";
+const char pstrUsageALPreviousTaskApplication [] PROGMEM = "AL Prev App";
+const char pstrUsageALPreemptiveHaltTaskApp [] PROGMEM = "AL Prmpt Halt App";
+const char pstrUsageALIntegratedHelpCenter [] PROGMEM = "AL Hlp Cntr";
+const char pstrUsageALDocuments [] PROGMEM = "AL Docs";
+const char pstrUsageALThesaurus [] PROGMEM = "AL Thsrs";
+const char pstrUsageALDictionary [] PROGMEM = "AL Dict";
+const char pstrUsageALDesktop [] PROGMEM = "AL Desktop";
+const char pstrUsageALSpellCheck [] PROGMEM = "AL Spell Chk";
+const char pstrUsageALGrammarCheck [] PROGMEM = "AL Gram Chk";
+const char pstrUsageALWirelessStatus [] PROGMEM = "AL Wireless Sts";
+const char pstrUsageALKeyboardLayout [] PROGMEM = "AL Kbd Layout";
+const char pstrUsageALVirusProtection [] PROGMEM = "AL Vir Protect";
+const char pstrUsageALEncryption [] PROGMEM = "AL Encrypt";
+const char pstrUsageALScreenSaver [] PROGMEM = "AL Scr Sav";
+const char pstrUsageALAlarms [] PROGMEM = "AL Alarms";
+const char pstrUsageALClock [] PROGMEM = "AL Clock";
+const char pstrUsageALFileBrowser [] PROGMEM = "AL File Brow";
+const char pstrUsageALPowerStatus [] PROGMEM = "AL Pwr Sts";
+const char pstrUsageALImageBrowser [] PROGMEM = "AL Img Brow";
+const char pstrUsageALAudioBrowser [] PROGMEM = "AL Aud Brow";
+const char pstrUsageALMovieBrowser [] PROGMEM = "AL Mov Brow";
+const char pstrUsageALDigitalRightsManager [] PROGMEM = "AL Dig Rights Mgr";
+const char pstrUsageALDigitalWallet [] PROGMEM = "AL Dig Wallet";
+const char pstrUsageALInstantMessaging [] PROGMEM = "AL Inst Msg";
+const char pstrUsageALOEMFeaturesBrowser [] PROGMEM = "AL OEM Tips Brow";
+const char pstrUsageALOEMHelp [] PROGMEM = "AL OEM Hlp";
+const char pstrUsageALOnlineCommunity [] PROGMEM = "AL Online Com";
+const char pstrUsageALEntertainmentContentBrow [] PROGMEM = "AL Ent Cont Brow";
+const char pstrUsageALOnlineShoppingBrowser [] PROGMEM = "AL Online Shop Brow";
+const char pstrUsageALSmartCardInfoHelp [] PROGMEM = "AL SmartCard Inf";
+const char pstrUsageALMarketMonitorFinBrowser [] PROGMEM = "AL Market Brow";
+const char pstrUsageALCustomCorpNewsBrowser [] PROGMEM = "AL Cust Corp News Brow";
+const char pstrUsageALOnlineActivityBrowser [] PROGMEM = "AL Online Act Brow";
+const char pstrUsageALResearchSearchBrowser [] PROGMEM = "AL Search Brow";
+const char pstrUsageALAudioPlayer [] PROGMEM = "AL Aud Player";
+const char pstrUsageGenericGUIAppControls [] PROGMEM = "Gen GUI App Ctrl";
+const char pstrUsageACNew [] PROGMEM = "AC New";
+const char pstrUsageACOpen [] PROGMEM = "AC Open";
+const char pstrUsageACClose [] PROGMEM = "AC Close";
+const char pstrUsageACExit [] PROGMEM = "AC Exit";
+const char pstrUsageACMaximize [] PROGMEM = "AC Max";
+const char pstrUsageACMinimize [] PROGMEM = "AC Min";
+const char pstrUsageACSave [] PROGMEM = "AC Save";
+const char pstrUsageACPrint [] PROGMEM = "AC Print";
+const char pstrUsageACProperties [] PROGMEM = "AC Prop";
+const char pstrUsageACUndo [] PROGMEM = "AC Undo";
+const char pstrUsageACCopy [] PROGMEM = "AC Copy";
+const char pstrUsageACCut [] PROGMEM = "AC Cut";
+const char pstrUsageACPaste [] PROGMEM = "AC Paste";
+const char pstrUsageACSelectAll [] PROGMEM = "AC Sel All";
+const char pstrUsageACFind [] PROGMEM = "AC Find";
+const char pstrUsageACFindAndReplace [] PROGMEM = "AC Find/Replace";
+const char pstrUsageACSearch [] PROGMEM = "AC Search";
+const char pstrUsageACGoto [] PROGMEM = "AC Goto";
+const char pstrUsageACHome [] PROGMEM = "AC Home";
+const char pstrUsageACBack [] PROGMEM = "AC Back";
+const char pstrUsageACForward [] PROGMEM = "AC Fwd";
+const char pstrUsageACStop [] PROGMEM = "AC Stop";
+const char pstrUsageACRefresh [] PROGMEM = "AC Refresh";
+const char pstrUsageACPreviousLink [] PROGMEM = "AC Prev Link";
+const char pstrUsageACNextLink [] PROGMEM = "AC Next Link";
+const char pstrUsageACBookmarks [] PROGMEM = "AC Bkmarks";
+const char pstrUsageACHistory [] PROGMEM = "AC Hist";
+const char pstrUsageACSubscriptions [] PROGMEM = "AC Subscr";
+const char pstrUsageACZoomIn [] PROGMEM = "AC Zoom In";
+const char pstrUsageACZoomOut [] PROGMEM = "AC Zoom Out";
+const char pstrUsageACZoom [] PROGMEM = "AC Zoom";
+const char pstrUsageACFullScreenView [] PROGMEM = "AC Full Scr";
+const char pstrUsageACNormalView [] PROGMEM = "AC Norm View";
+const char pstrUsageACViewToggle [] PROGMEM = "AC View Tgl";
+const char pstrUsageACScrollUp [] PROGMEM = "AC Scroll Up";
+const char pstrUsageACScrollDown [] PROGMEM = "AC Scroll Down";
+const char pstrUsageACScroll [] PROGMEM = "AC Scroll";
+const char pstrUsageACPanLeft [] PROGMEM = "AC Pan Left";
+const char pstrUsageACPanRight [] PROGMEM = "AC Pan Right";
+const char pstrUsageACPan [] PROGMEM = "AC Pan";
+const char pstrUsageACNewWindow [] PROGMEM = "AC New Wnd";
+const char pstrUsageACTileHoriz [] PROGMEM = "AC Tile Horiz";
+const char pstrUsageACTileVert [] PROGMEM = "AC Tile Vert";
+const char pstrUsageACFormat [] PROGMEM = "AC Frmt";
+const char pstrUsageACEdit [] PROGMEM = "AC Edit";
+const char pstrUsageACBold [] PROGMEM = "AC Bold";
+const char pstrUsageACItalics [] PROGMEM = "AC Ital";
+const char pstrUsageACUnderline [] PROGMEM = "AC Under";
+const char pstrUsageACStrikethrough [] PROGMEM = "AC Strike";
+const char pstrUsageACSubscript [] PROGMEM = "AC Sub";
+const char pstrUsageACSuperscript [] PROGMEM = "AC Super";
+const char pstrUsageACAllCaps [] PROGMEM = "AC All Caps";
+const char pstrUsageACRotate [] PROGMEM = "AC Rotate";
+const char pstrUsageACResize [] PROGMEM = "AC Resize";
+const char pstrUsageACFlipHorizontal [] PROGMEM = "AC Flp H";
+const char pstrUsageACFlipVertical [] PROGMEM = "AC Flp V";
+const char pstrUsageACMirrorHorizontal [] PROGMEM = "AC Mir H";
+const char pstrUsageACMirrorVertical [] PROGMEM = "AC Mir V";
+const char pstrUsageACFontSelect [] PROGMEM = "AC Fnt Sel";
+const char pstrUsageACFontColor [] PROGMEM = "AC Fnt Clr";
+const char pstrUsageACFontSize [] PROGMEM = "AC Fnt Size";
+const char pstrUsageACJustifyLeft [] PROGMEM = "AC Just Left";
+const char pstrUsageACJustifyCenterH [] PROGMEM = "AC Just Cent H";
+const char pstrUsageACJustifyRight [] PROGMEM = "AC Just Right";
+const char pstrUsageACJustifyBlockH [] PROGMEM = "AC Just Block H";
+const char pstrUsageACJustifyTop [] PROGMEM = "AC Just Top";
+const char pstrUsageACJustifyCenterV [] PROGMEM = "AC Just Cent V";
+const char pstrUsageACJustifyBottom [] PROGMEM = "AC Just Bot";
+const char pstrUsageACJustifyBlockV [] PROGMEM = "AC Just Block V";
+const char pstrUsageACIndentDecrease [] PROGMEM = "AC Indent Dec";
+const char pstrUsageACIndentIncrease [] PROGMEM = "AC Indent Inc";
+const char pstrUsageACNumberedList [] PROGMEM = "AC Num List";
+const char pstrUsageACRestartNumbering [] PROGMEM = "AC Res Num";
+const char pstrUsageACBulletedList [] PROGMEM = "AC Blt List";
+const char pstrUsageACPromote [] PROGMEM = "AC Promote";
+const char pstrUsageACDemote [] PROGMEM = "AC Demote";
+const char pstrUsageACYes [] PROGMEM = "AC Yes";
+const char pstrUsageACNo [] PROGMEM = "AC No";
+const char pstrUsageACCancel [] PROGMEM = "AC Cancel";
+const char pstrUsageACCatalog [] PROGMEM = "AC Ctlg";
+const char pstrUsageACBuyChkout [] PROGMEM = "AC Buy";
+const char pstrUsageACAddToCart [] PROGMEM = "AC Add2Cart";
+const char pstrUsageACExpand [] PROGMEM = "AC Xpnd";
+const char pstrUsageACExpandAll [] PROGMEM = "AC Xpand All";
+const char pstrUsageACCollapse [] PROGMEM = "AC Collapse";
+const char pstrUsageACCollapseAll [] PROGMEM = "AC Collapse All";
+const char pstrUsageACPrintPreview [] PROGMEM = "AC Prn Prevw";
+const char pstrUsageACPasteSpecial [] PROGMEM = "AC Paste Spec";
+const char pstrUsageACInsertMode [] PROGMEM = "AC Ins Mode";
+const char pstrUsageACDelete [] PROGMEM = "AC Del";
+const char pstrUsageACLock [] PROGMEM = "AC Lock";
+const char pstrUsageACUnlock [] PROGMEM = "AC Unlock";
+const char pstrUsageACProtect [] PROGMEM = "AC Prot";
+const char pstrUsageACUnprotect [] PROGMEM = "AC Unprot";
+const char pstrUsageACAttachComment [] PROGMEM = "AC Attach Cmnt";
+const char pstrUsageACDeleteComment [] PROGMEM = "AC Del Cmnt";
+const char pstrUsageACViewComment [] PROGMEM = "AC View Cmnt";
+const char pstrUsageACSelectWord [] PROGMEM = "AC Sel Word";
+const char pstrUsageACSelectSentence [] PROGMEM = "AC Sel Sntc";
+const char pstrUsageACSelectParagraph [] PROGMEM = "AC Sel Para";
+const char pstrUsageACSelectColumn [] PROGMEM = "AC Sel Col";
+const char pstrUsageACSelectRow [] PROGMEM = "AC Sel Row";
+const char pstrUsageACSelectTable [] PROGMEM = "AC Sel Tbl";
+const char pstrUsageACSelectObject [] PROGMEM = "AC Sel Obj";
+const char pstrUsageACRedoRepeat [] PROGMEM = "AC Redo";
+const char pstrUsageACSort [] PROGMEM = "AC Sort";
+const char pstrUsageACSortAscending [] PROGMEM = "AC Sort Asc";
+const char pstrUsageACSortDescending [] PROGMEM = "AC Sort Desc";
+const char pstrUsageACFilter [] PROGMEM = "AC Filt";
+const char pstrUsageACSetClock [] PROGMEM = "AC Set Clk";
+const char pstrUsageACViewClock [] PROGMEM = "AC View Clk";
+const char pstrUsageACSelectTimeZone [] PROGMEM = "AC Sel Time Z";
+const char pstrUsageACEditTimeZone [] PROGMEM = "AC Edt Time Z";
+const char pstrUsageACSetAlarm [] PROGMEM = "AC Set Alm";
+const char pstrUsageACClearAlarm [] PROGMEM = "AC Clr Alm";
+const char pstrUsageACSnoozeAlarm [] PROGMEM = "AC Snz Alm";
+const char pstrUsageACResetAlarm [] PROGMEM = "AC Rst Alm";
+const char pstrUsageACSyncronize [] PROGMEM = "AC Sync";
+const char pstrUsageACSendReceive [] PROGMEM = "AC Snd/Rcv";
+const char pstrUsageACSendTo [] PROGMEM = "AC Snd To";
+const char pstrUsageACReply [] PROGMEM = "AC Reply";
+const char pstrUsageACReplyAll [] PROGMEM = "AC Reply All";
+const char pstrUsageACForwardMessage [] PROGMEM = "AC Fwd Msg";
+const char pstrUsageACSend [] PROGMEM = "AC Snd";
+const char pstrUsageACAttachFile [] PROGMEM = "AC Att File";
+const char pstrUsageACUpload [] PROGMEM = "AC Upld";
+const char pstrUsageACDownload [] PROGMEM = "AC Dnld";
+const char pstrUsageACSetBorders [] PROGMEM = "AC Set Brd";
+const char pstrUsageACInsertRow [] PROGMEM = "AC Ins Row";
+const char pstrUsageACInsertColumn [] PROGMEM = "AC Ins Col";
+const char pstrUsageACInsertFile [] PROGMEM = "AC Ins File";
+const char pstrUsageACInsertPicture [] PROGMEM = "AC Ins Pic";
+const char pstrUsageACInsertObject [] PROGMEM = "AC Ins Obj";
+const char pstrUsageACInsertSymbol [] PROGMEM = "AC Ins Sym";
+const char pstrUsageACSaveAndClose [] PROGMEM = "AC Sav&Cls";
+const char pstrUsageACRename [] PROGMEM = "AC Rename";
+const char pstrUsageACMerge [] PROGMEM = "AC Merge";
+const char pstrUsageACSplit [] PROGMEM = "AC Split";
+const char pstrUsageACDistributeHorizontaly [] PROGMEM = "AC Dist Hor";
+const char pstrUsageACDistributeVerticaly [] PROGMEM = "AC Dist Ver";
+
+// Digitaizers
+const char pstrUsageDigitizer [] PROGMEM = "Digitizer";
+const char pstrUsagePen [] PROGMEM = "Pen";
+const char pstrUsageLightPen [] PROGMEM = "Light Pen";
+const char pstrUsageTouchScreen [] PROGMEM = "Touch Scr";
+const char pstrUsageTouchPad [] PROGMEM = "Touch Pad";
+const char pstrUsageWhiteBoard [] PROGMEM = "White Brd";
+const char pstrUsageCoordinateMeasuringMachine [] PROGMEM = "Coord Meas Mach";
+const char pstrUsage3DDigitizer [] PROGMEM = "3D Dgtz";
+const char pstrUsageStereoPlotter [] PROGMEM = "Stereo Plot";
+const char pstrUsageArticulatedArm [] PROGMEM = "Art Arm";
+const char pstrUsageArmature [] PROGMEM = "Armature";
+const char pstrUsageMultiplePointDigitizer [] PROGMEM = "Multi Point Dgtz";
+const char pstrUsageFreeSpaceWand [] PROGMEM = "Free Space Wand";
+const char pstrUsageStylus [] PROGMEM = "Stylus";
+const char pstrUsagePuck [] PROGMEM = "Puck";
+const char pstrUsageFinger [] PROGMEM = "Finger";
+const char pstrUsageTipPressure [] PROGMEM = "Tip Press";
+const char pstrUsageBarrelPressure [] PROGMEM = "Brl Press";
+const char pstrUsageInRange [] PROGMEM = "In Range";
+const char pstrUsageTouch [] PROGMEM = "Touch";
+const char pstrUsageUntouch [] PROGMEM = "Untouch";
+const char pstrUsageTap [] PROGMEM = "Tap";
+const char pstrUsageQuality [] PROGMEM = "Qlty";
+const char pstrUsageDataValid [] PROGMEM = "Data Valid";
+const char pstrUsageTransducerIndex [] PROGMEM = "Transducer Ind";
+const char pstrUsageTabletFunctionKeys [] PROGMEM = "Tabl Func Keys";
+const char pstrUsageProgramChangeKeys [] PROGMEM = "Pgm Chng Keys";
+//const char pstrUsageBatteryStrength [] PROGMEM = "Bat Strength";
+const char pstrUsageInvert [] PROGMEM = "Invert";
+const char pstrUsageXTilt [] PROGMEM = "X Tilt";
+const char pstrUsageYTilt [] PROGMEM = "Y Tilt";
+const char pstrUsageAzimuth [] PROGMEM = "Azimuth";
+const char pstrUsageAltitude [] PROGMEM = "Altitude";
+const char pstrUsageTwist [] PROGMEM = "Twist";
+const char pstrUsageTipSwitch [] PROGMEM = "Tip Sw";
+const char pstrUsageSecondaryTipSwitch [] PROGMEM = "Scnd Tip Sw";
+const char pstrUsageBarrelSwitch [] PROGMEM = "Brl Sw";
+const char pstrUsageEraser [] PROGMEM = "Eraser";
+const char pstrUsageTabletPick [] PROGMEM = "Tbl Pick";
+
+// Alphanumeric Display Page
+const char pstrUsageAlphanumericDisplay [] PROGMEM = "Alphanum Disp";
+const char pstrUsageBitmappedDisplay [] PROGMEM = "Bmp Disp";
+const char pstrUsageDisplayAttributesReport [] PROGMEM = "Disp Attr Rpt";
+const char pstrUsageASCIICharacterSet [] PROGMEM = "ASCII chset";
+const char pstrUsageDataReadBack [] PROGMEM = "Data Rd Back";
+const char pstrUsageFontReadBack [] PROGMEM = "Fnt Rd Back";
+const char pstrUsageDisplayControlReport [] PROGMEM = "Disp Ctrl Rpt";
+const char pstrUsageClearDisplay [] PROGMEM = "Clr Disp";
+//const char pstrUsageDisplayEnable [] PROGMEM = "Disp Enbl";
+const char pstrUsageScreenSaverDelay [] PROGMEM = "Scr Sav Delay";
+const char pstrUsageScreenSaverEnable [] PROGMEM = "Scr Sav Enbl";
+const char pstrUsageVerticalScroll [] PROGMEM = "V Scroll";
+const char pstrUsageHorizontalScroll [] PROGMEM = "H Scroll";
+const char pstrUsageCharacterReport [] PROGMEM = "Char Rpt";
+const char pstrUsageDisplayData [] PROGMEM = "Disp Data";
+const char pstrUsageDisplayStatus [] PROGMEM = "Disp Stat";
+const char pstrUsageStatusNotReady [] PROGMEM = "Stat !Ready";
+const char pstrUsageStatusReady [] PROGMEM = "Stat Ready";
+const char pstrUsageErrorNotALoadableCharacter [] PROGMEM = "Err Not Ld Char";
+const char pstrUsageErrorFotDataCanNotBeRead [] PROGMEM = "Fnt Data Rd Err";
+const char pstrUsageCursorPositionReport [] PROGMEM = "Cur Pos Rpt";
+const char pstrUsageRow [] PROGMEM = "Row";
+const char pstrUsageColumn [] PROGMEM = "Col";
+const char pstrUsageRows [] PROGMEM = "Rows";
+const char pstrUsageColumns [] PROGMEM = "Cols";
+const char pstrUsageCursorPixelPosition [] PROGMEM = "Cur Pix Pos";
+const char pstrUsageCursorMode [] PROGMEM = "Cur Mode";
+const char pstrUsageCursorEnable [] PROGMEM = "Cur Enbl";
+const char pstrUsageCursorBlink [] PROGMEM = "Cur Blnk";
+const char pstrUsageFontReport [] PROGMEM = "Fnt Rpt";
+const char pstrUsageFontData [] PROGMEM = "Fnt Data";
+const char pstrUsageCharacterWidth [] PROGMEM = "Char Wdth";
+const char pstrUsageCharacterHeight [] PROGMEM = "Char Hght";
+const char pstrUsageCharacterSpacingHorizontal [] PROGMEM = "Char Space H";
+const char pstrUsageCharacterSpacingVertical [] PROGMEM = "Char Space V";
+const char pstrUsageUnicodeCharset [] PROGMEM = "Unicode Char";
+const char pstrUsageFont7Segment [] PROGMEM = "Fnt 7-seg";
+const char pstrUsage7SegmentDirectMap [] PROGMEM = "7-seg map";
+const char pstrUsageFont14Segment [] PROGMEM = "Fnt 14-seg";
+const char pstrUsage14SegmentDirectMap [] PROGMEM = "14-seg map";
+const char pstrUsageDisplayBrightness [] PROGMEM = "Disp Bright";
+const char pstrUsageDisplayContrast [] PROGMEM = "Disp Cntrst";
+const char pstrUsageCharacterAttribute [] PROGMEM = "Char Attr";
+const char pstrUsageAttributeReadback [] PROGMEM = "Attr Readbk";
+const char pstrUsageAttributeData [] PROGMEM = "Attr Data";
+const char pstrUsageCharAttributeEnhance [] PROGMEM = "Char Attr Enh";
+const char pstrUsageCharAttributeUnderline [] PROGMEM = "Char Attr Undl";
+const char pstrUsageCharAttributeBlink [] PROGMEM = "Char Attr Blnk";
+const char pstrUsageBitmapSizeX [] PROGMEM = "Bmp Size X";
+const char pstrUsageBitmapSizeY [] PROGMEM = "Bmp Size Y";
+const char pstrUsageBitDepthFormat [] PROGMEM = "Bit Dpth Fmt";
+const char pstrUsageDisplayOrientation [] PROGMEM = "Disp Ornt";
+const char pstrUsagePaletteReport [] PROGMEM = "Pal Rpt";
+const char pstrUsagePaletteDataSize [] PROGMEM = "Pal Data Size";
+const char pstrUsagePaletteDataOffset [] PROGMEM = "Pal Data Off";
+const char pstrUsagePaletteData [] PROGMEM = "Pal Data";
+const char pstrUsageBlitReport [] PROGMEM = "Blit Rpt";
+const char pstrUsageBlitRectangleX1 [] PROGMEM = "Blit Rect X1";
+const char pstrUsageBlitRectangleY1 [] PROGMEM = "Blit Rect Y1";
+const char pstrUsageBlitRectangleX2 [] PROGMEM = "Blit Rect X2";
+const char pstrUsageBlitRectangleY2 [] PROGMEM = "Blit Rect Y2";
+const char pstrUsageBlitData [] PROGMEM = "Blit Data";
+const char pstrUsageSoftButton [] PROGMEM = "Soft Btn";
+const char pstrUsageSoftButtonID [] PROGMEM = "Soft Btn ID";
+const char pstrUsageSoftButtonSide [] PROGMEM = "Soft Btn Side";
+const char pstrUsageSoftButtonOffset1 [] PROGMEM = "Soft Btn Off1";
+const char pstrUsageSoftButtonOffset2 [] PROGMEM = "Soft Btn Off2";
+const char pstrUsageSoftButtonReport [] PROGMEM = "Soft Btn Rpt";
+
+// Medical Instrument Page
+const char pstrUsageMedicalUltrasound [] PROGMEM = "Med Ultrasnd";
+const char pstrUsageVCRAcquisition [] PROGMEM = "VCR/Acq";
+const char pstrUsageFreezeThaw [] PROGMEM = "Freeze";
+const char pstrUsageClipStore [] PROGMEM = "Clip Store";
+const char pstrUsageUpdate [] PROGMEM = "Update";
+const char pstrUsageNext [] PROGMEM = "Next";
+const char pstrUsageSave [] PROGMEM = "Save";
+const char pstrUsagePrint [] PROGMEM = "Print";
+const char pstrUsageMicrophoneEnable [] PROGMEM = "Mic Enbl";
+const char pstrUsageCine [] PROGMEM = "Cine";
+const char pstrUsageTransmitPower [] PROGMEM = "Trans Pwr";
+//const char pstrUsageVolume [] PROGMEM = "Vol";
+const char pstrUsageFocus [] PROGMEM = "Focus";
+const char pstrUsageDepth [] PROGMEM = "Depth";
+const char pstrUsageSoftStepPrimary [] PROGMEM = "Soft Stp-Pri";
+const char pstrUsageSoftStepSecondary [] PROGMEM = "Soft Stp-Sec";
+const char pstrUsageDepthGainCompensation [] PROGMEM = "Dpth Gain Comp";
+const char pstrUsageZoomSelect [] PROGMEM = "Zoom Sel";
+const char pstrUsageZoomAdjust [] PROGMEM = "Zoom Adj";
+const char pstrUsageSpectralDopplerModeSelect [] PROGMEM = "Spec Dop Mode Sel";
+const char pstrUsageSpectralDopplerModeAdjust [] PROGMEM = "Spec Dop Mode Adj";
+const char pstrUsageColorDopplerModeSelect [] PROGMEM = "Color Dop Mode Sel";
+const char pstrUsageColorDopplerModeAdjust [] PROGMEM = "Color Dop Mode Adj";
+const char pstrUsageMotionModeSelect [] PROGMEM = "Motion Mode Sel";
+const char pstrUsageMotionModeAdjust [] PROGMEM = "Motion Mode Adj";
+const char pstrUsage2DModeSelect [] PROGMEM = "2D Mode Sel";
+const char pstrUsage2DModeAdjust [] PROGMEM = "2D Mode Adj";
+const char pstrUsageSoftControlSelect [] PROGMEM = "Soft Ctrl Sel";
+const char pstrUsageSoftControlAdjust [] PROGMEM = "Soft Ctrl Adj";
+
+//extern const char *usagePageTitles0[15];
+//const char *usagePageTitles1[];
+//const char *genDesktopTitles0[];
+//const char *genDesktopTitles1[];
+//const char *genDesktopTitles2[];
+//const char *genDesktopTitles3[];
+//const char *genDesktopTitles4[];
+//const char *simuTitles0[];
+//const char *simuTitles1[];
+//const char *simuTitles2[];
+//const char *vrTitles0[];
+//const char *vrTitles1[];
+//const char *sportsCtrlTitles0[];
+//const char *sportsCtrlTitles1[];
+//const char *sportsCtrlTitles2[];
+//const char *gameTitles0[];
+//const char *gameTitles1[];
+//const char *genDevCtrlTitles[];
+//const char *ledTitles[];
+//const char *telTitles0[];
+//const char *telTitles1[];
+//const char *telTitles2[];
+//const char *telTitles3[];
+//const char *telTitles4[];
+//const char *telTitles5[];
+//const char *consTitles0[];
+//const char *consTitles1[];
+//const char *consTitles2[];
+//const char *consTitles3[];
+//const char *consTitles4[];
+//const char *consTitles5[];
+//const char *consTitles6[];
+//const char *consTitles7[];
+//const char *consTitles8[];
+//const char *consTitles9[];
+//const char *consTitlesA[];
+//const char *consTitlesB[];
+//const char *consTitlesC[];
+//const char *consTitlesD[];
+//const char *consTitlesE[];
+//const char *digitTitles0[];
+//const char *digitTitles1[];
+//const char *digitTitles2[];
+//const char *aplphanumTitles0[];
+//const char *aplphanumTitles1[];
+//const char *aplphanumTitles2[];
+//const char *medInstrTitles0[];
+//const char *medInstrTitles1[];
+//const char *medInstrTitles2[];
+//const char *medInstrTitles3[];
+//const char *medInstrTitles4[];
+
+#endif //__HIDUSAGESTR_H__
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidusagetitlearrays.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidusagetitlearrays.cpp
new file mode 100644
index 000000000..ee233002c
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/hidusagetitlearrays.cpp
@@ -0,0 +1,1048 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+#if !defined(__HIDUSAGETITLEARRAYS_H__)
+#define __HIDUSAGETITLEARRAYS_H__
+
+#include "hidusagestr.h"
+
+// This is here why?
+
+//const char *usagePageTitles0[] PROGMEM =
+//{
+// pstrUsagePageGenericDesktopControls ,
+// pstrUsagePageSimulationControls ,
+// pstrUsagePageVRControls ,
+// pstrUsagePageSportControls ,
+// pstrUsagePageGameControls ,
+// pstrUsagePageGenericDeviceControls ,
+// pstrUsagePageKeyboardKeypad ,
+// pstrUsagePageLEDs ,
+// pstrUsagePageButton ,
+// pstrUsagePageOrdinal ,
+// pstrUsagePageTelephone ,
+// pstrUsagePageConsumer ,
+// pstrUsagePageDigitizer ,
+// pstrUsagePagePID ,
+// pstrUsagePageUnicode
+//};
+//
+//const char *usagePageTitles1[] PROGMEM =
+//{
+// pstrUsagePageBarCodeScanner ,
+// pstrUsagePageScale ,
+// pstrUsagePageMSRDevices ,
+// pstrUsagePagePointOfSale ,
+// pstrUsagePageCameraControl ,
+// pstrUsagePageArcade
+//};
+//const char *genDesktopTitles0[] PROGMEM =
+//{
+// pstrUsagePointer ,
+// pstrUsageMouse ,
+// pstrUsageJoystick ,
+// pstrUsageGamePad ,
+// pstrUsageKeyboard ,
+// pstrUsageKeypad ,
+// pstrUsageMultiAxisController ,
+// pstrUsageTabletPCSystemControls
+//
+//};
+//const char *genDesktopTitles1[] PROGMEM =
+//{
+// pstrUsageX ,
+// pstrUsageY ,
+// pstrUsageZ ,
+// pstrUsageRx ,
+// pstrUsageRy ,
+// pstrUsageRz ,
+// pstrUsageSlider ,
+// pstrUsageDial ,
+// pstrUsageWheel ,
+// pstrUsageHatSwitch ,
+// pstrUsageCountedBuffer ,
+// pstrUsageByteCount ,
+// pstrUsageMotionWakeup ,
+// pstrUsageStart ,
+// pstrUsageSelect ,
+// pstrUsagePageReserved ,
+// pstrUsageVx ,
+// pstrUsageVy ,
+// pstrUsageVz ,
+// pstrUsageVbrx ,
+// pstrUsageVbry ,
+// pstrUsageVbrz ,
+// pstrUsageVno ,
+// pstrUsageFeatureNotification ,
+// pstrUsageResolutionMultiplier
+//};
+//const char *genDesktopTitles2[] PROGMEM =
+//{
+// pstrUsageSystemControl ,
+// pstrUsageSystemPowerDown ,
+// pstrUsageSystemSleep ,
+// pstrUsageSystemWakeup ,
+// pstrUsageSystemContextMenu ,
+// pstrUsageSystemMainMenu ,
+// pstrUsageSystemAppMenu ,
+// pstrUsageSystemMenuHelp ,
+// pstrUsageSystemMenuExit ,
+// pstrUsageSystemMenuSelect ,
+// pstrUsageSystemMenuRight ,
+// pstrUsageSystemMenuLeft ,
+// pstrUsageSystemMenuUp ,
+// pstrUsageSystemMenuDown ,
+// pstrUsageSystemColdRestart ,
+// pstrUsageSystemWarmRestart ,
+// pstrUsageDPadUp ,
+// pstrUsageDPadDown ,
+// pstrUsageDPadRight ,
+// pstrUsageDPadLeft
+//};
+//const char *genDesktopTitles3[] PROGMEM =
+//{
+// pstrUsageSystemDock ,
+// pstrUsageSystemUndock ,
+// pstrUsageSystemSetup ,
+// pstrUsageSystemBreak ,
+// pstrUsageSystemDebuggerBreak ,
+// pstrUsageApplicationBreak ,
+// pstrUsageApplicationDebuggerBreak,
+// pstrUsageSystemSpeakerMute ,
+// pstrUsageSystemHibernate
+//};
+//const char *genDesktopTitles4[] PROGMEM =
+//{
+// pstrUsageSystemDisplayInvert ,
+// pstrUsageSystemDisplayInternal ,
+// pstrUsageSystemDisplayExternal ,
+// pstrUsageSystemDisplayBoth ,
+// pstrUsageSystemDisplayDual ,
+// pstrUsageSystemDisplayToggleIntExt ,
+// pstrUsageSystemDisplaySwapPriSec ,
+// pstrUsageSystemDisplayLCDAutoscale
+//};
+//const char *simuTitles0[] PROGMEM =
+//{
+// pstrUsageFlightSimulationDevice ,
+// pstrUsageAutomobileSimulationDevice ,
+// pstrUsageTankSimulationDevice ,
+// pstrUsageSpaceshipSimulationDevice ,
+// pstrUsageSubmarineSimulationDevice ,
+// pstrUsageSailingSimulationDevice ,
+// pstrUsageMotocicleSimulationDevice ,
+// pstrUsageSportsSimulationDevice ,
+// pstrUsageAirplaneSimulationDevice ,
+// pstrUsageHelicopterSimulationDevice ,
+// pstrUsageMagicCarpetSimulationDevice,
+// pstrUsageBicycleSimulationDevice
+//};
+//const char *simuTitles1[] PROGMEM =
+//{
+// pstrUsageFlightControlStick ,
+// pstrUsageFlightStick ,
+// pstrUsageCyclicControl ,
+// pstrUsageCyclicTrim ,
+// pstrUsageFlightYoke ,
+// pstrUsageTrackControl
+//};
+//const char *simuTitles2[] PROGMEM =
+//{
+// pstrUsageAileron ,
+// pstrUsageAileronTrim ,
+// pstrUsageAntiTorqueControl ,
+// pstrUsageAutopilotEnable ,
+// pstrUsageChaffRelease ,
+// pstrUsageCollectiveControl ,
+// pstrUsageDiveBrake ,
+// pstrUsageElectronicCountermeasures ,
+// pstrUsageElevator ,
+// pstrUsageElevatorTrim ,
+// pstrUsageRudder ,
+// pstrUsageThrottle ,
+// pstrUsageFlightCommunications ,
+// pstrUsageFlareRelease ,
+// pstrUsageLandingGear ,
+// pstrUsageToeBrake ,
+// pstrUsageTrigger ,
+// pstrUsageWeaponsArm ,
+// pstrUsageWeaponsSelect ,
+// pstrUsageWingFlaps ,
+// pstrUsageAccelerator ,
+// pstrUsageBrake ,
+// pstrUsageClutch ,
+// pstrUsageShifter ,
+// pstrUsageSteering ,
+// pstrUsageTurretDirection ,
+// pstrUsageBarrelElevation ,
+// pstrUsageDivePlane ,
+// pstrUsageBallast ,
+// pstrUsageBicycleCrank ,
+// pstrUsageHandleBars ,
+// pstrUsageFrontBrake ,
+// pstrUsageRearBrake
+//};
+//const char *vrTitles0[] PROGMEM =
+//{
+// pstrUsageBelt ,
+// pstrUsageBodySuit ,
+// pstrUsageFlexor ,
+// pstrUsageGlove ,
+// pstrUsageHeadTracker ,
+// pstrUsageHeadMountedDisplay ,
+// pstrUsageHandTracker ,
+// pstrUsageOculometer ,
+// pstrUsageVest ,
+// pstrUsageAnimatronicDevice
+//};
+//const char *vrTitles1[] PROGMEM =
+//{
+// pstrUsageStereoEnable ,
+// pstrUsageDisplayEnable
+//};
+//const char *sportsCtrlTitles0[] PROGMEM =
+//{
+// pstrUsageBaseballBat ,
+// pstrUsageGolfClub ,
+// pstrUsageRowingMachine ,
+// pstrUsageTreadmill
+//};
+//const char *sportsCtrlTitles1[] PROGMEM =
+//{
+// pstrUsageOar ,
+// pstrUsageSlope ,
+// pstrUsageRate ,
+// pstrUsageStickSpeed ,
+// pstrUsageStickFaceAngle ,
+// pstrUsageStickHeelToe ,
+// pstrUsageStickFollowThough ,
+// pstrUsageStickTempo ,
+// pstrUsageStickType ,
+// pstrUsageStickHeight
+//};
+//const char *sportsCtrlTitles2[] PROGMEM =
+//{
+// pstrUsagePutter ,
+// pstrUsage1Iron ,
+// pstrUsage2Iron ,
+// pstrUsage3Iron ,
+// pstrUsage4Iron ,
+// pstrUsage5Iron ,
+// pstrUsage6Iron ,
+// pstrUsage7Iron ,
+// pstrUsage8Iron ,
+// pstrUsage9Iron ,
+// pstrUsage10Iron ,
+// pstrUsage11Iron ,
+// pstrUsageSandWedge ,
+// pstrUsageLoftWedge ,
+// pstrUsagePowerWedge ,
+// pstrUsage1Wood ,
+// pstrUsage3Wood ,
+// pstrUsage5Wood ,
+// pstrUsage7Wood ,
+// pstrUsage9Wood
+//};
+//const char *gameTitles0[] PROGMEM =
+//{
+// pstrUsage3DGameController ,
+// pstrUsagePinballDevice ,
+// pstrUsageGunDevice
+//};
+//const char *gameTitles1[] PROGMEM =
+//{
+// pstrUsagePointOfView ,
+// pstrUsageTurnRightLeft ,
+// pstrUsagePitchForwardBackward ,
+// pstrUsageRollRightLeft ,
+// pstrUsageMoveRightLeft ,
+// pstrUsageMoveForwardBackward ,
+// pstrUsageMoveUpDown ,
+// pstrUsageLeanRightLeft ,
+// pstrUsageLeanForwardBackward ,
+// pstrUsageHeightOfPOV ,
+// pstrUsageFlipper ,
+// pstrUsageSecondaryFlipper ,
+// pstrUsageBump ,
+// pstrUsageNewGame ,
+// pstrUsageShootBall ,
+// pstrUsagePlayer ,
+// pstrUsageGunBolt ,
+// pstrUsageGunClip ,
+// pstrUsageGunSelector ,
+// pstrUsageGunSingleShot ,
+// pstrUsageGunBurst ,
+// pstrUsageGunAutomatic ,
+// pstrUsageGunSafety ,
+// pstrUsageGamepadFireJump ,
+// pstrUsageGamepadTrigger
+//};
+//const char *genDevCtrlTitles[] PROGMEM =
+//{
+// pstrUsageBatteryStrength,
+// pstrUsageWirelessChannel,
+// pstrUsageWirelessID,
+// pstrUsageDiscoverWirelessControl,
+// pstrUsageSecurityCodeCharEntered,
+// pstrUsageSecurityCodeCharErased,
+// pstrUsageSecurityCodeCleared
+//};
+//const char *ledTitles[] PROGMEM =
+//{
+// pstrUsageNumLock ,
+// pstrUsageCapsLock ,
+// pstrUsageScrollLock ,
+// pstrUsageCompose ,
+// pstrUsageKana ,
+// pstrUsagePower ,
+// pstrUsageShift ,
+// pstrUsageDoNotDisturb ,
+// pstrUsageMute ,
+// pstrUsageToneEnable ,
+// pstrUsageHighCutFilter ,
+// pstrUsageLowCutFilter ,
+// pstrUsageEqualizerEnable ,
+// pstrUsageSoundFieldOn ,
+// pstrUsageSurroundOn ,
+// pstrUsageRepeat ,
+// pstrUsageStereo ,
+// pstrUsageSamplingRateDetect ,
+// pstrUsageSpinning ,
+// pstrUsageCAV ,
+// pstrUsageCLV ,
+// pstrUsageRecordingFormatDetect ,
+// pstrUsageOffHook ,
+// pstrUsageRing ,
+// pstrUsageMessageWaiting ,
+// pstrUsageDataMode ,
+// pstrUsageBatteryOperation ,
+// pstrUsageBatteryOK ,
+// pstrUsageBatteryLow ,
+// pstrUsageSpeaker ,
+// pstrUsageHeadSet ,
+// pstrUsageHold ,
+// pstrUsageMicrophone ,
+// pstrUsageCoverage ,
+// pstrUsageNightMode ,
+// pstrUsageSendCalls ,
+// pstrUsageCallPickup ,
+// pstrUsageConference ,
+// pstrUsageStandBy ,
+// pstrUsageCameraOn ,
+// pstrUsageCameraOff ,
+// pstrUsageOnLine ,
+// pstrUsageOffLine ,
+// pstrUsageBusy ,
+// pstrUsageReady ,
+// pstrUsagePaperOut ,
+// pstrUsagePaperJam ,
+// pstrUsageRemote ,
+// pstrUsageForward ,
+// pstrUsageReverse ,
+// pstrUsageStop ,
+// pstrUsageRewind ,
+// pstrUsageFastForward ,
+// pstrUsagePlay ,
+// pstrUsagePause ,
+// pstrUsageRecord ,
+// pstrUsageError ,
+// pstrUsageSelectedIndicator ,
+// pstrUsageInUseIndicator ,
+// pstrUsageMultiModeIndicator ,
+// pstrUsageIndicatorOn ,
+// pstrUsageIndicatorFlash ,
+// pstrUsageIndicatorSlowBlink ,
+// pstrUsageIndicatorFastBlink ,
+// pstrUsageIndicatorOff ,
+// pstrUsageFlashOnTime ,
+// pstrUsageSlowBlinkOnTime ,
+// pstrUsageSlowBlinkOffTime ,
+// pstrUsageFastBlinkOnTime ,
+// pstrUsageFastBlinkOffTime ,
+// pstrUsageIndicatorColor ,
+// pstrUsageIndicatorRed ,
+// pstrUsageIndicatorGreen ,
+// pstrUsageIndicatorAmber ,
+// pstrUsageGenericIndicator ,
+// pstrUsageSystemSuspend ,
+// pstrUsageExternalPowerConnected
+//};
+//const char *telTitles0 [] PROGMEM =
+//{
+// pstrUsagePhone ,
+// pstrUsageAnsweringMachine ,
+// pstrUsageMessageControls ,
+// pstrUsageHandset ,
+// pstrUsageHeadset ,
+// pstrUsageTelephonyKeyPad ,
+// pstrUsageProgrammableButton
+//};
+//const char *telTitles1 [] PROGMEM =
+//{
+// pstrUsageHookSwitch ,
+// pstrUsageFlash ,
+// pstrUsageFeature ,
+// pstrUsageHold ,
+// pstrUsageRedial ,
+// pstrUsageTransfer ,
+// pstrUsageDrop ,
+// pstrUsagePark ,
+// pstrUsageForwardCalls ,
+// pstrUsageAlternateFunction ,
+// pstrUsageLine ,
+// pstrUsageSpeakerPhone ,
+// pstrUsageConference ,
+// pstrUsageRingEnable ,
+// pstrUsageRingSelect ,
+// pstrUsagePhoneMute ,
+// pstrUsageCallerID ,
+// pstrUsageSend
+//};
+//const char *telTitles2 [] PROGMEM =
+//{
+// pstrUsageSpeedDial ,
+// pstrUsageStoreNumber ,
+// pstrUsageRecallNumber ,
+// pstrUsagePhoneDirectory
+//};
+//const char *telTitles3 [] PROGMEM =
+//{
+// pstrUsageVoiceMail ,
+// pstrUsageScreenCalls ,
+// pstrUsageDoNotDisturb ,
+// pstrUsageMessage ,
+// pstrUsageAnswerOnOff
+//};
+//const char *telTitles4 [] PROGMEM =
+//{
+// pstrUsageInsideDialTone ,
+// pstrUsageOutsideDialTone ,
+// pstrUsageInsideRingTone ,
+// pstrUsageOutsideRingTone ,
+// pstrUsagePriorityRingTone ,
+// pstrUsageInsideRingback ,
+// pstrUsagePriorityRingback ,
+// pstrUsageLineBusyTone ,
+// pstrUsageReorderTone ,
+// pstrUsageCallWaitingTone ,
+// pstrUsageConfirmationTone1 ,
+// pstrUsageConfirmationTone2 ,
+// pstrUsageTonesOff ,
+// pstrUsageOutsideRingback ,
+// pstrUsageRinger
+//};
+//const char *telTitles5 [] PROGMEM =
+//{
+// pstrUsagePhoneKey0 ,
+// pstrUsagePhoneKey1 ,
+// pstrUsagePhoneKey2 ,
+// pstrUsagePhoneKey3 ,
+// pstrUsagePhoneKey4 ,
+// pstrUsagePhoneKey5 ,
+// pstrUsagePhoneKey6 ,
+// pstrUsagePhoneKey7 ,
+// pstrUsagePhoneKey8 ,
+// pstrUsagePhoneKey9 ,
+// pstrUsagePhoneKeyStar ,
+// pstrUsagePhoneKeyPound ,
+// pstrUsagePhoneKeyA ,
+// pstrUsagePhoneKeyB ,
+// pstrUsagePhoneKeyC ,
+// pstrUsagePhoneKeyD
+//};
+//const char *consTitles0[] PROGMEM =
+//{
+// pstrUsageConsumerControl,
+// pstrUsageNumericKeyPad,
+// pstrUsageProgrammableButton,
+// pstrUsageMicrophone,
+// pstrUsageHeadphone,
+// pstrUsageGraphicEqualizer
+//};
+//const char *consTitles1[] PROGMEM =
+//{
+// pstrUsagePlus10 ,
+// pstrUsagePlus100,
+// pstrUsageAMPM
+//};
+//const char *consTitles2[] PROGMEM =
+//{
+// pstrUsagePower ,
+// pstrUsageReset ,
+// pstrUsageSleep ,
+// pstrUsageSleepAfter ,
+// pstrUsageSleepMode ,
+// pstrUsageIllumination ,
+// pstrUsageFunctionButtons
+//
+//};
+//const char *consTitles3[] PROGMEM =
+//{
+// pstrUsageMenu ,
+// pstrUsageMenuPick ,
+// pstrUsageMenuUp ,
+// pstrUsageMenuDown ,
+// pstrUsageMenuLeft ,
+// pstrUsageMenuRight ,
+// pstrUsageMenuEscape ,
+// pstrUsageMenuValueIncrease,
+// pstrUsageMenuValueDecrease
+//};
+//const char *consTitles4[] PROGMEM =
+//{
+// pstrUsageDataOnScreen ,
+// pstrUsageClosedCaption ,
+// pstrUsageClosedCaptionSelect,
+// pstrUsageVCRTV ,
+// pstrUsageBroadcastMode ,
+// pstrUsageSnapshot ,
+// pstrUsageStill
+//};
+//const char *consTitles5[] PROGMEM =
+//{
+// pstrUsageSelection ,
+// pstrUsageAssignSelection ,
+// pstrUsageModeStep ,
+// pstrUsageRecallLast ,
+// pstrUsageEnterChannel ,
+// pstrUsageOrderMovie ,
+// pstrUsageChannel ,
+// pstrUsageMediaSelection ,
+// pstrUsageMediaSelectComputer ,
+// pstrUsageMediaSelectTV ,
+// pstrUsageMediaSelectWWW ,
+// pstrUsageMediaSelectDVD ,
+// pstrUsageMediaSelectTelephone ,
+// pstrUsageMediaSelectProgramGuide ,
+// pstrUsageMediaSelectVideoPhone ,
+// pstrUsageMediaSelectGames ,
+// pstrUsageMediaSelectMessages ,
+// pstrUsageMediaSelectCD ,
+// pstrUsageMediaSelectVCR ,
+// pstrUsageMediaSelectTuner ,
+// pstrUsageQuit ,
+// pstrUsageHelp ,
+// pstrUsageMediaSelectTape ,
+// pstrUsageMediaSelectCable ,
+// pstrUsageMediaSelectSatellite ,
+// pstrUsageMediaSelectSecurity ,
+// pstrUsageMediaSelectHome ,
+// pstrUsageMediaSelectCall ,
+// pstrUsageChannelIncrement ,
+// pstrUsageChannelDecrement ,
+// pstrUsageMediaSelectSAP ,
+// pstrUsagePageReserved ,
+// pstrUsageVCRPlus ,
+// pstrUsageOnce ,
+// pstrUsageDaily ,
+// pstrUsageWeekly ,
+// pstrUsageMonthly
+//};
+//const char *consTitles6[] PROGMEM =
+//{
+// pstrUsagePlay ,
+// pstrUsagePause ,
+// pstrUsageRecord ,
+// pstrUsageFastForward ,
+// pstrUsageRewind ,
+// pstrUsageScanNextTrack ,
+// pstrUsageScanPreviousTrack ,
+// pstrUsageStop ,
+// pstrUsageEject ,
+// pstrUsageRandomPlay ,
+// pstrUsageSelectDisk ,
+// pstrUsageEnterDisk ,
+// pstrUsageRepeat ,
+// pstrUsageTracking ,
+// pstrUsageTrackNormal ,
+// pstrUsageSlowTracking ,
+// pstrUsageFrameForward ,
+// pstrUsageFrameBackwards ,
+// pstrUsageMark ,
+// pstrUsageClearMark ,
+// pstrUsageRepeatFromMark ,
+// pstrUsageReturnToMark ,
+// pstrUsageSearchMarkForward ,
+// pstrUsageSearchMarkBackwards ,
+// pstrUsageCounterReset ,
+// pstrUsageShowCounter ,
+// pstrUsageTrackingIncrement ,
+// pstrUsageTrackingDecrement ,
+// pstrUsageStopEject ,
+// pstrUsagePlayPause ,
+// pstrUsagePlaySkip
+//};
+//const char *consTitles7[] PROGMEM =
+//{
+// pstrUsageVolume ,
+// pstrUsageBalance ,
+// pstrUsageMute ,
+// pstrUsageBass ,
+// pstrUsageTreble ,
+// pstrUsageBassBoost ,
+// pstrUsageSurroundMode ,
+// pstrUsageLoudness ,
+// pstrUsageMPX ,
+// pstrUsageVolumeIncrement ,
+// pstrUsageVolumeDecrement
+//};
+//const char *consTitles8[] PROGMEM =
+//{
+// pstrUsageSpeedSelect ,
+// pstrUsagePlaybackSpeed ,
+// pstrUsageStandardPlay ,
+// pstrUsageLongPlay ,
+// pstrUsageExtendedPlay ,
+// pstrUsageSlow
+//};
+//const char *consTitles9[] PROGMEM =
+//{
+// pstrUsageFanEnable ,
+// pstrUsageFanSpeed ,
+// pstrUsageLightEnable ,
+// pstrUsageLightIlluminationLevel ,
+// pstrUsageClimateControlEnable ,
+// pstrUsageRoomTemperature ,
+// pstrUsageSecurityEnable ,
+// pstrUsageFireAlarm ,
+// pstrUsagePoliceAlarm ,
+// pstrUsageProximity ,
+// pstrUsageMotion ,
+// pstrUsageDuresAlarm ,
+// pstrUsageHoldupAlarm ,
+// pstrUsageMedicalAlarm
+//};
+//const char *consTitlesA[] PROGMEM =
+//{
+// pstrUsageBalanceRight ,
+// pstrUsageBalanceLeft ,
+// pstrUsageBassIncrement ,
+// pstrUsageBassDecrement ,
+// pstrUsageTrebleIncrement ,
+// pstrUsageTrebleDecrement
+//};
+//const char *consTitlesB[] PROGMEM =
+//{
+// pstrUsageSpeakerSystem ,
+// pstrUsageChannelLeft ,
+// pstrUsageChannelRight ,
+// pstrUsageChannelCenter ,
+// pstrUsageChannelFront ,
+// pstrUsageChannelCenterFront ,
+// pstrUsageChannelSide ,
+// pstrUsageChannelSurround ,
+// pstrUsageChannelLowFreqEnhancement ,
+// pstrUsageChannelTop ,
+// pstrUsageChannelUnknown
+//};
+//const char *consTitlesC[] PROGMEM =
+//{
+// pstrUsageSubChannel ,
+// pstrUsageSubChannelIncrement ,
+// pstrUsageSubChannelDecrement ,
+// pstrUsageAlternateAudioIncrement ,
+// pstrUsageAlternateAudioDecrement
+//};
+//const char *consTitlesD[] PROGMEM =
+//{
+// pstrUsageApplicationLaunchButtons ,
+// pstrUsageALLaunchButtonConfigTool ,
+// pstrUsageALProgrammableButton ,
+// pstrUsageALConsumerControlConfig ,
+// pstrUsageALWordProcessor ,
+// pstrUsageALTextEditor ,
+// pstrUsageALSpreadsheet ,
+// pstrUsageALGraphicsEditor ,
+// pstrUsageALPresentationApp ,
+// pstrUsageALDatabaseApp ,
+// pstrUsageALEmailReader ,
+// pstrUsageALNewsreader ,
+// pstrUsageALVoicemail ,
+// pstrUsageALContactsAddressBook ,
+// pstrUsageALCalendarSchedule ,
+// pstrUsageALTaskProjectManager ,
+// pstrUsageALLogJournalTimecard ,
+// pstrUsageALCheckbookFinance ,
+// pstrUsageALCalculator ,
+// pstrUsageALAVCapturePlayback ,
+// pstrUsageALLocalMachineBrowser ,
+// pstrUsageALLANWANBrow ,
+// pstrUsageALInternetBrowser ,
+// pstrUsageALRemoteNetISPConnect ,
+// pstrUsageALNetworkConference ,
+// pstrUsageALNetworkChat ,
+// pstrUsageALTelephonyDialer ,
+// pstrUsageALLogon ,
+// pstrUsageALLogoff ,
+// pstrUsageALLogonLogoff ,
+// pstrUsageALTermLockScrSav ,
+// pstrUsageALControlPannel ,
+// pstrUsageALCommandLineProcessorRun ,
+// pstrUsageALProcessTaskManager ,
+// pstrUsageALSelectTaskApplication ,
+// pstrUsageALNextTaskApplication ,
+// pstrUsageALPreviousTaskApplication ,
+// pstrUsageALPreemptiveHaltTaskApp ,
+// pstrUsageALIntegratedHelpCenter ,
+// pstrUsageALDocuments ,
+// pstrUsageALThesaurus ,
+// pstrUsageALDictionary ,
+// pstrUsageALDesktop ,
+// pstrUsageALSpellCheck ,
+// pstrUsageALGrammarCheck ,
+// pstrUsageALWirelessStatus ,
+// pstrUsageALKeyboardLayout ,
+// pstrUsageALVirusProtection ,
+// pstrUsageALEncryption ,
+// pstrUsageALScreenSaver ,
+// pstrUsageALAlarms ,
+// pstrUsageALClock ,
+// pstrUsageALFileBrowser ,
+// pstrUsageALPowerStatus ,
+// pstrUsageALImageBrowser ,
+// pstrUsageALAudioBrowser ,
+// pstrUsageALMovieBrowser ,
+// pstrUsageALDigitalRightsManager ,
+// pstrUsageALDigitalWallet ,
+// pstrUsagePageReserved ,
+// pstrUsageALInstantMessaging ,
+// pstrUsageALOEMFeaturesBrowser ,
+// pstrUsageALOEMHelp ,
+// pstrUsageALOnlineCommunity ,
+// pstrUsageALEntertainmentContentBrow ,
+// pstrUsageALOnlineShoppingBrowser ,
+// pstrUsageALSmartCardInfoHelp ,
+// pstrUsageALMarketMonitorFinBrowser ,
+// pstrUsageALCustomCorpNewsBrowser ,
+// pstrUsageALOnlineActivityBrowser ,
+// pstrUsageALResearchSearchBrowser ,
+// pstrUsageALAudioPlayer
+//};
+//const char *consTitlesE[] PROGMEM =
+//{
+// pstrUsageGenericGUIAppControls ,
+// pstrUsageACNew ,
+// pstrUsageACOpen ,
+// pstrUsageACClose ,
+// pstrUsageACExit ,
+// pstrUsageACMaximize ,
+// pstrUsageACMinimize ,
+// pstrUsageACSave ,
+// pstrUsageACPrint ,
+// pstrUsageACProperties ,
+// pstrUsageACUndo ,
+// pstrUsageACCopy ,
+// pstrUsageACCut ,
+// pstrUsageACPaste ,
+// pstrUsageACSelectAll ,
+// pstrUsageACFind ,
+// pstrUsageACFindAndReplace ,
+// pstrUsageACSearch ,
+// pstrUsageACGoto ,
+// pstrUsageACHome ,
+// pstrUsageACBack ,
+// pstrUsageACForward ,
+// pstrUsageACStop ,
+// pstrUsageACRefresh ,
+// pstrUsageACPreviousLink ,
+// pstrUsageACNextLink ,
+// pstrUsageACBookmarks ,
+// pstrUsageACHistory ,
+// pstrUsageACSubscriptions ,
+// pstrUsageACZoomIn ,
+// pstrUsageACZoomOut ,
+// pstrUsageACZoom ,
+// pstrUsageACFullScreenView ,
+// pstrUsageACNormalView ,
+// pstrUsageACViewToggle ,
+// pstrUsageACScrollUp ,
+// pstrUsageACScrollDown ,
+// pstrUsageACScroll ,
+// pstrUsageACPanLeft ,
+// pstrUsageACPanRight ,
+// pstrUsageACPan ,
+// pstrUsageACNewWindow ,
+// pstrUsageACTileHoriz ,
+// pstrUsageACTileVert ,
+// pstrUsageACFormat ,
+// pstrUsageACEdit ,
+// pstrUsageACBold ,
+// pstrUsageACItalics ,
+// pstrUsageACUnderline ,
+// pstrUsageACStrikethrough ,
+// pstrUsageACSubscript ,
+// pstrUsageACSuperscript ,
+// pstrUsageACAllCaps ,
+// pstrUsageACRotate ,
+// pstrUsageACResize ,
+// pstrUsageACFlipHorizontal ,
+// pstrUsageACFlipVertical ,
+// pstrUsageACMirrorHorizontal ,
+// pstrUsageACMirrorVertical ,
+// pstrUsageACFontSelect ,
+// pstrUsageACFontColor ,
+// pstrUsageACFontSize ,
+// pstrUsageACJustifyLeft ,
+// pstrUsageACJustifyCenterH ,
+// pstrUsageACJustifyRight ,
+// pstrUsageACJustifyBlockH ,
+// pstrUsageACJustifyTop ,
+// pstrUsageACJustifyCenterV ,
+// pstrUsageACJustifyBottom ,
+// pstrUsageACJustifyBlockV ,
+// pstrUsageACIndentDecrease ,
+// pstrUsageACIndentIncrease ,
+// pstrUsageACNumberedList ,
+// pstrUsageACRestartNumbering ,
+// pstrUsageACBulletedList ,
+// pstrUsageACPromote ,
+// pstrUsageACDemote ,
+// pstrUsageACYes ,
+// pstrUsageACNo ,
+// pstrUsageACCancel ,
+// pstrUsageACCatalog ,
+// pstrUsageACBuyChkout ,
+// pstrUsageACAddToCart ,
+// pstrUsageACExpand ,
+// pstrUsageACExpandAll ,
+// pstrUsageACCollapse ,
+// pstrUsageACCollapseAll ,
+// pstrUsageACPrintPreview ,
+// pstrUsageACPasteSpecial ,
+// pstrUsageACInsertMode ,
+// pstrUsageACDelete ,
+// pstrUsageACLock ,
+// pstrUsageACUnlock ,
+// pstrUsageACProtect ,
+// pstrUsageACUnprotect ,
+// pstrUsageACAttachComment ,
+// pstrUsageACDeleteComment ,
+// pstrUsageACViewComment ,
+// pstrUsageACSelectWord ,
+// pstrUsageACSelectSentence ,
+// pstrUsageACSelectParagraph ,
+// pstrUsageACSelectColumn ,
+// pstrUsageACSelectRow ,
+// pstrUsageACSelectTable ,
+// pstrUsageACSelectObject ,
+// pstrUsageACRedoRepeat ,
+// pstrUsageACSort ,
+// pstrUsageACSortAscending ,
+// pstrUsageACSortDescending ,
+// pstrUsageACFilter ,
+// pstrUsageACSetClock ,
+// pstrUsageACViewClock ,
+// pstrUsageACSelectTimeZone ,
+// pstrUsageACEditTimeZone ,
+// pstrUsageACSetAlarm ,
+// pstrUsageACClearAlarm ,
+// pstrUsageACSnoozeAlarm ,
+// pstrUsageACResetAlarm ,
+// pstrUsageACSyncronize ,
+// pstrUsageACSendReceive ,
+// pstrUsageACSendTo ,
+// pstrUsageACReply ,
+// pstrUsageACReplyAll ,
+// pstrUsageACForwardMessage ,
+// pstrUsageACSend ,
+// pstrUsageACAttachFile ,
+// pstrUsageACUpload ,
+// pstrUsageACDownload ,
+// pstrUsageACSetBorders ,
+// pstrUsageACInsertRow ,
+// pstrUsageACInsertColumn ,
+// pstrUsageACInsertFile ,
+// pstrUsageACInsertPicture ,
+// pstrUsageACInsertObject ,
+// pstrUsageACInsertSymbol ,
+// pstrUsageACSaveAndClose ,
+// pstrUsageACRename ,
+// pstrUsageACMerge ,
+// pstrUsageACSplit ,
+// pstrUsageACDistributeHorizontaly ,
+// pstrUsageACDistributeVerticaly
+//};
+//const char *digitTitles0[] PROGMEM =
+//{
+// pstrUsageDigitizer ,
+// pstrUsagePen ,
+// pstrUsageLightPen ,
+// pstrUsageTouchScreen ,
+// pstrUsageTouchPad ,
+// pstrUsageWhiteBoard ,
+// pstrUsageCoordinateMeasuringMachine ,
+// pstrUsage3DDigitizer ,
+// pstrUsageStereoPlotter ,
+// pstrUsageArticulatedArm ,
+// pstrUsageArmature ,
+// pstrUsageMultiplePointDigitizer ,
+// pstrUsageFreeSpaceWand
+//};
+//const char *digitTitles1[] PROGMEM =
+//{
+// pstrUsageStylus ,
+// pstrUsagePuck ,
+// pstrUsageFinger
+//
+//};
+//const char *digitTitles2[] PROGMEM =
+//{
+// pstrUsageTipPressure ,
+// pstrUsageBarrelPressure ,
+// pstrUsageInRange ,
+// pstrUsageTouch ,
+// pstrUsageUntouch ,
+// pstrUsageTap ,
+// pstrUsageQuality ,
+// pstrUsageDataValid ,
+// pstrUsageTransducerIndex ,
+// pstrUsageTabletFunctionKeys ,
+// pstrUsageProgramChangeKeys ,
+// pstrUsageBatteryStrength ,
+// pstrUsageInvert ,
+// pstrUsageXTilt ,
+// pstrUsageYTilt ,
+// pstrUsageAzimuth ,
+// pstrUsageAltitude ,
+// pstrUsageTwist ,
+// pstrUsageTipSwitch ,
+// pstrUsageSecondaryTipSwitch ,
+// pstrUsageBarrelSwitch ,
+// pstrUsageEraser ,
+// pstrUsageTabletPick
+//};
+//const char *aplphanumTitles0[] PROGMEM =
+//{
+// pstrUsageAlphanumericDisplay,
+// pstrUsageBitmappedDisplay
+//};
+//const char *aplphanumTitles1[] PROGMEM =
+//{
+// pstrUsageDisplayAttributesReport ,
+// pstrUsageASCIICharacterSet ,
+// pstrUsageDataReadBack ,
+// pstrUsageFontReadBack ,
+// pstrUsageDisplayControlReport ,
+// pstrUsageClearDisplay ,
+// pstrUsageDisplayEnable ,
+// pstrUsageScreenSaverDelay ,
+// pstrUsageScreenSaverEnable ,
+// pstrUsageVerticalScroll ,
+// pstrUsageHorizontalScroll ,
+// pstrUsageCharacterReport ,
+// pstrUsageDisplayData ,
+// pstrUsageDisplayStatus ,
+// pstrUsageStatusNotReady ,
+// pstrUsageStatusReady ,
+// pstrUsageErrorNotALoadableCharacter ,
+// pstrUsageErrorFotDataCanNotBeRead ,
+// pstrUsageCursorPositionReport ,
+// pstrUsageRow ,
+// pstrUsageColumn ,
+// pstrUsageRows ,
+// pstrUsageColumns ,
+// pstrUsageCursorPixelPosition ,
+// pstrUsageCursorMode ,
+// pstrUsageCursorEnable ,
+// pstrUsageCursorBlink ,
+// pstrUsageFontReport ,
+// pstrUsageFontData ,
+// pstrUsageCharacterWidth ,
+// pstrUsageCharacterHeight ,
+// pstrUsageCharacterSpacingHorizontal ,
+// pstrUsageCharacterSpacingVertical ,
+// pstrUsageUnicodeCharset ,
+// pstrUsageFont7Segment ,
+// pstrUsage7SegmentDirectMap ,
+// pstrUsageFont14Segment ,
+// pstrUsage14SegmentDirectMap ,
+// pstrUsageDisplayBrightness ,
+// pstrUsageDisplayContrast ,
+// pstrUsageCharacterAttribute ,
+// pstrUsageAttributeReadback ,
+// pstrUsageAttributeData ,
+// pstrUsageCharAttributeEnhance ,
+// pstrUsageCharAttributeUnderline ,
+// pstrUsageCharAttributeBlink
+//};
+//const char *aplphanumTitles2[] PROGMEM =
+//{
+// pstrUsageBitmapSizeX ,
+// pstrUsageBitmapSizeY ,
+// pstrUsagePageReserved ,
+// pstrUsageBitDepthFormat ,
+// pstrUsageDisplayOrientation ,
+// pstrUsagePaletteReport ,
+// pstrUsagePaletteDataSize ,
+// pstrUsagePaletteDataOffset ,
+// pstrUsagePaletteData ,
+// pstrUsageBlitReport ,
+// pstrUsageBlitRectangleX1 ,
+// pstrUsageBlitRectangleY1 ,
+// pstrUsageBlitRectangleX2 ,
+// pstrUsageBlitRectangleY2 ,
+// pstrUsageBlitData ,
+// pstrUsageSoftButton ,
+// pstrUsageSoftButtonID ,
+// pstrUsageSoftButtonSide ,
+// pstrUsageSoftButtonOffset1 ,
+// pstrUsageSoftButtonOffset2 ,
+// pstrUsageSoftButtonReport
+//};
+//const char *medInstrTitles0[] PROGMEM =
+//{
+// pstrUsageVCRAcquisition ,
+// pstrUsageFreezeThaw ,
+// pstrUsageClipStore ,
+// pstrUsageUpdate ,
+// pstrUsageNext ,
+// pstrUsageSave ,
+// pstrUsagePrint ,
+// pstrUsageMicrophoneEnable
+//};
+//const char *medInstrTitles1[] PROGMEM =
+//{
+// pstrUsageCine ,
+// pstrUsageTransmitPower ,
+// pstrUsageVolume ,
+// pstrUsageFocus ,
+// pstrUsageDepth
+//};
+//const char *medInstrTitles2[] PROGMEM =
+//{
+// pstrUsageSoftStepPrimary ,
+// pstrUsageSoftStepSecondary
+//};
+//const char *medInstrTitles3[] PROGMEM =
+//{
+// pstrUsageZoomSelect ,
+// pstrUsageZoomAdjust ,
+// pstrUsageSpectralDopplerModeSelect ,
+// pstrUsageSpectralDopplerModeAdjust ,
+// pstrUsageColorDopplerModeSelect ,
+// pstrUsageColorDopplerModeAdjust ,
+// pstrUsageMotionModeSelect ,
+// pstrUsageMotionModeAdjust ,
+// pstrUsage2DModeSelect ,
+// pstrUsage2DModeAdjust
+//};
+//const char *medInstrTitles4[] PROGMEM =
+//{
+// pstrUsageSoftControlSelect ,
+// pstrUsageSoftControlAdjust
+//};
+
+#endif // __HIDUSAGETITLEARRAYS_H__
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/keywords.txt b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/keywords.txt
new file mode 100644
index 000000000..f4e19cd13
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/keywords.txt
@@ -0,0 +1,371 @@
+####################################################
+# Syntax Coloring Map For USB Library
+####################################################
+
+####################################################
+# Datatypes (KEYWORD1)
+####################################################
+
+USB KEYWORD1
+USBHub KEYWORD1
+
+####################################################
+# Syntax Coloring Map For BTD (Bluetooth) Library
+####################################################
+
+####################################################
+# Datatypes (KEYWORD1)
+####################################################
+
+BTD KEYWORD1
+
+####################################################
+# Methods and Functions (KEYWORD2)
+####################################################
+Task KEYWORD2
+
+####################################################
+# Syntax Coloring Map For PS3/PS4 Bluetooth/USB Library
+####################################################
+
+####################################################
+# Datatypes (KEYWORD1)
+####################################################
+
+PS3BT KEYWORD1
+PS3USB KEYWORD1
+PS4BT KEYWORD1
+PS4USB KEYWORD1
+
+####################################################
+# Methods and Functions (KEYWORD2)
+####################################################
+setBdaddr KEYWORD2
+getBdaddr KEYWORD2
+setMoveBdaddr KEYWORD2
+getMoveBdaddr KEYWORD2
+getMoveCalibration KEYWORD2
+
+getButtonPress KEYWORD2
+getButtonClick KEYWORD2
+getAnalogButton KEYWORD2
+getAnalogHat KEYWORD2
+getSensor KEYWORD2
+getAngle KEYWORD2
+get9DOFValues KEYWORD2
+getStatus KEYWORD2
+printStatusString KEYWORD2
+getTemperature KEYWORD2
+disconnect KEYWORD2
+
+setAllOff KEYWORD2
+setRumbleOff KEYWORD2
+setRumbleOn KEYWORD2
+setLedOff KEYWORD2
+setLedOn KEYWORD2
+setLedToggle KEYWORD2
+setLedFlash KEYWORD2
+moveSetBulb KEYWORD2
+moveSetRumble KEYWORD2
+
+attachOnInit KEYWORD2
+
+PS3Connected KEYWORD2
+PS3MoveConnected KEYWORD2
+PS3NavigationConnected KEYWORD2
+
+isReady KEYWORD2
+watingForConnection KEYWORD2
+
+isTouching KEYWORD2
+getX KEYWORD2
+getY KEYWORD2
+getTouchCounter KEYWORD2
+
+getUsbStatus KEYWORD2
+getAudioStatus KEYWORD2
+getMicStatus KEYWORD2
+
+####################################################
+# Constants and enums (LITERAL1)
+####################################################
+OFF LITERAL1
+LED1 LITERAL1
+LED2 LITERAL1
+LED3 LITERAL1
+LED4 LITERAL1
+LED5 LITERAL1
+LED6 LITERAL1
+LED7 LITERAL1
+LED8 LITERAL1
+LED9 LITERAL1
+LED10 LITERAL1
+
+Red LITERAL1
+Green LITERAL1
+Blue LITERAL1
+Yellow LITERAL1
+Lightblue LITERAL1
+Purble LITERAL1
+White LITERAL1
+Off LITERAL1
+
+SELECT LITERAL1
+L3 LITERAL1
+R3 LITERAL1
+START LITERAL1
+UP LITERAL1
+RIGHT LITERAL1
+DOWN LITERAL1
+LEFT LITERAL1
+L2 LITERAL1
+R2 LITERAL1
+L1 LITERAL1
+R1 LITERAL1
+TRIANGLE LITERAL1
+CIRCLE LITERAL1
+CROSS LITERAL1
+SQUARE LITERAL1
+PS LITERAL1
+MOVE LITERAL1
+T LITERAL1
+
+SHARE LITERAL1
+OPTIONS LITERAL1
+TOUCHPAD LITERAL1
+
+LeftHatX LITERAL1
+LeftHatY LITERAL1
+RightHatX LITERAL1
+RightHatY LITERAL1
+
+aX LITERAL1
+aY LITERAL1
+aZ LITERAL1
+gX LITERAL1
+gY LITERAL1
+gZ LITERAL1
+aXmove LITERAL1
+aYmove LITERAL1
+aZmove LITERAL1
+gXmove LITERAL1
+gYmove LITERAL1
+gZmove LITERAL1
+tempMove LITERAL1
+mXmove LITERAL1
+mZmove LITERAL1
+mYmove LITERAL1
+
+Pitch LITERAL1
+Roll LITERAL1
+
+Plugged LITERAL1
+Unplugged LITERAL1
+Charging LITERAL1
+NotCharging LITERAL1
+Shutdown LITERAL1
+Dying LITERAL1
+Low LITERAL1
+High LITERAL1
+Full LITERAL1
+MoveCharging LITERAL1
+MoveNotCharging LITERAL1
+MoveShutdown LITERAL1
+MoveDying LITERAL1
+MoveLow LITERAL1
+MoveHigh LITERAL1
+MoveFull LITERAL1
+CableRumble LITERAL1
+Cable LITERAL1
+BluetoothRumble LITERAL1
+Bluetooth LITERAL1
+
+RumbleHigh LITERAL1
+RumbleLow LITERAL1
+
+####################################################
+# Syntax Coloring Map For Xbox 360 Libraries
+####################################################
+
+####################################################
+# Datatypes (KEYWORD1)
+####################################################
+
+XBOXUSB KEYWORD1
+XBOXONE KEYWORD1
+XBOXOLD KEYWORD1
+XBOXRECV KEYWORD1
+
+####################################################
+# Methods and Functions (KEYWORD2)
+####################################################
+
+setLedRaw KEYWORD2
+setLedBlink KEYWORD2
+setLedMode KEYWORD2
+getBatteryLevel KEYWORD2
+buttonChanged KEYWORD2
+
+XboxReceiverConnected KEYWORD2
+Xbox360Connected KEYWORD2
+XboxOneConnected KEYWORD2
+
+####################################################
+# Constants and enums (LITERAL1)
+####################################################
+
+ALL LITERAL1
+
+ROTATING LITERAL1
+FASTBLINK LITERAL1
+SLOWBLINK LITERAL1
+ALTERNATING LITERAL1
+
+BACK LITERAL1
+
+XBOX LITERAL1
+SYNC LITERAL1
+
+BLACK LITERAL1
+WHITE LITERAL1
+
+A LITERAL1
+B LITERAL1
+X LITERAL1
+Y LITERAL1
+
+####################################################
+# Syntax Coloring Map For RFCOMM/SPP Library
+####################################################
+
+####################################################
+# Datatypes (KEYWORD1)
+####################################################
+
+SPP KEYWORD1
+
+####################################################
+# Methods and Functions (KEYWORD2)
+####################################################
+
+connected KEYWORD2
+discard KEYWORD2
+
+####################################################
+# Syntax Coloring Map For Wiimote Library
+####################################################
+
+####################################################
+# Datatypes (KEYWORD1)
+####################################################
+
+WII KEYWORD1
+
+####################################################
+# Methods and Functions (KEYWORD2)
+####################################################
+
+wiimoteConnected KEYWORD2
+nunchuckConnected KEYWORD2
+motionPlusConnected KEYWORD2
+wiiUProControllerConnected KEYWORD2
+wiiBalanceBoardConnected KEYWORD2
+setRumbleToggle KEYWORD2
+getPitch KEYWORD2
+getRoll KEYWORD2
+getYaw KEYWORD2
+getWiimotePitch KEYWORD2
+getWiimoteRoll KEYWORD2
+getNunchuckPitch KEYWORD2
+getNunchuckRoll KEYWORD2
+PAIR KEYWORD2
+statusRequest KEYWORD2
+getBatteryLevel KEYWORD2
+getWiiState KEYWORD2
+getWeight KEYWORD2
+getTotalWeight KEYWORD2
+getWeightRaw KEYWORD2
+
+####################################################
+# Constants and enums (LITERAL1)
+####################################################
+
+PLUS LITERAL1
+MINUS LITERAL1
+ONE LITERAL1
+TWO LITERAL1
+HOME LITERAL1
+Z LITERAL1
+C LITERAL1
+L LITERAL1
+R LITERAL1
+ZL LITERAL1
+ZR LITERAL1
+HatX LITERAL1
+HatY LITERAL1
+TopRight LITERAL1
+BotRight LITERAL1
+TopLeft LITERAL1
+BotLeft LITERAL1
+
+####################################################
+# Methods and Functions for the IR Camera
+####################################################
+
+IRinitialize KEYWORD2
+isIRCameraEnabled KEYWORD2
+getIRx1 KEYWORD2
+getIRy1 KEYWORD2
+getIRs1 KEYWORD2
+getIRx2 KEYWORD2
+getIRy2 KEYWORD2
+getIRs2 KEYWORD2
+getIRx3 KEYWORD2
+getIRy3 KEYWORD2
+getIRs3 KEYWORD2
+getIRx4 KEYWORD2
+getIRy4 KEYWORD2
+getIRs4 KEYWORD2
+
+####################################################
+# Syntax Coloring Map For BTHID Library
+####################################################
+
+####################################################
+# Datatypes (KEYWORD1)
+####################################################
+
+BTHID KEYWORD1
+
+####################################################
+# Methods and Functions (KEYWORD2)
+####################################################
+SetReportParser KEYWORD2
+setProtocolMode KEYWORD2
+
+####################################################
+# Syntax Coloring Map For PS Buzz Library
+####################################################
+
+####################################################
+# Datatypes (KEYWORD1)
+####################################################
+
+PSBuzz KEYWORD1
+
+####################################################
+# Methods and Functions (KEYWORD2)
+####################################################
+
+setLedOnAll KEYWORD2
+setLedOffAll KEYWORD2
+
+####################################################
+# Constants and enums (LITERAL1)
+####################################################
+
+RED LITERAL1
+YELLOW LITERAL1
+GREEN LITERAL1
+ORANGE LITERAL1
+BLUE LITERAL1
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/library.json b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/library.json
new file mode 100644
index 000000000..1d649b1e1
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/library.json
@@ -0,0 +1,47 @@
+{
+ "name": "USB-Host-Shield-20",
+ "keywords": "usb, host, ftdi, adk, acm, pl2303, hid, bluetooth, spp, ps3, ps4, buzz, xbox, wii, mass storage",
+ "description": "Revision 2.0 of MAX3421E-based USB Host Shield Library",
+ "authors":
+ [
+ {
+ "name": "Oleg Mazurov",
+ "email": "mazurov@circuitsathome.com",
+ "url": "http://www.circuitsathome.com",
+ "maintainer": true
+ },
+ {
+ "name": "Alexei Glushchenko",
+ "email": "alex-gl@mail.ru"
+ },
+ {
+ "name": "Kristian Lauszus",
+ "email": "kristianl@tkjelectronics.com",
+ "url": "http://tkjelectronics.com",
+ "maintainer": true
+ },
+ {
+ "name": "Andrew Kroll",
+ "email": "xxxajk@gmail.com",
+ "maintainer": true
+ }
+ ],
+ "repository":
+ {
+ "type": "git",
+ "url": "https://github.com/felis/USB_Host_Shield_2.0.git"
+ },
+ "examples":
+ [
+ "examples/*/*.ino",
+ "examples/*/*/*.ino"
+ ],
+ "frameworks": "arduino",
+ "platforms":
+ [
+ "atmelavr",
+ "teensy",
+ "atmelsam",
+ "nordicnrf51"
+ ]
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/library.properties b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/library.properties
new file mode 100644
index 000000000..7881b05e9
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/library.properties
@@ -0,0 +1,9 @@
+name=USB Host Shield Library 2.0
+version=1.1.0
+author=Oleg Mazurov (Circuits@Home) <mazurov@circuitsathome.com>, Kristian Lauszus (TKJ Electronics) <kristianl@tkjelectronics.com>, Andrew Kroll <xxxajk@gmail.com>, Alexei Glushchenko (Circuits@Home) <alex-gl@mail.ru>
+maintainer=Oleg Mazurov (Circuits@Home) <mazurov@circuitsathome.com>, Kristian Lauszus (TKJ Electronics) <kristianl@tkjelectronics.com>, Andrew Kroll <xxxajk@gmail.com>
+sentence=Revision 2.0 of MAX3421E-based USB Host Shield Library.
+paragraph=Supports HID devices, FTDI, ADK, ACM, PL2303, Bluetooth HID devices, SPP communication and mass storage devices. Furthermore it supports PS3, PS4, PS Buzz, Wii and Xbox controllers.
+category=Other
+url=https://github.com/felis/USB_Host_Shield_2.0
+architectures=* \ No newline at end of file
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/macros.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/macros.h
new file mode 100644
index 000000000..e14a711fa
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/macros.h
@@ -0,0 +1,82 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+
+#if !defined(_usb_h_) || defined(MACROS_H)
+#error "Never include macros.h directly; include Usb.h instead"
+#else
+#define MACROS_H
+
+////////////////////////////////////////////////////////////////////////////////
+// HANDY MACROS
+////////////////////////////////////////////////////////////////////////////////
+
+#define VALUE_BETWEEN(v,l,h) (((v)>(l)) && ((v)<(h)))
+#define VALUE_WITHIN(v,l,h) (((v)>=(l)) && ((v)<=(h)))
+#define output_pgm_message(wa,fp,mp,el) wa = &mp, fp((char *)pgm_read_pointer(wa), el)
+#define output_if_between(v,l,h,wa,fp,mp,el) if(VALUE_BETWEEN(v,l,h)) output_pgm_message(wa,fp,mp[v-(l+1)],el);
+
+#define SWAP(a, b) (((a) ^= (b)), ((b) ^= (a)), ((a) ^= (b)))
+#ifndef __BYTE_GRABBING_DEFINED__
+#define __BYTE_GRABBING_DEFINED__ 1
+#ifdef BROKEN_OPTIMIZER_LITTLE_ENDIAN
+// Note: Use this if your compiler generates horrible assembler!
+#define BGRAB0(__usi__) (((uint8_t *)&(__usi__))[0])
+#define BGRAB1(__usi__) (((uint8_t *)&(__usi__))[1])
+#define BGRAB2(__usi__) (((uint8_t *)&(__usi__))[2])
+#define BGRAB3(__usi__) (((uint8_t *)&(__usi__))[3])
+#define BGRAB4(__usi__) (((uint8_t *)&(__usi__))[4])
+#define BGRAB5(__usi__) (((uint8_t *)&(__usi__))[5])
+#define BGRAB6(__usi__) (((uint8_t *)&(__usi__))[6])
+#define BGRAB7(__usi__) (((uint8_t *)&(__usi__))[7])
+#else
+// Note: The cast alone to uint8_t is actually enough.
+// GCC throws out the "& 0xff", and the size is no different.
+// Some compilers need it.
+#define BGRAB0(__usi__) ((uint8_t)((__usi__) & 0xff ))
+#define BGRAB1(__usi__) ((uint8_t)(((__usi__) >> 8) & 0xff))
+#define BGRAB2(__usi__) ((uint8_t)(((__usi__) >> 16) & 0xff))
+#define BGRAB3(__usi__) ((uint8_t)(((__usi__) >> 24) & 0xff))
+#define BGRAB4(__usi__) ((uint8_t)(((__usi__) >> 32) & 0xff))
+#define BGRAB5(__usi__) ((uint8_t)(((__usi__) >> 40) & 0xff))
+#define BGRAB6(__usi__) ((uint8_t)(((__usi__) >> 48) & 0xff))
+#define BGRAB7(__usi__) ((uint8_t)(((__usi__) >> 56) & 0xff))
+#endif
+#define BOVER1(__usi__) ((uint16_t)(__usi__) << 8)
+#define BOVER2(__usi__) ((uint32_t)(__usi__) << 16)
+#define BOVER3(__usi__) ((uint32_t)(__usi__) << 24)
+#define BOVER4(__usi__) ((uint64_t)(__usi__) << 32)
+#define BOVER5(__usi__) ((uint64_t)(__usi__) << 40)
+#define BOVER6(__usi__) ((uint64_t)(__usi__) << 48)
+#define BOVER7(__usi__) ((uint64_t)(__usi__) << 56)
+
+// These are the smallest and fastest ways I have found so far in pure C/C++.
+#define BMAKE16(__usc1__,__usc0__) ((uint16_t)((uint16_t)(__usc0__) | (uint16_t)BOVER1(__usc1__)))
+#define BMAKE32(__usc3__,__usc2__,__usc1__,__usc0__) ((uint32_t)((uint32_t)(__usc0__) | (uint32_t)BOVER1(__usc1__) | (uint32_t)BOVER2(__usc2__) | (uint32_t)BOVER3(__usc3__)))
+#define BMAKE64(__usc7__,__usc6__,__usc5__,__usc4__,__usc3__,__usc2__,__usc1__,__usc0__) ((uint64_t)((uint64_t)__usc0__ | (uint64_t)BOVER1(__usc1__) | (uint64_t)BOVER2(__usc2__) | (uint64_t)BOVER3(__usc3__) | (uint64_t)BOVER4(__usc4__) | (uint64_t)BOVER5(__usc5__) | (uint64_t)BOVER6(__usc6__) | (uint64_t)BOVER1(__usc7__)))
+#endif
+
+/*
+ * Debug macros: Strings are stored in progmem (flash) instead of RAM.
+ */
+#define USBTRACE(s) (Notify(PSTR(s), 0x80))
+#define USBTRACE1(s,l) (Notify(PSTR(s), l))
+#define USBTRACE2(s,r) (Notify(PSTR(s), 0x80), D_PrintHex((r), 0x80), Notify(PSTR("\r\n"), 0x80))
+#define USBTRACE3(s,r,l) (Notify(PSTR(s), l), D_PrintHex((r), l), Notify(PSTR("\r\n"), l))
+
+
+#endif /* MACROS_H */
+
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/masstorage.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/masstorage.cpp
new file mode 100644
index 000000000..9299f71a4
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/masstorage.cpp
@@ -0,0 +1,1266 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+
+#include "masstorage.h"
+
+const uint8_t BulkOnly::epDataInIndex = 1;
+const uint8_t BulkOnly::epDataOutIndex = 2;
+const uint8_t BulkOnly::epInterruptInIndex = 3;
+
+////////////////////////////////////////////////////////////////////////////////
+
+// Interface code
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Get the capacity of the media
+ *
+ * @param lun Logical Unit Number
+ * @return media capacity
+ */
+uint32_t BulkOnly::GetCapacity(uint8_t lun) {
+ if(LUNOk[lun])
+ return CurrentCapacity[lun];
+ return 0LU;
+}
+
+/**
+ * Get the sector (block) size used on the media
+ *
+ * @param lun Logical Unit Number
+ * @return media sector size
+ */
+uint16_t BulkOnly::GetSectorSize(uint8_t lun) {
+ if(LUNOk[lun])
+ return CurrentSectorSize[lun];
+ return 0U;
+}
+
+/**
+ * Test if LUN is ready for use
+ *
+ * @param lun Logical Unit Number
+ * @return true if LUN is ready for use
+ */
+bool BulkOnly::LUNIsGood(uint8_t lun) {
+ return LUNOk[lun];
+}
+
+/**
+ * Test if LUN is write protected
+ *
+ * @param lun Logical Unit Number
+ * @return cached status of write protect switch
+ */
+bool BulkOnly::WriteProtected(uint8_t lun) {
+ return WriteOk[lun];
+}
+
+/**
+ * Wrap and execute a SCSI CDB with length of 6
+ *
+ * @param cdb CDB to execute
+ * @param buf_size Size of expected transaction
+ * @param buf Buffer
+ * @param dir MASS_CMD_DIR_IN | MASS_CMD_DIR_OUT
+ * @return
+ */
+uint8_t BulkOnly::SCSITransaction6(CDB6_t *cdb, uint16_t buf_size, void *buf, uint8_t dir) {
+ // promote buf_size to 32bits.
+ CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)buf_size, cdb, dir);
+ //SetCurLUN(cdb->LUN);
+ return (HandleSCSIError(Transaction(&cbw, buf_size, buf)));
+}
+
+/**
+ * Wrap and execute a SCSI CDB with length of 10
+ *
+ * @param cdb CDB to execute
+ * @param buf_size Size of expected transaction
+ * @param buf Buffer
+ * @param dir MASS_CMD_DIR_IN | MASS_CMD_DIR_OUT
+ * @return
+ */
+uint8_t BulkOnly::SCSITransaction10(CDB10_t *cdb, uint16_t buf_size, void *buf, uint8_t dir) {
+ // promote buf_size to 32bits.
+ CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)buf_size, cdb, dir);
+ //SetCurLUN(cdb->LUN);
+ return (HandleSCSIError(Transaction(&cbw, buf_size, buf)));
+}
+
+/**
+ * Lock or Unlock the tray or door on device.
+ * Caution: Some devices with buggy firmware will lock up.
+ *
+ * @param lun Logical Unit Number
+ * @param lock 1 to lock, 0 to unlock
+ * @return
+ */
+uint8_t BulkOnly::LockMedia(uint8_t lun, uint8_t lock) {
+ Notify(PSTR("\r\nLockMedia\r\n"), 0x80);
+ Notify(PSTR("---------\r\n"), 0x80);
+
+ CDB6_t cdb = CDB6_t(SCSI_CMD_PREVENT_REMOVAL, lun, (uint8_t)0, lock);
+ return SCSITransaction6(&cdb, (uint16_t)0, NULL, (uint8_t)MASS_CMD_DIR_IN);
+}
+
+/**
+ * Media control, for spindle motor and media tray or door.
+ * This includes CDROM, TAPE and anything with a media loader.
+ *
+ * @param lun Logical Unit Number
+ * @param ctl 0x00 Stop Motor, 0x01 Start Motor, 0x02 Eject Media, 0x03 Load Media
+ * @return 0 on success
+ */
+uint8_t BulkOnly::MediaCTL(uint8_t lun, uint8_t ctl) {
+ Notify(PSTR("\r\nMediaCTL\r\n"), 0x80);
+ Notify(PSTR("-----------------\r\n"), 0x80);
+
+ uint8_t rcode = MASS_ERR_UNIT_NOT_READY;
+ if(bAddress) {
+ CDB6_t cdb = CDB6_t(SCSI_CMD_START_STOP_UNIT, lun, ctl & 0x03, 0);
+ rcode = SCSITransaction6(&cdb, (uint16_t)0, NULL, (uint8_t)MASS_CMD_DIR_OUT);
+ } else {
+ SetCurLUN(lun);
+ }
+ return rcode;
+}
+
+/**
+ * Read data from media
+ *
+ * @param lun Logical Unit Number
+ * @param addr LBA address on media to read
+ * @param bsize size of a block (we should probably use the cached size)
+ * @param blocks how many blocks to read
+ * @param buf memory that is able to hold the requested data
+ * @return 0 on success
+ */
+uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf) {
+ if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
+ Notify(PSTR("\r\nRead LUN:\t"), 0x80);
+ D_PrintHex<uint8_t > (lun, 0x90);
+ Notify(PSTR("\r\nLBA:\t\t"), 0x90);
+ D_PrintHex<uint32_t > (addr, 0x90);
+ Notify(PSTR("\r\nblocks:\t\t"), 0x90);
+ D_PrintHex<uint8_t > (blocks, 0x90);
+ Notify(PSTR("\r\nblock size:\t"), 0x90);
+ D_PrintHex<uint16_t > (bsize, 0x90);
+ Notify(PSTR("\r\n---------\r\n"), 0x80);
+ CDB10_t cdb = CDB10_t(SCSI_CMD_READ_10, lun, blocks, addr);
+
+again:
+ uint8_t er = SCSITransaction10(&cdb, ((uint16_t)bsize * blocks), buf, (uint8_t)MASS_CMD_DIR_IN);
+
+ if(er == MASS_ERR_STALL) {
+ MediaCTL(lun, 1);
+ delay(150);
+ if(!TestUnitReady(lun)) goto again;
+ }
+ return er;
+}
+
+/**
+ * Write data to media
+ *
+ * @param lun Logical Unit Number
+ * @param addr LBA address on media to write
+ * @param bsize size of a block (we should probably use the cached size)
+ * @param blocks how many blocks to write
+ * @param buf memory that contains the data to write
+ * @return 0 on success
+ */
+uint8_t BulkOnly::Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t * buf) {
+ if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
+ if(!WriteOk[lun]) return MASS_ERR_WRITE_PROTECTED;
+ Notify(PSTR("\r\nWrite LUN:\t"), 0x80);
+ D_PrintHex<uint8_t > (lun, 0x90);
+ Notify(PSTR("\r\nLBA:\t\t"), 0x90);
+ D_PrintHex<uint32_t > (addr, 0x90);
+ Notify(PSTR("\r\nblocks:\t\t"), 0x90);
+ D_PrintHex<uint8_t > (blocks, 0x90);
+ Notify(PSTR("\r\nblock size:\t"), 0x90);
+ D_PrintHex<uint16_t > (bsize, 0x90);
+ Notify(PSTR("\r\n---------\r\n"), 0x80);
+ CDB10_t cdb = CDB10_t(SCSI_CMD_WRITE_10, lun, blocks, addr);
+
+again:
+ uint8_t er = SCSITransaction10(&cdb, ((uint16_t)bsize * blocks), (void*)buf, (uint8_t)MASS_CMD_DIR_OUT);
+
+ if(er == MASS_ERR_WRITE_STALL) {
+ MediaCTL(lun, 1);
+ delay(150);
+ if(!TestUnitReady(lun)) goto again;
+ }
+ return er;
+}
+
+// End of user functions, the remaining code below is driver internals.
+// Only developer serviceable parts below!
+
+////////////////////////////////////////////////////////////////////////////////
+
+// Main driver code
+
+////////////////////////////////////////////////////////////////////////////////
+
+BulkOnly::BulkOnly(USB *p) :
+pUsb(p),
+bAddress(0),
+bIface(0),
+bNumEP(1),
+qNextPollTime(0),
+bPollEnable(false),
+//dCBWTag(0),
+bLastUsbError(0) {
+ ClearAllEP();
+ dCBWTag = 0;
+ if(pUsb)
+ pUsb->RegisterDeviceClass(this);
+}
+
+/**
+ * USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET == success
+ * We need to standardize either the rcode, or change the API to return values
+ * so a signal that additional actions are required can be produced.
+ * Some of these codes do exist already.
+ *
+ * TECHNICAL: We could do most of this code elsewhere, with the exception of checking the class instance.
+ * Doing so would save some program memory when using multiple drivers.
+ *
+ * @param parent USB address of parent
+ * @param port address of port on parent
+ * @param lowspeed true if device is low speed
+ * @return
+ */
+uint8_t BulkOnly::ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed) {
+
+ const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
+
+ uint8_t buf[constBufSize];
+ USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
+ uint8_t rcode;
+ UsbDevice *p = NULL;
+ EpInfo *oldep_ptr = NULL;
+ USBTRACE("MS ConfigureDevice\r\n");
+ ClearAllEP();
+ AddressPool &addrPool = pUsb->GetAddressPool();
+
+
+ if(bAddress)
+ return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
+
+ // <TECHNICAL>
+ // Get pointer to pseudo device with address 0 assigned
+ p = addrPool.GetUsbDevicePtr(0);
+ if(!p) {
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+ }
+
+ if(!p->epinfo) {
+ USBTRACE("epinfo\r\n");
+ return USB_ERROR_EPINFO_IS_NULL;
+ }
+
+ // Save old pointer to EP_RECORD of address 0
+ oldep_ptr = p->epinfo;
+
+ // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
+ p->epinfo = epInfo;
+
+ p->lowspeed = lowspeed;
+ // Get device descriptor
+ rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf);
+
+ // Restore p->epinfo
+ p->epinfo = oldep_ptr;
+
+ if(rcode) {
+ goto FailGetDevDescr;
+ }
+ // Allocate new address according to device class
+ bAddress = addrPool.AllocAddress(parent, false, port);
+
+ if(!bAddress)
+ return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
+
+ // Extract Max Packet Size from the device descriptor
+ epInfo[0].maxPktSize = udd->bMaxPacketSize0;
+ // Steal and abuse from epInfo structure to save on memory.
+ epInfo[1].epAddr = udd->bNumConfigurations;
+ // </TECHNICAL>
+ return USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET;
+
+FailGetDevDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailGetDevDescr(rcode);
+#endif
+ rcode = USB_ERROR_FailGetDevDescr;
+
+ Release();
+ return rcode;
+};
+
+/**
+ *
+ * @param parent (not used)
+ * @param port (not used)
+ * @param lowspeed true if device is low speed
+ * @return 0 for success
+ */
+uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) {
+ uint8_t rcode;
+ uint8_t num_of_conf = epInfo[1].epAddr; // number of configurations
+ epInfo[1].epAddr = 0;
+ USBTRACE("MS Init\r\n");
+
+ AddressPool &addrPool = pUsb->GetAddressPool();
+ UsbDevice *p = addrPool.GetUsbDevicePtr(bAddress);
+
+ if(!p)
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+ // Assign new address to the device
+ delay(2000);
+ rcode = pUsb->setAddr(0, 0, bAddress);
+
+ if(rcode) {
+ p->lowspeed = false;
+ addrPool.FreeAddress(bAddress);
+ bAddress = 0;
+ USBTRACE2("setAddr:", rcode);
+ return rcode;
+ }
+
+ USBTRACE2("Addr:", bAddress);
+
+ p->lowspeed = false;
+
+ p = addrPool.GetUsbDevicePtr(bAddress);
+
+ if(!p)
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+ p->lowspeed = lowspeed;
+
+ // Assign epInfo to epinfo pointer
+ rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
+
+ if(rcode)
+ goto FailSetDevTblEntry;
+
+ USBTRACE2("NC:", num_of_conf);
+
+ for(uint8_t i = 0; i < num_of_conf; i++) {
+ ConfigDescParser< USB_CLASS_MASS_STORAGE,
+ MASS_SUBCLASS_SCSI,
+ MASS_PROTO_BBB,
+ CP_MASK_COMPARE_CLASS |
+ CP_MASK_COMPARE_SUBCLASS |
+ CP_MASK_COMPARE_PROTOCOL > BulkOnlyParser(this);
+
+ rcode = pUsb->getConfDescr(bAddress, 0, i, &BulkOnlyParser);
+
+ if(rcode)
+ goto FailGetConfDescr;
+
+ if(bNumEP > 1)
+ break;
+ }
+
+ if(bNumEP < 3)
+ return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
+
+ // Assign epInfo to epinfo pointer
+ pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
+
+ USBTRACE2("Conf:", bConfNum);
+
+ // Set Configuration Value
+ rcode = pUsb->setConf(bAddress, 0, bConfNum);
+
+ if(rcode)
+ goto FailSetConfDescr;
+
+ //Linux does a 1sec delay after this.
+ delay(1000);
+
+ rcode = GetMaxLUN(&bMaxLUN);
+ if(rcode)
+ goto FailGetMaxLUN;
+
+ if(bMaxLUN >= MASS_MAX_SUPPORTED_LUN) bMaxLUN = MASS_MAX_SUPPORTED_LUN - 1;
+ ErrorMessage<uint8_t > (PSTR("MaxLUN"), bMaxLUN);
+
+ delay(1000); // Delay a bit for slow firmware.
+
+ for(uint8_t lun = 0; lun <= bMaxLUN; lun++) {
+ InquiryResponse response;
+ rcode = Inquiry(lun, sizeof (InquiryResponse), (uint8_t*) & response);
+ if(rcode) {
+ ErrorMessage<uint8_t > (PSTR("Inquiry"), rcode);
+ } else {
+#if 0
+ printf("LUN %i `", lun);
+ uint8_t *buf = response.VendorID;
+ for(int i = 0; i < 28; i++) printf("%c", buf[i]);
+ printf("'\r\nQualifier %1.1X ", response.PeripheralQualifier);
+ printf("Device type %2.2X ", response.DeviceType);
+ printf("RMB %1.1X ", response.Removable);
+ printf("SSCS %1.1X ", response.SCCS);
+ uint8_t sv = response.Version;
+ printf("SCSI version %2.2X\r\nDevice conforms to ", sv);
+ switch(sv) {
+ case 0:
+ printf("No specific");
+ break;
+ case 1:
+ printf("ANSI X3.131-1986 (ANSI 1)");
+ break;
+ case 2:
+ printf("ANSI X3.131-1994 (ANSI 2)");
+ break;
+ case 3:
+ printf("ANSI INCITS 301-1997 (SPC)");
+ break;
+ case 4:
+ printf("ANSI INCITS 351-2001 (SPC-2)");
+ break;
+ case 5:
+ printf("ANSI INCITS 408-2005 (SPC-4)");
+ break;
+ case 6:
+ printf("T10/1731-D (SPC-4)");
+ break;
+ default:
+ printf("unknown");
+ }
+ printf(" standards.\r\n");
+#endif
+ uint8_t tries = 0xf0;
+ while((rcode = TestUnitReady(lun))) {
+ if(rcode == 0x08) break; // break on no media, this is OK to do.
+ // try to lock media and spin up
+ if(tries < 14) {
+ LockMedia(lun, 1);
+ MediaCTL(lun, 1); // I actually have a USB stick that needs this!
+ } else delay(2 * (tries + 1));
+ tries++;
+ if(!tries) break;
+ }
+ if(!rcode) {
+ delay(1000);
+ LUNOk[lun] = CheckLUN(lun);
+ if(!LUNOk[lun]) LUNOk[lun] = CheckLUN(lun);
+ }
+ }
+ }
+
+
+ CheckMedia();
+
+ rcode = OnInit();
+
+ if(rcode)
+ goto FailOnInit;
+
+#ifdef DEBUG_USB_HOST
+ USBTRACE("MS configured\r\n\r\n");
+#endif
+
+ bPollEnable = true;
+
+ //USBTRACE("Poll enabled\r\n");
+ return 0;
+
+FailSetConfDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailSetConfDescr();
+ goto Fail;
+#endif
+
+FailOnInit:
+#ifdef DEBUG_USB_HOST
+ USBTRACE("OnInit:");
+ goto Fail;
+#endif
+
+FailGetMaxLUN:
+#ifdef DEBUG_USB_HOST
+ USBTRACE("GetMaxLUN:");
+ goto Fail;
+#endif
+
+ //#ifdef DEBUG_USB_HOST
+ //FailInvalidSectorSize:
+ // USBTRACE("Sector Size is NOT VALID: ");
+ // goto Fail;
+ //#endif
+
+FailSetDevTblEntry:
+#ifdef DEBUG_USB_HOST
+ NotifyFailSetDevTblEntry();
+ goto Fail;
+#endif
+
+FailGetConfDescr:
+#ifdef DEBUG_USB_HOST
+ NotifyFailGetConfDescr();
+#endif
+
+#ifdef DEBUG_USB_HOST
+Fail:
+ NotifyFail(rcode);
+#endif
+ Release();
+ return rcode;
+}
+
+/**
+ * For driver use only.
+ *
+ * @param conf
+ * @param iface
+ * @param alt
+ * @param proto
+ * @param pep
+ */
+void BulkOnly::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR * pep) {
+ ErrorMessage<uint8_t > (PSTR("Conf.Val"), conf);
+ ErrorMessage<uint8_t > (PSTR("Iface Num"), iface);
+ ErrorMessage<uint8_t > (PSTR("Alt.Set"), alt);
+
+ bConfNum = conf;
+
+ uint8_t index;
+
+#if 1
+ if((pep->bmAttributes & 0x02) == 2) {
+ index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
+ // Fill in the endpoint info structure
+ epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
+ epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
+ epInfo[index].epAttribs = 0;
+
+ bNumEP++;
+
+ PrintEndpointDescriptor(pep);
+
+ }
+#else
+ if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80)
+ index = epInterruptInIndex;
+ else
+ if((pep->bmAttributes & 0x02) == 2)
+ index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
+ else
+ return;
+
+ // Fill in the endpoint info structure
+ epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
+ epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
+ epInfo[index].epAttribs = 0;
+
+ bNumEP++;
+
+ PrintEndpointDescriptor(pep);
+#endif
+}
+
+/**
+ * For driver use only.
+ *
+ * @return
+ */
+uint8_t BulkOnly::Release() {
+ ClearAllEP();
+ pUsb->GetAddressPool().FreeAddress(bAddress);
+ return 0;
+}
+
+/**
+ * For driver use only.
+ *
+ * @param lun Logical Unit Number
+ * @return true if LUN is ready for use.
+ */
+bool BulkOnly::CheckLUN(uint8_t lun) {
+ uint8_t rcode;
+ Capacity capacity;
+ for(uint8_t i = 0; i < 8; i++) capacity.data[i] = 0;
+
+ rcode = ReadCapacity10(lun, (uint8_t*)capacity.data);
+ if(rcode) {
+ //printf(">>>>>>>>>>>>>>>>ReadCapacity returned %i\r\n", rcode);
+ return false;
+ }
+ ErrorMessage<uint8_t > (PSTR(">>>>>>>>>>>>>>>>CAPACITY OK ON LUN"), lun);
+ for(uint8_t i = 0; i < 8 /*sizeof (Capacity)*/; i++)
+ D_PrintHex<uint8_t > (capacity.data[i], 0x80);
+ Notify(PSTR("\r\n\r\n"), 0x80);
+ // Only 512/1024/2048/4096 are valid values!
+ uint32_t c = BMAKE32(capacity.data[4], capacity.data[5], capacity.data[6], capacity.data[7]);
+ if(c != 0x0200LU && c != 0x0400LU && c != 0x0800LU && c != 0x1000LU) {
+ return false;
+ }
+ // Store capacity information.
+ CurrentSectorSize[lun] = (uint16_t)(c); // & 0xFFFF);
+
+ CurrentCapacity[lun] = BMAKE32(capacity.data[0], capacity.data[1], capacity.data[2], capacity.data[3]) + 1;
+ if(CurrentCapacity[lun] == /*0xffffffffLU */ 0x01LU || CurrentCapacity[lun] == 0x00LU) {
+ // Buggy firmware will report 0xffffffff or 0 for no media
+ if(CurrentCapacity[lun])
+ ErrorMessage<uint8_t > (PSTR(">>>>>>>>>>>>>>>>BUGGY FIRMWARE. CAPACITY FAIL ON LUN"), lun);
+ return false;
+ }
+ delay(20);
+ Page3F(lun);
+ if(!TestUnitReady(lun)) return true;
+ return false;
+}
+
+/**
+ * For driver use only.
+ *
+ * Scan for media change on all LUNs
+ */
+void BulkOnly::CheckMedia() {
+ for(uint8_t lun = 0; lun <= bMaxLUN; lun++) {
+ if(TestUnitReady(lun)) {
+ LUNOk[lun] = false;
+ continue;
+ }
+ if(!LUNOk[lun])
+ LUNOk[lun] = CheckLUN(lun);
+ }
+#if 0
+ printf("}}}}}}}}}}}}}}}}STATUS ");
+ for(uint8_t lun = 0; lun <= bMaxLUN; lun++) {
+ if(LUNOk[lun])
+ printf("#");
+ else printf(".");
+ }
+ printf("\r\n");
+#endif
+ qNextPollTime = millis() + 2000;
+}
+
+/**
+ * For driver use only.
+ *
+ * @return
+ */
+uint8_t BulkOnly::Poll() {
+ //uint8_t rcode = 0;
+
+ if(!bPollEnable)
+ return 0;
+
+ if((long)(millis() - qNextPollTime) >= 0L) {
+ CheckMedia();
+ }
+ //rcode = 0;
+
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+
+// SCSI code
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * For driver use only.
+ *
+ * @param plun
+ * @return
+ */
+uint8_t BulkOnly::GetMaxLUN(uint8_t *plun) {
+ uint8_t ret = pUsb->ctrlReq(bAddress, 0, bmREQ_MASSIN, MASS_REQ_GET_MAX_LUN, 0, 0, bIface, 1, 1, plun, NULL);
+
+ if(ret == hrSTALL)
+ *plun = 0;
+
+ return 0;
+}
+
+/**
+ * For driver use only. Used during Driver Init
+ *
+ * @param lun Logical Unit Number
+ * @param bsize
+ * @param buf
+ * @return
+ */
+uint8_t BulkOnly::Inquiry(uint8_t lun, uint16_t bsize, uint8_t *buf) {
+ Notify(PSTR("\r\nInquiry\r\n"), 0x80);
+ Notify(PSTR("---------\r\n"), 0x80);
+
+ CDB6_t cdb = CDB6_t(SCSI_CMD_INQUIRY, lun, 0LU, (uint8_t)bsize, 0);
+ uint8_t rc = SCSITransaction6(&cdb, bsize, buf, (uint8_t)MASS_CMD_DIR_IN);
+
+ return rc;
+}
+
+/**
+ * For driver use only.
+ *
+ * @param lun Logical Unit Number
+ * @return
+ */
+uint8_t BulkOnly::TestUnitReady(uint8_t lun) {
+ //SetCurLUN(lun);
+ if(!bAddress)
+ return MASS_ERR_UNIT_NOT_READY;
+
+ Notify(PSTR("\r\nTestUnitReady\r\n"), 0x80);
+ Notify(PSTR("-----------------\r\n"), 0x80);
+
+ CDB6_t cdb = CDB6_t(SCSI_CMD_TEST_UNIT_READY, lun, (uint8_t)0, 0);
+ return SCSITransaction6(&cdb, 0, NULL, (uint8_t)MASS_CMD_DIR_IN);
+
+}
+
+/**
+ * For driver use only.
+ *
+ * @param lun Logical Unit Number
+ * @param pc
+ * @param page
+ * @param subpage
+ * @param len
+ * @param pbuf
+ * @return
+ */
+uint8_t BulkOnly::ModeSense6(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t * pbuf) {
+ Notify(PSTR("\r\rModeSense\r\n"), 0x80);
+ Notify(PSTR("------------\r\n"), 0x80);
+
+ CDB6_t cdb = CDB6_t(SCSI_CMD_TEST_UNIT_READY, lun, (uint32_t)((((pc << 6) | page) << 8) | subpage), len, 0);
+ return SCSITransaction6(&cdb, len, pbuf, (uint8_t)MASS_CMD_DIR_IN);
+}
+
+/**
+ * For driver use only.
+ *
+ * @param lun Logical Unit Number
+ * @param bsize
+ * @param buf
+ * @return
+ */
+uint8_t BulkOnly::ReadCapacity10(uint8_t lun, uint8_t *buf) {
+ Notify(PSTR("\r\nReadCapacity\r\n"), 0x80);
+ Notify(PSTR("---------------\r\n"), 0x80);
+
+ CDB10_t cdb = CDB10_t(SCSI_CMD_READ_CAPACITY_10, lun);
+ return SCSITransaction10(&cdb, 8, buf, (uint8_t)MASS_CMD_DIR_IN);
+}
+
+/**
+ * For driver use only.
+ *
+ * Page 3F contains write protect status.
+ *
+ * @param lun Logical Unit Number to test.
+ * @return Write protect switch status.
+ */
+uint8_t BulkOnly::Page3F(uint8_t lun) {
+ uint8_t buf[192];
+ for(int i = 0; i < 192; i++) {
+ buf[i] = 0x00;
+ }
+ WriteOk[lun] = true;
+ uint8_t rc = ModeSense6(lun, 0, 0x3f, 0, 192, buf);
+ if(!rc) {
+ WriteOk[lun] = ((buf[2] & 0x80) == 0);
+ Notify(PSTR("Mode Sense: "), 0x80);
+ for(int i = 0; i < 4; i++) {
+ D_PrintHex<uint8_t > (buf[i], 0x80);
+ Notify(PSTR(" "), 0x80);
+ }
+ Notify(PSTR("\r\n"), 0x80);
+ }
+ return rc;
+}
+
+/**
+ * For driver use only.
+ *
+ * @param lun Logical Unit Number
+ * @param size
+ * @param buf
+ * @return
+ */
+uint8_t BulkOnly::RequestSense(uint8_t lun, uint16_t size, uint8_t *buf) {
+ Notify(PSTR("\r\nRequestSense\r\n"), 0x80);
+ Notify(PSTR("----------------\r\n"), 0x80);
+
+ CDB6_t cdb = CDB6_t(SCSI_CMD_REQUEST_SENSE, lun, 0LU, (uint8_t)size, 0);
+ CommandBlockWrapper cbw = CommandBlockWrapper(++dCBWTag, (uint32_t)size, &cdb, (uint8_t)MASS_CMD_DIR_IN);
+ //SetCurLUN(lun);
+ return Transaction(&cbw, size, buf);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+
+// USB code
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * For driver use only.
+ *
+ * @param index
+ * @return
+ */
+uint8_t BulkOnly::ClearEpHalt(uint8_t index) {
+ if(index == 0)
+ return 0;
+
+ uint8_t ret = 0;
+
+ while((ret = (pUsb->ctrlReq(bAddress, 0, USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_STANDARD | USB_SETUP_RECIPIENT_ENDPOINT, USB_REQUEST_CLEAR_FEATURE, USB_FEATURE_ENDPOINT_HALT, 0, ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr), 0, 0, NULL, NULL)) == 0x01))
+ delay(6);
+
+ if(ret) {
+ ErrorMessage<uint8_t > (PSTR("ClearEpHalt"), ret);
+ ErrorMessage<uint8_t > (PSTR("EP"), ((index == epDataInIndex) ? (0x80 | epInfo[index].epAddr) : epInfo[index].epAddr));
+ return ret;
+ }
+ epInfo[index].bmSndToggle = 0;
+ epInfo[index].bmRcvToggle = 0;
+ // epAttribs = 0;
+ return 0;
+}
+
+/**
+ * For driver use only.
+ *
+ */
+void BulkOnly::Reset() {
+ while(pUsb->ctrlReq(bAddress, 0, bmREQ_MASSOUT, MASS_REQ_BOMSR, 0, 0, bIface, 0, 0, NULL, NULL) == 0x01) delay(6);
+}
+
+/**
+ * For driver use only.
+ *
+ * @return 0 if successful
+ */
+uint8_t BulkOnly::ResetRecovery() {
+ Notify(PSTR("\r\nResetRecovery\r\n"), 0x80);
+ Notify(PSTR("-----------------\r\n"), 0x80);
+
+ delay(6);
+ Reset();
+ delay(6);
+ ClearEpHalt(epDataInIndex);
+ delay(6);
+ bLastUsbError = ClearEpHalt(epDataOutIndex);
+ delay(6);
+ return bLastUsbError;
+}
+
+/**
+ * For driver use only.
+ *
+ * Clear all EP data and clear all LUN status
+ */
+void BulkOnly::ClearAllEP() {
+ for(uint8_t i = 0; i < MASS_MAX_ENDPOINTS; i++) {
+ epInfo[i].epAddr = 0;
+ epInfo[i].maxPktSize = (i) ? 0 : 8;
+ epInfo[i].epAttribs = 0;
+
+ epInfo[i].bmNakPower = USB_NAK_DEFAULT;
+ }
+
+ for(uint8_t i = 0; i < MASS_MAX_SUPPORTED_LUN; i++) {
+ LUNOk[i] = false;
+ WriteOk[i] = false;
+ CurrentCapacity[i] = 0lu;
+ CurrentSectorSize[i] = 0;
+ }
+
+ bIface = 0;
+ bNumEP = 1;
+ bAddress = 0;
+ qNextPollTime = 0;
+ bPollEnable = false;
+ bLastUsbError = 0;
+ bMaxLUN = 0;
+ bTheLUN = 0;
+}
+
+/**
+ * For driver use only.
+ *
+ * @param pcsw
+ * @param pcbw
+ * @return
+ */
+bool BulkOnly::IsValidCSW(CommandStatusWrapper *pcsw, CommandBlockWrapperBase *pcbw) {
+ if(pcsw->dCSWSignature != MASS_CSW_SIGNATURE) {
+ Notify(PSTR("CSW:Sig error\r\n"), 0x80);
+ return false;
+ }
+ if(pcsw->dCSWTag != pcbw->dCBWTag) {
+ Notify(PSTR("CSW:Wrong tag\r\n"), 0x80);
+ return false;
+ }
+ return true;
+}
+
+/**
+ * For driver use only.
+ *
+ * @param error
+ * @param index
+ * @return
+ */
+uint8_t BulkOnly::HandleUsbError(uint8_t error, uint8_t index) {
+ uint8_t count = 3;
+
+ bLastUsbError = error;
+ //if (error)
+ //ClearEpHalt(index);
+ while(error && count) {
+ if(error != hrSUCCESS) {
+ ErrorMessage<uint8_t > (PSTR("USB Error"), error);
+ ErrorMessage<uint8_t > (PSTR("Index"), index);
+ }
+ switch(error) {
+ // case hrWRONGPID:
+ case hrSUCCESS:
+ return MASS_ERR_SUCCESS;
+ case hrBUSY:
+ // SIE is busy, just hang out and try again.
+ return MASS_ERR_UNIT_BUSY;
+ case hrTIMEOUT:
+ case hrJERR: return MASS_ERR_DEVICE_DISCONNECTED;
+ case hrSTALL:
+ if(index == 0)
+ return MASS_ERR_STALL;
+ ClearEpHalt(index);
+ if(index != epDataInIndex)
+ return MASS_ERR_WRITE_STALL;
+ return MASS_ERR_STALL;
+
+ case hrNAK:
+ if(index == 0)
+ return MASS_ERR_UNIT_BUSY;
+ return MASS_ERR_UNIT_BUSY;
+
+ case hrTOGERR:
+ // Handle a very super rare corner case, where toggles become de-synched.
+ // I have only ran into one device that has this firmware bug, and this is
+ // the only clean way to get back into sync with the buggy device firmware.
+ // --AJK
+ if(bAddress && bConfNum) {
+ error = pUsb->setConf(bAddress, 0, bConfNum);
+
+ if(error)
+ break;
+ }
+ return MASS_ERR_SUCCESS;
+ default:
+ ErrorMessage<uint8_t > (PSTR("\r\nUSB"), error);
+ return MASS_ERR_GENERAL_USB_ERROR;
+ }
+ count--;
+ } // while
+
+ return ((error && !count) ? MASS_ERR_GENERAL_USB_ERROR : MASS_ERR_SUCCESS);
+}
+
+#if MS_WANT_PARSER
+
+uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf) {
+ return Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf, 0);
+}
+#endif
+
+/**
+ * For driver use only.
+ *
+ * @param pcbw
+ * @param buf_size
+ * @param buf
+ * @param flags
+ * @return
+ */
+uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void *buf
+#if MS_WANT_PARSER
+ , uint8_t flags
+#endif
+ ) {
+
+#if MS_WANT_PARSER
+ uint16_t bytes = (pcbw->dCBWDataTransferLength > buf_size) ? buf_size : pcbw->dCBWDataTransferLength;
+ printf("Transfersize %i\r\n", bytes);
+ delay(1000);
+
+ bool callback = (flags & MASS_TRANS_FLG_CALLBACK) == MASS_TRANS_FLG_CALLBACK;
+#else
+ uint16_t bytes = buf_size;
+#endif
+ bool write = (pcbw->bmCBWFlags & MASS_CMD_DIR_IN) != MASS_CMD_DIR_IN;
+ uint8_t ret = 0;
+ uint8_t usberr;
+ CommandStatusWrapper csw; // up here, we allocate ahead to save cpu cycles.
+ SetCurLUN(pcbw->bmCBWLUN);
+ ErrorMessage<uint32_t > (PSTR("CBW.dCBWTag"), pcbw->dCBWTag);
+
+ while((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw)) == hrBUSY) delay(1);
+
+ ret = HandleUsbError(usberr, epDataOutIndex);
+ //ret = HandleUsbError(pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw), epDataOutIndex);
+ if(ret) {
+ ErrorMessage<uint8_t > (PSTR("============================ CBW"), ret);
+ } else {
+ if(bytes) {
+ if(!write) {
+#if MS_WANT_PARSER
+ if(callback) {
+ uint8_t rbuf[bytes];
+ while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, rbuf)) == hrBUSY) delay(1);
+ if(usberr == hrSUCCESS) ((USBReadParser*)buf)->Parse(bytes, rbuf, 0);
+ } else {
+#endif
+ while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*)buf)) == hrBUSY) delay(1);
+#if MS_WANT_PARSER
+
+ }
+#endif
+ ret = HandleUsbError(usberr, epDataInIndex);
+ } else {
+ while((usberr = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, bytes, (uint8_t*)buf)) == hrBUSY) delay(1);
+ ret = HandleUsbError(usberr, epDataOutIndex);
+ }
+ if(ret) {
+ ErrorMessage<uint8_t > (PSTR("============================ DAT"), ret);
+ }
+ }
+ }
+
+ {
+ bytes = sizeof (CommandStatusWrapper);
+ int tries = 2;
+ while(tries--) {
+ while((usberr = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &bytes, (uint8_t*) & csw)) == hrBUSY) delay(1);
+ if(!usberr) break;
+ ClearEpHalt(epDataInIndex);
+ if(tries) ResetRecovery();
+ }
+ if(!ret) {
+ Notify(PSTR("CBW:\t\tOK\r\n"), 0x80);
+ Notify(PSTR("Data Stage:\tOK\r\n"), 0x80);
+ } else {
+ // Throw away csw, IT IS NOT OF ANY USE.
+ ResetRecovery();
+ return ret;
+ }
+ ret = HandleUsbError(usberr, epDataInIndex);
+ if(ret) {
+ ErrorMessage<uint8_t > (PSTR("============================ CSW"), ret);
+ }
+ if(usberr == hrSUCCESS) {
+ if(IsValidCSW(&csw, pcbw)) {
+ //ErrorMessage<uint32_t > (PSTR("CSW.dCBWTag"), csw.dCSWTag);
+ //ErrorMessage<uint8_t > (PSTR("bCSWStatus"), csw.bCSWStatus);
+ //ErrorMessage<uint32_t > (PSTR("dCSWDataResidue"), csw.dCSWDataResidue);
+ Notify(PSTR("CSW:\t\tOK\r\n\r\n"), 0x80);
+ return csw.bCSWStatus;
+ } else {
+ // NOTE! Sometimes this is caused by the reported residue being wrong.
+ // Get a different device. It isn't compliant, and should have never passed Q&A.
+ // I own one... 05e3:0701 Genesys Logic, Inc. USB 2.0 IDE Adapter.
+ // Other devices that exhibit this behavior exist in the wild too.
+ // Be sure to check quirks in the Linux source code before reporting a bug. --xxxajk
+ Notify(PSTR("Invalid CSW\r\n"), 0x80);
+ ResetRecovery();
+ //return MASS_ERR_SUCCESS;
+ return MASS_ERR_INVALID_CSW;
+ }
+ }
+ }
+ return ret;
+}
+
+/**
+ * For driver use only.
+ *
+ * @param lun Logical Unit Number
+ * @return
+ */
+uint8_t BulkOnly::SetCurLUN(uint8_t lun) {
+ if(lun > bMaxLUN)
+ return MASS_ERR_INVALID_LUN;
+ bTheLUN = lun;
+ return MASS_ERR_SUCCESS;
+};
+
+/**
+ * For driver use only.
+ *
+ * @param status
+ * @return
+ */
+uint8_t BulkOnly::HandleSCSIError(uint8_t status) {
+ uint8_t ret = 0;
+
+ switch(status) {
+ case 0: return MASS_ERR_SUCCESS;
+
+ case 2:
+ ErrorMessage<uint8_t > (PSTR("Phase Error"), status);
+ ErrorMessage<uint8_t > (PSTR("LUN"), bTheLUN);
+ ResetRecovery();
+ return MASS_ERR_GENERAL_SCSI_ERROR;
+
+ case 1:
+ ErrorMessage<uint8_t > (PSTR("SCSI Error"), status);
+ ErrorMessage<uint8_t > (PSTR("LUN"), bTheLUN);
+ RequestSenseResponce rsp;
+
+ ret = RequestSense(bTheLUN, sizeof (RequestSenseResponce), (uint8_t*) & rsp);
+
+ if(ret) {
+ return MASS_ERR_GENERAL_SCSI_ERROR;
+ }
+ ErrorMessage<uint8_t > (PSTR("Response Code"), rsp.bResponseCode);
+ if(rsp.bResponseCode & 0x80) {
+ Notify(PSTR("Information field: "), 0x80);
+ for(int i = 0; i < 4; i++) {
+ D_PrintHex<uint8_t > (rsp.CmdSpecificInformation[i], 0x80);
+ Notify(PSTR(" "), 0x80);
+ }
+ Notify(PSTR("\r\n"), 0x80);
+ }
+ ErrorMessage<uint8_t > (PSTR("Sense Key"), rsp.bmSenseKey);
+ ErrorMessage<uint8_t > (PSTR("Add Sense Code"), rsp.bAdditionalSenseCode);
+ ErrorMessage<uint8_t > (PSTR("Add Sense Qual"), rsp.bAdditionalSenseQualifier);
+ // warning, this is not testing ASQ, only SK and ASC.
+ switch(rsp.bmSenseKey) {
+ case SCSI_S_UNIT_ATTENTION:
+ switch(rsp.bAdditionalSenseCode) {
+ case SCSI_ASC_MEDIA_CHANGED:
+ return MASS_ERR_MEDIA_CHANGED;
+ default:
+ return MASS_ERR_UNIT_NOT_READY;
+ }
+ case SCSI_S_NOT_READY:
+ switch(rsp.bAdditionalSenseCode) {
+ case SCSI_ASC_MEDIUM_NOT_PRESENT:
+ return MASS_ERR_NO_MEDIA;
+ default:
+ return MASS_ERR_UNIT_NOT_READY;
+ }
+ case SCSI_S_ILLEGAL_REQUEST:
+ switch(rsp.bAdditionalSenseCode) {
+ case SCSI_ASC_LBA_OUT_OF_RANGE:
+ return MASS_ERR_BAD_LBA;
+ default:
+ return MASS_ERR_CMD_NOT_SUPPORTED;
+ }
+ default:
+ return MASS_ERR_GENERAL_SCSI_ERROR;
+ }
+
+ // case 4: return MASS_ERR_UNIT_BUSY; // Busy means retry later.
+ // case 0x05/0x14: we stalled out
+ // case 0x15/0x16: we naked out.
+ default:
+ ErrorMessage<uint8_t > (PSTR("Gen SCSI Err"), status);
+ ErrorMessage<uint8_t > (PSTR("LUN"), bTheLUN);
+ return status;
+ } // switch
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+
+// Debugging code
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ *
+ * @param ep_ptr
+ */
+void BulkOnly::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR * ep_ptr) {
+ Notify(PSTR("Endpoint descriptor:"), 0x80);
+ Notify(PSTR("\r\nLength:\t\t"), 0x80);
+ D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
+ Notify(PSTR("\r\nType:\t\t"), 0x80);
+ D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
+ Notify(PSTR("\r\nAddress:\t"), 0x80);
+ D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
+ Notify(PSTR("\r\nAttributes:\t"), 0x80);
+ D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
+ Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
+ D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
+ Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
+ D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
+ Notify(PSTR("\r\n"), 0x80);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+
+// misc/to kill/to-do
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+/* We won't be needing this... */
+uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, USBReadParser * prs) {
+#if MS_WANT_PARSER
+ if(!LUNOk[lun]) return MASS_ERR_NO_MEDIA;
+ Notify(PSTR("\r\nRead (With parser)\r\n"), 0x80);
+ Notify(PSTR("---------\r\n"), 0x80);
+
+ CommandBlockWrapper cbw = CommandBlockWrapper();
+
+ cbw.dCBWSignature = MASS_CBW_SIGNATURE;
+ cbw.dCBWTag = ++dCBWTag;
+ cbw.dCBWDataTransferLength = ((uint32_t)bsize * blocks);
+ cbw.bmCBWFlags = MASS_CMD_DIR_IN,
+ cbw.bmCBWLUN = lun;
+ cbw.bmCBWCBLength = 10;
+
+ cbw.CBWCB[0] = SCSI_CMD_READ_10;
+ cbw.CBWCB[8] = blocks;
+ cbw.CBWCB[2] = ((addr >> 24) & 0xff);
+ cbw.CBWCB[3] = ((addr >> 16) & 0xff);
+ cbw.CBWCB[4] = ((addr >> 8) & 0xff);
+ cbw.CBWCB[5] = (addr & 0xff);
+
+ return HandleSCSIError(Transaction(&cbw, bsize, prs, 1));
+#else
+ return MASS_ERR_NOT_IMPLEMENTED;
+#endif
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/masstorage.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/masstorage.h
new file mode 100644
index 000000000..d39fd66f3
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/masstorage.h
@@ -0,0 +1,571 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+
+#if !defined(__MASSTORAGE_H__)
+#define __MASSTORAGE_H__
+
+// Cruft removal, makes driver smaller, faster.
+#ifndef MS_WANT_PARSER
+#define MS_WANT_PARSER 0
+#endif
+
+#include "Usb.h"
+
+#define bmREQ_MASSOUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
+#define bmREQ_MASSIN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE
+
+// Mass Storage Subclass Constants
+#define MASS_SUBCLASS_SCSI_NOT_REPORTED 0x00 // De facto use
+#define MASS_SUBCLASS_RBC 0x01
+#define MASS_SUBCLASS_ATAPI 0x02 // MMC-5 (ATAPI)
+#define MASS_SUBCLASS_OBSOLETE1 0x03 // Was QIC-157
+#define MASS_SUBCLASS_UFI 0x04 // Specifies how to interface Floppy Disk Drives to USB
+#define MASS_SUBCLASS_OBSOLETE2 0x05 // Was SFF-8070i
+#define MASS_SUBCLASS_SCSI 0x06 // SCSI Transparent Command Set
+#define MASS_SUBCLASS_LSDFS 0x07 // Specifies how host has to negotiate access before trying SCSI
+#define MASS_SUBCLASS_IEEE1667 0x08
+
+// Mass Storage Class Protocols
+#define MASS_PROTO_CBI 0x00 // CBI (with command completion interrupt)
+#define MASS_PROTO_CBI_NO_INT 0x01 // CBI (without command completion interrupt)
+#define MASS_PROTO_OBSOLETE 0x02
+#define MASS_PROTO_BBB 0x50 // Bulk Only Transport
+#define MASS_PROTO_UAS 0x62
+
+// Request Codes
+#define MASS_REQ_ADSC 0x00
+#define MASS_REQ_GET 0xFC
+#define MASS_REQ_PUT 0xFD
+#define MASS_REQ_GET_MAX_LUN 0xFE
+#define MASS_REQ_BOMSR 0xFF // Bulk-Only Mass Storage Reset
+
+#define MASS_CBW_SIGNATURE 0x43425355
+#define MASS_CSW_SIGNATURE 0x53425355
+
+#define MASS_CMD_DIR_OUT 0 // (0 << 7)
+#define MASS_CMD_DIR_IN 0x80 //(1 << 7)
+
+/*
+ * Reference documents from T10 (http://www.t10.org)
+ * SCSI Primary Commands - 3 (SPC-3)
+ * SCSI Block Commands - 2 (SBC-2)
+ * Multi-Media Commands - 5 (MMC-5)
+ */
+
+/* Group 1 commands (CDB's here are should all be 6-bytes) */
+#define SCSI_CMD_TEST_UNIT_READY 0x00
+#define SCSI_CMD_REQUEST_SENSE 0x03
+#define SCSI_CMD_FORMAT_UNIT 0x04
+#define SCSI_CMD_READ_6 0x08
+#define SCSI_CMD_WRITE_6 0x0A
+#define SCSI_CMD_INQUIRY 0x12
+#define SCSI_CMD_MODE_SELECT_6 0x15
+#define SCSI_CMD_MODE_SENSE_6 0x1A
+#define SCSI_CMD_START_STOP_UNIT 0x1B
+#define SCSI_CMD_PREVENT_REMOVAL 0x1E
+/* Group 2 Commands (CDB's here are 10-bytes) */
+#define SCSI_CMD_READ_FORMAT_CAPACITIES 0x23
+#define SCSI_CMD_READ_CAPACITY_10 0x25
+#define SCSI_CMD_READ_10 0x28
+#define SCSI_CMD_WRITE_10 0x2A
+#define SCSI_CMD_SEEK_10 0x2B
+#define SCSI_CMD_ERASE_10 0x2C
+#define SCSI_CMD_WRITE_AND_VERIFY_10 0x2E
+#define SCSI_CMD_VERIFY_10 0x2F
+#define SCSI_CMD_SYNCHRONIZE_CACHE 0x35
+#define SCSI_CMD_WRITE_BUFFER 0x3B
+#define SCSI_CMD_READ_BUFFER 0x3C
+#define SCSI_CMD_READ_SUBCHANNEL 0x42
+#define SCSI_CMD_READ_TOC 0x43
+#define SCSI_CMD_READ_HEADER 0x44
+#define SCSI_CMD_PLAY_AUDIO_10 0x45
+#define SCSI_CMD_GET_CONFIGURATION 0x46
+#define SCSI_CMD_PLAY_AUDIO_MSF 0x47
+#define SCSI_CMD_PLAY_AUDIO_TI 0x48
+#define SCSI_CMD_PLAY_TRACK_REL_10 0x49
+#define SCSI_CMD_GET_EVENT_STATUS 0x4A
+#define SCSI_CMD_PAUSE_RESUME 0x4B
+#define SCSI_CMD_READ_DISC_INFORMATION 0x51
+#define SCSI_CMD_READ_TRACK_INFORMATION 0x52
+#define SCSI_CMD_RESERVE_TRACK 0x53
+#define SCSI_CMD_SEND_OPC_INFORMATION 0x54
+#define SCSI_CMD_MODE_SELECT_10 0x55
+#define SCSI_CMD_REPAIR_TRACK 0x58
+#define SCSI_CMD_MODE_SENSE_10 0x5A
+#define SCSI_CMD_CLOSE_TRACK_SESSION 0x5B
+#define SCSI_CMD_READ_BUFFER_CAPACITY 0x5C
+#define SCSI_CMD_SEND_CUE_SHEET 0x5D
+/* Group 5 Commands (CDB's here are 12-bytes) */
+#define SCSI_CMD_REPORT_LUNS 0xA0
+#define SCSI_CMD_BLANK 0xA1
+#define SCSI_CMD_SECURITY_PROTOCOL_IN 0xA2
+#define SCSI_CMD_SEND_KEY 0xA3
+#define SCSI_CMD_REPORT_KEY 0xA4
+#define SCSI_CMD_PLAY_AUDIO_12 0xA5
+#define SCSI_CMD_LOAD_UNLOAD 0xA6
+#define SCSI_CMD_SET_READ_AHEAD 0xA7
+#define SCSI_CMD_READ_12 0xA8
+#define SCSI_CMD_PLAY_TRACK_REL_12 0xA9
+#define SCSI_CMD_WRITE_12 0xAA
+#define SCSI_CMD_READ_MEDIA_SERIAL_12 0xAB
+#define SCSI_CMD_GET_PERFORMANCE 0xAC
+#define SCSI_CMD_READ_DVD_STRUCTURE 0xAD
+#define SCSI_CMD_SECURITY_PROTOCOL_OUT 0xB5
+#define SCSI_CMD_SET_STREAMING 0xB6
+#define SCSI_CMD_READ_MSF 0xB9
+#define SCSI_CMD_SET_SPEED 0xBB
+#define SCSI_CMD_MECHANISM_STATUS 0xBD
+#define SCSI_CMD_READ_CD 0xBE
+#define SCSI_CMD_SEND_DISC_STRUCTURE 0xBF
+/* Vendor-unique Commands, included for completeness */
+#define SCSI_CMD_CD_PLAYBACK_STATUS 0xC4 /* SONY unique */
+#define SCSI_CMD_PLAYBACK_CONTROL 0xC9 /* SONY unique */
+#define SCSI_CMD_READ_CDDA 0xD8 /* Vendor unique */
+#define SCSI_CMD_READ_CDXA 0xDB /* Vendor unique */
+#define SCSI_CMD_READ_ALL_SUBCODES 0xDF /* Vendor unique */
+
+/* SCSI error codes */
+#define SCSI_S_NOT_READY 0x02
+#define SCSI_S_MEDIUM_ERROR 0x03
+#define SCSI_S_ILLEGAL_REQUEST 0x05
+#define SCSI_S_UNIT_ATTENTION 0x06
+#define SCSI_ASC_LBA_OUT_OF_RANGE 0x21
+#define SCSI_ASC_MEDIA_CHANGED 0x28
+#define SCSI_ASC_MEDIUM_NOT_PRESENT 0x3A
+
+/* USB error codes */
+#define MASS_ERR_SUCCESS 0x00
+#define MASS_ERR_PHASE_ERROR 0x02
+#define MASS_ERR_UNIT_NOT_READY 0x03
+#define MASS_ERR_UNIT_BUSY 0x04
+#define MASS_ERR_STALL 0x05
+#define MASS_ERR_CMD_NOT_SUPPORTED 0x06
+#define MASS_ERR_INVALID_CSW 0x07
+#define MASS_ERR_NO_MEDIA 0x08
+#define MASS_ERR_BAD_LBA 0x09
+#define MASS_ERR_MEDIA_CHANGED 0x0A
+#define MASS_ERR_DEVICE_DISCONNECTED 0x11
+#define MASS_ERR_UNABLE_TO_RECOVER 0x12 // Reset recovery error
+#define MASS_ERR_INVALID_LUN 0x13
+#define MASS_ERR_WRITE_STALL 0x14
+#define MASS_ERR_READ_NAKS 0x15
+#define MASS_ERR_WRITE_NAKS 0x16
+#define MASS_ERR_WRITE_PROTECTED 0x17
+#define MASS_ERR_NOT_IMPLEMENTED 0xFD
+#define MASS_ERR_GENERAL_SCSI_ERROR 0xFE
+#define MASS_ERR_GENERAL_USB_ERROR 0xFF
+#define MASS_ERR_USER 0xA0 // For subclasses to define their own error codes
+
+#define MASS_TRANS_FLG_CALLBACK 0x01 // Callback is involved
+#define MASS_TRANS_FLG_NO_STALL_CHECK 0x02 // STALL condition is not checked
+#define MASS_TRANS_FLG_NO_PHASE_CHECK 0x04 // PHASE_ERROR is not checked
+
+#define MASS_MAX_ENDPOINTS 3
+
+struct Capacity {
+ uint8_t data[8];
+ //uint32_t dwBlockAddress;
+ //uint32_t dwBlockLength;
+} __attribute__((packed));
+
+struct BASICCDB {
+ uint8_t Opcode;
+
+ unsigned unused : 5;
+ unsigned LUN : 3;
+
+ uint8_t info[12];
+} __attribute__((packed));
+
+typedef BASICCDB BASICCDB_t;
+
+struct CDB6 {
+ uint8_t Opcode;
+
+ unsigned LBAMSB : 5;
+ unsigned LUN : 3;
+
+ uint8_t LBAHB;
+ uint8_t LBALB;
+ uint8_t AllocationLength;
+ uint8_t Control;
+
+public:
+
+ CDB6(uint8_t _Opcode, uint8_t _LUN, uint32_t LBA, uint8_t _AllocationLength, uint8_t _Control) :
+ Opcode(_Opcode), LBAMSB(BGRAB2(LBA) & 0x1f), LUN(_LUN), LBAHB(BGRAB1(LBA)), LBALB(BGRAB0(LBA)),
+ AllocationLength(_AllocationLength), Control(_Control) {
+ }
+
+ CDB6(uint8_t _Opcode, uint8_t _LUN, uint8_t _AllocationLength, uint8_t _Control) :
+ Opcode(_Opcode), LBAMSB(0), LUN(_LUN), LBAHB(0), LBALB(0),
+ AllocationLength(_AllocationLength), Control(_Control) {
+ }
+} __attribute__((packed));
+
+typedef CDB6 CDB6_t;
+
+struct CDB10 {
+ uint8_t Opcode;
+
+ unsigned Service_Action : 5;
+ unsigned LUN : 3;
+
+ uint8_t LBA_L_M_MB;
+ uint8_t LBA_L_M_LB;
+ uint8_t LBA_L_L_MB;
+ uint8_t LBA_L_L_LB;
+
+ uint8_t Misc2;
+
+ uint8_t ALC_MB;
+ uint8_t ALC_LB;
+
+ uint8_t Control;
+public:
+
+ CDB10(uint8_t _Opcode, uint8_t _LUN) :
+ Opcode(_Opcode), Service_Action(0), LUN(_LUN),
+ LBA_L_M_MB(0), LBA_L_M_LB(0), LBA_L_L_MB(0), LBA_L_L_LB(0),
+ Misc2(0), ALC_MB(0), ALC_LB(0), Control(0) {
+ }
+
+ CDB10(uint8_t _Opcode, uint8_t _LUN, uint16_t xflen, uint32_t _LBA) :
+ Opcode(_Opcode), Service_Action(0), LUN(_LUN),
+ LBA_L_M_MB(BGRAB3(_LBA)), LBA_L_M_LB(BGRAB2(_LBA)), LBA_L_L_MB(BGRAB1(_LBA)), LBA_L_L_LB(BGRAB0(_LBA)),
+ Misc2(0), ALC_MB(BGRAB1(xflen)), ALC_LB(BGRAB0(xflen)), Control(0) {
+ }
+} __attribute__((packed));
+
+typedef CDB10 CDB10_t;
+
+struct CDB12 {
+ uint8_t Opcode;
+
+ unsigned Service_Action : 5;
+ unsigned Misc : 3;
+
+ uint8_t LBA_L_M_LB;
+ uint8_t LBA_L_L_MB;
+ uint8_t LBA_L_L_LB;
+
+ uint8_t ALC_M_LB;
+ uint8_t ALC_L_MB;
+ uint8_t ALC_L_LB;
+ uint8_t Control;
+} __attribute__((packed));
+
+typedef CDB12 CDB12_t;
+
+struct CDB_LBA32_16 {
+ uint8_t Opcode;
+
+ unsigned Service_Action : 5;
+ unsigned Misc : 3;
+
+ uint8_t LBA_L_M_MB;
+ uint8_t LBA_L_M_LB;
+ uint8_t LBA_L_L_MB;
+ uint8_t LBA_L_L_LB;
+
+ uint8_t A_M_M_MB;
+ uint8_t A_M_M_LB;
+ uint8_t A_M_L_MB;
+ uint8_t A_M_L_LB;
+
+ uint8_t ALC_M_MB;
+ uint8_t ALC_M_LB;
+ uint8_t ALC_L_MB;
+ uint8_t ALC_L_LB;
+
+ uint8_t Misc2;
+ uint8_t Control;
+} __attribute__((packed));
+
+struct CDB_LBA64_16 {
+ uint8_t Opcode;
+ uint8_t Misc;
+
+ uint8_t LBA_M_M_MB;
+ uint8_t LBA_M_M_LB;
+ uint8_t LBA_M_L_MB;
+ uint8_t LBA_M_L_LB;
+
+ uint8_t LBA_L_M_MB;
+ uint8_t LBA_L_M_LB;
+ uint8_t LBA_L_L_MB;
+ uint8_t LBA_L_L_LB;
+
+ uint8_t ALC_M_MB;
+ uint8_t ALC_M_LB;
+ uint8_t ALC_L_MB;
+ uint8_t ALC_L_LB;
+
+ uint8_t Misc2;
+ uint8_t Control;
+} __attribute__((packed));
+
+struct InquiryResponse {
+ uint8_t DeviceType : 5;
+ uint8_t PeripheralQualifier : 3;
+
+ unsigned Reserved : 7;
+ unsigned Removable : 1;
+
+ uint8_t Version;
+
+ unsigned ResponseDataFormat : 4;
+ unsigned HISUP : 1;
+ unsigned NormACA : 1;
+ unsigned TrmTsk : 1;
+ unsigned AERC : 1;
+
+ uint8_t AdditionalLength;
+ //uint8_t Reserved3[2];
+
+ unsigned PROTECT : 1;
+ unsigned Res : 2;
+ unsigned ThreePC : 1;
+ unsigned TPGS : 2;
+ unsigned ACC : 1;
+ unsigned SCCS : 1;
+
+ unsigned ADDR16 : 1;
+ unsigned R1 : 1;
+ unsigned R2 : 1;
+ unsigned MCHNGR : 1;
+ unsigned MULTIP : 1;
+ unsigned VS : 1;
+ unsigned ENCSERV : 1;
+ unsigned BQUE : 1;
+
+ unsigned SoftReset : 1;
+ unsigned CmdQue : 1;
+ unsigned Reserved4 : 1;
+ unsigned Linked : 1;
+ unsigned Sync : 1;
+ unsigned WideBus16Bit : 1;
+ unsigned WideBus32Bit : 1;
+ unsigned RelAddr : 1;
+
+ uint8_t VendorID[8];
+ uint8_t ProductID[16];
+ uint8_t RevisionID[4];
+} __attribute__((packed));
+
+struct CommandBlockWrapperBase {
+ uint32_t dCBWSignature;
+ uint32_t dCBWTag;
+ uint32_t dCBWDataTransferLength;
+ uint8_t bmCBWFlags;
+public:
+
+ CommandBlockWrapperBase() {
+ }
+
+ CommandBlockWrapperBase(uint32_t tag, uint32_t xflen, uint8_t flgs) :
+ dCBWSignature(MASS_CBW_SIGNATURE), dCBWTag(tag), dCBWDataTransferLength(xflen), bmCBWFlags(flgs) {
+ }
+} __attribute__((packed));
+
+struct CommandBlockWrapper : public CommandBlockWrapperBase {
+
+ struct {
+ uint8_t bmCBWLUN : 4;
+ uint8_t bmReserved1 : 4;
+ };
+
+ struct {
+ uint8_t bmCBWCBLength : 4;
+ uint8_t bmReserved2 : 4;
+ };
+
+ uint8_t CBWCB[16];
+
+public:
+ // All zeroed.
+
+ CommandBlockWrapper() :
+ CommandBlockWrapperBase(0, 0, 0), bmReserved1(0), bmReserved2(0) {
+ for(int i = 0; i < 16; i++) CBWCB[i] = 0;
+ }
+
+ // Generic Wrap, CDB zeroed.
+
+ CommandBlockWrapper(uint32_t tag, uint32_t xflen, uint8_t flgs, uint8_t lu, uint8_t cmdlen, uint8_t cmd) :
+ CommandBlockWrapperBase(tag, xflen, flgs),
+ bmCBWLUN(lu), bmReserved1(0), bmCBWCBLength(cmdlen), bmReserved2(0) {
+ for(int i = 0; i < 16; i++) CBWCB[i] = 0;
+ // Type punning can cause optimization problems and bugs.
+ // Using reinterpret_cast to a dreinterpretifferent object is the proper way to do this.
+ //(((BASICCDB_t *) CBWCB)->LUN) = cmd;
+ BASICCDB_t *x = reinterpret_cast<BASICCDB_t *>(CBWCB);
+ x->LUN = cmd;
+ }
+
+ // Wrap for CDB of 6
+
+ CommandBlockWrapper(uint32_t tag, uint32_t xflen, CDB6_t *cdb, uint8_t dir) :
+ CommandBlockWrapperBase(tag, xflen, dir),
+ bmCBWLUN(cdb->LUN), bmReserved1(0), bmCBWCBLength(6), bmReserved2(0) {
+ memcpy(&CBWCB, cdb, 6);
+ }
+ // Wrap for CDB of 10
+
+ CommandBlockWrapper(uint32_t tag, uint32_t xflen, CDB10_t *cdb, uint8_t dir) :
+ CommandBlockWrapperBase(tag, xflen, dir),
+ bmCBWLUN(cdb->LUN), bmReserved1(0), bmCBWCBLength(10), bmReserved2(0) {
+ memcpy(&CBWCB, cdb, 10);
+ }
+} __attribute__((packed));
+
+struct CommandStatusWrapper {
+ uint32_t dCSWSignature;
+ uint32_t dCSWTag;
+ uint32_t dCSWDataResidue;
+ uint8_t bCSWStatus;
+} __attribute__((packed));
+
+struct RequestSenseResponce {
+ uint8_t bResponseCode;
+ uint8_t bSegmentNumber;
+
+ uint8_t bmSenseKey : 4;
+ uint8_t bmReserved : 1;
+ uint8_t bmILI : 1;
+ uint8_t bmEOM : 1;
+ uint8_t bmFileMark : 1;
+
+ uint8_t Information[4];
+ uint8_t bAdditionalLength;
+ uint8_t CmdSpecificInformation[4];
+ uint8_t bAdditionalSenseCode;
+ uint8_t bAdditionalSenseQualifier;
+ uint8_t bFieldReplaceableUnitCode;
+ uint8_t SenseKeySpecific[3];
+} __attribute__((packed));
+
+class BulkOnly : public USBDeviceConfig, public UsbConfigXtracter {
+protected:
+ static const uint8_t epDataInIndex; // DataIn endpoint index
+ static const uint8_t epDataOutIndex; // DataOUT endpoint index
+ static const uint8_t epInterruptInIndex; // InterruptIN endpoint index
+
+ USB *pUsb;
+ uint8_t bAddress;
+ uint8_t bConfNum; // configuration number
+ uint8_t bIface; // interface value
+ uint8_t bNumEP; // total number of EP in the configuration
+ uint32_t qNextPollTime; // next poll time
+ bool bPollEnable; // poll enable flag
+
+ EpInfo epInfo[MASS_MAX_ENDPOINTS];
+
+ uint32_t dCBWTag; // Tag
+ //uint32_t dCBWDataTransferLength; // Data Transfer Length
+ uint8_t bLastUsbError; // Last USB error
+ uint8_t bMaxLUN; // Max LUN
+ uint8_t bTheLUN; // Active LUN
+ uint32_t CurrentCapacity[MASS_MAX_SUPPORTED_LUN]; // Total sectors
+ uint16_t CurrentSectorSize[MASS_MAX_SUPPORTED_LUN]; // Sector size, clipped to 16 bits
+ bool LUNOk[MASS_MAX_SUPPORTED_LUN]; // use this to check for media changes.
+ bool WriteOk[MASS_MAX_SUPPORTED_LUN];
+ void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr);
+
+
+ // Additional Initialization Method for Subclasses
+
+ virtual uint8_t OnInit() {
+ return 0;
+ };
+public:
+ BulkOnly(USB *p);
+
+ uint8_t GetLastUsbError() {
+ return bLastUsbError;
+ };
+
+ uint8_t GetbMaxLUN() {
+ return bMaxLUN; // Max LUN
+ }
+
+ uint8_t GetbTheLUN() {
+ return bTheLUN; // Active LUN
+ }
+
+ bool WriteProtected(uint8_t lun);
+ uint8_t MediaCTL(uint8_t lun, uint8_t ctl);
+ uint8_t Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf);
+ uint8_t Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, USBReadParser *prs);
+ uint8_t Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t *buf);
+ uint8_t LockMedia(uint8_t lun, uint8_t lock);
+
+ bool LUNIsGood(uint8_t lun);
+ uint32_t GetCapacity(uint8_t lun);
+ uint16_t GetSectorSize(uint8_t lun);
+
+ // USBDeviceConfig implementation
+ uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
+ uint8_t ConfigureDevice(uint8_t parent, uint8_t port, bool lowspeed);
+
+ uint8_t Release();
+ uint8_t Poll();
+
+ virtual uint8_t GetAddress() {
+ return bAddress;
+ };
+
+ // UsbConfigXtracter implementation
+ void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
+
+ virtual bool DEVCLASSOK(uint8_t klass) {
+ return (klass == USB_CLASS_MASS_STORAGE);
+ }
+
+ uint8_t SCSITransaction6(CDB6_t *cdb, uint16_t buf_size, void *buf, uint8_t dir);
+ uint8_t SCSITransaction10(CDB10_t *cdb, uint16_t buf_size, void *buf, uint8_t dir);
+
+private:
+ uint8_t Inquiry(uint8_t lun, uint16_t size, uint8_t *buf);
+ uint8_t TestUnitReady(uint8_t lun);
+ uint8_t RequestSense(uint8_t lun, uint16_t size, uint8_t *buf);
+ uint8_t ModeSense6(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t *buf);
+ uint8_t GetMaxLUN(uint8_t *max_lun);
+ uint8_t SetCurLUN(uint8_t lun);
+ void Reset();
+ uint8_t ResetRecovery();
+ uint8_t ReadCapacity10(uint8_t lun, uint8_t *buf);
+ void ClearAllEP();
+ void CheckMedia();
+ bool CheckLUN(uint8_t lun);
+ uint8_t Page3F(uint8_t lun);
+ bool IsValidCBW(uint8_t size, uint8_t *pcbw);
+ bool IsMeaningfulCBW(uint8_t size, uint8_t *pcbw);
+
+ bool IsValidCSW(CommandStatusWrapper *pcsw, CommandBlockWrapperBase *pcbw);
+
+ uint8_t ClearEpHalt(uint8_t index);
+#if MS_WANT_PARSER
+ uint8_t Transaction(CommandBlockWrapper *cbw, uint16_t bsize, void *buf, uint8_t flags);
+#endif
+ uint8_t Transaction(CommandBlockWrapper *cbw, uint16_t bsize, void *buf);
+ uint8_t HandleUsbError(uint8_t error, uint8_t index);
+ uint8_t HandleSCSIError(uint8_t status);
+
+};
+
+#endif // __MASSTORAGE_H__
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/max3421e.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/max3421e.h
new file mode 100644
index 000000000..4e45a35e8
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/max3421e.h
@@ -0,0 +1,228 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+#if !defined(_usb_h_) || defined(_max3421e_h_)
+#error "Never include max3421e.h directly; include Usb.h instead"
+#else
+
+#define _max3421e_h_
+
+/* MAX3421E register/bit names and bitmasks */
+
+/* Arduino pin definitions */
+/* pin numbers to port numbers */
+
+#define SE0 0
+#define SE1 1
+#define FSHOST 2
+#define LSHOST 3
+
+/* MAX3421E command byte format: rrrrr0wa where 'r' is register number */
+//
+// MAX3421E Registers in HOST mode.
+//
+#define rRCVFIFO 0x08 //1<<3
+#define rSNDFIFO 0x10 //2<<3
+#define rSUDFIFO 0x20 //4<<3
+#define rRCVBC 0x30 //6<<3
+#define rSNDBC 0x38 //7<<3
+
+#define rUSBIRQ 0x68 //13<<3
+/* USBIRQ Bits */
+#define bmVBUSIRQ 0x40 //b6
+#define bmNOVBUSIRQ 0x20 //b5
+#define bmOSCOKIRQ 0x01 //b0
+
+#define rUSBIEN 0x70 //14<<3
+/* USBIEN Bits */
+#define bmVBUSIE 0x40 //b6
+#define bmNOVBUSIE 0x20 //b5
+#define bmOSCOKIE 0x01 //b0
+
+#define rUSBCTL 0x78 //15<<3
+/* USBCTL Bits */
+#define bmCHIPRES 0x20 //b5
+#define bmPWRDOWN 0x10 //b4
+
+#define rCPUCTL 0x80 //16<<3
+/* CPUCTL Bits */
+#define bmPUSLEWID1 0x80 //b7
+#define bmPULSEWID0 0x40 //b6
+#define bmIE 0x01 //b0
+
+#define rPINCTL 0x88 //17<<3
+/* PINCTL Bits */
+#define bmFDUPSPI 0x10 //b4
+#define bmINTLEVEL 0x08 //b3
+#define bmPOSINT 0x04 //b2
+#define bmGPXB 0x02 //b1
+#define bmGPXA 0x01 //b0
+// GPX pin selections
+#define GPX_OPERATE 0x00
+#define GPX_VBDET 0x01
+#define GPX_BUSACT 0x02
+#define GPX_SOF 0x03
+
+#define rREVISION 0x90 //18<<3
+
+#define rIOPINS1 0xa0 //20<<3
+
+/* IOPINS1 Bits */
+#define bmGPOUT0 0x01
+#define bmGPOUT1 0x02
+#define bmGPOUT2 0x04
+#define bmGPOUT3 0x08
+#define bmGPIN0 0x10
+#define bmGPIN1 0x20
+#define bmGPIN2 0x40
+#define bmGPIN3 0x80
+
+#define rIOPINS2 0xa8 //21<<3
+/* IOPINS2 Bits */
+#define bmGPOUT4 0x01
+#define bmGPOUT5 0x02
+#define bmGPOUT6 0x04
+#define bmGPOUT7 0x08
+#define bmGPIN4 0x10
+#define bmGPIN5 0x20
+#define bmGPIN6 0x40
+#define bmGPIN7 0x80
+
+#define rGPINIRQ 0xb0 //22<<3
+/* GPINIRQ Bits */
+#define bmGPINIRQ0 0x01
+#define bmGPINIRQ1 0x02
+#define bmGPINIRQ2 0x04
+#define bmGPINIRQ3 0x08
+#define bmGPINIRQ4 0x10
+#define bmGPINIRQ5 0x20
+#define bmGPINIRQ6 0x40
+#define bmGPINIRQ7 0x80
+
+#define rGPINIEN 0xb8 //23<<3
+/* GPINIEN Bits */
+#define bmGPINIEN0 0x01
+#define bmGPINIEN1 0x02
+#define bmGPINIEN2 0x04
+#define bmGPINIEN3 0x08
+#define bmGPINIEN4 0x10
+#define bmGPINIEN5 0x20
+#define bmGPINIEN6 0x40
+#define bmGPINIEN7 0x80
+
+#define rGPINPOL 0xc0 //24<<3
+/* GPINPOL Bits */
+#define bmGPINPOL0 0x01
+#define bmGPINPOL1 0x02
+#define bmGPINPOL2 0x04
+#define bmGPINPOL3 0x08
+#define bmGPINPOL4 0x10
+#define bmGPINPOL5 0x20
+#define bmGPINPOL6 0x40
+#define bmGPINPOL7 0x80
+
+#define rHIRQ 0xc8 //25<<3
+/* HIRQ Bits */
+#define bmBUSEVENTIRQ 0x01 // indicates BUS Reset Done or BUS Resume
+#define bmRWUIRQ 0x02
+#define bmRCVDAVIRQ 0x04
+#define bmSNDBAVIRQ 0x08
+#define bmSUSDNIRQ 0x10
+#define bmCONDETIRQ 0x20
+#define bmFRAMEIRQ 0x40
+#define bmHXFRDNIRQ 0x80
+
+#define rHIEN 0xd0 //26<<3
+
+/* HIEN Bits */
+#define bmBUSEVENTIE 0x01
+#define bmRWUIE 0x02
+#define bmRCVDAVIE 0x04
+#define bmSNDBAVIE 0x08
+#define bmSUSDNIE 0x10
+#define bmCONDETIE 0x20
+#define bmFRAMEIE 0x40
+#define bmHXFRDNIE 0x80
+
+#define rMODE 0xd8 //27<<3
+
+/* MODE Bits */
+#define bmHOST 0x01
+#define bmLOWSPEED 0x02
+#define bmHUBPRE 0x04
+#define bmSOFKAENAB 0x08
+#define bmSEPIRQ 0x10
+#define bmDELAYISO 0x20
+#define bmDMPULLDN 0x40
+#define bmDPPULLDN 0x80
+
+#define rPERADDR 0xe0 //28<<3
+
+#define rHCTL 0xe8 //29<<3
+/* HCTL Bits */
+#define bmBUSRST 0x01
+#define bmFRMRST 0x02
+#define bmSAMPLEBUS 0x04
+#define bmSIGRSM 0x08
+#define bmRCVTOG0 0x10
+#define bmRCVTOG1 0x20
+#define bmSNDTOG0 0x40
+#define bmSNDTOG1 0x80
+
+#define rHXFR 0xf0 //30<<3
+/* Host transfer token values for writing the HXFR register (R30) */
+/* OR this bit field with the endpoint number in bits 3:0 */
+#define tokSETUP 0x10 // HS=0, ISO=0, OUTNIN=0, SETUP=1
+#define tokIN 0x00 // HS=0, ISO=0, OUTNIN=0, SETUP=0
+#define tokOUT 0x20 // HS=0, ISO=0, OUTNIN=1, SETUP=0
+#define tokINHS 0x80 // HS=1, ISO=0, OUTNIN=0, SETUP=0
+#define tokOUTHS 0xA0 // HS=1, ISO=0, OUTNIN=1, SETUP=0
+#define tokISOIN 0x40 // HS=0, ISO=1, OUTNIN=0, SETUP=0
+#define tokISOOUT 0x60 // HS=0, ISO=1, OUTNIN=1, SETUP=0
+
+#define rHRSL 0xf8 //31<<3
+
+/* HRSL Bits */
+#define bmRCVTOGRD 0x10
+#define bmSNDTOGRD 0x20
+#define bmKSTATUS 0x40
+#define bmJSTATUS 0x80
+#define bmSE0 0x00 //SE0 - disconnect state
+#define bmSE1 0xc0 //SE1 - illegal state
+
+/* Host error result codes, the 4 LSB's in the HRSL register */
+#define hrSUCCESS 0x00
+#define hrBUSY 0x01
+#define hrBADREQ 0x02
+#define hrUNDEF 0x03
+#define hrNAK 0x04
+#define hrSTALL 0x05
+#define hrTOGERR 0x06
+#define hrWRONGPID 0x07
+#define hrBADBC 0x08
+#define hrPIDERR 0x09
+#define hrPKTERR 0x0A
+#define hrCRCERR 0x0B
+#define hrKERR 0x0C
+#define hrJERR 0x0D
+#define hrTIMEOUT 0x0E
+#define hrBABBLE 0x0F
+
+#define MODE_FS_HOST (bmDPPULLDN|bmDMPULLDN|bmHOST|bmSOFKAENAB)
+#define MODE_LS_HOST (bmDPPULLDN|bmDMPULLDN|bmHOST|bmLOWSPEED|bmSOFKAENAB)
+
+
+#endif //_max3421e_h_
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/max_LCD.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/max_LCD.cpp
new file mode 100644
index 000000000..f0c64666f
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/max_LCD.cpp
@@ -0,0 +1,255 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+#include "max_LCD.h"
+#include <string.h>
+
+// pin definition and set/clear
+
+#define RS 0x04 // RS pin
+#define E 0x08 // E pin
+
+#define SET_RS lcdPins |= RS
+#define CLR_RS lcdPins &= ~RS
+#define SET_E lcdPins |= E
+#define CLR_E lcdPins &= ~E
+
+#define SENDlcdPins() pUsb->gpioWr( lcdPins )
+
+#define LCD_sendcmd(a) { CLR_RS; \
+ sendbyte(a); \
+ }
+
+#define LCD_sendchar(a) { SET_RS; \
+ sendbyte(a); \
+ }
+
+static byte lcdPins; //copy of LCD pins
+
+Max_LCD::Max_LCD(USB *pusb) : pUsb(pusb) {
+ lcdPins = 0;
+}
+
+void Max_LCD::init() {
+ _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
+
+ // MAX3421E::gpioWr(0x55);
+
+ begin(16, 1);
+}
+
+void Max_LCD::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) {
+ if(lines > 1) {
+ _displayfunction |= LCD_2LINE;
+ }
+ _numlines = lines;
+ _currline = 0;
+
+ // for some 1 line displays you can select a 10 pixel high font
+ if((dotsize != 0) && (lines == 1)) {
+ _displayfunction |= LCD_5x10DOTS;
+ }
+
+ // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
+ // according to datasheet, we need at least 40ms after power rises above 2.7V
+ // before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50
+ delayMicroseconds(50000);
+ lcdPins = 0x30;
+ SET_E;
+ SENDlcdPins();
+ CLR_E;
+ SENDlcdPins();
+ delayMicroseconds(10000); // wait min 4.1ms
+ //second try
+ SET_E;
+ SENDlcdPins();
+ CLR_E;
+ SENDlcdPins();
+ delayMicroseconds(10000); // wait min 4.1ms
+ // third go!
+ SET_E;
+ SENDlcdPins();
+ CLR_E;
+ SENDlcdPins();
+ delayMicroseconds(10000);
+ // finally, set to 4-bit interface
+ lcdPins = 0x20;
+ //SET_RS;
+ SET_E;
+ SENDlcdPins();
+ //CLR_RS;
+ CLR_E;
+ SENDlcdPins();
+ delayMicroseconds(10000);
+ // finally, set # lines, font size, etc.
+ command(LCD_FUNCTIONSET | _displayfunction);
+
+ // turn the display on with no cursor or blinking default
+ _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
+ display();
+
+ // clear it off
+ clear();
+
+ // Initialize to default text direction (for romance languages)
+ _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
+ // set the entry mode
+ command(LCD_ENTRYMODESET | _displaymode);
+}
+
+/********** high level commands, for the user! */
+void Max_LCD::clear() {
+ command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero
+ delayMicroseconds(2000); // this command takes a long time!
+}
+
+void Max_LCD::home() {
+ command(LCD_RETURNHOME); // set cursor position to zero
+ delayMicroseconds(2000); // this command takes a long time!
+}
+
+void Max_LCD::setCursor(uint8_t col, uint8_t row) {
+ int row_offsets[] = {0x00, 0x40, 0x14, 0x54};
+ if(row > _numlines) {
+ row = _numlines - 1; // we count rows starting w/0
+ }
+
+ command(LCD_SETDDRAMADDR | (col + row_offsets[row]));
+}
+
+// Turn the display on/off (quickly)
+
+void Max_LCD::noDisplay() {
+ _displaycontrol &= ~LCD_DISPLAYON;
+ command(LCD_DISPLAYCONTROL | _displaycontrol);
+}
+
+void Max_LCD::display() {
+ _displaycontrol |= LCD_DISPLAYON;
+ command(LCD_DISPLAYCONTROL | _displaycontrol);
+}
+
+// Turns the underline cursor on/off
+
+void Max_LCD::noCursor() {
+ _displaycontrol &= ~LCD_CURSORON;
+ command(LCD_DISPLAYCONTROL | _displaycontrol);
+}
+
+void Max_LCD::cursor() {
+ _displaycontrol |= LCD_CURSORON;
+ command(LCD_DISPLAYCONTROL | _displaycontrol);
+}
+
+
+// Turn on and off the blinking cursor
+
+void Max_LCD::noBlink() {
+ _displaycontrol &= ~LCD_BLINKON;
+ command(LCD_DISPLAYCONTROL | _displaycontrol);
+}
+
+void Max_LCD::blink() {
+ _displaycontrol |= LCD_BLINKON;
+ command(LCD_DISPLAYCONTROL | _displaycontrol);
+}
+
+// These commands scroll the display without changing the RAM
+
+void Max_LCD::scrollDisplayLeft(void) {
+ command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
+}
+
+void Max_LCD::scrollDisplayRight(void) {
+ command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
+}
+
+// This is for text that flows Left to Right
+
+void Max_LCD::leftToRight(void) {
+ _displaymode |= LCD_ENTRYLEFT;
+ command(LCD_ENTRYMODESET | _displaymode);
+}
+
+// This is for text that flows Right to Left
+
+void Max_LCD::rightToLeft(void) {
+ _displaymode &= ~LCD_ENTRYLEFT;
+ command(LCD_ENTRYMODESET | _displaymode);
+}
+
+// This will 'right justify' text from the cursor
+
+void Max_LCD::autoscroll(void) {
+ _displaymode |= LCD_ENTRYSHIFTINCREMENT;
+ command(LCD_ENTRYMODESET | _displaymode);
+}
+
+// This will 'left justify' text from the cursor
+
+void Max_LCD::noAutoscroll(void) {
+ _displaymode &= ~LCD_ENTRYSHIFTINCREMENT;
+ command(LCD_ENTRYMODESET | _displaymode);
+}
+
+// Allows us to fill the first 8 CGRAM locations
+// with custom characters
+
+void Max_LCD::createChar(uint8_t location, uint8_t charmap[]) {
+ location &= 0x7; // we only have 8 locations 0-7
+ command(LCD_SETCGRAMADDR | (location << 3));
+ for(int i = 0; i < 8; i++) {
+ write(charmap[i]);
+ }
+}
+
+/*********** mid level commands, for sending data/cmds */
+
+inline void Max_LCD::command(uint8_t value) {
+ LCD_sendcmd(value);
+ delayMicroseconds(100);
+}
+
+#if defined(ARDUINO) && ARDUINO >=100
+
+inline size_t Max_LCD::write(uint8_t value) {
+ LCD_sendchar(value);
+ return 1; // Assume success
+}
+#else
+
+inline void Max_LCD::write(uint8_t value) {
+ LCD_sendchar(value);
+}
+#endif
+
+void Max_LCD::sendbyte(uint8_t val) {
+ lcdPins &= 0x0f; //prepare place for the upper nibble
+ lcdPins |= (val & 0xf0); //copy upper nibble to LCD variable
+ SET_E; //send
+ SENDlcdPins();
+ delayMicroseconds(2);
+ CLR_E;
+ delayMicroseconds(2);
+ SENDlcdPins();
+ lcdPins &= 0x0f; //prepare place for the lower nibble
+ lcdPins |= (val << 4) & 0xf0; //copy lower nibble to LCD variable
+ SET_E; //send
+ SENDlcdPins();
+ CLR_E;
+ SENDlcdPins();
+ delayMicroseconds(100);
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/max_LCD.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/max_LCD.h
new file mode 100644
index 000000000..950c9c5aa
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/max_LCD.h
@@ -0,0 +1,106 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+//HD44780 compatible LCD display via MAX3421E GPOUT support header
+//pinout: D[4-7] -> GPOUT[4-7], RS-> GPOUT[2], E ->GPOUT[3]
+//
+
+#ifndef _Max_LCD_h_
+#define _Max_LCD_h_
+
+#include "Usb.h"
+#include "Print.h"
+
+// commands
+#define LCD_CLEARDISPLAY 0x01
+#define LCD_RETURNHOME 0x02
+#define LCD_ENTRYMODESET 0x04
+#define LCD_DISPLAYCONTROL 0x08
+#define LCD_CURSORSHIFT 0x10
+#define LCD_FUNCTIONSET 0x20
+#define LCD_SETCGRAMADDR 0x40
+#define LCD_SETDDRAMADDR 0x80
+
+// flags for display entry mode
+#define LCD_ENTRYRIGHT 0x00
+#define LCD_ENTRYLEFT 0x02
+#define LCD_ENTRYSHIFTINCREMENT 0x01
+#define LCD_ENTRYSHIFTDECREMENT 0x00
+
+// flags for display on/off control
+#define LCD_DISPLAYON 0x04
+#define LCD_DISPLAYOFF 0x00
+#define LCD_CURSORON 0x02
+#define LCD_CURSOROFF 0x00
+#define LCD_BLINKON 0x01
+#define LCD_BLINKOFF 0x00
+
+// flags for display/cursor shift
+#define LCD_DISPLAYMOVE 0x08
+#define LCD_CURSORMOVE 0x00
+#define LCD_MOVERIGHT 0x04
+#define LCD_MOVELEFT 0x00
+
+// flags for function set
+#define LCD_8BITMODE 0x10
+#define LCD_4BITMODE 0x00
+#define LCD_2LINE 0x08
+#define LCD_1LINE 0x00
+#define LCD_5x10DOTS 0x04
+#define LCD_5x8DOTS 0x00
+
+class Max_LCD : public Print {
+ USB *pUsb;
+
+public:
+ Max_LCD(USB *pusb);
+ void init();
+ void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS);
+ void clear();
+ void home();
+ void noDisplay();
+ void display();
+ void noBlink();
+ void blink();
+ void noCursor();
+ void cursor();
+ void scrollDisplayLeft();
+ void scrollDisplayRight();
+ void leftToRight();
+ void rightToLeft();
+ void autoscroll();
+ void noAutoscroll();
+ void createChar(uint8_t, uint8_t[]);
+ void setCursor(uint8_t, uint8_t);
+ void command(uint8_t);
+
+#if defined(ARDUINO) && ARDUINO >=100
+ size_t write(uint8_t);
+ using Print::write;
+#else
+ void write(uint8_t);
+#endif
+
+private:
+ void sendbyte(uint8_t val);
+ uint8_t _displayfunction; //tokill
+ uint8_t _displaycontrol;
+ uint8_t _displaymode;
+ uint8_t _initialized;
+ uint8_t _numlines, _currline;
+};
+
+#endif
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/message.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/message.cpp
new file mode 100644
index 000000000..bdcdd1833
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/message.cpp
@@ -0,0 +1,116 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+
+#include "Usb.h"
+// 0x80 is the default (i.e. trace) to turn off set this global to something lower.
+// this allows for 126 other debugging levels.
+// TO-DO: Allow assignment to a different serial port by software
+int UsbDEBUGlvl = 0x80;
+
+void E_Notifyc(char c, int lvl) {
+ if(UsbDEBUGlvl < lvl) return;
+#if defined(ARDUINO) && ARDUINO >=100
+ USB_HOST_SERIAL.print(c);
+#else
+ USB_HOST_SERIAL.print(c, BYTE);
+#endif
+ //USB_HOST_SERIAL.flush();
+}
+
+void E_Notify(char const * msg, int lvl) {
+ if(UsbDEBUGlvl < lvl) return;
+ if(!msg) return;
+ char c;
+
+ while((c = pgm_read_byte(msg++))) E_Notifyc(c, lvl);
+}
+
+void E_NotifyStr(char const * msg, int lvl) {
+ if(UsbDEBUGlvl < lvl) return;
+ if(!msg) return;
+ char c;
+
+ while((c = *msg++)) E_Notifyc(c, lvl);
+}
+
+void E_Notify(uint8_t b, int lvl) {
+ if(UsbDEBUGlvl < lvl) return;
+#if defined(ARDUINO) && ARDUINO >=100
+ USB_HOST_SERIAL.print(b);
+#else
+ USB_HOST_SERIAL.print(b, DEC);
+#endif
+ //USB_HOST_SERIAL.flush();
+}
+
+void E_Notify(double d, int lvl) {
+ if(UsbDEBUGlvl < lvl) return;
+ USB_HOST_SERIAL.print(d);
+ //USB_HOST_SERIAL.flush();
+}
+
+#ifdef DEBUG_USB_HOST
+
+void NotifyFailGetDevDescr(void) {
+ Notify(PSTR("\r\ngetDevDescr "), 0x80);
+}
+
+void NotifyFailSetDevTblEntry(void) {
+ Notify(PSTR("\r\nsetDevTblEn "), 0x80);
+}
+
+void NotifyFailGetConfDescr(void) {
+ Notify(PSTR("\r\ngetConf "), 0x80);
+}
+
+void NotifyFailSetConfDescr(void) {
+ Notify(PSTR("\r\nsetConf "), 0x80);
+}
+
+void NotifyFailGetDevDescr(uint8_t reason) {
+ NotifyFailGetDevDescr();
+ NotifyFail(reason);
+}
+
+void NotifyFailSetDevTblEntry(uint8_t reason) {
+ NotifyFailSetDevTblEntry();
+ NotifyFail(reason);
+
+}
+
+void NotifyFailGetConfDescr(uint8_t reason) {
+ NotifyFailGetConfDescr();
+ NotifyFail(reason);
+}
+
+void NotifyFailSetConfDescr(uint8_t reason) {
+ NotifyFailSetConfDescr();
+ NotifyFail(reason);
+}
+
+void NotifyFailUnknownDevice(uint16_t VID, uint16_t PID) {
+ Notify(PSTR("\r\nUnknown Device Connected - VID: "), 0x80);
+ D_PrintHex<uint16_t > (VID, 0x80);
+ Notify(PSTR(" PID: "), 0x80);
+ D_PrintHex<uint16_t > (PID, 0x80);
+}
+
+void NotifyFail(uint8_t rcode) {
+ D_PrintHex<uint8_t > (rcode, 0x80);
+ Notify(PSTR("\r\n"), 0x80);
+}
+#endif
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/message.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/message.h
new file mode 100644
index 000000000..c26628e7f
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/message.h
@@ -0,0 +1,78 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+#if !defined(_usb_h_) || defined(__MESSAGE_H__)
+#error "Never include message.h directly; include Usb.h instead"
+#else
+#define __MESSAGE_H__
+
+extern int UsbDEBUGlvl;
+
+void E_Notify(char const * msg, int lvl);
+void E_Notify(uint8_t b, int lvl);
+void E_NotifyStr(char const * msg, int lvl);
+void E_Notifyc(char c, int lvl);
+
+#ifdef DEBUG_USB_HOST
+#define Notify E_Notify
+#define NotifyStr E_NotifyStr
+#define Notifyc E_Notifyc
+void NotifyFailGetDevDescr(uint8_t reason);
+void NotifyFailSetDevTblEntry(uint8_t reason);
+void NotifyFailGetConfDescr(uint8_t reason);
+void NotifyFailSetConfDescr(uint8_t reason);
+void NotifyFailGetDevDescr(void);
+void NotifyFailSetDevTblEntry(void);
+void NotifyFailGetConfDescr(void);
+void NotifyFailSetConfDescr(void);
+void NotifyFailUnknownDevice(uint16_t VID, uint16_t PID);
+void NotifyFail(uint8_t rcode);
+#else
+#define Notify(...) ((void)0)
+#define NotifyStr(...) ((void)0)
+#define Notifyc(...) ((void)0)
+#define NotifyFailGetDevDescr(...) ((void)0)
+#define NotifyFailSetDevTblEntry(...) ((void)0)
+#define NotifyFailGetConfDescr(...) ((void)0)
+#define NotifyFailGetDevDescr(...) ((void)0)
+#define NotifyFailSetDevTblEntry(...) ((void)0)
+#define NotifyFailGetConfDescr(...) ((void)0)
+#define NotifyFailSetConfDescr(...) ((void)0)
+#define NotifyFailUnknownDevice(...) ((void)0)
+#define NotifyFail(...) ((void)0)
+#endif
+
+template <class ERROR_TYPE>
+void ErrorMessage(uint8_t level, char const * msg, ERROR_TYPE rcode = 0) {
+#ifdef DEBUG_USB_HOST
+ Notify(msg, level);
+ Notify(PSTR(": "), level);
+ D_PrintHex<ERROR_TYPE > (rcode, level);
+ Notify(PSTR("\r\n"), level);
+#endif
+}
+
+template <class ERROR_TYPE>
+void ErrorMessage(char const * msg, ERROR_TYPE rcode = 0) {
+#ifdef DEBUG_USB_HOST
+ Notify(msg, 0x80);
+ Notify(PSTR(": "), 0x80);
+ D_PrintHex<ERROR_TYPE > (rcode, 0x80);
+ Notify(PSTR("\r\n"), 0x80);
+#endif
+}
+
+#endif // __MESSAGE_H__
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/parsetools.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/parsetools.cpp
new file mode 100644
index 000000000..74a861059
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/parsetools.cpp
@@ -0,0 +1,67 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+#include "Usb.h"
+
+bool MultiByteValueParser::Parse(uint8_t **pp, uint16_t *pcntdn) {
+ if(!pBuf) {
+ Notify(PSTR("Buffer pointer is NULL!\r\n"), 0x80);
+ return false;
+ }
+ for(; countDown && (*pcntdn); countDown--, (*pcntdn)--, (*pp)++)
+ pBuf[valueSize - countDown] = (**pp);
+
+ if(countDown)
+ return false;
+
+ countDown = valueSize;
+ return true;
+}
+
+bool PTPListParser::Parse(uint8_t **pp, uint16_t *pcntdn, PTP_ARRAY_EL_FUNC pf, const void *me) {
+ switch(nStage) {
+ case 0:
+ pBuf->valueSize = lenSize;
+ theParser.Initialize(pBuf);
+ nStage = 1;
+
+ case 1:
+ if(!theParser.Parse(pp, pcntdn))
+ return false;
+
+ arLen = 0;
+ arLen = (pBuf->valueSize >= 4) ? *((uint32_t*)pBuf->pValue) : (uint32_t)(*((uint16_t*)pBuf->pValue));
+ arLenCntdn = arLen;
+ nStage = 2;
+
+ case 2:
+ pBuf->valueSize = valSize;
+ theParser.Initialize(pBuf);
+ nStage = 3;
+
+ case 3:
+ for(; arLenCntdn; arLenCntdn--) {
+ if(!theParser.Parse(pp, pcntdn))
+ return false;
+
+ if(pf)
+ pf(pBuf, (arLen - arLenCntdn), me);
+ }
+
+ nStage = 0;
+ }
+ return true;
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/parsetools.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/parsetools.h
new file mode 100644
index 000000000..66e9531c3
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/parsetools.h
@@ -0,0 +1,140 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+
+#if !defined(_usb_h_) || defined(__PARSETOOLS_H__)
+#error "Never include parsetools.h directly; include Usb.h instead"
+#else
+#define __PARSETOOLS_H__
+
+struct MultiValueBuffer {
+ uint8_t valueSize;
+ void *pValue;
+} __attribute__((packed));
+
+class MultiByteValueParser {
+ uint8_t * pBuf;
+ uint8_t countDown;
+ uint8_t valueSize;
+
+public:
+
+ MultiByteValueParser() : pBuf(NULL), countDown(0), valueSize(0) {
+ };
+
+ const uint8_t* GetBuffer() {
+ return pBuf;
+ };
+
+ void Initialize(MultiValueBuffer * const pbuf) {
+ pBuf = (uint8_t*)pbuf->pValue;
+ countDown = valueSize = pbuf->valueSize;
+ };
+
+ bool Parse(uint8_t **pp, uint16_t *pcntdn);
+};
+
+class ByteSkipper {
+ uint8_t *pBuf;
+ uint8_t nStage;
+ uint16_t countDown;
+
+public:
+
+ ByteSkipper() : pBuf(NULL), nStage(0), countDown(0) {
+ };
+
+ void Initialize(MultiValueBuffer *pbuf) {
+ pBuf = (uint8_t*)pbuf->pValue;
+ countDown = 0;
+ };
+
+ bool Skip(uint8_t **pp, uint16_t *pcntdn, uint16_t bytes_to_skip) {
+ switch(nStage) {
+ case 0:
+ countDown = bytes_to_skip;
+ nStage++;
+ case 1:
+ for(; countDown && (*pcntdn); countDown--, (*pp)++, (*pcntdn)--);
+
+ if(!countDown)
+ nStage = 0;
+ };
+ return (!countDown);
+ };
+};
+
+// Pointer to a callback function triggered for each element of PTP array when used with PTPArrayParser
+typedef void (*PTP_ARRAY_EL_FUNC)(const MultiValueBuffer * const p, uint32_t count, const void *me);
+
+class PTPListParser {
+public:
+
+ enum ParseMode {
+ modeArray, modeRange/*, modeEnum*/
+ };
+
+private:
+ uint8_t nStage;
+ uint8_t enStage;
+
+ uint32_t arLen;
+ uint32_t arLenCntdn;
+
+ uint8_t lenSize; // size of the array length field in bytes
+ uint8_t valSize; // size of the array element in bytes
+
+ MultiValueBuffer *pBuf;
+
+ // The only parser for both size and array element parsing
+ MultiByteValueParser theParser;
+
+ uint8_t /*ParseMode*/ prsMode;
+
+public:
+
+ PTPListParser() :
+ nStage(0),
+ enStage(0),
+ arLen(0),
+ arLenCntdn(0),
+ lenSize(0),
+ valSize(0),
+ pBuf(NULL),
+ prsMode(modeArray) {
+ };
+
+ void Initialize(const uint8_t len_size, const uint8_t val_size, MultiValueBuffer * const p, const uint8_t mode = modeArray) {
+ pBuf = p;
+ lenSize = len_size;
+ valSize = val_size;
+ prsMode = mode;
+
+ if(prsMode == modeRange) {
+ arLenCntdn = arLen = 3;
+ nStage = 2;
+ } else {
+ arLenCntdn = arLen = 0;
+ nStage = 0;
+ }
+ enStage = 0;
+ theParser.Initialize(p);
+ };
+
+ bool Parse(uint8_t **pp, uint16_t *pcntdn, PTP_ARRAY_EL_FUNC pf, const void *me = NULL);
+};
+
+#endif // __PARSETOOLS_H__
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/printhex.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/printhex.h
new file mode 100644
index 000000000..369d7e1f7
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/printhex.h
@@ -0,0 +1,84 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+
+#if !defined(_usb_h_) || defined(__PRINTHEX_H__)
+#error "Never include printhex.h directly; include Usb.h instead"
+#else
+#define __PRINTHEX_H__
+
+void E_Notifyc(char c, int lvl);
+
+template <class T>
+void PrintHex(T val, int lvl) {
+ int num_nibbles = sizeof (T) * 2;
+
+ do {
+ char v = 48 + (((val >> (num_nibbles - 1) * 4)) & 0x0f);
+ if(v > 57) v += 7;
+ E_Notifyc(v, lvl);
+ } while(--num_nibbles);
+}
+
+template <class T>
+void PrintBin(T val, int lvl) {
+ for(T mask = (((T)1) << ((sizeof (T) << 3) - 1)); mask; mask >>= 1)
+ if(val & mask)
+ E_Notifyc('1', lvl);
+ else
+ E_Notifyc('0', lvl);
+}
+
+template <class T>
+void SerialPrintHex(T val) {
+ int num_nibbles = sizeof (T) * 2;
+
+ do {
+ char v = 48 + (((val >> (num_nibbles - 1) * 4)) & 0x0f);
+ if(v > 57) v += 7;
+ USB_HOST_SERIAL.print(v);
+ } while(--num_nibbles);
+}
+
+template <class T>
+void PrintHex2(Print *prn, T val) {
+ T mask = (((T)1) << (((sizeof (T) << 1) - 1) << 2));
+
+ while(mask > 1) {
+ if(val < mask)
+ prn->print("0");
+
+ mask >>= 4;
+ }
+ prn->print((T)val, HEX);
+}
+
+template <class T> void D_PrintHex(T val, int lvl) {
+#ifdef DEBUG_USB_HOST
+ PrintHex<T > (val, lvl);
+#endif
+}
+
+template <class T>
+void D_PrintBin(T val, int lvl) {
+#ifdef DEBUG_USB_HOST
+ PrintBin<T > (val, lvl);
+#endif
+}
+
+
+
+#endif // __PRINTHEX_H__
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/readme.md b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/readme.md
new file mode 100644
index 000000000..49cd83e0a
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/readme.md
@@ -0,0 +1,351 @@
+# USB Host Library Rev.2.0
+
+The code is released under the GNU General Public License.
+__________
+
+# Summary
+This is Revision 2.0 of MAX3421E-based USB Host Shield Library for AVR's.
+
+Project main web site is: <http://www.circuitsathome.com>.
+
+Some information can also be found at: <http://blog.tkjelectronics.dk/>.
+
+The shield can be purchased at the main site: <http://www.circuitsathome.com/products-page/arduino-shields> or from [TKJ Electronics](http://tkjelectronics.com/): <http://shop.tkjelectronics.dk/product_info.php?products_id=43>.
+
+![USB Host Shield](http://shop.tkjelectronics.dk/images/USB_Host_Shield1.jpg)
+
+For more information about the hardware see the [Hardware Manual](http://www.circuitsathome.com/usb-host-shield-hardware-manual).
+
+# Developed By
+
+* __Oleg Mazurov, Circuits@Home__ - <mazurov@circuitsathome.com>
+* __Alexei Glushchenko, Circuits@Home__ - <alex-gl@mail.ru>
+ * Developers of the USB Core, HID, FTDI, ADK, ACM, and PL2303 libraries
+* __Kristian Lauszus, TKJ Electronics__ - <kristianl@tkjelectronics.com>
+ * Developer of the [BTD](#bluetooth-libraries), [BTHID](#bthid-library), [SPP](#spp-library), [PS4](#ps4-library), [PS3](#ps3-library), [Wii](#wii-library), [Xbox](#xbox-library), and [PSBuzz](#ps-buzz-library) libraries
+* __Andrew Kroll__ - <xxxajk@gmail.com>
+ * Major contributor to mass storage code
+* __guruthree__
+ * [Xbox ONE](#xbox-one-library) controller support
+
+# Donate
+
+Help yourself by helping us support you! Many thousands of hours have been spent developing the USB Host Shield library. Since you find it useful, please consider donating via the button below. Donations will allow us to support you by ensuring hardware that you have can be acquired in order to add support for your microcontroller board.
+
+<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&amp;business=donate@circuitsathome.com&amp;lc=US&amp;item_name=Donate%20to%20the%20USB%20Host%20Library%20project&amp;no_note=0&amp;currency_code=USD&amp;bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHostedGuest"><img src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif" alt="PayPal - The safer, easier way to pay online!" /></a>
+
+# Table of Contents
+
+* [How to include the library](#how-to-include-the-library)
+ * [Arduino Library Manager](#arduino-library-manager)
+ * [Manual installation](#manual-installation)
+* [How to use the library](#how-to-use-the-library)
+ * [Documentation](#documentation)
+ * [Enable debugging](#enable-debugging)
+ * [Boards](#boards)
+ * [Bluetooth libraries](#bluetooth-libraries)
+ * [BTHID library](#bthid-library)
+ * [SPP library](#spp-library)
+ * [PS4 Library](#ps4-library)
+ * [PS3 Library](#ps3-library)
+ * [Xbox Libraries](#xbox-libraries)
+ * [Xbox library](#xbox-library)
+ * [Xbox 360 Library](#xbox-360-library)
+ * [Xbox ONE Library](#xbox-one-library)
+ * [Wii library](#wii-library)
+ * [PS Buzz Library](#ps-buzz-library)
+* [Interface modifications](#interface-modifications)
+* [FAQ](#faq)
+
+# How to include the library
+
+### Arduino Library Manager
+
+First install Arduino IDE version 1.6.2 or newer, then simply use the Arduino Library Manager to install the library.
+
+Please see the following page for instructions: <http://www.arduino.cc/en/Guide/Libraries#toc3>.
+
+### Manual installation
+
+First download the library by clicking on the following link: <https://github.com/felis/USB_Host_Shield_2.0/archive/master.zip>.
+
+Then uncompress the zip folder and rename the directory to "USB\_Host\_Shield\_20", as any special characters are not supported by the Arduino IDE.
+
+Now open up the Arduino IDE and open "File>Preferences". There you will see the location of your sketchbook. Open that directory and create a directory called "libraries" inside that directory.
+Now move the "USB\_Host\_Shield\_20" directory to the "libraries" directory.
+
+The final structure should look like this:
+
+* Arduino/
+ * libraries/
+ * USB\_Host\_Shield\_20/
+
+Now quit the Arduino IDE and reopen it.
+
+Now you should be able to go open all the examples codes by navigating to "File>Examples>USB\_Host\_Shield\_20" and then select the example you will like to open.
+
+For more information visit the following sites: <http://arduino.cc/en/Guide/Libraries> and <https://learn.adafruit.com/adafruit-all-about-arduino-libraries-install-use>.
+
+# How to use the library
+
+### Documentation
+
+Documentation for the library can be found at the following link: <http://felis.github.com/USB_Host_Shield_2.0/>.
+
+### Enable debugging
+
+By default serial debugging is disabled. To turn it on simply change ```ENABLE_UHS_DEBUGGING``` to 1 in [settings.h](settings.h) like so:
+
+```C++
+#define ENABLE_UHS_DEBUGGING 1
+```
+
+### Boards
+
+Currently the following boards are supported by the library:
+
+* All official Arduino AVR boards (Uno, Duemilanove, Mega, Mega 2560, Mega ADK, Leonardo etc.)
+* Arduino Due, Intel Galileo, Intel Galileo 2, and Intel Edison
+ * Note that the Intel Galileo uses pin 2 and 3 as INT and SS pin respectively by default, so some modifications to the shield are needed. See the "Interface modifications" section in the [hardware manual](https://www.circuitsathome.com/usb-host-shield-hardware-manual) for more information.
+* Teensy (Teensy++ 1.0, Teensy 2.0, Teensy++ 2.0, and Teensy 3.x)
+ * Note if you are using the Teensy 3.x you should download this SPI library as well: <https://github.com/xxxajk/spi4teensy3>. You should then add ```#include <spi4teensy3.h>``` to your .ino file.
+* Balanduino
+* Sanguino
+* Black Widdow
+* RedBearLab nRF51822
+* Digilent chipKIT
+ * Please see: <http://www.circuitsathome.com/mcu/usb/running-usb-host-code-on-digilent-chipkit-board>.
+
+The following boards need to be activated manually in [settings.h](settings.h):
+
+* Arduino Mega ADK
+ * If you are using Arduino 1.5.5 or newer there is no need to activate the Arduino Mega ADK manually
+* Black Widdow
+
+Simply set the corresponding value to 1 instead of 0.
+
+### [Bluetooth libraries](BTD.cpp)
+
+The [BTD library](BTD.cpp) is a general purpose library for an ordinary Bluetooth dongle.
+This library make it easy to add support for different Bluetooth services like a PS3 or a Wii controller or SPP which is a virtual serial port via Bluetooth.
+Some different examples can be found in the [example directory](examples/Bluetooth).
+
+The BTD library also makes it possible to use multiple services at once, the following example sketch is an example of this:
+[PS3SPP.ino](examples/Bluetooth/PS3SPP/PS3SPP.ino).
+
+### [BTHID library](BTHID.cpp)
+
+The [Bluetooth HID library](BTHID.cpp) allows you to connect HID devices via Bluetooth to the USB Host Shield.
+
+Currently HID mice and keyboards are supported.
+
+It uses the standard Boot protocol by default, but it is also able to use the Report protocol as well. You would simply have to call ```setProtocolMode()``` and then parse ```HID_RPT_PROTOCOL``` as an argument. You will then have to modify the parser for your device. See the example: [BTHID.ino](examples/Bluetooth/BTHID/BTHID.ino) for more information.
+
+The [PS4 library](#ps4-library) also uses this class to handle all Bluetooth communication.
+
+For information see the following blog post: <http://blog.tkjelectronics.dk/2013/12/bluetooth-hid-devices-now-supported-by-the-usb-host-library/>.
+
+### [SPP library](SPP.cpp)
+
+SPP stands for "Serial Port Profile" and is a Bluetooth protocol that implements a virtual comport which allows you to send data back and forth from your computer/phone to your Arduino via Bluetooth.
+It has been tested successfully on Windows, Mac OS X, Linux, and Android.
+
+Take a look at the [SPP.ino](examples/Bluetooth/SPP/SPP.ino) example for more information.
+
+More information can be found at these blog posts:
+
+* <http://www.circuitsathome.com/mcu/bluetooth-rfcommspp-service-support-for-usb-host-2-0-library-released>
+* <http://blog.tkjelectronics.dk/2012/07/rfcommspp-library-for-arduino/>
+
+To implement the SPP protocol I used a Bluetooth sniffing tool called [PacketLogger](http://www.tkjelectronics.com/uploads/PacketLogger.zip) developed by Apple.
+It enables me to see the Bluetooth communication between my Mac and any device.
+
+### PS4 Library
+
+The PS4BT library is split up into the [PS4BT](PS4BT.h) and the [PS4USB](PS4USB.h) library. These allow you to use the Sony PS4 controller via Bluetooth and USB.
+
+The [PS4BT.ino](examples/Bluetooth/PS4BT/PS4BT.ino) and [PS4USB.ino](examples/PS4USB/PS4USB.ino) examples shows how to easily read the buttons, joysticks, touchpad and IMU on the controller via Bluetooth and USB respectively. It is also possible to control the rumble and light on the controller and get the battery level.
+
+Before you can use the PS4 controller via Bluetooth you will need to pair with it.
+
+Simply create the PS4BT instance like so: ```PS4BT PS4(&Btd, PAIR);``` and then hold down the Share button and then hold down the PS without releasing the Share button. The PS4 controller will then start to blink rapidly indicating that it is in paring mode.
+
+It should then automatically pair the dongle with your controller. This only have to be done once.
+
+For information see the following blog post: <http://blog.tkjelectronics.dk/2014/01/ps4-controller-now-supported-by-the-usb-host-library/>.
+
+Also check out this excellent Wiki by Frank Zhao about the PS4 controller: <http://eleccelerator.com/wiki/index.php?title=DualShock_4> and this Linux driver: <https://github.com/chrippa/ds4drv>.
+
+### PS3 Library
+
+These libraries consist of the [PS3BT](PS3BT.cpp) and [PS3USB](PS3USB.cpp). These libraries allows you to use a Dualshock 3, Navigation or a Motion controller with the USB Host Shield both via Bluetooth and USB.
+
+In order to use your Playstation controller via Bluetooth you have to set the Bluetooth address of the dongle internally to your PS3 Controller. This can be achieved by first plugging in the Bluetooth dongle and wait a few seconds. Now plug in the controller via USB and wait until the LEDs start to flash. The library has now written the Bluetooth address of the dongle to the PS3 controller.
+
+Finally simply plug in the Bluetooth dongle again and press PS on the PS3 controller. After a few seconds it should be connected to the dongle and ready to use.
+
+__Note:__ You will have to plug in the Bluetooth dongle before connecting the controller, as the library needs to read the address of the dongle. Alternatively you could set it in code like so: [PS3BT.ino#L20](examples/Bluetooth/PS3BT/PS3BT.ino#L20).
+
+For more information about the PS3 protocol see the official wiki: <https://github.com/felis/USB_Host_Shield_2.0/wiki/PS3-Information>.
+
+Also take a look at the blog posts:
+
+* <http://blog.tkjelectronics.dk/2012/01/ps3-controller-bt-library-for-arduino/>
+* <http://www.circuitsathome.com/mcu/sony-ps3-controller-support-added-to-usb-host-library>
+* <http://www.circuitsathome.com/mcu/arduino/interfacing-ps3-controllers-via-usb>
+
+A special thanks go to the following people:
+
+1. _Richard Ibbotson_ who made this excellent guide: <http://www.circuitsathome.com/mcu/ps3-and-wiimote-game-controllers-on-the-arduino-host-shield-part>
+2. _Tomoyuki Tanaka_ for releasing his code for the Arduino USB Host shield connected to the wiimote: <http://www.circuitsathome.com/mcu/rc-car-controlled-by-wii-remote-on-arduino>
+
+Also a big thanks all the people behind these sites about the Motion controller:
+
+* <http://thp.io/2010/psmove/>
+* <http://www.copenhagengamecollective.org/unimove/>
+* <https://github.com/thp/psmoveapi>
+* <http://code.google.com/p/moveonpc/>
+
+### Xbox Libraries
+
+The library supports both the original Xbox controller via USB and the Xbox 360 controller both via USB and wirelessly.
+
+#### Xbox library
+
+The [XBOXOLD](XBOXOLD.cpp) class implements support for the original Xbox controller via USB.
+
+All the information are from the following sites:
+
+* <https://github.com/torvalds/linux/blob/master/Documentation/input/xpad.txt>
+* <https://github.com/torvalds/linux/blob/master/drivers/input/joystick/xpad.c>
+* <http://euc.jp/periphs/xbox-controller.ja.html>
+* <https://github.com/Grumbel/xboxdrv/blob/master/PROTOCOL#L15>
+
+#### Xbox 360 Library
+
+The library support one Xbox 360 via USB or up to four Xbox 360 controllers wirelessly by using a [Xbox 360 wireless receiver](http://blog.tkjelectronics.dk/wp-content/uploads/xbox360-wireless-receiver.jpg).
+
+To use it via USB use the [XBOXUSB](XBOXUSB.cpp) library or to use it wirelessly use the [XBOXRECV](XBOXRECV.cpp) library.
+
+__Note that a Wireless controller can NOT be used via USB!__
+
+Examples code can be found in the [examples directory](examples/Xbox).
+
+Also see the following blog posts:
+
+* <http://www.circuitsathome.com/mcu/xbox360-controller-support-added-to-usb-host-shield-2-0-library>
+* <http://blog.tkjelectronics.dk/2012/07/xbox-360-controller-support-added-to-the-usb-host-library/>
+* <http://blog.tkjelectronics.dk/2012/12/xbox-360-receiver-added-to-the-usb-host-library/>
+
+All the information regarding the Xbox 360 controller protocol are form these sites:
+
+* <http://tattiebogle.net/index.php/ProjectRoot/Xbox360Controller/UsbInfo>
+* <http://tattiebogle.net/index.php/ProjectRoot/Xbox360Controller/WirelessUsbInfo>
+* <https://github.com/Grumbel/xboxdrv/blob/master/PROTOCOL>
+
+#### Xbox ONE Library
+
+An Xbox ONE controller is supported via USB in the [XBOXONE](XBOXONE.cpp) class. It is heavily based on the 360 library above. In addition to cross referencing the above, information on the protocol was found at:
+
+* <https://github.com/quantus/xbox-one-controller-protocol>
+* <https://github.com/torvalds/linux/blob/master/drivers/input/joystick/xpad.c>
+* <https://github.com/kylelemons/xbox/blob/master/xbox.go>
+
+### [Wii library](Wii.cpp)
+
+The [Wii](Wii.cpp) library support the Wiimote, but also the Nunchuch and Motion Plus extensions via Bluetooth. The Wii U Pro Controller and Wii Balance Board are also supported via Bluetooth.
+
+First you have to pair with the controller, this is done automatically by the library if you create the instance like so:
+
+```C++
+WII Wii(&Btd, PAIR);
+```
+
+And then press 1 & 2 at once on the Wiimote or the SYNC buttons if you are using a Wii U Pro Controller or a Wii Balance Board.
+
+After that you can simply create the instance like so:
+
+```C++
+WII Wii(&Btd);
+```
+
+Then just press any button on the Wiimote and it will then connect to the dongle.
+
+Take a look at the example for more information: [Wii.ino](examples/Bluetooth/Wii/Wii.ino).
+
+Also take a look at the blog post:
+
+* <http://blog.tkjelectronics.dk/2012/08/wiimote-added-to-usb-host-library/>
+
+The Wii IR camera can also be used, but you will have to activate the code for it manually as it is quite large. Simply set ```ENABLE_WII_IR_CAMERA``` to 1 in [settings.h](settings.h).
+
+The [WiiIRCamera.ino](examples/Bluetooth/WiiIRCamera/WiiIRCamera.ino) example shows how it can be used.
+
+All the information about the Wii controllers are from these sites:
+
+* <http://wiibrew.org/wiki/Wiimote>
+* <http://wiibrew.org/wiki/Wiimote/Extension_Controllers>
+* <http://wiibrew.org/wiki/Wiimote/Extension_Controllers/Nunchuck>
+* <http://wiibrew.org/wiki/Wiimote/Extension_Controllers/Wii_Motion_Plus>
+* <http://wiibrew.org/wiki/Wii_Balance_Board>
+* The old library created by _Tomoyuki Tanaka_: <https://github.com/moyuchin/WiiRemote_on_Arduino> also helped a lot.
+
+### [PS Buzz Library](PSBuzz.cpp)
+
+This library implements support for the Playstation Buzz controllers via USB.
+
+It is essentially just a wrapper around the [HIDUniversal](hiduniversal.cpp) which takes care of the initializing and reading of the controllers. The [PSBuzz](PSBuzz.cpp) class simply inherits this and parses the data, so it is easy for users to read the buttons and turn the big red button on the controllers on and off.
+
+The example [PSBuzz.ino](examples/PSBuzz/PSBuzz.ino) shows how one can do this with just a few lines of code.
+
+More information about the controller can be found at the following sites:
+
+* http://www.developerfusion.com/article/84338/making-usb-c-friendly/
+* https://github.com/torvalds/linux/blob/master/drivers/hid/hid-sony.c
+
+# Interface modifications
+
+The shield is using SPI for communicating with the MAX3421E USB host controller. It uses the SCK, MISO and MOSI pins via the ICSP on your board.
+
+Note this means that it uses pin 13, 12, 11 on an Arduino Uno, so these pins can not be used for anything else than SPI communication!
+
+Furthermore it uses one pin as SS and one INT pin. These are by default located on pin 10 and 9 respectively. They can easily be reconfigured in case you need to use them for something else by cutting the jumper on the shield and then solder a wire from the pad to the new pin.
+
+After that you need modify the following entry in [UsbCore.h](UsbCore.h):
+
+```C++
+typedef MAX3421e<P10, P9> MAX3421E;
+```
+
+For instance if you have rerouted SS to pin 7 it should read:
+
+```C++
+typedef MAX3421e<P7, P9> MAX3421E;
+```
+
+See the "Interface modifications" section in the [hardware manual](https://www.circuitsathome.com/usb-host-shield-hardware-manual) for more information.
+
+# FAQ
+
+> When I plug my device into the USB connector nothing happens?
+
+* Try to connect a external power supply to the Arduino - this solves the problem in most cases.
+* You can also use a powered hub between the device and the USB Host Shield. You should then include the USB hub library: ```#include <usbhub.h>``` and create the instance like so: ```USBHub Hub1(&Usb);```.
+
+> When I connecting my PS3 controller I get a output like this:
+
+```
+Dualshock 3 Controller Enabled
+
+LeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0
+LeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0
+LeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0
+LeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0
+LeftHatX: 0 LeftHatY: 0 RightHatX: 0 RightHatY: 0
+```
+
+* This means that your dongle does not support 2.0+EDR, so you will need another dongle. Please see the following [list](https://github.com/felis/USB_Host_Shield_2.0/wiki/Bluetooth-dongles) for tested working dongles.
+
+> When compiling I am getting the following error: "fatal error: SPI.h: No such file or directory".
+
+* Please make sure to include the SPI library like so: ```#include <SPI.h>``` in your .ino file.
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/settings.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/settings.h
new file mode 100644
index 000000000..5c060354b
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/settings.h
@@ -0,0 +1,139 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+
+#ifndef USB_HOST_SHIELD_SETTINGS_H
+#define USB_HOST_SHIELD_SETTINGS_H
+#include "macros.h"
+
+////////////////////////////////////////////////////////////////////////////////
+// DEBUGGING
+////////////////////////////////////////////////////////////////////////////////
+
+/* Set this to 1 to activate serial debugging */
+#define ENABLE_UHS_DEBUGGING 0
+
+/* This can be used to select which serial port to use for debugging if
+ * multiple serial ports are available.
+ * For example Serial3.
+ */
+#ifndef USB_HOST_SERIAL
+#define USB_HOST_SERIAL Serial
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// Manual board activation
+////////////////////////////////////////////////////////////////////////////////
+
+/* Set this to 1 if you are using an Arduino Mega ADK board with MAX3421e built-in */
+#define USE_UHS_MEGA_ADK 0 // If you are using Arduino 1.5.5 or newer there is no need to do this manually
+
+/* Set this to 1 if you are using a Black Widdow */
+#define USE_UHS_BLACK_WIDDOW 0
+
+/* Set this to a one to use the xmem2 lock. This is needed for multitasking and threading */
+#define USE_XMEM_SPI_LOCK 0
+
+////////////////////////////////////////////////////////////////////////////////
+// Wii IR camera
+////////////////////////////////////////////////////////////////////////////////
+
+/* Set this to 1 to activate code for the Wii IR camera */
+#define ENABLE_WII_IR_CAMERA 0
+
+////////////////////////////////////////////////////////////////////////////////
+// MASS STORAGE
+////////////////////////////////////////////////////////////////////////////////
+// <<<<<<<<<<<<<<<< IMPORTANT >>>>>>>>>>>>>>>
+// Set this to 1 to support single LUN devices, and save RAM. -- I.E. thumb drives.
+// Each LUN needs ~13 bytes to be able to track the state of each unit.
+#ifndef MASS_MAX_SUPPORTED_LUN
+#define MASS_MAX_SUPPORTED_LUN 8
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// Set to 1 to use the faster spi4teensy3 driver.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef USE_SPI4TEENSY3
+#define USE_SPI4TEENSY3 1
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+// AUTOMATIC Settings
+////////////////////////////////////////////////////////////////////////////////
+
+// No user serviceable parts below this line.
+// DO NOT change anything below here unless you are a developer!
+
+#include "version_helper.h"
+
+#if defined(__GNUC__) && defined(__AVR__)
+#ifndef GCC_VERSION
+#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+#endif
+#if GCC_VERSION < 40602 // Test for GCC < 4.6.2
+#ifdef PROGMEM
+#undef PROGMEM
+#define PROGMEM __attribute__((section(".progmem.data"))) // Workaround for http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34734#c4
+#ifdef PSTR
+#undef PSTR
+#define PSTR(s) (__extension__({static const char __c[] PROGMEM = (s); &__c[0];})) // Copied from pgmspace.h in avr-libc source
+#endif
+#endif
+#endif
+#endif
+
+#if !defined(DEBUG_USB_HOST) && ENABLE_UHS_DEBUGGING
+#define DEBUG_USB_HOST
+#endif
+
+#if !defined(WIICAMERA) && ENABLE_WII_IR_CAMERA
+#define WIICAMERA
+#endif
+
+// To use some other locking (e.g. freertos),
+// define XMEM_ACQUIRE_SPI and XMEM_RELEASE_SPI to point to your lock and unlock.
+// NOTE: NO argument is passed. You have to do this within your routine for
+// whatever you are using to lock and unlock.
+#if !defined(XMEM_ACQUIRE_SPI)
+#if USE_XMEM_SPI_LOCK || defined(USE_MULTIPLE_APP_API)
+#include <xmem.h>
+#else
+#define XMEM_ACQUIRE_SPI() (void(0))
+#define XMEM_RELEASE_SPI() (void(0))
+#endif
+#endif
+
+#if !defined(EXT_RAM) && defined(EXT_RAM_STACK) || defined(EXT_RAM_HEAP)
+#include <xmem.h>
+#else
+#define EXT_RAM 0
+#endif
+
+#if defined(CORE_TEENSY) && (defined(__MK20DX128__) || defined(__MK20DX256__))
+#define USING_SPI4TEENSY3 USE_SPI4TEENSY3
+#else
+#define USING_SPI4TEENSY3 0
+#endif
+
+#if ((defined(ARDUINO_SAM_DUE) && defined(__SAM3X8E__)) || defined(RBL_NRF51822) || defined(__ARDUINO_X86__) || ARDUINO >= 10600) && !USING_SPI4TEENSY3
+#include <SPI.h> // Use the Arduino SPI library for the Arduino Due, RedBearLab nRF51822, Intel Galileo 1 & 2, Intel Edison or if the SPI library with transaction is available
+#endif
+#if defined(__PIC32MX__) || defined(__PIC32MZ__)
+#include <../../../../hardware/pic32/libraries/SPI/SPI.h> // Hack to use the SPI library
+#endif
+
+#endif /* SETTINGS_H */
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/sink_parser.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/sink_parser.h
new file mode 100644
index 000000000..a23637d2b
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/sink_parser.h
@@ -0,0 +1,41 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+#if !defined(_usb_h_) || defined(__SINK_PARSER_H__)
+#error "Never include hexdump.h directly; include Usb.h instead"
+#else
+#define __SINK_PARSER_H__
+
+extern int UsbDEBUGlvl;
+
+// This parser does absolutely nothing with the data, just swallows it.
+
+template <class BASE_CLASS, class LEN_TYPE, class OFFSET_TYPE>
+class SinkParser : public BASE_CLASS {
+public:
+
+ SinkParser() {
+ };
+
+ void Initialize() {
+ };
+
+ void Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset) {
+ };
+};
+
+
+#endif // __HEXDUMP_H__
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usb_ch9.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usb_ch9.h
new file mode 100644
index 000000000..18f2d3e2e
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usb_ch9.h
@@ -0,0 +1,166 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+
+#if !defined(_usb_h_) || defined(_ch9_h_)
+#error "Never include usb_ch9.h directly; include Usb.h instead"
+#else
+
+/* USB chapter 9 structures */
+#define _ch9_h_
+
+/* Misc.USB constants */
+#define DEV_DESCR_LEN 18 //device descriptor length
+#define CONF_DESCR_LEN 9 //configuration descriptor length
+#define INTR_DESCR_LEN 9 //interface descriptor length
+#define EP_DESCR_LEN 7 //endpoint descriptor length
+
+/* Standard Device Requests */
+
+#define USB_REQUEST_GET_STATUS 0 // Standard Device Request - GET STATUS
+#define USB_REQUEST_CLEAR_FEATURE 1 // Standard Device Request - CLEAR FEATURE
+#define USB_REQUEST_SET_FEATURE 3 // Standard Device Request - SET FEATURE
+#define USB_REQUEST_SET_ADDRESS 5 // Standard Device Request - SET ADDRESS
+#define USB_REQUEST_GET_DESCRIPTOR 6 // Standard Device Request - GET DESCRIPTOR
+#define USB_REQUEST_SET_DESCRIPTOR 7 // Standard Device Request - SET DESCRIPTOR
+#define USB_REQUEST_GET_CONFIGURATION 8 // Standard Device Request - GET CONFIGURATION
+#define USB_REQUEST_SET_CONFIGURATION 9 // Standard Device Request - SET CONFIGURATION
+#define USB_REQUEST_GET_INTERFACE 10 // Standard Device Request - GET INTERFACE
+#define USB_REQUEST_SET_INTERFACE 11 // Standard Device Request - SET INTERFACE
+#define USB_REQUEST_SYNCH_FRAME 12 // Standard Device Request - SYNCH FRAME
+
+#define USB_FEATURE_ENDPOINT_HALT 0 // CLEAR/SET FEATURE - Endpoint Halt
+#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // CLEAR/SET FEATURE - Device remote wake-up
+#define USB_FEATURE_TEST_MODE 2 // CLEAR/SET FEATURE - Test mode
+
+/* Setup Data Constants */
+
+#define USB_SETUP_HOST_TO_DEVICE 0x00 // Device Request bmRequestType transfer direction - host to device transfer
+#define USB_SETUP_DEVICE_TO_HOST 0x80 // Device Request bmRequestType transfer direction - device to host transfer
+#define USB_SETUP_TYPE_STANDARD 0x00 // Device Request bmRequestType type - standard
+#define USB_SETUP_TYPE_CLASS 0x20 // Device Request bmRequestType type - class
+#define USB_SETUP_TYPE_VENDOR 0x40 // Device Request bmRequestType type - vendor
+#define USB_SETUP_RECIPIENT_DEVICE 0x00 // Device Request bmRequestType recipient - device
+#define USB_SETUP_RECIPIENT_INTERFACE 0x01 // Device Request bmRequestType recipient - interface
+#define USB_SETUP_RECIPIENT_ENDPOINT 0x02 // Device Request bmRequestType recipient - endpoint
+#define USB_SETUP_RECIPIENT_OTHER 0x03 // Device Request bmRequestType recipient - other
+
+/* USB descriptors */
+
+#define USB_DESCRIPTOR_DEVICE 0x01 // bDescriptorType for a Device Descriptor.
+#define USB_DESCRIPTOR_CONFIGURATION 0x02 // bDescriptorType for a Configuration Descriptor.
+#define USB_DESCRIPTOR_STRING 0x03 // bDescriptorType for a String Descriptor.
+#define USB_DESCRIPTOR_INTERFACE 0x04 // bDescriptorType for an Interface Descriptor.
+#define USB_DESCRIPTOR_ENDPOINT 0x05 // bDescriptorType for an Endpoint Descriptor.
+#define USB_DESCRIPTOR_DEVICE_QUALIFIER 0x06 // bDescriptorType for a Device Qualifier.
+#define USB_DESCRIPTOR_OTHER_SPEED 0x07 // bDescriptorType for a Other Speed Configuration.
+#define USB_DESCRIPTOR_INTERFACE_POWER 0x08 // bDescriptorType for Interface Power.
+#define USB_DESCRIPTOR_OTG 0x09 // bDescriptorType for an OTG Descriptor.
+
+#define HID_DESCRIPTOR_HID 0x21
+
+
+
+/* OTG SET FEATURE Constants */
+#define OTG_FEATURE_B_HNP_ENABLE 3 // SET FEATURE OTG - Enable B device to perform HNP
+#define OTG_FEATURE_A_HNP_SUPPORT 4 // SET FEATURE OTG - A device supports HNP
+#define OTG_FEATURE_A_ALT_HNP_SUPPORT 5 // SET FEATURE OTG - Another port on the A device supports HNP
+
+/* USB Endpoint Transfer Types */
+#define USB_TRANSFER_TYPE_CONTROL 0x00 // Endpoint is a control endpoint.
+#define USB_TRANSFER_TYPE_ISOCHRONOUS 0x01 // Endpoint is an isochronous endpoint.
+#define USB_TRANSFER_TYPE_BULK 0x02 // Endpoint is a bulk endpoint.
+#define USB_TRANSFER_TYPE_INTERRUPT 0x03 // Endpoint is an interrupt endpoint.
+#define bmUSB_TRANSFER_TYPE 0x03 // bit mask to separate transfer type from ISO attributes
+
+
+/* Standard Feature Selectors for CLEAR_FEATURE Requests */
+#define USB_FEATURE_ENDPOINT_STALL 0 // Endpoint recipient
+#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // Device recipient
+#define USB_FEATURE_TEST_MODE 2 // Device recipient
+
+/* descriptor data structures */
+
+/* Device descriptor structure */
+typedef struct {
+ uint8_t bLength; // Length of this descriptor.
+ uint8_t bDescriptorType; // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE).
+ uint16_t bcdUSB; // USB Spec Release Number (BCD).
+ uint8_t bDeviceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific.
+ uint8_t bDeviceSubClass; // Subclass code (assigned by the USB-IF).
+ uint8_t bDeviceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific.
+ uint8_t bMaxPacketSize0; // Maximum packet size for endpoint 0.
+ uint16_t idVendor; // Vendor ID (assigned by the USB-IF).
+ uint16_t idProduct; // Product ID (assigned by the manufacturer).
+ uint16_t bcdDevice; // Device release number (BCD).
+ uint8_t iManufacturer; // Index of String Descriptor describing the manufacturer.
+ uint8_t iProduct; // Index of String Descriptor describing the product.
+ uint8_t iSerialNumber; // Index of String Descriptor with the device's serial number.
+ uint8_t bNumConfigurations; // Number of possible configurations.
+} __attribute__((packed)) USB_DEVICE_DESCRIPTOR;
+
+/* Configuration descriptor structure */
+typedef struct {
+ uint8_t bLength; // Length of this descriptor.
+ uint8_t bDescriptorType; // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION).
+ uint16_t wTotalLength; // Total length of all descriptors for this configuration.
+ uint8_t bNumInterfaces; // Number of interfaces in this configuration.
+ uint8_t bConfigurationValue; // Value of this configuration (1 based).
+ uint8_t iConfiguration; // Index of String Descriptor describing the configuration.
+ uint8_t bmAttributes; // Configuration characteristics.
+ uint8_t bMaxPower; // Maximum power consumed by this configuration.
+} __attribute__((packed)) USB_CONFIGURATION_DESCRIPTOR;
+
+/* Interface descriptor structure */
+typedef struct {
+ uint8_t bLength; // Length of this descriptor.
+ uint8_t bDescriptorType; // INTERFACE descriptor type (USB_DESCRIPTOR_INTERFACE).
+ uint8_t bInterfaceNumber; // Number of this interface (0 based).
+ uint8_t bAlternateSetting; // Value of this alternate interface setting.
+ uint8_t bNumEndpoints; // Number of endpoints in this interface.
+ uint8_t bInterfaceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific.
+ uint8_t bInterfaceSubClass; // Subclass code (assigned by the USB-IF).
+ uint8_t bInterfaceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific.
+ uint8_t iInterface; // Index of String Descriptor describing the interface.
+} __attribute__((packed)) USB_INTERFACE_DESCRIPTOR;
+
+/* Endpoint descriptor structure */
+typedef struct {
+ uint8_t bLength; // Length of this descriptor.
+ uint8_t bDescriptorType; // ENDPOINT descriptor type (USB_DESCRIPTOR_ENDPOINT).
+ uint8_t bEndpointAddress; // Endpoint address. Bit 7 indicates direction (0=OUT, 1=IN).
+ uint8_t bmAttributes; // Endpoint transfer type.
+ uint16_t wMaxPacketSize; // Maximum packet size.
+ uint8_t bInterval; // Polling interval in frames.
+} __attribute__((packed)) USB_ENDPOINT_DESCRIPTOR;
+
+/* HID descriptor */
+typedef struct {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint16_t bcdHID; // HID class specification release
+ uint8_t bCountryCode;
+ uint8_t bNumDescriptors; // Number of additional class specific descriptors
+ uint8_t bDescrType; // Type of class descriptor
+ uint16_t wDescriptorLength; // Total size of the Report descriptor
+} __attribute__((packed)) USB_HID_DESCRIPTOR;
+
+typedef struct {
+ uint8_t bDescrType; // Type of class descriptor
+ uint16_t wDescriptorLength; // Total size of the Report descriptor
+} __attribute__((packed)) HID_CLASS_DESCRIPTOR_LEN_AND_TYPE;
+
+#endif // _ch9_h_
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usbhost.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usbhost.h
new file mode 100644
index 000000000..eba480e60
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usbhost.h
@@ -0,0 +1,529 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+/* MAX3421E-based USB Host Library header file */
+
+
+#if !defined(_usb_h_) || defined(_USBHOST_H_)
+#error "Never include usbhost.h directly; include Usb.h instead"
+#else
+#define _USBHOST_H_
+
+#if USING_SPI4TEENSY3
+#include <spi4teensy3.h>
+#include <sys/types.h>
+#endif
+
+/* SPI initialization */
+template< typename SPI_CLK, typename SPI_MOSI, typename SPI_MISO, typename SPI_SS > class SPi {
+public:
+#if USING_SPI4TEENSY3
+ static void init() {
+ // spi4teensy3 inits everything for us, except /SS
+ // CLK, MOSI and MISO are hard coded for now.
+ // spi4teensy3::init(0,0,0); // full speed, cpol 0, cpha 0
+ spi4teensy3::init(); // full speed, cpol 0, cpha 0
+ SPI_SS::SetDirWrite();
+ SPI_SS::Set();
+ }
+#elif SPI_HAS_TRANSACTION
+ static void init() {
+ SPI.begin(); // The SPI library with transaction will take care of setting up the pins - settings is set in beginTransaction()
+ }
+#elif !defined(SPDR)
+ static void init() {
+ SPI_SS::SetDirWrite();
+ SPI_SS::Set();
+ SPI.begin();
+#if defined(__MIPSEL__)
+ SPI.setClockDivider(1);
+#elif defined(__ARDUINO_X86__)
+ #ifdef SPI_CLOCK_1M // Hack used to check if setClockSpeed is available
+ SPI.setClockSpeed(12000000); // The MAX3421E can handle up to 26MHz, but in practice this was the maximum that I could reliably use
+ #else
+ SPI.setClockDivider(SPI_CLOCK_DIV2); // This will set the SPI frequency to 8MHz - it could be higher, but it is not supported in the old API
+ #endif
+#else
+ SPI.setClockDivider(4); // Set speed to 84MHz/4=21MHz - the MAX3421E can handle up to 26MHz
+#endif
+ }
+#elif defined(RBL_NRF51822)
+ static void init() {
+ SPI_SS::SetDirWrite();
+ SPI_SS::Set();
+ SPI.begin();
+ // SPI.setFrequency(SPI_FREQUENCY_8M);
+ }
+#else
+ static void init() {
+ //uint8_t tmp;
+ SPI_CLK::SetDirWrite();
+ SPI_MOSI::SetDirWrite();
+ SPI_MISO::SetDirRead();
+ SPI_SS::SetDirWrite();
+ /* mode 00 (CPOL=0, CPHA=0) master, fclk/2. Mode 11 (CPOL=11, CPHA=11) is also supported by MAX3421E */
+ SPCR = 0x50;
+ SPSR = 0x01; // 0x01
+ /**/
+ //tmp = SPSR;
+ //tmp = SPDR;
+ }
+#endif
+};
+
+/* SPI pin definitions. see avrpins.h */
+#if defined(__AVR_ATmega1280__) || (__AVR_ATmega2560__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
+typedef SPi< Pb1, Pb2, Pb3, Pb0 > spi;
+#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
+typedef SPi< Pb5, Pb3, Pb4, Pb2 > spi;
+#elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__)
+typedef SPi< Pb7, Pb5, Pb6, Pb4 > spi;
+#elif (defined(CORE_TEENSY) && (defined(__MK20DX128__) || defined(__MK20DX256__))) || defined(__ARDUINO_X86__) || defined(__MIPSEL__)
+typedef SPi< P13, P11, P12, P10 > spi;
+#elif defined(ARDUINO_SAM_DUE) && defined(__SAM3X8E__)
+typedef SPi< P76, P75, P74, P10 > spi;
+#elif defined(RBL_NRF51822)
+typedef SPi< P16, P18, P17, P10 > spi;
+#else
+#error "No SPI entry in usbhost.h"
+#endif
+
+typedef enum {
+ vbus_on = 0,
+ vbus_off = GPX_VBDET
+} VBUS_t;
+
+template< typename SPI_SS, typename INTR > class MAX3421e /* : public spi */ {
+ static uint8_t vbusState;
+
+public:
+ MAX3421e();
+ void regWr(uint8_t reg, uint8_t data);
+ uint8_t* bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* data_p);
+ void gpioWr(uint8_t data);
+ uint8_t regRd(uint8_t reg);
+ uint8_t* bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* data_p);
+ uint8_t gpioRd();
+ uint16_t reset();
+ int8_t Init();
+ int8_t Init(int mseconds);
+
+ void vbusPower(VBUS_t state) {
+ regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL | state));
+ }
+
+ uint8_t getVbusState(void) {
+ return vbusState;
+ };
+ void busprobe();
+ uint8_t GpxHandler();
+ uint8_t IntHandler();
+ uint8_t Task();
+};
+
+template< typename SPI_SS, typename INTR >
+ uint8_t MAX3421e< SPI_SS, INTR >::vbusState = 0;
+
+/* constructor */
+template< typename SPI_SS, typename INTR >
+MAX3421e< SPI_SS, INTR >::MAX3421e() {
+ // Leaving ADK hardware setup in here, for now. This really belongs with the other parts.
+#ifdef BOARD_MEGA_ADK
+ // For Mega ADK, which has a Max3421e on-board, set MAX_RESET to output mode, and then set it to HIGH
+ P55::SetDirWrite();
+ P55::Set();
+#endif
+};
+
+/* write single byte into MAX3421 register */
+template< typename SPI_SS, typename INTR >
+void MAX3421e< SPI_SS, INTR >::regWr(uint8_t reg, uint8_t data) {
+ XMEM_ACQUIRE_SPI();
+#if SPI_HAS_TRANSACTION
+ SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0
+#endif
+ SPI_SS::Clear();
+
+#if USING_SPI4TEENSY3
+ uint8_t c[2];
+ c[0] = reg | 0x02;
+ c[1] = data;
+ spi4teensy3::send(c, 2);
+#elif SPI_HAS_TRANSACTION
+ uint8_t c[2];
+ c[0] = reg | 0x02;
+ c[1] = data;
+ SPI.transfer(c, 2);
+#elif !defined(SPDR)
+ SPI.transfer(reg | 0x02);
+ SPI.transfer(data);
+#else
+ SPDR = (reg | 0x02);
+ while(!(SPSR & (1 << SPIF)));
+ SPDR = data;
+ while(!(SPSR & (1 << SPIF)));
+#endif
+
+ SPI_SS::Set();
+#if SPI_HAS_TRANSACTION
+ SPI.endTransaction();
+#endif
+ XMEM_RELEASE_SPI();
+ return;
+};
+/* multiple-byte write */
+
+/* returns a pointer to memory position after last written */
+template< typename SPI_SS, typename INTR >
+uint8_t* MAX3421e< SPI_SS, INTR >::bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* data_p) {
+ XMEM_ACQUIRE_SPI();
+#if SPI_HAS_TRANSACTION
+ SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0
+#endif
+ SPI_SS::Clear();
+
+#if USING_SPI4TEENSY3
+ spi4teensy3::send(reg | 0x02);
+ spi4teensy3::send(data_p, nbytes);
+ data_p += nbytes;
+#elif SPI_HAS_TRANSACTION
+ SPI.transfer(reg | 0x02);
+ SPI.transfer(data_p, nbytes);
+ data_p += nbytes;
+#elif defined(__ARDUINO_X86__)
+ SPI.transfer(reg | 0x02);
+ SPI.transferBuffer(data_p, NULL, nbytes);
+ data_p += nbytes;
+#elif !defined(SPDR)
+ SPI.transfer(reg | 0x02);
+ while(nbytes) {
+ SPI.transfer(*data_p);
+ nbytes--;
+ data_p++; // advance data pointer
+ }
+#else
+ SPDR = (reg | 0x02); //set WR bit and send register number
+ while(nbytes) {
+ while(!(SPSR & (1 << SPIF))); //check if previous byte was sent
+ SPDR = (*data_p); // send next data byte
+ nbytes--;
+ data_p++; // advance data pointer
+ }
+ while(!(SPSR & (1 << SPIF)));
+#endif
+
+ SPI_SS::Set();
+#if SPI_HAS_TRANSACTION
+ SPI.endTransaction();
+#endif
+ XMEM_RELEASE_SPI();
+ return ( data_p);
+}
+/* GPIO write */
+/*GPIO byte is split between 2 registers, so two writes are needed to write one byte */
+
+/* GPOUT bits are in the low nibble. 0-3 in IOPINS1, 4-7 in IOPINS2 */
+template< typename SPI_SS, typename INTR >
+void MAX3421e< SPI_SS, INTR >::gpioWr(uint8_t data) {
+ regWr(rIOPINS1, data);
+ data >>= 4;
+ regWr(rIOPINS2, data);
+ return;
+}
+
+/* single host register read */
+template< typename SPI_SS, typename INTR >
+uint8_t MAX3421e< SPI_SS, INTR >::regRd(uint8_t reg) {
+ XMEM_ACQUIRE_SPI();
+#if SPI_HAS_TRANSACTION
+ SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0
+#endif
+ SPI_SS::Clear();
+
+#if USING_SPI4TEENSY3
+ spi4teensy3::send(reg);
+ uint8_t rv = spi4teensy3::receive();
+ SPI_SS::Set();
+#elif !defined(SPDR) || SPI_HAS_TRANSACTION
+ SPI.transfer(reg);
+ uint8_t rv = SPI.transfer(0); // Send empty byte
+ SPI_SS::Set();
+#else
+ SPDR = reg;
+ while(!(SPSR & (1 << SPIF)));
+ SPDR = 0; // Send empty byte
+ while(!(SPSR & (1 << SPIF)));
+ SPI_SS::Set();
+ uint8_t rv = SPDR;
+#endif
+
+#if SPI_HAS_TRANSACTION
+ SPI.endTransaction();
+#endif
+ XMEM_RELEASE_SPI();
+ return (rv);
+}
+/* multiple-byte register read */
+
+/* returns a pointer to a memory position after last read */
+template< typename SPI_SS, typename INTR >
+uint8_t* MAX3421e< SPI_SS, INTR >::bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* data_p) {
+ XMEM_ACQUIRE_SPI();
+#if SPI_HAS_TRANSACTION
+ SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0
+#endif
+ SPI_SS::Clear();
+
+#if USING_SPI4TEENSY3
+ spi4teensy3::send(reg);
+ spi4teensy3::receive(data_p, nbytes);
+ data_p += nbytes;
+#elif SPI_HAS_TRANSACTION
+ SPI.transfer(reg);
+ memset(data_p, 0, nbytes); // Make sure we send out empty bytes
+ SPI.transfer(data_p, nbytes);
+ data_p += nbytes;
+#elif defined(__ARDUINO_X86__)
+ SPI.transfer(reg);
+ SPI.transferBuffer(NULL, data_p, nbytes);
+ data_p += nbytes;
+#elif !defined(SPDR)
+ SPI.transfer(reg);
+ while(nbytes) {
+ *data_p++ = SPI.transfer(0);
+ nbytes--;
+ }
+#else
+ SPDR = reg;
+ while(!(SPSR & (1 << SPIF))); //wait
+ while(nbytes) {
+ SPDR = 0; // Send empty byte
+ nbytes--;
+ while(!(SPSR & (1 << SPIF)));
+#if 0
+ {
+ *data_p = SPDR;
+ printf("%2.2x ", *data_p);
+ }
+ data_p++;
+ }
+ printf("\r\n");
+#else
+ *data_p++ = SPDR;
+ }
+#endif
+#endif
+
+ SPI_SS::Set();
+#if SPI_HAS_TRANSACTION
+ SPI.endTransaction();
+#endif
+ XMEM_RELEASE_SPI();
+ return ( data_p);
+}
+/* GPIO read. See gpioWr for explanation */
+
+/* GPIN pins are in high nibbles of IOPINS1, IOPINS2 */
+template< typename SPI_SS, typename INTR >
+uint8_t MAX3421e< SPI_SS, INTR >::gpioRd() {
+ uint8_t gpin = 0;
+ gpin = regRd(rIOPINS2); //pins 4-7
+ gpin &= 0xf0; //clean lower nibble
+ gpin |= (regRd(rIOPINS1) >> 4); //shift low bits and OR with upper from previous operation.
+ return ( gpin);
+}
+
+/* reset MAX3421E. Returns number of cycles it took for PLL to stabilize after reset
+ or zero if PLL haven't stabilized in 65535 cycles */
+template< typename SPI_SS, typename INTR >
+uint16_t MAX3421e< SPI_SS, INTR >::reset() {
+ uint16_t i = 0;
+ regWr(rUSBCTL, bmCHIPRES);
+ regWr(rUSBCTL, 0x00);
+ while(++i) {
+ if((regRd(rUSBIRQ) & bmOSCOKIRQ)) {
+ break;
+ }
+ }
+ return ( i);
+}
+
+/* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */
+template< typename SPI_SS, typename INTR >
+int8_t MAX3421e< SPI_SS, INTR >::Init() {
+ XMEM_ACQUIRE_SPI();
+ // Moved here.
+ // you really should not init hardware in the constructor when it involves locks.
+ // Also avoids the vbus flicker issue confusing some devices.
+ /* pin and peripheral setup */
+ SPI_SS::SetDirWrite();
+ SPI_SS::Set();
+ spi::init();
+ INTR::SetDirRead();
+ XMEM_RELEASE_SPI();
+ /* MAX3421E - full-duplex SPI, level interrupt */
+ // GPX pin on. Moved here, otherwise we flicker the vbus.
+ regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL));
+
+ if(reset() == 0) { //OSCOKIRQ hasn't asserted in time
+ return ( -1);
+ }
+
+ regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); // set pull-downs, Host
+
+ regWr(rHIEN, bmCONDETIE | bmFRAMEIE); //connection detection
+
+ /* check if device is connected */
+ regWr(rHCTL, bmSAMPLEBUS); // sample USB bus
+ while(!(regRd(rHCTL) & bmSAMPLEBUS)); //wait for sample operation to finish
+
+ busprobe(); //check if anything is connected
+
+ regWr(rHIRQ, bmCONDETIRQ); //clear connection detect interrupt
+ regWr(rCPUCTL, 0x01); //enable interrupt pin
+
+ return ( 0);
+}
+
+/* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */
+template< typename SPI_SS, typename INTR >
+int8_t MAX3421e< SPI_SS, INTR >::Init(int mseconds) {
+ XMEM_ACQUIRE_SPI();
+ // Moved here.
+ // you really should not init hardware in the constructor when it involves locks.
+ // Also avoids the vbus flicker issue confusing some devices.
+ /* pin and peripheral setup */
+ SPI_SS::SetDirWrite();
+ SPI_SS::Set();
+ spi::init();
+ INTR::SetDirRead();
+ XMEM_RELEASE_SPI();
+ /* MAX3421E - full-duplex SPI, level interrupt, vbus off */
+ regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL | GPX_VBDET));
+
+ if(reset() == 0) { //OSCOKIRQ hasn't asserted in time
+ return ( -1);
+ }
+
+ // Delay a minimum of 1 second to ensure any capacitors are drained.
+ // 1 second is required to make sure we do not smoke a Microdrive!
+ if(mseconds < 1000) mseconds = 1000;
+ delay(mseconds);
+
+ regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); // set pull-downs, Host
+
+ regWr(rHIEN, bmCONDETIE | bmFRAMEIE); //connection detection
+
+ /* check if device is connected */
+ regWr(rHCTL, bmSAMPLEBUS); // sample USB bus
+ while(!(regRd(rHCTL) & bmSAMPLEBUS)); //wait for sample operation to finish
+
+ busprobe(); //check if anything is connected
+
+ regWr(rHIRQ, bmCONDETIRQ); //clear connection detect interrupt
+ regWr(rCPUCTL, 0x01); //enable interrupt pin
+
+ // GPX pin on. This is done here so that busprobe will fail if we have a switch connected.
+ regWr(rPINCTL, (bmFDUPSPI | bmINTLEVEL));
+
+ return ( 0);
+}
+
+/* probe bus to determine device presence and speed and switch host to this speed */
+template< typename SPI_SS, typename INTR >
+void MAX3421e< SPI_SS, INTR >::busprobe() {
+ uint8_t bus_sample;
+ bus_sample = regRd(rHRSL); //Get J,K status
+ bus_sample &= (bmJSTATUS | bmKSTATUS); //zero the rest of the byte
+ switch(bus_sample) { //start full-speed or low-speed host
+ case( bmJSTATUS):
+ if((regRd(rMODE) & bmLOWSPEED) == 0) {
+ regWr(rMODE, MODE_FS_HOST); //start full-speed host
+ vbusState = FSHOST;
+ } else {
+ regWr(rMODE, MODE_LS_HOST); //start low-speed host
+ vbusState = LSHOST;
+ }
+ break;
+ case( bmKSTATUS):
+ if((regRd(rMODE) & bmLOWSPEED) == 0) {
+ regWr(rMODE, MODE_LS_HOST); //start low-speed host
+ vbusState = LSHOST;
+ } else {
+ regWr(rMODE, MODE_FS_HOST); //start full-speed host
+ vbusState = FSHOST;
+ }
+ break;
+ case( bmSE1): //illegal state
+ vbusState = SE1;
+ break;
+ case( bmSE0): //disconnected state
+ regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST | bmSEPIRQ);
+ vbusState = SE0;
+ break;
+ }//end switch( bus_sample )
+}
+
+/* MAX3421 state change task and interrupt handler */
+template< typename SPI_SS, typename INTR >
+uint8_t MAX3421e< SPI_SS, INTR >::Task(void) {
+ uint8_t rcode = 0;
+ uint8_t pinvalue;
+ //USB_HOST_SERIAL.print("Vbus state: ");
+ //USB_HOST_SERIAL.println( vbusState, HEX );
+ pinvalue = INTR::IsSet(); //Read();
+ //pinvalue = digitalRead( MAX_INT );
+ if(pinvalue == 0) {
+ rcode = IntHandler();
+ }
+ // pinvalue = digitalRead( MAX_GPX );
+ // if( pinvalue == LOW ) {
+ // GpxHandler();
+ // }
+ // usbSM(); //USB state machine
+ return ( rcode);
+}
+
+template< typename SPI_SS, typename INTR >
+uint8_t MAX3421e< SPI_SS, INTR >::IntHandler() {
+ uint8_t HIRQ;
+ uint8_t HIRQ_sendback = 0x00;
+ HIRQ = regRd(rHIRQ); //determine interrupt source
+ //if( HIRQ & bmFRAMEIRQ ) { //->1ms SOF interrupt handler
+ // HIRQ_sendback |= bmFRAMEIRQ;
+ //}//end FRAMEIRQ handling
+ if(HIRQ & bmCONDETIRQ) {
+ busprobe();
+ HIRQ_sendback |= bmCONDETIRQ;
+ }
+ /* End HIRQ interrupts handling, clear serviced IRQs */
+ regWr(rHIRQ, HIRQ_sendback);
+ return ( HIRQ_sendback);
+}
+//template< typename SPI_SS, typename INTR >
+//uint8_t MAX3421e< SPI_SS, INTR >::GpxHandler()
+//{
+// uint8_t GPINIRQ = regRd( rGPINIRQ ); //read GPIN IRQ register
+//// if( GPINIRQ & bmGPINIRQ7 ) { //vbus overload
+//// vbusPwr( OFF ); //attempt powercycle
+//// delay( 1000 );
+//// vbusPwr( ON );
+//// regWr( rGPINIRQ, bmGPINIRQ7 );
+//// }
+// return( GPINIRQ );
+//}
+
+#endif // _USBHOST_H_
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usbhub.cpp b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usbhub.cpp
new file mode 100644
index 000000000..7fed48e78
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usbhub.cpp
@@ -0,0 +1,425 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+#include "usbhub.h"
+
+bool USBHub::bResetInitiated = false;
+
+USBHub::USBHub(USB *p) :
+pUsb(p),
+bAddress(0),
+bNbrPorts(0),
+//bInitState(0),
+qNextPollTime(0),
+bPollEnable(false) {
+ epInfo[0].epAddr = 0;
+ epInfo[0].maxPktSize = 8;
+ epInfo[0].epAttribs = 0;
+ epInfo[0].bmNakPower = USB_NAK_MAX_POWER;
+
+ epInfo[1].epAddr = 1;
+ epInfo[1].maxPktSize = 8; //kludge
+ epInfo[1].epAttribs = 0;
+ epInfo[1].bmNakPower = USB_NAK_NOWAIT;
+
+ if(pUsb)
+ pUsb->RegisterDeviceClass(this);
+}
+
+uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed) {
+ uint8_t buf[32];
+ USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
+ HubDescriptor* hd = reinterpret_cast<HubDescriptor*>(buf);
+ USB_CONFIGURATION_DESCRIPTOR * ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR*>(buf);
+ uint8_t rcode;
+ UsbDevice *p = NULL;
+ EpInfo *oldep_ptr = NULL;
+ uint8_t len = 0;
+ uint16_t cd_len = 0;
+
+ //USBTRACE("\r\nHub Init Start ");
+ //D_PrintHex<uint8_t > (bInitState, 0x80);
+
+ AddressPool &addrPool = pUsb->GetAddressPool();
+
+ //switch (bInitState) {
+ // case 0:
+ if(bAddress)
+ return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
+
+ // Get pointer to pseudo device with address 0 assigned
+ p = addrPool.GetUsbDevicePtr(0);
+
+ if(!p)
+ return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
+
+ if(!p->epinfo)
+ return USB_ERROR_EPINFO_IS_NULL;
+
+ // Save old pointer to EP_RECORD of address 0
+ oldep_ptr = p->epinfo;
+
+ // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
+ p->epinfo = epInfo;
+
+ p->lowspeed = lowspeed;
+
+ // Get device descriptor
+ rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf);
+
+ p->lowspeed = false;
+
+ if(!rcode)
+ len = (buf[0] > 32) ? 32 : buf[0];
+
+ if(rcode) {
+ // Restore p->epinfo
+ p->epinfo = oldep_ptr;
+ return rcode;
+ }
+
+ // Extract device class from device descriptor
+ // If device class is not a hub return
+ if(udd->bDeviceClass != 0x09)
+ return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
+
+ // Allocate new address according to device class
+ bAddress = addrPool.AllocAddress(parent, (udd->bDeviceClass == 0x09) ? true : false, port);
+
+ if(!bAddress)
+ return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
+
+ // Extract Max Packet Size from the device descriptor
+ epInfo[0].maxPktSize = udd->bMaxPacketSize0;
+
+ // Assign new address to the device
+ rcode = pUsb->setAddr(0, 0, bAddress);
+
+ if(rcode) {
+ // Restore p->epinfo
+ p->epinfo = oldep_ptr;
+ addrPool.FreeAddress(bAddress);
+ bAddress = 0;
+ return rcode;
+ }
+
+ //USBTRACE2("\r\nHub address: ", bAddress );
+
+ // Restore p->epinfo
+ p->epinfo = oldep_ptr;
+
+ if(len)
+ rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf);
+
+ if(rcode)
+ goto FailGetDevDescr;
+
+ // Assign epInfo to epinfo pointer
+ rcode = pUsb->setEpInfoEntry(bAddress, 2, epInfo);
+
+ if(rcode)
+ goto FailSetDevTblEntry;
+
+ // bInitState = 1;
+
+ // case 1:
+ // Get hub descriptor
+ rcode = GetHubDescriptor(0, 8, buf);
+
+ if(rcode)
+ goto FailGetHubDescr;
+
+ // Save number of ports for future use
+ bNbrPorts = hd->bNbrPorts;
+
+ // bInitState = 2;
+
+ // case 2:
+ // Read configuration Descriptor in Order To Obtain Proper Configuration Value
+ rcode = pUsb->getConfDescr(bAddress, 0, 8, 0, buf);
+
+ if(!rcode) {
+ cd_len = ucd->wTotalLength;
+ rcode = pUsb->getConfDescr(bAddress, 0, cd_len, 0, buf);
+ }
+ if(rcode)
+ goto FailGetConfDescr;
+
+ // The following code is of no practical use in real life applications.
+ // It only intended for the usb protocol sniffer to properly parse hub-class requests.
+ {
+ uint8_t buf2[24];
+
+ rcode = pUsb->getConfDescr(bAddress, 0, buf[0], 0, buf2);
+
+ if(rcode)
+ goto FailGetConfDescr;
+ }
+
+ // Set Configuration Value
+ rcode = pUsb->setConf(bAddress, 0, buf[5]);
+
+ if(rcode)
+ goto FailSetConfDescr;
+
+ // bInitState = 3;
+
+ // case 3:
+ // Power on all ports
+ for(uint8_t j = 1; j <= bNbrPorts; j++)
+ SetPortFeature(HUB_FEATURE_PORT_POWER, j, 0); //HubPortPowerOn(j);
+
+ pUsb->SetHubPreMask();
+ bPollEnable = true;
+ // bInitState = 0;
+ //}
+ //bInitState = 0;
+ //USBTRACE("...OK\r\n");
+ return 0;
+
+ // Oleg, No debugging?? -- xxxajk
+FailGetDevDescr:
+ goto Fail;
+
+FailSetDevTblEntry:
+ goto Fail;
+
+FailGetHubDescr:
+ goto Fail;
+
+FailGetConfDescr:
+ goto Fail;
+
+FailSetConfDescr:
+ goto Fail;
+
+Fail:
+ USBTRACE("...FAIL\r\n");
+ return rcode;
+}
+
+uint8_t USBHub::Release() {
+ pUsb->GetAddressPool().FreeAddress(bAddress);
+
+ if(bAddress == 0x41)
+ pUsb->SetHubPreMask();
+
+ bAddress = 0;
+ bNbrPorts = 0;
+ qNextPollTime = 0;
+ bPollEnable = false;
+ return 0;
+}
+
+uint8_t USBHub::Poll() {
+ uint8_t rcode = 0;
+
+ if(!bPollEnable)
+ return 0;
+
+ if(((long)(millis() - qNextPollTime) >= 0L)) {
+ rcode = CheckHubStatus();
+ qNextPollTime = millis() + 100;
+ }
+ return rcode;
+}
+
+uint8_t USBHub::CheckHubStatus() {
+ uint8_t rcode;
+ uint8_t buf[8];
+ uint16_t read = 1;
+
+ rcode = pUsb->inTransfer(bAddress, 1, &read, buf);
+
+ if(rcode)
+ return rcode;
+
+ //if (buf[0] & 0x01) // Hub Status Change
+ //{
+ // pUsb->PrintHubStatus(addr);
+ // rcode = GetHubStatus(1, 0, 1, 4, buf);
+ // if (rcode)
+ // {
+ // USB_HOST_SERIAL.print("GetHubStatus Error");
+ // USB_HOST_SERIAL.println(rcode, HEX);
+ // return rcode;
+ // }
+ //}
+ for(uint8_t port = 1, mask = 0x02; port < 8; mask <<= 1, port++) {
+ if(buf[0] & mask) {
+ HubEvent evt;
+ evt.bmEvent = 0;
+
+ rcode = GetPortStatus(port, 4, evt.evtBuff);
+
+ if(rcode)
+ continue;
+
+ rcode = PortStatusChange(port, evt);
+
+ if(rcode == HUB_ERROR_PORT_HAS_BEEN_RESET)
+ return 0;
+
+ if(rcode)
+ return rcode;
+ }
+ } // for
+
+ for(uint8_t port = 1; port <= bNbrPorts; port++) {
+ HubEvent evt;
+ evt.bmEvent = 0;
+
+ rcode = GetPortStatus(port, 4, evt.evtBuff);
+
+ if(rcode)
+ continue;
+
+ if((evt.bmStatus & bmHUB_PORT_STATE_CHECK_DISABLED) != bmHUB_PORT_STATE_DISABLED)
+ continue;
+
+ // Emulate connection event for the port
+ evt.bmChange |= bmHUB_PORT_STATUS_C_PORT_CONNECTION;
+
+ rcode = PortStatusChange(port, evt);
+
+ if(rcode == HUB_ERROR_PORT_HAS_BEEN_RESET)
+ return 0;
+
+ if(rcode)
+ return rcode;
+ } // for
+ return 0;
+}
+
+void USBHub::ResetHubPort(uint8_t port) {
+ HubEvent evt;
+ evt.bmEvent = 0;
+ uint8_t rcode;
+
+ ClearPortFeature(HUB_FEATURE_C_PORT_ENABLE, port, 0);
+ ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0);
+ SetPortFeature(HUB_FEATURE_PORT_RESET, port, 0);
+
+
+ for(int i = 0; i < 3; i++) {
+ rcode = GetPortStatus(port, 4, evt.evtBuff);
+ if(rcode) break; // Some kind of error, bail.
+ if(evt.bmEvent == bmHUB_PORT_EVENT_RESET_COMPLETE || evt.bmEvent == bmHUB_PORT_EVENT_LS_RESET_COMPLETE) {
+ break;
+ }
+ delay(100); // simulate polling.
+ }
+ ClearPortFeature(HUB_FEATURE_C_PORT_RESET, port, 0);
+ ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0);
+ delay(20);
+}
+
+uint8_t USBHub::PortStatusChange(uint8_t port, HubEvent &evt) {
+ switch(evt.bmEvent) {
+ // Device connected event
+ case bmHUB_PORT_EVENT_CONNECT:
+ case bmHUB_PORT_EVENT_LS_CONNECT:
+ if(bResetInitiated)
+ return 0;
+
+ ClearPortFeature(HUB_FEATURE_C_PORT_ENABLE, port, 0);
+ ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0);
+ SetPortFeature(HUB_FEATURE_PORT_RESET, port, 0);
+ bResetInitiated = true;
+ return HUB_ERROR_PORT_HAS_BEEN_RESET;
+
+ // Device disconnected event
+ case bmHUB_PORT_EVENT_DISCONNECT:
+ ClearPortFeature(HUB_FEATURE_C_PORT_ENABLE, port, 0);
+ ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0);
+ bResetInitiated = false;
+
+ UsbDeviceAddress a;
+ a.devAddress = 0;
+ a.bmHub = 0;
+ a.bmParent = bAddress;
+ a.bmAddress = port;
+ pUsb->ReleaseDevice(a.devAddress);
+ return 0;
+
+ // Reset complete event
+ case bmHUB_PORT_EVENT_RESET_COMPLETE:
+ case bmHUB_PORT_EVENT_LS_RESET_COMPLETE:
+ ClearPortFeature(HUB_FEATURE_C_PORT_RESET, port, 0);
+ ClearPortFeature(HUB_FEATURE_C_PORT_CONNECTION, port, 0);
+
+ delay(20);
+
+ a.devAddress = bAddress;
+
+ pUsb->Configuring(a.bmAddress, port, (evt.bmStatus & bmHUB_PORT_STATUS_PORT_LOW_SPEED));
+ bResetInitiated = false;
+ break;
+
+ } // switch (evt.bmEvent)
+ return 0;
+}
+
+void PrintHubPortStatus(USBHub *hubptr, uint8_t addr, uint8_t port, bool print_changes) {
+ uint8_t rcode = 0;
+ HubEvent evt;
+
+ rcode = hubptr->GetPortStatus(port, 4, evt.evtBuff);
+
+ if(rcode) {
+ USB_HOST_SERIAL.println("ERROR!");
+ return;
+ }
+ USB_HOST_SERIAL.print("\r\nPort ");
+ USB_HOST_SERIAL.println(port, DEC);
+
+ USB_HOST_SERIAL.println("Status");
+ USB_HOST_SERIAL.print("CONNECTION:\t");
+ USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_CONNECTION) > 0, DEC);
+ USB_HOST_SERIAL.print("ENABLE:\t\t");
+ USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_ENABLE) > 0, DEC);
+ USB_HOST_SERIAL.print("SUSPEND:\t");
+ USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_SUSPEND) > 0, DEC);
+ USB_HOST_SERIAL.print("OVER_CURRENT:\t");
+ USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_OVER_CURRENT) > 0, DEC);
+ USB_HOST_SERIAL.print("RESET:\t\t");
+ USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_RESET) > 0, DEC);
+ USB_HOST_SERIAL.print("POWER:\t\t");
+ USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_POWER) > 0, DEC);
+ USB_HOST_SERIAL.print("LOW_SPEED:\t");
+ USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_LOW_SPEED) > 0, DEC);
+ USB_HOST_SERIAL.print("HIGH_SPEED:\t");
+ USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_HIGH_SPEED) > 0, DEC);
+ USB_HOST_SERIAL.print("TEST:\t\t");
+ USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_TEST) > 0, DEC);
+ USB_HOST_SERIAL.print("INDICATOR:\t");
+ USB_HOST_SERIAL.println((evt.bmStatus & bmHUB_PORT_STATUS_PORT_INDICATOR) > 0, DEC);
+
+ if(!print_changes)
+ return;
+
+ USB_HOST_SERIAL.println("\r\nChange");
+ USB_HOST_SERIAL.print("CONNECTION:\t");
+ USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_CONNECTION) > 0, DEC);
+ USB_HOST_SERIAL.print("ENABLE:\t\t");
+ USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_ENABLE) > 0, DEC);
+ USB_HOST_SERIAL.print("SUSPEND:\t");
+ USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_SUSPEND) > 0, DEC);
+ USB_HOST_SERIAL.print("OVER_CURRENT:\t");
+ USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_OVER_CURRENT) > 0, DEC);
+ USB_HOST_SERIAL.print("RESET:\t\t");
+ USB_HOST_SERIAL.println((evt.bmChange & bmHUB_PORT_STATUS_C_PORT_RESET) > 0, DEC);
+}
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usbhub.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usbhub.h
new file mode 100644
index 000000000..1ac949445
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/usbhub.h
@@ -0,0 +1,252 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+#if !defined(__USBHUB_H__)
+#define __USBHUB_H__
+
+#include "Usb.h"
+
+#define USB_DESCRIPTOR_HUB 0x09 // Hub descriptor type
+
+// Hub Requests
+#define bmREQ_CLEAR_HUB_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE
+#define bmREQ_CLEAR_PORT_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
+#define bmREQ_CLEAR_TT_BUFFER USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
+#define bmREQ_GET_HUB_DESCRIPTOR USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE
+#define bmREQ_GET_HUB_STATUS USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE
+#define bmREQ_GET_PORT_STATUS USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
+#define bmREQ_RESET_TT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
+#define bmREQ_SET_HUB_DESCRIPTOR USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE
+#define bmREQ_SET_HUB_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_DEVICE
+#define bmREQ_SET_PORT_FEATURE USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
+#define bmREQ_GET_TT_STATE USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
+#define bmREQ_STOP_TT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_OTHER
+
+// Hub Class Requests
+#define HUB_REQUEST_CLEAR_TT_BUFFER 8
+#define HUB_REQUEST_RESET_TT 9
+#define HUB_REQUEST_GET_TT_STATE 10
+#define HUB_REQUEST_STOP_TT 11
+
+// Hub Features
+#define HUB_FEATURE_C_HUB_LOCAL_POWER 0
+#define HUB_FEATURE_C_HUB_OVER_CURRENT 1
+#define HUB_FEATURE_PORT_CONNECTION 0
+#define HUB_FEATURE_PORT_ENABLE 1
+#define HUB_FEATURE_PORT_SUSPEND 2
+#define HUB_FEATURE_PORT_OVER_CURRENT 3
+#define HUB_FEATURE_PORT_RESET 4
+#define HUB_FEATURE_PORT_POWER 8
+#define HUB_FEATURE_PORT_LOW_SPEED 9
+#define HUB_FEATURE_C_PORT_CONNECTION 16
+#define HUB_FEATURE_C_PORT_ENABLE 17
+#define HUB_FEATURE_C_PORT_SUSPEND 18
+#define HUB_FEATURE_C_PORT_OVER_CURRENT 19
+#define HUB_FEATURE_C_PORT_RESET 20
+#define HUB_FEATURE_PORT_TEST 21
+#define HUB_FEATURE_PORT_INDICATOR 22
+
+// Hub Port Test Modes
+#define HUB_PORT_TEST_MODE_J 1
+#define HUB_PORT_TEST_MODE_K 2
+#define HUB_PORT_TEST_MODE_SE0_NAK 3
+#define HUB_PORT_TEST_MODE_PACKET 4
+#define HUB_PORT_TEST_MODE_FORCE_ENABLE 5
+
+// Hub Port Indicator Color
+#define HUB_PORT_INDICATOR_AUTO 0
+#define HUB_PORT_INDICATOR_AMBER 1
+#define HUB_PORT_INDICATOR_GREEN 2
+#define HUB_PORT_INDICATOR_OFF 3
+
+// Hub Port Status Bitmasks
+#define bmHUB_PORT_STATUS_PORT_CONNECTION 0x0001
+#define bmHUB_PORT_STATUS_PORT_ENABLE 0x0002
+#define bmHUB_PORT_STATUS_PORT_SUSPEND 0x0004
+#define bmHUB_PORT_STATUS_PORT_OVER_CURRENT 0x0008
+#define bmHUB_PORT_STATUS_PORT_RESET 0x0010
+#define bmHUB_PORT_STATUS_PORT_POWER 0x0100
+#define bmHUB_PORT_STATUS_PORT_LOW_SPEED 0x0200
+#define bmHUB_PORT_STATUS_PORT_HIGH_SPEED 0x0400
+#define bmHUB_PORT_STATUS_PORT_TEST 0x0800
+#define bmHUB_PORT_STATUS_PORT_INDICATOR 0x1000
+
+// Hub Port Status Change Bitmasks (used one byte instead of two)
+#define bmHUB_PORT_STATUS_C_PORT_CONNECTION 0x0001
+#define bmHUB_PORT_STATUS_C_PORT_ENABLE 0x0002
+#define bmHUB_PORT_STATUS_C_PORT_SUSPEND 0x0004
+#define bmHUB_PORT_STATUS_C_PORT_OVER_CURRENT 0x0008
+#define bmHUB_PORT_STATUS_C_PORT_RESET 0x0010
+
+// Hub Status Bitmasks (used one byte instead of two)
+#define bmHUB_STATUS_LOCAL_POWER_SOURCE 0x01
+#define bmHUB_STATUS_OVER_CURRENT 0x12
+
+// Hub Status Change Bitmasks (used one byte instead of two)
+#define bmHUB_STATUS_C_LOCAL_POWER_SOURCE 0x01
+#define bmHUB_STATUS_C_OVER_CURRENT 0x12
+
+
+// Hub Port Configuring Substates
+#define USB_STATE_HUB_PORT_CONFIGURING 0xb0
+#define USB_STATE_HUB_PORT_POWERED_OFF 0xb1
+#define USB_STATE_HUB_PORT_WAIT_FOR_POWER_GOOD 0xb2
+#define USB_STATE_HUB_PORT_DISCONNECTED 0xb3
+#define USB_STATE_HUB_PORT_DISABLED 0xb4
+#define USB_STATE_HUB_PORT_RESETTING 0xb5
+#define USB_STATE_HUB_PORT_ENABLED 0xb6
+
+// Additional Error Codes
+#define HUB_ERROR_PORT_HAS_BEEN_RESET 0xb1
+
+// The bit mask to check for all necessary state bits
+#define bmHUB_PORT_STATUS_ALL_MAIN ((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION | bmHUB_PORT_STATUS_C_PORT_ENABLE | bmHUB_PORT_STATUS_C_PORT_SUSPEND | bmHUB_PORT_STATUS_C_PORT_RESET) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_SUSPEND)
+
+// Bit mask to check for DISABLED state in HubEvent::bmStatus field
+#define bmHUB_PORT_STATE_CHECK_DISABLED (0x0000 | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_SUSPEND)
+
+// Hub Port States
+#define bmHUB_PORT_STATE_DISABLED (0x0000 | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION)
+
+// Hub Port Events
+#define bmHUB_PORT_EVENT_CONNECT (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION)
+#define bmHUB_PORT_EVENT_DISCONNECT (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION) << 16) | bmHUB_PORT_STATUS_PORT_POWER)
+#define bmHUB_PORT_EVENT_RESET_COMPLETE (((0UL | bmHUB_PORT_STATUS_C_PORT_RESET) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION)
+
+#define bmHUB_PORT_EVENT_LS_CONNECT (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_LOW_SPEED)
+#define bmHUB_PORT_EVENT_LS_RESET_COMPLETE (((0UL | bmHUB_PORT_STATUS_C_PORT_RESET) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_LOW_SPEED)
+#define bmHUB_PORT_EVENT_LS_PORT_ENABLED (((0UL | bmHUB_PORT_STATUS_C_PORT_CONNECTION | bmHUB_PORT_STATUS_C_PORT_ENABLE) << 16) | bmHUB_PORT_STATUS_PORT_POWER | bmHUB_PORT_STATUS_PORT_ENABLE | bmHUB_PORT_STATUS_PORT_CONNECTION | bmHUB_PORT_STATUS_PORT_LOW_SPEED)
+
+struct HubDescriptor {
+ uint8_t bDescLength; // descriptor length
+ uint8_t bDescriptorType; // descriptor type
+ uint8_t bNbrPorts; // number of ports a hub equiped with
+
+ struct {
+ uint16_t LogPwrSwitchMode : 2;
+ uint16_t CompoundDevice : 1;
+ uint16_t OverCurrentProtectMode : 2;
+ uint16_t TTThinkTime : 2;
+ uint16_t PortIndicatorsSupported : 1;
+ uint16_t Reserved : 8;
+ } __attribute__((packed));
+
+ uint8_t bPwrOn2PwrGood;
+ uint8_t bHubContrCurrent;
+} __attribute__((packed));
+
+struct HubEvent {
+
+ union {
+
+ struct {
+ uint16_t bmStatus; // port status bits
+ uint16_t bmChange; // port status change bits
+ } __attribute__((packed));
+ uint32_t bmEvent;
+ uint8_t evtBuff[4];
+ };
+} __attribute__((packed));
+
+class USBHub : USBDeviceConfig {
+ static bool bResetInitiated; // True when reset is triggered
+
+ USB *pUsb; // USB class instance pointer
+
+ EpInfo epInfo[2]; // interrupt endpoint info structure
+
+ uint8_t bAddress; // address
+ uint8_t bNbrPorts; // number of ports
+ // uint8_t bInitState; // initialization state variable
+ uint32_t qNextPollTime; // next poll time
+ bool bPollEnable; // poll enable flag
+
+ uint8_t CheckHubStatus();
+ uint8_t PortStatusChange(uint8_t port, HubEvent &evt);
+
+public:
+ USBHub(USB *p);
+
+ uint8_t ClearHubFeature(uint8_t fid);
+ uint8_t ClearPortFeature(uint8_t fid, uint8_t port, uint8_t sel = 0);
+ uint8_t GetHubDescriptor(uint8_t index, uint16_t nbytes, uint8_t *dataptr);
+ uint8_t GetHubStatus(uint16_t nbytes, uint8_t* dataptr);
+ uint8_t GetPortStatus(uint8_t port, uint16_t nbytes, uint8_t* dataptr);
+ uint8_t SetHubDescriptor(uint8_t port, uint16_t nbytes, uint8_t* dataptr);
+ uint8_t SetHubFeature(uint8_t fid);
+ uint8_t SetPortFeature(uint8_t fid, uint8_t port, uint8_t sel = 0);
+
+ void PrintHubStatus();
+
+ uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
+ uint8_t Release();
+ uint8_t Poll();
+ void ResetHubPort(uint8_t port);
+
+ virtual uint8_t GetAddress() {
+ return bAddress;
+ };
+
+ virtual bool DEVCLASSOK(uint8_t klass) {
+ return (klass == 0x09);
+ }
+
+};
+
+// Clear Hub Feature
+
+inline uint8_t USBHub::ClearHubFeature(uint8_t fid) {
+ return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CLEAR_HUB_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, 0, 0, 0, NULL, NULL));
+}
+// Clear Port Feature
+
+inline uint8_t USBHub::ClearPortFeature(uint8_t fid, uint8_t port, uint8_t sel) {
+ return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CLEAR_PORT_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, ((0x0000 | port) | (sel << 8)), 0, 0, NULL, NULL));
+}
+// Get Hub Descriptor
+
+inline uint8_t USBHub::GetHubDescriptor(uint8_t index, uint16_t nbytes, uint8_t *dataptr) {
+ return ( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_HUB_DESCRIPTOR, USB_REQUEST_GET_DESCRIPTOR, index, 0x29, 0, nbytes, nbytes, dataptr, NULL));
+}
+// Get Hub Status
+
+inline uint8_t USBHub::GetHubStatus(uint16_t nbytes, uint8_t* dataptr) {
+ return ( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_HUB_STATUS, USB_REQUEST_GET_STATUS, 0, 0, 0x0000, nbytes, nbytes, dataptr, NULL));
+}
+// Get Port Status
+
+inline uint8_t USBHub::GetPortStatus(uint8_t port, uint16_t nbytes, uint8_t* dataptr) {
+ return ( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_PORT_STATUS, USB_REQUEST_GET_STATUS, 0, 0, port, nbytes, nbytes, dataptr, NULL));
+}
+// Set Hub Descriptor
+
+inline uint8_t USBHub::SetHubDescriptor(uint8_t port, uint16_t nbytes, uint8_t* dataptr) {
+ return ( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_HUB_DESCRIPTOR, USB_REQUEST_SET_DESCRIPTOR, 0, 0, port, nbytes, nbytes, dataptr, NULL));
+}
+// Set Hub Feature
+
+inline uint8_t USBHub::SetHubFeature(uint8_t fid) {
+ return ( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_HUB_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, 0, 0, 0, NULL, NULL));
+}
+// Set Port Feature
+
+inline uint8_t USBHub::SetPortFeature(uint8_t fid, uint8_t port, uint8_t sel) {
+ return ( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_PORT_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, (((0x0000 | sel) << 8) | port), 0, 0, NULL, NULL));
+}
+
+void PrintHubPortStatus(USB *usbptr, uint8_t addr, uint8_t port, bool print_changes = false);
+
+#endif // __USBHUB_H__
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/version_helper.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/version_helper.h
new file mode 100644
index 000000000..0cb3b4adc
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/version_helper.h
@@ -0,0 +1,194 @@
+/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
+
+This software may be distributed and modified under the terms of the GNU
+General Public License version 2 (GPL2) as published by the Free Software
+Foundation and appearing in the file GPL2.TXT included in the packaging of
+this file. Please note that GPL2 Section 2[b] requires that all works based
+on this software must also be made publicly available under the terms of
+the GPL2 ("Copyleft").
+
+Contact information
+-------------------
+
+Circuits At Home, LTD
+Web : http://www.circuitsathome.com
+e-mail : support@circuitsathome.com
+ */
+
+/*
+ * Universal Arduino(tm) "IDE" fixups.
+ * Includes fixes for versions as low as 0023, used by Digilent.
+ */
+
+#if defined(ARDUINO) && ARDUINO >=100
+#include <Arduino.h>
+#else
+#include <WProgram.h>
+#include <pins_arduino.h>
+#ifdef __AVR__
+#include <avr/pgmspace.h>
+#include <avr/io.h>
+#else
+#endif
+#endif
+
+#ifndef __PGMSPACE_H_
+#define __PGMSPACE_H_ 1
+
+#include <inttypes.h>
+
+#ifndef PROGMEM
+#define PROGMEM
+#endif
+#ifndef PGM_P
+#define PGM_P const char *
+#endif
+#ifndef PSTR
+#define PSTR(str) (str)
+#endif
+#ifndef F
+#define F(str) (str)
+#endif
+#ifndef _SFR_BYTE
+#define _SFR_BYTE(n) (n)
+#endif
+
+#ifndef memchr_P
+#define memchr_P(str, c, len) memchr((str), (c), (len))
+#endif
+#ifndef memcmp_P
+#define memcmp_P(a, b, n) memcmp((a), (b), (n))
+#endif
+#ifndef memcpy_P
+#define memcpy_P(dest, src, num) memcpy((dest), (src), (num))
+#endif
+#ifndef memmem_P
+#define memmem_P(a, alen, b, blen) memmem((a), (alen), (b), (blen))
+#endif
+#ifndef memrchr_P
+#define memrchr_P(str, val, len) memrchr((str), (val), (len))
+#endif
+#ifndef strcat_P
+#define strcat_P(dest, src) strcat((dest), (src))
+#endif
+#ifndef strchr_P
+#define strchr_P(str, c) strchr((str), (c))
+#endif
+#ifndef strchrnul_P
+#define strchrnul_P(str, c) strchrnul((str), (c))
+#endif
+#ifndef strcmp_P
+#define strcmp_P(a, b) strcmp((a), (b))
+#endif
+#ifndef strcpy_P
+#define strcpy_P(dest, src) strcpy((dest), (src))
+#endif
+#ifndef strcasecmp_P
+#define strcasecmp_P(a, b) strcasecmp((a), (b))
+#endif
+#ifndef strcasestr_P
+#define strcasestr_P(a, b) strcasestr((a), (b))
+#endif
+#ifndef strlcat_P
+#define strlcat_P(dest, src, len) strlcat((dest), (src), (len))
+#endif
+#ifndef strlcpy_P
+#define strlcpy_P(dest, src, len) strlcpy((dest), (src), (len))
+#endif
+#ifndef strlen_P
+#define strlen_P(s) strlen((const char *)(s))
+#endif
+#ifndef strnlen_P
+#define strnlen_P(str, len) strnlen((str), (len))
+#endif
+#ifndef strncmp_P
+#define strncmp_P(a, b, n) strncmp((a), (b), (n))
+#endif
+#ifndef strncasecmp_P
+#define strncasecmp_P(a, b, n) strncasecmp((a), (b), (n))
+#endif
+#ifndef strncat_P
+#define strncat_P(a, b, n) strncat((a), (b), (n))
+#endif
+#ifndef strncpy_P
+#define strncpy_P(a, b, n) strncmp((a), (b), (n))
+#endif
+#ifndef strpbrk_P
+#define strpbrk_P(str, chrs) strpbrk((str), (chrs))
+#endif
+#ifndef strrchr_P
+#define strrchr_P(str, c) strrchr((str), (c))
+#endif
+#ifndef strsep_P
+#define strsep_P(strp, delim) strsep((strp), (delim))
+#endif
+#ifndef strspn_P
+#define strspn_P(str, chrs) strspn((str), (chrs))
+#endif
+#ifndef strstr_P
+#define strstr_P(a, b) strstr((a), (b))
+#endif
+#ifndef sprintf_P
+#define sprintf_P(s, ...) sprintf((s), __VA_ARGS__)
+#endif
+#ifndef vfprintf_P
+#define vfprintf_P(s, ...) vfprintf((s), __VA_ARGS__)
+#endif
+#ifndef printf_P
+#define printf_P(...) printf(__VA_ARGS__)
+#endif
+#ifndef snprintf_P
+#define snprintf_P(s, n, ...) ((s), (n), __VA_ARGS__)
+#endif
+#ifndef vsprintf_P
+#define vsprintf_P(s, ...) ((s),__VA_ARGS__)
+#endif
+#ifndef vsnprintf_P
+#define vsnprintf_P(s, n, ...) ((s), (n),__VA_ARGS__)
+#endif
+#ifndef fprintf_P
+#define fprintf_P(s, ...) ((s), __VA_ARGS__)
+#endif
+
+#ifndef pgm_read_byte
+#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
+#endif
+#ifndef pgm_read_word
+#define pgm_read_word(addr) (*(const unsigned short *)(addr))
+#endif
+#ifndef pgm_read_dword
+#define pgm_read_dword(addr) (*(const unsigned long *)(addr))
+#endif
+#ifndef pgm_read_float
+#define pgm_read_float(addr) (*(const float *)(addr))
+#endif
+
+#ifndef pgm_read_byte_near
+#define pgm_read_byte_near(addr) pgm_read_byte(addr)
+#endif
+#ifndef pgm_read_word_near
+#define pgm_read_word_near(addr) pgm_read_word(addr)
+#endif
+#ifndef pgm_read_dword_near
+#define pgm_read_dword_near(addr) pgm_read_dword(addr)
+#endif
+#ifndef pgm_read_float_near
+#define pgm_read_float_near(addr) pgm_read_float(addr)
+#endif
+#ifndef pgm_read_byte_far
+#define pgm_read_byte_far(addr) pgm_read_byte(addr)
+#endif
+#ifndef pgm_read_word_far
+#define pgm_read_word_far(addr) pgm_read_word(addr)
+#endif
+#ifndef pgm_read_dword_far
+#define pgm_read_dword_far(addr) pgm_read_dword(addr)
+#endif
+#ifndef pgm_read_float_far
+#define pgm_read_float_far(addr) pgm_read_float(addr)
+#endif
+
+#ifndef pgm_read_pointer
+#define pgm_read_pointer
+#endif
+#endif
diff --git a/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/xboxEnums.h b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/xboxEnums.h
new file mode 100644
index 000000000..84b137bb6
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/USB_Host_Shield_2.0/xboxEnums.h
@@ -0,0 +1,65 @@
+/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
+
+ This software may be distributed and modified under the terms of the GNU
+ General Public License version 2 (GPL2) as published by the Free Software
+ Foundation and appearing in the file GPL2.TXT included in the packaging of
+ this file. Please note that GPL2 Section 2[b] requires that all works based
+ on this software must also be made publicly available under the terms of
+ the GPL2 ("Copyleft").
+
+ Contact information
+ -------------------
+
+ Kristian Lauszus, TKJ Electronics
+ Web : http://www.tkjelectronics.com
+ e-mail : kristianl@tkjelectronics.com
+ */
+
+#ifndef _xboxenums_h
+#define _xboxenums_h
+
+#include "controllerEnums.h"
+
+/** Enum used to set special LED modes supported by the Xbox controller. */
+enum LEDModeEnum {
+ ROTATING = 0x0A,
+ FASTBLINK = 0x0B,
+ SLOWBLINK = 0x0C,
+ ALTERNATING = 0x0D,
+};
+
+/** Used to set the LEDs on the controllers */
+const uint8_t XBOX_LEDS[] PROGMEM = {
+ 0x00, // OFF
+ 0x02, // LED1
+ 0x03, // LED2
+ 0x04, // LED3
+ 0x05, // LED4
+ 0x01, // ALL - Used to blink all LEDs
+};
+/** Buttons on the controllers */
+const uint16_t XBOX_BUTTONS[] PROGMEM = {
+ 0x0100, // UP
+ 0x0800, // RIGHT
+ 0x0200, // DOWN
+ 0x0400, // LEFT
+
+ 0x2000, // BACK
+ 0x1000, // START
+ 0x4000, // L3
+ 0x8000, // R3
+
+ 0, 0, // Skip L2 and R2 as these are analog buttons
+ 0x0001, // L1
+ 0x0002, // R1
+
+ 0x0020, // B
+ 0x0010, // A
+ 0x0040, // X
+ 0x0080, // Y
+
+ 0x0004, // XBOX
+ 0x0008, // SYNC
+};
+
+#endif
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Arduino.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Arduino.h
new file mode 100644
index 000000000..830c9952f
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Arduino.h
@@ -0,0 +1,215 @@
+#ifndef Arduino_h
+#define Arduino_h
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include <avr/pgmspace.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+
+#include "binary.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+#define HIGH 0x1
+#define LOW 0x0
+
+#define INPUT 0x0
+#define OUTPUT 0x1
+#define INPUT_PULLUP 0x2
+
+#define true 0x1
+#define false 0x0
+
+#define PI 3.1415926535897932384626433832795
+#define HALF_PI 1.5707963267948966192313216916398
+#define TWO_PI 6.283185307179586476925286766559
+#define DEG_TO_RAD 0.017453292519943295769236907684886
+#define RAD_TO_DEG 57.295779513082320876798154814105
+
+#define SERIAL 0x0
+#define DISPLAY 0x1
+
+#define LSBFIRST 0
+#define MSBFIRST 1
+
+#define CHANGE 1
+#define FALLING 2
+#define RISING 3
+
+#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
+#define DEFAULT 0
+#define EXTERNAL 1
+#define INTERNAL 2
+#else
+#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1284P__)
+#define INTERNAL1V1 2
+#define INTERNAL2V56 3
+#else
+#define INTERNAL 3
+#endif
+#define DEFAULT 1
+#define EXTERNAL 0
+#endif
+
+// undefine stdlib's abs if encountered
+#ifdef abs
+#undef abs
+#endif
+
+#define min(a,b) ((a)<(b)?(a):(b))
+#define max(a,b) ((a)>(b)?(a):(b))
+#define abs(x) ((x)>0?(x):-(x))
+#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
+#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
+#define radians(deg) ((deg)*DEG_TO_RAD)
+#define degrees(rad) ((rad)*RAD_TO_DEG)
+#define sq(x) ((x)*(x))
+
+#define interrupts() sei()
+#define noInterrupts() cli()
+
+#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
+#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
+#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() )
+
+#define lowByte(w) ((uint8_t) ((w) & 0xff))
+#define highByte(w) ((uint8_t) ((w) >> 8))
+
+#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
+#define bitSet(value, bit) ((value) |= (1UL << (bit)))
+#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
+#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
+
+
+typedef unsigned int word;
+
+#define bit(b) (1UL << (b))
+
+typedef uint8_t boolean;
+typedef uint8_t byte;
+
+void init(void);
+
+void pinMode(uint8_t, uint8_t);
+void digitalWrite(uint8_t, uint8_t);
+int digitalRead(uint8_t);
+int analogRead(uint8_t);
+void analogReference(uint8_t mode);
+void analogWrite(uint8_t, int);
+
+unsigned long millis(void);
+unsigned long micros(void);
+void delay(unsigned long);
+void delayMicroseconds(unsigned int us);
+unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout);
+
+void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val);
+uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder);
+
+void attachInterrupt(uint8_t, void (*)(void), int mode);
+void detachInterrupt(uint8_t);
+
+void setup(void);
+void loop(void);
+
+// Get the bit location within the hardware port of the given virtual pin.
+// This comes from the pins_*.c file for the active board configuration.
+
+#define analogInPinToBit(P) (P)
+
+// On the ATmega1280, the addresses of some of the port registers are
+// greater than 255, so we can't store them in uint8_t's.
+extern const uint16_t PROGMEM port_to_mode_PGM[];
+extern const uint16_t PROGMEM port_to_input_PGM[];
+extern const uint16_t PROGMEM port_to_output_PGM[];
+
+extern const uint8_t PROGMEM digital_pin_to_port_PGM[];
+// extern const uint8_t PROGMEM digital_pin_to_bit_PGM[];
+extern const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[];
+extern const uint8_t PROGMEM digital_pin_to_timer_PGM[];
+
+// Get the bit location within the hardware port of the given virtual pin.
+// This comes from the pins_*.c file for the active board configuration.
+//
+// These perform slightly better as macros compared to inline functions
+//
+#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) )
+#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) )
+#define digitalPinToTimer(P) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) )
+#define analogInPinToBit(P) (P)
+#define portOutputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_output_PGM + (P))) )
+#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + (P))) )
+#define portModeRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_mode_PGM + (P))) )
+
+#define NOT_A_PIN 0
+#define NOT_A_PORT 0
+
+#ifdef ARDUINO_MAIN
+#define PA 1
+#define PB 2
+#define PC 3
+#define PD 4
+#define PE 5
+#define PF 6
+#define PG 7
+#define PH 8
+#define PJ 10
+#define PK 11
+#define PL 12
+#endif
+
+#define NOT_ON_TIMER 0
+#define TIMER0A 1
+#define TIMER0B 2
+#define TIMER1A 3
+#define TIMER1B 4
+#define TIMER2 5
+#define TIMER2A 6
+#define TIMER2B 7
+
+#define TIMER3A 8
+#define TIMER3B 9
+#define TIMER3C 10
+#define TIMER4A 11
+#define TIMER4B 12
+#define TIMER4C 13
+#define TIMER4D 14
+#define TIMER5A 15
+#define TIMER5B 16
+#define TIMER5C 17
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#ifdef __cplusplus
+#include "WCharacter.h"
+#include "WString.h"
+#include "HardwareSerial.h"
+
+uint16_t makeWord(uint16_t w);
+uint16_t makeWord(byte h, byte l);
+
+#define word(...) makeWord(__VA_ARGS__)
+
+unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);
+
+void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0);
+void noTone(uint8_t _pin);
+
+// WMath prototypes
+long random(long);
+long random(long, long);
+void randomSeed(unsigned int);
+long map(long, long, long, long, long);
+
+#endif
+
+#include "pins_arduino.h"
+
+#endif
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/CDC.cpp b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/CDC.cpp
new file mode 100644
index 000000000..1ee3a488a
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/CDC.cpp
@@ -0,0 +1,233 @@
+
+
+/* Copyright (c) 2011, Peter Barrett
+**
+** Permission to use, copy, modify, and/or distribute this software for
+** any purpose with or without fee is hereby granted, provided that the
+** above copyright notice and this permission notice appear in all copies.
+**
+** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
+** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
+** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+** SOFTWARE.
+*/
+
+#include "Platform.h"
+#include "USBAPI.h"
+#include <avr/wdt.h>
+
+#if defined(USBCON)
+#ifdef CDC_ENABLED
+
+#if (RAMEND < 1000)
+#define SERIAL_BUFFER_SIZE 16
+#else
+#define SERIAL_BUFFER_SIZE 64
+#endif
+
+struct ring_buffer
+{
+ unsigned char buffer[SERIAL_BUFFER_SIZE];
+ volatile int head;
+ volatile int tail;
+};
+
+ring_buffer cdc_rx_buffer = { { 0 }, 0, 0};
+
+typedef struct
+{
+ u32 dwDTERate;
+ u8 bCharFormat;
+ u8 bParityType;
+ u8 bDataBits;
+ u8 lineState;
+} LineInfo;
+
+static volatile LineInfo _usbLineInfo = { 57600, 0x00, 0x00, 0x00, 0x00 };
+
+#define WEAK __attribute__ ((weak))
+
+extern const CDCDescriptor _cdcInterface PROGMEM;
+const CDCDescriptor _cdcInterface =
+{
+ D_IAD(0,2,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,1),
+
+ // CDC communication interface
+ D_INTERFACE(CDC_ACM_INTERFACE,1,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,0),
+ D_CDCCS(CDC_HEADER,0x10,0x01), // Header (1.10 bcd)
+ D_CDCCS(CDC_CALL_MANAGEMENT,1,1), // Device handles call management (not)
+ D_CDCCS4(CDC_ABSTRACT_CONTROL_MANAGEMENT,6), // SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported
+ D_CDCCS(CDC_UNION,CDC_ACM_INTERFACE,CDC_DATA_INTERFACE), // Communication interface is master, data interface is slave 0
+ D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_ACM),USB_ENDPOINT_TYPE_INTERRUPT,0x10,0x40),
+
+ // CDC data interface
+ D_INTERFACE(CDC_DATA_INTERFACE,2,CDC_DATA_INTERFACE_CLASS,0,0),
+ D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT),USB_ENDPOINT_TYPE_BULK,0x40,0),
+ D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,0x40,0)
+};
+
+int WEAK CDC_GetInterface(u8* interfaceNum)
+{
+ interfaceNum[0] += 2; // uses 2
+ return USB_SendControl(TRANSFER_PGM,&_cdcInterface,sizeof(_cdcInterface));
+}
+
+bool WEAK CDC_Setup(Setup& setup)
+{
+ u8 r = setup.bRequest;
+ u8 requestType = setup.bmRequestType;
+
+ if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType)
+ {
+ if (CDC_GET_LINE_CODING == r)
+ {
+ USB_SendControl(0,(void*)&_usbLineInfo,7);
+ return true;
+ }
+ }
+
+ if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType)
+ {
+ if (CDC_SET_LINE_CODING == r)
+ {
+ USB_RecvControl((void*)&_usbLineInfo,7);
+ return true;
+ }
+
+ if (CDC_SET_CONTROL_LINE_STATE == r)
+ {
+ _usbLineInfo.lineState = setup.wValueL;
+
+ // auto-reset into the bootloader is triggered when the port, already
+ // open at 1200 bps, is closed. this is the signal to start the watchdog
+ // with a relatively long period so it can finish housekeeping tasks
+ // like servicing endpoints before the sketch ends
+ if (1200 == _usbLineInfo.dwDTERate) {
+ // We check DTR state to determine if host port is open (bit 0 of lineState).
+ if ((_usbLineInfo.lineState & 0x01) == 0) {
+ *(uint16_t *)0x0800 = 0x7777;
+ wdt_enable(WDTO_120MS);
+ } else {
+ // Most OSs do some intermediate steps when configuring ports and DTR can
+ // twiggle more than once before stabilizing.
+ // To avoid spurious resets we set the watchdog to 250ms and eventually
+ // cancel if DTR goes back high.
+
+ wdt_disable();
+ wdt_reset();
+ *(uint16_t *)0x0800 = 0x0;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+
+int _serialPeek = -1;
+void Serial_::begin(uint16_t baud_count)
+{
+}
+
+void Serial_::end(void)
+{
+}
+
+void Serial_::accept(void)
+{
+ ring_buffer *buffer = &cdc_rx_buffer;
+ int c = USB_Recv(CDC_RX);
+ int i = (unsigned int)(buffer->head+1) % SERIAL_BUFFER_SIZE;
+
+ // if we should be storing the received character into the location
+ // just before the tail (meaning that the head would advance to the
+ // current location of the tail), we're about to overflow the buffer
+ // and so we don't write the character or advance the head.
+ if (i != buffer->tail) {
+ buffer->buffer[buffer->head] = c;
+ buffer->head = i;
+ }
+}
+
+int Serial_::available(void)
+{
+ ring_buffer *buffer = &cdc_rx_buffer;
+ return (unsigned int)(SERIAL_BUFFER_SIZE + buffer->head - buffer->tail) % SERIAL_BUFFER_SIZE;
+}
+
+int Serial_::peek(void)
+{
+ ring_buffer *buffer = &cdc_rx_buffer;
+ if (buffer->head == buffer->tail) {
+ return -1;
+ } else {
+ return buffer->buffer[buffer->tail];
+ }
+}
+
+int Serial_::read(void)
+{
+ ring_buffer *buffer = &cdc_rx_buffer;
+ // if the head isn't ahead of the tail, we don't have any characters
+ if (buffer->head == buffer->tail) {
+ return -1;
+ } else {
+ unsigned char c = buffer->buffer[buffer->tail];
+ buffer->tail = (unsigned int)(buffer->tail + 1) % SERIAL_BUFFER_SIZE;
+ return c;
+ }
+}
+
+void Serial_::flush(void)
+{
+ USB_Flush(CDC_TX);
+}
+
+size_t Serial_::write(uint8_t c)
+{
+ /* only try to send bytes if the high-level CDC connection itself
+ is open (not just the pipe) - the OS should set lineState when the port
+ is opened and clear lineState when the port is closed.
+ bytes sent before the user opens the connection or after
+ the connection is closed are lost - just like with a UART. */
+
+ // TODO - ZE - check behavior on different OSes and test what happens if an
+ // open connection isn't broken cleanly (cable is yanked out, host dies
+ // or locks up, or host virtual serial port hangs)
+ if (_usbLineInfo.lineState > 0) {
+ int r = USB_Send(CDC_TX,&c,1);
+ if (r > 0) {
+ return r;
+ } else {
+ setWriteError();
+ return 0;
+ }
+ }
+ setWriteError();
+ return 0;
+}
+
+// This operator is a convenient way for a sketch to check whether the
+// port has actually been configured and opened by the host (as opposed
+// to just being connected to the host). It can be used, for example, in
+// setup() before printing to ensure that an application on the host is
+// actually ready to receive and display the data.
+// We add a short delay before returning to fix a bug observed by Federico
+// where the port is configured (lineState != 0) but not quite opened.
+Serial_::operator bool() {
+ bool result = false;
+ if (_usbLineInfo.lineState > 0)
+ result = true;
+ delay(10);
+ return result;
+}
+
+Serial_ Serial;
+
+#endif
+#endif /* if defined(USBCON) */
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Client.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Client.h
new file mode 100644
index 000000000..ea134838a
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Client.h
@@ -0,0 +1,26 @@
+#ifndef client_h
+#define client_h
+#include "Print.h"
+#include "Stream.h"
+#include "IPAddress.h"
+
+class Client : public Stream {
+
+public:
+ virtual int connect(IPAddress ip, uint16_t port) =0;
+ virtual int connect(const char *host, uint16_t port) =0;
+ virtual size_t write(uint8_t) =0;
+ virtual size_t write(const uint8_t *buf, size_t size) =0;
+ virtual int available() = 0;
+ virtual int read() = 0;
+ virtual int read(uint8_t *buf, size_t size) = 0;
+ virtual int peek() = 0;
+ virtual void flush() = 0;
+ virtual void stop() = 0;
+ virtual uint8_t connected() = 0;
+ virtual operator bool() = 0;
+protected:
+ uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); };
+};
+
+#endif
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/HID.cpp b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/HID.cpp
new file mode 100644
index 000000000..ac6360844
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/HID.cpp
@@ -0,0 +1,520 @@
+
+
+/* Copyright (c) 2011, Peter Barrett
+**
+** Permission to use, copy, modify, and/or distribute this software for
+** any purpose with or without fee is hereby granted, provided that the
+** above copyright notice and this permission notice appear in all copies.
+**
+** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
+** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
+** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+** SOFTWARE.
+*/
+
+#include "Platform.h"
+#include "USBAPI.h"
+#include "USBDesc.h"
+
+#if defined(USBCON)
+#ifdef HID_ENABLED
+
+//#define RAWHID_ENABLED
+
+// Singletons for mouse and keyboard
+
+Mouse_ Mouse;
+Keyboard_ Keyboard;
+
+//================================================================================
+//================================================================================
+
+// HID report descriptor
+
+#define LSB(_x) ((_x) & 0xFF)
+#define MSB(_x) ((_x) >> 8)
+
+#define RAWHID_USAGE_PAGE 0xFFC0
+#define RAWHID_USAGE 0x0C00
+#define RAWHID_TX_SIZE 64
+#define RAWHID_RX_SIZE 64
+
+extern const u8 _hidReportDescriptor[] PROGMEM;
+const u8 _hidReportDescriptor[] = {
+
+ // Mouse
+ 0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 54
+ 0x09, 0x02, // USAGE (Mouse)
+ 0xa1, 0x01, // COLLECTION (Application)
+ 0x09, 0x01, // USAGE (Pointer)
+ 0xa1, 0x00, // COLLECTION (Physical)
+ 0x85, 0x01, // REPORT_ID (1)
+ 0x05, 0x09, // USAGE_PAGE (Button)
+ 0x19, 0x01, // USAGE_MINIMUM (Button 1)
+ 0x29, 0x03, // USAGE_MAXIMUM (Button 3)
+ 0x15, 0x00, // LOGICAL_MINIMUM (0)
+ 0x25, 0x01, // LOGICAL_MAXIMUM (1)
+ 0x95, 0x03, // REPORT_COUNT (3)
+ 0x75, 0x01, // REPORT_SIZE (1)
+ 0x81, 0x02, // INPUT (Data,Var,Abs)
+ 0x95, 0x01, // REPORT_COUNT (1)
+ 0x75, 0x05, // REPORT_SIZE (5)
+ 0x81, 0x03, // INPUT (Cnst,Var,Abs)
+ 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+ 0x09, 0x30, // USAGE (X)
+ 0x09, 0x31, // USAGE (Y)
+ 0x09, 0x38, // USAGE (Wheel)
+ 0x15, 0x81, // LOGICAL_MINIMUM (-127)
+ 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
+ 0x75, 0x08, // REPORT_SIZE (8)
+ 0x95, 0x03, // REPORT_COUNT (3)
+ 0x81, 0x06, // INPUT (Data,Var,Rel)
+ 0xc0, // END_COLLECTION
+ 0xc0, // END_COLLECTION
+
+ // Keyboard
+ 0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 47
+ 0x09, 0x06, // USAGE (Keyboard)
+ 0xa1, 0x01, // COLLECTION (Application)
+ 0x85, 0x02, // REPORT_ID (2)
+ 0x05, 0x07, // USAGE_PAGE (Keyboard)
+
+ 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
+ 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
+ 0x15, 0x00, // LOGICAL_MINIMUM (0)
+ 0x25, 0x01, // LOGICAL_MAXIMUM (1)
+ 0x75, 0x01, // REPORT_SIZE (1)
+
+ 0x95, 0x08, // REPORT_COUNT (8)
+ 0x81, 0x02, // INPUT (Data,Var,Abs)
+ 0x95, 0x01, // REPORT_COUNT (1)
+ 0x75, 0x08, // REPORT_SIZE (8)
+ 0x81, 0x03, // INPUT (Cnst,Var,Abs)
+
+ 0x95, 0x06, // REPORT_COUNT (6)
+ 0x75, 0x08, // REPORT_SIZE (8)
+ 0x15, 0x00, // LOGICAL_MINIMUM (0)
+ 0x25, 0x65, // LOGICAL_MAXIMUM (101)
+ 0x05, 0x07, // USAGE_PAGE (Keyboard)
+
+ 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
+ 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
+ 0x81, 0x00, // INPUT (Data,Ary,Abs)
+ 0xc0, // END_COLLECTION
+
+#if RAWHID_ENABLED
+ // RAW HID
+ 0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE), // 30
+ 0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE),
+
+ 0xA1, 0x01, // Collection 0x01
+ 0x85, 0x03, // REPORT_ID (3)
+ 0x75, 0x08, // report size = 8 bits
+ 0x15, 0x00, // logical minimum = 0
+ 0x26, 0xFF, 0x00, // logical maximum = 255
+
+ 0x95, 64, // report count TX
+ 0x09, 0x01, // usage
+ 0x81, 0x02, // Input (array)
+
+ 0x95, 64, // report count RX
+ 0x09, 0x02, // usage
+ 0x91, 0x02, // Output (array)
+ 0xC0 // end collection
+#endif
+};
+
+extern const HIDDescriptor _hidInterface PROGMEM;
+const HIDDescriptor _hidInterface =
+{
+ D_INTERFACE(HID_INTERFACE,1,3,0,0),
+ D_HIDREPORT(sizeof(_hidReportDescriptor)),
+ D_ENDPOINT(USB_ENDPOINT_IN (HID_ENDPOINT_INT),USB_ENDPOINT_TYPE_INTERRUPT,0x40,0x01)
+};
+
+//================================================================================
+//================================================================================
+// Driver
+
+u8 _hid_protocol = 1;
+u8 _hid_idle = 1;
+
+#define WEAK __attribute__ ((weak))
+
+int WEAK HID_GetInterface(u8* interfaceNum)
+{
+ interfaceNum[0] += 1; // uses 1
+ return USB_SendControl(TRANSFER_PGM,&_hidInterface,sizeof(_hidInterface));
+}
+
+int WEAK HID_GetDescriptor(int i)
+{
+ return USB_SendControl(TRANSFER_PGM,_hidReportDescriptor,sizeof(_hidReportDescriptor));
+}
+
+void WEAK HID_SendReport(u8 id, const void* data, int len)
+{
+ USB_Send(HID_TX, &id, 1);
+ USB_Send(HID_TX | TRANSFER_RELEASE,data,len);
+}
+
+bool WEAK HID_Setup(Setup& setup)
+{
+ u8 r = setup.bRequest;
+ u8 requestType = setup.bmRequestType;
+ if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType)
+ {
+ if (HID_GET_REPORT == r)
+ {
+ //HID_GetReport();
+ return true;
+ }
+ if (HID_GET_PROTOCOL == r)
+ {
+ //Send8(_hid_protocol); // TODO
+ return true;
+ }
+ }
+
+ if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType)
+ {
+ if (HID_SET_PROTOCOL == r)
+ {
+ _hid_protocol = setup.wValueL;
+ return true;
+ }
+
+ if (HID_SET_IDLE == r)
+ {
+ _hid_idle = setup.wValueL;
+ return true;
+ }
+ }
+ return false;
+}
+
+//================================================================================
+//================================================================================
+// Mouse
+
+Mouse_::Mouse_(void) : _buttons(0)
+{
+}
+
+void Mouse_::begin(void)
+{
+}
+
+void Mouse_::end(void)
+{
+}
+
+void Mouse_::click(uint8_t b)
+{
+ _buttons = b;
+ move(0,0,0);
+ _buttons = 0;
+ move(0,0,0);
+}
+
+void Mouse_::move(signed char x, signed char y, signed char wheel)
+{
+ u8 m[4];
+ m[0] = _buttons;
+ m[1] = x;
+ m[2] = y;
+ m[3] = wheel;
+ HID_SendReport(1,m,4);
+}
+
+void Mouse_::buttons(uint8_t b)
+{
+ if (b != _buttons)
+ {
+ _buttons = b;
+ move(0,0,0);
+ }
+}
+
+void Mouse_::press(uint8_t b)
+{
+ buttons(_buttons | b);
+}
+
+void Mouse_::release(uint8_t b)
+{
+ buttons(_buttons & ~b);
+}
+
+bool Mouse_::isPressed(uint8_t b)
+{
+ if ((b & _buttons) > 0)
+ return true;
+ return false;
+}
+
+//================================================================================
+//================================================================================
+// Keyboard
+
+Keyboard_::Keyboard_(void)
+{
+}
+
+void Keyboard_::begin(void)
+{
+}
+
+void Keyboard_::end(void)
+{
+}
+
+void Keyboard_::sendReport(KeyReport* keys)
+{
+ HID_SendReport(2,keys,sizeof(KeyReport));
+}
+
+extern
+const uint8_t _asciimap[128] PROGMEM;
+
+#define SHIFT 0x80
+const uint8_t _asciimap[128] =
+{
+ 0x00, // NUL
+ 0x00, // SOH
+ 0x00, // STX
+ 0x00, // ETX
+ 0x00, // EOT
+ 0x00, // ENQ
+ 0x00, // ACK
+ 0x00, // BEL
+ 0x2a, // BS Backspace
+ 0x2b, // TAB Tab
+ 0x28, // LF Enter
+ 0x00, // VT
+ 0x00, // FF
+ 0x00, // CR
+ 0x00, // SO
+ 0x00, // SI
+ 0x00, // DEL
+ 0x00, // DC1
+ 0x00, // DC2
+ 0x00, // DC3
+ 0x00, // DC4
+ 0x00, // NAK
+ 0x00, // SYN
+ 0x00, // ETB
+ 0x00, // CAN
+ 0x00, // EM
+ 0x00, // SUB
+ 0x00, // ESC
+ 0x00, // FS
+ 0x00, // GS
+ 0x00, // RS
+ 0x00, // US
+
+ 0x2c, // ' '
+ 0x1e|SHIFT, // !
+ 0x34|SHIFT, // "
+ 0x20|SHIFT, // #
+ 0x21|SHIFT, // $
+ 0x22|SHIFT, // %
+ 0x24|SHIFT, // &
+ 0x34, // '
+ 0x26|SHIFT, // (
+ 0x27|SHIFT, // )
+ 0x25|SHIFT, // *
+ 0x2e|SHIFT, // +
+ 0x36, // ,
+ 0x2d, // -
+ 0x37, // .
+ 0x38, // /
+ 0x27, // 0
+ 0x1e, // 1
+ 0x1f, // 2
+ 0x20, // 3
+ 0x21, // 4
+ 0x22, // 5
+ 0x23, // 6
+ 0x24, // 7
+ 0x25, // 8
+ 0x26, // 9
+ 0x33|SHIFT, // :
+ 0x33, // ;
+ 0x36|SHIFT, // <
+ 0x2e, // =
+ 0x37|SHIFT, // >
+ 0x38|SHIFT, // ?
+ 0x1f|SHIFT, // @
+ 0x04|SHIFT, // A
+ 0x05|SHIFT, // B
+ 0x06|SHIFT, // C
+ 0x07|SHIFT, // D
+ 0x08|SHIFT, // E
+ 0x09|SHIFT, // F
+ 0x0a|SHIFT, // G
+ 0x0b|SHIFT, // H
+ 0x0c|SHIFT, // I
+ 0x0d|SHIFT, // J
+ 0x0e|SHIFT, // K
+ 0x0f|SHIFT, // L
+ 0x10|SHIFT, // M
+ 0x11|SHIFT, // N
+ 0x12|SHIFT, // O
+ 0x13|SHIFT, // P
+ 0x14|SHIFT, // Q
+ 0x15|SHIFT, // R
+ 0x16|SHIFT, // S
+ 0x17|SHIFT, // T
+ 0x18|SHIFT, // U
+ 0x19|SHIFT, // V
+ 0x1a|SHIFT, // W
+ 0x1b|SHIFT, // X
+ 0x1c|SHIFT, // Y
+ 0x1d|SHIFT, // Z
+ 0x2f, // [
+ 0x31, // bslash
+ 0x30, // ]
+ 0x23|SHIFT, // ^
+ 0x2d|SHIFT, // _
+ 0x35, // `
+ 0x04, // a
+ 0x05, // b
+ 0x06, // c
+ 0x07, // d
+ 0x08, // e
+ 0x09, // f
+ 0x0a, // g
+ 0x0b, // h
+ 0x0c, // i
+ 0x0d, // j
+ 0x0e, // k
+ 0x0f, // l
+ 0x10, // m
+ 0x11, // n
+ 0x12, // o
+ 0x13, // p
+ 0x14, // q
+ 0x15, // r
+ 0x16, // s
+ 0x17, // t
+ 0x18, // u
+ 0x19, // v
+ 0x1a, // w
+ 0x1b, // x
+ 0x1c, // y
+ 0x1d, // z
+ 0x2f|SHIFT, //
+ 0x31|SHIFT, // |
+ 0x30|SHIFT, // }
+ 0x35|SHIFT, // ~
+ 0 // DEL
+};
+
+uint8_t USBPutChar(uint8_t c);
+
+// press() adds the specified key (printing, non-printing, or modifier)
+// to the persistent key report and sends the report. Because of the way
+// USB HID works, the host acts like the key remains pressed until we
+// call release(), releaseAll(), or otherwise clear the report and resend.
+size_t Keyboard_::press(uint8_t k)
+{
+ uint8_t i;
+ if (k >= 136) { // it's a non-printing key (not a modifier)
+ k = k - 136;
+ } else if (k >= 128) { // it's a modifier key
+ _keyReport.modifiers |= (1<<(k-128));
+ k = 0;
+ } else { // it's a printing key
+ k = pgm_read_byte(_asciimap + k);
+ if (!k) {
+ setWriteError();
+ return 0;
+ }
+ if (k & 0x80) { // it's a capital letter or other character reached with shift
+ _keyReport.modifiers |= 0x02; // the left shift modifier
+ k &= 0x7F;
+ }
+ }
+
+ // Add k to the key report only if it's not already present
+ // and if there is an empty slot.
+ if (_keyReport.keys[0] != k && _keyReport.keys[1] != k &&
+ _keyReport.keys[2] != k && _keyReport.keys[3] != k &&
+ _keyReport.keys[4] != k && _keyReport.keys[5] != k) {
+
+ for (i=0; i<6; i++) {
+ if (_keyReport.keys[i] == 0x00) {
+ _keyReport.keys[i] = k;
+ break;
+ }
+ }
+ if (i == 6) {
+ setWriteError();
+ return 0;
+ }
+ }
+ sendReport(&_keyReport);
+ return 1;
+}
+
+// release() takes the specified key out of the persistent key report and
+// sends the report. This tells the OS the key is no longer pressed and that
+// it shouldn't be repeated any more.
+size_t Keyboard_::release(uint8_t k)
+{
+ uint8_t i;
+ if (k >= 136) { // it's a non-printing key (not a modifier)
+ k = k - 136;
+ } else if (k >= 128) { // it's a modifier key
+ _keyReport.modifiers &= ~(1<<(k-128));
+ k = 0;
+ } else { // it's a printing key
+ k = pgm_read_byte(_asciimap + k);
+ if (!k) {
+ return 0;
+ }
+ if (k & 0x80) { // it's a capital letter or other character reached with shift
+ _keyReport.modifiers &= ~(0x02); // the left shift modifier
+ k &= 0x7F;
+ }
+ }
+
+ // Test the key report to see if k is present. Clear it if it exists.
+ // Check all positions in case the key is present more than once (which it shouldn't be)
+ for (i=0; i<6; i++) {
+ if (0 != k && _keyReport.keys[i] == k) {
+ _keyReport.keys[i] = 0x00;
+ }
+ }
+
+ sendReport(&_keyReport);
+ return 1;
+}
+
+void Keyboard_::releaseAll(void)
+{
+ _keyReport.keys[0] = 0;
+ _keyReport.keys[1] = 0;
+ _keyReport.keys[2] = 0;
+ _keyReport.keys[3] = 0;
+ _keyReport.keys[4] = 0;
+ _keyReport.keys[5] = 0;
+ _keyReport.modifiers = 0;
+ sendReport(&_keyReport);
+}
+
+size_t Keyboard_::write(uint8_t c)
+{
+ uint8_t p = press(c); // Keydown
+ uint8_t r = release(c); // Keyup
+ return (p); // just return the result of press() since release() almost always returns 1
+}
+
+#endif
+
+#endif /* if defined(USBCON) */ \ No newline at end of file
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/HardwareSerial.cpp b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/HardwareSerial.cpp
new file mode 100644
index 000000000..f40ddee06
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/HardwareSerial.cpp
@@ -0,0 +1,428 @@
+/*
+ HardwareSerial.cpp - Hardware serial library for Wiring
+ Copyright (c) 2006 Nicholas Zambetti. All right reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Modified 23 November 2006 by David A. Mellis
+ Modified 28 September 2010 by Mark Sproul
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include "Arduino.h"
+#include "wiring_private.h"
+
+// this next line disables the entire HardwareSerial.cpp,
+// this is so I can support Attiny series and any other chip without a uart
+#if defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H)
+
+#include "HardwareSerial.h"
+
+// Define constants and variables for buffering incoming serial data. We're
+// using a ring buffer (I think), in which head is the index of the location
+// to which to write the next incoming character and tail is the index of the
+// location from which to read.
+#if (RAMEND < 1000)
+ #define SERIAL_BUFFER_SIZE 16
+#else
+ #define SERIAL_BUFFER_SIZE 64
+#endif
+
+struct ring_buffer
+{
+ unsigned char buffer[SERIAL_BUFFER_SIZE];
+ volatile unsigned int head;
+ volatile unsigned int tail;
+};
+
+#if defined(USBCON)
+ ring_buffer rx_buffer = { { 0 }, 0, 0};
+ ring_buffer tx_buffer = { { 0 }, 0, 0};
+#endif
+#if defined(UBRRH) || defined(UBRR0H)
+ ring_buffer rx_buffer = { { 0 }, 0, 0 };
+ ring_buffer tx_buffer = { { 0 }, 0, 0 };
+#endif
+#if defined(UBRR1H)
+ ring_buffer rx_buffer1 = { { 0 }, 0, 0 };
+ ring_buffer tx_buffer1 = { { 0 }, 0, 0 };
+#endif
+#if defined(UBRR2H)
+ ring_buffer rx_buffer2 = { { 0 }, 0, 0 };
+ ring_buffer tx_buffer2 = { { 0 }, 0, 0 };
+#endif
+#if defined(UBRR3H)
+ ring_buffer rx_buffer3 = { { 0 }, 0, 0 };
+ ring_buffer tx_buffer3 = { { 0 }, 0, 0 };
+#endif
+
+inline void store_char(unsigned char c, ring_buffer *buffer)
+{
+ int i = (unsigned int)(buffer->head + 1) % SERIAL_BUFFER_SIZE;
+
+ // if we should be storing the received character into the location
+ // just before the tail (meaning that the head would advance to the
+ // current location of the tail), we're about to overflow the buffer
+ // and so we don't write the character or advance the head.
+ if (i != buffer->tail) {
+ buffer->buffer[buffer->head] = c;
+ buffer->head = i;
+ }
+}
+
+#if !defined(USART0_RX_vect) && defined(USART1_RX_vect)
+// do nothing - on the 32u4 the first USART is USART1
+#else
+#if !defined(USART_RX_vect) && !defined(SIG_USART0_RECV) && \
+ !defined(SIG_UART0_RECV) && !defined(USART0_RX_vect) && \
+ !defined(SIG_UART_RECV)
+ #error "Don't know what the Data Received vector is called for the first UART"
+#else
+ void serialEvent() __attribute__((weak));
+ void serialEvent() {}
+ #define serialEvent_implemented
+#if defined(USART_RX_vect)
+ SIGNAL(USART_RX_vect)
+#elif defined(SIG_USART0_RECV)
+ SIGNAL(SIG_USART0_RECV)
+#elif defined(SIG_UART0_RECV)
+ SIGNAL(SIG_UART0_RECV)
+#elif defined(USART0_RX_vect)
+ SIGNAL(USART0_RX_vect)
+#elif defined(SIG_UART_RECV)
+ SIGNAL(SIG_UART_RECV)
+#endif
+ {
+ #if defined(UDR0)
+ unsigned char c = UDR0;
+ #elif defined(UDR)
+ unsigned char c = UDR;
+ #else
+ #error UDR not defined
+ #endif
+ store_char(c, &rx_buffer);
+ }
+#endif
+#endif
+
+#if defined(USART1_RX_vect)
+ void serialEvent1() __attribute__((weak));
+ void serialEvent1() {}
+ #define serialEvent1_implemented
+ SIGNAL(USART1_RX_vect)
+ {
+ unsigned char c = UDR1;
+ store_char(c, &rx_buffer1);
+ }
+#elif defined(SIG_USART1_RECV)
+ #error SIG_USART1_RECV
+#endif
+
+#if defined(USART2_RX_vect) && defined(UDR2)
+ void serialEvent2() __attribute__((weak));
+ void serialEvent2() {}
+ #define serialEvent2_implemented
+ SIGNAL(USART2_RX_vect)
+ {
+ unsigned char c = UDR2;
+ store_char(c, &rx_buffer2);
+ }
+#elif defined(SIG_USART2_RECV)
+ #error SIG_USART2_RECV
+#endif
+
+#if defined(USART3_RX_vect) && defined(UDR3)
+ void serialEvent3() __attribute__((weak));
+ void serialEvent3() {}
+ #define serialEvent3_implemented
+ SIGNAL(USART3_RX_vect)
+ {
+ unsigned char c = UDR3;
+ store_char(c, &rx_buffer3);
+ }
+#elif defined(SIG_USART3_RECV)
+ #error SIG_USART3_RECV
+#endif
+
+void serialEventRun(void)
+{
+#ifdef serialEvent_implemented
+ if (Serial.available()) serialEvent();
+#endif
+#ifdef serialEvent1_implemented
+ if (Serial1.available()) serialEvent1();
+#endif
+#ifdef serialEvent2_implemented
+ if (Serial2.available()) serialEvent2();
+#endif
+#ifdef serialEvent3_implemented
+ if (Serial3.available()) serialEvent3();
+#endif
+}
+
+
+#if !defined(USART0_UDRE_vect) && defined(USART1_UDRE_vect)
+// do nothing - on the 32u4 the first USART is USART1
+#else
+#if !defined(UART0_UDRE_vect) && !defined(UART_UDRE_vect) && !defined(USART0_UDRE_vect) && !defined(USART_UDRE_vect)
+ #error "Don't know what the Data Register Empty vector is called for the first UART"
+#else
+#if defined(UART0_UDRE_vect)
+ISR(UART0_UDRE_vect)
+#elif defined(UART_UDRE_vect)
+ISR(UART_UDRE_vect)
+#elif defined(USART0_UDRE_vect)
+ISR(USART0_UDRE_vect)
+#elif defined(USART_UDRE_vect)
+ISR(USART_UDRE_vect)
+#endif
+{
+ if (tx_buffer.head == tx_buffer.tail) {
+ // Buffer empty, so disable interrupts
+#if defined(UCSR0B)
+ cbi(UCSR0B, UDRIE0);
+#else
+ cbi(UCSRB, UDRIE);
+#endif
+ }
+ else {
+ // There is more data in the output buffer. Send the next byte
+ unsigned char c = tx_buffer.buffer[tx_buffer.tail];
+ tx_buffer.tail = (tx_buffer.tail + 1) % SERIAL_BUFFER_SIZE;
+
+ #if defined(UDR0)
+ UDR0 = c;
+ #elif defined(UDR)
+ UDR = c;
+ #else
+ #error UDR not defined
+ #endif
+ }
+}
+#endif
+#endif
+
+#ifdef USART1_UDRE_vect
+ISR(USART1_UDRE_vect)
+{
+ if (tx_buffer1.head == tx_buffer1.tail) {
+ // Buffer empty, so disable interrupts
+ cbi(UCSR1B, UDRIE1);
+ }
+ else {
+ // There is more data in the output buffer. Send the next byte
+ unsigned char c = tx_buffer1.buffer[tx_buffer1.tail];
+ tx_buffer1.tail = (tx_buffer1.tail + 1) % SERIAL_BUFFER_SIZE;
+
+ UDR1 = c;
+ }
+}
+#endif
+
+#ifdef USART2_UDRE_vect
+ISR(USART2_UDRE_vect)
+{
+ if (tx_buffer2.head == tx_buffer2.tail) {
+ // Buffer empty, so disable interrupts
+ cbi(UCSR2B, UDRIE2);
+ }
+ else {
+ // There is more data in the output buffer. Send the next byte
+ unsigned char c = tx_buffer2.buffer[tx_buffer2.tail];
+ tx_buffer2.tail = (tx_buffer2.tail + 1) % SERIAL_BUFFER_SIZE;
+
+ UDR2 = c;
+ }
+}
+#endif
+
+#ifdef USART3_UDRE_vect
+ISR(USART3_UDRE_vect)
+{
+ if (tx_buffer3.head == tx_buffer3.tail) {
+ // Buffer empty, so disable interrupts
+ cbi(UCSR3B, UDRIE3);
+ }
+ else {
+ // There is more data in the output buffer. Send the next byte
+ unsigned char c = tx_buffer3.buffer[tx_buffer3.tail];
+ tx_buffer3.tail = (tx_buffer3.tail + 1) % SERIAL_BUFFER_SIZE;
+
+ UDR3 = c;
+ }
+}
+#endif
+
+
+// Constructors ////////////////////////////////////////////////////////////////
+
+HardwareSerial::HardwareSerial(ring_buffer *rx_buffer, ring_buffer *tx_buffer,
+ volatile uint8_t *ubrrh, volatile uint8_t *ubrrl,
+ volatile uint8_t *ucsra, volatile uint8_t *ucsrb,
+ volatile uint8_t *udr,
+ uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udrie, uint8_t u2x)
+{
+ _rx_buffer = rx_buffer;
+ _tx_buffer = tx_buffer;
+ _ubrrh = ubrrh;
+ _ubrrl = ubrrl;
+ _ucsra = ucsra;
+ _ucsrb = ucsrb;
+ _udr = udr;
+ _rxen = rxen;
+ _txen = txen;
+ _rxcie = rxcie;
+ _udrie = udrie;
+ _u2x = u2x;
+}
+
+// Public Methods //////////////////////////////////////////////////////////////
+
+void HardwareSerial::begin(unsigned long baud)
+{
+ uint16_t baud_setting;
+ bool use_u2x = true;
+
+#if F_CPU == 16000000UL
+ // hardcoded exception for compatibility with the bootloader shipped
+ // with the Duemilanove and previous boards and the firmware on the 8U2
+ // on the Uno and Mega 2560.
+ if (baud == 57600) {
+ use_u2x = false;
+ }
+#endif
+
+try_again:
+
+ if (use_u2x) {
+ *_ucsra = 1 << _u2x;
+ baud_setting = (F_CPU / 4 / baud - 1) / 2;
+ } else {
+ *_ucsra = 0;
+ baud_setting = (F_CPU / 8 / baud - 1) / 2;
+ }
+
+ if ((baud_setting > 4095) && use_u2x)
+ {
+ use_u2x = false;
+ goto try_again;
+ }
+
+ // assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register)
+ *_ubrrh = baud_setting >> 8;
+ *_ubrrl = baud_setting;
+
+ sbi(*_ucsrb, _rxen);
+ sbi(*_ucsrb, _txen);
+ sbi(*_ucsrb, _rxcie);
+ cbi(*_ucsrb, _udrie);
+}
+
+void HardwareSerial::end()
+{
+ // wait for transmission of outgoing data
+ while (_tx_buffer->head != _tx_buffer->tail)
+ ;
+
+ cbi(*_ucsrb, _rxen);
+ cbi(*_ucsrb, _txen);
+ cbi(*_ucsrb, _rxcie);
+ cbi(*_ucsrb, _udrie);
+
+ // clear any received data
+ _rx_buffer->head = _rx_buffer->tail;
+}
+
+int HardwareSerial::available(void)
+{
+ return (unsigned int)(SERIAL_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % SERIAL_BUFFER_SIZE;
+}
+
+int HardwareSerial::peek(void)
+{
+ if (_rx_buffer->head == _rx_buffer->tail) {
+ return -1;
+ } else {
+ return _rx_buffer->buffer[_rx_buffer->tail];
+ }
+}
+
+int HardwareSerial::read(void)
+{
+ // if the head isn't ahead of the tail, we don't have any characters
+ if (_rx_buffer->head == _rx_buffer->tail) {
+ return -1;
+ } else {
+ unsigned char c = _rx_buffer->buffer[_rx_buffer->tail];
+ _rx_buffer->tail = (unsigned int)(_rx_buffer->tail + 1) % SERIAL_BUFFER_SIZE;
+ return c;
+ }
+}
+
+void HardwareSerial::flush()
+{
+ while (_tx_buffer->head != _tx_buffer->tail)
+ ;
+}
+
+size_t HardwareSerial::write(uint8_t c)
+{
+ int i = (_tx_buffer->head + 1) % SERIAL_BUFFER_SIZE;
+
+ // If the output buffer is full, there's nothing for it other than to
+ // wait for the interrupt handler to empty it a bit
+ // ???: return 0 here instead?
+ while (i == _tx_buffer->tail)
+ ;
+
+ _tx_buffer->buffer[_tx_buffer->head] = c;
+ _tx_buffer->head = i;
+
+ sbi(*_ucsrb, _udrie);
+
+ return 1;
+}
+
+HardwareSerial::operator bool() {
+ return true;
+}
+
+// Preinstantiate Objects //////////////////////////////////////////////////////
+
+#if defined(UBRRH) && defined(UBRRL)
+ HardwareSerial Serial(&rx_buffer, &tx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UDR, RXEN, TXEN, RXCIE, UDRIE, U2X);
+#elif defined(UBRR0H) && defined(UBRR0L)
+ HardwareSerial Serial(&rx_buffer, &tx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRIE0, U2X0);
+#elif defined(USBCON)
+ // do nothing - Serial object and buffers are initialized in CDC code
+#else
+ #error no serial port defined (port 0)
+#endif
+
+#if defined(UBRR1H)
+ HardwareSerial Serial1(&rx_buffer1, &tx_buffer1, &UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UDR1, RXEN1, TXEN1, RXCIE1, UDRIE1, U2X1);
+#endif
+#if defined(UBRR2H)
+ HardwareSerial Serial2(&rx_buffer2, &tx_buffer2, &UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UDR2, RXEN2, TXEN2, RXCIE2, UDRIE2, U2X2);
+#endif
+#if defined(UBRR3H)
+ HardwareSerial Serial3(&rx_buffer3, &tx_buffer3, &UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UDR3, RXEN3, TXEN3, RXCIE3, UDRIE3, U2X3);
+#endif
+
+#endif // whole file
+
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/HardwareSerial.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/HardwareSerial.h
new file mode 100644
index 000000000..bf4924c6d
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/HardwareSerial.h
@@ -0,0 +1,81 @@
+/*
+ HardwareSerial.h - Hardware serial library for Wiring
+ Copyright (c) 2006 Nicholas Zambetti. All right reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Modified 28 September 2010 by Mark Sproul
+*/
+
+#ifndef HardwareSerial_h
+#define HardwareSerial_h
+
+#include <inttypes.h>
+
+#include "Stream.h"
+
+struct ring_buffer;
+
+class HardwareSerial : public Stream
+{
+ private:
+ ring_buffer *_rx_buffer;
+ ring_buffer *_tx_buffer;
+ volatile uint8_t *_ubrrh;
+ volatile uint8_t *_ubrrl;
+ volatile uint8_t *_ucsra;
+ volatile uint8_t *_ucsrb;
+ volatile uint8_t *_udr;
+ uint8_t _rxen;
+ uint8_t _txen;
+ uint8_t _rxcie;
+ uint8_t _udrie;
+ uint8_t _u2x;
+ public:
+ HardwareSerial(ring_buffer *rx_buffer, ring_buffer *tx_buffer,
+ volatile uint8_t *ubrrh, volatile uint8_t *ubrrl,
+ volatile uint8_t *ucsra, volatile uint8_t *ucsrb,
+ volatile uint8_t *udr,
+ uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udrie, uint8_t u2x);
+ void begin(unsigned long);
+ void end();
+ virtual int available(void);
+ virtual int peek(void);
+ virtual int read(void);
+ virtual void flush(void);
+ virtual size_t write(uint8_t);
+ using Print::write; // pull in write(str) and write(buf, size) from Print
+ operator bool();
+};
+
+#if defined(UBRRH) || defined(UBRR0H)
+ extern HardwareSerial Serial;
+#elif defined(USBCON)
+ #include "USBAPI.h"
+// extern HardwareSerial Serial_;
+#endif
+#if defined(UBRR1H)
+ extern HardwareSerial Serial1;
+#endif
+#if defined(UBRR2H)
+ extern HardwareSerial Serial2;
+#endif
+#if defined(UBRR3H)
+ extern HardwareSerial Serial3;
+#endif
+
+extern void serialEventRun(void) __attribute__((weak));
+
+#endif
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/IPAddress.cpp b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/IPAddress.cpp
new file mode 100644
index 000000000..fe3deb77a
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/IPAddress.cpp
@@ -0,0 +1,56 @@
+
+#include <Arduino.h>
+#include <IPAddress.h>
+
+IPAddress::IPAddress()
+{
+ memset(_address, 0, sizeof(_address));
+}
+
+IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet)
+{
+ _address[0] = first_octet;
+ _address[1] = second_octet;
+ _address[2] = third_octet;
+ _address[3] = fourth_octet;
+}
+
+IPAddress::IPAddress(uint32_t address)
+{
+ memcpy(_address, &address, sizeof(_address));
+}
+
+IPAddress::IPAddress(const uint8_t *address)
+{
+ memcpy(_address, address, sizeof(_address));
+}
+
+IPAddress& IPAddress::operator=(const uint8_t *address)
+{
+ memcpy(_address, address, sizeof(_address));
+ return *this;
+}
+
+IPAddress& IPAddress::operator=(uint32_t address)
+{
+ memcpy(_address, (const uint8_t *)&address, sizeof(_address));
+ return *this;
+}
+
+bool IPAddress::operator==(const uint8_t* addr)
+{
+ return memcmp(addr, _address, sizeof(_address)) == 0;
+}
+
+size_t IPAddress::printTo(Print& p) const
+{
+ size_t n = 0;
+ for (int i =0; i < 3; i++)
+ {
+ n += p.print(_address[i], DEC);
+ n += p.print('.');
+ }
+ n += p.print(_address[3], DEC);
+ return n;
+}
+
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/IPAddress.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/IPAddress.h
new file mode 100644
index 000000000..2585aec0e
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/IPAddress.h
@@ -0,0 +1,76 @@
+/*
+ *
+ * MIT License:
+ * Copyright (c) 2011 Adrian McEwen
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * adrianm@mcqn.com 1/1/2011
+ */
+
+#ifndef IPAddress_h
+#define IPAddress_h
+
+#include <Printable.h>
+
+// A class to make it easier to handle and pass around IP addresses
+
+class IPAddress : public Printable {
+private:
+ uint8_t _address[4]; // IPv4 address
+ // Access the raw byte array containing the address. Because this returns a pointer
+ // to the internal structure rather than a copy of the address this function should only
+ // be used when you know that the usage of the returned uint8_t* will be transient and not
+ // stored.
+ uint8_t* raw_address() { return _address; };
+
+public:
+ // Constructors
+ IPAddress();
+ IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet);
+ IPAddress(uint32_t address);
+ IPAddress(const uint8_t *address);
+
+ // Overloaded cast operator to allow IPAddress objects to be used where a pointer
+ // to a four-byte uint8_t array is expected
+ operator uint32_t() { return *((uint32_t*)_address); };
+ bool operator==(const IPAddress& addr) { return (*((uint32_t*)_address)) == (*((uint32_t*)addr._address)); };
+ bool operator==(const uint8_t* addr);
+
+ // Overloaded index operator to allow getting and setting individual octets of the address
+ uint8_t operator[](int index) const { return _address[index]; };
+ uint8_t& operator[](int index) { return _address[index]; };
+
+ // Overloaded copy operators to allow initialisation of IPAddress objects from other types
+ IPAddress& operator=(const uint8_t *address);
+ IPAddress& operator=(uint32_t address);
+
+ virtual size_t printTo(Print& p) const;
+
+ friend class EthernetClass;
+ friend class UDP;
+ friend class Client;
+ friend class Server;
+ friend class DhcpClass;
+ friend class DNSClient;
+};
+
+const IPAddress INADDR_NONE(0,0,0,0);
+
+
+#endif
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Platform.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Platform.h
new file mode 100644
index 000000000..8b8f74277
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Platform.h
@@ -0,0 +1,23 @@
+
+#ifndef __PLATFORM_H__
+#define __PLATFORM_H__
+
+#include <inttypes.h>
+#include <avr/pgmspace.h>
+#include <avr/eeprom.h>
+#include <avr/interrupt.h>
+#include <util/delay.h>
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned long u32;
+
+#include "Arduino.h"
+
+#if defined(USBCON)
+ #include "USBDesc.h"
+ #include "USBCore.h"
+ #include "USBAPI.h"
+#endif /* if defined(USBCON) */
+
+#endif
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Print.cpp b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Print.cpp
new file mode 100644
index 000000000..e541a6ce7
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Print.cpp
@@ -0,0 +1,263 @@
+/*
+ Print.cpp - Base class that provides print() and println()
+ Copyright (c) 2008 David A. Mellis. All right reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Modified 23 November 2006 by David A. Mellis
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include "Arduino.h"
+
+#include "Print.h"
+
+// Public Methods //////////////////////////////////////////////////////////////
+
+/* default implementation: may be overridden */
+size_t Print::write(const uint8_t *buffer, size_t size)
+{
+ size_t n = 0;
+ while (size--) {
+ n += write(*buffer++);
+ }
+ return n;
+}
+
+size_t Print::print(const __FlashStringHelper *ifsh)
+{
+ const char PROGMEM *p = (const char PROGMEM *)ifsh;
+ size_t n = 0;
+ while (1) {
+ unsigned char c = pgm_read_byte(p++);
+ if (c == 0) break;
+ n += write(c);
+ }
+ return n;
+}
+
+size_t Print::print(const String &s)
+{
+ size_t n = 0;
+ for (uint16_t i = 0; i < s.length(); i++) {
+ n += write(s[i]);
+ }
+ return n;
+}
+
+size_t Print::print(const char str[])
+{
+ return write(str);
+}
+
+size_t Print::print(char c)
+{
+ return write(c);
+}
+
+size_t Print::print(unsigned char b, int base)
+{
+ return print((unsigned long) b, base);
+}
+
+size_t Print::print(int n, int base)
+{
+ return print((long) n, base);
+}
+
+size_t Print::print(unsigned int n, int base)
+{
+ return print((unsigned long) n, base);
+}
+
+size_t Print::print(long n, int base)
+{
+ if (base == 0) {
+ return write(n);
+ } else if (base == 10) {
+ if (n < 0) {
+ int t = print('-');
+ n = -n;
+ return printNumber(n, 10) + t;
+ }
+ return printNumber(n, 10);
+ } else {
+ return printNumber(n, base);
+ }
+}
+
+size_t Print::print(unsigned long n, int base)
+{
+ if (base == 0) return write(n);
+ else return printNumber(n, base);
+}
+
+size_t Print::print(double n, int digits)
+{
+ return printFloat(n, digits);
+}
+
+size_t Print::println(const __FlashStringHelper *ifsh)
+{
+ size_t n = print(ifsh);
+ n += println();
+ return n;
+}
+
+size_t Print::print(const Printable& x)
+{
+ return x.printTo(*this);
+}
+
+size_t Print::println(void)
+{
+ size_t n = print('\r');
+ n += print('\n');
+ return n;
+}
+
+size_t Print::println(const String &s)
+{
+ size_t n = print(s);
+ n += println();
+ return n;
+}
+
+size_t Print::println(const char c[])
+{
+ size_t n = print(c);
+ n += println();
+ return n;
+}
+
+size_t Print::println(char c)
+{
+ size_t n = print(c);
+ n += println();
+ return n;
+}
+
+size_t Print::println(unsigned char b, int base)
+{
+ size_t n = print(b, base);
+ n += println();
+ return n;
+}
+
+size_t Print::println(int num, int base)
+{
+ size_t n = print(num, base);
+ n += println();
+ return n;
+}
+
+size_t Print::println(unsigned int num, int base)
+{
+ size_t n = print(num, base);
+ n += println();
+ return n;
+}
+
+size_t Print::println(long num, int base)
+{
+ size_t n = print(num, base);
+ n += println();
+ return n;
+}
+
+size_t Print::println(unsigned long num, int base)
+{
+ size_t n = print(num, base);
+ n += println();
+ return n;
+}
+
+size_t Print::println(double num, int digits)
+{
+ size_t n = print(num, digits);
+ n += println();
+ return n;
+}
+
+size_t Print::println(const Printable& x)
+{
+ size_t n = print(x);
+ n += println();
+ return n;
+}
+
+// Private Methods /////////////////////////////////////////////////////////////
+
+size_t Print::printNumber(unsigned long n, uint8_t base) {
+ char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
+ char *str = &buf[sizeof(buf) - 1];
+
+ *str = '\0';
+
+ // prevent crash if called with base == 1
+ if (base < 2) base = 10;
+
+ do {
+ unsigned long m = n;
+ n /= base;
+ char c = m - base * n;
+ *--str = c < 10 ? c + '0' : c + 'A' - 10;
+ } while(n);
+
+ return write(str);
+}
+
+size_t Print::printFloat(double number, uint8_t digits)
+{
+ size_t n = 0;
+
+ // Handle negative numbers
+ if (number < 0.0)
+ {
+ n += print('-');
+ number = -number;
+ }
+
+ // Round correctly so that print(1.999, 2) prints as "2.00"
+ double rounding = 0.5;
+ for (uint8_t i=0; i<digits; ++i)
+ rounding /= 10.0;
+
+ number += rounding;
+
+ // Extract the integer part of the number and print it
+ unsigned long int_part = (unsigned long)number;
+ double remainder = number - (double)int_part;
+ n += print(int_part);
+
+ // Print the decimal point, but only if there are digits beyond
+ if (digits > 0) {
+ n += print(".");
+ }
+
+ // Extract digits from the remainder one at a time
+ while (digits-- > 0)
+ {
+ remainder *= 10.0;
+ int toPrint = int(remainder);
+ n += print(toPrint);
+ remainder -= toPrint;
+ }
+
+ return n;
+}
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Print.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Print.h
new file mode 100644
index 000000000..1af6b723f
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Print.h
@@ -0,0 +1,78 @@
+/*
+ Print.h - Base class that provides print() and println()
+ Copyright (c) 2008 David A. Mellis. All right reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef Print_h
+#define Print_h
+
+#include <inttypes.h>
+#include <stdio.h> // for size_t
+
+#include "WString.h"
+#include "Printable.h"
+
+#define DEC 10
+#define HEX 16
+#define OCT 8
+#define BIN 2
+
+class Print
+{
+ private:
+ int write_error;
+ size_t printNumber(unsigned long, uint8_t);
+ size_t printFloat(double, uint8_t);
+ protected:
+ void setWriteError(int err = 1) { write_error = err; }
+ public:
+ Print() : write_error(0) {}
+
+ int getWriteError() { return write_error; }
+ void clearWriteError() { setWriteError(0); }
+
+ virtual size_t write(uint8_t) = 0;
+ size_t write(const char *str) { return write((const uint8_t *)str, strlen(str)); }
+ virtual size_t write(const uint8_t *buffer, size_t size);
+
+ size_t print(const __FlashStringHelper *);
+ size_t print(const String &);
+ size_t print(const char[]);
+ size_t print(char);
+ size_t print(unsigned char, int = DEC);
+ size_t print(int, int = DEC);
+ size_t print(unsigned int, int = DEC);
+ size_t print(long, int = DEC);
+ size_t print(unsigned long, int = DEC);
+ size_t print(double, int = 2);
+ size_t print(const Printable&);
+
+ size_t println(const __FlashStringHelper *);
+ size_t println(const String &s);
+ size_t println(const char[]);
+ size_t println(char);
+ size_t println(unsigned char, int = DEC);
+ size_t println(int, int = DEC);
+ size_t println(unsigned int, int = DEC);
+ size_t println(long, int = DEC);
+ size_t println(unsigned long, int = DEC);
+ size_t println(double, int = 2);
+ size_t println(const Printable&);
+ size_t println(void);
+};
+
+#endif
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Printable.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Printable.h
new file mode 100644
index 000000000..d03c9af62
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Printable.h
@@ -0,0 +1,40 @@
+/*
+ Printable.h - Interface class that allows printing of complex types
+ Copyright (c) 2011 Adrian McEwen. All right reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef Printable_h
+#define Printable_h
+
+#include <new.h>
+
+class Print;
+
+/** The Printable class provides a way for new classes to allow themselves to be printed.
+ By deriving from Printable and implementing the printTo method, it will then be possible
+ for users to print out instances of this class by passing them into the usual
+ Print::print and Print::println methods.
+*/
+
+class Printable
+{
+ public:
+ virtual size_t printTo(Print& p) const = 0;
+};
+
+#endif
+
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Server.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Server.h
new file mode 100644
index 000000000..9674c7626
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Server.h
@@ -0,0 +1,9 @@
+#ifndef server_h
+#define server_h
+
+class Server : public Print {
+public:
+ virtual void begin() =0;
+};
+
+#endif
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Stream.cpp b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Stream.cpp
new file mode 100644
index 000000000..aafb7fcf9
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Stream.cpp
@@ -0,0 +1,270 @@
+/*
+ Stream.cpp - adds parsing methods to Stream class
+ Copyright (c) 2008 David A. Mellis. All right reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Created July 2011
+ parsing functions based on TextFinder library by Michael Margolis
+ */
+
+#include "Arduino.h"
+#include "Stream.h"
+
+#define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait
+#define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field
+
+// private method to read stream with timeout
+int Stream::timedRead()
+{
+ int c;
+ _startMillis = millis();
+ do {
+ c = read();
+ if (c >= 0) return c;
+ } while(millis() - _startMillis < _timeout);
+ return -1; // -1 indicates timeout
+}
+
+// private method to peek stream with timeout
+int Stream::timedPeek()
+{
+ int c;
+ _startMillis = millis();
+ do {
+ c = peek();
+ if (c >= 0) return c;
+ } while(millis() - _startMillis < _timeout);
+ return -1; // -1 indicates timeout
+}
+
+// returns peek of the next digit in the stream or -1 if timeout
+// discards non-numeric characters
+int Stream::peekNextDigit()
+{
+ int c;
+ while (1) {
+ c = timedPeek();
+ if (c < 0) return c; // timeout
+ if (c == '-') return c;
+ if (c >= '0' && c <= '9') return c;
+ read(); // discard non-numeric
+ }
+}
+
+// Public Methods
+//////////////////////////////////////////////////////////////
+
+void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait
+{
+ _timeout = timeout;
+}
+
+ // find returns true if the target string is found
+bool Stream::find(char *target)
+{
+ return findUntil(target, NULL);
+}
+
+// reads data from the stream until the target string of given length is found
+// returns true if target string is found, false if timed out
+bool Stream::find(char *target, size_t length)
+{
+ return findUntil(target, length, NULL, 0);
+}
+
+// as find but search ends if the terminator string is found
+bool Stream::findUntil(char *target, char *terminator)
+{
+ return findUntil(target, strlen(target), terminator, strlen(terminator));
+}
+
+// reads data from the stream until the target string of the given length is found
+// search terminated if the terminator string is found
+// returns true if target string is found, false if terminated or timed out
+bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t termLen)
+{
+ size_t index = 0; // maximum target string length is 64k bytes!
+ size_t termIndex = 0;
+ int c;
+
+ if( *target == 0)
+ return true; // return true if target is a null string
+ while( (c = timedRead()) > 0){
+
+ if(c != target[index])
+ index = 0; // reset index if any char does not match
+
+ if( c == target[index]){
+ //////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1);
+ if(++index >= targetLen){ // return true if all chars in the target match
+ return true;
+ }
+ }
+
+ if(termLen > 0 && c == terminator[termIndex]){
+ if(++termIndex >= termLen)
+ return false; // return false if terminate string found before target string
+ }
+ else
+ termIndex = 0;
+ }
+ return false;
+}
+
+
+// returns the first valid (long) integer value from the current position.
+// initial characters that are not digits (or the minus sign) are skipped
+// function is terminated by the first character that is not a digit.
+long Stream::parseInt()
+{
+ return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout)
+}
+
+// as above but a given skipChar is ignored
+// this allows format characters (typically commas) in values to be ignored
+long Stream::parseInt(char skipChar)
+{
+ boolean isNegative = false;
+ long value = 0;
+ int c;
+
+ c = peekNextDigit();
+ // ignore non numeric leading characters
+ if(c < 0)
+ return 0; // zero returned if timeout
+
+ do{
+ if(c == skipChar)
+ ; // ignore this charactor
+ else if(c == '-')
+ isNegative = true;
+ else if(c >= '0' && c <= '9') // is c a digit?
+ value = value * 10 + c - '0';
+ read(); // consume the character we got with peek
+ c = timedPeek();
+ }
+ while( (c >= '0' && c <= '9') || c == skipChar );
+
+ if(isNegative)
+ value = -value;
+ return value;
+}
+
+
+// as parseInt but returns a floating point value
+float Stream::parseFloat()
+{
+ return parseFloat(NO_SKIP_CHAR);
+}
+
+// as above but the given skipChar is ignored
+// this allows format characters (typically commas) in values to be ignored
+float Stream::parseFloat(char skipChar){
+ boolean isNegative = false;
+ boolean isFraction = false;
+ long value = 0;
+ char c;
+ float fraction = 1.0;
+
+ c = peekNextDigit();
+ // ignore non numeric leading characters
+ if(c < 0)
+ return 0; // zero returned if timeout
+
+ do{
+ if(c == skipChar)
+ ; // ignore
+ else if(c == '-')
+ isNegative = true;
+ else if (c == '.')
+ isFraction = true;
+ else if(c >= '0' && c <= '9') { // is c a digit?
+ value = value * 10 + c - '0';
+ if(isFraction)
+ fraction *= 0.1;
+ }
+ read(); // consume the character we got with peek
+ c = timedPeek();
+ }
+ while( (c >= '0' && c <= '9') || c == '.' || c == skipChar );
+
+ if(isNegative)
+ value = -value;
+ if(isFraction)
+ return value * fraction;
+ else
+ return value;
+}
+
+// read characters from stream into buffer
+// terminates if length characters have been read, or timeout (see setTimeout)
+// returns the number of characters placed in the buffer
+// the buffer is NOT null terminated.
+//
+size_t Stream::readBytes(char *buffer, size_t length)
+{
+ size_t count = 0;
+ while (count < length) {
+ int c = timedRead();
+ if (c < 0) break;
+ *buffer++ = (char)c;
+ count++;
+ }
+ return count;
+}
+
+
+// as readBytes with terminator character
+// terminates if length characters have been read, timeout, or if the terminator character detected
+// returns the number of characters placed in the buffer (0 means no valid data found)
+
+size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)
+{
+ if (length < 1) return 0;
+ size_t index = 0;
+ while (index < length) {
+ int c = timedRead();
+ if (c < 0 || c == terminator) break;
+ *buffer++ = (char)c;
+ index++;
+ }
+ return index; // return number of characters, not including null terminator
+}
+
+String Stream::readString()
+{
+ String ret;
+ int c = timedRead();
+ while (c >= 0)
+ {
+ ret += (char)c;
+ c = timedRead();
+ }
+ return ret;
+}
+
+String Stream::readStringUntil(char terminator)
+{
+ String ret;
+ int c = timedRead();
+ while (c >= 0 && c != terminator)
+ {
+ ret += (char)c;
+ c = timedRead();
+ }
+ return ret;
+}
+
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Stream.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Stream.h
new file mode 100644
index 000000000..58bbf752f
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Stream.h
@@ -0,0 +1,96 @@
+/*
+ Stream.h - base class for character-based streams.
+ Copyright (c) 2010 David A. Mellis. All right reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ parsing functions based on TextFinder library by Michael Margolis
+*/
+
+#ifndef Stream_h
+#define Stream_h
+
+#include <inttypes.h>
+#include "Print.h"
+
+// compatability macros for testing
+/*
+#define getInt() parseInt()
+#define getInt(skipChar) parseInt(skipchar)
+#define getFloat() parseFloat()
+#define getFloat(skipChar) parseFloat(skipChar)
+#define getString( pre_string, post_string, buffer, length)
+readBytesBetween( pre_string, terminator, buffer, length)
+*/
+
+class Stream : public Print
+{
+ private:
+ unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read
+ unsigned long _startMillis; // used for timeout measurement
+ int timedRead(); // private method to read stream with timeout
+ int timedPeek(); // private method to peek stream with timeout
+ int peekNextDigit(); // returns the next numeric digit in the stream or -1 if timeout
+
+ public:
+ virtual int available() = 0;
+ virtual int read() = 0;
+ virtual int peek() = 0;
+ virtual void flush() = 0;
+
+ Stream() {_timeout=1000;}
+
+// parsing methods
+
+ void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second
+
+ bool find(char *target); // reads data from the stream until the target string is found
+ // returns true if target string is found, false if timed out (see setTimeout)
+
+ bool find(char *target, size_t length); // reads data from the stream until the target string of given length is found
+ // returns true if target string is found, false if timed out
+
+ bool findUntil(char *target, char *terminator); // as find but search ends if the terminator string is found
+
+ bool findUntil(char *target, size_t targetLen, char *terminate, size_t termLen); // as above but search ends if the terminate string is found
+
+
+ long parseInt(); // returns the first valid (long) integer value from the current position.
+ // initial characters that are not digits (or the minus sign) are skipped
+ // integer is terminated by the first character that is not a digit.
+
+ float parseFloat(); // float version of parseInt
+
+ size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer
+ // terminates if length characters have been read or timeout (see setTimeout)
+ // returns the number of characters placed in the buffer (0 means no valid data found)
+
+ size_t readBytesUntil( char terminator, char *buffer, size_t length); // as readBytes with terminator character
+ // terminates if length characters have been read, timeout, or if the terminator character detected
+ // returns the number of characters placed in the buffer (0 means no valid data found)
+
+ // Arduino String functions to be added here
+ String readString();
+ String readStringUntil(char terminator);
+
+ protected:
+ long parseInt(char skipChar); // as above but the given skipChar is ignored
+ // as above but the given skipChar is ignored
+ // this allows format characters (typically commas) in values to be ignored
+
+ float parseFloat(char skipChar); // as above but the given skipChar is ignored
+};
+
+#endif
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Tone.cpp b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Tone.cpp
new file mode 100644
index 000000000..20eed3f48
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Tone.cpp
@@ -0,0 +1,601 @@
+/* Tone.cpp
+
+ A Tone Generator Library
+
+ Written by Brett Hagman
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+Version Modified By Date Comments
+------- ----------- -------- --------
+0001 B Hagman 09/08/02 Initial coding
+0002 B Hagman 09/08/18 Multiple pins
+0003 B Hagman 09/08/18 Moved initialization from constructor to begin()
+0004 B Hagman 09/09/26 Fixed problems with ATmega8
+0005 B Hagman 09/11/23 Scanned prescalars for best fit on 8 bit timers
+ 09/11/25 Changed pin toggle method to XOR
+ 09/11/25 Fixed timer0 from being excluded
+0006 D Mellis 09/12/29 Replaced objects with functions
+0007 M Sproul 10/08/29 Changed #ifdefs from cpu to register
+*************************************************/
+
+#include <avr/interrupt.h>
+#include <avr/pgmspace.h>
+#include "Arduino.h"
+#include "pins_arduino.h"
+
+#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__)
+#define TCCR2A TCCR2
+#define TCCR2B TCCR2
+#define COM2A1 COM21
+#define COM2A0 COM20
+#define OCR2A OCR2
+#define TIMSK2 TIMSK
+#define OCIE2A OCIE2
+#define TIMER2_COMPA_vect TIMER2_COMP_vect
+#define TIMSK1 TIMSK
+#endif
+
+// timerx_toggle_count:
+// > 0 - duration specified
+// = 0 - stopped
+// < 0 - infinitely (until stop() method called, or new play() called)
+
+#if !defined(__AVR_ATmega8__)
+volatile long timer0_toggle_count;
+volatile uint8_t *timer0_pin_port;
+volatile uint8_t timer0_pin_mask;
+#endif
+
+volatile long timer1_toggle_count;
+volatile uint8_t *timer1_pin_port;
+volatile uint8_t timer1_pin_mask;
+volatile long timer2_toggle_count;
+volatile uint8_t *timer2_pin_port;
+volatile uint8_t timer2_pin_mask;
+
+#if defined(TIMSK3)
+volatile long timer3_toggle_count;
+volatile uint8_t *timer3_pin_port;
+volatile uint8_t timer3_pin_mask;
+#endif
+
+#if defined(TIMSK4)
+volatile long timer4_toggle_count;
+volatile uint8_t *timer4_pin_port;
+volatile uint8_t timer4_pin_mask;
+#endif
+
+#if defined(TIMSK5)
+volatile long timer5_toggle_count;
+volatile uint8_t *timer5_pin_port;
+volatile uint8_t timer5_pin_mask;
+#endif
+
+
+// MLS: This does not make sense, the 3 options are the same
+#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
+
+#define AVAILABLE_TONE_PINS 1
+
+const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 3, 4, 5, 1, 0 */ };
+static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255, 255, 255, 255, 255 */ };
+
+#elif defined(__AVR_ATmega8__)
+
+#define AVAILABLE_TONE_PINS 1
+
+const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1 */ };
+static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255 */ };
+
+#else
+
+#define AVAILABLE_TONE_PINS 1
+
+// Leave timer 0 to last.
+const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1, 0 */ };
+static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255, 255 */ };
+
+#endif
+
+
+
+static int8_t toneBegin(uint8_t _pin)
+{
+ int8_t _timer = -1;
+
+ // if we're already using the pin, the timer should be configured.
+ for (int i = 0; i < AVAILABLE_TONE_PINS; i++) {
+ if (tone_pins[i] == _pin) {
+ return pgm_read_byte(tone_pin_to_timer_PGM + i);
+ }
+ }
+
+ // search for an unused timer.
+ for (int i = 0; i < AVAILABLE_TONE_PINS; i++) {
+ if (tone_pins[i] == 255) {
+ tone_pins[i] = _pin;
+ _timer = pgm_read_byte(tone_pin_to_timer_PGM + i);
+ break;
+ }
+ }
+
+ if (_timer != -1)
+ {
+ // Set timer specific stuff
+ // All timers in CTC mode
+ // 8 bit timers will require changing prescalar values,
+ // whereas 16 bit timers are set to either ck/1 or ck/64 prescalar
+ switch (_timer)
+ {
+ #if defined(TCCR0A) && defined(TCCR0B)
+ case 0:
+ // 8 bit timer
+ TCCR0A = 0;
+ TCCR0B = 0;
+ bitWrite(TCCR0A, WGM01, 1);
+ bitWrite(TCCR0B, CS00, 1);
+ timer0_pin_port = portOutputRegister(digitalPinToPort(_pin));
+ timer0_pin_mask = digitalPinToBitMask(_pin);
+ break;
+ #endif
+
+ #if defined(TCCR1A) && defined(TCCR1B) && defined(WGM12)
+ case 1:
+ // 16 bit timer
+ TCCR1A = 0;
+ TCCR1B = 0;
+ bitWrite(TCCR1B, WGM12, 1);
+ bitWrite(TCCR1B, CS10, 1);
+ timer1_pin_port = portOutputRegister(digitalPinToPort(_pin));
+ timer1_pin_mask = digitalPinToBitMask(_pin);
+ break;
+ #endif
+
+ #if defined(TCCR2A) && defined(TCCR2B)
+ case 2:
+ // 8 bit timer
+ TCCR2A = 0;
+ TCCR2B = 0;
+ bitWrite(TCCR2A, WGM21, 1);
+ bitWrite(TCCR2B, CS20, 1);
+ timer2_pin_port = portOutputRegister(digitalPinToPort(_pin));
+ timer2_pin_mask = digitalPinToBitMask(_pin);
+ break;
+ #endif
+
+ #if defined(TCCR3A) && defined(TCCR3B) && defined(TIMSK3)
+ case 3:
+ // 16 bit timer
+ TCCR3A = 0;
+ TCCR3B = 0;
+ bitWrite(TCCR3B, WGM32, 1);
+ bitWrite(TCCR3B, CS30, 1);
+ timer3_pin_port = portOutputRegister(digitalPinToPort(_pin));
+ timer3_pin_mask = digitalPinToBitMask(_pin);
+ break;
+ #endif
+
+ #if defined(TCCR4A) && defined(TCCR4B) && defined(TIMSK4)
+ case 4:
+ // 16 bit timer
+ TCCR4A = 0;
+ TCCR4B = 0;
+ #if defined(WGM42)
+ bitWrite(TCCR4B, WGM42, 1);
+ #elif defined(CS43)
+ #warning this may not be correct
+ // atmega32u4
+ bitWrite(TCCR4B, CS43, 1);
+ #endif
+ bitWrite(TCCR4B, CS40, 1);
+ timer4_pin_port = portOutputRegister(digitalPinToPort(_pin));
+ timer4_pin_mask = digitalPinToBitMask(_pin);
+ break;
+ #endif
+
+ #if defined(TCCR5A) && defined(TCCR5B) && defined(TIMSK5)
+ case 5:
+ // 16 bit timer
+ TCCR5A = 0;
+ TCCR5B = 0;
+ bitWrite(TCCR5B, WGM52, 1);
+ bitWrite(TCCR5B, CS50, 1);
+ timer5_pin_port = portOutputRegister(digitalPinToPort(_pin));
+ timer5_pin_mask = digitalPinToBitMask(_pin);
+ break;
+ #endif
+ }
+ }
+
+ return _timer;
+}
+
+
+
+// frequency (in hertz) and duration (in milliseconds).
+
+void tone(uint8_t _pin, unsigned int frequency, unsigned long duration)
+{
+ uint8_t prescalarbits = 0b001;
+ long toggle_count = 0;
+ uint32_t ocr = 0;
+ int8_t _timer;
+
+ _timer = toneBegin(_pin);
+
+ if (_timer >= 0)
+ {
+ // Set the pinMode as OUTPUT
+ pinMode(_pin, OUTPUT);
+
+ // if we are using an 8 bit timer, scan through prescalars to find the best fit
+ if (_timer == 0 || _timer == 2)
+ {
+ ocr = F_CPU / frequency / 2 - 1;
+ prescalarbits = 0b001; // ck/1: same for both timers
+ if (ocr > 255)
+ {
+ ocr = F_CPU / frequency / 2 / 8 - 1;
+ prescalarbits = 0b010; // ck/8: same for both timers
+
+ if (_timer == 2 && ocr > 255)
+ {
+ ocr = F_CPU / frequency / 2 / 32 - 1;
+ prescalarbits = 0b011;
+ }
+
+ if (ocr > 255)
+ {
+ ocr = F_CPU / frequency / 2 / 64 - 1;
+ prescalarbits = _timer == 0 ? 0b011 : 0b100;
+
+ if (_timer == 2 && ocr > 255)
+ {
+ ocr = F_CPU / frequency / 2 / 128 - 1;
+ prescalarbits = 0b101;
+ }
+
+ if (ocr > 255)
+ {
+ ocr = F_CPU / frequency / 2 / 256 - 1;
+ prescalarbits = _timer == 0 ? 0b100 : 0b110;
+ if (ocr > 255)
+ {
+ // can't do any better than /1024
+ ocr = F_CPU / frequency / 2 / 1024 - 1;
+ prescalarbits = _timer == 0 ? 0b101 : 0b111;
+ }
+ }
+ }
+ }
+
+#if defined(TCCR0B)
+ if (_timer == 0)
+ {
+ TCCR0B = prescalarbits;
+ }
+ else
+#endif
+#if defined(TCCR2B)
+ {
+ TCCR2B = prescalarbits;
+ }
+#else
+ {
+ // dummy place holder to make the above ifdefs work
+ }
+#endif
+ }
+ else
+ {
+ // two choices for the 16 bit timers: ck/1 or ck/64
+ ocr = F_CPU / frequency / 2 - 1;
+
+ prescalarbits = 0b001;
+ if (ocr > 0xffff)
+ {
+ ocr = F_CPU / frequency / 2 / 64 - 1;
+ prescalarbits = 0b011;
+ }
+
+ if (_timer == 1)
+ {
+#if defined(TCCR1B)
+ TCCR1B = (TCCR1B & 0b11111000) | prescalarbits;
+#endif
+ }
+#if defined(TCCR3B)
+ else if (_timer == 3)
+ TCCR3B = (TCCR3B & 0b11111000) | prescalarbits;
+#endif
+#if defined(TCCR4B)
+ else if (_timer == 4)
+ TCCR4B = (TCCR4B & 0b11111000) | prescalarbits;
+#endif
+#if defined(TCCR5B)
+ else if (_timer == 5)
+ TCCR5B = (TCCR5B & 0b11111000) | prescalarbits;
+#endif
+
+ }
+
+
+ // Calculate the toggle count
+ if (duration > 0)
+ {
+ toggle_count = 2 * frequency * duration / 1000;
+ }
+ else
+ {
+ toggle_count = -1;
+ }
+
+ // Set the OCR for the given timer,
+ // set the toggle count,
+ // then turn on the interrupts
+ switch (_timer)
+ {
+
+#if defined(OCR0A) && defined(TIMSK0) && defined(OCIE0A)
+ case 0:
+ OCR0A = ocr;
+ timer0_toggle_count = toggle_count;
+ bitWrite(TIMSK0, OCIE0A, 1);
+ break;
+#endif
+
+ case 1:
+#if defined(OCR1A) && defined(TIMSK1) && defined(OCIE1A)
+ OCR1A = ocr;
+ timer1_toggle_count = toggle_count;
+ bitWrite(TIMSK1, OCIE1A, 1);
+#elif defined(OCR1A) && defined(TIMSK) && defined(OCIE1A)
+ // this combination is for at least the ATmega32
+ OCR1A = ocr;
+ timer1_toggle_count = toggle_count;
+ bitWrite(TIMSK, OCIE1A, 1);
+#endif
+ break;
+
+#if defined(OCR2A) && defined(TIMSK2) && defined(OCIE2A)
+ case 2:
+ OCR2A = ocr;
+ timer2_toggle_count = toggle_count;
+ bitWrite(TIMSK2, OCIE2A, 1);
+ break;
+#endif
+
+#if defined(TIMSK3)
+ case 3:
+ OCR3A = ocr;
+ timer3_toggle_count = toggle_count;
+ bitWrite(TIMSK3, OCIE3A, 1);
+ break;
+#endif
+
+#if defined(TIMSK4)
+ case 4:
+ OCR4A = ocr;
+ timer4_toggle_count = toggle_count;
+ bitWrite(TIMSK4, OCIE4A, 1);
+ break;
+#endif
+
+#if defined(OCR5A) && defined(TIMSK5) && defined(OCIE5A)
+ case 5:
+ OCR5A = ocr;
+ timer5_toggle_count = toggle_count;
+ bitWrite(TIMSK5, OCIE5A, 1);
+ break;
+#endif
+
+ }
+ }
+}
+
+
+// XXX: this function only works properly for timer 2 (the only one we use
+// currently). for the others, it should end the tone, but won't restore
+// proper PWM functionality for the timer.
+void disableTimer(uint8_t _timer)
+{
+ switch (_timer)
+ {
+ case 0:
+ #if defined(TIMSK0)
+ TIMSK0 = 0;
+ #elif defined(TIMSK)
+ TIMSK = 0; // atmega32
+ #endif
+ break;
+
+#if defined(TIMSK1) && defined(OCIE1A)
+ case 1:
+ bitWrite(TIMSK1, OCIE1A, 0);
+ break;
+#endif
+
+ case 2:
+ #if defined(TIMSK2) && defined(OCIE2A)
+ bitWrite(TIMSK2, OCIE2A, 0); // disable interrupt
+ #endif
+ #if defined(TCCR2A) && defined(WGM20)
+ TCCR2A = (1 << WGM20);
+ #endif
+ #if defined(TCCR2B) && defined(CS22)
+ TCCR2B = (TCCR2B & 0b11111000) | (1 << CS22);
+ #endif
+ #if defined(OCR2A)
+ OCR2A = 0;
+ #endif
+ break;
+
+#if defined(TIMSK3)
+ case 3:
+ TIMSK3 = 0;
+ break;
+#endif
+
+#if defined(TIMSK4)
+ case 4:
+ TIMSK4 = 0;
+ break;
+#endif
+
+#if defined(TIMSK5)
+ case 5:
+ TIMSK5 = 0;
+ break;
+#endif
+ }
+}
+
+
+void noTone(uint8_t _pin)
+{
+ int8_t _timer = -1;
+
+ for (int i = 0; i < AVAILABLE_TONE_PINS; i++) {
+ if (tone_pins[i] == _pin) {
+ _timer = pgm_read_byte(tone_pin_to_timer_PGM + i);
+ tone_pins[i] = 255;
+ }
+ }
+
+ disableTimer(_timer);
+
+ digitalWrite(_pin, 0);
+}
+
+#if 0
+#if !defined(__AVR_ATmega8__)
+ISR(TIMER0_COMPA_vect)
+{
+ if (timer0_toggle_count != 0)
+ {
+ // toggle the pin
+ *timer0_pin_port ^= timer0_pin_mask;
+
+ if (timer0_toggle_count > 0)
+ timer0_toggle_count--;
+ }
+ else
+ {
+ disableTimer(0);
+ *timer0_pin_port &= ~(timer0_pin_mask); // keep pin low after stop
+ }
+}
+#endif
+
+
+ISR(TIMER1_COMPA_vect)
+{
+ if (timer1_toggle_count != 0)
+ {
+ // toggle the pin
+ *timer1_pin_port ^= timer1_pin_mask;
+
+ if (timer1_toggle_count > 0)
+ timer1_toggle_count--;
+ }
+ else
+ {
+ disableTimer(1);
+ *timer1_pin_port &= ~(timer1_pin_mask); // keep pin low after stop
+ }
+}
+#endif
+
+
+ISR(TIMER2_COMPA_vect)
+{
+
+ if (timer2_toggle_count != 0)
+ {
+ // toggle the pin
+ *timer2_pin_port ^= timer2_pin_mask;
+
+ if (timer2_toggle_count > 0)
+ timer2_toggle_count--;
+ }
+ else
+ {
+ // need to call noTone() so that the tone_pins[] entry is reset, so the
+ // timer gets initialized next time we call tone().
+ // XXX: this assumes timer 2 is always the first one used.
+ noTone(tone_pins[0]);
+// disableTimer(2);
+// *timer2_pin_port &= ~(timer2_pin_mask); // keep pin low after stop
+ }
+}
+
+
+
+//#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
+#if 0
+
+ISR(TIMER3_COMPA_vect)
+{
+ if (timer3_toggle_count != 0)
+ {
+ // toggle the pin
+ *timer3_pin_port ^= timer3_pin_mask;
+
+ if (timer3_toggle_count > 0)
+ timer3_toggle_count--;
+ }
+ else
+ {
+ disableTimer(3);
+ *timer3_pin_port &= ~(timer3_pin_mask); // keep pin low after stop
+ }
+}
+
+ISR(TIMER4_COMPA_vect)
+{
+ if (timer4_toggle_count != 0)
+ {
+ // toggle the pin
+ *timer4_pin_port ^= timer4_pin_mask;
+
+ if (timer4_toggle_count > 0)
+ timer4_toggle_count--;
+ }
+ else
+ {
+ disableTimer(4);
+ *timer4_pin_port &= ~(timer4_pin_mask); // keep pin low after stop
+ }
+}
+
+ISR(TIMER5_COMPA_vect)
+{
+ if (timer5_toggle_count != 0)
+ {
+ // toggle the pin
+ *timer5_pin_port ^= timer5_pin_mask;
+
+ if (timer5_toggle_count > 0)
+ timer5_toggle_count--;
+ }
+ else
+ {
+ disableTimer(5);
+ *timer5_pin_port &= ~(timer5_pin_mask); // keep pin low after stop
+ }
+}
+
+#endif
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/USBAPI.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/USBAPI.h
new file mode 100644
index 000000000..d5abdb690
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/USBAPI.h
@@ -0,0 +1,195 @@
+
+
+#ifndef __USBAPI__
+#define __USBAPI__
+
+#if defined(USBCON)
+
+//================================================================================
+//================================================================================
+// USB
+
+class USBDevice_
+{
+public:
+ USBDevice_();
+ bool configured();
+
+ void attach();
+ void detach(); // Serial port goes down too...
+ void poll();
+};
+extern USBDevice_ USBDevice;
+
+//================================================================================
+//================================================================================
+// Serial over CDC (Serial1 is the physical port)
+
+class Serial_ : public Stream
+{
+private:
+ ring_buffer *_cdc_rx_buffer;
+public:
+ void begin(uint16_t baud_count);
+ void end(void);
+
+ virtual int available(void);
+ virtual void accept(void);
+ virtual int peek(void);
+ virtual int read(void);
+ virtual void flush(void);
+ virtual size_t write(uint8_t);
+ operator bool();
+};
+extern Serial_ Serial;
+
+//================================================================================
+//================================================================================
+// Mouse
+
+#define MOUSE_LEFT 1
+#define MOUSE_RIGHT 2
+#define MOUSE_MIDDLE 4
+#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)
+
+class Mouse_
+{
+private:
+ uint8_t _buttons;
+ void buttons(uint8_t b);
+public:
+ Mouse_(void);
+ void begin(void);
+ void end(void);
+ void click(uint8_t b = MOUSE_LEFT);
+ void move(signed char x, signed char y, signed char wheel = 0);
+ void press(uint8_t b = MOUSE_LEFT); // press LEFT by default
+ void release(uint8_t b = MOUSE_LEFT); // release LEFT by default
+ bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default
+};
+extern Mouse_ Mouse;
+
+//================================================================================
+//================================================================================
+// Keyboard
+
+#define KEY_LEFT_CTRL 0x80
+#define KEY_LEFT_SHIFT 0x81
+#define KEY_LEFT_ALT 0x82
+#define KEY_LEFT_GUI 0x83
+#define KEY_RIGHT_CTRL 0x84
+#define KEY_RIGHT_SHIFT 0x85
+#define KEY_RIGHT_ALT 0x86
+#define KEY_RIGHT_GUI 0x87
+
+#define KEY_UP_ARROW 0xDA
+#define KEY_DOWN_ARROW 0xD9
+#define KEY_LEFT_ARROW 0xD8
+#define KEY_RIGHT_ARROW 0xD7
+#define KEY_BACKSPACE 0xB2
+#define KEY_TAB 0xB3
+#define KEY_RETURN 0xB0
+#define KEY_ESC 0xB1
+#define KEY_INSERT 0xD1
+#define KEY_DELETE 0xD4
+#define KEY_PAGE_UP 0xD3
+#define KEY_PAGE_DOWN 0xD6
+#define KEY_HOME 0xD2
+#define KEY_END 0xD5
+#define KEY_CAPS_LOCK 0xC1
+#define KEY_F1 0xC2
+#define KEY_F2 0xC3
+#define KEY_F3 0xC4
+#define KEY_F4 0xC5
+#define KEY_F5 0xC6
+#define KEY_F6 0xC7
+#define KEY_F7 0xC8
+#define KEY_F8 0xC9
+#define KEY_F9 0xCA
+#define KEY_F10 0xCB
+#define KEY_F11 0xCC
+#define KEY_F12 0xCD
+
+// Low level key report: up to 6 keys and shift, ctrl etc at once
+typedef struct
+{
+ uint8_t modifiers;
+ uint8_t reserved;
+ uint8_t keys[6];
+} KeyReport;
+
+class Keyboard_ : public Print
+{
+private:
+ KeyReport _keyReport;
+ void sendReport(KeyReport* keys);
+public:
+ Keyboard_(void);
+ void begin(void);
+ void end(void);
+ virtual size_t write(uint8_t k);
+ virtual size_t press(uint8_t k);
+ virtual size_t release(uint8_t k);
+ virtual void releaseAll(void);
+};
+extern Keyboard_ Keyboard;
+
+//================================================================================
+//================================================================================
+// Low level API
+
+typedef struct
+{
+ uint8_t bmRequestType;
+ uint8_t bRequest;
+ uint8_t wValueL;
+ uint8_t wValueH;
+ uint16_t wIndex;
+ uint16_t wLength;
+} Setup;
+
+//================================================================================
+//================================================================================
+// HID 'Driver'
+
+int HID_GetInterface(uint8_t* interfaceNum);
+int HID_GetDescriptor(int i);
+bool HID_Setup(Setup& setup);
+void HID_SendReport(uint8_t id, const void* data, int len);
+
+//================================================================================
+//================================================================================
+// MSC 'Driver'
+
+int MSC_GetInterface(uint8_t* interfaceNum);
+int MSC_GetDescriptor(int i);
+bool MSC_Setup(Setup& setup);
+bool MSC_Data(uint8_t rx,uint8_t tx);
+
+//================================================================================
+//================================================================================
+// CSC 'Driver'
+
+int CDC_GetInterface(uint8_t* interfaceNum);
+int CDC_GetDescriptor(int i);
+bool CDC_Setup(Setup& setup);
+
+//================================================================================
+//================================================================================
+
+#define TRANSFER_PGM 0x80
+#define TRANSFER_RELEASE 0x40
+#define TRANSFER_ZERO 0x20
+
+int USB_SendControl(uint8_t flags, const void* d, int len);
+int USB_RecvControl(void* d, int len);
+
+uint8_t USB_Available(uint8_t ep);
+int USB_Send(uint8_t ep, const void* data, int len); // blocking
+int USB_Recv(uint8_t ep, void* data, int len); // non-blocking
+int USB_Recv(uint8_t ep); // non-blocking
+void USB_Flush(uint8_t ep);
+
+#endif
+
+#endif /* if defined(USBCON) */ \ No newline at end of file
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/USBCore.cpp b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/USBCore.cpp
new file mode 100644
index 000000000..6766be61a
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/USBCore.cpp
@@ -0,0 +1,672 @@
+
+
+/* Copyright (c) 2010, Peter Barrett
+**
+** Permission to use, copy, modify, and/or distribute this software for
+** any purpose with or without fee is hereby granted, provided that the
+** above copyright notice and this permission notice appear in all copies.
+**
+** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
+** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
+** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+** SOFTWARE.
+*/
+
+#include "Platform.h"
+#include "USBAPI.h"
+#include "USBDesc.h"
+
+#if defined(USBCON)
+
+#define EP_TYPE_CONTROL 0x00
+#define EP_TYPE_BULK_IN 0x81
+#define EP_TYPE_BULK_OUT 0x80
+#define EP_TYPE_INTERRUPT_IN 0xC1
+#define EP_TYPE_INTERRUPT_OUT 0xC0
+#define EP_TYPE_ISOCHRONOUS_IN 0x41
+#define EP_TYPE_ISOCHRONOUS_OUT 0x40
+
+/** Pulse generation counters to keep track of the number of milliseconds remaining for each pulse type */
+#define TX_RX_LED_PULSE_MS 100
+volatile u8 TxLEDPulse; /**< Milliseconds remaining for data Tx LED pulse */
+volatile u8 RxLEDPulse; /**< Milliseconds remaining for data Rx LED pulse */
+
+//==================================================================
+//==================================================================
+
+extern const u16 STRING_LANGUAGE[] PROGMEM;
+extern const u16 STRING_IPRODUCT[] PROGMEM;
+extern const u16 STRING_IMANUFACTURER[] PROGMEM;
+extern const DeviceDescriptor USB_DeviceDescriptor PROGMEM;
+extern const DeviceDescriptor USB_DeviceDescriptorA PROGMEM;
+
+const u16 STRING_LANGUAGE[2] = {
+ (3<<8) | (2+2),
+ 0x0409 // English
+};
+
+const u16 STRING_IPRODUCT[17] = {
+ (3<<8) | (2+2*16),
+#if USB_PID == 0x8036
+ 'A','r','d','u','i','n','o',' ','L','e','o','n','a','r','d','o'
+#else
+ 'U','S','B',' ','I','O',' ','B','o','a','r','d',' ',' ',' ',' '
+#endif
+};
+
+const u16 STRING_IMANUFACTURER[12] = {
+ (3<<8) | (2+2*11),
+#if USB_VID == 0x2341
+ 'A','r','d','u','i','n','o',' ','L','L','C'
+#else
+ 'U','n','k','n','o','w','n',' ',' ',' ',' '
+#endif
+};
+
+#ifdef CDC_ENABLED
+#define DEVICE_CLASS 0x02
+#else
+#define DEVICE_CLASS 0x00
+#endif
+
+// DEVICE DESCRIPTOR
+const DeviceDescriptor USB_DeviceDescriptor =
+ D_DEVICE(0x00,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1);
+
+const DeviceDescriptor USB_DeviceDescriptorA =
+ D_DEVICE(DEVICE_CLASS,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1);
+
+//==================================================================
+//==================================================================
+
+volatile u8 _usbConfiguration = 0;
+
+static inline void WaitIN(void)
+{
+ while (!(UEINTX & (1<<TXINI)));
+}
+
+static inline void ClearIN(void)
+{
+ UEINTX = ~(1<<TXINI);
+}
+
+static inline void WaitOUT(void)
+{
+ while (!(UEINTX & (1<<RXOUTI)))
+ ;
+}
+
+static inline u8 WaitForINOrOUT()
+{
+ while (!(UEINTX & ((1<<TXINI)|(1<<RXOUTI))))
+ ;
+ return (UEINTX & (1<<RXOUTI)) == 0;
+}
+
+static inline void ClearOUT(void)
+{
+ UEINTX = ~(1<<RXOUTI);
+}
+
+void Recv(volatile u8* data, u8 count)
+{
+ while (count--)
+ *data++ = UEDATX;
+
+ RXLED1; // light the RX LED
+ RxLEDPulse = TX_RX_LED_PULSE_MS;
+}
+
+static inline u8 Recv8()
+{
+ RXLED1; // light the RX LED
+ RxLEDPulse = TX_RX_LED_PULSE_MS;
+
+ return UEDATX;
+}
+
+static inline void Send8(u8 d)
+{
+ UEDATX = d;
+}
+
+static inline void SetEP(u8 ep)
+{
+ UENUM = ep;
+}
+
+static inline u8 FifoByteCount()
+{
+ return UEBCLX;
+}
+
+static inline u8 ReceivedSetupInt()
+{
+ return UEINTX & (1<<RXSTPI);
+}
+
+static inline void ClearSetupInt()
+{
+ UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
+}
+
+static inline void Stall()
+{
+ UECONX = (1<<STALLRQ) | (1<<EPEN);
+}
+
+static inline u8 ReadWriteAllowed()
+{
+ return UEINTX & (1<<RWAL);
+}
+
+static inline u8 Stalled()
+{
+ return UEINTX & (1<<STALLEDI);
+}
+
+static inline u8 FifoFree()
+{
+ return UEINTX & (1<<FIFOCON);
+}
+
+static inline void ReleaseRX()
+{
+ UEINTX = 0x6B; // FIFOCON=0 NAKINI=1 RWAL=1 NAKOUTI=0 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=1
+}
+
+static inline void ReleaseTX()
+{
+ UEINTX = 0x3A; // FIFOCON=0 NAKINI=0 RWAL=1 NAKOUTI=1 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=0
+}
+
+static inline u8 FrameNumber()
+{
+ return UDFNUML;
+}
+
+//==================================================================
+//==================================================================
+
+u8 USBGetConfiguration(void)
+{
+ return _usbConfiguration;
+}
+
+#define USB_RECV_TIMEOUT
+class LockEP
+{
+ u8 _sreg;
+public:
+ LockEP(u8 ep) : _sreg(SREG)
+ {
+ cli();
+ SetEP(ep & 7);
+ }
+ ~LockEP()
+ {
+ SREG = _sreg;
+ }
+};
+
+// Number of bytes, assumes a rx endpoint
+u8 USB_Available(u8 ep)
+{
+ LockEP lock(ep);
+ return FifoByteCount();
+}
+
+// Non Blocking receive
+// Return number of bytes read
+int USB_Recv(u8 ep, void* d, int len)
+{
+ if (!_usbConfiguration || len < 0)
+ return -1;
+
+ LockEP lock(ep);
+ u8 n = FifoByteCount();
+ len = min(n,len);
+ n = len;
+ u8* dst = (u8*)d;
+ while (n--)
+ *dst++ = Recv8();
+ if (len && !FifoByteCount()) // release empty buffer
+ ReleaseRX();
+
+ return len;
+}
+
+// Recv 1 byte if ready
+int USB_Recv(u8 ep)
+{
+ u8 c;
+ if (USB_Recv(ep,&c,1) != 1)
+ return -1;
+ return c;
+}
+
+// Space in send EP
+u8 USB_SendSpace(u8 ep)
+{
+ LockEP lock(ep);
+ if (!ReadWriteAllowed())
+ return 0;
+ return 64 - FifoByteCount();
+}
+
+// Blocking Send of data to an endpoint
+int USB_Send(u8 ep, const void* d, int len)
+{
+ if (!_usbConfiguration)
+ return -1;
+
+ int r = len;
+ const u8* data = (const u8*)d;
+ u8 zero = ep & TRANSFER_ZERO;
+ u8 timeout = 250; // 250ms timeout on send? TODO
+ while (len)
+ {
+ u8 n = USB_SendSpace(ep);
+ if (n == 0)
+ {
+ if (!(--timeout))
+ return -1;
+ delay(1);
+ continue;
+ }
+
+ if (n > len)
+ n = len;
+ len -= n;
+ {
+ LockEP lock(ep);
+ if (ep & TRANSFER_ZERO)
+ {
+ while (n--)
+ Send8(0);
+ }
+ else if (ep & TRANSFER_PGM)
+ {
+ while (n--)
+ Send8(pgm_read_byte(data++));
+ }
+ else
+ {
+ while (n--)
+ Send8(*data++);
+ }
+ if (!ReadWriteAllowed() || ((len == 0) && (ep & TRANSFER_RELEASE))) // Release full buffer
+ ReleaseTX();
+ }
+ }
+ TXLED1; // light the TX LED
+ TxLEDPulse = TX_RX_LED_PULSE_MS;
+ return r;
+}
+
+extern const u8 _initEndpoints[] PROGMEM;
+const u8 _initEndpoints[] =
+{
+ 0,
+
+#ifdef CDC_ENABLED
+ EP_TYPE_INTERRUPT_IN, // CDC_ENDPOINT_ACM
+ EP_TYPE_BULK_OUT, // CDC_ENDPOINT_OUT
+ EP_TYPE_BULK_IN, // CDC_ENDPOINT_IN
+#endif
+
+#ifdef HID_ENABLED
+ EP_TYPE_INTERRUPT_IN // HID_ENDPOINT_INT
+#endif
+};
+
+#define EP_SINGLE_64 0x32 // EP0
+#define EP_DOUBLE_64 0x36 // Other endpoints
+
+static
+void InitEP(u8 index, u8 type, u8 size)
+{
+ UENUM = index;
+ UECONX = 1;
+ UECFG0X = type;
+ UECFG1X = size;
+}
+
+static
+void InitEndpoints()
+{
+ for (u8 i = 1; i < sizeof(_initEndpoints); i++)
+ {
+ UENUM = i;
+ UECONX = 1;
+ UECFG0X = pgm_read_byte(_initEndpoints+i);
+ UECFG1X = EP_DOUBLE_64;
+ }
+ UERST = 0x7E; // And reset them
+ UERST = 0;
+}
+
+// Handle CLASS_INTERFACE requests
+static
+bool ClassInterfaceRequest(Setup& setup)
+{
+ u8 i = setup.wIndex;
+
+#ifdef CDC_ENABLED
+ if (CDC_ACM_INTERFACE == i)
+ return CDC_Setup(setup);
+#endif
+
+#ifdef HID_ENABLED
+ if (HID_INTERFACE == i)
+ return HID_Setup(setup);
+#endif
+ return false;
+}
+
+int _cmark;
+int _cend;
+void InitControl(int end)
+{
+ SetEP(0);
+ _cmark = 0;
+ _cend = end;
+}
+
+static
+bool SendControl(u8 d)
+{
+ if (_cmark < _cend)
+ {
+ if (!WaitForINOrOUT())
+ return false;
+ Send8(d);
+ if (!((_cmark + 1) & 0x3F))
+ ClearIN(); // Fifo is full, release this packet
+ }
+ _cmark++;
+ return true;
+};
+
+// Clipped by _cmark/_cend
+int USB_SendControl(u8 flags, const void* d, int len)
+{
+ int sent = len;
+ const u8* data = (const u8*)d;
+ bool pgm = flags & TRANSFER_PGM;
+ while (len--)
+ {
+ u8 c = pgm ? pgm_read_byte(data++) : *data++;
+ if (!SendControl(c))
+ return -1;
+ }
+ return sent;
+}
+
+// Does not timeout or cross fifo boundaries
+// Will only work for transfers <= 64 bytes
+// TODO
+int USB_RecvControl(void* d, int len)
+{
+ WaitOUT();
+ Recv((u8*)d,len);
+ ClearOUT();
+ return len;
+}
+
+int SendInterfaces()
+{
+ int total = 0;
+ u8 interfaces = 0;
+
+#ifdef CDC_ENABLED
+ total = CDC_GetInterface(&interfaces);
+#endif
+
+#ifdef HID_ENABLED
+ total += HID_GetInterface(&interfaces);
+#endif
+
+ return interfaces;
+}
+
+// Construct a dynamic configuration descriptor
+// This really needs dynamic endpoint allocation etc
+// TODO
+static
+bool SendConfiguration(int maxlen)
+{
+ // Count and measure interfaces
+ InitControl(0);
+ int interfaces = SendInterfaces();
+ ConfigDescriptor config = D_CONFIG(_cmark + sizeof(ConfigDescriptor),interfaces);
+
+ // Now send them
+ InitControl(maxlen);
+ USB_SendControl(0,&config,sizeof(ConfigDescriptor));
+ SendInterfaces();
+ return true;
+}
+
+u8 _cdcComposite = 0;
+
+static
+bool SendDescriptor(Setup& setup)
+{
+ u8 t = setup.wValueH;
+ if (USB_CONFIGURATION_DESCRIPTOR_TYPE == t)
+ return SendConfiguration(setup.wLength);
+
+ InitControl(setup.wLength);
+#ifdef HID_ENABLED
+ if (HID_REPORT_DESCRIPTOR_TYPE == t)
+ return HID_GetDescriptor(t);
+#endif
+
+ u8 desc_length = 0;
+ const u8* desc_addr = 0;
+ if (USB_DEVICE_DESCRIPTOR_TYPE == t)
+ {
+ if (setup.wLength == 8)
+ _cdcComposite = 1;
+ desc_addr = _cdcComposite ? (const u8*)&USB_DeviceDescriptorA : (const u8*)&USB_DeviceDescriptor;
+ }
+ else if (USB_STRING_DESCRIPTOR_TYPE == t)
+ {
+ if (setup.wValueL == 0)
+ desc_addr = (const u8*)&STRING_LANGUAGE;
+ else if (setup.wValueL == IPRODUCT)
+ desc_addr = (const u8*)&STRING_IPRODUCT;
+ else if (setup.wValueL == IMANUFACTURER)
+ desc_addr = (const u8*)&STRING_IMANUFACTURER;
+ else
+ return false;
+ }
+
+ if (desc_addr == 0)
+ return false;
+ if (desc_length == 0)
+ desc_length = pgm_read_byte(desc_addr);
+
+ USB_SendControl(TRANSFER_PGM,desc_addr,desc_length);
+ return true;
+}
+
+// Endpoint 0 interrupt
+ISR(USB_COM_vect)
+{
+ SetEP(0);
+ if (!ReceivedSetupInt())
+ return;
+
+ Setup setup;
+ Recv((u8*)&setup,8);
+ ClearSetupInt();
+
+ u8 requestType = setup.bmRequestType;
+ if (requestType & REQUEST_DEVICETOHOST)
+ WaitIN();
+ else
+ ClearIN();
+
+ bool ok = true;
+ if (REQUEST_STANDARD == (requestType & REQUEST_TYPE))
+ {
+ // Standard Requests
+ u8 r = setup.bRequest;
+ if (GET_STATUS == r)
+ {
+ Send8(0); // TODO
+ Send8(0);
+ }
+ else if (CLEAR_FEATURE == r)
+ {
+ }
+ else if (SET_FEATURE == r)
+ {
+ }
+ else if (SET_ADDRESS == r)
+ {
+ WaitIN();
+ UDADDR = setup.wValueL | (1<<ADDEN);
+ }
+ else if (GET_DESCRIPTOR == r)
+ {
+ ok = SendDescriptor(setup);
+ }
+ else if (SET_DESCRIPTOR == r)
+ {
+ ok = false;
+ }
+ else if (GET_CONFIGURATION == r)
+ {
+ Send8(1);
+ }
+ else if (SET_CONFIGURATION == r)
+ {
+ if (REQUEST_DEVICE == (requestType & REQUEST_RECIPIENT))
+ {
+ InitEndpoints();
+ _usbConfiguration = setup.wValueL;
+ } else
+ ok = false;
+ }
+ else if (GET_INTERFACE == r)
+ {
+ }
+ else if (SET_INTERFACE == r)
+ {
+ }
+ }
+ else
+ {
+ InitControl(setup.wLength); // Max length of transfer
+ ok = ClassInterfaceRequest(setup);
+ }
+
+ if (ok)
+ ClearIN();
+ else
+ {
+ Stall();
+ }
+}
+
+void USB_Flush(u8 ep)
+{
+ SetEP(ep);
+ if (FifoByteCount())
+ ReleaseTX();
+}
+
+// General interrupt
+ISR(USB_GEN_vect)
+{
+ u8 udint = UDINT;
+ UDINT = 0;
+
+ // End of Reset
+ if (udint & (1<<EORSTI))
+ {
+ InitEP(0,EP_TYPE_CONTROL,EP_SINGLE_64); // init ep0
+ _usbConfiguration = 0; // not configured yet
+ UEIENX = 1 << RXSTPE; // Enable interrupts for ep0
+ }
+
+ // Start of Frame - happens every millisecond so we use it for TX and RX LED one-shot timing, too
+ if (udint & (1<<SOFI))
+ {
+#ifdef CDC_ENABLED
+ USB_Flush(CDC_TX); // Send a tx frame if found
+ while (USB_Available(CDC_RX)) // Handle received bytes (if any)
+ Serial.accept();
+#endif
+
+ // check whether the one-shot period has elapsed. if so, turn off the LED
+ if (TxLEDPulse && !(--TxLEDPulse))
+ TXLED0;
+ if (RxLEDPulse && !(--RxLEDPulse))
+ RXLED0;
+ }
+}
+
+// VBUS or counting frames
+// Any frame counting?
+u8 USBConnected()
+{
+ u8 f = UDFNUML;
+ delay(3);
+ return f != UDFNUML;
+}
+
+//=======================================================================
+//=======================================================================
+
+USBDevice_ USBDevice;
+
+USBDevice_::USBDevice_()
+{
+}
+
+void USBDevice_::attach()
+{
+ _usbConfiguration = 0;
+ UHWCON = 0x01; // power internal reg
+ USBCON = (1<<USBE)|(1<<FRZCLK); // clock frozen, usb enabled
+ PLLCSR = 0x12; // Need 16 MHz xtal
+ while (!(PLLCSR & (1<<PLOCK))) // wait for lock pll
+ ;
+
+ // Some tests on specific versions of macosx (10.7.3), reported some
+ // strange behaviuors when the board is reset using the serial
+ // port touch at 1200 bps. This delay fixes this behaviour.
+ delay(1);
+
+ USBCON = ((1<<USBE)|(1<<OTGPADE)); // start USB clock
+ UDIEN = (1<<EORSTE)|(1<<SOFE); // Enable interrupts for EOR (End of Reset) and SOF (start of frame)
+ UDCON = 0; // enable attach resistor
+
+ TX_RX_LED_INIT;
+}
+
+void USBDevice_::detach()
+{
+}
+
+// Check for interrupts
+// TODO: VBUS detection
+bool USBDevice_::configured()
+{
+ return _usbConfiguration;
+}
+
+void USBDevice_::poll()
+{
+}
+
+#endif /* if defined(USBCON) */
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/USBCore.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/USBCore.h
new file mode 100644
index 000000000..8d1380689
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/USBCore.h
@@ -0,0 +1,303 @@
+
+// Copyright (c) 2010, Peter Barrett
+/*
+** Permission to use, copy, modify, and/or distribute this software for
+** any purpose with or without fee is hereby granted, provided that the
+** above copyright notice and this permission notice appear in all copies.
+**
+** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
+** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
+** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+** SOFTWARE.
+*/
+
+#ifndef __USBCORE_H__
+#define __USBCORE_H__
+
+// Standard requests
+#define GET_STATUS 0
+#define CLEAR_FEATURE 1
+#define SET_FEATURE 3
+#define SET_ADDRESS 5
+#define GET_DESCRIPTOR 6
+#define SET_DESCRIPTOR 7
+#define GET_CONFIGURATION 8
+#define SET_CONFIGURATION 9
+#define GET_INTERFACE 10
+#define SET_INTERFACE 11
+
+
+// bmRequestType
+#define REQUEST_HOSTTODEVICE 0x00
+#define REQUEST_DEVICETOHOST 0x80
+#define REQUEST_DIRECTION 0x80
+
+#define REQUEST_STANDARD 0x00
+#define REQUEST_CLASS 0x20
+#define REQUEST_VENDOR 0x40
+#define REQUEST_TYPE 0x60
+
+#define REQUEST_DEVICE 0x00
+#define REQUEST_INTERFACE 0x01
+#define REQUEST_ENDPOINT 0x02
+#define REQUEST_OTHER 0x03
+#define REQUEST_RECIPIENT 0x03
+
+#define REQUEST_DEVICETOHOST_CLASS_INTERFACE (REQUEST_DEVICETOHOST + REQUEST_CLASS + REQUEST_INTERFACE)
+#define REQUEST_HOSTTODEVICE_CLASS_INTERFACE (REQUEST_HOSTTODEVICE + REQUEST_CLASS + REQUEST_INTERFACE)
+
+// Class requests
+
+#define CDC_SET_LINE_CODING 0x20
+#define CDC_GET_LINE_CODING 0x21
+#define CDC_SET_CONTROL_LINE_STATE 0x22
+
+#define MSC_RESET 0xFF
+#define MSC_GET_MAX_LUN 0xFE
+
+#define HID_GET_REPORT 0x01
+#define HID_GET_IDLE 0x02
+#define HID_GET_PROTOCOL 0x03
+#define HID_SET_REPORT 0x09
+#define HID_SET_IDLE 0x0A
+#define HID_SET_PROTOCOL 0x0B
+
+// Descriptors
+
+#define USB_DEVICE_DESC_SIZE 18
+#define USB_CONFIGUARTION_DESC_SIZE 9
+#define USB_INTERFACE_DESC_SIZE 9
+#define USB_ENDPOINT_DESC_SIZE 7
+
+#define USB_DEVICE_DESCRIPTOR_TYPE 1
+#define USB_CONFIGURATION_DESCRIPTOR_TYPE 2
+#define USB_STRING_DESCRIPTOR_TYPE 3
+#define USB_INTERFACE_DESCRIPTOR_TYPE 4
+#define USB_ENDPOINT_DESCRIPTOR_TYPE 5
+
+#define USB_DEVICE_CLASS_COMMUNICATIONS 0x02
+#define USB_DEVICE_CLASS_HUMAN_INTERFACE 0x03
+#define USB_DEVICE_CLASS_STORAGE 0x08
+#define USB_DEVICE_CLASS_VENDOR_SPECIFIC 0xFF
+
+#define USB_CONFIG_POWERED_MASK 0x40
+#define USB_CONFIG_BUS_POWERED 0x80
+#define USB_CONFIG_SELF_POWERED 0xC0
+#define USB_CONFIG_REMOTE_WAKEUP 0x20
+
+// bMaxPower in Configuration Descriptor
+#define USB_CONFIG_POWER_MA(mA) ((mA)/2)
+
+// bEndpointAddress in Endpoint Descriptor
+#define USB_ENDPOINT_DIRECTION_MASK 0x80
+#define USB_ENDPOINT_OUT(addr) ((addr) | 0x00)
+#define USB_ENDPOINT_IN(addr) ((addr) | 0x80)
+
+#define USB_ENDPOINT_TYPE_MASK 0x03
+#define USB_ENDPOINT_TYPE_CONTROL 0x00
+#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01
+#define USB_ENDPOINT_TYPE_BULK 0x02
+#define USB_ENDPOINT_TYPE_INTERRUPT 0x03
+
+#define TOBYTES(x) ((x) & 0xFF),(((x) >> 8) & 0xFF)
+
+#define CDC_V1_10 0x0110
+#define CDC_COMMUNICATION_INTERFACE_CLASS 0x02
+
+#define CDC_CALL_MANAGEMENT 0x01
+#define CDC_ABSTRACT_CONTROL_MODEL 0x02
+#define CDC_HEADER 0x00
+#define CDC_ABSTRACT_CONTROL_MANAGEMENT 0x02
+#define CDC_UNION 0x06
+#define CDC_CS_INTERFACE 0x24
+#define CDC_CS_ENDPOINT 0x25
+#define CDC_DATA_INTERFACE_CLASS 0x0A
+
+#define MSC_SUBCLASS_SCSI 0x06
+#define MSC_PROTOCOL_BULK_ONLY 0x50
+
+#define HID_HID_DESCRIPTOR_TYPE 0x21
+#define HID_REPORT_DESCRIPTOR_TYPE 0x22
+#define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23
+
+
+// Device
+typedef struct {
+ u8 len; // 18
+ u8 dtype; // 1 USB_DEVICE_DESCRIPTOR_TYPE
+ u16 usbVersion; // 0x200
+ u8 deviceClass;
+ u8 deviceSubClass;
+ u8 deviceProtocol;
+ u8 packetSize0; // Packet 0
+ u16 idVendor;
+ u16 idProduct;
+ u16 deviceVersion; // 0x100
+ u8 iManufacturer;
+ u8 iProduct;
+ u8 iSerialNumber;
+ u8 bNumConfigurations;
+} DeviceDescriptor;
+
+// Config
+typedef struct {
+ u8 len; // 9
+ u8 dtype; // 2
+ u16 clen; // total length
+ u8 numInterfaces;
+ u8 config;
+ u8 iconfig;
+ u8 attributes;
+ u8 maxPower;
+} ConfigDescriptor;
+
+// String
+
+// Interface
+typedef struct
+{
+ u8 len; // 9
+ u8 dtype; // 4
+ u8 number;
+ u8 alternate;
+ u8 numEndpoints;
+ u8 interfaceClass;
+ u8 interfaceSubClass;
+ u8 protocol;
+ u8 iInterface;
+} InterfaceDescriptor;
+
+// Endpoint
+typedef struct
+{
+ u8 len; // 7
+ u8 dtype; // 5
+ u8 addr;
+ u8 attr;
+ u16 packetSize;
+ u8 interval;
+} EndpointDescriptor;
+
+// Interface Association Descriptor
+// Used to bind 2 interfaces together in CDC compostite device
+typedef struct
+{
+ u8 len; // 8
+ u8 dtype; // 11
+ u8 firstInterface;
+ u8 interfaceCount;
+ u8 functionClass;
+ u8 funtionSubClass;
+ u8 functionProtocol;
+ u8 iInterface;
+} IADDescriptor;
+
+// CDC CS interface descriptor
+typedef struct
+{
+ u8 len; // 5
+ u8 dtype; // 0x24
+ u8 subtype;
+ u8 d0;
+ u8 d1;
+} CDCCSInterfaceDescriptor;
+
+typedef struct
+{
+ u8 len; // 4
+ u8 dtype; // 0x24
+ u8 subtype;
+ u8 d0;
+} CDCCSInterfaceDescriptor4;
+
+typedef struct
+{
+ u8 len;
+ u8 dtype; // 0x24
+ u8 subtype; // 1
+ u8 bmCapabilities;
+ u8 bDataInterface;
+} CMFunctionalDescriptor;
+
+typedef struct
+{
+ u8 len;
+ u8 dtype; // 0x24
+ u8 subtype; // 1
+ u8 bmCapabilities;
+} ACMFunctionalDescriptor;
+
+typedef struct
+{
+ // IAD
+ IADDescriptor iad; // Only needed on compound device
+
+ // Control
+ InterfaceDescriptor cif; //
+ CDCCSInterfaceDescriptor header;
+ CMFunctionalDescriptor callManagement; // Call Management
+ ACMFunctionalDescriptor controlManagement; // ACM
+ CDCCSInterfaceDescriptor functionalDescriptor; // CDC_UNION
+ EndpointDescriptor cifin;
+
+ // Data
+ InterfaceDescriptor dif;
+ EndpointDescriptor in;
+ EndpointDescriptor out;
+} CDCDescriptor;
+
+typedef struct
+{
+ InterfaceDescriptor msc;
+ EndpointDescriptor in;
+ EndpointDescriptor out;
+} MSCDescriptor;
+
+typedef struct
+{
+ u8 len; // 9
+ u8 dtype; // 0x21
+ u8 addr;
+ u8 versionL; // 0x101
+ u8 versionH; // 0x101
+ u8 country;
+ u8 desctype; // 0x22 report
+ u8 descLenL;
+ u8 descLenH;
+} HIDDescDescriptor;
+
+typedef struct
+{
+ InterfaceDescriptor hid;
+ HIDDescDescriptor desc;
+ EndpointDescriptor in;
+} HIDDescriptor;
+
+
+#define D_DEVICE(_class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs) \
+ { 18, 1, 0x200, _class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs }
+
+#define D_CONFIG(_totalLength,_interfaces) \
+ { 9, 2, _totalLength,_interfaces, 1, 0, USB_CONFIG_BUS_POWERED, USB_CONFIG_POWER_MA(500) }
+
+#define D_INTERFACE(_n,_numEndpoints,_class,_subClass,_protocol) \
+ { 9, 4, _n, 0, _numEndpoints, _class,_subClass, _protocol, 0 }
+
+#define D_ENDPOINT(_addr,_attr,_packetSize, _interval) \
+ { 7, 5, _addr,_attr,_packetSize, _interval }
+
+#define D_IAD(_firstInterface, _count, _class, _subClass, _protocol) \
+ { 8, 11, _firstInterface, _count, _class, _subClass, _protocol, 0 }
+
+#define D_HIDREPORT(_descriptorLength) \
+ { 9, 0x21, 0x1, 0x1, 0, 1, 0x22, _descriptorLength, 0 }
+
+#define D_CDCCS(_subtype,_d0,_d1) { 5, 0x24, _subtype, _d0, _d1 }
+#define D_CDCCS4(_subtype,_d0) { 4, 0x24, _subtype, _d0 }
+
+
+#endif \ No newline at end of file
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/USBDesc.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/USBDesc.h
new file mode 100644
index 000000000..900713e0f
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/USBDesc.h
@@ -0,0 +1,63 @@
+
+
+/* Copyright (c) 2011, Peter Barrett
+**
+** Permission to use, copy, modify, and/or distribute this software for
+** any purpose with or without fee is hereby granted, provided that the
+** above copyright notice and this permission notice appear in all copies.
+**
+** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
+** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
+** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+** SOFTWARE.
+*/
+
+#define CDC_ENABLED
+#define HID_ENABLED
+
+
+#ifdef CDC_ENABLED
+#define CDC_INTERFACE_COUNT 2
+#define CDC_ENPOINT_COUNT 3
+#else
+#define CDC_INTERFACE_COUNT 0
+#define CDC_ENPOINT_COUNT 0
+#endif
+
+#ifdef HID_ENABLED
+#define HID_INTERFACE_COUNT 1
+#define HID_ENPOINT_COUNT 1
+#else
+#define HID_INTERFACE_COUNT 0
+#define HID_ENPOINT_COUNT 0
+#endif
+
+#define CDC_ACM_INTERFACE 0 // CDC ACM
+#define CDC_DATA_INTERFACE 1 // CDC Data
+#define CDC_FIRST_ENDPOINT 1
+#define CDC_ENDPOINT_ACM (CDC_FIRST_ENDPOINT) // CDC First
+#define CDC_ENDPOINT_OUT (CDC_FIRST_ENDPOINT+1)
+#define CDC_ENDPOINT_IN (CDC_FIRST_ENDPOINT+2)
+
+#define HID_INTERFACE (CDC_ACM_INTERFACE + CDC_INTERFACE_COUNT) // HID Interface
+#define HID_FIRST_ENDPOINT (CDC_FIRST_ENDPOINT + CDC_ENPOINT_COUNT)
+#define HID_ENDPOINT_INT (HID_FIRST_ENDPOINT)
+
+#define INTERFACE_COUNT (MSC_INTERFACE + MSC_INTERFACE_COUNT)
+
+#ifdef CDC_ENABLED
+#define CDC_RX CDC_ENDPOINT_OUT
+#define CDC_TX CDC_ENDPOINT_IN
+#endif
+
+#ifdef HID_ENABLED
+#define HID_TX HID_ENDPOINT_INT
+#endif
+
+#define IMANUFACTURER 1
+#define IPRODUCT 2
+
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Udp.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Udp.h
new file mode 100644
index 000000000..dc5644b9d
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/Udp.h
@@ -0,0 +1,88 @@
+/*
+ * Udp.cpp: Library to send/receive UDP packets.
+ *
+ * NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these)
+ * 1) UDP does not guarantee the order in which assembled UDP packets are received. This
+ * might not happen often in practice, but in larger network topologies, a UDP
+ * packet can be received out of sequence.
+ * 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being
+ * aware of it. Again, this may not be a concern in practice on small local networks.
+ * For more information, see http://www.cafeaulait.org/course/week12/35.html
+ *
+ * MIT License:
+ * Copyright (c) 2008 Bjoern Hartmann
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * bjoern@cs.stanford.edu 12/30/2008
+ */
+
+#ifndef udp_h
+#define udp_h
+
+#include <Stream.h>
+#include <IPAddress.h>
+
+class UDP : public Stream {
+
+public:
+ virtual uint8_t begin(uint16_t) =0; // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use
+ virtual void stop() =0; // Finish with the UDP socket
+
+ // Sending UDP packets
+
+ // Start building up a packet to send to the remote host specific in ip and port
+ // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port
+ virtual int beginPacket(IPAddress ip, uint16_t port) =0;
+ // Start building up a packet to send to the remote host specific in host and port
+ // Returns 1 if successful, 0 if there was a problem resolving the hostname or port
+ virtual int beginPacket(const char *host, uint16_t port) =0;
+ // Finish off this packet and send it
+ // Returns 1 if the packet was sent successfully, 0 if there was an error
+ virtual int endPacket() =0;
+ // Write a single byte into the packet
+ virtual size_t write(uint8_t) =0;
+ // Write size bytes from buffer into the packet
+ virtual size_t write(const uint8_t *buffer, size_t size) =0;
+
+ // Start processing the next available incoming packet
+ // Returns the size of the packet in bytes, or 0 if no packets are available
+ virtual int parsePacket() =0;
+ // Number of bytes remaining in the current packet
+ virtual int available() =0;
+ // Read a single byte from the current packet
+ virtual int read() =0;
+ // Read up to len bytes from the current packet and place them into buffer
+ // Returns the number of bytes read, or 0 if none are available
+ virtual int read(unsigned char* buffer, size_t len) =0;
+ // Read up to len characters from the current packet and place them into buffer
+ // Returns the number of characters read, or 0 if none are available
+ virtual int read(char* buffer, size_t len) =0;
+ // Return the next byte from the current packet without moving on to the next byte
+ virtual int peek() =0;
+ virtual void flush() =0; // Finish reading the current packet
+
+ // Return the IP address of the host who sent the current incoming packet
+ virtual IPAddress remoteIP() =0;
+ // Return the port of the host who sent the current incoming packet
+ virtual uint16_t remotePort() =0;
+protected:
+ uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); };
+};
+
+#endif
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WCharacter.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WCharacter.h
new file mode 100644
index 000000000..79733b50a
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WCharacter.h
@@ -0,0 +1,168 @@
+/*
+ WCharacter.h - Character utility functions for Wiring & Arduino
+ Copyright (c) 2010 Hernando Barragan. All right reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef Character_h
+#define Character_h
+
+#include <ctype.h>
+
+// WCharacter.h prototypes
+inline boolean isAlphaNumeric(int c) __attribute__((always_inline));
+inline boolean isAlpha(int c) __attribute__((always_inline));
+inline boolean isAscii(int c) __attribute__((always_inline));
+inline boolean isWhitespace(int c) __attribute__((always_inline));
+inline boolean isControl(int c) __attribute__((always_inline));
+inline boolean isDigit(int c) __attribute__((always_inline));
+inline boolean isGraph(int c) __attribute__((always_inline));
+inline boolean isLowerCase(int c) __attribute__((always_inline));
+inline boolean isPrintable(int c) __attribute__((always_inline));
+inline boolean isPunct(int c) __attribute__((always_inline));
+inline boolean isSpace(int c) __attribute__((always_inline));
+inline boolean isUpperCase(int c) __attribute__((always_inline));
+inline boolean isHexadecimalDigit(int c) __attribute__((always_inline));
+inline int toAscii(int c) __attribute__((always_inline));
+inline int toLowerCase(int c) __attribute__((always_inline));
+inline int toUpperCase(int c)__attribute__((always_inline));
+
+
+// Checks for an alphanumeric character.
+// It is equivalent to (isalpha(c) || isdigit(c)).
+inline boolean isAlphaNumeric(int c)
+{
+ return ( isalnum(c) == 0 ? false : true);
+}
+
+
+// Checks for an alphabetic character.
+// It is equivalent to (isupper(c) || islower(c)).
+inline boolean isAlpha(int c)
+{
+ return ( isalpha(c) == 0 ? false : true);
+}
+
+
+// Checks whether c is a 7-bit unsigned char value
+// that fits into the ASCII character set.
+inline boolean isAscii(int c)
+{
+ return ( isascii (c) == 0 ? false : true);
+}
+
+
+// Checks for a blank character, that is, a space or a tab.
+inline boolean isWhitespace(int c)
+{
+ return ( isblank (c) == 0 ? false : true);
+}
+
+
+// Checks for a control character.
+inline boolean isControl(int c)
+{
+ return ( iscntrl (c) == 0 ? false : true);
+}
+
+
+// Checks for a digit (0 through 9).
+inline boolean isDigit(int c)
+{
+ return ( isdigit (c) == 0 ? false : true);
+}
+
+
+// Checks for any printable character except space.
+inline boolean isGraph(int c)
+{
+ return ( isgraph (c) == 0 ? false : true);
+}
+
+
+// Checks for a lower-case character.
+inline boolean isLowerCase(int c)
+{
+ return (islower (c) == 0 ? false : true);
+}
+
+
+// Checks for any printable character including space.
+inline boolean isPrintable(int c)
+{
+ return ( isprint (c) == 0 ? false : true);
+}
+
+
+// Checks for any printable character which is not a space
+// or an alphanumeric character.
+inline boolean isPunct(int c)
+{
+ return ( ispunct (c) == 0 ? false : true);
+}
+
+
+// Checks for white-space characters. For the avr-libc library,
+// these are: space, formfeed ('\f'), newline ('\n'), carriage
+// return ('\r'), horizontal tab ('\t'), and vertical tab ('\v').
+inline boolean isSpace(int c)
+{
+ return ( isspace (c) == 0 ? false : true);
+}
+
+
+// Checks for an uppercase letter.
+inline boolean isUpperCase(int c)
+{
+ return ( isupper (c) == 0 ? false : true);
+}
+
+
+// Checks for a hexadecimal digits, i.e. one of 0 1 2 3 4 5 6 7
+// 8 9 a b c d e f A B C D E F.
+inline boolean isHexadecimalDigit(int c)
+{
+ return ( isxdigit (c) == 0 ? false : true);
+}
+
+
+// Converts c to a 7-bit unsigned char value that fits into the
+// ASCII character set, by clearing the high-order bits.
+inline int toAscii(int c)
+{
+ return toascii (c);
+}
+
+
+// Warning:
+// Many people will be unhappy if you use this function.
+// This function will convert accented letters into random
+// characters.
+
+// Converts the letter c to lower case, if possible.
+inline int toLowerCase(int c)
+{
+ return tolower (c);
+}
+
+
+// Converts the letter c to upper case, if possible.
+inline int toUpperCase(int c)
+{
+ return toupper (c);
+}
+
+#endif \ No newline at end of file
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WInterrupts.c b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WInterrupts.c
new file mode 100644
index 000000000..8f3ec847f
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WInterrupts.c
@@ -0,0 +1,298 @@
+/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
+
+/*
+ Part of the Wiring project - http://wiring.uniandes.edu.co
+
+ Copyright (c) 2004-05 Hernando Barragan
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ Boston, MA 02111-1307 USA
+
+ Modified 24 November 2006 by David A. Mellis
+ Modified 1 August 2010 by Mark Sproul
+*/
+
+#include <inttypes.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/pgmspace.h>
+#include <stdio.h>
+
+#include "wiring_private.h"
+
+static volatile voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS];
+// volatile static voidFuncPtr twiIntFunc;
+
+void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) {
+ if(interruptNum < EXTERNAL_NUM_INTERRUPTS) {
+ intFunc[interruptNum] = userFunc;
+
+ // Configure the interrupt mode (trigger on low input, any change, rising
+ // edge, or falling edge). The mode constants were chosen to correspond
+ // to the configuration bits in the hardware register, so we simply shift
+ // the mode into place.
+
+ // Enable the interrupt.
+
+ switch (interruptNum) {
+#if defined(__AVR_ATmega32U4__)
+ // I hate doing this, but the register assignment differs between the 1280/2560
+ // and the 32U4. Since avrlib defines registers PCMSK1 and PCMSK2 that aren't
+ // even present on the 32U4 this is the only way to distinguish between them.
+ case 0:
+ EICRA = (EICRA & ~((1<<ISC00) | (1<<ISC01))) | (mode << ISC00);
+ EIMSK |= (1<<INT0);
+ break;
+ case 1:
+ EICRA = (EICRA & ~((1<<ISC10) | (1<<ISC11))) | (mode << ISC10);
+ EIMSK |= (1<<INT1);
+ break;
+#elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
+ case 2:
+ EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
+ EIMSK |= (1 << INT0);
+ break;
+ case 3:
+ EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
+ EIMSK |= (1 << INT1);
+ break;
+ case 4:
+ EICRA = (EICRA & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
+ EIMSK |= (1 << INT2);
+ break;
+ case 5:
+ EICRA = (EICRA & ~((1 << ISC30) | (1 << ISC31))) | (mode << ISC30);
+ EIMSK |= (1 << INT3);
+ break;
+ case 0:
+ EICRB = (EICRB & ~((1 << ISC40) | (1 << ISC41))) | (mode << ISC40);
+ EIMSK |= (1 << INT4);
+ break;
+ case 1:
+ EICRB = (EICRB & ~((1 << ISC50) | (1 << ISC51))) | (mode << ISC50);
+ EIMSK |= (1 << INT5);
+ break;
+ case 6:
+ EICRB = (EICRB & ~((1 << ISC60) | (1 << ISC61))) | (mode << ISC60);
+ EIMSK |= (1 << INT6);
+ break;
+ case 7:
+ EICRB = (EICRB & ~((1 << ISC70) | (1 << ISC71))) | (mode << ISC70);
+ EIMSK |= (1 << INT7);
+ break;
+#else
+ case 0:
+ #if defined(EICRA) && defined(ISC00) && defined(EIMSK)
+ EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
+ EIMSK |= (1 << INT0);
+ #elif defined(MCUCR) && defined(ISC00) && defined(GICR)
+ MCUCR = (MCUCR & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
+ GICR |= (1 << INT0);
+ #elif defined(MCUCR) && defined(ISC00) && defined(GIMSK)
+ MCUCR = (MCUCR & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
+ GIMSK |= (1 << INT0);
+ #else
+ #error attachInterrupt not finished for this CPU (case 0)
+ #endif
+ break;
+
+ case 1:
+ #if defined(EICRA) && defined(ISC10) && defined(ISC11) && defined(EIMSK)
+ EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
+ EIMSK |= (1 << INT1);
+ #elif defined(MCUCR) && defined(ISC10) && defined(ISC11) && defined(GICR)
+ MCUCR = (MCUCR & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
+ GICR |= (1 << INT1);
+ #elif defined(MCUCR) && defined(ISC10) && defined(GIMSK) && defined(GIMSK)
+ MCUCR = (MCUCR & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
+ GIMSK |= (1 << INT1);
+ #else
+ #warning attachInterrupt may need some more work for this cpu (case 1)
+ #endif
+ break;
+
+ case 2:
+ #if defined(EICRA) && defined(ISC20) && defined(ISC21) && defined(EIMSK)
+ EICRA = (EICRA & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
+ EIMSK |= (1 << INT2);
+ #elif defined(MCUCR) && defined(ISC20) && defined(ISC21) && defined(GICR)
+ MCUCR = (MCUCR & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
+ GICR |= (1 << INT2);
+ #elif defined(MCUCR) && defined(ISC20) && defined(GIMSK) && defined(GIMSK)
+ MCUCR = (MCUCR & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
+ GIMSK |= (1 << INT2);
+ #endif
+ break;
+#endif
+ }
+ }
+}
+
+void detachInterrupt(uint8_t interruptNum) {
+ if(interruptNum < EXTERNAL_NUM_INTERRUPTS) {
+ // Disable the interrupt. (We can't assume that interruptNum is equal
+ // to the number of the EIMSK bit to clear, as this isn't true on the
+ // ATmega8. There, INT0 is 6 and INT1 is 7.)
+ switch (interruptNum) {
+#if defined(__AVR_ATmega32U4__)
+ case 0:
+ EIMSK &= ~(1<<INT0);
+ break;
+ case 1:
+ EIMSK &= ~(1<<INT1);
+ break;
+#elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
+ case 2:
+ EIMSK &= ~(1 << INT0);
+ break;
+ case 3:
+ EIMSK &= ~(1 << INT1);
+ break;
+ case 4:
+ EIMSK &= ~(1 << INT2);
+ break;
+ case 5:
+ EIMSK &= ~(1 << INT3);
+ break;
+ case 0:
+ EIMSK &= ~(1 << INT4);
+ break;
+ case 1:
+ EIMSK &= ~(1 << INT5);
+ break;
+ case 6:
+ EIMSK &= ~(1 << INT6);
+ break;
+ case 7:
+ EIMSK &= ~(1 << INT7);
+ break;
+#else
+ case 0:
+ #if defined(EIMSK) && defined(INT0)
+ EIMSK &= ~(1 << INT0);
+ #elif defined(GICR) && defined(ISC00)
+ GICR &= ~(1 << INT0); // atmega32
+ #elif defined(GIMSK) && defined(INT0)
+ GIMSK &= ~(1 << INT0);
+ #else
+ #error detachInterrupt not finished for this cpu
+ #endif
+ break;
+
+ case 1:
+ #if defined(EIMSK) && defined(INT1)
+ EIMSK &= ~(1 << INT1);
+ #elif defined(GICR) && defined(INT1)
+ GICR &= ~(1 << INT1); // atmega32
+ #elif defined(GIMSK) && defined(INT1)
+ GIMSK &= ~(1 << INT1);
+ #else
+ #warning detachInterrupt may need some more work for this cpu (case 1)
+ #endif
+ break;
+#endif
+ }
+
+ intFunc[interruptNum] = 0;
+ }
+}
+
+/*
+void attachInterruptTwi(void (*userFunc)(void) ) {
+ twiIntFunc = userFunc;
+}
+*/
+
+#if defined(__AVR_ATmega32U4__)
+SIGNAL(INT0_vect) {
+ if(intFunc[EXTERNAL_INT_0])
+ intFunc[EXTERNAL_INT_0]();
+}
+
+SIGNAL(INT1_vect) {
+ if(intFunc[EXTERNAL_INT_1])
+ intFunc[EXTERNAL_INT_1]();
+}
+
+#elif defined(EICRA) && defined(EICRB)
+
+SIGNAL(INT0_vect) {
+ if(intFunc[EXTERNAL_INT_2])
+ intFunc[EXTERNAL_INT_2]();
+}
+
+SIGNAL(INT1_vect) {
+ if(intFunc[EXTERNAL_INT_3])
+ intFunc[EXTERNAL_INT_3]();
+}
+
+SIGNAL(INT2_vect) {
+ if(intFunc[EXTERNAL_INT_4])
+ intFunc[EXTERNAL_INT_4]();
+}
+
+SIGNAL(INT3_vect) {
+ if(intFunc[EXTERNAL_INT_5])
+ intFunc[EXTERNAL_INT_5]();
+}
+
+SIGNAL(INT4_vect) {
+ if(intFunc[EXTERNAL_INT_0])
+ intFunc[EXTERNAL_INT_0]();
+}
+
+SIGNAL(INT5_vect) {
+ if(intFunc[EXTERNAL_INT_1])
+ intFunc[EXTERNAL_INT_1]();
+}
+
+SIGNAL(INT6_vect) {
+ if(intFunc[EXTERNAL_INT_6])
+ intFunc[EXTERNAL_INT_6]();
+}
+
+SIGNAL(INT7_vect) {
+ if(intFunc[EXTERNAL_INT_7])
+ intFunc[EXTERNAL_INT_7]();
+}
+
+#else
+
+SIGNAL(INT0_vect) {
+ if(intFunc[EXTERNAL_INT_0])
+ intFunc[EXTERNAL_INT_0]();
+}
+
+SIGNAL(INT1_vect) {
+ if(intFunc[EXTERNAL_INT_1])
+ intFunc[EXTERNAL_INT_1]();
+}
+
+#if defined(EICRA) && defined(ISC20)
+SIGNAL(INT2_vect) {
+ if(intFunc[EXTERNAL_INT_2])
+ intFunc[EXTERNAL_INT_2]();
+}
+#endif
+
+#endif
+
+/*
+SIGNAL(SIG_2WIRE_SERIAL) {
+ if(twiIntFunc)
+ twiIntFunc();
+}
+*/
+
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WMath.cpp b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WMath.cpp
new file mode 100644
index 000000000..2120c4cc1
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WMath.cpp
@@ -0,0 +1,60 @@
+/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
+
+/*
+ Part of the Wiring project - http://wiring.org.co
+ Copyright (c) 2004-06 Hernando Barragan
+ Modified 13 August 2006, David A. Mellis for Arduino - http://www.arduino.cc/
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ Boston, MA 02111-1307 USA
+
+ $Id$
+*/
+
+extern "C" {
+ #include "stdlib.h"
+}
+
+void randomSeed(unsigned int seed)
+{
+ if (seed != 0) {
+ srandom(seed);
+ }
+}
+
+long random(long howbig)
+{
+ if (howbig == 0) {
+ return 0;
+ }
+ return random() % howbig;
+}
+
+long random(long howsmall, long howbig)
+{
+ if (howsmall >= howbig) {
+ return howsmall;
+ }
+ long diff = howbig - howsmall;
+ return random(diff) + howsmall;
+}
+
+long map(long x, long in_min, long in_max, long out_min, long out_max)
+{
+ return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
+}
+
+unsigned int makeWord(unsigned int w) { return w; }
+unsigned int makeWord(unsigned char h, unsigned char l) { return (h << 8) | l; } \ No newline at end of file
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WString.cpp b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WString.cpp
new file mode 100644
index 000000000..c6839fc0d
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WString.cpp
@@ -0,0 +1,645 @@
+/*
+ WString.cpp - String library for Wiring & Arduino
+ ...mostly rewritten by Paul Stoffregen...
+ Copyright (c) 2009-10 Hernando Barragan. All rights reserved.
+ Copyright 2011, Paul Stoffregen, paul@pjrc.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "WString.h"
+
+
+/*********************************************/
+/* Constructors */
+/*********************************************/
+
+String::String(const char *cstr)
+{
+ init();
+ if (cstr) copy(cstr, strlen(cstr));
+}
+
+String::String(const String &value)
+{
+ init();
+ *this = value;
+}
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+String::String(String &&rval)
+{
+ init();
+ move(rval);
+}
+String::String(StringSumHelper &&rval)
+{
+ init();
+ move(rval);
+}
+#endif
+
+String::String(char c)
+{
+ init();
+ char buf[2];
+ buf[0] = c;
+ buf[1] = 0;
+ *this = buf;
+}
+
+String::String(unsigned char value, unsigned char base)
+{
+ init();
+ char buf[9];
+ utoa(value, buf, base);
+ *this = buf;
+}
+
+String::String(int value, unsigned char base)
+{
+ init();
+ char buf[18];
+ itoa(value, buf, base);
+ *this = buf;
+}
+
+String::String(unsigned int value, unsigned char base)
+{
+ init();
+ char buf[17];
+ utoa(value, buf, base);
+ *this = buf;
+}
+
+String::String(long value, unsigned char base)
+{
+ init();
+ char buf[34];
+ ltoa(value, buf, base);
+ *this = buf;
+}
+
+String::String(unsigned long value, unsigned char base)
+{
+ init();
+ char buf[33];
+ ultoa(value, buf, base);
+ *this = buf;
+}
+
+String::~String()
+{
+ free(buffer);
+}
+
+/*********************************************/
+/* Memory Management */
+/*********************************************/
+
+inline void String::init(void)
+{
+ buffer = NULL;
+ capacity = 0;
+ len = 0;
+ flags = 0;
+}
+
+void String::invalidate(void)
+{
+ if (buffer) free(buffer);
+ buffer = NULL;
+ capacity = len = 0;
+}
+
+unsigned char String::reserve(unsigned int size)
+{
+ if (buffer && capacity >= size) return 1;
+ if (changeBuffer(size)) {
+ if (len == 0) buffer[0] = 0;
+ return 1;
+ }
+ return 0;
+}
+
+unsigned char String::changeBuffer(unsigned int maxStrLen)
+{
+ char *newbuffer = (char *)realloc(buffer, maxStrLen + 1);
+ if (newbuffer) {
+ buffer = newbuffer;
+ capacity = maxStrLen;
+ return 1;
+ }
+ return 0;
+}
+
+/*********************************************/
+/* Copy and Move */
+/*********************************************/
+
+String & String::copy(const char *cstr, unsigned int length)
+{
+ if (!reserve(length)) {
+ invalidate();
+ return *this;
+ }
+ len = length;
+ strcpy(buffer, cstr);
+ return *this;
+}
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+void String::move(String &rhs)
+{
+ if (buffer) {
+ if (capacity >= rhs.len) {
+ strcpy(buffer, rhs.buffer);
+ len = rhs.len;
+ rhs.len = 0;
+ return;
+ } else {
+ free(buffer);
+ }
+ }
+ buffer = rhs.buffer;
+ capacity = rhs.capacity;
+ len = rhs.len;
+ rhs.buffer = NULL;
+ rhs.capacity = 0;
+ rhs.len = 0;
+}
+#endif
+
+String & String::operator = (const String &rhs)
+{
+ if (this == &rhs) return *this;
+
+ if (rhs.buffer) copy(rhs.buffer, rhs.len);
+ else invalidate();
+
+ return *this;
+}
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+String & String::operator = (String &&rval)
+{
+ if (this != &rval) move(rval);
+ return *this;
+}
+
+String & String::operator = (StringSumHelper &&rval)
+{
+ if (this != &rval) move(rval);
+ return *this;
+}
+#endif
+
+String & String::operator = (const char *cstr)
+{
+ if (cstr) copy(cstr, strlen(cstr));
+ else invalidate();
+
+ return *this;
+}
+
+/*********************************************/
+/* concat */
+/*********************************************/
+
+unsigned char String::concat(const String &s)
+{
+ return concat(s.buffer, s.len);
+}
+
+unsigned char String::concat(const char *cstr, unsigned int length)
+{
+ unsigned int newlen = len + length;
+ if (!cstr) return 0;
+ if (length == 0) return 1;
+ if (!reserve(newlen)) return 0;
+ strcpy(buffer + len, cstr);
+ len = newlen;
+ return 1;
+}
+
+unsigned char String::concat(const char *cstr)
+{
+ if (!cstr) return 0;
+ return concat(cstr, strlen(cstr));
+}
+
+unsigned char String::concat(char c)
+{
+ char buf[2];
+ buf[0] = c;
+ buf[1] = 0;
+ return concat(buf, 1);
+}
+
+unsigned char String::concat(unsigned char num)
+{
+ char buf[4];
+ itoa(num, buf, 10);
+ return concat(buf, strlen(buf));
+}
+
+unsigned char String::concat(int num)
+{
+ char buf[7];
+ itoa(num, buf, 10);
+ return concat(buf, strlen(buf));
+}
+
+unsigned char String::concat(unsigned int num)
+{
+ char buf[6];
+ utoa(num, buf, 10);
+ return concat(buf, strlen(buf));
+}
+
+unsigned char String::concat(long num)
+{
+ char buf[12];
+ ltoa(num, buf, 10);
+ return concat(buf, strlen(buf));
+}
+
+unsigned char String::concat(unsigned long num)
+{
+ char buf[11];
+ ultoa(num, buf, 10);
+ return concat(buf, strlen(buf));
+}
+
+/*********************************************/
+/* Concatenate */
+/*********************************************/
+
+StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs)
+{
+ StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
+ if (!a.concat(rhs.buffer, rhs.len)) a.invalidate();
+ return a;
+}
+
+StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr)
+{
+ StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
+ if (!cstr || !a.concat(cstr, strlen(cstr))) a.invalidate();
+ return a;
+}
+
+StringSumHelper & operator + (const StringSumHelper &lhs, char c)
+{
+ StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
+ if (!a.concat(c)) a.invalidate();
+ return a;
+}
+
+StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num)
+{
+ StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
+ if (!a.concat(num)) a.invalidate();
+ return a;
+}
+
+StringSumHelper & operator + (const StringSumHelper &lhs, int num)
+{
+ StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
+ if (!a.concat(num)) a.invalidate();
+ return a;
+}
+
+StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num)
+{
+ StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
+ if (!a.concat(num)) a.invalidate();
+ return a;
+}
+
+StringSumHelper & operator + (const StringSumHelper &lhs, long num)
+{
+ StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
+ if (!a.concat(num)) a.invalidate();
+ return a;
+}
+
+StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num)
+{
+ StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
+ if (!a.concat(num)) a.invalidate();
+ return a;
+}
+
+/*********************************************/
+/* Comparison */
+/*********************************************/
+
+int String::compareTo(const String &s) const
+{
+ if (!buffer || !s.buffer) {
+ if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer;
+ if (buffer && len > 0) return *(unsigned char *)buffer;
+ return 0;
+ }
+ return strcmp(buffer, s.buffer);
+}
+
+unsigned char String::equals(const String &s2) const
+{
+ return (len == s2.len && compareTo(s2) == 0);
+}
+
+unsigned char String::equals(const char *cstr) const
+{
+ if (len == 0) return (cstr == NULL || *cstr == 0);
+ if (cstr == NULL) return buffer[0] == 0;
+ return strcmp(buffer, cstr) == 0;
+}
+
+unsigned char String::operator<(const String &rhs) const
+{
+ return compareTo(rhs) < 0;
+}
+
+unsigned char String::operator>(const String &rhs) const
+{
+ return compareTo(rhs) > 0;
+}
+
+unsigned char String::operator<=(const String &rhs) const
+{
+ return compareTo(rhs) <= 0;
+}
+
+unsigned char String::operator>=(const String &rhs) const
+{
+ return compareTo(rhs) >= 0;
+}
+
+unsigned char String::equalsIgnoreCase( const String &s2 ) const
+{
+ if (this == &s2) return 1;
+ if (len != s2.len) return 0;
+ if (len == 0) return 1;
+ const char *p1 = buffer;
+ const char *p2 = s2.buffer;
+ while (*p1) {
+ if (tolower(*p1++) != tolower(*p2++)) return 0;
+ }
+ return 1;
+}
+
+unsigned char String::startsWith( const String &s2 ) const
+{
+ if (len < s2.len) return 0;
+ return startsWith(s2, 0);
+}
+
+unsigned char String::startsWith( const String &s2, unsigned int offset ) const
+{
+ if (offset > len - s2.len || !buffer || !s2.buffer) return 0;
+ return strncmp( &buffer[offset], s2.buffer, s2.len ) == 0;
+}
+
+unsigned char String::endsWith( const String &s2 ) const
+{
+ if ( len < s2.len || !buffer || !s2.buffer) return 0;
+ return strcmp(&buffer[len - s2.len], s2.buffer) == 0;
+}
+
+/*********************************************/
+/* Character Access */
+/*********************************************/
+
+char String::charAt(unsigned int loc) const
+{
+ return operator[](loc);
+}
+
+void String::setCharAt(unsigned int loc, char c)
+{
+ if (loc < len) buffer[loc] = c;
+}
+
+char & String::operator[](unsigned int index)
+{
+ static char dummy_writable_char;
+ if (index >= len || !buffer) {
+ dummy_writable_char = 0;
+ return dummy_writable_char;
+ }
+ return buffer[index];
+}
+
+char String::operator[]( unsigned int index ) const
+{
+ if (index >= len || !buffer) return 0;
+ return buffer[index];
+}
+
+void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const
+{
+ if (!bufsize || !buf) return;
+ if (index >= len) {
+ buf[0] = 0;
+ return;
+ }
+ unsigned int n = bufsize - 1;
+ if (n > len - index) n = len - index;
+ strncpy((char *)buf, buffer + index, n);
+ buf[n] = 0;
+}
+
+/*********************************************/
+/* Search */
+/*********************************************/
+
+int String::indexOf(char c) const
+{
+ return indexOf(c, 0);
+}
+
+int String::indexOf( char ch, unsigned int fromIndex ) const
+{
+ if (fromIndex >= len) return -1;
+ const char* temp = strchr(buffer + fromIndex, ch);
+ if (temp == NULL) return -1;
+ return temp - buffer;
+}
+
+int String::indexOf(const String &s2) const
+{
+ return indexOf(s2, 0);
+}
+
+int String::indexOf(const String &s2, unsigned int fromIndex) const
+{
+ if (fromIndex >= len) return -1;
+ const char *found = strstr(buffer + fromIndex, s2.buffer);
+ if (found == NULL) return -1;
+ return found - buffer;
+}
+
+int String::lastIndexOf( char theChar ) const
+{
+ return lastIndexOf(theChar, len - 1);
+}
+
+int String::lastIndexOf(char ch, unsigned int fromIndex) const
+{
+ if (fromIndex >= len) return -1;
+ char tempchar = buffer[fromIndex + 1];
+ buffer[fromIndex + 1] = '\0';
+ char* temp = strrchr( buffer, ch );
+ buffer[fromIndex + 1] = tempchar;
+ if (temp == NULL) return -1;
+ return temp - buffer;
+}
+
+int String::lastIndexOf(const String &s2) const
+{
+ return lastIndexOf(s2, len - s2.len);
+}
+
+int String::lastIndexOf(const String &s2, unsigned int fromIndex) const
+{
+ if (s2.len == 0 || len == 0 || s2.len > len) return -1;
+ if (fromIndex >= len) fromIndex = len - 1;
+ int found = -1;
+ for (char *p = buffer; p <= buffer + fromIndex; p++) {
+ p = strstr(p, s2.buffer);
+ if (!p) break;
+ if ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer;
+ }
+ return found;
+}
+
+String String::substring( unsigned int left ) const
+{
+ return substring(left, len);
+}
+
+String String::substring(unsigned int left, unsigned int right) const
+{
+ if (left > right) {
+ unsigned int temp = right;
+ right = left;
+ left = temp;
+ }
+ String out;
+ if (left > len) return out;
+ if (right > len) right = len;
+ char temp = buffer[right]; // save the replaced character
+ buffer[right] = '\0';
+ out = buffer + left; // pointer arithmetic
+ buffer[right] = temp; //restore character
+ return out;
+}
+
+/*********************************************/
+/* Modification */
+/*********************************************/
+
+void String::replace(char find, char replace)
+{
+ if (!buffer) return;
+ for (char *p = buffer; *p; p++) {
+ if (*p == find) *p = replace;
+ }
+}
+
+void String::replace(const String& find, const String& replace)
+{
+ if (len == 0 || find.len == 0) return;
+ int diff = replace.len - find.len;
+ char *readFrom = buffer;
+ char *foundAt;
+ if (diff == 0) {
+ while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
+ memcpy(foundAt, replace.buffer, replace.len);
+ readFrom = foundAt + replace.len;
+ }
+ } else if (diff < 0) {
+ char *writeTo = buffer;
+ while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
+ unsigned int n = foundAt - readFrom;
+ memcpy(writeTo, readFrom, n);
+ writeTo += n;
+ memcpy(writeTo, replace.buffer, replace.len);
+ writeTo += replace.len;
+ readFrom = foundAt + find.len;
+ len += diff;
+ }
+ strcpy(writeTo, readFrom);
+ } else {
+ unsigned int size = len; // compute size needed for result
+ while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
+ readFrom = foundAt + find.len;
+ size += diff;
+ }
+ if (size == len) return;
+ if (size > capacity && !changeBuffer(size)) return; // XXX: tell user!
+ int index = len - 1;
+ while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) {
+ readFrom = buffer + index + find.len;
+ memmove(readFrom + diff, readFrom, len - (readFrom - buffer));
+ len += diff;
+ buffer[len] = 0;
+ memcpy(buffer + index, replace.buffer, replace.len);
+ index--;
+ }
+ }
+}
+
+void String::toLowerCase(void)
+{
+ if (!buffer) return;
+ for (char *p = buffer; *p; p++) {
+ *p = tolower(*p);
+ }
+}
+
+void String::toUpperCase(void)
+{
+ if (!buffer) return;
+ for (char *p = buffer; *p; p++) {
+ *p = toupper(*p);
+ }
+}
+
+void String::trim(void)
+{
+ if (!buffer || len == 0) return;
+ char *begin = buffer;
+ while (isspace(*begin)) begin++;
+ char *end = buffer + len - 1;
+ while (isspace(*end) && end >= begin) end--;
+ len = end + 1 - begin;
+ if (begin > buffer) memcpy(buffer, begin, len);
+ buffer[len] = 0;
+}
+
+/*********************************************/
+/* Parsing / Conversion */
+/*********************************************/
+
+long String::toInt(void) const
+{
+ if (buffer) return atol(buffer);
+ return 0;
+}
+
+
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WString.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WString.h
new file mode 100644
index 000000000..947325e5f
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/WString.h
@@ -0,0 +1,205 @@
+/*
+ WString.h - String library for Wiring & Arduino
+ ...mostly rewritten by Paul Stoffregen...
+ Copyright (c) 2009-10 Hernando Barragan. All right reserved.
+ Copyright 2011, Paul Stoffregen, paul@pjrc.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef String_class_h
+#define String_class_h
+#ifdef __cplusplus
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <avr/pgmspace.h>
+
+// When compiling programs with this class, the following gcc parameters
+// dramatically increase performance and memory (RAM) efficiency, typically
+// with little or no increase in code size.
+// -felide-constructors
+// -std=c++0x
+
+class __FlashStringHelper;
+#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))
+
+// An inherited class for holding the result of a concatenation. These
+// result objects are assumed to be writable by subsequent concatenations.
+class StringSumHelper;
+
+// The string class
+class String
+{
+ // use a function pointer to allow for "if (s)" without the
+ // complications of an operator bool(). for more information, see:
+ // http://www.artima.com/cppsource/safebool.html
+ typedef void (String::*StringIfHelperType)() const;
+ void StringIfHelper() const {}
+
+public:
+ // constructors
+ // creates a copy of the initial value.
+ // if the initial value is null or invalid, or if memory allocation
+ // fails, the string will be marked as invalid (i.e. "if (s)" will
+ // be false).
+ String(const char *cstr = "");
+ String(const String &str);
+ #ifdef __GXX_EXPERIMENTAL_CXX0X__
+ String(String &&rval);
+ String(StringSumHelper &&rval);
+ #endif
+ explicit String(char c);
+ explicit String(unsigned char, unsigned char base=10);
+ explicit String(int, unsigned char base=10);
+ explicit String(unsigned int, unsigned char base=10);
+ explicit String(long, unsigned char base=10);
+ explicit String(unsigned long, unsigned char base=10);
+ ~String(void);
+
+ // memory management
+ // return true on success, false on failure (in which case, the string
+ // is left unchanged). reserve(0), if successful, will validate an
+ // invalid string (i.e., "if (s)" will be true afterwards)
+ unsigned char reserve(unsigned int size);
+ inline unsigned int length(void) const {return len;}
+
+ // creates a copy of the assigned value. if the value is null or
+ // invalid, or if the memory allocation fails, the string will be
+ // marked as invalid ("if (s)" will be false).
+ String & operator = (const String &rhs);
+ String & operator = (const char *cstr);
+ #ifdef __GXX_EXPERIMENTAL_CXX0X__
+ String & operator = (String &&rval);
+ String & operator = (StringSumHelper &&rval);
+ #endif
+
+ // concatenate (works w/ built-in types)
+
+ // returns true on success, false on failure (in which case, the string
+ // is left unchanged). if the argument is null or invalid, the
+ // concatenation is considered unsucessful.
+ unsigned char concat(const String &str);
+ unsigned char concat(const char *cstr);
+ unsigned char concat(char c);
+ unsigned char concat(unsigned char c);
+ unsigned char concat(int num);
+ unsigned char concat(unsigned int num);
+ unsigned char concat(long num);
+ unsigned char concat(unsigned long num);
+
+ // if there's not enough memory for the concatenated value, the string
+ // will be left unchanged (but this isn't signalled in any way)
+ String & operator += (const String &rhs) {concat(rhs); return (*this);}
+ String & operator += (const char *cstr) {concat(cstr); return (*this);}
+ String & operator += (char c) {concat(c); return (*this);}
+ String & operator += (unsigned char num) {concat(num); return (*this);}
+ String & operator += (int num) {concat(num); return (*this);}
+ String & operator += (unsigned int num) {concat(num); return (*this);}
+ String & operator += (long num) {concat(num); return (*this);}
+ String & operator += (unsigned long num) {concat(num); return (*this);}
+
+ friend StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs);
+ friend StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr);
+ friend StringSumHelper & operator + (const StringSumHelper &lhs, char c);
+ friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num);
+ friend StringSumHelper & operator + (const StringSumHelper &lhs, int num);
+ friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num);
+ friend StringSumHelper & operator + (const StringSumHelper &lhs, long num);
+ friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num);
+
+ // comparison (only works w/ Strings and "strings")
+ operator StringIfHelperType() const { return buffer ? &String::StringIfHelper : 0; }
+ int compareTo(const String &s) const;
+ unsigned char equals(const String &s) const;
+ unsigned char equals(const char *cstr) const;
+ unsigned char operator == (const String &rhs) const {return equals(rhs);}
+ unsigned char operator == (const char *cstr) const {return equals(cstr);}
+ unsigned char operator != (const String &rhs) const {return !equals(rhs);}
+ unsigned char operator != (const char *cstr) const {return !equals(cstr);}
+ unsigned char operator < (const String &rhs) const;
+ unsigned char operator > (const String &rhs) const;
+ unsigned char operator <= (const String &rhs) const;
+ unsigned char operator >= (const String &rhs) const;
+ unsigned char equalsIgnoreCase(const String &s) const;
+ unsigned char startsWith( const String &prefix) const;
+ unsigned char startsWith(const String &prefix, unsigned int offset) const;
+ unsigned char endsWith(const String &suffix) const;
+
+ // character acccess
+ char charAt(unsigned int index) const;
+ void setCharAt(unsigned int index, char c);
+ char operator [] (unsigned int index) const;
+ char& operator [] (unsigned int index);
+ void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index=0) const;
+ void toCharArray(char *buf, unsigned int bufsize, unsigned int index=0) const
+ {getBytes((unsigned char *)buf, bufsize, index);}
+
+ // search
+ int indexOf( char ch ) const;
+ int indexOf( char ch, unsigned int fromIndex ) const;
+ int indexOf( const String &str ) const;
+ int indexOf( const String &str, unsigned int fromIndex ) const;
+ int lastIndexOf( char ch ) const;
+ int lastIndexOf( char ch, unsigned int fromIndex ) const;
+ int lastIndexOf( const String &str ) const;
+ int lastIndexOf( const String &str, unsigned int fromIndex ) const;
+ String substring( unsigned int beginIndex ) const;
+ String substring( unsigned int beginIndex, unsigned int endIndex ) const;
+
+ // modification
+ void replace(char find, char replace);
+ void replace(const String& find, const String& replace);
+ void toLowerCase(void);
+ void toUpperCase(void);
+ void trim(void);
+
+ // parsing/conversion
+ long toInt(void) const;
+
+protected:
+ char *buffer; // the actual char array
+ unsigned int capacity; // the array length minus one (for the '\0')
+ unsigned int len; // the String length (not counting the '\0')
+ unsigned char flags; // unused, for future features
+protected:
+ void init(void);
+ void invalidate(void);
+ unsigned char changeBuffer(unsigned int maxStrLen);
+ unsigned char concat(const char *cstr, unsigned int length);
+
+ // copy and move
+ String & copy(const char *cstr, unsigned int length);
+ #ifdef __GXX_EXPERIMENTAL_CXX0X__
+ void move(String &rhs);
+ #endif
+};
+
+class StringSumHelper : public String
+{
+public:
+ StringSumHelper(const String &s) : String(s) {}
+ StringSumHelper(const char *p) : String(p) {}
+ StringSumHelper(char c) : String(c) {}
+ StringSumHelper(unsigned char num) : String(num) {}
+ StringSumHelper(int num) : String(num) {}
+ StringSumHelper(unsigned int num) : String(num) {}
+ StringSumHelper(long num) : String(num) {}
+ StringSumHelper(unsigned long num) : String(num) {}
+};
+
+#endif // __cplusplus
+#endif // String_class_h
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/binary.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/binary.h
new file mode 100644
index 000000000..af1498033
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/binary.h
@@ -0,0 +1,515 @@
+#ifndef Binary_h
+#define Binary_h
+
+#define B0 0
+#define B00 0
+#define B000 0
+#define B0000 0
+#define B00000 0
+#define B000000 0
+#define B0000000 0
+#define B00000000 0
+#define B1 1
+#define B01 1
+#define B001 1
+#define B0001 1
+#define B00001 1
+#define B000001 1
+#define B0000001 1
+#define B00000001 1
+#define B10 2
+#define B010 2
+#define B0010 2
+#define B00010 2
+#define B000010 2
+#define B0000010 2
+#define B00000010 2
+#define B11 3
+#define B011 3
+#define B0011 3
+#define B00011 3
+#define B000011 3
+#define B0000011 3
+#define B00000011 3
+#define B100 4
+#define B0100 4
+#define B00100 4
+#define B000100 4
+#define B0000100 4
+#define B00000100 4
+#define B101 5
+#define B0101 5
+#define B00101 5
+#define B000101 5
+#define B0000101 5
+#define B00000101 5
+#define B110 6
+#define B0110 6
+#define B00110 6
+#define B000110 6
+#define B0000110 6
+#define B00000110 6
+#define B111 7
+#define B0111 7
+#define B00111 7
+#define B000111 7
+#define B0000111 7
+#define B00000111 7
+#define B1000 8
+#define B01000 8
+#define B001000 8
+#define B0001000 8
+#define B00001000 8
+#define B1001 9
+#define B01001 9
+#define B001001 9
+#define B0001001 9
+#define B00001001 9
+#define B1010 10
+#define B01010 10
+#define B001010 10
+#define B0001010 10
+#define B00001010 10
+#define B1011 11
+#define B01011 11
+#define B001011 11
+#define B0001011 11
+#define B00001011 11
+#define B1100 12
+#define B01100 12
+#define B001100 12
+#define B0001100 12
+#define B00001100 12
+#define B1101 13
+#define B01101 13
+#define B001101 13
+#define B0001101 13
+#define B00001101 13
+#define B1110 14
+#define B01110 14
+#define B001110 14
+#define B0001110 14
+#define B00001110 14
+#define B1111 15
+#define B01111 15
+#define B001111 15
+#define B0001111 15
+#define B00001111 15
+#define B10000 16
+#define B010000 16
+#define B0010000 16
+#define B00010000 16
+#define B10001 17
+#define B010001 17
+#define B0010001 17
+#define B00010001 17
+#define B10010 18
+#define B010010 18
+#define B0010010 18
+#define B00010010 18
+#define B10011 19
+#define B010011 19
+#define B0010011 19
+#define B00010011 19
+#define B10100 20
+#define B010100 20
+#define B0010100 20
+#define B00010100 20
+#define B10101 21
+#define B010101 21
+#define B0010101 21
+#define B00010101 21
+#define B10110 22
+#define B010110 22
+#define B0010110 22
+#define B00010110 22
+#define B10111 23
+#define B010111 23
+#define B0010111 23
+#define B00010111 23
+#define B11000 24
+#define B011000 24
+#define B0011000 24
+#define B00011000 24
+#define B11001 25
+#define B011001 25
+#define B0011001 25
+#define B00011001 25
+#define B11010 26
+#define B011010 26
+#define B0011010 26
+#define B00011010 26
+#define B11011 27
+#define B011011 27
+#define B0011011 27
+#define B00011011 27
+#define B11100 28
+#define B011100 28
+#define B0011100 28
+#define B00011100 28
+#define B11101 29
+#define B011101 29
+#define B0011101 29
+#define B00011101 29
+#define B11110 30
+#define B011110 30
+#define B0011110 30
+#define B00011110 30
+#define B11111 31
+#define B011111 31
+#define B0011111 31
+#define B00011111 31
+#define B100000 32
+#define B0100000 32
+#define B00100000 32
+#define B100001 33
+#define B0100001 33
+#define B00100001 33
+#define B100010 34
+#define B0100010 34
+#define B00100010 34
+#define B100011 35
+#define B0100011 35
+#define B00100011 35
+#define B100100 36
+#define B0100100 36
+#define B00100100 36
+#define B100101 37
+#define B0100101 37
+#define B00100101 37
+#define B100110 38
+#define B0100110 38
+#define B00100110 38
+#define B100111 39
+#define B0100111 39
+#define B00100111 39
+#define B101000 40
+#define B0101000 40
+#define B00101000 40
+#define B101001 41
+#define B0101001 41
+#define B00101001 41
+#define B101010 42
+#define B0101010 42
+#define B00101010 42
+#define B101011 43
+#define B0101011 43
+#define B00101011 43
+#define B101100 44
+#define B0101100 44
+#define B00101100 44
+#define B101101 45
+#define B0101101 45
+#define B00101101 45
+#define B101110 46
+#define B0101110 46
+#define B00101110 46
+#define B101111 47
+#define B0101111 47
+#define B00101111 47
+#define B110000 48
+#define B0110000 48
+#define B00110000 48
+#define B110001 49
+#define B0110001 49
+#define B00110001 49
+#define B110010 50
+#define B0110010 50
+#define B00110010 50
+#define B110011 51
+#define B0110011 51
+#define B00110011 51
+#define B110100 52
+#define B0110100 52
+#define B00110100 52
+#define B110101 53
+#define B0110101 53
+#define B00110101 53
+#define B110110 54
+#define B0110110 54
+#define B00110110 54
+#define B110111 55
+#define B0110111 55
+#define B00110111 55
+#define B111000 56
+#define B0111000 56
+#define B00111000 56
+#define B111001 57
+#define B0111001 57
+#define B00111001 57
+#define B111010 58
+#define B0111010 58
+#define B00111010 58
+#define B111011 59
+#define B0111011 59
+#define B00111011 59
+#define B111100 60
+#define B0111100 60
+#define B00111100 60
+#define B111101 61
+#define B0111101 61
+#define B00111101 61
+#define B111110 62
+#define B0111110 62
+#define B00111110 62
+#define B111111 63
+#define B0111111 63
+#define B00111111 63
+#define B1000000 64
+#define B01000000 64
+#define B1000001 65
+#define B01000001 65
+#define B1000010 66
+#define B01000010 66
+#define B1000011 67
+#define B01000011 67
+#define B1000100 68
+#define B01000100 68
+#define B1000101 69
+#define B01000101 69
+#define B1000110 70
+#define B01000110 70
+#define B1000111 71
+#define B01000111 71
+#define B1001000 72
+#define B01001000 72
+#define B1001001 73
+#define B01001001 73
+#define B1001010 74
+#define B01001010 74
+#define B1001011 75
+#define B01001011 75
+#define B1001100 76
+#define B01001100 76
+#define B1001101 77
+#define B01001101 77
+#define B1001110 78
+#define B01001110 78
+#define B1001111 79
+#define B01001111 79
+#define B1010000 80
+#define B01010000 80
+#define B1010001 81
+#define B01010001 81
+#define B1010010 82
+#define B01010010 82
+#define B1010011 83
+#define B01010011 83
+#define B1010100 84
+#define B01010100 84
+#define B1010101 85
+#define B01010101 85
+#define B1010110 86
+#define B01010110 86
+#define B1010111 87
+#define B01010111 87
+#define B1011000 88
+#define B01011000 88
+#define B1011001 89
+#define B01011001 89
+#define B1011010 90
+#define B01011010 90
+#define B1011011 91
+#define B01011011 91
+#define B1011100 92
+#define B01011100 92
+#define B1011101 93
+#define B01011101 93
+#define B1011110 94
+#define B01011110 94
+#define B1011111 95
+#define B01011111 95
+#define B1100000 96
+#define B01100000 96
+#define B1100001 97
+#define B01100001 97
+#define B1100010 98
+#define B01100010 98
+#define B1100011 99
+#define B01100011 99
+#define B1100100 100
+#define B01100100 100
+#define B1100101 101
+#define B01100101 101
+#define B1100110 102
+#define B01100110 102
+#define B1100111 103
+#define B01100111 103
+#define B1101000 104
+#define B01101000 104
+#define B1101001 105
+#define B01101001 105
+#define B1101010 106
+#define B01101010 106
+#define B1101011 107
+#define B01101011 107
+#define B1101100 108
+#define B01101100 108
+#define B1101101 109
+#define B01101101 109
+#define B1101110 110
+#define B01101110 110
+#define B1101111 111
+#define B01101111 111
+#define B1110000 112
+#define B01110000 112
+#define B1110001 113
+#define B01110001 113
+#define B1110010 114
+#define B01110010 114
+#define B1110011 115
+#define B01110011 115
+#define B1110100 116
+#define B01110100 116
+#define B1110101 117
+#define B01110101 117
+#define B1110110 118
+#define B01110110 118
+#define B1110111 119
+#define B01110111 119
+#define B1111000 120
+#define B01111000 120
+#define B1111001 121
+#define B01111001 121
+#define B1111010 122
+#define B01111010 122
+#define B1111011 123
+#define B01111011 123
+#define B1111100 124
+#define B01111100 124
+#define B1111101 125
+#define B01111101 125
+#define B1111110 126
+#define B01111110 126
+#define B1111111 127
+#define B01111111 127
+#define B10000000 128
+#define B10000001 129
+#define B10000010 130
+#define B10000011 131
+#define B10000100 132
+#define B10000101 133
+#define B10000110 134
+#define B10000111 135
+#define B10001000 136
+#define B10001001 137
+#define B10001010 138
+#define B10001011 139
+#define B10001100 140
+#define B10001101 141
+#define B10001110 142
+#define B10001111 143
+#define B10010000 144
+#define B10010001 145
+#define B10010010 146
+#define B10010011 147
+#define B10010100 148
+#define B10010101 149
+#define B10010110 150
+#define B10010111 151
+#define B10011000 152
+#define B10011001 153
+#define B10011010 154
+#define B10011011 155
+#define B10011100 156
+#define B10011101 157
+#define B10011110 158
+#define B10011111 159
+#define B10100000 160
+#define B10100001 161
+#define B10100010 162
+#define B10100011 163
+#define B10100100 164
+#define B10100101 165
+#define B10100110 166
+#define B10100111 167
+#define B10101000 168
+#define B10101001 169
+#define B10101010 170
+#define B10101011 171
+#define B10101100 172
+#define B10101101 173
+#define B10101110 174
+#define B10101111 175
+#define B10110000 176
+#define B10110001 177
+#define B10110010 178
+#define B10110011 179
+#define B10110100 180
+#define B10110101 181
+#define B10110110 182
+#define B10110111 183
+#define B10111000 184
+#define B10111001 185
+#define B10111010 186
+#define B10111011 187
+#define B10111100 188
+#define B10111101 189
+#define B10111110 190
+#define B10111111 191
+#define B11000000 192
+#define B11000001 193
+#define B11000010 194
+#define B11000011 195
+#define B11000100 196
+#define B11000101 197
+#define B11000110 198
+#define B11000111 199
+#define B11001000 200
+#define B11001001 201
+#define B11001010 202
+#define B11001011 203
+#define B11001100 204
+#define B11001101 205
+#define B11001110 206
+#define B11001111 207
+#define B11010000 208
+#define B11010001 209
+#define B11010010 210
+#define B11010011 211
+#define B11010100 212
+#define B11010101 213
+#define B11010110 214
+#define B11010111 215
+#define B11011000 216
+#define B11011001 217
+#define B11011010 218
+#define B11011011 219
+#define B11011100 220
+#define B11011101 221
+#define B11011110 222
+#define B11011111 223
+#define B11100000 224
+#define B11100001 225
+#define B11100010 226
+#define B11100011 227
+#define B11100100 228
+#define B11100101 229
+#define B11100110 230
+#define B11100111 231
+#define B11101000 232
+#define B11101001 233
+#define B11101010 234
+#define B11101011 235
+#define B11101100 236
+#define B11101101 237
+#define B11101110 238
+#define B11101111 239
+#define B11110000 240
+#define B11110001 241
+#define B11110010 242
+#define B11110011 243
+#define B11110100 244
+#define B11110101 245
+#define B11110110 246
+#define B11110111 247
+#define B11111000 248
+#define B11111001 249
+#define B11111010 250
+#define B11111011 251
+#define B11111100 252
+#define B11111101 253
+#define B11111110 254
+#define B11111111 255
+
+#endif
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/main.cpp b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/main.cpp
new file mode 100644
index 000000000..3d4e079d2
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/main.cpp
@@ -0,0 +1,20 @@
+#include <Arduino.h>
+
+int main(void)
+{
+ init();
+
+#if defined(USBCON)
+ USBDevice.attach();
+#endif
+
+ setup();
+
+ for (;;) {
+ loop();
+ if (serialEventRun) serialEventRun();
+ }
+
+ return 0;
+}
+
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/new.cpp b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/new.cpp
new file mode 100644
index 000000000..0f6d4220e
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/new.cpp
@@ -0,0 +1,18 @@
+#include <new.h>
+
+void * operator new(size_t size)
+{
+ return malloc(size);
+}
+
+void operator delete(void * ptr)
+{
+ free(ptr);
+}
+
+int __cxa_guard_acquire(__guard *g) {return !*(char *)(g);};
+void __cxa_guard_release (__guard *g) {*(char *)g = 1;};
+void __cxa_guard_abort (__guard *) {};
+
+void __cxa_pure_virtual(void) {};
+
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/new.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/new.h
new file mode 100644
index 000000000..cd940ce8b
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/new.h
@@ -0,0 +1,22 @@
+/* Header to define new/delete operators as they aren't provided by avr-gcc by default
+ Taken from http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=59453
+ */
+
+#ifndef NEW_H
+#define NEW_H
+
+#include <stdlib.h>
+
+void * operator new(size_t size);
+void operator delete(void * ptr);
+
+__extension__ typedef int __guard __attribute__((mode (__DI__)));
+
+extern "C" int __cxa_guard_acquire(__guard *);
+extern "C" void __cxa_guard_release (__guard *);
+extern "C" void __cxa_guard_abort (__guard *);
+
+extern "C" void __cxa_pure_virtual(void);
+
+#endif
+
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring.c b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring.c
new file mode 100644
index 000000000..ac8bb6f9b
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring.c
@@ -0,0 +1,324 @@
+/*
+ wiring.c - Partial implementation of the Wiring API for the ATmega8.
+ Part of Arduino - http://www.arduino.cc/
+
+ Copyright (c) 2005-2006 David A. Mellis
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ Boston, MA 02111-1307 USA
+
+ $Id$
+*/
+
+#include "wiring_private.h"
+
+// the prescaler is set so that timer0 ticks every 64 clock cycles, and the
+// the overflow handler is called every 256 ticks.
+#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))
+
+// the whole number of milliseconds per timer0 overflow
+#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000)
+
+// the fractional number of milliseconds per timer0 overflow. we shift right
+// by three to fit these numbers into a byte. (for the clock speeds we care
+// about - 8 and 16 MHz - this doesn't lose precision.)
+#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3)
+#define FRACT_MAX (1000 >> 3)
+
+volatile unsigned long timer0_overflow_count = 0;
+volatile unsigned long timer0_millis = 0;
+static unsigned char timer0_fract = 0;
+
+#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
+SIGNAL(TIM0_OVF_vect)
+#else
+SIGNAL(TIMER0_OVF_vect)
+#endif
+{
+ // copy these to local variables so they can be stored in registers
+ // (volatile variables must be read from memory on every access)
+ unsigned long m = timer0_millis;
+ unsigned char f = timer0_fract;
+
+ m += MILLIS_INC;
+ f += FRACT_INC;
+ if (f >= FRACT_MAX) {
+ f -= FRACT_MAX;
+ m += 1;
+ }
+
+ timer0_fract = f;
+ timer0_millis = m;
+ timer0_overflow_count++;
+}
+
+unsigned long millis()
+{
+ unsigned long m;
+ uint8_t oldSREG = SREG;
+
+ // disable interrupts while we read timer0_millis or we might get an
+ // inconsistent value (e.g. in the middle of a write to timer0_millis)
+ cli();
+ m = timer0_millis;
+ SREG = oldSREG;
+
+ return m;
+}
+
+unsigned long micros() {
+ unsigned long m;
+ uint8_t oldSREG = SREG, t;
+
+ cli();
+ m = timer0_overflow_count;
+#if defined(TCNT0)
+ t = TCNT0;
+#elif defined(TCNT0L)
+ t = TCNT0L;
+#else
+ #error TIMER 0 not defined
+#endif
+
+
+#ifdef TIFR0
+ if ((TIFR0 & _BV(TOV0)) && (t < 255))
+ m++;
+#else
+ if ((TIFR & _BV(TOV0)) && (t < 255))
+ m++;
+#endif
+
+ SREG = oldSREG;
+
+ return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
+}
+
+void delay(unsigned long ms)
+{
+ uint16_t start = (uint16_t)micros();
+
+ while (ms > 0) {
+ if (((uint16_t)micros() - start) >= 1000) {
+ ms--;
+ start += 1000;
+ }
+ }
+}
+
+/* Delay for the given number of microseconds. Assumes a 8 or 16 MHz clock. */
+void delayMicroseconds(unsigned int us)
+{
+ // calling avrlib's delay_us() function with low values (e.g. 1 or
+ // 2 microseconds) gives delays longer than desired.
+ //delay_us(us);
+#if F_CPU >= 20000000L
+ // for the 20 MHz clock on rare Arduino boards
+
+ // for a one-microsecond delay, simply wait 2 cycle and return. The overhead
+ // of the function call yields a delay of exactly a one microsecond.
+ __asm__ __volatile__ (
+ "nop" "\n\t"
+ "nop"); //just waiting 2 cycle
+ if (--us == 0)
+ return;
+
+ // the following loop takes a 1/5 of a microsecond (4 cycles)
+ // per iteration, so execute it five times for each microsecond of
+ // delay requested.
+ us = (us<<2) + us; // x5 us
+
+ // account for the time taken in the preceeding commands.
+ us -= 2;
+
+#elif F_CPU >= 16000000L
+ // for the 16 MHz clock on most Arduino boards
+
+ // for a one-microsecond delay, simply return. the overhead
+ // of the function call yields a delay of approximately 1 1/8 us.
+ if (--us == 0)
+ return;
+
+ // the following loop takes a quarter of a microsecond (4 cycles)
+ // per iteration, so execute it four times for each microsecond of
+ // delay requested.
+ us <<= 2;
+
+ // account for the time taken in the preceeding commands.
+ us -= 2;
+#else
+ // for the 8 MHz internal clock on the ATmega168
+
+ // for a one- or two-microsecond delay, simply return. the overhead of
+ // the function calls takes more than two microseconds. can't just
+ // subtract two, since us is unsigned; we'd overflow.
+ if (--us == 0)
+ return;
+ if (--us == 0)
+ return;
+
+ // the following loop takes half of a microsecond (4 cycles)
+ // per iteration, so execute it twice for each microsecond of
+ // delay requested.
+ us <<= 1;
+
+ // partially compensate for the time taken by the preceeding commands.
+ // we can't subtract any more than this or we'd overflow w/ small delays.
+ us--;
+#endif
+
+ // busy wait
+ __asm__ __volatile__ (
+ "1: sbiw %0,1" "\n\t" // 2 cycles
+ "brne 1b" : "=w" (us) : "0" (us) // 2 cycles
+ );
+}
+
+void init()
+{
+ // this needs to be called before setup() or some functions won't
+ // work there
+ sei();
+
+ // on the ATmega168, timer 0 is also used for fast hardware pwm
+ // (using phase-correct PWM would mean that timer 0 overflowed half as often
+ // resulting in different millis() behavior on the ATmega8 and ATmega168)
+#if defined(TCCR0A) && defined(WGM01)
+ sbi(TCCR0A, WGM01);
+ sbi(TCCR0A, WGM00);
+#endif
+
+ // set timer 0 prescale factor to 64
+#if defined(__AVR_ATmega128__)
+ // CPU specific: different values for the ATmega128
+ sbi(TCCR0, CS02);
+#elif defined(TCCR0) && defined(CS01) && defined(CS00)
+ // this combination is for the standard atmega8
+ sbi(TCCR0, CS01);
+ sbi(TCCR0, CS00);
+#elif defined(TCCR0B) && defined(CS01) && defined(CS00)
+ // this combination is for the standard 168/328/1280/2560
+ sbi(TCCR0B, CS01);
+ sbi(TCCR0B, CS00);
+#elif defined(TCCR0A) && defined(CS01) && defined(CS00)
+ // this combination is for the __AVR_ATmega645__ series
+ sbi(TCCR0A, CS01);
+ sbi(TCCR0A, CS00);
+#else
+ #error Timer 0 prescale factor 64 not set correctly
+#endif
+
+ // enable timer 0 overflow interrupt
+#if defined(TIMSK) && defined(TOIE0)
+ sbi(TIMSK, TOIE0);
+#elif defined(TIMSK0) && defined(TOIE0)
+ sbi(TIMSK0, TOIE0);
+#else
+ #error Timer 0 overflow interrupt not set correctly
+#endif
+
+ // timers 1 and 2 are used for phase-correct hardware pwm
+ // this is better for motors as it ensures an even waveform
+ // note, however, that fast pwm mode can achieve a frequency of up
+ // 8 MHz (with a 16 MHz clock) at 50% duty cycle
+
+#if defined(TCCR1B) && defined(CS11) && defined(CS10)
+ TCCR1B = 0;
+
+ // set timer 1 prescale factor to 64
+ sbi(TCCR1B, CS11);
+#if F_CPU >= 8000000L
+ sbi(TCCR1B, CS10);
+#endif
+#elif defined(TCCR1) && defined(CS11) && defined(CS10)
+ sbi(TCCR1, CS11);
+#if F_CPU >= 8000000L
+ sbi(TCCR1, CS10);
+#endif
+#endif
+ // put timer 1 in 8-bit phase correct pwm mode
+#if defined(TCCR1A) && defined(WGM10)
+ sbi(TCCR1A, WGM10);
+#elif defined(TCCR1)
+ #warning this needs to be finished
+#endif
+
+ // set timer 2 prescale factor to 64
+#if defined(TCCR2) && defined(CS22)
+ sbi(TCCR2, CS22);
+#elif defined(TCCR2B) && defined(CS22)
+ sbi(TCCR2B, CS22);
+#else
+ #warning Timer 2 not finished (may not be present on this CPU)
+#endif
+
+ // configure timer 2 for phase correct pwm (8-bit)
+#if defined(TCCR2) && defined(WGM20)
+ sbi(TCCR2, WGM20);
+#elif defined(TCCR2A) && defined(WGM20)
+ sbi(TCCR2A, WGM20);
+#else
+ #warning Timer 2 not finished (may not be present on this CPU)
+#endif
+
+#if defined(TCCR3B) && defined(CS31) && defined(WGM30)
+ sbi(TCCR3B, CS31); // set timer 3 prescale factor to 64
+ sbi(TCCR3B, CS30);
+ sbi(TCCR3A, WGM30); // put timer 3 in 8-bit phase correct pwm mode
+#endif
+
+#if defined(TCCR4A) && defined(TCCR4B) && defined(TCCR4D) /* beginning of timer4 block for 32U4 and similar */
+ sbi(TCCR4B, CS42); // set timer4 prescale factor to 64
+ sbi(TCCR4B, CS41);
+ sbi(TCCR4B, CS40);
+ sbi(TCCR4D, WGM40); // put timer 4 in phase- and frequency-correct PWM mode
+ sbi(TCCR4A, PWM4A); // enable PWM mode for comparator OCR4A
+ sbi(TCCR4C, PWM4D); // enable PWM mode for comparator OCR4D
+#else /* beginning of timer4 block for ATMEGA1280 and ATMEGA2560 */
+#if defined(TCCR4B) && defined(CS41) && defined(WGM40)
+ sbi(TCCR4B, CS41); // set timer 4 prescale factor to 64
+ sbi(TCCR4B, CS40);
+ sbi(TCCR4A, WGM40); // put timer 4 in 8-bit phase correct pwm mode
+#endif
+#endif /* end timer4 block for ATMEGA1280/2560 and similar */
+
+#if defined(TCCR5B) && defined(CS51) && defined(WGM50)
+ sbi(TCCR5B, CS51); // set timer 5 prescale factor to 64
+ sbi(TCCR5B, CS50);
+ sbi(TCCR5A, WGM50); // put timer 5 in 8-bit phase correct pwm mode
+#endif
+
+#if defined(ADCSRA)
+ // set a2d prescale factor to 128
+ // 16 MHz / 128 = 125 KHz, inside the desired 50-200 KHz range.
+ // XXX: this will not work properly for other clock speeds, and
+ // this code should use F_CPU to determine the prescale factor.
+ sbi(ADCSRA, ADPS2);
+ sbi(ADCSRA, ADPS1);
+ sbi(ADCSRA, ADPS0);
+
+ // enable a2d conversions
+ sbi(ADCSRA, ADEN);
+#endif
+
+ // the bootloader connects pins 0 and 1 to the USART; disconnect them
+ // here so they can be used as normal digital i/o; they will be
+ // reconnected in Serial.begin()
+#if defined(UCSRB)
+ UCSRB = 0;
+#elif defined(UCSR0B)
+ UCSR0B = 0;
+#endif
+}
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_analog.c b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_analog.c
new file mode 100644
index 000000000..0e9881f6a
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_analog.c
@@ -0,0 +1,282 @@
+/*
+ wiring_analog.c - analog input and output
+ Part of Arduino - http://www.arduino.cc/
+
+ Copyright (c) 2005-2006 David A. Mellis
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ Boston, MA 02111-1307 USA
+
+ Modified 28 September 2010 by Mark Sproul
+
+ $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
+*/
+
+#include "wiring_private.h"
+#include "pins_arduino.h"
+
+uint8_t analog_reference = DEFAULT;
+
+void analogReference(uint8_t mode)
+{
+ // can't actually set the register here because the default setting
+ // will connect AVCC and the AREF pin, which would cause a short if
+ // there's something connected to AREF.
+ analog_reference = mode;
+}
+
+int analogRead(uint8_t pin)
+{
+ uint8_t low, high;
+
+#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
+ if (pin >= 54) pin -= 54; // allow for channel or pin numbers
+#elif defined(__AVR_ATmega32U4__)
+ if (pin >= 18) pin -= 18; // allow for channel or pin numbers
+#elif defined(__AVR_ATmega1284__)
+ if (pin >= 24) pin -= 24; // allow for channel or pin numbers
+#else
+ if (pin >= 14) pin -= 14; // allow for channel or pin numbers
+#endif
+
+#if defined(__AVR_ATmega32U4__)
+ pin = analogPinToChannel(pin);
+ ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5);
+#elif defined(ADCSRB) && defined(MUX5)
+ // the MUX5 bit of ADCSRB selects whether we're reading from channels
+ // 0 to 7 (MUX5 low) or 8 to 15 (MUX5 high).
+ ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5);
+#endif
+
+ // set the analog reference (high two bits of ADMUX) and select the
+ // channel (low 4 bits). this also sets ADLAR (left-adjust result)
+ // to 0 (the default).
+#if defined(ADMUX)
+ ADMUX = (analog_reference << 6) | (pin & 0x07);
+#endif
+
+ // without a delay, we seem to read from the wrong channel
+ //delay(1);
+
+#if defined(ADCSRA) && defined(ADCL)
+ // start the conversion
+ sbi(ADCSRA, ADSC);
+
+ // ADSC is cleared when the conversion finishes
+ while (bit_is_set(ADCSRA, ADSC));
+
+ // we have to read ADCL first; doing so locks both ADCL
+ // and ADCH until ADCH is read. reading ADCL second would
+ // cause the results of each conversion to be discarded,
+ // as ADCL and ADCH would be locked when it completed.
+ low = ADCL;
+ high = ADCH;
+#else
+ // we dont have an ADC, return 0
+ low = 0;
+ high = 0;
+#endif
+
+ // combine the two bytes
+ return (high << 8) | low;
+}
+
+// Right now, PWM output only works on the pins with
+// hardware support. These are defined in the appropriate
+// pins_*.c file. For the rest of the pins, we default
+// to digital output.
+void analogWrite(uint8_t pin, int val)
+{
+ // We need to make sure the PWM output is enabled for those pins
+ // that support it, as we turn it off when digitally reading or
+ // writing with them. Also, make sure the pin is in output mode
+ // for consistenty with Wiring, which doesn't require a pinMode
+ // call for the analog output pins.
+ pinMode(pin, OUTPUT);
+ if (val == 0)
+ {
+ digitalWrite(pin, LOW);
+ }
+ else if (val == 255)
+ {
+ digitalWrite(pin, HIGH);
+ }
+ else
+ {
+ switch(digitalPinToTimer(pin))
+ {
+ // XXX fix needed for atmega8
+ #if defined(TCCR0) && defined(COM00) && !defined(__AVR_ATmega8__)
+ case TIMER0A:
+ // connect pwm to pin on timer 0
+ sbi(TCCR0, COM00);
+ OCR0 = val; // set pwm duty
+ break;
+ #endif
+
+ #if defined(TCCR0A) && defined(COM0A1)
+ case TIMER0A:
+ // connect pwm to pin on timer 0, channel A
+ sbi(TCCR0A, COM0A1);
+ OCR0A = val; // set pwm duty
+ break;
+ #endif
+
+ #if defined(TCCR0A) && defined(COM0B1)
+ case TIMER0B:
+ // connect pwm to pin on timer 0, channel B
+ sbi(TCCR0A, COM0B1);
+ OCR0B = val; // set pwm duty
+ break;
+ #endif
+
+ #if defined(TCCR1A) && defined(COM1A1)
+ case TIMER1A:
+ // connect pwm to pin on timer 1, channel A
+ sbi(TCCR1A, COM1A1);
+ OCR1A = val; // set pwm duty
+ break;
+ #endif
+
+ #if defined(TCCR1A) && defined(COM1B1)
+ case TIMER1B:
+ // connect pwm to pin on timer 1, channel B
+ sbi(TCCR1A, COM1B1);
+ OCR1B = val; // set pwm duty
+ break;
+ #endif
+
+ #if defined(TCCR2) && defined(COM21)
+ case TIMER2:
+ // connect pwm to pin on timer 2
+ sbi(TCCR2, COM21);
+ OCR2 = val; // set pwm duty
+ break;
+ #endif
+
+ #if defined(TCCR2A) && defined(COM2A1)
+ case TIMER2A:
+ // connect pwm to pin on timer 2, channel A
+ sbi(TCCR2A, COM2A1);
+ OCR2A = val; // set pwm duty
+ break;
+ #endif
+
+ #if defined(TCCR2A) && defined(COM2B1)
+ case TIMER2B:
+ // connect pwm to pin on timer 2, channel B
+ sbi(TCCR2A, COM2B1);
+ OCR2B = val; // set pwm duty
+ break;
+ #endif
+
+ #if defined(TCCR3A) && defined(COM3A1)
+ case TIMER3A:
+ // connect pwm to pin on timer 3, channel A
+ sbi(TCCR3A, COM3A1);
+ OCR3A = val; // set pwm duty
+ break;
+ #endif
+
+ #if defined(TCCR3A) && defined(COM3B1)
+ case TIMER3B:
+ // connect pwm to pin on timer 3, channel B
+ sbi(TCCR3A, COM3B1);
+ OCR3B = val; // set pwm duty
+ break;
+ #endif
+
+ #if defined(TCCR3A) && defined(COM3C1)
+ case TIMER3C:
+ // connect pwm to pin on timer 3, channel C
+ sbi(TCCR3A, COM3C1);
+ OCR3C = val; // set pwm duty
+ break;
+ #endif
+
+ #if defined(TCCR4A)
+ case TIMER4A:
+ //connect pwm to pin on timer 4, channel A
+ sbi(TCCR4A, COM4A1);
+ #if defined(COM4A0) // only used on 32U4
+ cbi(TCCR4A, COM4A0);
+ #endif
+ OCR4A = val; // set pwm duty
+ break;
+ #endif
+
+ #if defined(TCCR4A) && defined(COM4B1)
+ case TIMER4B:
+ // connect pwm to pin on timer 4, channel B
+ sbi(TCCR4A, COM4B1);
+ OCR4B = val; // set pwm duty
+ break;
+ #endif
+
+ #if defined(TCCR4A) && defined(COM4C1)
+ case TIMER4C:
+ // connect pwm to pin on timer 4, channel C
+ sbi(TCCR4A, COM4C1);
+ OCR4C = val; // set pwm duty
+ break;
+ #endif
+
+ #if defined(TCCR4C) && defined(COM4D1)
+ case TIMER4D:
+ // connect pwm to pin on timer 4, channel D
+ sbi(TCCR4C, COM4D1);
+ #if defined(COM4D0) // only used on 32U4
+ cbi(TCCR4C, COM4D0);
+ #endif
+ OCR4D = val; // set pwm duty
+ break;
+ #endif
+
+
+ #if defined(TCCR5A) && defined(COM5A1)
+ case TIMER5A:
+ // connect pwm to pin on timer 5, channel A
+ sbi(TCCR5A, COM5A1);
+ OCR5A = val; // set pwm duty
+ break;
+ #endif
+
+ #if defined(TCCR5A) && defined(COM5B1)
+ case TIMER5B:
+ // connect pwm to pin on timer 5, channel B
+ sbi(TCCR5A, COM5B1);
+ OCR5B = val; // set pwm duty
+ break;
+ #endif
+
+ #if defined(TCCR5A) && defined(COM5C1)
+ case TIMER5C:
+ // connect pwm to pin on timer 5, channel C
+ sbi(TCCR5A, COM5C1);
+ OCR5C = val; // set pwm duty
+ break;
+ #endif
+
+ case NOT_ON_TIMER:
+ default:
+ if (val < 128) {
+ digitalWrite(pin, LOW);
+ } else {
+ digitalWrite(pin, HIGH);
+ }
+ }
+ }
+}
+
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_digital.c b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_digital.c
new file mode 100644
index 000000000..be323b1df
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_digital.c
@@ -0,0 +1,178 @@
+/*
+ wiring_digital.c - digital input and output functions
+ Part of Arduino - http://www.arduino.cc/
+
+ Copyright (c) 2005-2006 David A. Mellis
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ Boston, MA 02111-1307 USA
+
+ Modified 28 September 2010 by Mark Sproul
+
+ $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
+*/
+
+#define ARDUINO_MAIN
+#include "wiring_private.h"
+#include "pins_arduino.h"
+
+void pinMode(uint8_t pin, uint8_t mode)
+{
+ uint8_t bit = digitalPinToBitMask(pin);
+ uint8_t port = digitalPinToPort(pin);
+ volatile uint8_t *reg, *out;
+
+ if (port == NOT_A_PIN) return;
+
+ // JWS: can I let the optimizer do this?
+ reg = portModeRegister(port);
+ out = portOutputRegister(port);
+
+ if (mode == INPUT) {
+ uint8_t oldSREG = SREG;
+ cli();
+ *reg &= ~bit;
+ *out &= ~bit;
+ SREG = oldSREG;
+ } else if (mode == INPUT_PULLUP) {
+ uint8_t oldSREG = SREG;
+ cli();
+ *reg &= ~bit;
+ *out |= bit;
+ SREG = oldSREG;
+ } else {
+ uint8_t oldSREG = SREG;
+ cli();
+ *reg |= bit;
+ SREG = oldSREG;
+ }
+}
+
+// Forcing this inline keeps the callers from having to push their own stuff
+// on the stack. It is a good performance win and only takes 1 more byte per
+// user than calling. (It will take more bytes on the 168.)
+//
+// But shouldn't this be moved into pinMode? Seems silly to check and do on
+// each digitalread or write.
+//
+// Mark Sproul:
+// - Removed inline. Save 170 bytes on atmega1280
+// - changed to a switch statment; added 32 bytes but much easier to read and maintain.
+// - Added more #ifdefs, now compiles for atmega645
+//
+//static inline void turnOffPWM(uint8_t timer) __attribute__ ((always_inline));
+//static inline void turnOffPWM(uint8_t timer)
+static void turnOffPWM(uint8_t timer)
+{
+ switch (timer)
+ {
+ #if defined(TCCR1A) && defined(COM1A1)
+ case TIMER1A: cbi(TCCR1A, COM1A1); break;
+ #endif
+ #if defined(TCCR1A) && defined(COM1B1)
+ case TIMER1B: cbi(TCCR1A, COM1B1); break;
+ #endif
+
+ #if defined(TCCR2) && defined(COM21)
+ case TIMER2: cbi(TCCR2, COM21); break;
+ #endif
+
+ #if defined(TCCR0A) && defined(COM0A1)
+ case TIMER0A: cbi(TCCR0A, COM0A1); break;
+ #endif
+
+ #if defined(TIMER0B) && defined(COM0B1)
+ case TIMER0B: cbi(TCCR0A, COM0B1); break;
+ #endif
+ #if defined(TCCR2A) && defined(COM2A1)
+ case TIMER2A: cbi(TCCR2A, COM2A1); break;
+ #endif
+ #if defined(TCCR2A) && defined(COM2B1)
+ case TIMER2B: cbi(TCCR2A, COM2B1); break;
+ #endif
+
+ #if defined(TCCR3A) && defined(COM3A1)
+ case TIMER3A: cbi(TCCR3A, COM3A1); break;
+ #endif
+ #if defined(TCCR3A) && defined(COM3B1)
+ case TIMER3B: cbi(TCCR3A, COM3B1); break;
+ #endif
+ #if defined(TCCR3A) && defined(COM3C1)
+ case TIMER3C: cbi(TCCR3A, COM3C1); break;
+ #endif
+
+ #if defined(TCCR4A) && defined(COM4A1)
+ case TIMER4A: cbi(TCCR4A, COM4A1); break;
+ #endif
+ #if defined(TCCR4A) && defined(COM4B1)
+ case TIMER4B: cbi(TCCR4A, COM4B1); break;
+ #endif
+ #if defined(TCCR4A) && defined(COM4C1)
+ case TIMER4C: cbi(TCCR4A, COM4C1); break;
+ #endif
+ #if defined(TCCR4C) && defined(COM4D1)
+ case TIMER4D: cbi(TCCR4C, COM4D1); break;
+ #endif
+
+ #if defined(TCCR5A)
+ case TIMER5A: cbi(TCCR5A, COM5A1); break;
+ case TIMER5B: cbi(TCCR5A, COM5B1); break;
+ case TIMER5C: cbi(TCCR5A, COM5C1); break;
+ #endif
+ }
+}
+
+void digitalWrite(uint8_t pin, uint8_t val)
+{
+ uint8_t timer = digitalPinToTimer(pin);
+ uint8_t bit = digitalPinToBitMask(pin);
+ uint8_t port = digitalPinToPort(pin);
+ volatile uint8_t *out;
+
+ if (port == NOT_A_PIN) return;
+
+ // If the pin that support PWM output, we need to turn it off
+ // before doing a digital write.
+ if (timer != NOT_ON_TIMER) turnOffPWM(timer);
+
+ out = portOutputRegister(port);
+
+ uint8_t oldSREG = SREG;
+ cli();
+
+ if (val == LOW) {
+ *out &= ~bit;
+ } else {
+ *out |= bit;
+ }
+
+ SREG = oldSREG;
+}
+
+int digitalRead(uint8_t pin)
+{
+ uint8_t timer = digitalPinToTimer(pin);
+ uint8_t bit = digitalPinToBitMask(pin);
+ uint8_t port = digitalPinToPort(pin);
+
+ if (port == NOT_A_PIN) return LOW;
+
+ // If the pin that support PWM output, we need to turn it off
+ // before getting a digital reading.
+ if (timer != NOT_ON_TIMER) turnOffPWM(timer);
+
+ if (*portInputRegister(port) & bit) return HIGH;
+ return LOW;
+}
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_private.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_private.h
new file mode 100644
index 000000000..f0ceb0cc4
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_private.h
@@ -0,0 +1,69 @@
+/*
+ wiring_private.h - Internal header file.
+ Part of Arduino - http://www.arduino.cc/
+
+ Copyright (c) 2005-2006 David A. Mellis
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ Boston, MA 02111-1307 USA
+
+ $Id: wiring.h 239 2007-01-12 17:58:39Z mellis $
+*/
+
+#ifndef WiringPrivate_h
+#define WiringPrivate_h
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "Arduino.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+#ifndef cbi
+#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
+#endif
+#ifndef sbi
+#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
+#endif
+
+#define EXTERNAL_INT_0 0
+#define EXTERNAL_INT_1 1
+#define EXTERNAL_INT_2 2
+#define EXTERNAL_INT_3 3
+#define EXTERNAL_INT_4 4
+#define EXTERNAL_INT_5 5
+#define EXTERNAL_INT_6 6
+#define EXTERNAL_INT_7 7
+
+#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
+#define EXTERNAL_NUM_INTERRUPTS 8
+#elif defined(__AVR_ATmega1284P__)
+#define EXTERNAL_NUM_INTERRUPTS 3
+#else
+#define EXTERNAL_NUM_INTERRUPTS 2
+#endif
+
+typedef void (*voidFuncPtr)(void);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_pulse.c b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_pulse.c
new file mode 100644
index 000000000..0d968865d
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_pulse.c
@@ -0,0 +1,69 @@
+/*
+ wiring_pulse.c - pulseIn() function
+ Part of Arduino - http://www.arduino.cc/
+
+ Copyright (c) 2005-2006 David A. Mellis
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ Boston, MA 02111-1307 USA
+
+ $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
+*/
+
+#include "wiring_private.h"
+#include "pins_arduino.h"
+
+/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH
+ * or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds
+ * to 3 minutes in length, but must be called at least a few dozen microseconds
+ * before the start of the pulse. */
+unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout)
+{
+ // cache the port and bit of the pin in order to speed up the
+ // pulse width measuring loop and achieve finer resolution. calling
+ // digitalRead() instead yields much coarser resolution.
+ uint8_t bit = digitalPinToBitMask(pin);
+ uint8_t port = digitalPinToPort(pin);
+ uint8_t stateMask = (state ? bit : 0);
+ unsigned long width = 0; // keep initialization out of time critical area
+
+ // convert the timeout from microseconds to a number of times through
+ // the initial loop; it takes 16 clock cycles per iteration.
+ unsigned long numloops = 0;
+ unsigned long maxloops = microsecondsToClockCycles(timeout) / 16;
+
+ // wait for any previous pulse to end
+ while ((*portInputRegister(port) & bit) == stateMask)
+ if (numloops++ == maxloops)
+ return 0;
+
+ // wait for the pulse to start
+ while ((*portInputRegister(port) & bit) != stateMask)
+ if (numloops++ == maxloops)
+ return 0;
+
+ // wait for the pulse to stop
+ while ((*portInputRegister(port) & bit) == stateMask) {
+ if (numloops++ == maxloops)
+ return 0;
+ width++;
+ }
+
+ // convert the reading to microseconds. The loop has been determined
+ // to be 20 clock cycles long and have about 16 clocks between the edge
+ // and the start of the loop. There will be some error introduced by
+ // the interrupt handlers.
+ return clockCyclesToMicroseconds(width * 21 + 16);
+}
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_shift.c b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_shift.c
new file mode 100644
index 000000000..cfe786758
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_shift.c
@@ -0,0 +1,55 @@
+/*
+ wiring_shift.c - shiftOut() function
+ Part of Arduino - http://www.arduino.cc/
+
+ Copyright (c) 2005-2006 David A. Mellis
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ Boston, MA 02111-1307 USA
+
+ $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
+*/
+
+#include "wiring_private.h"
+
+uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) {
+ uint8_t value = 0;
+ uint8_t i;
+
+ for (i = 0; i < 8; ++i) {
+ digitalWrite(clockPin, HIGH);
+ if (bitOrder == LSBFIRST)
+ value |= digitalRead(dataPin) << i;
+ else
+ value |= digitalRead(dataPin) << (7 - i);
+ digitalWrite(clockPin, LOW);
+ }
+ return value;
+}
+
+void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val)
+{
+ uint8_t i;
+
+ for (i = 0; i < 8; i++) {
+ if (bitOrder == LSBFIRST)
+ digitalWrite(dataPin, !!(val & (1 << i)));
+ else
+ digitalWrite(dataPin, !!(val & (1 << (7 - i))));
+
+ digitalWrite(clockPin, HIGH);
+ digitalWrite(clockPin, LOW);
+ }
+}
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/variants/eightanaloginputs/pins_arduino.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/variants/eightanaloginputs/pins_arduino.h
new file mode 100644
index 000000000..52b37efc4
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/variants/eightanaloginputs/pins_arduino.h
@@ -0,0 +1,27 @@
+/*
+ pins_arduino.h - Pin definition functions for Arduino
+ Part of Arduino - http://www.arduino.cc/
+
+ Copyright (c) 2007 David A. Mellis
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ Boston, MA 02111-1307 USA
+
+ $Id: wiring.h 249 2007-02-03 16:52:51Z mellis $
+*/
+
+#include "../standard/pins_arduino.h"
+#undef NUM_ANALOG_INPUTS
+#define NUM_ANALOG_INPUTS 8
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/variants/leonardo/pins_arduino.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/variants/leonardo/pins_arduino.h
new file mode 100644
index 000000000..9f770d6ce
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/variants/leonardo/pins_arduino.h
@@ -0,0 +1,256 @@
+/*
+ pins_arduino.h - Pin definition functions for Arduino
+ Part of Arduino - http://www.arduino.cc/
+
+ Copyright (c) 2007 David A. Mellis
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ Boston, MA 02111-1307 USA
+
+ $Id: wiring.h 249 2007-02-03 16:52:51Z mellis $
+*/
+
+#ifndef Pins_Arduino_h
+#define Pins_Arduino_h
+
+#include <avr/pgmspace.h>
+
+#define TX_RX_LED_INIT DDRD |= (1<<5), DDRB |= (1<<0)
+#define TXLED0 PORTD |= (1<<5)
+#define TXLED1 PORTD &= ~(1<<5)
+#define RXLED0 PORTB |= (1<<0)
+#define RXLED1 PORTB &= ~(1<<0)
+
+static const uint8_t SDA = 2;
+static const uint8_t SCL = 3;
+
+// Map SPI port to 'new' pins D14..D17
+static const uint8_t SS = 17;
+static const uint8_t MOSI = 16;
+static const uint8_t MISO = 14;
+static const uint8_t SCK = 15;
+
+// Mapping of analog pins as digital I/O
+// A6-A11 share with digital pins
+static const uint8_t A0 = 18;
+static const uint8_t A1 = 19;
+static const uint8_t A2 = 20;
+static const uint8_t A3 = 21;
+static const uint8_t A4 = 22;
+static const uint8_t A5 = 23;
+static const uint8_t A6 = 24; // D4
+static const uint8_t A7 = 25; // D6
+static const uint8_t A8 = 26; // D8
+static const uint8_t A9 = 27; // D9
+static const uint8_t A10 = 28; // D10
+static const uint8_t A11 = 29; // D12
+
+#define digitalPinToPCICR(p) ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCICR) : ((uint8_t *)0))
+#define digitalPinToPCICRbit(p) 0
+#define digitalPinToPCMSK(p) ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCMSK0) : ((uint8_t *)0))
+#define digitalPinToPCMSKbit(p) ( ((p) >= 8 && (p) <= 11) ? (p) - 4 : ((p) == 14 ? 3 : ((p) == 15 ? 1 : ((p) == 16 ? 2 : ((p) == 17 ? 0 : (p - A8 + 4))))))
+
+// __AVR_ATmega32U4__ has an unusual mapping of pins to channels
+extern const uint8_t PROGMEM analog_pin_to_channel_PGM[];
+#define analogPinToChannel(P) ( pgm_read_byte( analog_pin_to_channel_PGM + (P) ) )
+
+#ifdef ARDUINO_MAIN
+
+// On the Arduino board, digital pins are also used
+// for the analog output (software PWM). Analog input
+// pins are a separate set.
+
+// ATMEL ATMEGA32U4 / ARDUINO LEONARDO
+//
+// D0 PD2 RXD1/INT2
+// D1 PD3 TXD1/INT3
+// D2 PD1 SDA SDA/INT1
+// D3# PD0 PWM8/SCL OC0B/SCL/INT0
+// D4 A6 PD4 ADC8
+// D5# PC6 ??? OC3A/#OC4A
+// D6# A7 PD7 FastPWM #OC4D/ADC10
+// D7 PE6 INT6/AIN0
+//
+// D8 A8 PB4 ADC11/PCINT4
+// D9# A9 PB5 PWM16 OC1A/#OC4B/ADC12/PCINT5
+// D10# A10 PB6 PWM16 OC1B/0c4B/ADC13/PCINT6
+// D11# PB7 PWM8/16 0C0A/OC1C/#RTS/PCINT7
+// D12 A11 PD6 T1/#OC4D/ADC9
+// D13# PC7 PWM10 CLK0/OC4A
+//
+// A0 D18 PF7 ADC7
+// A1 D19 PF6 ADC6
+// A2 D20 PF5 ADC5
+// A3 D21 PF4 ADC4
+// A4 D22 PF1 ADC1
+// A5 D23 PF0 ADC0
+//
+// New pins D14..D17 to map SPI port to digital pins
+//
+// MISO D14 PB3 MISO,PCINT3
+// SCK D15 PB1 SCK,PCINT1
+// MOSI D16 PB2 MOSI,PCINT2
+// SS D17 PB0 RXLED,SS/PCINT0
+//
+// TXLED PD5
+// RXLED PB0
+// HWB PE2 HWB
+
+// these arrays map port names (e.g. port B) to the
+// appropriate addresses for various functions (e.g. reading
+// and writing)
+const uint16_t PROGMEM port_to_mode_PGM[] = {
+ NOT_A_PORT,
+ NOT_A_PORT,
+ (uint16_t) &DDRB,
+ (uint16_t) &DDRC,
+ (uint16_t) &DDRD,
+ (uint16_t) &DDRE,
+ (uint16_t) &DDRF,
+};
+
+const uint16_t PROGMEM port_to_output_PGM[] = {
+ NOT_A_PORT,
+ NOT_A_PORT,
+ (uint16_t) &PORTB,
+ (uint16_t) &PORTC,
+ (uint16_t) &PORTD,
+ (uint16_t) &PORTE,
+ (uint16_t) &PORTF,
+};
+
+const uint16_t PROGMEM port_to_input_PGM[] = {
+ NOT_A_PORT,
+ NOT_A_PORT,
+ (uint16_t) &PINB,
+ (uint16_t) &PINC,
+ (uint16_t) &PIND,
+ (uint16_t) &PINE,
+ (uint16_t) &PINF,
+};
+
+const uint8_t PROGMEM digital_pin_to_port_PGM[30] = {
+ PD, // D0 - PD2
+ PD, // D1 - PD3
+ PD, // D2 - PD1
+ PD, // D3 - PD0
+ PD, // D4 - PD4
+ PC, // D5 - PC6
+ PD, // D6 - PD7
+ PE, // D7 - PE6
+
+ PB, // D8 - PB4
+ PB, // D9 - PB5
+ PB, // D10 - PB6
+ PB, // D11 - PB7
+ PD, // D12 - PD6
+ PC, // D13 - PC7
+
+ PB, // D14 - MISO - PB3
+ PB, // D15 - SCK - PB1
+ PB, // D16 - MOSI - PB2
+ PB, // D17 - SS - PB0
+
+ PF, // D18 - A0 - PF7
+ PF, // D19 - A1 - PF6
+ PF, // D20 - A2 - PF5
+ PF, // D21 - A3 - PF4
+ PF, // D22 - A4 - PF1
+ PF, // D23 - A5 - PF0
+
+ PD, // D24 / D4 - A6 - PD4
+ PD, // D25 / D6 - A7 - PD7
+ PB, // D26 / D8 - A8 - PB4
+ PB, // D27 / D9 - A9 - PB5
+ PB, // D28 / D10 - A10 - PB6
+ PD, // D29 / D12 - A11 - PD6
+};
+
+const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[30] = {
+ _BV(2), // D0 - PD2
+ _BV(3), // D1 - PD3
+ _BV(1), // D2 - PD1
+ _BV(0), // D3 - PD0
+ _BV(4), // D4 - PD4
+ _BV(6), // D5 - PC6
+ _BV(7), // D6 - PD7
+ _BV(6), // D7 - PE6
+
+ _BV(4), // D8 - PB4
+ _BV(5), // D9 - PB5
+ _BV(6), // D10 - PB6
+ _BV(7), // D11 - PB7
+ _BV(6), // D12 - PD6
+ _BV(7), // D13 - PC7
+
+ _BV(3), // D14 - MISO - PB3
+ _BV(1), // D15 - SCK - PB1
+ _BV(2), // D16 - MOSI - PB2
+ _BV(0), // D17 - SS - PB0
+
+ _BV(7), // D18 - A0 - PF7
+ _BV(6), // D19 - A1 - PF6
+ _BV(5), // D20 - A2 - PF5
+ _BV(4), // D21 - A3 - PF4
+ _BV(1), // D22 - A4 - PF1
+ _BV(0), // D23 - A5 - PF0
+
+ _BV(4), // D24 / D4 - A6 - PD4
+ _BV(7), // D25 / D6 - A7 - PD7
+ _BV(4), // D26 / D8 - A8 - PB4
+ _BV(5), // D27 / D9 - A9 - PB5
+ _BV(6), // D28 / D10 - A10 - PB6
+ _BV(6), // D29 / D12 - A11 - PD6
+};
+
+const uint8_t PROGMEM digital_pin_to_timer_PGM[16] = {
+ NOT_ON_TIMER,
+ NOT_ON_TIMER,
+ NOT_ON_TIMER,
+ TIMER0B, /* 3 */
+ NOT_ON_TIMER,
+ TIMER3A, /* 5 */
+ TIMER4D, /* 6 */
+ NOT_ON_TIMER,
+
+ NOT_ON_TIMER,
+ TIMER1A, /* 9 */
+ TIMER1B, /* 10 */
+ TIMER0A, /* 11 */
+
+ NOT_ON_TIMER,
+ TIMER4A, /* 13 */
+
+ NOT_ON_TIMER,
+ NOT_ON_TIMER,
+};
+
+const uint8_t PROGMEM analog_pin_to_channel_PGM[12] = {
+ 7, // A0 PF7 ADC7
+ 6, // A1 PF6 ADC6
+ 5, // A2 PF5 ADC5
+ 4, // A3 PF4 ADC4
+ 1, // A4 PF1 ADC1
+ 0, // A5 PF0 ADC0
+ 8, // A6 D4 PD4 ADC8
+ 10, // A7 D6 PD7 ADC10
+ 11, // A8 D8 PB4 ADC11
+ 12, // A9 D9 PB5 ADC12
+ 13, // A10 D10 PB6 ADC13
+ 9 // A11 D12 PD6 ADC9
+};
+
+#endif /* ARDUINO_MAIN */
+#endif /* Pins_Arduino_h */
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/variants/mega/pins_arduino.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/variants/mega/pins_arduino.h
new file mode 100644
index 000000000..5a9b4cb09
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/variants/mega/pins_arduino.h
@@ -0,0 +1,363 @@
+/*
+ pins_arduino.h - Pin definition functions for Arduino
+ Part of Arduino - http://www.arduino.cc/
+
+ Copyright (c) 2007 David A. Mellis
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ Boston, MA 02111-1307 USA
+
+ $Id: wiring.h 249 2007-02-03 16:52:51Z mellis $
+*/
+
+#ifndef Pins_Arduino_h
+#define Pins_Arduino_h
+
+#include <avr/pgmspace.h>
+
+#define NUM_DIGITAL_PINS 70
+#define NUM_ANALOG_INPUTS 16
+#define analogInputToDigitalPin(p) ((p < 16) ? (p) + 54 : -1)
+#define digitalPinHasPWM(p) (((p) >= 2 && (p) <= 13) || ((p) >= 44 && (p)<= 46))
+
+static const uint8_t SS = 53;
+static const uint8_t MOSI = 51;
+static const uint8_t MISO = 50;
+static const uint8_t SCK = 52;
+
+static const uint8_t SDA = 20;
+static const uint8_t SCL = 21;
+static const uint8_t LED_BUILTIN = 13;
+
+static const uint8_t A0 = 54;
+static const uint8_t A1 = 55;
+static const uint8_t A2 = 56;
+static const uint8_t A3 = 57;
+static const uint8_t A4 = 58;
+static const uint8_t A5 = 59;
+static const uint8_t A6 = 60;
+static const uint8_t A7 = 61;
+static const uint8_t A8 = 62;
+static const uint8_t A9 = 63;
+static const uint8_t A10 = 64;
+static const uint8_t A11 = 65;
+static const uint8_t A12 = 66;
+static const uint8_t A13 = 67;
+static const uint8_t A14 = 68;
+static const uint8_t A15 = 69;
+
+// A majority of the pins are NOT PCINTs, SO BE WARNED (i.e. you cannot use them as receive pins)
+// Only pins available for RECEIVE (TRANSMIT can be on any pin):
+// (I've deliberately left out pin mapping to the Hardware USARTs - seems senseless to me)
+// Pins: 10, 11, 12, 13, 50, 51, 52, 53, 62, 63, 64, 65, 66, 67, 68, 69
+
+#define digitalPinToPCICR(p) ( (((p) >= 10) && ((p) <= 13)) || \
+ (((p) >= 50) && ((p) <= 53)) || \
+ (((p) >= 62) && ((p) <= 69)) ? (&PCICR) : ((uint8_t *)0) )
+
+#define digitalPinToPCICRbit(p) ( (((p) >= 10) && ((p) <= 13)) || (((p) >= 50) && ((p) <= 53)) ? 0 : \
+ ( (((p) >= 62) && ((p) <= 69)) ? 2 : \
+ 0 ) )
+
+#define digitalPinToPCMSK(p) ( (((p) >= 10) && ((p) <= 13)) || (((p) >= 50) && ((p) <= 53)) ? (&PCMSK0) : \
+ ( (((p) >= 62) && ((p) <= 69)) ? (&PCMSK2) : \
+ ((uint8_t *)0) ) )
+
+#define digitalPinToPCMSKbit(p) ( (((p) >= 10) && ((p) <= 13)) ? ((p) - 6) : \
+ ( ((p) == 50) ? 3 : \
+ ( ((p) == 51) ? 2 : \
+ ( ((p) == 52) ? 1 : \
+ ( ((p) == 53) ? 0 : \
+ ( (((p) >= 62) && ((p) <= 69)) ? ((p) - 62) : \
+ 0 ) ) ) ) ) )
+
+#ifdef ARDUINO_MAIN
+
+const uint16_t PROGMEM port_to_mode_PGM[] = {
+ NOT_A_PORT,
+ (uint16_t) &DDRA,
+ (uint16_t) &DDRB,
+ (uint16_t) &DDRC,
+ (uint16_t) &DDRD,
+ (uint16_t) &DDRE,
+ (uint16_t) &DDRF,
+ (uint16_t) &DDRG,
+ (uint16_t) &DDRH,
+ NOT_A_PORT,
+ (uint16_t) &DDRJ,
+ (uint16_t) &DDRK,
+ (uint16_t) &DDRL,
+};
+
+const uint16_t PROGMEM port_to_output_PGM[] = {
+ NOT_A_PORT,
+ (uint16_t) &PORTA,
+ (uint16_t) &PORTB,
+ (uint16_t) &PORTC,
+ (uint16_t) &PORTD,
+ (uint16_t) &PORTE,
+ (uint16_t) &PORTF,
+ (uint16_t) &PORTG,
+ (uint16_t) &PORTH,
+ NOT_A_PORT,
+ (uint16_t) &PORTJ,
+ (uint16_t) &PORTK,
+ (uint16_t) &PORTL,
+};
+
+const uint16_t PROGMEM port_to_input_PGM[] = {
+ NOT_A_PIN,
+ (uint16_t) &PINA,
+ (uint16_t) &PINB,
+ (uint16_t) &PINC,
+ (uint16_t) &PIND,
+ (uint16_t) &PINE,
+ (uint16_t) &PINF,
+ (uint16_t) &PING,
+ (uint16_t) &PINH,
+ NOT_A_PIN,
+ (uint16_t) &PINJ,
+ (uint16_t) &PINK,
+ (uint16_t) &PINL,
+};
+
+const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
+ // PORTLIST
+ // -------------------------------------------
+ PE , // PE 0 ** 0 ** USART0_RX
+ PE , // PE 1 ** 1 ** USART0_TX
+ PE , // PE 4 ** 2 ** PWM2
+ PE , // PE 5 ** 3 ** PWM3
+ PG , // PG 5 ** 4 ** PWM4
+ PE , // PE 3 ** 5 ** PWM5
+ PH , // PH 3 ** 6 ** PWM6
+ PH , // PH 4 ** 7 ** PWM7
+ PH , // PH 5 ** 8 ** PWM8
+ PH , // PH 6 ** 9 ** PWM9
+ PB , // PB 4 ** 10 ** PWM10
+ PB , // PB 5 ** 11 ** PWM11
+ PB , // PB 6 ** 12 ** PWM12
+ PB , // PB 7 ** 13 ** PWM13
+ PJ , // PJ 1 ** 14 ** USART3_TX
+ PJ , // PJ 0 ** 15 ** USART3_RX
+ PH , // PH 1 ** 16 ** USART2_TX
+ PH , // PH 0 ** 17 ** USART2_RX
+ PD , // PD 3 ** 18 ** USART1_TX
+ PD , // PD 2 ** 19 ** USART1_RX
+ PD , // PD 1 ** 20 ** I2C_SDA
+ PD , // PD 0 ** 21 ** I2C_SCL
+ PA , // PA 0 ** 22 ** D22
+ PA , // PA 1 ** 23 ** D23
+ PA , // PA 2 ** 24 ** D24
+ PA , // PA 3 ** 25 ** D25
+ PA , // PA 4 ** 26 ** D26
+ PA , // PA 5 ** 27 ** D27
+ PA , // PA 6 ** 28 ** D28
+ PA , // PA 7 ** 29 ** D29
+ PC , // PC 7 ** 30 ** D30
+ PC , // PC 6 ** 31 ** D31
+ PC , // PC 5 ** 32 ** D32
+ PC , // PC 4 ** 33 ** D33
+ PC , // PC 3 ** 34 ** D34
+ PC , // PC 2 ** 35 ** D35
+ PC , // PC 1 ** 36 ** D36
+ PC , // PC 0 ** 37 ** D37
+ PD , // PD 7 ** 38 ** D38
+ PG , // PG 2 ** 39 ** D39
+ PG , // PG 1 ** 40 ** D40
+ PG , // PG 0 ** 41 ** D41
+ PL , // PL 7 ** 42 ** D42
+ PL , // PL 6 ** 43 ** D43
+ PL , // PL 5 ** 44 ** D44
+ PL , // PL 4 ** 45 ** D45
+ PL , // PL 3 ** 46 ** D46
+ PL , // PL 2 ** 47 ** D47
+ PL , // PL 1 ** 48 ** D48
+ PL , // PL 0 ** 49 ** D49
+ PB , // PB 3 ** 50 ** SPI_MISO
+ PB , // PB 2 ** 51 ** SPI_MOSI
+ PB , // PB 1 ** 52 ** SPI_SCK
+ PB , // PB 0 ** 53 ** SPI_SS
+ PF , // PF 0 ** 54 ** A0
+ PF , // PF 1 ** 55 ** A1
+ PF , // PF 2 ** 56 ** A2
+ PF , // PF 3 ** 57 ** A3
+ PF , // PF 4 ** 58 ** A4
+ PF , // PF 5 ** 59 ** A5
+ PF , // PF 6 ** 60 ** A6
+ PF , // PF 7 ** 61 ** A7
+ PK , // PK 0 ** 62 ** A8
+ PK , // PK 1 ** 63 ** A9
+ PK , // PK 2 ** 64 ** A10
+ PK , // PK 3 ** 65 ** A11
+ PK , // PK 4 ** 66 ** A12
+ PK , // PK 5 ** 67 ** A13
+ PK , // PK 6 ** 68 ** A14
+ PK , // PK 7 ** 69 ** A15
+};
+
+const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = {
+ // PIN IN PORT
+ // -------------------------------------------
+ _BV( 0 ) , // PE 0 ** 0 ** USART0_RX
+ _BV( 1 ) , // PE 1 ** 1 ** USART0_TX
+ _BV( 4 ) , // PE 4 ** 2 ** PWM2
+ _BV( 5 ) , // PE 5 ** 3 ** PWM3
+ _BV( 5 ) , // PG 5 ** 4 ** PWM4
+ _BV( 3 ) , // PE 3 ** 5 ** PWM5
+ _BV( 3 ) , // PH 3 ** 6 ** PWM6
+ _BV( 4 ) , // PH 4 ** 7 ** PWM7
+ _BV( 5 ) , // PH 5 ** 8 ** PWM8
+ _BV( 6 ) , // PH 6 ** 9 ** PWM9
+ _BV( 4 ) , // PB 4 ** 10 ** PWM10
+ _BV( 5 ) , // PB 5 ** 11 ** PWM11
+ _BV( 6 ) , // PB 6 ** 12 ** PWM12
+ _BV( 7 ) , // PB 7 ** 13 ** PWM13
+ _BV( 1 ) , // PJ 1 ** 14 ** USART3_TX
+ _BV( 0 ) , // PJ 0 ** 15 ** USART3_RX
+ _BV( 1 ) , // PH 1 ** 16 ** USART2_TX
+ _BV( 0 ) , // PH 0 ** 17 ** USART2_RX
+ _BV( 3 ) , // PD 3 ** 18 ** USART1_TX
+ _BV( 2 ) , // PD 2 ** 19 ** USART1_RX
+ _BV( 1 ) , // PD 1 ** 20 ** I2C_SDA
+ _BV( 0 ) , // PD 0 ** 21 ** I2C_SCL
+ _BV( 0 ) , // PA 0 ** 22 ** D22
+ _BV( 1 ) , // PA 1 ** 23 ** D23
+ _BV( 2 ) , // PA 2 ** 24 ** D24
+ _BV( 3 ) , // PA 3 ** 25 ** D25
+ _BV( 4 ) , // PA 4 ** 26 ** D26
+ _BV( 5 ) , // PA 5 ** 27 ** D27
+ _BV( 6 ) , // PA 6 ** 28 ** D28
+ _BV( 7 ) , // PA 7 ** 29 ** D29
+ _BV( 7 ) , // PC 7 ** 30 ** D30
+ _BV( 6 ) , // PC 6 ** 31 ** D31
+ _BV( 5 ) , // PC 5 ** 32 ** D32
+ _BV( 4 ) , // PC 4 ** 33 ** D33
+ _BV( 3 ) , // PC 3 ** 34 ** D34
+ _BV( 2 ) , // PC 2 ** 35 ** D35
+ _BV( 1 ) , // PC 1 ** 36 ** D36
+ _BV( 0 ) , // PC 0 ** 37 ** D37
+ _BV( 7 ) , // PD 7 ** 38 ** D38
+ _BV( 2 ) , // PG 2 ** 39 ** D39
+ _BV( 1 ) , // PG 1 ** 40 ** D40
+ _BV( 0 ) , // PG 0 ** 41 ** D41
+ _BV( 7 ) , // PL 7 ** 42 ** D42
+ _BV( 6 ) , // PL 6 ** 43 ** D43
+ _BV( 5 ) , // PL 5 ** 44 ** D44
+ _BV( 4 ) , // PL 4 ** 45 ** D45
+ _BV( 3 ) , // PL 3 ** 46 ** D46
+ _BV( 2 ) , // PL 2 ** 47 ** D47
+ _BV( 1 ) , // PL 1 ** 48 ** D48
+ _BV( 0 ) , // PL 0 ** 49 ** D49
+ _BV( 3 ) , // PB 3 ** 50 ** SPI_MISO
+ _BV( 2 ) , // PB 2 ** 51 ** SPI_MOSI
+ _BV( 1 ) , // PB 1 ** 52 ** SPI_SCK
+ _BV( 0 ) , // PB 0 ** 53 ** SPI_SS
+ _BV( 0 ) , // PF 0 ** 54 ** A0
+ _BV( 1 ) , // PF 1 ** 55 ** A1
+ _BV( 2 ) , // PF 2 ** 56 ** A2
+ _BV( 3 ) , // PF 3 ** 57 ** A3
+ _BV( 4 ) , // PF 4 ** 58 ** A4
+ _BV( 5 ) , // PF 5 ** 59 ** A5
+ _BV( 6 ) , // PF 6 ** 60 ** A6
+ _BV( 7 ) , // PF 7 ** 61 ** A7
+ _BV( 0 ) , // PK 0 ** 62 ** A8
+ _BV( 1 ) , // PK 1 ** 63 ** A9
+ _BV( 2 ) , // PK 2 ** 64 ** A10
+ _BV( 3 ) , // PK 3 ** 65 ** A11
+ _BV( 4 ) , // PK 4 ** 66 ** A12
+ _BV( 5 ) , // PK 5 ** 67 ** A13
+ _BV( 6 ) , // PK 6 ** 68 ** A14
+ _BV( 7 ) , // PK 7 ** 69 ** A15
+};
+
+const uint8_t PROGMEM digital_pin_to_timer_PGM[] = {
+ // TIMERS
+ // -------------------------------------------
+ NOT_ON_TIMER , // PE 0 ** 0 ** USART0_RX
+ NOT_ON_TIMER , // PE 1 ** 1 ** USART0_TX
+ TIMER3B , // PE 4 ** 2 ** PWM2
+ TIMER3C , // PE 5 ** 3 ** PWM3
+ TIMER0B , // PG 5 ** 4 ** PWM4
+ TIMER3A , // PE 3 ** 5 ** PWM5
+ TIMER4A , // PH 3 ** 6 ** PWM6
+ TIMER4B , // PH 4 ** 7 ** PWM7
+ TIMER4C , // PH 5 ** 8 ** PWM8
+ TIMER2B , // PH 6 ** 9 ** PWM9
+ TIMER2A , // PB 4 ** 10 ** PWM10
+ TIMER1A , // PB 5 ** 11 ** PWM11
+ TIMER1B , // PB 6 ** 12 ** PWM12
+ TIMER0A , // PB 7 ** 13 ** PWM13
+ NOT_ON_TIMER , // PJ 1 ** 14 ** USART3_TX
+ NOT_ON_TIMER , // PJ 0 ** 15 ** USART3_RX
+ NOT_ON_TIMER , // PH 1 ** 16 ** USART2_TX
+ NOT_ON_TIMER , // PH 0 ** 17 ** USART2_RX
+ NOT_ON_TIMER , // PD 3 ** 18 ** USART1_TX
+ NOT_ON_TIMER , // PD 2 ** 19 ** USART1_RX
+ NOT_ON_TIMER , // PD 1 ** 20 ** I2C_SDA
+ NOT_ON_TIMER , // PD 0 ** 21 ** I2C_SCL
+ NOT_ON_TIMER , // PA 0 ** 22 ** D22
+ NOT_ON_TIMER , // PA 1 ** 23 ** D23
+ NOT_ON_TIMER , // PA 2 ** 24 ** D24
+ NOT_ON_TIMER , // PA 3 ** 25 ** D25
+ NOT_ON_TIMER , // PA 4 ** 26 ** D26
+ NOT_ON_TIMER , // PA 5 ** 27 ** D27
+ NOT_ON_TIMER , // PA 6 ** 28 ** D28
+ NOT_ON_TIMER , // PA 7 ** 29 ** D29
+ NOT_ON_TIMER , // PC 7 ** 30 ** D30
+ NOT_ON_TIMER , // PC 6 ** 31 ** D31
+ NOT_ON_TIMER , // PC 5 ** 32 ** D32
+ NOT_ON_TIMER , // PC 4 ** 33 ** D33
+ NOT_ON_TIMER , // PC 3 ** 34 ** D34
+ NOT_ON_TIMER , // PC 2 ** 35 ** D35
+ NOT_ON_TIMER , // PC 1 ** 36 ** D36
+ NOT_ON_TIMER , // PC 0 ** 37 ** D37
+ NOT_ON_TIMER , // PD 7 ** 38 ** D38
+ NOT_ON_TIMER , // PG 2 ** 39 ** D39
+ NOT_ON_TIMER , // PG 1 ** 40 ** D40
+ NOT_ON_TIMER , // PG 0 ** 41 ** D41
+ NOT_ON_TIMER , // PL 7 ** 42 ** D42
+ NOT_ON_TIMER , // PL 6 ** 43 ** D43
+ TIMER5C , // PL 5 ** 44 ** D44
+ TIMER5B , // PL 4 ** 45 ** D45
+ TIMER5A , // PL 3 ** 46 ** D46
+ NOT_ON_TIMER , // PL 2 ** 47 ** D47
+ NOT_ON_TIMER , // PL 1 ** 48 ** D48
+ NOT_ON_TIMER , // PL 0 ** 49 ** D49
+ NOT_ON_TIMER , // PB 3 ** 50 ** SPI_MISO
+ NOT_ON_TIMER , // PB 2 ** 51 ** SPI_MOSI
+ NOT_ON_TIMER , // PB 1 ** 52 ** SPI_SCK
+ NOT_ON_TIMER , // PB 0 ** 53 ** SPI_SS
+ NOT_ON_TIMER , // PF 0 ** 54 ** A0
+ NOT_ON_TIMER , // PF 1 ** 55 ** A1
+ NOT_ON_TIMER , // PF 2 ** 56 ** A2
+ NOT_ON_TIMER , // PF 3 ** 57 ** A3
+ NOT_ON_TIMER , // PF 4 ** 58 ** A4
+ NOT_ON_TIMER , // PF 5 ** 59 ** A5
+ NOT_ON_TIMER , // PF 6 ** 60 ** A6
+ NOT_ON_TIMER , // PF 7 ** 61 ** A7
+ NOT_ON_TIMER , // PK 0 ** 62 ** A8
+ NOT_ON_TIMER , // PK 1 ** 63 ** A9
+ NOT_ON_TIMER , // PK 2 ** 64 ** A10
+ NOT_ON_TIMER , // PK 3 ** 65 ** A11
+ NOT_ON_TIMER , // PK 4 ** 66 ** A12
+ NOT_ON_TIMER , // PK 5 ** 67 ** A13
+ NOT_ON_TIMER , // PK 6 ** 68 ** A14
+ NOT_ON_TIMER , // PK 7 ** 69 ** A15
+};
+
+#endif
+
+#endif \ No newline at end of file
diff --git a/tmk_core/protocol/usb_hid/arduino-1.0.1/variants/standard/pins_arduino.h b/tmk_core/protocol/usb_hid/arduino-1.0.1/variants/standard/pins_arduino.h
new file mode 100644
index 000000000..30b426630
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/arduino-1.0.1/variants/standard/pins_arduino.h
@@ -0,0 +1,218 @@
+/*
+ pins_arduino.h - Pin definition functions for Arduino
+ Part of Arduino - http://www.arduino.cc/
+
+ Copyright (c) 2007 David A. Mellis
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ Boston, MA 02111-1307 USA
+
+ $Id: wiring.h 249 2007-02-03 16:52:51Z mellis $
+*/
+
+#ifndef Pins_Arduino_h
+#define Pins_Arduino_h
+
+#include <avr/pgmspace.h>
+
+#define NUM_DIGITAL_PINS 20
+#define NUM_ANALOG_INPUTS 6
+#define analogInputToDigitalPin(p) ((p < 6) ? (p) + 14 : -1)
+
+#if defined(__AVR_ATmega8__)
+#define digitalPinHasPWM(p) ((p) == 9 || (p) == 10 || (p) == 11)
+#else
+#define digitalPinHasPWM(p) ((p) == 3 || (p) == 5 || (p) == 6 || (p) == 9 || (p) == 10 || (p) == 11)
+#endif
+
+static const uint8_t SS = 10;
+static const uint8_t MOSI = 11;
+static const uint8_t MISO = 12;
+static const uint8_t SCK = 13;
+
+static const uint8_t SDA = 18;
+static const uint8_t SCL = 19;
+static const uint8_t LED_BUILTIN = 13;
+
+static const uint8_t A0 = 14;
+static const uint8_t A1 = 15;
+static const uint8_t A2 = 16;
+static const uint8_t A3 = 17;
+static const uint8_t A4 = 18;
+static const uint8_t A5 = 19;
+static const uint8_t A6 = 20;
+static const uint8_t A7 = 21;
+
+#define digitalPinToPCICR(p) (((p) >= 0 && (p) <= 21) ? (&PCICR) : ((uint8_t *)0))
+#define digitalPinToPCICRbit(p) (((p) <= 7) ? 2 : (((p) <= 13) ? 0 : 1))
+#define digitalPinToPCMSK(p) (((p) <= 7) ? (&PCMSK2) : (((p) <= 13) ? (&PCMSK0) : (((p) <= 21) ? (&PCMSK1) : ((uint8_t *)0))))
+#define digitalPinToPCMSKbit(p) (((p) <= 7) ? (p) : (((p) <= 13) ? ((p) - 8) : ((p) - 14)))
+
+#ifdef ARDUINO_MAIN
+
+// On the Arduino board, digital pins are also used
+// for the analog output (software PWM). Analog input
+// pins are a separate set.
+
+// ATMEL ATMEGA8 & 168 / ARDUINO
+//
+// +-\/-+
+// PC6 1| |28 PC5 (AI 5)
+// (D 0) PD0 2| |27 PC4 (AI 4)
+// (D 1) PD1 3| |26 PC3 (AI 3)
+// (D 2) PD2 4| |25 PC2 (AI 2)
+// PWM+ (D 3) PD3 5| |24 PC1 (AI 1)
+// (D 4) PD4 6| |23 PC0 (AI 0)
+// VCC 7| |22 GND
+// GND 8| |21 AREF
+// PB6 9| |20 AVCC
+// PB7 10| |19 PB5 (D 13)
+// PWM+ (D 5) PD5 11| |18 PB4 (D 12)
+// PWM+ (D 6) PD6 12| |17 PB3 (D 11) PWM
+// (D 7) PD7 13| |16 PB2 (D 10) PWM
+// (D 8) PB0 14| |15 PB1 (D 9) PWM
+// +----+
+//
+// (PWM+ indicates the additional PWM pins on the ATmega168.)
+
+// ATMEL ATMEGA1280 / ARDUINO
+//
+// 0-7 PE0-PE7 works
+// 8-13 PB0-PB5 works
+// 14-21 PA0-PA7 works
+// 22-29 PH0-PH7 works
+// 30-35 PG5-PG0 works
+// 36-43 PC7-PC0 works
+// 44-51 PJ7-PJ0 works
+// 52-59 PL7-PL0 works
+// 60-67 PD7-PD0 works
+// A0-A7 PF0-PF7
+// A8-A15 PK0-PK7
+
+
+// these arrays map port names (e.g. port B) to the
+// appropriate addresses for various functions (e.g. reading
+// and writing)
+const uint16_t PROGMEM port_to_mode_PGM[] = {
+ NOT_A_PORT,
+ NOT_A_PORT,
+ (uint16_t) &DDRB,
+ (uint16_t) &DDRC,
+ (uint16_t) &DDRD,
+};
+
+const uint16_t PROGMEM port_to_output_PGM[] = {
+ NOT_A_PORT,
+ NOT_A_PORT,
+ (uint16_t) &PORTB,
+ (uint16_t) &PORTC,
+ (uint16_t) &PORTD,
+};
+
+const uint16_t PROGMEM port_to_input_PGM[] = {
+ NOT_A_PORT,
+ NOT_A_PORT,
+ (uint16_t) &PINB,
+ (uint16_t) &PINC,
+ (uint16_t) &PIND,
+};
+
+const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
+ PD, /* 0 */
+ PD,
+ PD,
+ PD,
+ PD,
+ PD,
+ PD,
+ PD,
+ PB, /* 8 */
+ PB,
+ PB,
+ PB,
+ PB,
+ PB,
+ PC, /* 14 */
+ PC,
+ PC,
+ PC,
+ PC,
+ PC,
+};
+
+const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = {
+ _BV(0), /* 0, port D */
+ _BV(1),
+ _BV(2),
+ _BV(3),
+ _BV(4),
+ _BV(5),
+ _BV(6),
+ _BV(7),
+ _BV(0), /* 8, port B */
+ _BV(1),
+ _BV(2),
+ _BV(3),
+ _BV(4),
+ _BV(5),
+ _BV(0), /* 14, port C */
+ _BV(1),
+ _BV(2),
+ _BV(3),
+ _BV(4),
+ _BV(5),
+};
+
+const uint8_t PROGMEM digital_pin_to_timer_PGM[] = {
+ NOT_ON_TIMER, /* 0 - port D */
+ NOT_ON_TIMER,
+ NOT_ON_TIMER,
+ // on the ATmega168, digital pin 3 has hardware pwm
+#if defined(__AVR_ATmega8__)
+ NOT_ON_TIMER,
+#else
+ TIMER2B,
+#endif
+ NOT_ON_TIMER,
+ // on the ATmega168, digital pins 5 and 6 have hardware pwm
+#if defined(__AVR_ATmega8__)
+ NOT_ON_TIMER,
+ NOT_ON_TIMER,
+#else
+ TIMER0B,
+ TIMER0A,
+#endif
+ NOT_ON_TIMER,
+ NOT_ON_TIMER, /* 8 - port B */
+ TIMER1A,
+ TIMER1B,
+#if defined(__AVR_ATmega8__)
+ TIMER2,
+#else
+ TIMER2A,
+#endif
+ NOT_ON_TIMER,
+ NOT_ON_TIMER,
+ NOT_ON_TIMER,
+ NOT_ON_TIMER, /* 14 - port C */
+ NOT_ON_TIMER,
+ NOT_ON_TIMER,
+ NOT_ON_TIMER,
+ NOT_ON_TIMER,
+};
+
+#endif
+
+#endif
diff --git a/tmk_core/protocol/usb_hid/override_Serial.cpp b/tmk_core/protocol/usb_hid/override_Serial.cpp
new file mode 100644
index 000000000..e1755a5dc
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/override_Serial.cpp
@@ -0,0 +1,51 @@
+/*
+ * Null implementation of Serial to dump debug print into blackhole
+ */
+#include "Arduino.h"
+#include "sendchar.h"
+
+#include "USBAPI.h"
+
+
+void Serial_::begin(uint16_t baud_count)
+{
+}
+
+void Serial_::end(void)
+{
+}
+
+void Serial_::accept(void)
+{
+}
+
+int Serial_::available(void)
+{
+ return 0;
+}
+
+int Serial_::peek(void)
+{
+ return -1;
+}
+
+int Serial_::read(void)
+{
+ return -1;
+}
+
+void Serial_::flush(void)
+{
+}
+
+size_t Serial_::write(uint8_t c)
+{
+ sendchar(c);
+ return 1;
+}
+
+Serial_::operator bool() {
+ return true;
+}
+
+Serial_ Serial;
diff --git a/tmk_core/protocol/usb_hid/override_wiring.c b/tmk_core/protocol/usb_hid/override_wiring.c
new file mode 100644
index 000000000..1e9a94ce2
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/override_wiring.c
@@ -0,0 +1,29 @@
+/*
+ * To keep Timer0 for common/timer.c override arduino/wiring.c.
+ */
+#define __DELAY_BACKWARD_COMPATIBLE__
+#include <util/delay.h>
+#include "common/timer.h"
+#include "Arduino.h"
+
+
+unsigned long millis()
+{
+ return timer_read32();
+}
+unsigned long micros()
+{
+ return timer_read32() * 1000UL;
+}
+void delay(unsigned long ms)
+{
+ _delay_ms(ms);
+}
+void delayMicroseconds(unsigned int us)
+{
+ _delay_us(us);
+}
+void init()
+{
+ timer_init();
+}
diff --git a/tmk_core/protocol/usb_hid/parser.cpp b/tmk_core/protocol/usb_hid/parser.cpp
new file mode 100644
index 000000000..1a152ff3f
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/parser.cpp
@@ -0,0 +1,33 @@
+#include "parser.h"
+#include "usb_hid.h"
+
+#include "debug.h"
+
+
+report_keyboard_t usb_hid_keyboard_report;
+uint16_t usb_hid_time_stamp;
+
+
+void KBDReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf)
+{
+ bool is_error = false;
+ report_keyboard_t *report = (report_keyboard_t *)buf;
+
+ dprintf("KBDReport: %02X %02X", report->mods, report->reserved);
+ for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
+ if (IS_ERROR(report->keys[i])) {
+ is_error = true;
+ }
+ dprintf(" %02X", report->keys[i]);
+ }
+ dprint("\r\n");
+
+ // ignore error and not send report to computer
+ if (is_error) {
+ dprint("Error usage! \r\n");
+ return;
+ }
+
+ ::memcpy(&usb_hid_keyboard_report, buf, sizeof(report_keyboard_t));
+ usb_hid_time_stamp = millis();
+}
diff --git a/tmk_core/protocol/usb_hid/parser.h b/tmk_core/protocol/usb_hid/parser.h
new file mode 100644
index 000000000..703eb1ed4
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/parser.h
@@ -0,0 +1,12 @@
+#ifndef PARSER_H
+#define PARSER_H
+
+#include "hid.h"
+
+class KBDReportParser : public HIDReportParser
+{
+public:
+ virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
+};
+
+#endif
diff --git a/tmk_core/protocol/usb_hid/test/Makefile b/tmk_core/protocol/usb_hid/test/Makefile
new file mode 100644
index 000000000..c093bbd4c
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/test/Makefile
@@ -0,0 +1,88 @@
+
+
+# Target file name (without extension).
+TARGET = usb_hid_test
+
+TMK_DIR = ../../..
+
+# Directory keyboard dependent files exist
+TARGET_DIR = .
+
+# MCU name
+MCU = atmega32u4
+
+
+# Processor frequency.
+# This will define a symbol, F_CPU, in all source code files equal to the
+# processor frequency in Hz. You can then use this symbol in your source code to
+# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
+# automatically to create a 32-bit value in your source code.
+#
+# This will be an integer division of F_USB below, as it is sourced by
+# F_USB after it has run through any CPU prescalers. Note that this value
+# does not *change* the processor frequency - it should merely be updated to
+# reflect the processor speed set externally so that the code can use accurate
+# software delays.
+F_CPU = 16000000
+
+
+
+#
+# LUFA specific
+#
+# Target architecture (see library "Board Types" documentation).
+ARCH = AVR8
+# Input clock frequency.
+# This will define a symbol, F_USB, in all source code files equal to the
+# input clock frequency (before any prescaling is performed) in Hz. This value may
+# differ from F_CPU if prescaling is used on the latter, and is required as the
+# raw input clock is fed directly to the PLL sections of the AVR for high speed
+# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
+# at the end, this will be done automatically to create a 32-bit value in your
+# source code.
+#
+# If no clock division is performed on the input clock inside the AVR (via the
+# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
+F_USB = $(F_CPU)
+# Interrupt driven control endpoint task
+OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
+
+
+
+# Build Options
+# comment out to disable the options.
+#
+# Console for debug
+OPT_DEFS += -DCONSOLE_ENABLE
+
+# Boot Section Size in bytes
+# Teensy halfKay 512
+# Atmel DFU loader 4096
+# LUFA bootloader 4096
+#OPT_DEFS += -DBOOT_SIZE=4096
+
+
+
+SRC = test.cpp
+SRC += common/debug.c
+SRC += common/print.c
+
+CONFIG_H = config.h
+
+
+
+# Search Path
+VPATH += $(TARGET_DIR)
+VPATH += $(TMK_DIR)
+VPATH += $(TMK_DIR)/common
+
+
+
+# program Leonardo
+PROGRAM_CMD = avrdude -p$(MCU) -cavr109 -P$(DEV) -b57600 -Uflash:w:$(TARGET).hex
+
+
+
+include $(TMK_DIR)/protocol/usb_hid.mk
+include $(TMK_DIR)/protocol/lufa.mk
+include $(TMK_DIR)/rules.mk
diff --git a/tmk_core/protocol/usb_hid/test/config.h b/tmk_core/protocol/usb_hid/test/config.h
new file mode 100644
index 000000000..c2230fb57
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/test/config.h
@@ -0,0 +1,40 @@
+/*
+Copyright 2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0xCAFE
+#define DEVICE_VER 0x0814
+#define MANUFACTURER t.m.k.
+#define PRODUCT USB to USB keyboard converter
+
+
+#define DESCRIPTION Product from t.m.k. keyboard firmware project
+
+
+/* matrix size */
+#define MATRIX_ROWS 32
+#define MATRIX_COLS 8
+
+
+/* key combination for command */
+#define IS_COMMAND() (keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT)))
+
+#endif
diff --git a/tmk_core/protocol/usb_hid/test/test.cpp b/tmk_core/protocol/usb_hid/test/test.cpp
new file mode 100644
index 000000000..4958f0c61
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/test/test.cpp
@@ -0,0 +1,92 @@
+#include <avr/io.h>
+#include <avr/wdt.h>
+#include <avr/power.h>
+#include <util/delay.h>
+#include <Arduino.h>
+
+// USB HID host
+#include "Usb.h"
+#include "hid.h"
+#include "hidboot.h"
+#include "parser.h"
+
+// LUFA
+#include "lufa.h"
+
+#include "debug.h"
+
+#include "leonardo_led.h"
+
+
+static USB usb_host;
+static HIDBoot<HID_PROTOCOL_KEYBOARD> kbd(&usb_host);
+static KBDReportParser kbd_parser;
+
+static void LUFA_setup(void)
+{
+ /* Disable watchdog if enabled by bootloader/fuses */
+ MCUSR &= ~(1 << WDRF);
+ wdt_disable();
+
+ /* Disable clock division */
+ clock_prescale_set(clock_div_1);
+
+ // Leonardo needs. Without this USB device is not recognized.
+ USB_Disable();
+
+ USB_Init();
+
+ // for Console_Task
+ USB_Device_EnableSOFEvents();
+}
+
+static void HID_setup()
+{
+ // Arduino Timer startup: wiring.c
+ init();
+
+ if (usb_host.Init() == -1) {
+ debug("HID init: failed\n");
+ LED_TX_OFF;
+ }
+
+ _delay_ms(200);
+
+ kbd.SetReportParser(0, (HIDReportParser*)&kbd_parser);
+}
+
+int main(void)
+{
+ // LED for debug
+ LED_TX_INIT;
+ LED_TX_ON;
+
+ print_enable = true;
+ debug_enable = true;
+ debug_matrix = true;
+ debug_keyboard = true;
+ debug_mouse = true;
+
+ LUFA_setup();
+ sei();
+
+ // wait for startup of sendchar routine
+ while (USB_DeviceState != DEVICE_STATE_Configured) ;
+ if (debug_enable) {
+ _delay_ms(1000);
+ }
+
+ HID_setup();
+
+ debug("init: done\n");
+ for (;;) {
+ usb_host.Task();
+
+#if !defined(INTERRUPT_CONTROL_ENDPOINT)
+ // LUFA Task for control request
+ USB_USBTask();
+#endif
+ }
+
+ return 0;
+}
diff --git a/tmk_core/protocol/usb_hid/usb_hid.h b/tmk_core/protocol/usb_hid/usb_hid.h
new file mode 100644
index 000000000..083b68d1f
--- /dev/null
+++ b/tmk_core/protocol/usb_hid/usb_hid.h
@@ -0,0 +1,10 @@
+#ifndef USB_HID_H
+#define USB_HID_H
+
+#include "report.h"
+
+
+extern report_keyboard_t usb_hid_keyboard_report;
+extern uint16_t usb_hid_time_stamp;
+
+#endif
diff --git a/tmk_core/protocol/vusb.mk b/tmk_core/protocol/vusb.mk
new file mode 100644
index 000000000..3cba3f71a
--- /dev/null
+++ b/tmk_core/protocol/vusb.mk
@@ -0,0 +1,21 @@
+VUSB_DIR = protocol/vusb
+
+OPT_DEFS += -DPROTOCOL_VUSB
+
+SRC += $(VUSB_DIR)/main.c \
+ $(VUSB_DIR)/vusb.c \
+ $(VUSB_DIR)/usbdrv/usbdrv.c \
+ $(VUSB_DIR)/usbdrv/usbdrvasm.S \
+ $(VUSB_DIR)/usbdrv/oddebug.c
+
+
+ifdef NO_UART
+SRC += $(COMMON_DIR)/sendchar_null.c
+else
+SRC += $(COMMON_DIR)/sendchar_uart.c \
+ $(COMMON_DIR)/uart.c
+endif
+
+
+# Search Path
+VPATH += $(TMK_DIR)/protocol/vusb:$(TMK_DIR)/protocol/vusb/usbdrv
diff --git a/tmk_core/protocol/vusb/main.c b/tmk_core/protocol/vusb/main.c
new file mode 100644
index 000000000..8e4a266e9
--- /dev/null
+++ b/tmk_core/protocol/vusb/main.c
@@ -0,0 +1,100 @@
+/* Name: main.c
+ * Project: hid-mouse, a very simple HID example
+ * Author: Christian Starkjohann
+ * Creation Date: 2008-04-07
+ * Tabsize: 4
+ * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
+ * This Revision: $Id: main.c 790 2010-05-30 21:00:26Z cs $
+ */
+#include <stdint.h>
+#include <avr/interrupt.h>
+#include <avr/wdt.h>
+#include <avr/sleep.h>
+#include <util/delay.h>
+#include "usbdrv.h"
+#include "oddebug.h"
+#include "vusb.h"
+#include "keyboard.h"
+#include "host.h"
+#include "timer.h"
+#include "uart.h"
+#include "debug.h"
+
+
+#define UART_BAUD_RATE 115200
+
+
+/* This is from main.c of USBaspLoader */
+static void initForUsbConnectivity(void)
+{
+ uint8_t i = 0;
+
+ usbInit();
+ /* enforce USB re-enumerate: */
+ usbDeviceDisconnect(); /* do this while interrupts are disabled */
+ while(--i){ /* fake USB disconnect for > 250 ms */
+ wdt_reset();
+ _delay_ms(1);
+ }
+ usbDeviceConnect();
+ sei();
+}
+
+int main(void)
+{
+ bool suspended = false;
+#if USB_COUNT_SOF
+ uint16_t last_timer = timer_read();
+#endif
+
+ CLKPR = 0x80, CLKPR = 0;
+#ifndef PS2_USE_USART
+ uart_init(UART_BAUD_RATE);
+#endif
+
+ keyboard_init();
+ host_set_driver(vusb_driver());
+
+ debug("initForUsbConnectivity()\n");
+ initForUsbConnectivity();
+
+ debug("main loop\n");
+ while (1) {
+#if USB_COUNT_SOF
+ if (usbSofCount != 0) {
+ suspended = false;
+ usbSofCount = 0;
+ last_timer = timer_read();
+ } else {
+ // Suspend when no SOF in 3ms-10ms(7.1.7.4 Suspending of USB1.1)
+ if (timer_elapsed(last_timer) > 5) {
+ suspended = true;
+/*
+ uart_putchar('S');
+ _delay_ms(1);
+ cli();
+ set_sleep_mode(SLEEP_MODE_PWR_DOWN);
+ sleep_enable();
+ sleep_bod_disable();
+ sei();
+ sleep_cpu();
+ sleep_disable();
+ _delay_ms(10);
+ uart_putchar('W');
+*/
+ }
+ }
+#endif
+ if (!suspended) {
+ usbPoll();
+
+ // TODO: configuration process is incosistent. it sometime fails.
+ // To prevent failing to configure NOT scan keyboard during configuration
+ if (usbConfiguration && usbInterruptIsReady()) {
+ keyboard_task();
+ }
+ vusb_transfer_keyboard();
+ }
+ }
+}
diff --git a/tmk_core/protocol/vusb/sendchar_usart.c b/tmk_core/protocol/vusb/sendchar_usart.c
new file mode 100644
index 000000000..8d24f87d1
--- /dev/null
+++ b/tmk_core/protocol/vusb/sendchar_usart.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
+ */
+#include <stdint.h>
+#include "oddebug.h"
+#include "sendchar.h"
+
+
+#if DEBUG_LEVEL > 0
+/* from oddebug.c */
+int8_t sendchar(uint8_t c)
+{
+ while(!(ODDBG_USR & (1 << ODDBG_UDRE))); /* wait for data register empty */
+ ODDBG_UDR = c;
+ return 1;
+}
+#else
+int8_t sendchar(uint8_t c)
+{
+ return 1;
+}
+#endif
diff --git a/tmk_core/protocol/vusb/usbdrv/Changelog.txt b/tmk_core/protocol/vusb/usbdrv/Changelog.txt
new file mode 100644
index 000000000..1e74180a9
--- /dev/null
+++ b/tmk_core/protocol/vusb/usbdrv/Changelog.txt
@@ -0,0 +1,308 @@
+This file documents changes in the firmware-only USB driver for atmel's AVR
+microcontrollers. New entries are always appended to the end of the file.
+Scroll down to the bottom to see the most recent changes.
+
+2005-04-01:
+ - Implemented endpoint 1 as interrupt-in endpoint.
+ - Moved all configuration options to usbconfig.h which is not part of the
+ driver.
+ - Changed interface for usbVendorSetup().
+ - Fixed compatibility with ATMega8 device.
+ - Various minor optimizations.
+
+2005-04-11:
+ - Changed interface to application: Use usbFunctionSetup(), usbFunctionRead()
+ and usbFunctionWrite() now. Added configuration options to choose which
+ of these functions to compile in.
+ - Assembler module delivers receive data non-inverted now.
+ - Made register and bit names compatible with more AVR devices.
+
+2005-05-03:
+ - Allow address of usbRxBuf on any memory page as long as the buffer does
+ not cross 256 byte page boundaries.
+ - Better device compatibility: works with Mega88 now.
+ - Code optimization in debugging module.
+ - Documentation updates.
+
+2006-01-02:
+ - Added (free) default Vendor- and Product-IDs bought from voti.nl.
+ - Added USBID-License.txt file which defines the rules for using the free
+ shared VID/PID pair.
+ - Added readme.txt to the usbdrv directory which clarifies administrative
+ issues.
+
+2006-01-25:
+ - Added "configured state" to become more standards compliant.
+ - Added "HALT" state for interrupt endpoint.
+ - Driver passes the "USB Command Verifier" test from usb.org now.
+ - Made "serial number" a configuration option.
+ - Minor optimizations, we now recommend compiler option "-Os" for best
+ results.
+ - Added a version number to usbdrv.h
+
+2006-02-03:
+ - New configuration variable USB_BUFFER_SECTION for the memory section where
+ the USB rx buffer will go. This defaults to ".bss" if not defined. Since
+ this buffer MUST NOT cross 256 byte pages (not even touch a page at the
+ end), the user may want to pass a linker option similar to
+ "-Wl,--section-start=.mybuffer=0x800060".
+ - Provide structure for usbRequest_t.
+ - New defines for USB constants.
+ - Prepared for HID implementations.
+ - Increased data size limit for interrupt transfers to 8 bytes.
+ - New macro usbInterruptIsReady() to query interrupt buffer state.
+
+2006-02-18:
+ - Ensure that the data token which is sent as an ack to an OUT transfer is
+ always zero sized. This fixes a bug where the host reports an error after
+ sending an out transfer to the device, although all data arrived at the
+ device.
+ - Updated docs in usbdrv.h to reflect changed API in usbFunctionWrite().
+
+* Release 2006-02-20
+
+ - Give a compiler warning when compiling with debugging turned on.
+ - Added Oleg Semyonov's changes for IAR-cc compatibility.
+ - Added new (optional) functions usbDeviceConnect() and usbDeviceDisconnect()
+ (also thanks to Oleg!).
+ - Rearranged tests in usbPoll() to save a couple of instructions in the most
+ likely case that no actions are pending.
+ - We need a delay between the SET ADDRESS request until the new address
+ becomes active. This delay was handled in usbPoll() until now. Since the
+ spec says that the delay must not exceed 2ms, previous versions required
+ aggressive polling during the enumeration phase. We have now moved the
+ handling of the delay into the interrupt routine.
+ - We must not reply with NAK to a SETUP transaction. We can only achieve this
+ by making sure that the rx buffer is empty when SETUP tokens are expected.
+ We therefore don't pass zero sized data packets from the status phase of
+ a transfer to usbPoll(). This change MAY cause troubles if you rely on
+ receiving a less than 8 bytes long packet in usbFunctionWrite() to
+ identify the end of a transfer. usbFunctionWrite() will NEVER be called
+ with a zero length.
+
+* Release 2006-03-14
+
+ - Improved IAR C support: tiny memory model, more devices
+ - Added template usbconfig.h file under the name usbconfig-prototype.h
+
+* Release 2006-03-26
+
+ - Added provision for one more interrupt-in endpoint (endpoint 3).
+ - Added provision for one interrupt-out endpoint (endpoint 1).
+ - Added flowcontrol macros for USB.
+ - Added provision for custom configuration descriptor.
+ - Allow ANY two port bits for D+ and D-.
+ - Merged (optional) receive endpoint number into global usbRxToken variable.
+ - Use USB_CFG_IOPORTNAME instead of USB_CFG_IOPORT. We now construct the
+ variable name from the single port letter instead of computing the address
+ of related ports from the output-port address.
+
+* Release 2006-06-26
+
+ - Updated documentation in usbdrv.h and usbconfig-prototype.h to reflect the
+ new features.
+ - Removed "#warning" directives because IAR does not understand them. Use
+ unused static variables instead to generate a warning.
+ - Do not include <avr/io.h> when compiling with IAR.
+ - Introduced USB_CFG_DESCR_PROPS_* in usbconfig.h to configure how each
+ USB descriptor should be handled. It is now possible to provide descriptor
+ data in Flash, RAM or dynamically at runtime.
+ - STALL is now a status in usbTxLen* instead of a message. We can now conform
+ to the spec and leave the stall status pending until it is cleared.
+ - Made usbTxPacketCnt1 and usbTxPacketCnt3 public. This allows the
+ application code to reset data toggling on interrupt pipes.
+
+* Release 2006-07-18
+
+ - Added an #if !defined __ASSEMBLER__ to the warning in usbdrv.h. This fixes
+ an assembler error.
+ - usbDeviceDisconnect() takes pull-up resistor to high impedance now.
+
+* Release 2007-02-01
+
+ - Merged in some code size improvements from usbtiny (thanks to Dick
+ Streefland for these optimizations!)
+ - Special alignment requirement for usbRxBuf not required any more. Thanks
+ again to Dick Streefland for this hint!
+ - Reverted to "#warning" instead of unused static variables -- new versions
+ of IAR CC should handle this directive.
+ - Changed Open Source license to GNU GPL v2 in order to make linking against
+ other free libraries easier. We no longer require publication of the
+ circuit diagrams, but we STRONGLY encourage it. If you improve the driver
+ itself, PLEASE grant us a royalty free license to your changes for our
+ commercial license.
+
+* Release 2007-03-29
+
+ - New configuration option "USB_PUBLIC" in usbconfig.h.
+ - Set USB version number to 1.10 instead of 1.01.
+ - Code used USB_CFG_DESCR_PROPS_STRING_DEVICE and
+ USB_CFG_DESCR_PROPS_STRING_PRODUCT inconsistently. Changed all occurrences
+ to USB_CFG_DESCR_PROPS_STRING_PRODUCT.
+ - New assembler module for 16.5 MHz RC oscillator clock with PLL in receiver
+ code.
+ - New assembler module for 16 MHz crystal.
+ - usbdrvasm.S contains common code only, clock-specific parts have been moved
+ to usbdrvasm12.S, usbdrvasm16.S and usbdrvasm165.S respectively.
+
+* Release 2007-06-25
+
+ - 16 MHz module: Do SE0 check in stuffed bits as well.
+
+* Release 2007-07-07
+
+ - Define hi8(x) for IAR compiler to limit result to 8 bits. This is necessary
+ for negative values.
+ - Added 15 MHz module contributed by V. Bosch.
+ - Interrupt vector name can now be configured. This is useful if somebody
+ wants to use a different hardware interrupt than INT0.
+
+* Release 2007-08-07
+
+ - Moved handleIn3 routine in usbdrvasm16.S so that relative jump range is
+ not exceeded.
+ - More config options: USB_RX_USER_HOOK(), USB_INITIAL_DATATOKEN,
+ USB_COUNT_SOF
+ - USB_INTR_PENDING can now be a memory address, not just I/O
+
+* Release 2007-09-19
+
+ - Split out common parts of assembler modules into separate include file
+ - Made endpoint numbers configurable so that given interface definitions
+ can be matched. See USB_CFG_EP3_NUMBER in usbconfig-prototype.h.
+ - Store endpoint number for interrupt/bulk-out so that usbFunctionWriteOut()
+ can handle any number of endpoints.
+ - Define usbDeviceConnect() and usbDeviceDisconnect() even if no
+ USB_CFG_PULLUP_IOPORTNAME is defined. Directly set D+ and D- to 0 in this
+ case.
+
+* Release 2007-12-01
+
+ - Optimize usbDeviceConnect() and usbDeviceDisconnect() for less code size
+ when USB_CFG_PULLUP_IOPORTNAME is not defined.
+
+* Release 2007-12-13
+
+ - Renamed all include-only assembler modules from *.S to *.inc so that
+ people don't add them to their project sources.
+ - Distribute leap bits in tx loop more evenly for 16 MHz module.
+ - Use "macro" and "endm" instead of ".macro" and ".endm" for IAR
+ - Avoid compiler warnings for constant expr range by casting some values in
+ USB descriptors.
+
+* Release 2008-01-21
+
+ - Fixed bug in 15 and 16 MHz module where the new address set with
+ SET_ADDRESS was already accepted at the next NAK or ACK we send, not at
+ the next data packet we send. This caused problems when the host polled
+ too fast. Thanks to Alexander Neumann for his help and patience debugging
+ this issue!
+
+* Release 2008-02-05
+
+ - Fixed bug in 16.5 MHz module where a register was used in the interrupt
+ handler before it was pushed. This bug was introduced with version
+ 2007-09-19 when common parts were moved to a separate file.
+ - Optimized CRC routine (thanks to Reimar Doeffinger).
+
+* Release 2008-02-16
+
+ - Removed outdated IAR compatibility stuff (code sections).
+ - Added hook macros for USB_RESET_HOOK() and USB_SET_ADDRESS_HOOK().
+ - Added optional routine usbMeasureFrameLength() for calibration of the
+ internal RC oscillator.
+
+* Release 2008-02-28
+
+ - USB_INITIAL_DATATOKEN defaults to USBPID_DATA1 now, which means that we
+ start with sending USBPID_DATA0.
+ - Changed defaults in usbconfig-prototype.h
+ - Added free USB VID/PID pair for MIDI class devices
+ - Restructured AVR-USB as separate package, not part of PowerSwitch any more.
+
+* Release 2008-04-18
+
+ - Restructured usbdrv.c so that it is easier to read and understand.
+ - Better code optimization with gcc 4.
+ - If a second interrupt in endpoint is enabled, also add it to config
+ descriptor.
+ - Added config option for long transfers (above 254 bytes), see
+ USB_CFG_LONG_TRANSFERS in usbconfig.h.
+ - Added 20 MHz module contributed by Jeroen Benschop.
+
+* Release 2008-05-13
+
+ - Fixed bug in libs-host/hiddata.c function usbhidGetReport(): length
+ was not incremented, pointer to length was incremented instead.
+ - Added code to command line tool(s) which claims an interface. This code
+ is disabled by default, but may be necessary on newer Linux kernels.
+ - Added usbconfig.h option "USB_CFG_CHECK_DATA_TOGGLING".
+ - New header "usbportability.h" prepares ports to other development
+ environments.
+ - Long transfers (above 254 bytes) did not work when usbFunctionRead() was
+ used to supply the data. Fixed this bug. [Thanks to Alexander Neumann!]
+ - In hiddata.c (example code for sending/receiving data over HID), use
+ USB_RECIP_DEVICE instead of USB_RECIP_INTERFACE for control transfers so
+ that we need not claim the interface.
+ - in usbPoll() loop 20 times polling for RESET state instead of 10 times.
+ This accounts for the higher clock rates we now support.
+ - Added a module for 12.8 MHz RC oscillator with PLL in receiver loop.
+ - Added hook to SOF code so that oscillator can be tuned to USB frame clock.
+ - Added timeout to waitForJ loop. Helps preventing unexpected hangs.
+ - Added example code for oscillator tuning to libs-device (thanks to
+ Henrik Haftmann for the idea to this routine).
+ - Implemented option USB_CFG_SUPPRESS_INTR_CODE.
+
+* Release 2008-10-22
+
+ - Fixed libs-device/osctune.h: OSCCAL is memory address on ATMega88 and
+ similar, not offset of 0x20 needs to be added.
+ - Allow distribution under GPLv3 for those who have to link against other
+ code distributed under GPLv3.
+
+* Release 2008-11-26
+
+ - Removed libusb-win32 dependency for hid-data example in Makefile.windows.
+ It was never required and confused many people.
+ - Added extern uchar usbRxToken to usbdrv.h.
+ - Integrated a module with CRC checks at 18 MHz by Lukas Schrittwieser.
+
+* Release 2009-03-23
+
+ - Hid-mouse example used settings from hid-data example, fixed that.
+ - Renamed project to V-USB due to a trademark issue with Atmel(r).
+ - Changed CommercialLicense.txt and USBID-License.txt to make the
+ background of USB ID registration clearer.
+
+* Release 2009-04-15
+
+ - Changed CommercialLicense.txt to reflect the new range of PIDs from
+ Jason Kotzin.
+ - Removed USBID-License.txt in favor of USB-IDs-for-free.txt and
+ USB-ID-FAQ.txt
+ - Fixed a bug in the 12.8 MHz module: End Of Packet decection was made in
+ the center between bit 0 and 1 of each byte. This is where the data lines
+ are expected to change and the sampled data may therefore be nonsense.
+ We therefore check EOP ONLY if bits 0 AND 1 have both been read as 0 on D-.
+ - Fixed a bitstuffing problem in the 16 MHz module: If bit 6 was stuffed,
+ the unstuffing code in the receiver routine was 1 cycle too long. If
+ multiple bytes had the unstuffing in bit 6, the error summed up until the
+ receiver was out of sync.
+ - Included option for faster CRC routine.
+ Thanks to Slawomir Fras (BoskiDialer) for this code!
+ - Updated bits in Configuration Descriptor's bmAttributes according to
+ USB 1.1 (in particular bit 7, it is a must-be-set bit now).
+
+* Release 2009-08-22
+
+ - Moved first DBG1() after odDebugInit() in all examples.
+ - Use vector INT0_vect instead of SIG_INTERRUPT0 if defined. This makes
+ V-USB compatible with the new "p" suffix devices (e.g. ATMega328p).
+ - USB_CFG_CLOCK_KHZ setting is now required in usbconfig.h (no default any
+ more).
+ - New option USB_CFG_DRIVER_FLASH_PAGE allows boot loaders on devices with
+ more than 64 kB flash.
+ - Built-in configuration descriptor allows custom definition for second
+ endpoint now.
+
+* Release 2010-07-15
diff --git a/tmk_core/protocol/vusb/usbdrv/CommercialLicense.txt b/tmk_core/protocol/vusb/usbdrv/CommercialLicense.txt
new file mode 100644
index 000000000..11d07d9df
--- /dev/null
+++ b/tmk_core/protocol/vusb/usbdrv/CommercialLicense.txt
@@ -0,0 +1,166 @@
+V-USB Driver Software License Agreement
+Version 2009-08-03
+
+THIS LICENSE AGREEMENT GRANTS YOU CERTAIN RIGHTS IN A SOFTWARE. YOU CAN
+ENTER INTO THIS AGREEMENT AND ACQUIRE THE RIGHTS OUTLINED BELOW BY PAYING
+THE AMOUNT ACCORDING TO SECTION 4 ("PAYMENT") TO OBJECTIVE DEVELOPMENT.
+
+
+1 DEFINITIONS
+
+1.1 "OBJECTIVE DEVELOPMENT" shall mean OBJECTIVE DEVELOPMENT Software GmbH,
+Grosse Schiffgasse 1A/7, 1020 Wien, AUSTRIA.
+
+1.2 "You" shall mean the Licensee.
+
+1.3 "V-USB" shall mean all files included in the package distributed under
+the name "vusb" by OBJECTIVE DEVELOPMENT (http://www.obdev.at/vusb/)
+unless otherwise noted. This includes the firmware-only USB device
+implementation for Atmel AVR microcontrollers, some simple device examples
+and host side software examples and libraries.
+
+
+2 LICENSE GRANTS
+
+2.1 Source Code. OBJECTIVE DEVELOPMENT shall furnish you with the source
+code of V-USB.
+
+2.2 Distribution and Use. OBJECTIVE DEVELOPMENT grants you the
+non-exclusive right to use, copy and distribute V-USB with your hardware
+product(s), restricted by the limitations in section 3 below.
+
+2.3 Modifications. OBJECTIVE DEVELOPMENT grants you the right to modify
+the source code and your copy of V-USB according to your needs.
+
+2.4 USB IDs. OBJECTIVE DEVELOPMENT furnishes you with one or two USB
+Product ID(s), sent to you in e-mail. These Product IDs are reserved
+exclusively for you. OBJECTIVE DEVELOPMENT has obtained USB Product ID
+ranges under the Vendor ID 5824 from Wouter van Ooijen (Van Ooijen
+Technische Informatica, www.voti.nl) and under the Vendor ID 8352 from
+Jason Kotzin (Clay Logic, www.claylogic.com). Both owners of the Vendor IDs
+have obtained these IDs from the USB Implementers Forum, Inc.
+(www.usb.org). OBJECTIVE DEVELOPMENT disclaims all liability which might
+arise from the assignment of USB IDs.
+
+2.5 USB Certification. Although not part of this agreement, we want to make
+it clear that you cannot become USB certified when you use V-USB or a USB
+Product ID assigned by OBJECTIVE DEVELOPMENT. AVR microcontrollers don't
+meet the electrical specifications required by the USB specification and
+the USB Implementers Forum certifies only members who bought a Vendor ID of
+their own.
+
+
+3 LICENSE RESTRICTIONS
+
+3.1 Number of Units. Only one of the following three definitions is
+applicable. Which one is determined by the amount you pay to OBJECTIVE
+DEVELOPMENT, see section 4 ("Payment") below.
+
+Hobby License: You may use V-USB according to section 2 above in no more
+than 5 hardware units. These units must not be sold for profit.
+
+Entry Level License: You may use V-USB according to section 2 above in no
+more than 150 hardware units.
+
+Professional License: You may use V-USB according to section 2 above in
+any number of hardware units, except for large scale production ("unlimited
+fair use"). Quantities below 10,000 units are not considered large scale
+production. If your reach quantities which are obviously large scale
+production, you must pay a license fee of 0.10 EUR per unit for all units
+above 10,000.
+
+3.2 Rental. You may not rent, lease, or lend V-USB or otherwise encumber
+any copy of V-USB, or any of the rights granted herein.
+
+3.3 Transfer. You may not transfer your rights under this Agreement to
+another party without OBJECTIVE DEVELOPMENT's prior written consent. If
+such consent is obtained, you may permanently transfer this License to
+another party. The recipient of such transfer must agree to all terms and
+conditions of this Agreement.
+
+3.4 Reservation of Rights. OBJECTIVE DEVELOPMENT retains all rights not
+expressly granted.
+
+3.5 Non-Exclusive Rights. Your license rights under this Agreement are
+non-exclusive.
+
+3.6 Third Party Rights. This Agreement cannot grant you rights controlled
+by third parties. In particular, you are not allowed to use the USB logo or
+other trademarks owned by the USB Implementers Forum, Inc. without their
+consent. Since such consent depends on USB certification, it should be
+noted that V-USB will not pass certification because it does not
+implement checksum verification and the microcontroller ports do not meet
+the electrical specifications.
+
+
+4 PAYMENT
+
+The payment amount depends on the variation of this agreement (according to
+section 3.1) into which you want to enter. Concrete prices are listed on
+OBJECTIVE DEVELOPMENT's web site, usually at
+http://www.obdev.at/vusb/license.html. You agree to pay the amount listed
+there to OBJECTIVE DEVELOPMENT or OBJECTIVE DEVELOPMENT's payment processor
+or reseller.
+
+
+5 COPYRIGHT AND OWNERSHIP
+
+V-USB is protected by copyright laws and international copyright
+treaties, as well as other intellectual property laws and treaties. V-USB
+is licensed, not sold.
+
+
+6 TERM AND TERMINATION
+
+6.1 Term. This Agreement shall continue indefinitely. However, OBJECTIVE
+DEVELOPMENT may terminate this Agreement and revoke the granted license and
+USB-IDs if you fail to comply with any of its terms and conditions.
+
+6.2 Survival of Terms. All provisions regarding secrecy, confidentiality
+and limitation of liability shall survive termination of this agreement.
+
+
+7 DISCLAIMER OF WARRANTY AND LIABILITY
+
+LIMITED WARRANTY. V-USB IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+KIND. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, OBJECTIVE
+DEVELOPMENT AND ITS SUPPLIERS HEREBY DISCLAIM ALL WARRANTIES, EITHER
+EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND
+NON-INFRINGEMENT, WITH REGARD TO V-USB, AND THE PROVISION OF OR FAILURE
+TO PROVIDE SUPPORT SERVICES. THIS LIMITED WARRANTY GIVES YOU SPECIFIC LEGAL
+RIGHTS. YOU MAY HAVE OTHERS, WHICH VARY FROM STATE/JURISDICTION TO
+STATE/JURISDICTION.
+
+LIMITATION OF LIABILITY. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW,
+IN NO EVENT SHALL OBJECTIVE DEVELOPMENT OR ITS SUPPLIERS BE LIABLE FOR ANY
+SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER
+(INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
+BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY
+LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE V-USB OR THE
+PROVISION OF OR FAILURE TO PROVIDE SUPPORT SERVICES, EVEN IF OBJECTIVE
+DEVELOPMENT HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. IN ANY
+CASE, OBJECTIVE DEVELOPMENT'S ENTIRE LIABILITY UNDER ANY PROVISION OF THIS
+AGREEMENT SHALL BE LIMITED TO THE AMOUNT ACTUALLY PAID BY YOU FOR V-USB.
+
+
+8 MISCELLANEOUS TERMS
+
+8.1 Marketing. OBJECTIVE DEVELOPMENT has the right to mention for marketing
+purposes that you entered into this agreement.
+
+8.2 Entire Agreement. This document represents the entire agreement between
+OBJECTIVE DEVELOPMENT and you. It may only be modified in writing signed by
+an authorized representative of both, OBJECTIVE DEVELOPMENT and you.
+
+8.3 Severability. In case a provision of these terms and conditions should
+be or become partly or entirely invalid, ineffective, or not executable,
+the validity of all other provisions shall not be affected.
+
+8.4 Applicable Law. This agreement is governed by the laws of the Republic
+of Austria.
+
+8.5 Responsible Courts. The responsible courts in Vienna/Austria will have
+exclusive jurisdiction regarding all disputes in connection with this
+agreement.
+
diff --git a/tmk_core/protocol/vusb/usbdrv/License.txt b/tmk_core/protocol/vusb/usbdrv/License.txt
new file mode 100644
index 000000000..ce4c3aed4
--- /dev/null
+++ b/tmk_core/protocol/vusb/usbdrv/License.txt
@@ -0,0 +1,361 @@
+OBJECTIVE DEVELOPMENT GmbH's V-USB driver software is distributed under the
+terms and conditions of the GNU GPL version 2 or the GNU GPL version 3. It is
+your choice whether you apply the terms of version 2 or version 3. The full
+text of GPLv2 is included below. In addition to the requirements in the GPL,
+we STRONGLY ENCOURAGE you to do the following:
+
+(1) Publish your entire project on a web site and drop us a note with the URL.
+Use the form at http://www.obdev.at/vusb/feedback.html for your submission.
+
+(2) Adhere to minimum publication standards. Please include AT LEAST:
+ - a circuit diagram in PDF, PNG or GIF format
+ - full source code for the host software
+ - a readme.txt file in ASCII format which describes the purpose of the
+ project and what can be found in which directories and which files
+ - a reference to http://www.obdev.at/vusb/
+
+(3) If you improve the driver firmware itself, please give us a free license
+to your modifications for our commercial license offerings.
+
+
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/tmk_core/protocol/vusb/usbdrv/Readme.txt b/tmk_core/protocol/vusb/usbdrv/Readme.txt
new file mode 100644
index 000000000..3cff49f6f
--- /dev/null
+++ b/tmk_core/protocol/vusb/usbdrv/Readme.txt
@@ -0,0 +1,172 @@
+This is the readme file to Objective Development's firmware-only USB driver
+for Atmel AVR microcontrollers. For more information please visit
+http://www.obdev.at/vusb/
+
+This directory contains the USB firmware only. Copy it as-is to your own
+project and add all .c and .S files to your project (these files are marked
+with an asterisk in the list below). Then copy usbconfig-prototype.h as
+usbconfig.h to your project and edit it according to your configuration.
+
+
+TECHNICAL DOCUMENTATION
+=======================
+The technical documentation (API) for the firmware driver is contained in the
+file "usbdrv.h". Please read all of it carefully! Configuration options are
+documented in "usbconfig-prototype.h".
+
+The driver consists of the following files:
+ readme.txt ............. The file you are currently reading.
+ Changelog.txt .......... Release notes for all versions of the driver.
+ usbdrv.h ............... Driver interface definitions and technical docs.
+* usbdrv.c ............... High level language part of the driver. Link this
+ module to your code!
+* usbdrvasm.S ............ Assembler part of the driver. This module is mostly
+ a stub and includes one of the usbdrvasm*.S files
+ depending on processor clock. Link this module to
+ your code!
+ usbdrvasm*.inc ......... Assembler routines for particular clock frequencies.
+ Included by usbdrvasm.S, don't link it directly!
+ asmcommon.inc .......... Common assembler routines. Included by
+ usbdrvasm*.inc, don't link it directly!
+ usbconfig-prototype.h .. Prototype for your own usbdrv.h file.
+* oddebug.c .............. Debug functions. Only used when DEBUG_LEVEL is
+ defined to a value greater than 0. Link this module
+ to your code!
+ oddebug.h .............. Interface definitions of the debug module.
+ usbportability.h ....... Header with compiler-dependent stuff.
+ usbdrvasm.asm .......... Compatibility stub for IAR-C-compiler. Use this
+ module instead of usbdrvasm.S when you assembler
+ with IAR's tools.
+ License.txt ............ Open Source license for this driver.
+ CommercialLicense.txt .. Optional commercial license for this driver.
+ USB-ID-FAQ.txt ......... General infos about USB Product- and Vendor-IDs.
+ USB-IDs-for-free.txt ... List and terms of use for free shared PIDs.
+
+(*) ... These files should be linked to your project.
+
+
+CPU CORE CLOCK FREQUENCY
+========================
+We supply assembler modules for clock frequencies of 12 MHz, 12.8 MHz, 15 MHz,
+16 MHz, 16.5 MHz 18 MHz and 20 MHz. Other clock rates are not supported. The
+actual clock rate must be configured in usbconfig.h.
+
+12 MHz Clock
+This is the traditional clock rate of V-USB because it's the lowest clock
+rate where the timing constraints of the USB spec can be met.
+
+15 MHz Clock
+Similar to 12 MHz, but some NOPs inserted. On the other hand, the higher clock
+rate allows for some loops which make the resulting code size somewhat smaller
+than the 12 MHz version.
+
+16 MHz Clock
+This clock rate has been added for users of the Arduino board and other
+ready-made boards which come with a fixed 16 MHz crystal. It's also an option
+if you need the slightly higher clock rate for performance reasons. Since
+16 MHz is not divisible by the USB low speed bit clock of 1.5 MHz, the code
+is somewhat tricky and has to insert a leap cycle every third byte.
+
+12.8 MHz and 16.5 MHz Clock
+The assembler modules for these clock rates differ from the other modules
+because they have been built for an RC oscillator with only 1% precision. The
+receiver code inserts leap cycles to compensate for clock deviations. 1% is
+also the precision which can be achieved by calibrating the internal RC
+oscillator of the AVR. Please note that only AVRs with internal 64 MHz PLL
+oscillator can reach 16.5 MHz with the RC oscillator. This includes the very
+popular ATTiny25, ATTiny45, ATTiny85 series as well as the ATTiny26. Almost
+all AVRs can reach 12.8 MHz, although this is outside the specified range.
+
+See the EasyLogger example at http://www.obdev.at/vusb/easylogger.html for
+code which calibrates the RC oscillator based on the USB frame clock.
+
+18 MHz Clock
+This module is closer to the USB specification because it performs an on the
+fly CRC check for incoming packets. Packets with invalid checksum are
+discarded as required by the spec. If you also implement checks for data
+PID toggling on application level (see option USB_CFG_CHECK_DATA_TOGGLING
+in usbconfig.h for more info), this ensures data integrity. Due to the CRC
+tables and alignment requirements, this code is bigger than modules for other
+clock rates. To activate this module, you must define USB_CFG_CHECK_CRC to 1
+and USB_CFG_CLOCK_KHZ to 18000 in usbconfig.h.
+
+20 MHz Clock
+This module is for people who won't do it with less than the maximum. Since
+20 MHz is not divisible by the USB low speed bit clock of 1.5 MHz, the code
+uses similar tricks as the 16 MHz module to insert leap cycles.
+
+
+USB IDENTIFIERS
+===============
+Every USB device needs a vendor- and a product-identifier (VID and PID). VIDs
+are obtained from usb.org for a price of 1,500 USD. Once you have a VID, you
+can assign PIDs at will.
+
+Since an entry level cost of 1,500 USD is too high for most small companies
+and hobbyists, we provide some VID/PID pairs for free. See the file
+USB-IDs-for-free.txt for details.
+
+Objective Development also has some license offerings which include product
+IDs. See http://www.obdev.at/vusb/ for details.
+
+
+DEVELOPMENT SYSTEM
+==================
+This driver has been developed and optimized for the GNU compiler version 3
+and 4. We recommend that you use the GNU compiler suite because it is freely
+available. V-USB has also been ported to the IAR compiler and assembler. It
+has been tested with IAR 4.10B/W32 and 4.12A/W32 on an ATmega8 with the
+"small" and "tiny" memory model. Not every release is tested with IAR CC and
+the driver may therefore fail to compile with IAR. Please note that gcc is
+more efficient for usbdrv.c because this module has been deliberately
+optimized for gcc.
+
+Gcc version 3 produces smaller code than version 4 due to new optimizing
+capabilities which don't always improve things on 8 bit CPUs. The code size
+generated by gcc 4 can be reduced with the compiler options
+-fno-move-loop-invariants, -fno-tree-scev-cprop and
+-fno-inline-small-functions in addition to -Os. On devices with more than
+8k of flash memory, we also recommend the linker option --relax (written as
+-Wl,--relax for gcc) to convert absolute calls into relative where possible.
+
+For more information about optimizing options see:
+
+ http://www.tty1.net/blog/2008-04-29-avr-gcc-optimisations_en.html
+
+These optimizations are good for gcc 4.x. Version 3.x of gcc does not support
+most of these options and produces good code anyway.
+
+
+USING V-USB FOR FREE
+====================
+The AVR firmware driver is published under the GNU General Public License
+Version 2 (GPL2) and the GNU General Public License Version 3 (GPL3). It is
+your choice whether you apply the terms of version 2 or version 3.
+
+If you decide for the free GPL2 or GPL3, we STRONGLY ENCOURAGE you to do the
+following things IN ADDITION to the obligations from the GPL:
+
+(1) Publish your entire project on a web site and drop us a note with the URL.
+Use the form at http://www.obdev.at/vusb/feedback.html for your submission.
+If you don't have a web site, you can publish the project in obdev's
+documentation wiki at
+http://www.obdev.at/goto.php?t=vusb-wiki&p=hosted-projects.
+
+(2) Adhere to minimum publication standards. Please include AT LEAST:
+ - a circuit diagram in PDF, PNG or GIF format
+ - full source code for the host software
+ - a readme.txt file in ASCII format which describes the purpose of the
+ project and what can be found in which directories and which files
+ - a reference to http://www.obdev.at/vusb/
+
+(3) If you improve the driver firmware itself, please give us a free license
+to your modifications for our commercial license offerings.
+
+
+COMMERCIAL LICENSES FOR V-USB
+=============================
+If you don't want to publish your source code under the terms of the GPL,
+you can simply pay money for V-USB. As an additional benefit you get
+USB PIDs for free, reserved exclusively to you. See the file
+"CommercialLicense.txt" for details.
+
diff --git a/tmk_core/protocol/vusb/usbdrv/USB-ID-FAQ.txt b/tmk_core/protocol/vusb/usbdrv/USB-ID-FAQ.txt
new file mode 100644
index 000000000..d1de8fb61
--- /dev/null
+++ b/tmk_core/protocol/vusb/usbdrv/USB-ID-FAQ.txt
@@ -0,0 +1,149 @@
+Version 2009-08-22
+
+==========================
+WHY DO WE NEED THESE IDs?
+==========================
+
+USB is more than a low level protocol for data transport. It also defines a
+common set of requests which must be understood by all devices. And as part
+of these common requests, the specification defines data structures, the
+USB Descriptors, which are used to describe the properties of the device.
+
+From the perspective of an operating system, it is therefore possible to find
+out basic properties of a device (such as e.g. the manufacturer and the name
+of the device) without a device-specific driver. This is essential because
+the operating system can choose a driver to load based on this information
+(Plug-And-Play).
+
+Among the most important properties in the Device Descriptor are the USB
+Vendor- and Product-ID. Both are 16 bit integers. The most simple form of
+driver matching is based on these IDs. The driver announces the Vendor- and
+Product-IDs of the devices it can handle and the operating system loads the
+appropriate driver when the device is connected.
+
+It is obvious that this technique only works if the pair Vendor- plus
+Product-ID is unique: Only devices which require the same driver can have the
+same pair of IDs.
+
+
+=====================================================
+HOW DOES THE USB STANDARD ENSURE THAT IDs ARE UNIQUE?
+=====================================================
+
+Since it is so important that USB IDs are unique, the USB Implementers Forum,
+Inc. (usb.org) needs a way to enforce this legally. It is not forbidden by
+law to build a device and assign it any random numbers as IDs. Usb.org
+therefore needs an agreement to regulate the use of USB IDs. The agreement
+binds only parties who agreed to it, of course. Everybody else is free to use
+any numbers for their IDs.
+
+So how can usb.org ensure that every manufacturer of USB devices enters into
+an agreement with them? They do it via trademark licensing. Usb.org has
+registered the trademark "USB", all associated logos and related terms. If
+you want to put an USB logo on your product or claim that it is USB
+compliant, you must license these trademarks from usb.org. And this is where
+you enter into an agreement. See the "USB-IF Trademark License Agreement and
+Usage Guidelines for the USB-IF Logo" at
+http://www.usb.org/developers/logo_license/.
+
+Licensing the USB trademarks requires that you buy a USB Vendor-ID from
+usb.org (one-time fee of ca. 2,000 USD), that you become a member of usb.org
+(yearly fee of ca. 4,000 USD) and that you meet all the technical
+specifications from the USB spec.
+
+This means that most hobbyists and small companies will never be able to
+become USB compliant, just because membership is so expensive. And you can't
+be compliant with a driver based on V-USB anyway, because the AVR's port pins
+don't meet the electrical specifications for USB. So, in principle, all
+hobbyists and small companies are free to choose any random numbers for their
+IDs. They have nothing to lose...
+
+There is one exception worth noting, though: If you use a sub-component which
+implements USB, the vendor of the sub-components may guarantee USB
+compliance. This might apply to some or all of FTDI's solutions.
+
+
+=======================================================================
+WHY SHOULD YOU OBTAIN USB IDs EVEN IF YOU DON'T LICENSE USB TRADEMARKS?
+=======================================================================
+
+You have learned in the previous section that you are free to choose any
+numbers for your IDs anyway. So why not do exactly this? There is still the
+technical issue. If you choose IDs which are already in use by somebody else,
+operating systems will load the wrong drivers and your device won't work.
+Even if you choose IDs which are not currently in use, they may be in use in
+the next version of the operating system or even after an automatic update.
+
+So what you need is a pair of Vendor- and Product-IDs for which you have the
+guarantee that no USB compliant product uses them. This implies that no
+operating system will ever ship with drivers responsible for these IDs.
+
+
+==============================================
+HOW DOES OBJECTIVE DEVELOPMENT HANDLE USB IDs?
+==============================================
+
+Objective Development gives away pairs of USB-IDs with their V-USB licenses.
+In order to ensure that these IDs are unique, Objective Development has an
+agreement with the company/person who has bought the USB Vendor-ID from
+usb.org. This agreement ensures that a range of USB Product-IDs is reserved
+for assignment by Objective Development and that the owner of the Vendor-ID
+won't give it to anybody else.
+
+This means that you have to trust three parties to ensure uniqueness of
+your IDs:
+
+ - Objective Development, that they don't give the same PID to more than
+ one person.
+ - The owner of the Vendor-ID that they don't assign PIDs from the range
+ assigned to Objective Development to anybody else.
+ - Usb.org that they don't assign the same Vendor-ID a second time.
+
+
+==================================
+WHO IS THE OWNER OF THE VENDOR-ID?
+==================================
+
+Objective Development has obtained ranges of USB Product-IDs under two
+Vendor-IDs: Under Vendor-ID 5824 from Wouter van Ooijen (Van Ooijen
+Technische Informatica, www.voti.nl) and under Vendor-ID 8352 from Jason
+Kotzin (Clay Logic, www.claylogic.com). Both VID owners have received their
+Vendor-ID directly from usb.org.
+
+
+=========================================================================
+CAN I USE USB-IDs FROM OBJECTIVE DEVELOPMENT WITH OTHER DRIVERS/HARDWARE?
+=========================================================================
+
+The short answer is: Yes. All you get is a guarantee that the IDs are never
+assigned to anybody else. What more do you need?
+
+
+============================
+WHAT ABOUT SHARED ID PAIRS?
+============================
+
+Objective Development has reserved some PID/VID pairs for shared use. You
+have no guarantee of uniqueness for them, except that no USB compliant device
+uses them. In order to avoid technical problems, we must ensure that all
+devices with the same pair of IDs use the same driver on kernel level. For
+details, see the file USB-IDs-for-free.txt.
+
+
+======================================================
+I HAVE HEARD THAT SUB-LICENSING OF USB-IDs IS ILLEGAL?
+======================================================
+
+A 16 bit integer number cannot be protected by copyright laws. It is not
+sufficiently complex. And since none of the parties involved entered into the
+USB-IF Trademark License Agreement, we are not bound by this agreement. So
+there is no reason why it should be illegal to sub-license USB-IDs.
+
+
+=============================================
+WHO IS LIABLE IF THERE ARE INCOMPATIBILITIES?
+=============================================
+
+Objective Development disclaims all liabilities which might arise from the
+assignment of IDs. If you guarantee product features to your customers
+without proper disclaimer, YOU are liable for that.
diff --git a/tmk_core/protocol/vusb/usbdrv/USB-IDs-for-free.txt b/tmk_core/protocol/vusb/usbdrv/USB-IDs-for-free.txt
new file mode 100644
index 000000000..2f4d59ad1
--- /dev/null
+++ b/tmk_core/protocol/vusb/usbdrv/USB-IDs-for-free.txt
@@ -0,0 +1,148 @@
+Version 2009-08-22
+
+===========================
+FREE USB-IDs FOR SHARED USE
+===========================
+
+Objective Development has reserved a set of USB Product-IDs for use according
+to the guidelines outlined below. For more information about the concept of
+USB IDs please see the file USB-ID-FAQ.txt. Objective Development guarantees
+that the IDs listed below are not used by any USB compliant devices.
+
+
+====================
+MECHANISM OF SHARING
+====================
+
+From a technical point of view, two different devices can share the same USB
+Vendor- and Product-ID if they require the same driver on operating system
+level. We make use of this fact by assigning separate IDs for various device
+classes. On application layer, devices must be distinguished by their textual
+name or serial number. We offer separate sets of IDs for discrimination by
+textual name and for serial number.
+
+Examples for shared use of USB IDs are included with V-USB in the "examples"
+subdirectory.
+
+
+======================================
+IDs FOR DISCRIMINATION BY TEXTUAL NAME
+======================================
+
+If you use one of the IDs listed below, your device and host-side software
+must conform to these rules:
+
+(1) The USB device MUST provide a textual representation of the manufacturer
+and product identification. The manufacturer identification MUST be available
+at least in USB language 0x0409 (English/US).
+
+(2) The textual manufacturer identification MUST contain either an Internet
+domain name (e.g. "mycompany.com") registered and owned by you, or an e-mail
+address under your control (e.g. "myname@gmx.net"). You can embed the domain
+name or e-mail address in any string you like, e.g. "Objective Development
+http://www.obdev.at/vusb/".
+
+(3) You are responsible for retaining ownership of the domain or e-mail
+address for as long as any of your products are in use.
+
+(4) You may choose any string for the textual product identification, as long
+as this string is unique within the scope of your textual manufacturer
+identification.
+
+(5) Application side device look-up MUST be based on the textual manufacturer
+and product identification in addition to VID/PID matching. The driver
+matching MUST be a comparison of the entire strings, NOT a sub-string match.
+
+(6) For devices which implement a particular USB device class (e.g. HID), the
+operating system's default class driver MUST be used. If an operating system
+driver for Vendor Class devices is needed, this driver must be libusb or
+libusb-win32 (see http://libusb.org/ and
+http://libusb-win32.sourceforge.net/).
+
+Table if IDs for discrimination by textual name:
+
+PID dec (hex) | VID dec (hex) | Description of use
+==============+===============+============================================
+1500 (0x05dc) | 5824 (0x16c0) | For Vendor Class devices with libusb
+--------------+---------------+--------------------------------------------
+1503 (0x05df) | 5824 (0x16c0) | For generic HID class devices (which are
+ | | NOT mice, keyboards or joysticks)
+--------------+---------------+--------------------------------------------
+1505 (0x05e1) | 5824 (0x16c0) | For CDC-ACM class devices (modems)
+--------------+---------------+--------------------------------------------
+1508 (0x05e4) | 5824 (0x16c0) | For MIDI class devices
+--------------+---------------+--------------------------------------------
+
+Note that Windows caches the textual product- and vendor-description for
+mice, keyboards and joysticks. Name-bsed discrimination is therefore not
+recommended for these device classes.
+
+
+=======================================
+IDs FOR DISCRIMINATION BY SERIAL NUMBER
+=======================================
+
+If you use one of the IDs listed below, your device and host-side software
+must conform to these rules:
+
+(1) The USB device MUST provide a textual representation of the serial
+number. The serial number string MUST be available at least in USB language
+0x0409 (English/US).
+
+(2) The serial number MUST start with either an Internet domain name (e.g.
+"mycompany.com") registered and owned by you, or an e-mail address under your
+control (e.g. "myname@gmx.net"), both terminated with a colon (":") character.
+You MAY append any string you like for further discrimination of your devices.
+
+(3) You are responsible for retaining ownership of the domain or e-mail
+address for as long as any of your products are in use.
+
+(5) Application side device look-up MUST be based on the serial number string
+in addition to VID/PID matching. The matching must start at the first
+character of the serial number string and include the colon character
+terminating your domain or e-mail address. It MAY stop anywhere after that.
+
+(6) For devices which implement a particular USB device class (e.g. HID), the
+operating system's default class driver MUST be used. If an operating system
+driver for Vendor Class devices is needed, this driver must be libusb or
+libusb-win32 (see http://libusb.org/ and
+http://libusb-win32.sourceforge.net/).
+
+Table if IDs for discrimination by serial number string:
+
+PID dec (hex) | VID dec (hex) | Description of use
+===============+===============+===========================================
+10200 (0x27d8) | 5824 (0x16c0) | For Vendor Class devices with libusb
+---------------+---------------+-------------------------------------------
+10201 (0x27d9) | 5824 (0x16c0) | For generic HID class devices (which are
+ | | NOT mice, keyboards or joysticks)
+---------------+---------------+-------------------------------------------
+10202 (0x27da) | 5824 (0x16c0) | For USB Mice
+---------------+---------------+-------------------------------------------
+10203 (0x27db) | 5824 (0x16c0) | For USB Keyboards
+---------------+---------------+-------------------------------------------
+10204 (0x27db) | 5824 (0x16c0) | For USB Joysticks
+---------------+---------------+-------------------------------------------
+10205 (0x27dc) | 5824 (0x16c0) | For CDC-ACM class devices (modems)
+---------------+---------------+-------------------------------------------
+10206 (0x27dd) | 5824 (0x16c0) | For MIDI class devices
+---------------+---------------+-------------------------------------------
+
+
+=================
+ORIGIN OF USB-IDs
+=================
+
+OBJECTIVE DEVELOPMENT Software GmbH has obtained all VID/PID pairs listed
+here from Wouter van Ooijen (see www.voti.nl) for exclusive disposition.
+Wouter van Ooijen has obtained the VID from the USB Implementers Forum, Inc.
+(see www.usb.org). The VID is registered for the company name "Van Ooijen
+Technische Informatica".
+
+
+==========
+DISCLAIMER
+==========
+
+OBJECTIVE DEVELOPMENT Software GmbH disclaims all liability for any
+problems which are caused by the shared use of these VID/PID pairs.
diff --git a/tmk_core/protocol/vusb/usbdrv/asmcommon.inc b/tmk_core/protocol/vusb/usbdrv/asmcommon.inc
new file mode 100644
index 000000000..07d692be3
--- /dev/null
+++ b/tmk_core/protocol/vusb/usbdrv/asmcommon.inc
@@ -0,0 +1,188 @@
+/* Name: asmcommon.inc
+ * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
+ * Author: Christian Starkjohann
+ * Creation Date: 2007-11-05
+ * Tabsize: 4
+ * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
+ * Revision: $Id$
+ */
+
+/* Do not link this file! Link usbdrvasm.S instead, which includes the
+ * appropriate implementation!
+ */
+
+/*
+General Description:
+This file contains assembler code which is shared among the USB driver
+implementations for different CPU cocks. Since the code must be inserted
+in the middle of the module, it's split out into this file and #included.
+
+Jump destinations called from outside:
+ sofError: Called when no start sequence was found.
+ se0: Called when a package has been successfully received.
+ overflow: Called when receive buffer overflows.
+ doReturn: Called after sending data.
+
+Outside jump destinations used by this module:
+ waitForJ: Called to receive an already arriving packet.
+ sendAckAndReti:
+ sendNakAndReti:
+ sendCntAndReti:
+ usbSendAndReti:
+
+The following macros must be defined before this file is included:
+ .macro POP_STANDARD
+ .endm
+ .macro POP_RETI
+ .endm
+*/
+
+#define token x1
+
+overflow:
+ ldi x2, 1<<USB_INTR_PENDING_BIT
+ USB_STORE_PENDING(x2) ; clear any pending interrupts
+ignorePacket:
+ clr token
+ rjmp storeTokenAndReturn
+
+;----------------------------------------------------------------------------
+; Processing of received packet (numbers in brackets are cycles after center of SE0)
+;----------------------------------------------------------------------------
+;This is the only non-error exit point for the software receiver loop
+;we don't check any CRCs here because there is no time left.
+se0:
+ subi cnt, USB_BUFSIZE ;[5]
+ neg cnt ;[6]
+ sub YL, cnt ;[7]
+ sbci YH, 0 ;[8]
+ ldi x2, 1<<USB_INTR_PENDING_BIT ;[9]
+ USB_STORE_PENDING(x2) ;[10] clear pending intr and check flag later. SE0 should be over.
+ ld token, y ;[11]
+ cpi token, USBPID_DATA0 ;[13]
+ breq handleData ;[14]
+ cpi token, USBPID_DATA1 ;[15]
+ breq handleData ;[16]
+ lds shift, usbDeviceAddr;[17]
+ ldd x2, y+1 ;[19] ADDR and 1 bit endpoint number
+ lsl x2 ;[21] shift out 1 bit endpoint number
+ cpse x2, shift ;[22]
+ rjmp ignorePacket ;[23]
+/* only compute endpoint number in x3 if required later */
+#if USB_CFG_HAVE_INTRIN_ENDPOINT || USB_CFG_IMPLEMENT_FN_WRITEOUT
+ ldd x3, y+2 ;[24] endpoint number + crc
+ rol x3 ;[26] shift in LSB of endpoint
+#endif
+ cpi token, USBPID_IN ;[27]
+ breq handleIn ;[28]
+ cpi token, USBPID_SETUP ;[29]
+ breq handleSetupOrOut ;[30]
+ cpi token, USBPID_OUT ;[31]
+ brne ignorePacket ;[32] must be ack, nak or whatever
+; rjmp handleSetupOrOut ; fallthrough
+
+;Setup and Out are followed by a data packet two bit times (16 cycles) after
+;the end of SE0. The sync code allows up to 40 cycles delay from the start of
+;the sync pattern until the first bit is sampled. That's a total of 56 cycles.
+handleSetupOrOut: ;[32]
+#if USB_CFG_IMPLEMENT_FN_WRITEOUT /* if we have data for endpoint != 0, set usbCurrentTok to address */
+ andi x3, 0xf ;[32]
+ breq storeTokenAndReturn ;[33]
+ mov token, x3 ;[34] indicate that this is endpoint x OUT
+#endif
+storeTokenAndReturn:
+ sts usbCurrentTok, token;[35]
+doReturn:
+ POP_STANDARD ;[37] 12...16 cycles
+ USB_LOAD_PENDING(YL) ;[49]
+ sbrc YL, USB_INTR_PENDING_BIT;[50] check whether data is already arriving
+ rjmp waitForJ ;[51] save the pops and pushes -- a new interrupt is already pending
+sofError:
+ POP_RETI ;macro call
+ reti
+
+handleData:
+#if USB_CFG_CHECK_CRC
+ CRC_CLEANUP_AND_CHECK ; jumps to ignorePacket if CRC error
+#endif
+ lds shift, usbCurrentTok;[18]
+ tst shift ;[20]
+ breq doReturn ;[21]
+ lds x2, usbRxLen ;[22]
+ tst x2 ;[24]
+ brne sendNakAndReti ;[25]
+; 2006-03-11: The following two lines fix a problem where the device was not
+; recognized if usbPoll() was called less frequently than once every 4 ms.
+ cpi cnt, 4 ;[26] zero sized data packets are status phase only -- ignore and ack
+ brmi sendAckAndReti ;[27] keep rx buffer clean -- we must not NAK next SETUP
+#if USB_CFG_CHECK_DATA_TOGGLING
+ sts usbCurrentDataToken, token ; store for checking by C code
+#endif
+ sts usbRxLen, cnt ;[28] store received data, swap buffers
+ sts usbRxToken, shift ;[30]
+ lds x2, usbInputBufOffset;[32] swap buffers
+ ldi cnt, USB_BUFSIZE ;[34]
+ sub cnt, x2 ;[35]
+ sts usbInputBufOffset, cnt;[36] buffers now swapped
+ rjmp sendAckAndReti ;[38] 40 + 17 = 57 until SOP
+
+handleIn:
+;We don't send any data as long as the C code has not processed the current
+;input data and potentially updated the output data. That's more efficient
+;in terms of code size than clearing the tx buffers when a packet is received.
+ lds x1, usbRxLen ;[30]
+ cpi x1, 1 ;[32] negative values are flow control, 0 means "buffer free"
+ brge sendNakAndReti ;[33] unprocessed input packet?
+ ldi x1, USBPID_NAK ;[34] prepare value for usbTxLen
+#if USB_CFG_HAVE_INTRIN_ENDPOINT
+ andi x3, 0xf ;[35] x3 contains endpoint
+#if USB_CFG_SUPPRESS_INTR_CODE
+ brne sendNakAndReti ;[36]
+#else
+ brne handleIn1 ;[36]
+#endif
+#endif
+ lds cnt, usbTxLen ;[37]
+ sbrc cnt, 4 ;[39] all handshake tokens have bit 4 set
+ rjmp sendCntAndReti ;[40] 42 + 16 = 58 until SOP
+ sts usbTxLen, x1 ;[41] x1 == USBPID_NAK from above
+ ldi YL, lo8(usbTxBuf) ;[43]
+ ldi YH, hi8(usbTxBuf) ;[44]
+ rjmp usbSendAndReti ;[45] 57 + 12 = 59 until SOP
+
+; Comment about when to set usbTxLen to USBPID_NAK:
+; We should set it back when we receive the ACK from the host. This would
+; be simple to implement: One static variable which stores whether the last
+; tx was for endpoint 0 or 1 and a compare in the receiver to distinguish the
+; ACK. However, we set it back immediately when we send the package,
+; assuming that no error occurs and the host sends an ACK. We save one byte
+; RAM this way and avoid potential problems with endless retries. The rest of
+; the driver assumes error-free transfers anyway.
+
+#if !USB_CFG_SUPPRESS_INTR_CODE && USB_CFG_HAVE_INTRIN_ENDPOINT /* placed here due to relative jump range */
+handleIn1: ;[38]
+#if USB_CFG_HAVE_INTRIN_ENDPOINT3
+; 2006-06-10 as suggested by O.Tamura: support second INTR IN / BULK IN endpoint
+ cpi x3, USB_CFG_EP3_NUMBER;[38]
+ breq handleIn3 ;[39]
+#endif
+ lds cnt, usbTxLen1 ;[40]
+ sbrc cnt, 4 ;[42] all handshake tokens have bit 4 set
+ rjmp sendCntAndReti ;[43] 47 + 16 = 63 until SOP
+ sts usbTxLen1, x1 ;[44] x1 == USBPID_NAK from above
+ ldi YL, lo8(usbTxBuf1) ;[46]
+ ldi YH, hi8(usbTxBuf1) ;[47]
+ rjmp usbSendAndReti ;[48] 50 + 12 = 62 until SOP
+
+#if USB_CFG_HAVE_INTRIN_ENDPOINT3
+handleIn3:
+ lds cnt, usbTxLen3 ;[41]
+ sbrc cnt, 4 ;[43]
+ rjmp sendCntAndReti ;[44] 49 + 16 = 65 until SOP
+ sts usbTxLen3, x1 ;[45] x1 == USBPID_NAK from above
+ ldi YL, lo8(usbTxBuf3) ;[47]
+ ldi YH, hi8(usbTxBuf3) ;[48]
+ rjmp usbSendAndReti ;[49] 51 + 12 = 63 until SOP
+#endif
+#endif
diff --git a/tmk_core/protocol/vusb/usbdrv/oddebug.c b/tmk_core/protocol/vusb/usbdrv/oddebug.c
new file mode 100644
index 000000000..945457c1f
--- /dev/null
+++ b/tmk_core/protocol/vusb/usbdrv/oddebug.c
@@ -0,0 +1,50 @@
+/* Name: oddebug.c
+ * Project: AVR library
+ * Author: Christian Starkjohann
+ * Creation Date: 2005-01-16
+ * Tabsize: 4
+ * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
+ * This Revision: $Id: oddebug.c 692 2008-11-07 15:07:40Z cs $
+ */
+
+#include "oddebug.h"
+
+#if DEBUG_LEVEL > 0
+
+#warning "Never compile production devices with debugging enabled"
+
+static void uartPutc(char c)
+{
+ while(!(ODDBG_USR & (1 << ODDBG_UDRE))); /* wait for data register empty */
+ ODDBG_UDR = c;
+}
+
+static uchar hexAscii(uchar h)
+{
+ h &= 0xf;
+ if(h >= 10)
+ h += 'a' - (uchar)10 - '0';
+ h += '0';
+ return h;
+}
+
+static void printHex(uchar c)
+{
+ uartPutc(hexAscii(c >> 4));
+ uartPutc(hexAscii(c));
+}
+
+void odDebug(uchar prefix, uchar *data, uchar len)
+{
+ printHex(prefix);
+ uartPutc(':');
+ while(len--){
+ uartPutc(' ');
+ printHex(*data++);
+ }
+ uartPutc('\r');
+ uartPutc('\n');
+}
+
+#endif
diff --git a/tmk_core/protocol/vusb/usbdrv/oddebug.h b/tmk_core/protocol/vusb/usbdrv/oddebug.h
new file mode 100644
index 000000000..d61309daa
--- /dev/null
+++ b/tmk_core/protocol/vusb/usbdrv/oddebug.h
@@ -0,0 +1,123 @@
+/* Name: oddebug.h
+ * Project: AVR library
+ * Author: Christian Starkjohann
+ * Creation Date: 2005-01-16
+ * Tabsize: 4
+ * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
+ * This Revision: $Id: oddebug.h 692 2008-11-07 15:07:40Z cs $
+ */
+
+#ifndef __oddebug_h_included__
+#define __oddebug_h_included__
+
+/*
+General Description:
+This module implements a function for debug logs on the serial line of the
+AVR microcontroller. Debugging can be configured with the define
+'DEBUG_LEVEL'. If this macro is not defined or defined to 0, all debugging
+calls are no-ops. If it is 1, DBG1 logs will appear, but not DBG2. If it is
+2, DBG1 and DBG2 logs will be printed.
+
+A debug log consists of a label ('prefix') to indicate which debug log created
+the output and a memory block to dump in hex ('data' and 'len').
+*/
+
+
+#ifndef F_CPU
+# define F_CPU 12000000 /* 12 MHz */
+#endif
+
+/* make sure we have the UART defines: */
+#include "usbportability.h"
+
+#ifndef uchar
+# define uchar unsigned char
+#endif
+
+#if DEBUG_LEVEL > 0 && !(defined TXEN || defined TXEN0) /* no UART in device */
+# warning "Debugging disabled because device has no UART"
+# undef DEBUG_LEVEL
+#endif
+
+#ifndef DEBUG_LEVEL
+# define DEBUG_LEVEL 0
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+#if DEBUG_LEVEL > 0
+# define DBG1(prefix, data, len) odDebug(prefix, data, len)
+#else
+# define DBG1(prefix, data, len)
+#endif
+
+#if DEBUG_LEVEL > 1
+# define DBG2(prefix, data, len) odDebug(prefix, data, len)
+#else
+# define DBG2(prefix, data, len)
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+#if DEBUG_LEVEL > 0
+extern void odDebug(uchar prefix, uchar *data, uchar len);
+
+/* Try to find our control registers; ATMEL likes to rename these */
+
+#if defined UBRR
+# define ODDBG_UBRR UBRR
+#elif defined UBRRL
+# define ODDBG_UBRR UBRRL
+#elif defined UBRR0
+# define ODDBG_UBRR UBRR0
+#elif defined UBRR0L
+# define ODDBG_UBRR UBRR0L
+#endif
+
+#if defined UCR
+# define ODDBG_UCR UCR
+#elif defined UCSRB
+# define ODDBG_UCR UCSRB
+#elif defined UCSR0B
+# define ODDBG_UCR UCSR0B
+#endif
+
+#if defined TXEN
+# define ODDBG_TXEN TXEN
+#else
+# define ODDBG_TXEN TXEN0
+#endif
+
+#if defined USR
+# define ODDBG_USR USR
+#elif defined UCSRA
+# define ODDBG_USR UCSRA
+#elif defined UCSR0A
+# define ODDBG_USR UCSR0A
+#endif
+
+#if defined UDRE
+# define ODDBG_UDRE UDRE
+#else
+# define ODDBG_UDRE UDRE0
+#endif
+
+#if defined UDR
+# define ODDBG_UDR UDR
+#elif defined UDR0
+# define ODDBG_UDR UDR0
+#endif
+
+static inline void odDebugInit(void)
+{
+ ODDBG_UCR |= (1<<ODDBG_TXEN);
+ ODDBG_UBRR = F_CPU / (19200 * 16L) - 1;
+}
+#else
+# define odDebugInit()
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+#endif /* __oddebug_h_included__ */
diff --git a/tmk_core/protocol/vusb/usbdrv/usbconfig-prototype.h b/tmk_core/protocol/vusb/usbdrv/usbconfig-prototype.h
new file mode 100644
index 000000000..847710e2a
--- /dev/null
+++ b/tmk_core/protocol/vusb/usbdrv/usbconfig-prototype.h
@@ -0,0 +1,376 @@
+/* Name: usbconfig.h
+ * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
+ * Author: Christian Starkjohann
+ * Creation Date: 2005-04-01
+ * Tabsize: 4
+ * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
+ * This Revision: $Id: usbconfig-prototype.h 785 2010-05-30 17:57:07Z cs $
+ */
+
+#ifndef __usbconfig_h_included__
+#define __usbconfig_h_included__
+
+/*
+General Description:
+This file is an example configuration (with inline documentation) for the USB
+driver. It configures V-USB for USB D+ connected to Port D bit 2 (which is
+also hardware interrupt 0 on many devices) and USB D- to Port D bit 4. You may
+wire the lines to any other port, as long as D+ is also wired to INT0 (or any
+other hardware interrupt, as long as it is the highest level interrupt, see
+section at the end of this file).
++ To create your own usbconfig.h file, copy this file to your project's
++ firmware source directory) and rename it to "usbconfig.h".
++ Then edit it accordingly.
+*/
+
+/* ---------------------------- Hardware Config ---------------------------- */
+
+#define USB_CFG_IOPORTNAME D
+/* This is the port where the USB bus is connected. When you configure it to
+ * "B", the registers PORTB, PINB and DDRB will be used.
+ */
+#define USB_CFG_DMINUS_BIT 4
+/* This is the bit number in USB_CFG_IOPORT where the USB D- line is connected.
+ * This may be any bit in the port.
+ */
+#define USB_CFG_DPLUS_BIT 2
+/* This is the bit number in USB_CFG_IOPORT where the USB D+ line is connected.
+ * This may be any bit in the port. Please note that D+ must also be connected
+ * to interrupt pin INT0! [You can also use other interrupts, see section
+ * "Optional MCU Description" below, or you can connect D- to the interrupt, as
+ * it is required if you use the USB_COUNT_SOF feature. If you use D- for the
+ * interrupt, the USB interrupt will also be triggered at Start-Of-Frame
+ * markers every millisecond.]
+ */
+#define USB_CFG_CLOCK_KHZ (F_CPU/1000)
+/* Clock rate of the AVR in kHz. Legal values are 12000, 12800, 15000, 16000,
+ * 16500, 18000 and 20000. The 12.8 MHz and 16.5 MHz versions of the code
+ * require no crystal, they tolerate +/- 1% deviation from the nominal
+ * frequency. All other rates require a precision of 2000 ppm and thus a
+ * crystal!
+ * Since F_CPU should be defined to your actual clock rate anyway, you should
+ * not need to modify this setting.
+ */
+#define USB_CFG_CHECK_CRC 0
+/* Define this to 1 if you want that the driver checks integrity of incoming
+ * data packets (CRC checks). CRC checks cost quite a bit of code size and are
+ * currently only available for 18 MHz crystal clock. You must choose
+ * USB_CFG_CLOCK_KHZ = 18000 if you enable this option.
+ */
+
+/* ----------------------- Optional Hardware Config ------------------------ */
+
+/* #define USB_CFG_PULLUP_IOPORTNAME D */
+/* If you connect the 1.5k pullup resistor from D- to a port pin instead of
+ * V+, you can connect and disconnect the device from firmware by calling
+ * the macros usbDeviceConnect() and usbDeviceDisconnect() (see usbdrv.h).
+ * This constant defines the port on which the pullup resistor is connected.
+ */
+/* #define USB_CFG_PULLUP_BIT 4 */
+/* This constant defines the bit number in USB_CFG_PULLUP_IOPORT (defined
+ * above) where the 1.5k pullup resistor is connected. See description
+ * above for details.
+ */
+
+/* --------------------------- Functional Range ---------------------------- */
+
+#define USB_CFG_HAVE_INTRIN_ENDPOINT 0
+/* Define this to 1 if you want to compile a version with two endpoints: The
+ * default control endpoint 0 and an interrupt-in endpoint (any other endpoint
+ * number).
+ */
+#define USB_CFG_HAVE_INTRIN_ENDPOINT3 0
+/* Define this to 1 if you want to compile a version with three endpoints: The
+ * default control endpoint 0, an interrupt-in endpoint 3 (or the number
+ * configured below) and a catch-all default interrupt-in endpoint as above.
+ * You must also define USB_CFG_HAVE_INTRIN_ENDPOINT to 1 for this feature.
+ */
+#define USB_CFG_EP3_NUMBER 3
+/* If the so-called endpoint 3 is used, it can now be configured to any other
+ * endpoint number (except 0) with this macro. Default if undefined is 3.
+ */
+/* #define USB_INITIAL_DATATOKEN USBPID_DATA1 */
+/* The above macro defines the startup condition for data toggling on the
+ * interrupt/bulk endpoints 1 and 3. Defaults to USBPID_DATA1.
+ * Since the token is toggled BEFORE sending any data, the first packet is
+ * sent with the oposite value of this configuration!
+ */
+#define USB_CFG_IMPLEMENT_HALT 0
+/* Define this to 1 if you also want to implement the ENDPOINT_HALT feature
+ * for endpoint 1 (interrupt endpoint). Although you may not need this feature,
+ * it is required by the standard. We have made it a config option because it
+ * bloats the code considerably.
+ */
+#define USB_CFG_SUPPRESS_INTR_CODE 0
+/* Define this to 1 if you want to declare interrupt-in endpoints, but don't
+ * want to send any data over them. If this macro is defined to 1, functions
+ * usbSetInterrupt() and usbSetInterrupt3() are omitted. This is useful if
+ * you need the interrupt-in endpoints in order to comply to an interface
+ * (e.g. HID), but never want to send any data. This option saves a couple
+ * of bytes in flash memory and the transmit buffers in RAM.
+ */
+#define USB_CFG_INTR_POLL_INTERVAL 10
+/* If you compile a version with endpoint 1 (interrupt-in), this is the poll
+ * interval. The value is in milliseconds and must not be less than 10 ms for
+ * low speed devices.
+ */
+#define USB_CFG_IS_SELF_POWERED 0
+/* Define this to 1 if the device has its own power supply. Set it to 0 if the
+ * device is powered from the USB bus.
+ */
+#define USB_CFG_MAX_BUS_POWER 100
+/* Set this variable to the maximum USB bus power consumption of your device.
+ * The value is in milliamperes. [It will be divided by two since USB
+ * communicates power requirements in units of 2 mA.]
+ */
+#define USB_CFG_IMPLEMENT_FN_WRITE 0
+/* Set this to 1 if you want usbFunctionWrite() to be called for control-out
+ * transfers. Set it to 0 if you don't need it and want to save a couple of
+ * bytes.
+ */
+#define USB_CFG_IMPLEMENT_FN_READ 0
+/* Set this to 1 if you need to send control replies which are generated
+ * "on the fly" when usbFunctionRead() is called. If you only want to send
+ * data from a static buffer, set it to 0 and return the data from
+ * usbFunctionSetup(). This saves a couple of bytes.
+ */
+#define USB_CFG_IMPLEMENT_FN_WRITEOUT 0
+/* Define this to 1 if you want to use interrupt-out (or bulk out) endpoints.
+ * You must implement the function usbFunctionWriteOut() which receives all
+ * interrupt/bulk data sent to any endpoint other than 0. The endpoint number
+ * can be found in 'usbRxToken'.
+ */
+#define USB_CFG_HAVE_FLOWCONTROL 0
+/* Define this to 1 if you want flowcontrol over USB data. See the definition
+ * of the macros usbDisableAllRequests() and usbEnableAllRequests() in
+ * usbdrv.h.
+ */
+#define USB_CFG_DRIVER_FLASH_PAGE 0
+/* If the device has more than 64 kBytes of flash, define this to the 64 k page
+ * where the driver's constants (descriptors) are located. Or in other words:
+ * Define this to 1 for boot loaders on the ATMega128.
+ */
+#define USB_CFG_LONG_TRANSFERS 0
+/* Define this to 1 if you want to send/receive blocks of more than 254 bytes
+ * in a single control-in or control-out transfer. Note that the capability
+ * for long transfers increases the driver size.
+ */
+/* #define USB_RX_USER_HOOK(data, len) if(usbRxToken == (uchar)USBPID_SETUP) blinkLED(); */
+/* This macro is a hook if you want to do unconventional things. If it is
+ * defined, it's inserted at the beginning of received message processing.
+ * If you eat the received message and don't want default processing to
+ * proceed, do a return after doing your things. One possible application
+ * (besides debugging) is to flash a status LED on each packet.
+ */
+/* #define USB_RESET_HOOK(resetStarts) if(!resetStarts){hadUsbReset();} */
+/* This macro is a hook if you need to know when an USB RESET occurs. It has
+ * one parameter which distinguishes between the start of RESET state and its
+ * end.
+ */
+/* #define USB_SET_ADDRESS_HOOK() hadAddressAssigned(); */
+/* This macro (if defined) is executed when a USB SET_ADDRESS request was
+ * received.
+ */
+#define USB_COUNT_SOF 0
+/* define this macro to 1 if you need the global variable "usbSofCount" which
+ * counts SOF packets. This feature requires that the hardware interrupt is
+ * connected to D- instead of D+.
+ */
+/* #ifdef __ASSEMBLER__
+ * macro myAssemblerMacro
+ * in YL, TCNT0
+ * sts timer0Snapshot, YL
+ * endm
+ * #endif
+ * #define USB_SOF_HOOK myAssemblerMacro
+ * This macro (if defined) is executed in the assembler module when a
+ * Start Of Frame condition is detected. It is recommended to define it to
+ * the name of an assembler macro which is defined here as well so that more
+ * than one assembler instruction can be used. The macro may use the register
+ * YL and modify SREG. If it lasts longer than a couple of cycles, USB messages
+ * immediately after an SOF pulse may be lost and must be retried by the host.
+ * What can you do with this hook? Since the SOF signal occurs exactly every
+ * 1 ms (unless the host is in sleep mode), you can use it to tune OSCCAL in
+ * designs running on the internal RC oscillator.
+ * Please note that Start Of Frame detection works only if D- is wired to the
+ * interrupt, not D+. THIS IS DIFFERENT THAN MOST EXAMPLES!
+ */
+#define USB_CFG_CHECK_DATA_TOGGLING 0
+/* define this macro to 1 if you want to filter out duplicate data packets
+ * sent by the host. Duplicates occur only as a consequence of communication
+ * errors, when the host does not receive an ACK. Please note that you need to
+ * implement the filtering yourself in usbFunctionWriteOut() and
+ * usbFunctionWrite(). Use the global usbCurrentDataToken and a static variable
+ * for each control- and out-endpoint to check for duplicate packets.
+ */
+#define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 0
+/* define this macro to 1 if you want the function usbMeasureFrameLength()
+ * compiled in. This function can be used to calibrate the AVR's RC oscillator.
+ */
+#define USB_USE_FAST_CRC 0
+/* The assembler module has two implementations for the CRC algorithm. One is
+ * faster, the other is smaller. This CRC routine is only used for transmitted
+ * messages where timing is not critical. The faster routine needs 31 cycles
+ * per byte while the smaller one needs 61 to 69 cycles. The faster routine
+ * may be worth the 32 bytes bigger code size if you transmit lots of data and
+ * run the AVR close to its limit.
+ */
+
+/* -------------------------- Device Description --------------------------- */
+
+#define USB_CFG_VENDOR_ID 0xc0, 0x16 /* = 0x16c0 = 5824 = voti.nl */
+/* USB vendor ID for the device, low byte first. If you have registered your
+ * own Vendor ID, define it here. Otherwise you may use one of obdev's free
+ * shared VID/PID pairs. Be sure to read USB-IDs-for-free.txt for rules!
+ * *** IMPORTANT NOTE ***
+ * This template uses obdev's shared VID/PID pair for Vendor Class devices
+ * with libusb: 0x16c0/0x5dc. Use this VID/PID pair ONLY if you understand
+ * the implications!
+ */
+#define USB_CFG_DEVICE_ID 0xdc, 0x05 /* = 0x05dc = 1500 */
+/* This is the ID of the product, low byte first. It is interpreted in the
+ * scope of the vendor ID. If you have registered your own VID with usb.org
+ * or if you have licensed a PID from somebody else, define it here. Otherwise
+ * you may use one of obdev's free shared VID/PID pairs. See the file
+ * USB-IDs-for-free.txt for details!
+ * *** IMPORTANT NOTE ***
+ * This template uses obdev's shared VID/PID pair for Vendor Class devices
+ * with libusb: 0x16c0/0x5dc. Use this VID/PID pair ONLY if you understand
+ * the implications!
+ */
+#define USB_CFG_DEVICE_VERSION 0x00, 0x01
+/* Version number of the device: Minor number first, then major number.
+ */
+#define USB_CFG_VENDOR_NAME 'o', 'b', 'd', 'e', 'v', '.', 'a', 't'
+#define USB_CFG_VENDOR_NAME_LEN 8
+/* These two values define the vendor name returned by the USB device. The name
+ * must be given as a list of characters under single quotes. The characters
+ * are interpreted as Unicode (UTF-16) entities.
+ * If you don't want a vendor name string, undefine these macros.
+ * ALWAYS define a vendor name containing your Internet domain name if you use
+ * obdev's free shared VID/PID pair. See the file USB-IDs-for-free.txt for
+ * details.
+ */
+#define USB_CFG_DEVICE_NAME 'T', 'e', 'm', 'p', 'l', 'a', 't', 'e'
+#define USB_CFG_DEVICE_NAME_LEN 8
+/* Same as above for the device name. If you don't want a device name, undefine
+ * the macros. See the file USB-IDs-for-free.txt before you assign a name if
+ * you use a shared VID/PID.
+ */
+/*#define USB_CFG_SERIAL_NUMBER 'N', 'o', 'n', 'e' */
+/*#define USB_CFG_SERIAL_NUMBER_LEN 0 */
+/* Same as above for the serial number. If you don't want a serial number,
+ * undefine the macros.
+ * It may be useful to provide the serial number through other means than at
+ * compile time. See the section about descriptor properties below for how
+ * to fine tune control over USB descriptors such as the string descriptor
+ * for the serial number.
+ */
+#define USB_CFG_DEVICE_CLASS 0xff /* set to 0 if deferred to interface */
+#define USB_CFG_DEVICE_SUBCLASS 0
+/* See USB specification if you want to conform to an existing device class.
+ * Class 0xff is "vendor specific".
+ */
+#define USB_CFG_INTERFACE_CLASS 0 /* define class here if not at device level */
+#define USB_CFG_INTERFACE_SUBCLASS 0
+#define USB_CFG_INTERFACE_PROTOCOL 0
+/* See USB specification if you want to conform to an existing device class or
+ * protocol. The following classes must be set at interface level:
+ * HID class is 3, no subclass and protocol required (but may be useful!)
+ * CDC class is 2, use subclass 2 and protocol 1 for ACM
+ */
+/* #define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH 42 */
+/* Define this to the length of the HID report descriptor, if you implement
+ * an HID device. Otherwise don't define it or define it to 0.
+ * If you use this define, you must add a PROGMEM character array named
+ * "usbHidReportDescriptor" to your code which contains the report descriptor.
+ * Don't forget to keep the array and this define in sync!
+ */
+
+/* #define USB_PUBLIC static */
+/* Use the define above if you #include usbdrv.c instead of linking against it.
+ * This technique saves a couple of bytes in flash memory.
+ */
+
+/* ------------------- Fine Control over USB Descriptors ------------------- */
+/* If you don't want to use the driver's default USB descriptors, you can
+ * provide our own. These can be provided as (1) fixed length static data in
+ * flash memory, (2) fixed length static data in RAM or (3) dynamically at
+ * runtime in the function usbFunctionDescriptor(). See usbdrv.h for more
+ * information about this function.
+ * Descriptor handling is configured through the descriptor's properties. If
+ * no properties are defined or if they are 0, the default descriptor is used.
+ * Possible properties are:
+ * + USB_PROP_IS_DYNAMIC: The data for the descriptor should be fetched
+ * at runtime via usbFunctionDescriptor(). If the usbMsgPtr mechanism is
+ * used, the data is in FLASH by default. Add property USB_PROP_IS_RAM if
+ * you want RAM pointers.
+ * + USB_PROP_IS_RAM: The data returned by usbFunctionDescriptor() or found
+ * in static memory is in RAM, not in flash memory.
+ * + USB_PROP_LENGTH(len): If the data is in static memory (RAM or flash),
+ * the driver must know the descriptor's length. The descriptor itself is
+ * found at the address of a well known identifier (see below).
+ * List of static descriptor names (must be declared PROGMEM if in flash):
+ * char usbDescriptorDevice[];
+ * char usbDescriptorConfiguration[];
+ * char usbDescriptorHidReport[];
+ * char usbDescriptorString0[];
+ * int usbDescriptorStringVendor[];
+ * int usbDescriptorStringDevice[];
+ * int usbDescriptorStringSerialNumber[];
+ * Other descriptors can't be provided statically, they must be provided
+ * dynamically at runtime.
+ *
+ * Descriptor properties are or-ed or added together, e.g.:
+ * #define USB_CFG_DESCR_PROPS_DEVICE (USB_PROP_IS_RAM | USB_PROP_LENGTH(18))
+ *
+ * The following descriptors are defined:
+ * USB_CFG_DESCR_PROPS_DEVICE
+ * USB_CFG_DESCR_PROPS_CONFIGURATION
+ * USB_CFG_DESCR_PROPS_STRINGS
+ * USB_CFG_DESCR_PROPS_STRING_0
+ * USB_CFG_DESCR_PROPS_STRING_VENDOR
+ * USB_CFG_DESCR_PROPS_STRING_PRODUCT
+ * USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER
+ * USB_CFG_DESCR_PROPS_HID
+ * USB_CFG_DESCR_PROPS_HID_REPORT
+ * USB_CFG_DESCR_PROPS_UNKNOWN (for all descriptors not handled by the driver)
+ *
+ * Note about string descriptors: String descriptors are not just strings, they
+ * are Unicode strings prefixed with a 2 byte header. Example:
+ * int serialNumberDescriptor[] = {
+ * USB_STRING_DESCRIPTOR_HEADER(6),
+ * 'S', 'e', 'r', 'i', 'a', 'l'
+ * };
+ */
+
+#define USB_CFG_DESCR_PROPS_DEVICE 0
+#define USB_CFG_DESCR_PROPS_CONFIGURATION 0
+#define USB_CFG_DESCR_PROPS_STRINGS 0
+#define USB_CFG_DESCR_PROPS_STRING_0 0
+#define USB_CFG_DESCR_PROPS_STRING_VENDOR 0
+#define USB_CFG_DESCR_PROPS_STRING_PRODUCT 0
+#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER 0
+#define USB_CFG_DESCR_PROPS_HID 0
+#define USB_CFG_DESCR_PROPS_HID_REPORT 0
+#define USB_CFG_DESCR_PROPS_UNKNOWN 0
+
+/* ----------------------- Optional MCU Description ------------------------ */
+
+/* The following configurations have working defaults in usbdrv.h. You
+ * usually don't need to set them explicitly. Only if you want to run
+ * the driver on a device which is not yet supported or with a compiler
+ * which is not fully supported (such as IAR C) or if you use a differnt
+ * interrupt than INT0, you may have to define some of these.
+ */
+/* #define USB_INTR_CFG MCUCR */
+/* #define USB_INTR_CFG_SET ((1 << ISC00) | (1 << ISC01)) */
+/* #define USB_INTR_CFG_CLR 0 */
+/* #define USB_INTR_ENABLE GIMSK */
+/* #define USB_INTR_ENABLE_BIT INT0 */
+/* #define USB_INTR_PENDING GIFR */
+/* #define USB_INTR_PENDING_BIT INTF0 */
+/* #define USB_INTR_VECTOR INT0_vect */
+
+#endif /* __usbconfig_h_included__ */
diff --git a/tmk_core/protocol/vusb/usbdrv/usbdrv.c b/tmk_core/protocol/vusb/usbdrv/usbdrv.c
new file mode 100644
index 000000000..2e8dd8756
--- /dev/null
+++ b/tmk_core/protocol/vusb/usbdrv/usbdrv.c
@@ -0,0 +1,625 @@
+/* Name: usbdrv.c
+ * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
+ * Author: Christian Starkjohann
+ * Creation Date: 2004-12-29
+ * Tabsize: 4
+ * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
+ * This Revision: $Id: usbdrv.c 791 2010-07-15 15:56:13Z cs $
+ */
+
+#include "usbportability.h"
+#include "usbdrv.h"
+#include "oddebug.h"
+
+/*
+General Description:
+This module implements the C-part of the USB driver. See usbdrv.h for a
+documentation of the entire driver.
+*/
+
+/* ------------------------------------------------------------------------- */
+
+/* raw USB registers / interface to assembler code: */
+uchar usbRxBuf[2*USB_BUFSIZE]; /* raw RX buffer: PID, 8 bytes data, 2 bytes CRC */
+uchar usbInputBufOffset; /* offset in usbRxBuf used for low level receiving */
+uchar usbDeviceAddr; /* assigned during enumeration, defaults to 0 */
+uchar usbNewDeviceAddr; /* device ID which should be set after status phase */
+uchar usbConfiguration; /* currently selected configuration. Administered by driver, but not used */
+volatile schar usbRxLen; /* = 0; number of bytes in usbRxBuf; 0 means free, -1 for flow control */
+uchar usbCurrentTok; /* last token received or endpoint number for last OUT token if != 0 */
+uchar usbRxToken; /* token for data we received; or endpont number for last OUT */
+volatile uchar usbTxLen = USBPID_NAK; /* number of bytes to transmit with next IN token or handshake token */
+uchar usbTxBuf[USB_BUFSIZE];/* data to transmit with next IN, free if usbTxLen contains handshake token */
+#if USB_COUNT_SOF
+volatile uchar usbSofCount; /* incremented by assembler module every SOF */
+#endif
+#if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE
+usbTxStatus_t usbTxStatus1;
+# if USB_CFG_HAVE_INTRIN_ENDPOINT3
+usbTxStatus_t usbTxStatus3;
+# endif
+#endif
+#if USB_CFG_CHECK_DATA_TOGGLING
+uchar usbCurrentDataToken;/* when we check data toggling to ignore duplicate packets */
+#endif
+
+/* USB status registers / not shared with asm code */
+uchar *usbMsgPtr; /* data to transmit next -- ROM or RAM address */
+static usbMsgLen_t usbMsgLen = USB_NO_MSG; /* remaining number of bytes */
+static uchar usbMsgFlags; /* flag values see below */
+
+#define USB_FLG_MSGPTR_IS_ROM (1<<6)
+#define USB_FLG_USE_USER_RW (1<<7)
+
+/*
+optimizing hints:
+- do not post/pre inc/dec integer values in operations
+- assign value of USB_READ_FLASH() to register variables and don't use side effects in arg
+- use narrow scope for variables which should be in X/Y/Z register
+- assign char sized expressions to variables to force 8 bit arithmetics
+*/
+
+/* -------------------------- String Descriptors --------------------------- */
+
+#if USB_CFG_DESCR_PROPS_STRINGS == 0
+
+#if USB_CFG_DESCR_PROPS_STRING_0 == 0
+#undef USB_CFG_DESCR_PROPS_STRING_0
+#define USB_CFG_DESCR_PROPS_STRING_0 sizeof(usbDescriptorString0)
+const PROGMEM char usbDescriptorString0[] = { /* language descriptor */
+ 4, /* sizeof(usbDescriptorString0): length of descriptor in bytes */
+ 3, /* descriptor type */
+ 0x09, 0x04, /* language index (0x0409 = US-English) */
+};
+#endif
+
+#if USB_CFG_DESCR_PROPS_STRING_VENDOR == 0 && USB_CFG_VENDOR_NAME_LEN
+#undef USB_CFG_DESCR_PROPS_STRING_VENDOR
+#define USB_CFG_DESCR_PROPS_STRING_VENDOR sizeof(usbDescriptorStringVendor)
+const PROGMEM int usbDescriptorStringVendor[] = {
+ USB_STRING_DESCRIPTOR_HEADER(USB_CFG_VENDOR_NAME_LEN),
+ USB_CFG_VENDOR_NAME
+};
+#endif
+
+#if USB_CFG_DESCR_PROPS_STRING_PRODUCT == 0 && USB_CFG_DEVICE_NAME_LEN
+#undef USB_CFG_DESCR_PROPS_STRING_PRODUCT
+#define USB_CFG_DESCR_PROPS_STRING_PRODUCT sizeof(usbDescriptorStringDevice)
+const PROGMEM int usbDescriptorStringDevice[] = {
+ USB_STRING_DESCRIPTOR_HEADER(USB_CFG_DEVICE_NAME_LEN),
+ USB_CFG_DEVICE_NAME
+};
+#endif
+
+#if USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER == 0 && USB_CFG_SERIAL_NUMBER_LEN
+#undef USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER
+#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER sizeof(usbDescriptorStringSerialNumber)
+PROGMEM int usbDescriptorStringSerialNumber[] = {
+ USB_STRING_DESCRIPTOR_HEADER(USB_CFG_SERIAL_NUMBER_LEN),
+ USB_CFG_SERIAL_NUMBER
+};
+#endif
+
+#endif /* USB_CFG_DESCR_PROPS_STRINGS == 0 */
+
+/* --------------------------- Device Descriptor --------------------------- */
+
+#if USB_CFG_DESCR_PROPS_DEVICE == 0
+#undef USB_CFG_DESCR_PROPS_DEVICE
+#define USB_CFG_DESCR_PROPS_DEVICE sizeof(usbDescriptorDevice)
+const PROGMEM char usbDescriptorDevice[] = { /* USB device descriptor */
+ 18, /* sizeof(usbDescriptorDevice): length of descriptor in bytes */
+ USBDESCR_DEVICE, /* descriptor type */
+ 0x10, 0x01, /* USB version supported */
+ USB_CFG_DEVICE_CLASS,
+ USB_CFG_DEVICE_SUBCLASS,
+ 0, /* protocol */
+ 8, /* max packet size */
+ /* the following two casts affect the first byte of the constant only, but
+ * that's sufficient to avoid a warning with the default values.
+ */
+ (char)USB_CFG_VENDOR_ID,/* 2 bytes */
+ (char)USB_CFG_DEVICE_ID,/* 2 bytes */
+ USB_CFG_DEVICE_VERSION, /* 2 bytes */
+ USB_CFG_DESCR_PROPS_STRING_VENDOR != 0 ? 1 : 0, /* manufacturer string index */
+ USB_CFG_DESCR_PROPS_STRING_PRODUCT != 0 ? 2 : 0, /* product string index */
+ USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER != 0 ? 3 : 0, /* serial number string index */
+ 1, /* number of configurations */
+};
+#endif
+
+/* ----------------------- Configuration Descriptor ------------------------ */
+
+#if USB_CFG_DESCR_PROPS_HID_REPORT != 0 && USB_CFG_DESCR_PROPS_HID == 0
+#undef USB_CFG_DESCR_PROPS_HID
+#define USB_CFG_DESCR_PROPS_HID 9 /* length of HID descriptor in config descriptor below */
+#endif
+
+#if USB_CFG_DESCR_PROPS_CONFIGURATION == 0
+#undef USB_CFG_DESCR_PROPS_CONFIGURATION
+#define USB_CFG_DESCR_PROPS_CONFIGURATION sizeof(usbDescriptorConfiguration)
+PROGMEM char usbDescriptorConfiguration[] = { /* USB configuration descriptor */
+ 9, /* sizeof(usbDescriptorConfiguration): length of descriptor in bytes */
+ USBDESCR_CONFIG, /* descriptor type */
+ 18 + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT3 +
+ (USB_CFG_DESCR_PROPS_HID & 0xff), 0,
+ /* total length of data returned (including inlined descriptors) */
+ 1, /* number of interfaces in this configuration */
+ 1, /* index of this configuration */
+ 0, /* configuration name string index */
+#if USB_CFG_IS_SELF_POWERED
+ (1 << 7) | USBATTR_SELFPOWER, /* attributes */
+#else
+ (1 << 7), /* attributes */
+#endif
+ USB_CFG_MAX_BUS_POWER/2, /* max USB current in 2mA units */
+/* interface descriptor follows inline: */
+ 9, /* sizeof(usbDescrInterface): length of descriptor in bytes */
+ USBDESCR_INTERFACE, /* descriptor type */
+ 0, /* index of this interface */
+ 0, /* alternate setting for this interface */
+ USB_CFG_HAVE_INTRIN_ENDPOINT + USB_CFG_HAVE_INTRIN_ENDPOINT3, /* endpoints excl 0: number of endpoint descriptors to follow */
+ USB_CFG_INTERFACE_CLASS,
+ USB_CFG_INTERFACE_SUBCLASS,
+ USB_CFG_INTERFACE_PROTOCOL,
+ 0, /* string index for interface */
+#if (USB_CFG_DESCR_PROPS_HID & 0xff) /* HID descriptor */
+ 9, /* sizeof(usbDescrHID): length of descriptor in bytes */
+ USBDESCR_HID, /* descriptor type: HID */
+ 0x01, 0x01, /* BCD representation of HID version */
+ 0x00, /* target country code */
+ 0x01, /* number of HID Report (or other HID class) Descriptor infos to follow */
+ 0x22, /* descriptor type: report */
+ USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH, 0, /* total length of report descriptor */
+#endif
+#if USB_CFG_HAVE_INTRIN_ENDPOINT /* endpoint descriptor for endpoint 1 */
+ 7, /* sizeof(usbDescrEndpoint) */
+ USBDESCR_ENDPOINT, /* descriptor type = endpoint */
+ (char)0x81, /* IN endpoint number 1 */
+ 0x03, /* attrib: Interrupt endpoint */
+ 8, 0, /* maximum packet size */
+ USB_CFG_INTR_POLL_INTERVAL, /* in ms */
+#endif
+#if USB_CFG_HAVE_INTRIN_ENDPOINT3 /* endpoint descriptor for endpoint 3 */
+ 7, /* sizeof(usbDescrEndpoint) */
+ USBDESCR_ENDPOINT, /* descriptor type = endpoint */
+ (char)(0x80 | USB_CFG_EP3_NUMBER), /* IN endpoint number 3 */
+ 0x03, /* attrib: Interrupt endpoint */
+ 8, 0, /* maximum packet size */
+ USB_CFG_INTR_POLL_INTERVAL, /* in ms */
+#endif
+};
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+static inline void usbResetDataToggling(void)
+{
+#if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE
+ USB_SET_DATATOKEN1(USB_INITIAL_DATATOKEN); /* reset data toggling for interrupt endpoint */
+# if USB_CFG_HAVE_INTRIN_ENDPOINT3
+ USB_SET_DATATOKEN3(USB_INITIAL_DATATOKEN); /* reset data toggling for interrupt endpoint */
+# endif
+#endif
+}
+
+static inline void usbResetStall(void)
+{
+#if USB_CFG_IMPLEMENT_HALT && USB_CFG_HAVE_INTRIN_ENDPOINT
+ usbTxLen1 = USBPID_NAK;
+#if USB_CFG_HAVE_INTRIN_ENDPOINT3
+ usbTxLen3 = USBPID_NAK;
+#endif
+#endif
+}
+
+/* ------------------------------------------------------------------------- */
+
+#if !USB_CFG_SUPPRESS_INTR_CODE
+#if USB_CFG_HAVE_INTRIN_ENDPOINT
+static void usbGenericSetInterrupt(uchar *data, uchar len, usbTxStatus_t *txStatus)
+{
+uchar *p;
+char i;
+
+#if USB_CFG_IMPLEMENT_HALT
+ if(usbTxLen1 == USBPID_STALL)
+ return;
+#endif
+ if(txStatus->len & 0x10){ /* packet buffer was empty */
+ txStatus->buffer[0] ^= USBPID_DATA0 ^ USBPID_DATA1; /* toggle token */
+ }else{
+ txStatus->len = USBPID_NAK; /* avoid sending outdated (overwritten) interrupt data */
+ }
+ p = txStatus->buffer + 1;
+ i = len;
+ do{ /* if len == 0, we still copy 1 byte, but that's no problem */
+ *p++ = *data++;
+ }while(--i > 0); /* loop control at the end is 2 bytes shorter than at beginning */
+ usbCrc16Append(&txStatus->buffer[1], len);
+ txStatus->len = len + 4; /* len must be given including sync byte */
+ DBG2(0x21 + (((int)txStatus >> 3) & 3), txStatus->buffer, len + 3);
+}
+
+USB_PUBLIC void usbSetInterrupt(uchar *data, uchar len)
+{
+ usbGenericSetInterrupt(data, len, &usbTxStatus1);
+}
+#endif
+
+#if USB_CFG_HAVE_INTRIN_ENDPOINT3
+USB_PUBLIC void usbSetInterrupt3(uchar *data, uchar len)
+{
+ usbGenericSetInterrupt(data, len, &usbTxStatus3);
+}
+#endif
+#endif /* USB_CFG_SUPPRESS_INTR_CODE */
+
+/* ------------------ utilities for code following below ------------------- */
+
+/* Use defines for the switch statement so that we can choose between an
+ * if()else if() and a switch/case based implementation. switch() is more
+ * efficient for a LARGE set of sequential choices, if() is better in all other
+ * cases.
+ */
+#if USB_CFG_USE_SWITCH_STATEMENT
+# define SWITCH_START(cmd) switch(cmd){{
+# define SWITCH_CASE(value) }break; case (value):{
+# define SWITCH_CASE2(v1,v2) }break; case (v1): case(v2):{
+# define SWITCH_CASE3(v1,v2,v3) }break; case (v1): case(v2): case(v3):{
+# define SWITCH_DEFAULT }break; default:{
+# define SWITCH_END }}
+#else
+# define SWITCH_START(cmd) {uchar _cmd = cmd; if(0){
+# define SWITCH_CASE(value) }else if(_cmd == (value)){
+# define SWITCH_CASE2(v1,v2) }else if(_cmd == (v1) || _cmd == (v2)){
+# define SWITCH_CASE3(v1,v2,v3) }else if(_cmd == (v1) || _cmd == (v2) || (_cmd == v3)){
+# define SWITCH_DEFAULT }else{
+# define SWITCH_END }}
+#endif
+
+#ifndef USB_RX_USER_HOOK
+#define USB_RX_USER_HOOK(data, len)
+#endif
+#ifndef USB_SET_ADDRESS_HOOK
+#define USB_SET_ADDRESS_HOOK()
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+/* We use if() instead of #if in the macro below because #if can't be used
+ * in macros and the compiler optimizes constant conditions anyway.
+ * This may cause problems with undefined symbols if compiled without
+ * optimizing!
+ */
+#define GET_DESCRIPTOR(cfgProp, staticName) \
+ if(cfgProp){ \
+ if((cfgProp) & USB_PROP_IS_RAM) \
+ flags = 0; \
+ if((cfgProp) & USB_PROP_IS_DYNAMIC){ \
+ len = usbFunctionDescriptor(rq); \
+ }else{ \
+ len = USB_PROP_LENGTH(cfgProp); \
+ usbMsgPtr = (uchar *)(staticName); \
+ } \
+ }
+
+/* usbDriverDescriptor() is similar to usbFunctionDescriptor(), but used
+ * internally for all types of descriptors.
+ */
+static inline usbMsgLen_t usbDriverDescriptor(usbRequest_t *rq)
+{
+usbMsgLen_t len = 0;
+uchar flags = USB_FLG_MSGPTR_IS_ROM;
+
+ SWITCH_START(rq->wValue.bytes[1])
+ SWITCH_CASE(USBDESCR_DEVICE) /* 1 */
+ GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_DEVICE, usbDescriptorDevice)
+ SWITCH_CASE(USBDESCR_CONFIG) /* 2 */
+ GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_CONFIGURATION, usbDescriptorConfiguration)
+ SWITCH_CASE(USBDESCR_STRING) /* 3 */
+#if USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC
+ if(USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_RAM)
+ flags = 0;
+ len = usbFunctionDescriptor(rq);
+#else /* USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC */
+ SWITCH_START(rq->wValue.bytes[0])
+ SWITCH_CASE(0)
+ GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_0, usbDescriptorString0)
+ SWITCH_CASE(1)
+ GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_VENDOR, usbDescriptorStringVendor)
+ SWITCH_CASE(2)
+ GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_PRODUCT, usbDescriptorStringDevice)
+ SWITCH_CASE(3)
+ GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER, usbDescriptorStringSerialNumber)
+ SWITCH_DEFAULT
+ if(USB_CFG_DESCR_PROPS_UNKNOWN & USB_PROP_IS_DYNAMIC){
+ len = usbFunctionDescriptor(rq);
+ }
+ SWITCH_END
+#endif /* USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC */
+#if USB_CFG_DESCR_PROPS_HID_REPORT /* only support HID descriptors if enabled */
+ SWITCH_CASE(USBDESCR_HID) /* 0x21 */
+ GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_HID, usbDescriptorConfiguration + 18)
+ SWITCH_CASE(USBDESCR_HID_REPORT)/* 0x22 */
+ GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_HID_REPORT, usbDescriptorHidReport)
+#endif
+ SWITCH_DEFAULT
+ if(USB_CFG_DESCR_PROPS_UNKNOWN & USB_PROP_IS_DYNAMIC){
+ len = usbFunctionDescriptor(rq);
+ }
+ SWITCH_END
+ usbMsgFlags = flags;
+ return len;
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* usbDriverSetup() is similar to usbFunctionSetup(), but it's used for
+ * standard requests instead of class and custom requests.
+ */
+static inline usbMsgLen_t usbDriverSetup(usbRequest_t *rq)
+{
+uchar len = 0, *dataPtr = usbTxBuf + 9; /* there are 2 bytes free space at the end of the buffer */
+uchar value = rq->wValue.bytes[0];
+#if USB_CFG_IMPLEMENT_HALT
+uchar index = rq->wIndex.bytes[0];
+#endif
+
+ dataPtr[0] = 0; /* default reply common to USBRQ_GET_STATUS and USBRQ_GET_INTERFACE */
+ SWITCH_START(rq->bRequest)
+ SWITCH_CASE(USBRQ_GET_STATUS) /* 0 */
+ uchar recipient = rq->bmRequestType & USBRQ_RCPT_MASK; /* assign arith ops to variables to enforce byte size */
+ if(USB_CFG_IS_SELF_POWERED && recipient == USBRQ_RCPT_DEVICE)
+ dataPtr[0] = USB_CFG_IS_SELF_POWERED;
+#if USB_CFG_IMPLEMENT_HALT
+ if(recipient == USBRQ_RCPT_ENDPOINT && index == 0x81) /* request status for endpoint 1 */
+ dataPtr[0] = usbTxLen1 == USBPID_STALL;
+#endif
+ dataPtr[1] = 0;
+ len = 2;
+#if USB_CFG_IMPLEMENT_HALT
+ SWITCH_CASE2(USBRQ_CLEAR_FEATURE, USBRQ_SET_FEATURE) /* 1, 3 */
+ if(value == 0 && index == 0x81){ /* feature 0 == HALT for endpoint == 1 */
+ usbTxLen1 = rq->bRequest == USBRQ_CLEAR_FEATURE ? USBPID_NAK : USBPID_STALL;
+ usbResetDataToggling();
+ }
+#endif
+ SWITCH_CASE(USBRQ_SET_ADDRESS) /* 5 */
+ usbNewDeviceAddr = value;
+ USB_SET_ADDRESS_HOOK();
+ SWITCH_CASE(USBRQ_GET_DESCRIPTOR) /* 6 */
+ len = usbDriverDescriptor(rq);
+ goto skipMsgPtrAssignment;
+ SWITCH_CASE(USBRQ_GET_CONFIGURATION) /* 8 */
+ dataPtr = &usbConfiguration; /* send current configuration value */
+ len = 1;
+ SWITCH_CASE(USBRQ_SET_CONFIGURATION) /* 9 */
+ usbConfiguration = value;
+ usbResetStall();
+ SWITCH_CASE(USBRQ_GET_INTERFACE) /* 10 */
+ len = 1;
+#if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE
+ SWITCH_CASE(USBRQ_SET_INTERFACE) /* 11 */
+ usbResetDataToggling();
+ usbResetStall();
+#endif
+ SWITCH_DEFAULT /* 7=SET_DESCRIPTOR, 12=SYNC_FRAME */
+ /* Should we add an optional hook here? */
+ SWITCH_END
+ usbMsgPtr = dataPtr;
+skipMsgPtrAssignment:
+ return len;
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* usbProcessRx() is called for every message received by the interrupt
+ * routine. It distinguishes between SETUP and DATA packets and processes
+ * them accordingly.
+ */
+static inline void usbProcessRx(uchar *data, uchar len)
+{
+usbRequest_t *rq = (void *)data;
+
+/* usbRxToken can be:
+ * 0x2d 00101101 (USBPID_SETUP for setup data)
+ * 0xe1 11100001 (USBPID_OUT: data phase of setup transfer)
+ * 0...0x0f for OUT on endpoint X
+ */
+ DBG2(0x10 + (usbRxToken & 0xf), data, len + 2); /* SETUP=1d, SETUP-DATA=11, OUTx=1x */
+ USB_RX_USER_HOOK(data, len)
+#if USB_CFG_IMPLEMENT_FN_WRITEOUT
+ if(usbRxToken < 0x10){ /* OUT to endpoint != 0: endpoint number in usbRxToken */
+ usbFunctionWriteOut(data, len);
+ return;
+ }
+#endif
+ if(usbRxToken == (uchar)USBPID_SETUP){
+ if(len != 8) /* Setup size must be always 8 bytes. Ignore otherwise. */
+ return;
+ usbMsgLen_t replyLen;
+ usbTxBuf[0] = USBPID_DATA0; /* initialize data toggling */
+ usbTxLen = USBPID_NAK; /* abort pending transmit */
+ usbMsgFlags = 0;
+ uchar type = rq->bmRequestType & USBRQ_TYPE_MASK;
+ if(type != USBRQ_TYPE_STANDARD){ /* standard requests are handled by driver */
+ replyLen = usbFunctionSetup(data);
+ }else{
+ replyLen = usbDriverSetup(rq);
+ }
+#if USB_CFG_IMPLEMENT_FN_READ || USB_CFG_IMPLEMENT_FN_WRITE
+ if(replyLen == USB_NO_MSG){ /* use user-supplied read/write function */
+ /* do some conditioning on replyLen, but on IN transfers only */
+ if((rq->bmRequestType & USBRQ_DIR_MASK) != USBRQ_DIR_HOST_TO_DEVICE){
+ if(sizeof(replyLen) < sizeof(rq->wLength.word)){ /* help compiler with optimizing */
+ replyLen = rq->wLength.bytes[0];
+ }else{
+ replyLen = rq->wLength.word;
+ }
+ }
+ usbMsgFlags = USB_FLG_USE_USER_RW;
+ }else /* The 'else' prevents that we limit a replyLen of USB_NO_MSG to the maximum transfer len. */
+#endif
+ if(sizeof(replyLen) < sizeof(rq->wLength.word)){ /* help compiler with optimizing */
+ if(!rq->wLength.bytes[1] && replyLen > rq->wLength.bytes[0]) /* limit length to max */
+ replyLen = rq->wLength.bytes[0];
+ }else{
+ if(replyLen > rq->wLength.word) /* limit length to max */
+ replyLen = rq->wLength.word;
+ }
+ usbMsgLen = replyLen;
+ }else{ /* usbRxToken must be USBPID_OUT, which means data phase of setup (control-out) */
+#if USB_CFG_IMPLEMENT_FN_WRITE
+ if(usbMsgFlags & USB_FLG_USE_USER_RW){
+ uchar rval = usbFunctionWrite(data, len);
+ if(rval == 0xff){ /* an error occurred */
+ usbTxLen = USBPID_STALL;
+ }else if(rval != 0){ /* This was the final package */
+ usbMsgLen = 0; /* answer with a zero-sized data packet */
+ }
+ }
+#endif
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* This function is similar to usbFunctionRead(), but it's also called for
+ * data handled automatically by the driver (e.g. descriptor reads).
+ */
+static uchar usbDeviceRead(uchar *data, uchar len)
+{
+ if(len > 0){ /* don't bother app with 0 sized reads */
+#if USB_CFG_IMPLEMENT_FN_READ
+ if(usbMsgFlags & USB_FLG_USE_USER_RW){
+ len = usbFunctionRead(data, len);
+ }else
+#endif
+ {
+ uchar i = len, *r = usbMsgPtr;
+ if(usbMsgFlags & USB_FLG_MSGPTR_IS_ROM){ /* ROM data */
+ do{
+ uchar c = USB_READ_FLASH(r); /* assign to char size variable to enforce byte ops */
+ *data++ = c;
+ r++;
+ }while(--i);
+ }else{ /* RAM data */
+ do{
+ *data++ = *r++;
+ }while(--i);
+ }
+ usbMsgPtr = r;
+ }
+ }
+ return len;
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* usbBuildTxBlock() is called when we have data to transmit and the
+ * interrupt routine's transmit buffer is empty.
+ */
+static inline void usbBuildTxBlock(void)
+{
+usbMsgLen_t wantLen;
+uchar len;
+
+ wantLen = usbMsgLen;
+ if(wantLen > 8)
+ wantLen = 8;
+ usbMsgLen -= wantLen;
+ usbTxBuf[0] ^= USBPID_DATA0 ^ USBPID_DATA1; /* DATA toggling */
+ len = usbDeviceRead(usbTxBuf + 1, wantLen);
+ if(len <= 8){ /* valid data packet */
+ usbCrc16Append(&usbTxBuf[1], len);
+ len += 4; /* length including sync byte */
+ if(len < 12) /* a partial package identifies end of message */
+ usbMsgLen = USB_NO_MSG;
+ }else{
+ len = USBPID_STALL; /* stall the endpoint */
+ usbMsgLen = USB_NO_MSG;
+ }
+ usbTxLen = len;
+ DBG2(0x20, usbTxBuf, len-1);
+}
+
+/* ------------------------------------------------------------------------- */
+
+static inline void usbHandleResetHook(uchar notResetState)
+{
+#ifdef USB_RESET_HOOK
+static uchar wasReset;
+uchar isReset = !notResetState;
+
+ if(wasReset != isReset){
+ USB_RESET_HOOK(isReset);
+ wasReset = isReset;
+ }
+#endif
+}
+
+/* ------------------------------------------------------------------------- */
+
+USB_PUBLIC void usbPoll(void)
+{
+schar len;
+uchar i;
+
+ len = usbRxLen - 3;
+ if(len >= 0){
+/* We could check CRC16 here -- but ACK has already been sent anyway. If you
+ * need data integrity checks with this driver, check the CRC in your app
+ * code and report errors back to the host. Since the ACK was already sent,
+ * retries must be handled on application level.
+ * unsigned crc = usbCrc16(buffer + 1, usbRxLen - 3);
+ */
+ usbProcessRx(usbRxBuf + USB_BUFSIZE + 1 - usbInputBufOffset, len);
+#if USB_CFG_HAVE_FLOWCONTROL
+ if(usbRxLen > 0) /* only mark as available if not inactivated */
+ usbRxLen = 0;
+#else
+ usbRxLen = 0; /* mark rx buffer as available */
+#endif
+ }
+ if(usbTxLen & 0x10){ /* transmit system idle */
+ if(usbMsgLen != USB_NO_MSG){ /* transmit data pending? */
+ usbBuildTxBlock();
+ }
+ }
+ for(i = 20; i > 0; i--){
+ uchar usbLineStatus = USBIN & USBMASK;
+ if(usbLineStatus != 0) /* SE0 has ended */
+ goto isNotReset;
+ }
+ /* RESET condition, called multiple times during reset */
+ usbNewDeviceAddr = 0;
+ usbDeviceAddr = 0;
+ usbResetStall();
+ DBG1(0xff, 0, 0);
+isNotReset:
+ usbHandleResetHook(i);
+}
+
+/* ------------------------------------------------------------------------- */
+
+USB_PUBLIC void usbInit(void)
+{
+#if USB_INTR_CFG_SET != 0
+ USB_INTR_CFG |= USB_INTR_CFG_SET;
+#endif
+#if USB_INTR_CFG_CLR != 0
+ USB_INTR_CFG &= ~(USB_INTR_CFG_CLR);
+#endif
+ USB_INTR_ENABLE |= (1 << USB_INTR_ENABLE_BIT);
+ usbResetDataToggling();
+#if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE
+ usbTxLen1 = USBPID_NAK;
+#if USB_CFG_HAVE_INTRIN_ENDPOINT3
+ usbTxLen3 = USBPID_NAK;
+#endif
+#endif
+}
+
+/* ------------------------------------------------------------------------- */
diff --git a/tmk_core/protocol/vusb/usbdrv/usbdrv.h b/tmk_core/protocol/vusb/usbdrv/usbdrv.h
new file mode 100644
index 000000000..42fe16372
--- /dev/null
+++ b/tmk_core/protocol/vusb/usbdrv/usbdrv.h
@@ -0,0 +1,735 @@
+/* Name: usbdrv.h
+ * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
+ * Author: Christian Starkjohann
+ * Creation Date: 2004-12-29
+ * Tabsize: 4
+ * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
+ * This Revision: $Id: usbdrv.h 793 2010-07-15 15:58:11Z cs $
+ */
+
+#ifndef __usbdrv_h_included__
+#define __usbdrv_h_included__
+#include "usbconfig.h"
+#include "usbportability.h"
+
+/*
+Hardware Prerequisites:
+=======================
+USB lines D+ and D- MUST be wired to the same I/O port. We recommend that D+
+triggers the interrupt (best achieved by using INT0 for D+), but it is also
+possible to trigger the interrupt from D-. If D- is used, interrupts are also
+triggered by SOF packets. D- requires a pull-up of 1.5k to +3.5V (and the
+device must be powered at 3.5V) to identify as low-speed USB device. A
+pull-down or pull-up of 1M SHOULD be connected from D+ to +3.5V to prevent
+interference when no USB master is connected. If you use Zener diodes to limit
+the voltage on D+ and D-, you MUST use a pull-down resistor, not a pull-up.
+We use D+ as interrupt source and not D- because it does not trigger on
+keep-alive and RESET states. If you want to count keep-alive events with
+USB_COUNT_SOF, you MUST use D- as an interrupt source.
+
+As a compile time option, the 1.5k pull-up resistor on D- can be made
+switchable to allow the device to disconnect at will. See the definition of
+usbDeviceConnect() and usbDeviceDisconnect() further down in this file.
+
+Please adapt the values in usbconfig.h according to your hardware!
+
+The device MUST be clocked at exactly 12 MHz, 15 MHz, 16 MHz or 20 MHz
+or at 12.8 MHz resp. 16.5 MHz +/- 1%. See usbconfig-prototype.h for details.
+
+
+Limitations:
+============
+Robustness with respect to communication errors:
+The driver assumes error-free communication. It DOES check for errors in
+the PID, but does NOT check bit stuffing errors, SE0 in middle of a byte,
+token CRC (5 bit) and data CRC (16 bit). CRC checks can not be performed due
+to timing constraints: We must start sending a reply within 7 bit times.
+Bit stuffing and misplaced SE0 would have to be checked in real-time, but CPU
+performance does not permit that. The driver does not check Data0/Data1
+toggling, but application software can implement the check.
+
+Input characteristics:
+Since no differential receiver circuit is used, electrical interference
+robustness may suffer. The driver samples only one of the data lines with
+an ordinary I/O pin's input characteristics. However, since this is only a
+low speed USB implementation and the specification allows for 8 times the
+bit rate over the same hardware, we should be on the safe side. Even the spec
+requires detection of asymmetric states at high bit rate for SE0 detection.
+
+Number of endpoints:
+The driver supports the following endpoints:
+
+- Endpoint 0, the default control endpoint.
+- Any number of interrupt- or bulk-out endpoints. The data is sent to
+ usbFunctionWriteOut() and USB_CFG_IMPLEMENT_FN_WRITEOUT must be defined
+ to 1 to activate this feature. The endpoint number can be found in the
+ global variable 'usbRxToken'.
+- One default interrupt- or bulk-in endpoint. This endpoint is used for
+ interrupt- or bulk-in transfers which are not handled by any other endpoint.
+ You must define USB_CFG_HAVE_INTRIN_ENDPOINT in order to activate this
+ feature and call usbSetInterrupt() to send interrupt/bulk data.
+- One additional interrupt- or bulk-in endpoint. This was endpoint 3 in
+ previous versions of this driver but can now be configured to any endpoint
+ number. You must define USB_CFG_HAVE_INTRIN_ENDPOINT3 in order to activate
+ this feature and call usbSetInterrupt3() to send interrupt/bulk data. The
+ endpoint number can be set with USB_CFG_EP3_NUMBER.
+
+Please note that the USB standard forbids bulk endpoints for low speed devices!
+Most operating systems allow them anyway, but the AVR will spend 90% of the CPU
+time in the USB interrupt polling for bulk data.
+
+Maximum data payload:
+Data payload of control in and out transfers may be up to 254 bytes. In order
+to accept payload data of out transfers, you need to implement
+'usbFunctionWrite()'.
+
+USB Suspend Mode supply current:
+The USB standard limits power consumption to 500uA when the bus is in suspend
+mode. This is not a problem for self-powered devices since they don't need
+bus power anyway. Bus-powered devices can achieve this only by putting the
+CPU in sleep mode. The driver does not implement suspend handling by itself.
+However, the application may implement activity monitoring and wakeup from
+sleep. The host sends regular SE0 states on the bus to keep it active. These
+SE0 states can be detected by using D- as the interrupt source. Define
+USB_COUNT_SOF to 1 and use the global variable usbSofCount to check for bus
+activity.
+
+Operation without an USB master:
+The driver behaves neutral without connection to an USB master if D- reads
+as 1. To avoid spurious interrupts, we recommend a high impedance (e.g. 1M)
+pull-down or pull-up resistor on D+ (interrupt). If Zener diodes are used,
+use a pull-down. If D- becomes statically 0, the driver may block in the
+interrupt routine.
+
+Interrupt latency:
+The application must ensure that the USB interrupt is not disabled for more
+than 25 cycles (this is for 12 MHz, faster clocks allow longer latency).
+This implies that all interrupt routines must either have the "ISR_NOBLOCK"
+attribute set (see "avr/interrupt.h") or be written in assembler with "sei"
+as the first instruction.
+
+Maximum interrupt duration / CPU cycle consumption:
+The driver handles all USB communication during the interrupt service
+routine. The routine will not return before an entire USB message is received
+and the reply is sent. This may be up to ca. 1200 cycles @ 12 MHz (= 100us) if
+the host conforms to the standard. The driver will consume CPU cycles for all
+USB messages, even if they address another (low-speed) device on the same bus.
+
+*/
+
+/* ------------------------------------------------------------------------- */
+/* --------------------------- Module Interface ---------------------------- */
+/* ------------------------------------------------------------------------- */
+
+#define USBDRV_VERSION 20100715
+/* This define uniquely identifies a driver version. It is a decimal number
+ * constructed from the driver's release date in the form YYYYMMDD. If the
+ * driver's behavior or interface changes, you can use this constant to
+ * distinguish versions. If it is not defined, the driver's release date is
+ * older than 2006-01-25.
+ */
+
+
+#ifndef USB_PUBLIC
+#define USB_PUBLIC
+#endif
+/* USB_PUBLIC is used as declaration attribute for all functions exported by
+ * the USB driver. The default is no attribute (see above). You may define it
+ * to static either in usbconfig.h or from the command line if you include
+ * usbdrv.c instead of linking against it. Including the C module of the driver
+ * directly in your code saves a couple of bytes in flash memory.
+ */
+
+#ifndef __ASSEMBLER__
+#ifndef uchar
+#define uchar unsigned char
+#endif
+#ifndef schar
+#define schar signed char
+#endif
+/* shortcuts for well defined 8 bit integer types */
+
+#if USB_CFG_LONG_TRANSFERS /* if more than 254 bytes transfer size required */
+# define usbMsgLen_t unsigned
+#else
+# define usbMsgLen_t uchar
+#endif
+/* usbMsgLen_t is the data type used for transfer lengths. By default, it is
+ * defined to uchar, allowing a maximum of 254 bytes (255 is reserved for
+ * USB_NO_MSG below). If the usbconfig.h defines USB_CFG_LONG_TRANSFERS to 1,
+ * a 16 bit data type is used, allowing up to 16384 bytes (the rest is used
+ * for flags in the descriptor configuration).
+ */
+#define USB_NO_MSG ((usbMsgLen_t)-1) /* constant meaning "no message" */
+
+struct usbRequest; /* forward declaration */
+
+USB_PUBLIC void usbInit(void);
+/* This function must be called before interrupts are enabled and the main
+ * loop is entered. We exepct that the PORT and DDR bits for D+ and D- have
+ * not been changed from their default status (which is 0). If you have changed
+ * them, set both back to 0 (configure them as input with no internal pull-up).
+ */
+USB_PUBLIC void usbPoll(void);
+/* This function must be called at regular intervals from the main loop.
+ * Maximum delay between calls is somewhat less than 50ms (USB timeout for
+ * accepting a Setup message). Otherwise the device will not be recognized.
+ * Please note that debug outputs through the UART take ~ 0.5ms per byte
+ * at 19200 bps.
+ */
+extern uchar *usbMsgPtr;
+/* This variable may be used to pass transmit data to the driver from the
+ * implementation of usbFunctionWrite(). It is also used internally by the
+ * driver for standard control requests.
+ */
+USB_PUBLIC usbMsgLen_t usbFunctionSetup(uchar data[8]);
+/* This function is called when the driver receives a SETUP transaction from
+ * the host which is not answered by the driver itself (in practice: class and
+ * vendor requests). All control transfers start with a SETUP transaction where
+ * the host communicates the parameters of the following (optional) data
+ * transfer. The SETUP data is available in the 'data' parameter which can
+ * (and should) be casted to 'usbRequest_t *' for a more user-friendly access
+ * to parameters.
+ *
+ * If the SETUP indicates a control-in transfer, you should provide the
+ * requested data to the driver. There are two ways to transfer this data:
+ * (1) Set the global pointer 'usbMsgPtr' to the base of the static RAM data
+ * block and return the length of the data in 'usbFunctionSetup()'. The driver
+ * will handle the rest. Or (2) return USB_NO_MSG in 'usbFunctionSetup()'. The
+ * driver will then call 'usbFunctionRead()' when data is needed. See the
+ * documentation for usbFunctionRead() for details.
+ *
+ * If the SETUP indicates a control-out transfer, the only way to receive the
+ * data from the host is through the 'usbFunctionWrite()' call. If you
+ * implement this function, you must return USB_NO_MSG in 'usbFunctionSetup()'
+ * to indicate that 'usbFunctionWrite()' should be used. See the documentation
+ * of this function for more information. If you just want to ignore the data
+ * sent by the host, return 0 in 'usbFunctionSetup()'.
+ *
+ * Note that calls to the functions usbFunctionRead() and usbFunctionWrite()
+ * are only done if enabled by the configuration in usbconfig.h.
+ */
+USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq);
+/* You need to implement this function ONLY if you provide USB descriptors at
+ * runtime (which is an expert feature). It is very similar to
+ * usbFunctionSetup() above, but it is called only to request USB descriptor
+ * data. See the documentation of usbFunctionSetup() above for more info.
+ */
+#if USB_CFG_HAVE_INTRIN_ENDPOINT
+USB_PUBLIC void usbSetInterrupt(uchar *data, uchar len);
+/* This function sets the message which will be sent during the next interrupt
+ * IN transfer. The message is copied to an internal buffer and must not exceed
+ * a length of 8 bytes. The message may be 0 bytes long just to indicate the
+ * interrupt status to the host.
+ * If you need to transfer more bytes, use a control read after the interrupt.
+ */
+#define usbInterruptIsReady() (usbTxLen1 & 0x10)
+/* This macro indicates whether the last interrupt message has already been
+ * sent. If you set a new interrupt message before the old was sent, the
+ * message already buffered will be lost.
+ */
+#if USB_CFG_HAVE_INTRIN_ENDPOINT3
+USB_PUBLIC void usbSetInterrupt3(uchar *data, uchar len);
+#define usbInterruptIsReady3() (usbTxLen3 & 0x10)
+/* Same as above for endpoint 3 */
+#endif
+#endif /* USB_CFG_HAVE_INTRIN_ENDPOINT */
+#if USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH /* simplified interface for backward compatibility */
+#define usbHidReportDescriptor usbDescriptorHidReport
+/* should be declared as: PROGMEM char usbHidReportDescriptor[]; */
+/* If you implement an HID device, you need to provide a report descriptor.
+ * The HID report descriptor syntax is a bit complex. If you understand how
+ * report descriptors are constructed, we recommend that you use the HID
+ * Descriptor Tool from usb.org, see http://www.usb.org/developers/hidpage/.
+ * Otherwise you should probably start with a working example.
+ */
+#endif /* USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH */
+#if USB_CFG_IMPLEMENT_FN_WRITE
+USB_PUBLIC uchar usbFunctionWrite(uchar *data, uchar len);
+/* This function is called by the driver to provide a control transfer's
+ * payload data (control-out). It is called in chunks of up to 8 bytes. The
+ * total count provided in the current control transfer can be obtained from
+ * the 'length' property in the setup data. If an error occurred during
+ * processing, return 0xff (== -1). The driver will answer the entire transfer
+ * with a STALL token in this case. If you have received the entire payload
+ * successfully, return 1. If you expect more data, return 0. If you don't
+ * know whether the host will send more data (you should know, the total is
+ * provided in the usbFunctionSetup() call!), return 1.
+ * NOTE: If you return 0xff for STALL, 'usbFunctionWrite()' may still be called
+ * for the remaining data. You must continue to return 0xff for STALL in these
+ * calls.
+ * In order to get usbFunctionWrite() called, define USB_CFG_IMPLEMENT_FN_WRITE
+ * to 1 in usbconfig.h and return 0xff in usbFunctionSetup()..
+ */
+#endif /* USB_CFG_IMPLEMENT_FN_WRITE */
+#if USB_CFG_IMPLEMENT_FN_READ
+USB_PUBLIC uchar usbFunctionRead(uchar *data, uchar len);
+/* This function is called by the driver to ask the application for a control
+ * transfer's payload data (control-in). It is called in chunks of up to 8
+ * bytes each. You should copy the data to the location given by 'data' and
+ * return the actual number of bytes copied. If you return less than requested,
+ * the control-in transfer is terminated. If you return 0xff, the driver aborts
+ * the transfer with a STALL token.
+ * In order to get usbFunctionRead() called, define USB_CFG_IMPLEMENT_FN_READ
+ * to 1 in usbconfig.h and return 0xff in usbFunctionSetup()..
+ */
+#endif /* USB_CFG_IMPLEMENT_FN_READ */
+
+extern uchar usbRxToken; /* may be used in usbFunctionWriteOut() below */
+#if USB_CFG_IMPLEMENT_FN_WRITEOUT
+USB_PUBLIC void usbFunctionWriteOut(uchar *data, uchar len);
+/* This function is called by the driver when data is received on an interrupt-
+ * or bulk-out endpoint. The endpoint number can be found in the global
+ * variable usbRxToken. You must define USB_CFG_IMPLEMENT_FN_WRITEOUT to 1 in
+ * usbconfig.h to get this function called.
+ */
+#endif /* USB_CFG_IMPLEMENT_FN_WRITEOUT */
+#ifdef USB_CFG_PULLUP_IOPORTNAME
+#define usbDeviceConnect() ((USB_PULLUP_DDR |= (1<<USB_CFG_PULLUP_BIT)), \
+ (USB_PULLUP_OUT |= (1<<USB_CFG_PULLUP_BIT)))
+#define usbDeviceDisconnect() ((USB_PULLUP_DDR &= ~(1<<USB_CFG_PULLUP_BIT)), \
+ (USB_PULLUP_OUT &= ~(1<<USB_CFG_PULLUP_BIT)))
+#else /* USB_CFG_PULLUP_IOPORTNAME */
+#define usbDeviceConnect() (USBDDR &= ~(1<<USBMINUS))
+#define usbDeviceDisconnect() (USBDDR |= (1<<USBMINUS))
+#endif /* USB_CFG_PULLUP_IOPORTNAME */
+/* The macros usbDeviceConnect() and usbDeviceDisconnect() (intended to look
+ * like a function) connect resp. disconnect the device from the host's USB.
+ * If the constants USB_CFG_PULLUP_IOPORT and USB_CFG_PULLUP_BIT are defined
+ * in usbconfig.h, a disconnect consists of removing the pull-up resisitor
+ * from D-, otherwise the disconnect is done by brute-force pulling D- to GND.
+ * This does not conform to the spec, but it works.
+ * Please note that the USB interrupt must be disabled while the device is
+ * in disconnected state, or the interrupt handler will hang! You can either
+ * turn off the USB interrupt selectively with
+ * USB_INTR_ENABLE &= ~(1 << USB_INTR_ENABLE_BIT)
+ * or use cli() to disable interrupts globally.
+ */
+extern unsigned usbCrc16(unsigned data, uchar len);
+#define usbCrc16(data, len) usbCrc16((unsigned)(data), len)
+/* This function calculates the binary complement of the data CRC used in
+ * USB data packets. The value is used to build raw transmit packets.
+ * You may want to use this function for data checksums or to verify received
+ * data. We enforce 16 bit calling conventions for compatibility with IAR's
+ * tiny memory model.
+ */
+extern unsigned usbCrc16Append(unsigned data, uchar len);
+#define usbCrc16Append(data, len) usbCrc16Append((unsigned)(data), len)
+/* This function is equivalent to usbCrc16() above, except that it appends
+ * the 2 bytes CRC (lowbyte first) in the 'data' buffer after reading 'len'
+ * bytes.
+ */
+#if USB_CFG_HAVE_MEASURE_FRAME_LENGTH
+extern unsigned usbMeasureFrameLength(void);
+/* This function MUST be called IMMEDIATELY AFTER USB reset and measures 1/7 of
+ * the number of CPU cycles during one USB frame minus one low speed bit
+ * length. In other words: return value = 1499 * (F_CPU / 10.5 MHz)
+ * Since this is a busy wait, you MUST disable all interrupts with cli() before
+ * calling this function.
+ * This can be used to calibrate the AVR's RC oscillator.
+ */
+#endif
+extern uchar usbConfiguration;
+/* This value contains the current configuration set by the host. The driver
+ * allows setting and querying of this variable with the USB SET_CONFIGURATION
+ * and GET_CONFIGURATION requests, but does not use it otherwise.
+ * You may want to reflect the "configured" status with a LED on the device or
+ * switch on high power parts of the circuit only if the device is configured.
+ */
+#if USB_COUNT_SOF
+extern volatile uchar usbSofCount;
+/* This variable is incremented on every SOF packet. It is only available if
+ * the macro USB_COUNT_SOF is defined to a value != 0.
+ */
+#endif
+#if USB_CFG_CHECK_DATA_TOGGLING
+extern uchar usbCurrentDataToken;
+/* This variable can be checked in usbFunctionWrite() and usbFunctionWriteOut()
+ * to ignore duplicate packets.
+ */
+#endif
+
+#define USB_STRING_DESCRIPTOR_HEADER(stringLength) ((2*(stringLength)+2) | (3<<8))
+/* This macro builds a descriptor header for a string descriptor given the
+ * string's length. See usbdrv.c for an example how to use it.
+ */
+#if USB_CFG_HAVE_FLOWCONTROL
+extern volatile schar usbRxLen;
+#define usbDisableAllRequests() usbRxLen = -1
+/* Must be called from usbFunctionWrite(). This macro disables all data input
+ * from the USB interface. Requests from the host are answered with a NAK
+ * while they are disabled.
+ */
+#define usbEnableAllRequests() usbRxLen = 0
+/* May only be called if requests are disabled. This macro enables input from
+ * the USB interface after it has been disabled with usbDisableAllRequests().
+ */
+#define usbAllRequestsAreDisabled() (usbRxLen < 0)
+/* Use this macro to find out whether requests are disabled. It may be needed
+ * to ensure that usbEnableAllRequests() is never called when requests are
+ * enabled.
+ */
+#endif
+
+#define USB_SET_DATATOKEN1(token) usbTxBuf1[0] = token
+#define USB_SET_DATATOKEN3(token) usbTxBuf3[0] = token
+/* These two macros can be used by application software to reset data toggling
+ * for interrupt-in endpoints 1 and 3. Since the token is toggled BEFORE
+ * sending data, you must set the opposite value of the token which should come
+ * first.
+ */
+
+#endif /* __ASSEMBLER__ */
+
+
+/* ------------------------------------------------------------------------- */
+/* ----------------- Definitions for Descriptor Properties ----------------- */
+/* ------------------------------------------------------------------------- */
+/* This is advanced stuff. See usbconfig-prototype.h for more information
+ * about the various methods to define USB descriptors. If you do nothing,
+ * the default descriptors will be used.
+ */
+#define USB_PROP_IS_DYNAMIC (1 << 14)
+/* If this property is set for a descriptor, usbFunctionDescriptor() will be
+ * used to obtain the particular descriptor. Data directly returned via
+ * usbMsgPtr are FLASH data by default, combine (OR) with USB_PROP_IS_RAM to
+ * return RAM data.
+ */
+#define USB_PROP_IS_RAM (1 << 15)
+/* If this property is set for a descriptor, the data is read from RAM
+ * memory instead of Flash. The property is used for all methods to provide
+ * external descriptors.
+ */
+#define USB_PROP_LENGTH(len) ((len) & 0x3fff)
+/* If a static external descriptor is used, this is the total length of the
+ * descriptor in bytes.
+ */
+
+/* all descriptors which may have properties: */
+#ifndef USB_CFG_DESCR_PROPS_DEVICE
+#define USB_CFG_DESCR_PROPS_DEVICE 0
+#endif
+#ifndef USB_CFG_DESCR_PROPS_CONFIGURATION
+#define USB_CFG_DESCR_PROPS_CONFIGURATION 0
+#endif
+#ifndef USB_CFG_DESCR_PROPS_STRINGS
+#define USB_CFG_DESCR_PROPS_STRINGS 0
+#endif
+#ifndef USB_CFG_DESCR_PROPS_STRING_0
+#define USB_CFG_DESCR_PROPS_STRING_0 0
+#endif
+#ifndef USB_CFG_DESCR_PROPS_STRING_VENDOR
+#define USB_CFG_DESCR_PROPS_STRING_VENDOR 0
+#endif
+#ifndef USB_CFG_DESCR_PROPS_STRING_PRODUCT
+#define USB_CFG_DESCR_PROPS_STRING_PRODUCT 0
+#endif
+#ifndef USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER
+#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER 0
+#endif
+#ifndef USB_CFG_DESCR_PROPS_HID
+#define USB_CFG_DESCR_PROPS_HID 0
+#endif
+#if !(USB_CFG_DESCR_PROPS_HID_REPORT)
+# undef USB_CFG_DESCR_PROPS_HID_REPORT
+# if USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH /* do some backward compatibility tricks */
+# define USB_CFG_DESCR_PROPS_HID_REPORT USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH
+# else
+# define USB_CFG_DESCR_PROPS_HID_REPORT 0
+# endif
+#endif
+#ifndef USB_CFG_DESCR_PROPS_UNKNOWN
+#define USB_CFG_DESCR_PROPS_UNKNOWN 0
+#endif
+
+/* ------------------ forward declaration of descriptors ------------------- */
+/* If you use external static descriptors, they must be stored in global
+ * arrays as declared below:
+ */
+#ifndef __ASSEMBLER__
+extern
+#if !(USB_CFG_DESCR_PROPS_DEVICE & USB_PROP_IS_RAM)
+PROGMEM
+#endif
+const char usbDescriptorDevice[];
+
+extern
+#if !(USB_CFG_DESCR_PROPS_CONFIGURATION & USB_PROP_IS_RAM)
+PROGMEM
+#endif
+const char usbDescriptorConfiguration[];
+
+extern
+#if !(USB_CFG_DESCR_PROPS_HID_REPORT & USB_PROP_IS_RAM)
+PROGMEM
+#endif
+const char usbDescriptorHidReport[];
+
+extern
+#if !(USB_CFG_DESCR_PROPS_STRING_0 & USB_PROP_IS_RAM)
+PROGMEM
+#endif
+const char usbDescriptorString0[];
+
+extern
+#if !(USB_CFG_DESCR_PROPS_STRING_VENDOR & USB_PROP_IS_RAM)
+PROGMEM
+#endif
+const int usbDescriptorStringVendor[];
+
+extern
+#if !(USB_CFG_DESCR_PROPS_STRING_PRODUCT & USB_PROP_IS_RAM)
+PROGMEM
+#endif
+const int usbDescriptorStringDevice[];
+
+extern
+#if !(USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER & USB_PROP_IS_RAM)
+PROGMEM
+#endif
+const int usbDescriptorStringSerialNumber[];
+
+#endif /* __ASSEMBLER__ */
+
+/* ------------------------------------------------------------------------- */
+/* ------------------------ General Purpose Macros ------------------------- */
+/* ------------------------------------------------------------------------- */
+
+#define USB_CONCAT(a, b) a ## b
+#define USB_CONCAT_EXPANDED(a, b) USB_CONCAT(a, b)
+
+#define USB_OUTPORT(name) USB_CONCAT(PORT, name)
+#define USB_INPORT(name) USB_CONCAT(PIN, name)
+#define USB_DDRPORT(name) USB_CONCAT(DDR, name)
+/* The double-define trick above lets us concatenate strings which are
+ * defined by macros.
+ */
+
+/* ------------------------------------------------------------------------- */
+/* ------------------------- Constant definitions -------------------------- */
+/* ------------------------------------------------------------------------- */
+
+#if !defined __ASSEMBLER__ && (!defined USB_CFG_VENDOR_ID || !defined USB_CFG_DEVICE_ID)
+#warning "You should define USB_CFG_VENDOR_ID and USB_CFG_DEVICE_ID in usbconfig.h"
+/* If the user has not defined IDs, we default to obdev's free IDs.
+ * See USB-IDs-for-free.txt for details.
+ */
+#endif
+
+/* make sure we have a VID and PID defined, byte order is lowbyte, highbyte */
+#ifndef USB_CFG_VENDOR_ID
+# define USB_CFG_VENDOR_ID 0xc0, 0x16 /* = 0x16c0 = 5824 = voti.nl */
+#endif
+
+#ifndef USB_CFG_DEVICE_ID
+# if USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH
+# define USB_CFG_DEVICE_ID 0xdf, 0x05 /* = 0x5df = 1503, shared PID for HIDs */
+# elif USB_CFG_INTERFACE_CLASS == 2
+# define USB_CFG_DEVICE_ID 0xe1, 0x05 /* = 0x5e1 = 1505, shared PID for CDC Modems */
+# else
+# define USB_CFG_DEVICE_ID 0xdc, 0x05 /* = 0x5dc = 1500, obdev's free PID */
+# endif
+#endif
+
+/* Derive Output, Input and DataDirection ports from port names */
+#ifndef USB_CFG_IOPORTNAME
+#error "You must define USB_CFG_IOPORTNAME in usbconfig.h, see usbconfig-prototype.h"
+#endif
+
+#define USBOUT USB_OUTPORT(USB_CFG_IOPORTNAME)
+#define USB_PULLUP_OUT USB_OUTPORT(USB_CFG_PULLUP_IOPORTNAME)
+#define USBIN USB_INPORT(USB_CFG_IOPORTNAME)
+#define USBDDR USB_DDRPORT(USB_CFG_IOPORTNAME)
+#define USB_PULLUP_DDR USB_DDRPORT(USB_CFG_PULLUP_IOPORTNAME)
+
+#define USBMINUS USB_CFG_DMINUS_BIT
+#define USBPLUS USB_CFG_DPLUS_BIT
+#define USBIDLE (1<<USB_CFG_DMINUS_BIT) /* value representing J state */
+#define USBMASK ((1<<USB_CFG_DPLUS_BIT) | (1<<USB_CFG_DMINUS_BIT)) /* mask for USB I/O bits */
+
+/* defines for backward compatibility with older driver versions: */
+#define USB_CFG_IOPORT USB_OUTPORT(USB_CFG_IOPORTNAME)
+#ifdef USB_CFG_PULLUP_IOPORTNAME
+#define USB_CFG_PULLUP_IOPORT USB_OUTPORT(USB_CFG_PULLUP_IOPORTNAME)
+#endif
+
+#ifndef USB_CFG_EP3_NUMBER /* if not defined in usbconfig.h */
+#define USB_CFG_EP3_NUMBER 3
+#endif
+
+#ifndef USB_CFG_HAVE_INTRIN_ENDPOINT3
+#define USB_CFG_HAVE_INTRIN_ENDPOINT3 0
+#endif
+
+#define USB_BUFSIZE 11 /* PID, 8 bytes data, 2 bytes CRC */
+
+/* ----- Try to find registers and bits responsible for ext interrupt 0 ----- */
+
+#ifndef USB_INTR_CFG /* allow user to override our default */
+# if defined EICRA
+# define USB_INTR_CFG EICRA
+# else
+# define USB_INTR_CFG MCUCR
+# endif
+#endif
+#ifndef USB_INTR_CFG_SET /* allow user to override our default */
+# if defined(USB_COUNT_SOF) || defined(USB_SOF_HOOK)
+# define USB_INTR_CFG_SET (1 << ISC01) /* cfg for falling edge */
+ /* If any SOF logic is used, the interrupt must be wired to D- where
+ * we better trigger on falling edge
+ */
+# else
+# define USB_INTR_CFG_SET ((1 << ISC00) | (1 << ISC01)) /* cfg for rising edge */
+# endif
+#endif
+#ifndef USB_INTR_CFG_CLR /* allow user to override our default */
+# define USB_INTR_CFG_CLR 0 /* no bits to clear */
+#endif
+
+#ifndef USB_INTR_ENABLE /* allow user to override our default */
+# if defined GIMSK
+# define USB_INTR_ENABLE GIMSK
+# elif defined EIMSK
+# define USB_INTR_ENABLE EIMSK
+# else
+# define USB_INTR_ENABLE GICR
+# endif
+#endif
+#ifndef USB_INTR_ENABLE_BIT /* allow user to override our default */
+# define USB_INTR_ENABLE_BIT INT0
+#endif
+
+#ifndef USB_INTR_PENDING /* allow user to override our default */
+# if defined EIFR
+# define USB_INTR_PENDING EIFR
+# else
+# define USB_INTR_PENDING GIFR
+# endif
+#endif
+#ifndef USB_INTR_PENDING_BIT /* allow user to override our default */
+# define USB_INTR_PENDING_BIT INTF0
+#endif
+
+/*
+The defines above don't work for the following chips
+at90c8534: no ISC0?, no PORTB, can't find a data sheet
+at86rf401: no PORTB, no MCUCR etc, low clock rate
+atmega103: no ISC0? (maybe omission in header, can't find data sheet)
+atmega603: not defined in avr-libc
+at43usb320, at43usb355, at76c711: have USB anyway
+at94k: is different...
+
+at90s1200, attiny11, attiny12, attiny15, attiny28: these have no RAM
+*/
+
+/* ------------------------------------------------------------------------- */
+/* ----------------- USB Specification Constants and Types ----------------- */
+/* ------------------------------------------------------------------------- */
+
+/* USB Token values */
+#define USBPID_SETUP 0x2d
+#define USBPID_OUT 0xe1
+#define USBPID_IN 0x69
+#define USBPID_DATA0 0xc3
+#define USBPID_DATA1 0x4b
+
+#define USBPID_ACK 0xd2
+#define USBPID_NAK 0x5a
+#define USBPID_STALL 0x1e
+
+#ifndef USB_INITIAL_DATATOKEN
+#define USB_INITIAL_DATATOKEN USBPID_DATA1
+#endif
+
+#ifndef __ASSEMBLER__
+
+typedef struct usbTxStatus{
+ volatile uchar len;
+ uchar buffer[USB_BUFSIZE];
+}usbTxStatus_t;
+
+extern usbTxStatus_t usbTxStatus1, usbTxStatus3;
+#define usbTxLen1 usbTxStatus1.len
+#define usbTxBuf1 usbTxStatus1.buffer
+#define usbTxLen3 usbTxStatus3.len
+#define usbTxBuf3 usbTxStatus3.buffer
+
+
+typedef union usbWord{
+ unsigned word;
+ uchar bytes[2];
+}usbWord_t;
+
+typedef struct usbRequest{
+ uchar bmRequestType;
+ uchar bRequest;
+ usbWord_t wValue;
+ usbWord_t wIndex;
+ usbWord_t wLength;
+}usbRequest_t;
+/* This structure matches the 8 byte setup request */
+#endif
+
+/* bmRequestType field in USB setup:
+ * d t t r r r r r, where
+ * d ..... direction: 0=host->device, 1=device->host
+ * t ..... type: 0=standard, 1=class, 2=vendor, 3=reserved
+ * r ..... recipient: 0=device, 1=interface, 2=endpoint, 3=other
+ */
+
+/* USB setup recipient values */
+#define USBRQ_RCPT_MASK 0x1f
+#define USBRQ_RCPT_DEVICE 0
+#define USBRQ_RCPT_INTERFACE 1
+#define USBRQ_RCPT_ENDPOINT 2
+
+/* USB request type values */
+#define USBRQ_TYPE_MASK 0x60
+#define USBRQ_TYPE_STANDARD (0<<5)
+#define USBRQ_TYPE_CLASS (1<<5)
+#define USBRQ_TYPE_VENDOR (2<<5)
+
+/* USB direction values: */
+#define USBRQ_DIR_MASK 0x80
+#define USBRQ_DIR_HOST_TO_DEVICE (0<<7)
+#define USBRQ_DIR_DEVICE_TO_HOST (1<<7)
+
+/* USB Standard Requests */
+#define USBRQ_GET_STATUS 0
+#define USBRQ_CLEAR_FEATURE 1
+#define USBRQ_SET_FEATURE 3
+#define USBRQ_SET_ADDRESS 5
+#define USBRQ_GET_DESCRIPTOR 6
+#define USBRQ_SET_DESCRIPTOR 7
+#define USBRQ_GET_CONFIGURATION 8
+#define USBRQ_SET_CONFIGURATION 9
+#define USBRQ_GET_INTERFACE 10
+#define USBRQ_SET_INTERFACE 11
+#define USBRQ_SYNCH_FRAME 12
+
+/* USB descriptor constants */
+#define USBDESCR_DEVICE 1
+#define USBDESCR_CONFIG 2
+#define USBDESCR_STRING 3
+#define USBDESCR_INTERFACE 4
+#define USBDESCR_ENDPOINT 5
+#define USBDESCR_HID 0x21
+#define USBDESCR_HID_REPORT 0x22
+#define USBDESCR_HID_PHYS 0x23
+
+//#define USBATTR_BUSPOWER 0x80 // USB 1.1 does not define this value any more
+#define USBATTR_SELFPOWER 0x40
+#define USBATTR_REMOTEWAKE 0x20
+
+/* USB HID Requests */
+#define USBRQ_HID_GET_REPORT 0x01
+#define USBRQ_HID_GET_IDLE 0x02
+#define USBRQ_HID_GET_PROTOCOL 0x03
+#define USBRQ_HID_SET_REPORT 0x09
+#define USBRQ_HID_SET_IDLE 0x0a
+#define USBRQ_HID_SET_PROTOCOL 0x0b
+
+/* ------------------------------------------------------------------------- */
+
+#endif /* __usbdrv_h_included__ */
diff --git a/tmk_core/protocol/vusb/usbdrv/usbdrvasm.S b/tmk_core/protocol/vusb/usbdrv/usbdrvasm.S
new file mode 100644
index 000000000..45fcf1831
--- /dev/null
+++ b/tmk_core/protocol/vusb/usbdrv/usbdrvasm.S
@@ -0,0 +1,393 @@
+/* Name: usbdrvasm.S
+ * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
+ * Author: Christian Starkjohann
+ * Creation Date: 2007-06-13
+ * Tabsize: 4
+ * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
+ * Revision: $Id: usbdrvasm.S 785 2010-05-30 17:57:07Z cs $
+ */
+
+/*
+General Description:
+This module is the assembler part of the USB driver. This file contains
+general code (preprocessor acrobatics and CRC computation) and then includes
+the file appropriate for the given clock rate.
+*/
+
+#define __SFR_OFFSET 0 /* used by avr-libc's register definitions */
+#include "usbportability.h"
+#include "usbdrv.h" /* for common defs */
+
+/* register names */
+#define x1 r16
+#define x2 r17
+#define shift r18
+#define cnt r19
+#define x3 r20
+#define x4 r21
+#define x5 r22
+#define bitcnt x5
+#define phase x4
+#define leap x4
+
+/* Some assembler dependent definitions and declarations: */
+
+#ifdef __IAR_SYSTEMS_ASM__
+ extern usbRxBuf, usbDeviceAddr, usbNewDeviceAddr, usbInputBufOffset
+ extern usbCurrentTok, usbRxLen, usbRxToken, usbTxLen
+ extern usbTxBuf, usbTxStatus1, usbTxStatus3
+# if USB_COUNT_SOF
+ extern usbSofCount
+# endif
+ public usbCrc16
+ public usbCrc16Append
+
+ COMMON INTVEC
+# ifndef USB_INTR_VECTOR
+ ORG INT0_vect
+# else /* USB_INTR_VECTOR */
+ ORG USB_INTR_VECTOR
+# undef USB_INTR_VECTOR
+# endif /* USB_INTR_VECTOR */
+# define USB_INTR_VECTOR usbInterruptHandler
+ rjmp USB_INTR_VECTOR
+ RSEG CODE
+
+#else /* __IAR_SYSTEMS_ASM__ */
+
+# ifndef USB_INTR_VECTOR /* default to hardware interrupt INT0 */
+# ifdef INT0_vect
+# define USB_INTR_VECTOR INT0_vect // this is the "new" define for the vector
+# else
+# define USB_INTR_VECTOR SIG_INTERRUPT0 // this is the "old" vector
+# endif
+# endif
+ .text
+ .global USB_INTR_VECTOR
+ .type USB_INTR_VECTOR, @function
+ .global usbCrc16
+ .global usbCrc16Append
+#endif /* __IAR_SYSTEMS_ASM__ */
+
+
+#if USB_INTR_PENDING < 0x40 /* This is an I/O address, use in and out */
+# define USB_LOAD_PENDING(reg) in reg, USB_INTR_PENDING
+# define USB_STORE_PENDING(reg) out USB_INTR_PENDING, reg
+#else /* It's a memory address, use lds and sts */
+# define USB_LOAD_PENDING(reg) lds reg, USB_INTR_PENDING
+# define USB_STORE_PENDING(reg) sts USB_INTR_PENDING, reg
+#endif
+
+#define usbTxLen1 usbTxStatus1
+#define usbTxBuf1 (usbTxStatus1 + 1)
+#define usbTxLen3 usbTxStatus3
+#define usbTxBuf3 (usbTxStatus3 + 1)
+
+
+;----------------------------------------------------------------------------
+; Utility functions
+;----------------------------------------------------------------------------
+
+#ifdef __IAR_SYSTEMS_ASM__
+/* Register assignments for usbCrc16 on IAR cc */
+/* Calling conventions on IAR:
+ * First parameter passed in r16/r17, second in r18/r19 and so on.
+ * Callee must preserve r4-r15, r24-r29 (r28/r29 is frame pointer)
+ * Result is passed in r16/r17
+ * In case of the "tiny" memory model, pointers are only 8 bit with no
+ * padding. We therefore pass argument 1 as "16 bit unsigned".
+ */
+RTMODEL "__rt_version", "3"
+/* The line above will generate an error if cc calling conventions change.
+ * The value "3" above is valid for IAR 4.10B/W32
+ */
+# define argLen r18 /* argument 2 */
+# define argPtrL r16 /* argument 1 */
+# define argPtrH r17 /* argument 1 */
+
+# define resCrcL r16 /* result */
+# define resCrcH r17 /* result */
+
+# define ptrL ZL
+# define ptrH ZH
+# define ptr Z
+# define byte r22
+# define bitCnt r19
+# define polyL r20
+# define polyH r21
+# define scratch r23
+
+#else /* __IAR_SYSTEMS_ASM__ */
+/* Register assignments for usbCrc16 on gcc */
+/* Calling conventions on gcc:
+ * First parameter passed in r24/r25, second in r22/23 and so on.
+ * Callee must preserve r1-r17, r28/r29
+ * Result is passed in r24/r25
+ */
+# define argLen r22 /* argument 2 */
+# define argPtrL r24 /* argument 1 */
+# define argPtrH r25 /* argument 1 */
+
+# define resCrcL r24 /* result */
+# define resCrcH r25 /* result */
+
+# define ptrL XL
+# define ptrH XH
+# define ptr x
+# define byte r18
+# define bitCnt r19
+# define polyL r20
+# define polyH r21
+# define scratch r23
+
+#endif
+
+#if USB_USE_FAST_CRC
+
+; This implementation is faster, but has bigger code size
+; Thanks to Slawomir Fras (BoskiDialer) for this code!
+; It implements the following C pseudo-code:
+; unsigned table(unsigned char x)
+; {
+; unsigned value;
+;
+; value = (unsigned)x << 6;
+; value ^= (unsigned)x << 7;
+; if(parity(x))
+; value ^= 0xc001;
+; return value;
+; }
+; unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen)
+; {
+; unsigned crc = 0xffff;
+;
+; while(argLen--)
+; crc = table(lo8(crc) ^ *argPtr++) ^ hi8(crc);
+; return ~crc;
+; }
+
+; extern unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen);
+; argPtr r24+25 / r16+r17
+; argLen r22 / r18
+; temp variables:
+; byte r18 / r22
+; scratch r23
+; resCrc r24+r25 / r16+r17
+; ptr X / Z
+usbCrc16:
+ mov ptrL, argPtrL
+ mov ptrH, argPtrH
+ ldi resCrcL, 0xFF
+ ldi resCrcH, 0xFF
+ rjmp usbCrc16LoopTest
+usbCrc16ByteLoop:
+ ld byte, ptr+
+ eor resCrcL, byte ; resCrcL is now 'x' in table()
+ mov byte, resCrcL ; compute parity of 'x'
+ swap byte
+ eor byte, resCrcL
+ mov scratch, byte
+ lsr byte
+ lsr byte
+ eor byte, scratch
+ inc byte
+ lsr byte
+ andi byte, 1 ; byte is now parity(x)
+ mov scratch, resCrcL
+ mov resCrcL, resCrcH
+ eor resCrcL, byte ; low byte of if(parity(x)) value ^= 0xc001;
+ neg byte
+ andi byte, 0xc0
+ mov resCrcH, byte ; high byte of if(parity(x)) value ^= 0xc001;
+ clr byte
+ lsr scratch
+ ror byte
+ eor resCrcH, scratch
+ eor resCrcL, byte
+ lsr scratch
+ ror byte
+ eor resCrcH, scratch
+ eor resCrcL, byte
+usbCrc16LoopTest:
+ subi argLen, 1
+ brsh usbCrc16ByteLoop
+ com resCrcL
+ com resCrcH
+ ret
+
+#else /* USB_USE_FAST_CRC */
+
+; This implementation is slower, but has less code size
+;
+; extern unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen);
+; argPtr r24+25 / r16+r17
+; argLen r22 / r18
+; temp variables:
+; byte r18 / r22
+; bitCnt r19
+; poly r20+r21
+; scratch r23
+; resCrc r24+r25 / r16+r17
+; ptr X / Z
+usbCrc16:
+ mov ptrL, argPtrL
+ mov ptrH, argPtrH
+ ldi resCrcL, 0
+ ldi resCrcH, 0
+ ldi polyL, lo8(0xa001)
+ ldi polyH, hi8(0xa001)
+ com argLen ; argLen = -argLen - 1: modified loop to ensure that carry is set
+ ldi bitCnt, 0 ; loop counter with starnd condition = end condition
+ rjmp usbCrcLoopEntry
+usbCrcByteLoop:
+ ld byte, ptr+
+ eor resCrcL, byte
+usbCrcBitLoop:
+ ror resCrcH ; carry is always set here (see brcs jumps to here)
+ ror resCrcL
+ brcs usbCrcNoXor
+ eor resCrcL, polyL
+ eor resCrcH, polyH
+usbCrcNoXor:
+ subi bitCnt, 224 ; (8 * 224) % 256 = 0; this loop iterates 8 times
+ brcs usbCrcBitLoop
+usbCrcLoopEntry:
+ subi argLen, -1
+ brcs usbCrcByteLoop
+usbCrcReady:
+ ret
+; Thanks to Reimar Doeffinger for optimizing this CRC routine!
+
+#endif /* USB_USE_FAST_CRC */
+
+; extern unsigned usbCrc16Append(unsigned char *data, unsigned char len);
+usbCrc16Append:
+ rcall usbCrc16
+ st ptr+, resCrcL
+ st ptr+, resCrcH
+ ret
+
+#undef argLen
+#undef argPtrL
+#undef argPtrH
+#undef resCrcL
+#undef resCrcH
+#undef ptrL
+#undef ptrH
+#undef ptr
+#undef byte
+#undef bitCnt
+#undef polyL
+#undef polyH
+#undef scratch
+
+
+#if USB_CFG_HAVE_MEASURE_FRAME_LENGTH
+#ifdef __IAR_SYSTEMS_ASM__
+/* Register assignments for usbMeasureFrameLength on IAR cc */
+/* Calling conventions on IAR:
+ * First parameter passed in r16/r17, second in r18/r19 and so on.
+ * Callee must preserve r4-r15, r24-r29 (r28/r29 is frame pointer)
+ * Result is passed in r16/r17
+ * In case of the "tiny" memory model, pointers are only 8 bit with no
+ * padding. We therefore pass argument 1 as "16 bit unsigned".
+ */
+# define resL r16
+# define resH r17
+# define cnt16L r30
+# define cnt16H r31
+# define cntH r18
+
+#else /* __IAR_SYSTEMS_ASM__ */
+/* Register assignments for usbMeasureFrameLength on gcc */
+/* Calling conventions on gcc:
+ * First parameter passed in r24/r25, second in r22/23 and so on.
+ * Callee must preserve r1-r17, r28/r29
+ * Result is passed in r24/r25
+ */
+# define resL r24
+# define resH r25
+# define cnt16L r24
+# define cnt16H r25
+# define cntH r26
+#endif
+# define cnt16 cnt16L
+
+; extern unsigned usbMeasurePacketLength(void);
+; returns time between two idle strobes in multiples of 7 CPU clocks
+.global usbMeasureFrameLength
+usbMeasureFrameLength:
+ ldi cntH, 6 ; wait ~ 10 ms for D- == 0
+ clr cnt16L
+ clr cnt16H
+usbMFTime16:
+ dec cntH
+ breq usbMFTimeout
+usbMFWaitStrobe: ; first wait for D- == 0 (idle strobe)
+ sbiw cnt16, 1 ;[0] [6]
+ breq usbMFTime16 ;[2]
+ sbic USBIN, USBMINUS ;[3]
+ rjmp usbMFWaitStrobe ;[4]
+usbMFWaitIdle: ; then wait until idle again
+ sbis USBIN, USBMINUS ;1 wait for D- == 1
+ rjmp usbMFWaitIdle ;2
+ ldi cnt16L, 1 ;1 represents cycles so far
+ clr cnt16H ;1
+usbMFWaitLoop:
+ in cntH, USBIN ;[0] [7]
+ adiw cnt16, 1 ;[1]
+ breq usbMFTimeout ;[3]
+ andi cntH, USBMASK ;[4]
+ brne usbMFWaitLoop ;[5]
+usbMFTimeout:
+#if resL != cnt16L
+ mov resL, cnt16L
+ mov resH, cnt16H
+#endif
+ ret
+
+#undef resL
+#undef resH
+#undef cnt16
+#undef cnt16L
+#undef cnt16H
+#undef cntH
+
+#endif /* USB_CFG_HAVE_MEASURE_FRAME_LENGTH */
+
+;----------------------------------------------------------------------------
+; Now include the clock rate specific code
+;----------------------------------------------------------------------------
+
+#ifndef USB_CFG_CLOCK_KHZ
+# ifdef F_CPU
+# define USB_CFG_CLOCK_KHZ (F_CPU/1000)
+# else
+# error "USB_CFG_CLOCK_KHZ not defined in usbconfig.h and no F_CPU set!"
+# endif
+#endif
+
+#if USB_CFG_CHECK_CRC /* separate dispatcher for CRC type modules */
+# if USB_CFG_CLOCK_KHZ == 18000
+# include "usbdrvasm18-crc.inc"
+# else
+# error "USB_CFG_CLOCK_KHZ is not one of the supported crc-rates!"
+# endif
+#else /* USB_CFG_CHECK_CRC */
+# if USB_CFG_CLOCK_KHZ == 12000
+# include "usbdrvasm12.inc"
+# elif USB_CFG_CLOCK_KHZ == 12800
+# include "usbdrvasm128.inc"
+# elif USB_CFG_CLOCK_KHZ == 15000
+# include "usbdrvasm15.inc"
+# elif USB_CFG_CLOCK_KHZ == 16000
+# include "usbdrvasm16.inc"
+# elif USB_CFG_CLOCK_KHZ == 16500
+# include "usbdrvasm165.inc"
+# elif USB_CFG_CLOCK_KHZ == 20000
+# include "usbdrvasm20.inc"
+# else
+# error "USB_CFG_CLOCK_KHZ is not one of the supported non-crc-rates!"
+# endif
+#endif /* USB_CFG_CHECK_CRC */
diff --git a/tmk_core/protocol/vusb/usbdrv/usbdrvasm.asm b/tmk_core/protocol/vusb/usbdrv/usbdrvasm.asm
new file mode 100644
index 000000000..9cc4e4d73
--- /dev/null
+++ b/tmk_core/protocol/vusb/usbdrv/usbdrvasm.asm
@@ -0,0 +1,21 @@
+/* Name: usbdrvasm.asm
+ * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
+ * Author: Christian Starkjohann
+ * Creation Date: 2006-03-01
+ * Tabsize: 4
+ * Copyright: (c) 2006 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
+ * This Revision: $Id$
+ */
+
+/*
+General Description:
+The IAR compiler/assembler system prefers assembler files with file extension
+".asm". We simply provide this file as an alias for usbdrvasm.S.
+
+Thanks to Oleg Semyonov for his help with the IAR tools port!
+*/
+
+#include "usbdrvasm.S"
+
+end
diff --git a/tmk_core/protocol/vusb/usbdrv/usbdrvasm12.inc b/tmk_core/protocol/vusb/usbdrv/usbdrvasm12.inc
new file mode 100644
index 000000000..c1167584c
--- /dev/null
+++ b/tmk_core/protocol/vusb/usbdrv/usbdrvasm12.inc
@@ -0,0 +1,393 @@
+/* Name: usbdrvasm12.inc
+ * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
+ * Author: Christian Starkjohann
+ * Creation Date: 2004-12-29
+ * Tabsize: 4
+ * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
+ * This Revision: $Id: usbdrvasm12.inc 740 2009-04-13 18:23:31Z cs $
+ */
+
+/* Do not link this file! Link usbdrvasm.S instead, which includes the
+ * appropriate implementation!
+ */
+
+/*
+General Description:
+This file is the 12 MHz version of the asssembler part of the USB driver. It
+requires a 12 MHz crystal (not a ceramic resonator and not a calibrated RC
+oscillator).
+
+See usbdrv.h for a description of the entire driver.
+
+Since almost all of this code is timing critical, don't change unless you
+really know what you are doing! Many parts require not only a maximum number
+of CPU cycles, but even an exact number of cycles!
+
+
+Timing constraints according to spec (in bit times):
+timing subject min max CPUcycles
+---------------------------------------------------------------------------
+EOP of OUT/SETUP to sync pattern of DATA0 (both rx) 2 16 16-128
+EOP of IN to sync pattern of DATA0 (rx, then tx) 2 7.5 16-60
+DATAx (rx) to ACK/NAK/STALL (tx) 2 7.5 16-60
+*/
+
+;Software-receiver engine. Strict timing! Don't change unless you can preserve timing!
+;interrupt response time: 4 cycles + insn running = 7 max if interrupts always enabled
+;max allowable interrupt latency: 34 cycles -> max 25 cycles interrupt disable
+;max stack usage: [ret(2), YL, SREG, YH, shift, x1, x2, x3, cnt, x4] = 11 bytes
+;Numbers in brackets are maximum cycles since SOF.
+USB_INTR_VECTOR:
+;order of registers pushed: YL, SREG [sofError], YH, shift, x1, x2, x3, cnt
+ push YL ;2 [35] push only what is necessary to sync with edge ASAP
+ in YL, SREG ;1 [37]
+ push YL ;2 [39]
+;----------------------------------------------------------------------------
+; Synchronize with sync pattern:
+;----------------------------------------------------------------------------
+;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K]
+;sync up with J to K edge during sync pattern -- use fastest possible loops
+;The first part waits at most 1 bit long since we must be in sync pattern.
+;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to
+;waitForJ, ensure that this prerequisite is met.
+waitForJ:
+ inc YL
+ sbis USBIN, USBMINUS
+ brne waitForJ ; just make sure we have ANY timeout
+waitForK:
+;The following code results in a sampling window of 1/4 bit which meets the spec.
+ sbis USBIN, USBMINUS
+ rjmp foundK
+ sbis USBIN, USBMINUS
+ rjmp foundK
+ sbis USBIN, USBMINUS
+ rjmp foundK
+ sbis USBIN, USBMINUS
+ rjmp foundK
+ sbis USBIN, USBMINUS
+ rjmp foundK
+#if USB_COUNT_SOF
+ lds YL, usbSofCount
+ inc YL
+ sts usbSofCount, YL
+#endif /* USB_COUNT_SOF */
+#ifdef USB_SOF_HOOK
+ USB_SOF_HOOK
+#endif
+ rjmp sofError
+foundK:
+;{3, 5} after falling D- edge, average delay: 4 cycles [we want 4 for center sampling]
+;we have 1 bit time for setup purposes, then sample again. Numbers in brackets
+;are cycles from center of first sync (double K) bit after the instruction
+ push YH ;2 [2]
+ lds YL, usbInputBufOffset;2 [4]
+ clr YH ;1 [5]
+ subi YL, lo8(-(usbRxBuf));1 [6]
+ sbci YH, hi8(-(usbRxBuf));1 [7]
+
+ sbis USBIN, USBMINUS ;1 [8] we want two bits K [sample 1 cycle too early]
+ rjmp haveTwoBitsK ;2 [10]
+ pop YH ;2 [11] undo the push from before
+ rjmp waitForK ;2 [13] this was not the end of sync, retry
+haveTwoBitsK:
+;----------------------------------------------------------------------------
+; push more registers and initialize values while we sample the first bits:
+;----------------------------------------------------------------------------
+ push shift ;2 [16]
+ push x1 ;2 [12]
+ push x2 ;2 [14]
+
+ in x1, USBIN ;1 [17] <-- sample bit 0
+ ldi shift, 0xff ;1 [18]
+ bst x1, USBMINUS ;1 [19]
+ bld shift, 0 ;1 [20]
+ push x3 ;2 [22]
+ push cnt ;2 [24]
+
+ in x2, USBIN ;1 [25] <-- sample bit 1
+ ser x3 ;1 [26] [inserted init instruction]
+ eor x1, x2 ;1 [27]
+ bst x1, USBMINUS ;1 [28]
+ bld shift, 1 ;1 [29]
+ ldi cnt, USB_BUFSIZE;1 [30] [inserted init instruction]
+ rjmp rxbit2 ;2 [32]
+
+;----------------------------------------------------------------------------
+; Receiver loop (numbers in brackets are cycles within byte after instr)
+;----------------------------------------------------------------------------
+
+unstuff0: ;1 (branch taken)
+ andi x3, ~0x01 ;1 [15]
+ mov x1, x2 ;1 [16] x2 contains last sampled (stuffed) bit
+ in x2, USBIN ;1 [17] <-- sample bit 1 again
+ ori shift, 0x01 ;1 [18]
+ rjmp didUnstuff0 ;2 [20]
+
+unstuff1: ;1 (branch taken)
+ mov x2, x1 ;1 [21] x1 contains last sampled (stuffed) bit
+ andi x3, ~0x02 ;1 [22]
+ ori shift, 0x02 ;1 [23]
+ nop ;1 [24]
+ in x1, USBIN ;1 [25] <-- sample bit 2 again
+ rjmp didUnstuff1 ;2 [27]
+
+unstuff2: ;1 (branch taken)
+ andi x3, ~0x04 ;1 [29]
+ ori shift, 0x04 ;1 [30]
+ mov x1, x2 ;1 [31] x2 contains last sampled (stuffed) bit
+ nop ;1 [32]
+ in x2, USBIN ;1 [33] <-- sample bit 3
+ rjmp didUnstuff2 ;2 [35]
+
+unstuff3: ;1 (branch taken)
+ in x2, USBIN ;1 [34] <-- sample stuffed bit 3 [one cycle too late]
+ andi x3, ~0x08 ;1 [35]
+ ori shift, 0x08 ;1 [36]
+ rjmp didUnstuff3 ;2 [38]
+
+unstuff4: ;1 (branch taken)
+ andi x3, ~0x10 ;1 [40]
+ in x1, USBIN ;1 [41] <-- sample stuffed bit 4
+ ori shift, 0x10 ;1 [42]
+ rjmp didUnstuff4 ;2 [44]
+
+unstuff5: ;1 (branch taken)
+ andi x3, ~0x20 ;1 [48]
+ in x2, USBIN ;1 [49] <-- sample stuffed bit 5
+ ori shift, 0x20 ;1 [50]
+ rjmp didUnstuff5 ;2 [52]
+
+unstuff6: ;1 (branch taken)
+ andi x3, ~0x40 ;1 [56]
+ in x1, USBIN ;1 [57] <-- sample stuffed bit 6
+ ori shift, 0x40 ;1 [58]
+ rjmp didUnstuff6 ;2 [60]
+
+; extra jobs done during bit interval:
+; bit 0: store, clear [SE0 is unreliable here due to bit dribbling in hubs]
+; bit 1: se0 check
+; bit 2: overflow check
+; bit 3: recovery from delay [bit 0 tasks took too long]
+; bit 4: none
+; bit 5: none
+; bit 6: none
+; bit 7: jump, eor
+rxLoop:
+ eor x3, shift ;1 [0] reconstruct: x3 is 0 at bit locations we changed, 1 at others
+ in x1, USBIN ;1 [1] <-- sample bit 0
+ st y+, x3 ;2 [3] store data
+ ser x3 ;1 [4]
+ nop ;1 [5]
+ eor x2, x1 ;1 [6]
+ bst x2, USBMINUS;1 [7]
+ bld shift, 0 ;1 [8]
+ in x2, USBIN ;1 [9] <-- sample bit 1 (or possibly bit 0 stuffed)
+ andi x2, USBMASK ;1 [10]
+ breq se0 ;1 [11] SE0 check for bit 1
+ andi shift, 0xf9 ;1 [12]
+didUnstuff0:
+ breq unstuff0 ;1 [13]
+ eor x1, x2 ;1 [14]
+ bst x1, USBMINUS;1 [15]
+ bld shift, 1 ;1 [16]
+rxbit2:
+ in x1, USBIN ;1 [17] <-- sample bit 2 (or possibly bit 1 stuffed)
+ andi shift, 0xf3 ;1 [18]
+ breq unstuff1 ;1 [19] do remaining work for bit 1
+didUnstuff1:
+ subi cnt, 1 ;1 [20]
+ brcs overflow ;1 [21] loop control
+ eor x2, x1 ;1 [22]
+ bst x2, USBMINUS;1 [23]
+ bld shift, 2 ;1 [24]
+ in x2, USBIN ;1 [25] <-- sample bit 3 (or possibly bit 2 stuffed)
+ andi shift, 0xe7 ;1 [26]
+ breq unstuff2 ;1 [27]
+didUnstuff2:
+ eor x1, x2 ;1 [28]
+ bst x1, USBMINUS;1 [29]
+ bld shift, 3 ;1 [30]
+didUnstuff3:
+ andi shift, 0xcf ;1 [31]
+ breq unstuff3 ;1 [32]
+ in x1, USBIN ;1 [33] <-- sample bit 4
+ eor x2, x1 ;1 [34]
+ bst x2, USBMINUS;1 [35]
+ bld shift, 4 ;1 [36]
+didUnstuff4:
+ andi shift, 0x9f ;1 [37]
+ breq unstuff4 ;1 [38]
+ nop2 ;2 [40]
+ in x2, USBIN ;1 [41] <-- sample bit 5
+ eor x1, x2 ;1 [42]
+ bst x1, USBMINUS;1 [43]
+ bld shift, 5 ;1 [44]
+didUnstuff5:
+ andi shift, 0x3f ;1 [45]
+ breq unstuff5 ;1 [46]
+ nop2 ;2 [48]
+ in x1, USBIN ;1 [49] <-- sample bit 6
+ eor x2, x1 ;1 [50]
+ bst x2, USBMINUS;1 [51]
+ bld shift, 6 ;1 [52]
+didUnstuff6:
+ cpi shift, 0x02 ;1 [53]
+ brlo unstuff6 ;1 [54]
+ nop2 ;2 [56]
+ in x2, USBIN ;1 [57] <-- sample bit 7
+ eor x1, x2 ;1 [58]
+ bst x1, USBMINUS;1 [59]
+ bld shift, 7 ;1 [60]
+didUnstuff7:
+ cpi shift, 0x04 ;1 [61]
+ brsh rxLoop ;2 [63] loop control
+unstuff7:
+ andi x3, ~0x80 ;1 [63]
+ ori shift, 0x80 ;1 [64]
+ in x2, USBIN ;1 [65] <-- sample stuffed bit 7
+ nop ;1 [66]
+ rjmp didUnstuff7 ;2 [68]
+
+macro POP_STANDARD ; 12 cycles
+ pop cnt
+ pop x3
+ pop x2
+ pop x1
+ pop shift
+ pop YH
+ endm
+macro POP_RETI ; 5 cycles
+ pop YL
+ out SREG, YL
+ pop YL
+ endm
+
+#include "asmcommon.inc"
+
+;----------------------------------------------------------------------------
+; Transmitting data
+;----------------------------------------------------------------------------
+
+txByteLoop:
+txBitloop:
+stuffN1Delay: ; [03]
+ ror shift ;[-5] [11] [59]
+ brcc doExorN1 ;[-4] [60]
+ subi x4, 1 ;[-3]
+ brne commonN1 ;[-2]
+ lsl shift ;[-1] compensate ror after rjmp stuffDelay
+ nop ;[00] stuffing consists of just waiting 8 cycles
+ rjmp stuffN1Delay ;[01] after ror, C bit is reliably clear
+
+sendNakAndReti: ;0 [-19] 19 cycles until SOP
+ ldi x3, USBPID_NAK ;1 [-18]
+ rjmp usbSendX3 ;2 [-16]
+sendAckAndReti: ;0 [-19] 19 cycles until SOP
+ ldi x3, USBPID_ACK ;1 [-18]
+ rjmp usbSendX3 ;2 [-16]
+sendCntAndReti: ;0 [-17] 17 cycles until SOP
+ mov x3, cnt ;1 [-16]
+usbSendX3: ;0 [-16]
+ ldi YL, 20 ;1 [-15] 'x3' is R20
+ ldi YH, 0 ;1 [-14]
+ ldi cnt, 2 ;1 [-13]
+; rjmp usbSendAndReti fallthrough
+
+; USB spec says:
+; idle = J
+; J = (D+ = 0), (D- = 1) or USBOUT = 0x01
+; K = (D+ = 1), (D- = 0) or USBOUT = 0x02
+; Spec allows 7.5 bit times from EOP to SOP for replies (= 60 cycles)
+
+;usbSend:
+;pointer to data in 'Y'
+;number of bytes in 'cnt' -- including sync byte
+;uses: x1...x2, x4, shift, cnt, Y [x1 = mirror USBOUT, x2 = USBMASK, x4 = bitstuff cnt]
+;Numbers in brackets are time since first bit of sync pattern is sent (start of instruction)
+usbSendAndReti:
+ in x2, USBDDR ;[-12] 12 cycles until SOP
+ ori x2, USBMASK ;[-11]
+ sbi USBOUT, USBMINUS ;[-10] prepare idle state; D+ and D- must have been 0 (no pullups)
+ out USBDDR, x2 ;[-8] <--- acquire bus
+ in x1, USBOUT ;[-7] port mirror for tx loop
+ ldi shift, 0x40 ;[-6] sync byte is first byte sent (we enter loop after ror)
+ ldi x2, USBMASK ;[-5]
+ push x4 ;[-4]
+doExorN1:
+ eor x1, x2 ;[-2] [06] [62]
+ ldi x4, 6 ;[-1] [07] [63]
+commonN1:
+stuffN2Delay:
+ out USBOUT, x1 ;[00] [08] [64] <--- set bit
+ ror shift ;[01]
+ brcc doExorN2 ;[02]
+ subi x4, 1 ;[03]
+ brne commonN2 ;[04]
+ lsl shift ;[05] compensate ror after rjmp stuffDelay
+ rjmp stuffN2Delay ;[06] after ror, C bit is reliably clear
+doExorN2:
+ eor x1, x2 ;[04] [12]
+ ldi x4, 6 ;[05] [13]
+commonN2:
+ nop ;[06] [14]
+ subi cnt, 171 ;[07] [15] trick: (3 * 171) & 0xff = 1
+ out USBOUT, x1 ;[08] [16] <--- set bit
+ brcs txBitloop ;[09] [25] [41]
+
+stuff6Delay:
+ ror shift ;[42] [50]
+ brcc doExor6 ;[43]
+ subi x4, 1 ;[44]
+ brne common6 ;[45]
+ lsl shift ;[46] compensate ror after rjmp stuffDelay
+ nop ;[47] stuffing consists of just waiting 8 cycles
+ rjmp stuff6Delay ;[48] after ror, C bit is reliably clear
+doExor6:
+ eor x1, x2 ;[45] [53]
+ ldi x4, 6 ;[46]
+common6:
+stuff7Delay:
+ ror shift ;[47] [55]
+ out USBOUT, x1 ;[48] <--- set bit
+ brcc doExor7 ;[49]
+ subi x4, 1 ;[50]
+ brne common7 ;[51]
+ lsl shift ;[52] compensate ror after rjmp stuffDelay
+ rjmp stuff7Delay ;[53] after ror, C bit is reliably clear
+doExor7:
+ eor x1, x2 ;[51] [59]
+ ldi x4, 6 ;[52]
+common7:
+ ld shift, y+ ;[53]
+ tst cnt ;[55]
+ out USBOUT, x1 ;[56] <--- set bit
+ brne txByteLoop ;[57]
+
+;make SE0:
+ cbr x1, USBMASK ;[58] prepare SE0 [spec says EOP may be 15 to 18 cycles]
+ lds x2, usbNewDeviceAddr;[59]
+ lsl x2 ;[61] we compare with left shifted address
+ subi YL, 2 + 20 ;[62] Only assign address on data packets, not ACK/NAK in x3
+ sbci YH, 0 ;[63]
+ out USBOUT, x1 ;[00] <-- out SE0 -- from now 2 bits = 16 cycles until bus idle
+;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm:
+;set address only after data packet was sent, not after handshake
+ breq skipAddrAssign ;[01]
+ sts usbDeviceAddr, x2 ; if not skipped: SE0 is one cycle longer
+skipAddrAssign:
+;end of usbDeviceAddress transfer
+ ldi x2, 1<<USB_INTR_PENDING_BIT;[03] int0 occurred during TX -- clear pending flag
+ USB_STORE_PENDING(x2) ;[04]
+ ori x1, USBIDLE ;[05]
+ in x2, USBDDR ;[06]
+ cbr x2, USBMASK ;[07] set both pins to input
+ mov x3, x1 ;[08]
+ cbr x3, USBMASK ;[09] configure no pullup on both pins
+ pop x4 ;[10]
+ nop2 ;[12]
+ nop2 ;[14]
+ out USBOUT, x1 ;[16] <-- out J (idle) -- end of SE0 (EOP signal)
+ out USBDDR, x2 ;[17] <-- release bus now
+ out USBOUT, x3 ;[18] <-- ensure no pull-up resistors are active
+ rjmp doReturn
diff --git a/tmk_core/protocol/vusb/usbdrv/usbdrvasm128.inc b/tmk_core/protocol/vusb/usbdrv/usbdrvasm128.inc
new file mode 100644
index 000000000..bcd6621cc
--- /dev/null
+++ b/tmk_core/protocol/vusb/usbdrv/usbdrvasm128.inc
@@ -0,0 +1,750 @@
+/* Name: usbdrvasm128.inc
+ * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
+ * Author: Christian Starkjohann
+ * Creation Date: 2008-10-11
+ * Tabsize: 4
+ * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
+ * This Revision: $Id: usbdrvasm128.inc 758 2009-08-06 10:12:54Z cs $
+ */
+
+/* Do not link this file! Link usbdrvasm.S instead, which includes the
+ * appropriate implementation!
+ */
+
+/*
+General Description:
+This file is the 12.8 MHz version of the USB driver. It is intended for use
+with the internal RC oscillator. Although 12.8 MHz is outside the guaranteed
+calibration range of the oscillator, almost all AVRs can reach this frequency.
+This version contains a phase locked loop in the receiver routine to cope with
+slight clock rate deviations of up to +/- 1%.
+
+See usbdrv.h for a description of the entire driver.
+
+LIMITATIONS
+===========
+Although it may seem very handy to save the crystal and use the internal
+RC oscillator of the CPU, this method (and this module) has some serious
+limitations:
+(1) The guaranteed calibration range of the oscillator is only 8.1 MHz.
+They typical range is 14.5 MHz and most AVRs can actually reach this rate.
+(2) Writing EEPROM and Flash may be unreliable (short data lifetime) since
+the write procedure is timed from the RC oscillator.
+(3) End Of Packet detection (SE0) should be in bit 1, bit it is only checked
+if bits 0 and 1 both read as 0 on D- and D+ read as 0 in the middle. This may
+cause problems with old hubs which delay SE0 by up to one cycle.
+(4) Code size is much larger than that of the other modules.
+
+Since almost all of this code is timing critical, don't change unless you
+really know what you are doing! Many parts require not only a maximum number
+of CPU cycles, but even an exact number of cycles!
+
+Implementation notes:
+======================
+min frequency: 67 cycles for 8 bit -> 12.5625 MHz
+max frequency: 69.286 cycles for 8 bit -> 12.99 MHz
+nominal frequency: 12.77 MHz ( = sqrt(min * max))
+
+sampling positions: (next even number in range [+/- 0.5])
+cycle index range: 0 ... 66
+bits:
+.5, 8.875, 17.25, 25.625, 34, 42.375, 50.75, 59.125
+[0/1], [9], [17], [25/+26], [34], [+42/43], [51], [59]
+
+bit number: 0 1 2 3 4 5 6 7
+spare cycles 1 2 1 2 1 1 1 0
+
+operations to perform: duration cycle
+ ----------------
+ eor fix, shift 1 -> 00
+ andi phase, USBMASK 1 -> 08
+ breq se0 1 -> 16 (moved to 11)
+ st y+, data 2 -> 24, 25
+ mov data, fix 1 -> 33
+ ser data 1 -> 41
+ subi cnt, 1 1 -> 49
+ brcs overflow 1 -> 50
+
+layout of samples and operations:
+[##] = sample bit
+<##> = sample phase
+*##* = operation
+
+0: *00* [01] 02 03 04 <05> 06 07
+1: *08* [09] 10 11 12 <13> 14 15 *16*
+2: [17] 18 19 20 <21> 22 23
+3: *24* *25* [26] 27 28 29 <30> 31 32
+4: *33* [34] 35 36 37 <38> 39 40
+5: *41* [42] 43 44 45 <46> 47 48
+6: *49* *50* [51] 52 53 54 <55> 56 57 58
+7: [59] 60 61 62 <63> 64 65 66
+*****************************************************************************/
+
+/* we prefer positive expressions (do if condition) instead of negative
+ * (skip if condition), therefore use defines for skip instructions:
+ */
+#define ifioclr sbis
+#define ifioset sbic
+#define ifrclr sbrs
+#define ifrset sbrc
+
+/* The registers "fix" and "data" swap their meaning during the loop. Use
+ * defines to keep their name constant.
+ */
+#define fix x2
+#define data x1
+#undef phase /* phase has a default definition to x4 */
+#define phase x3
+
+
+USB_INTR_VECTOR:
+;order of registers pushed: YL, SREG [sofError], YH, shift, x1, x2, x3, cnt, r0
+ push YL ;2 push only what is necessary to sync with edge ASAP
+ in YL, SREG ;1
+ push YL ;2
+;----------------------------------------------------------------------------
+; Synchronize with sync pattern:
+;----------------------------------------------------------------------------
+;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K]
+;sync up with J to K edge during sync pattern -- use fastest possible loops
+;The first part waits at most 1 bit long since we must be in sync pattern.
+;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to
+;waitForJ, ensure that this prerequisite is met.
+waitForJ:
+ inc YL
+ sbis USBIN, USBMINUS
+ brne waitForJ ; just make sure we have ANY timeout
+waitForK:
+;The following code results in a sampling window of 1/4 bit which meets the spec.
+ sbis USBIN, USBMINUS
+ rjmp foundK
+ sbis USBIN, USBMINUS
+ rjmp foundK
+ sbis USBIN, USBMINUS
+ rjmp foundK
+ sbis USBIN, USBMINUS
+ rjmp foundK
+ sbis USBIN, USBMINUS ;[0]
+ rjmp foundK ;[1]
+#if USB_COUNT_SOF
+ lds YL, usbSofCount
+ inc YL
+ sts usbSofCount, YL
+#endif /* USB_COUNT_SOF */
+#ifdef USB_SOF_HOOK
+ USB_SOF_HOOK
+#endif
+ rjmp sofError
+
+foundK:
+;{3, 5} after falling D- edge, average delay: 4 cycles [we want 4 for center sampling]
+;we have 1 bit time for setup purposes, then sample again. Numbers in brackets
+;are cycles from center of first sync (double K) bit after the instruction
+ push YH ;[2]
+ lds YL, usbInputBufOffset;[4]
+ clr YH ;[6]
+ subi YL, lo8(-(usbRxBuf));[7]
+ sbci YH, hi8(-(usbRxBuf));[8]
+
+ sbis USBIN, USBMINUS ;[9] we want two bits K [we want to sample at 8 + 4 - 1.5 = 10.5]
+ rjmp haveTwoBitsK ;[10]
+ pop YH ;[11] undo the push from before
+ rjmp waitForK ;[13] this was not the end of sync, retry
+haveTwoBitsK:
+;----------------------------------------------------------------------------
+; push more registers and initialize values while we sample the first bits:
+;----------------------------------------------------------------------------
+#define fix x2
+#define data x1
+
+ push shift ;[12]
+ push x1 ;[14]
+ push x2 ;[16]
+ ldi shift, 0x80 ;[18] prevent bit-unstuffing but init low bits to 0
+ ifioset USBIN, USBMINUS ;[19] [01] <--- bit 0 [10.5 + 8 = 18.5]
+ ori shift, 1<<0 ;[02]
+ push x3 ;[03]
+ push cnt ;[05]
+ push r0 ;[07]
+ ifioset USBIN, USBMINUS ;[09] <--- bit 1
+ ori shift, 1<<1 ;[10]
+ ser fix ;[11]
+ ldi cnt, USB_BUFSIZE ;[12]
+ mov data, shift ;[13]
+ lsl shift ;[14]
+ nop2 ;[15]
+ ifioset USBIN, USBMINUS ;[17] <--- bit 2
+ ori data, 3<<2 ;[18] store in bit 2 AND bit 3
+ eor shift, data ;[19] do nrzi decoding
+ andi data, 1<<3 ;[20]
+ in phase, USBIN ;[21] <- phase
+ brne jumpToEntryAfterSet ;[22] if USBMINS at bit 3 was 1
+ nop ;[23]
+ rjmp entryAfterClr ;[24]
+jumpToEntryAfterSet:
+ rjmp entryAfterSet ;[24]
+
+;----------------------------------------------------------------------------
+; Receiver loop (numbers in brackets are cycles within byte after instr)
+;----------------------------------------------------------------------------
+#undef fix
+#define fix x1
+#undef data
+#define data x2
+
+bit7IsSet:
+ ifrclr phase, USBMINUS ;[62] check phase only if D- changed
+ lpm ;[63]
+ in phase, USBIN ;[64] <- phase (one cycle too late)
+ ori shift, 1 << 7 ;[65]
+ nop ;[66]
+;;;;rjmp bit0AfterSet ; -> [00] == [67] moved block up to save jump
+bit0AfterSet:
+ eor fix, shift ;[00]
+#undef fix
+#define fix x2
+#undef data
+#define data x1 /* we now have result in data, fix is reset to 0xff */
+ ifioclr USBIN, USBMINUS ;[01] <--- sample 0
+ rjmp bit0IsClr ;[02]
+ andi shift, ~(7 << 0) ;[03]
+ breq unstuff0s ;[04]
+ in phase, USBIN ;[05] <- phase
+ rjmp bit1AfterSet ;[06]
+unstuff0s:
+ in phase, USBIN ;[06] <- phase (one cycle too late)
+ andi fix, ~(1 << 0) ;[07]
+ ifioclr USBIN, USBMINUS ;[00]
+ ifioset USBIN, USBPLUS ;[01]
+ rjmp bit0IsClr ;[02] executed if first expr false or second true
+se0AndStore: ; executed only if both bits 0
+ st y+, x1 ;[15/17] cycles after start of byte
+ rjmp se0 ;[17/19]
+
+bit0IsClr:
+ ifrset phase, USBMINUS ;[04] check phase only if D- changed
+ lpm ;[05]
+ in phase, USBIN ;[06] <- phase (one cycle too late)
+ ori shift, 1 << 0 ;[07]
+bit1AfterClr:
+ andi phase, USBMASK ;[08]
+ ifioset USBIN, USBMINUS ;[09] <--- sample 1
+ rjmp bit1IsSet ;[10]
+ breq se0AndStore ;[11] if D- was 0 in bits 0 AND 1 and D+ was 0 in between, we have SE0
+ andi shift, ~(7 << 1) ;[12]
+ in phase, USBIN ;[13] <- phase
+ breq unstuff1c ;[14]
+ rjmp bit2AfterClr ;[15]
+unstuff1c:
+ andi fix, ~(1 << 1) ;[16]
+ nop2 ;[08]
+ nop2 ;[10]
+bit1IsSet:
+ ifrclr phase, USBMINUS ;[12] check phase only if D- changed
+ lpm ;[13]
+ in phase, USBIN ;[14] <- phase (one cycle too late)
+ ori shift, 1 << 1 ;[15]
+ nop ;[16]
+bit2AfterSet:
+ ifioclr USBIN, USBMINUS ;[17] <--- sample 2
+ rjmp bit2IsClr ;[18]
+ andi shift, ~(7 << 2) ;[19]
+ breq unstuff2s ;[20]
+ in phase, USBIN ;[21] <- phase
+ rjmp bit3AfterSet ;[22]
+unstuff2s:
+ in phase, USBIN ;[22] <- phase (one cycle too late)
+ andi fix, ~(1 << 2) ;[23]
+ nop2 ;[16]
+ nop2 ;[18]
+bit2IsClr:
+ ifrset phase, USBMINUS ;[20] check phase only if D- changed
+ lpm ;[21]
+ in phase, USBIN ;[22] <- phase (one cycle too late)
+ ori shift, 1 << 2 ;[23]
+bit3AfterClr:
+ st y+, data ;[24]
+entryAfterClr:
+ ifioset USBIN, USBMINUS ;[26] <--- sample 3
+ rjmp bit3IsSet ;[27]
+ andi shift, ~(7 << 3) ;[28]
+ breq unstuff3c ;[29]
+ in phase, USBIN ;[30] <- phase
+ rjmp bit4AfterClr ;[31]
+unstuff3c:
+ in phase, USBIN ;[31] <- phase (one cycle too late)
+ andi fix, ~(1 << 3) ;[32]
+ nop2 ;[25]
+ nop2 ;[27]
+bit3IsSet:
+ ifrclr phase, USBMINUS ;[29] check phase only if D- changed
+ lpm ;[30]
+ in phase, USBIN ;[31] <- phase (one cycle too late)
+ ori shift, 1 << 3 ;[32]
+bit4AfterSet:
+ mov data, fix ;[33] undo this move by swapping defines
+#undef fix
+#define fix x1
+#undef data
+#define data x2
+ ifioclr USBIN, USBMINUS ;[34] <--- sample 4
+ rjmp bit4IsClr ;[35]
+ andi shift, ~(7 << 4) ;[36]
+ breq unstuff4s ;[37]
+ in phase, USBIN ;[38] <- phase
+ rjmp bit5AfterSet ;[39]
+unstuff4s:
+ in phase, USBIN ;[39] <- phase (one cycle too late)
+ andi fix, ~(1 << 4) ;[40]
+ nop2 ;[33]
+ nop2 ;[35]
+bit4IsClr:
+ ifrset phase, USBMINUS ;[37] check phase only if D- changed
+ lpm ;[38]
+ in phase, USBIN ;[39] <- phase (one cycle too late)
+ ori shift, 1 << 4 ;[40]
+bit5AfterClr:
+ ser data ;[41]
+ ifioset USBIN, USBMINUS ;[42] <--- sample 5
+ rjmp bit5IsSet ;[43]
+ andi shift, ~(7 << 5) ;[44]
+ breq unstuff5c ;[45]
+ in phase, USBIN ;[46] <- phase
+ rjmp bit6AfterClr ;[47]
+unstuff5c:
+ in phase, USBIN ;[47] <- phase (one cycle too late)
+ andi fix, ~(1 << 5) ;[48]
+ nop2 ;[41]
+ nop2 ;[43]
+bit5IsSet:
+ ifrclr phase, USBMINUS ;[45] check phase only if D- changed
+ lpm ;[46]
+ in phase, USBIN ;[47] <- phase (one cycle too late)
+ ori shift, 1 << 5 ;[48]
+bit6AfterSet:
+ subi cnt, 1 ;[49]
+ brcs jumpToOverflow ;[50]
+ ifioclr USBIN, USBMINUS ;[51] <--- sample 6
+ rjmp bit6IsClr ;[52]
+ andi shift, ~(3 << 6) ;[53]
+ cpi shift, 2 ;[54]
+ in phase, USBIN ;[55] <- phase
+ brlt unstuff6s ;[56]
+ rjmp bit7AfterSet ;[57]
+
+jumpToOverflow:
+ rjmp overflow
+
+unstuff6s:
+ andi fix, ~(1 << 6) ;[50]
+ lpm ;[51]
+bit6IsClr:
+ ifrset phase, USBMINUS ;[54] check phase only if D- changed
+ lpm ;[55]
+ in phase, USBIN ;[56] <- phase (one cycle too late)
+ ori shift, 1 << 6 ;[57]
+ nop ;[58]
+bit7AfterClr:
+ ifioset USBIN, USBMINUS ;[59] <--- sample 7
+ rjmp bit7IsSet ;[60]
+ andi shift, ~(1 << 7) ;[61]
+ cpi shift, 4 ;[62]
+ in phase, USBIN ;[63] <- phase
+ brlt unstuff7c ;[64]
+ rjmp bit0AfterClr ;[65] -> [00] == [67]
+unstuff7c:
+ andi fix, ~(1 << 7) ;[58]
+ nop ;[59]
+ rjmp bit7IsSet ;[60]
+
+bit7IsClr:
+ ifrset phase, USBMINUS ;[62] check phase only if D- changed
+ lpm ;[63]
+ in phase, USBIN ;[64] <- phase (one cycle too late)
+ ori shift, 1 << 7 ;[65]
+ nop ;[66]
+;;;;rjmp bit0AfterClr ; -> [00] == [67] moved block up to save jump
+bit0AfterClr:
+ eor fix, shift ;[00]
+#undef fix
+#define fix x2
+#undef data
+#define data x1 /* we now have result in data, fix is reset to 0xff */
+ ifioset USBIN, USBMINUS ;[01] <--- sample 0
+ rjmp bit0IsSet ;[02]
+ andi shift, ~(7 << 0) ;[03]
+ breq unstuff0c ;[04]
+ in phase, USBIN ;[05] <- phase
+ rjmp bit1AfterClr ;[06]
+unstuff0c:
+ in phase, USBIN ;[06] <- phase (one cycle too late)
+ andi fix, ~(1 << 0) ;[07]
+ ifioclr USBIN, USBMINUS ;[00]
+ ifioset USBIN, USBPLUS ;[01]
+ rjmp bit0IsSet ;[02] executed if first expr false or second true
+ rjmp se0AndStore ;[03] executed only if both bits 0
+bit0IsSet:
+ ifrclr phase, USBMINUS ;[04] check phase only if D- changed
+ lpm ;[05]
+ in phase, USBIN ;[06] <- phase (one cycle too late)
+ ori shift, 1 << 0 ;[07]
+bit1AfterSet:
+ andi shift, ~(7 << 1) ;[08] compensated by "ori shift, 1<<1" if bit1IsClr
+ ifioclr USBIN, USBMINUS ;[09] <--- sample 1
+ rjmp bit1IsClr ;[10]
+ breq unstuff1s ;[11]
+ nop2 ;[12] do not check for SE0 if bit 0 was 1
+ in phase, USBIN ;[14] <- phase (one cycle too late)
+ rjmp bit2AfterSet ;[15]
+unstuff1s:
+ in phase, USBIN ;[13] <- phase
+ andi fix, ~(1 << 1) ;[14]
+ lpm ;[07]
+ nop2 ;[10]
+bit1IsClr:
+ ifrset phase, USBMINUS ;[12] check phase only if D- changed
+ lpm ;[13]
+ in phase, USBIN ;[14] <- phase (one cycle too late)
+ ori shift, 1 << 1 ;[15]
+ nop ;[16]
+bit2AfterClr:
+ ifioset USBIN, USBMINUS ;[17] <--- sample 2
+ rjmp bit2IsSet ;[18]
+ andi shift, ~(7 << 2) ;[19]
+ breq unstuff2c ;[20]
+ in phase, USBIN ;[21] <- phase
+ rjmp bit3AfterClr ;[22]
+unstuff2c:
+ in phase, USBIN ;[22] <- phase (one cycle too late)
+ andi fix, ~(1 << 2) ;[23]
+ nop2 ;[16]
+ nop2 ;[18]
+bit2IsSet:
+ ifrclr phase, USBMINUS ;[20] check phase only if D- changed
+ lpm ;[21]
+ in phase, USBIN ;[22] <- phase (one cycle too late)
+ ori shift, 1 << 2 ;[23]
+bit3AfterSet:
+ st y+, data ;[24]
+entryAfterSet:
+ ifioclr USBIN, USBMINUS ;[26] <--- sample 3
+ rjmp bit3IsClr ;[27]
+ andi shift, ~(7 << 3) ;[28]
+ breq unstuff3s ;[29]
+ in phase, USBIN ;[30] <- phase
+ rjmp bit4AfterSet ;[31]
+unstuff3s:
+ in phase, USBIN ;[31] <- phase (one cycle too late)
+ andi fix, ~(1 << 3) ;[32]
+ nop2 ;[25]
+ nop2 ;[27]
+bit3IsClr:
+ ifrset phase, USBMINUS ;[29] check phase only if D- changed
+ lpm ;[30]
+ in phase, USBIN ;[31] <- phase (one cycle too late)
+ ori shift, 1 << 3 ;[32]
+bit4AfterClr:
+ mov data, fix ;[33] undo this move by swapping defines
+#undef fix
+#define fix x1
+#undef data
+#define data x2
+ ifioset USBIN, USBMINUS ;[34] <--- sample 4
+ rjmp bit4IsSet ;[35]
+ andi shift, ~(7 << 4) ;[36]
+ breq unstuff4c ;[37]
+ in phase, USBIN ;[38] <- phase
+ rjmp bit5AfterClr ;[39]
+unstuff4c:
+ in phase, USBIN ;[39] <- phase (one cycle too late)
+ andi fix, ~(1 << 4) ;[40]
+ nop2 ;[33]
+ nop2 ;[35]
+bit4IsSet:
+ ifrclr phase, USBMINUS ;[37] check phase only if D- changed
+ lpm ;[38]
+ in phase, USBIN ;[39] <- phase (one cycle too late)
+ ori shift, 1 << 4 ;[40]
+bit5AfterSet:
+ ser data ;[41]
+ ifioclr USBIN, USBMINUS ;[42] <--- sample 5
+ rjmp bit5IsClr ;[43]
+ andi shift, ~(7 << 5) ;[44]
+ breq unstuff5s ;[45]
+ in phase, USBIN ;[46] <- phase
+ rjmp bit6AfterSet ;[47]
+unstuff5s:
+ in phase, USBIN ;[47] <- phase (one cycle too late)
+ andi fix, ~(1 << 5) ;[48]
+ nop2 ;[41]
+ nop2 ;[43]
+bit5IsClr:
+ ifrset phase, USBMINUS ;[45] check phase only if D- changed
+ lpm ;[46]
+ in phase, USBIN ;[47] <- phase (one cycle too late)
+ ori shift, 1 << 5 ;[48]
+bit6AfterClr:
+ subi cnt, 1 ;[49]
+ brcs overflow ;[50]
+ ifioset USBIN, USBMINUS ;[51] <--- sample 6
+ rjmp bit6IsSet ;[52]
+ andi shift, ~(3 << 6) ;[53]
+ cpi shift, 2 ;[54]
+ in phase, USBIN ;[55] <- phase
+ brlt unstuff6c ;[56]
+ rjmp bit7AfterClr ;[57]
+unstuff6c:
+ andi fix, ~(1 << 6) ;[50]
+ lpm ;[51]
+bit6IsSet:
+ ifrclr phase, USBMINUS ;[54] check phase only if D- changed
+ lpm ;[55]
+ in phase, USBIN ;[56] <- phase (one cycle too late)
+ ori shift, 1 << 6 ;[57]
+bit7AfterSet:
+ ifioclr USBIN, USBMINUS ;[59] <--- sample 7
+ rjmp bit7IsClr ;[60]
+ andi shift, ~(1 << 7) ;[61]
+ cpi shift, 4 ;[62]
+ in phase, USBIN ;[63] <- phase
+ brlt unstuff7s ;[64]
+ rjmp bit0AfterSet ;[65] -> [00] == [67]
+unstuff7s:
+ andi fix, ~(1 << 7) ;[58]
+ nop ;[59]
+ rjmp bit7IsClr ;[60]
+
+macro POP_STANDARD ; 14 cycles
+ pop r0
+ pop cnt
+ pop x3
+ pop x2
+ pop x1
+ pop shift
+ pop YH
+ endm
+macro POP_RETI ; 5 cycles
+ pop YL
+ out SREG, YL
+ pop YL
+ endm
+
+#include "asmcommon.inc"
+
+;----------------------------------------------------------------------------
+; Transmitting data
+;----------------------------------------------------------------------------
+
+txByteLoop:
+txBitloop:
+stuffN1Delay: ; [03]
+ ror shift ;[-5] [11] [63]
+ brcc doExorN1 ;[-4] [64]
+ subi x3, 1 ;[-3]
+ brne commonN1 ;[-2]
+ lsl shift ;[-1] compensate ror after rjmp stuffDelay
+ nop ;[00] stuffing consists of just waiting 8 cycles
+ rjmp stuffN1Delay ;[01] after ror, C bit is reliably clear
+
+sendNakAndReti:
+ ldi cnt, USBPID_NAK ;[-19]
+ rjmp sendCntAndReti ;[-18]
+sendAckAndReti:
+ ldi cnt, USBPID_ACK ;[-17]
+sendCntAndReti:
+ mov r0, cnt ;[-16]
+ ldi YL, 0 ;[-15] R0 address is 0
+ ldi YH, 0 ;[-14]
+ ldi cnt, 2 ;[-13]
+; rjmp usbSendAndReti fallthrough
+
+; USB spec says:
+; idle = J
+; J = (D+ = 0), (D- = 1) or USBOUT = 0x01
+; K = (D+ = 1), (D- = 0) or USBOUT = 0x02
+; Spec allows 7.5 bit times from EOP to SOP for replies (= 60 cycles)
+
+;usbSend:
+;pointer to data in 'Y'
+;number of bytes in 'cnt' -- including sync byte
+;uses: x1...x3, shift, cnt, Y [x1 = mirror USBOUT, x2 = USBMASK, x3 = bitstuff cnt]
+;Numbers in brackets are time since first bit of sync pattern is sent (start of instruction)
+usbSendAndReti:
+ in x2, USBDDR ;[-10] 10 cycles until SOP
+ ori x2, USBMASK ;[-9]
+ sbi USBOUT, USBMINUS ;[-8] prepare idle state; D+ and D- must have been 0 (no pullups)
+ out USBDDR, x2 ;[-6] <--- acquire bus
+ in x1, USBOUT ;[-5] port mirror for tx loop
+ ldi shift, 0x40 ;[-4] sync byte is first byte sent (we enter loop after ror)
+ ldi x2, USBMASK ;[-3]
+doExorN1:
+ eor x1, x2 ;[-2] [06] [62]
+ ldi x3, 6 ;[-1] [07] [63]
+commonN1:
+stuffN2Delay:
+ out USBOUT, x1 ;[00] [08] [64] <--- set bit
+ ror shift ;[01]
+ brcc doExorN2 ;[02]
+ subi x3, 1 ;[03]
+ brne commonN2 ;[04]
+ lsl shift ;[05] compensate ror after rjmp stuffDelay
+ rjmp stuffN2Delay ;[06] after ror, C bit is reliably clear
+doExorN2:
+ eor x1, x2 ;[04] [12]
+ ldi x3, 6 ;[05] [13]
+commonN2:
+ nop2 ;[06] [14]
+ subi cnt, 171 ;[08] [16] trick: (3 * 171) & 0xff = 1
+ out USBOUT, x1 ;[09] [17] <--- set bit
+ brcs txBitloop ;[10] [27] [44]
+
+stuff6Delay:
+ ror shift ;[45] [53]
+ brcc doExor6 ;[46]
+ subi x3, 1 ;[47]
+ brne common6 ;[48]
+ lsl shift ;[49] compensate ror after rjmp stuffDelay
+ nop ;[50] stuffing consists of just waiting 8 cycles
+ rjmp stuff6Delay ;[51] after ror, C bit is reliably clear
+doExor6:
+ eor x1, x2 ;[48] [56]
+ ldi x3, 6 ;[49]
+common6:
+stuff7Delay:
+ ror shift ;[50] [58]
+ out USBOUT, x1 ;[51] <--- set bit
+ brcc doExor7 ;[52]
+ subi x3, 1 ;[53]
+ brne common7 ;[54]
+ lsl shift ;[55] compensate ror after rjmp stuffDelay
+ rjmp stuff7Delay ;[56] after ror, C bit is reliably clear
+doExor7:
+ eor x1, x2 ;[54] [62]
+ ldi x3, 6 ;[55]
+common7:
+ ld shift, y+ ;[56]
+ nop ;[58]
+ tst cnt ;[59]
+ out USBOUT, x1 ;[60] [00]<--- set bit
+ brne txByteLoop ;[61] [01]
+;make SE0:
+ cbr x1, USBMASK ;[02] prepare SE0 [spec says EOP may be 15 to 18 cycles]
+ lds x2, usbNewDeviceAddr;[03]
+ lsl x2 ;[05] we compare with left shifted address
+ subi YL, 2 + 0 ;[06] Only assign address on data packets, not ACK/NAK in r0
+ sbci YH, 0 ;[07]
+ out USBOUT, x1 ;[00] <-- out SE0 -- from now 2 bits = 16 cycles until bus idle
+;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm:
+;set address only after data packet was sent, not after handshake
+ breq skipAddrAssign ;[01]
+ sts usbDeviceAddr, x2 ; if not skipped: SE0 is one cycle longer
+skipAddrAssign:
+;end of usbDeviceAddress transfer
+ ldi x2, 1<<USB_INTR_PENDING_BIT;[03] int0 occurred during TX -- clear pending flag
+ USB_STORE_PENDING(x2) ;[04]
+ ori x1, USBIDLE ;[05]
+ in x2, USBDDR ;[06]
+ cbr x2, USBMASK ;[07] set both pins to input
+ mov x3, x1 ;[08]
+ cbr x3, USBMASK ;[09] configure no pullup on both pins
+ lpm ;[10]
+ lpm ;[13]
+ out USBOUT, x1 ;[16] <-- out J (idle) -- end of SE0 (EOP signal)
+ out USBDDR, x2 ;[17] <-- release bus now
+ out USBOUT, x3 ;[18] <-- ensure no pull-up resistors are active
+ rjmp doReturn
+
+
+
+/*****************************************************************************
+The following PHP script generates a code skeleton for the receiver routine:
+
+<?php
+
+function printCmdBuffer($thisBit)
+{
+global $cycle;
+
+ $nextBit = ($thisBit + 1) % 8;
+ $s = ob_get_contents();
+ ob_end_clean();
+ $s = str_replace("#", $thisBit, $s);
+ $s = str_replace("@", $nextBit, $s);
+ $lines = explode("\n", $s);
+ for($i = 0; $i < count($lines); $i++){
+ $s = $lines[$i];
+ if(ereg("\\[([0-9-][0-9])\\]", $s, $regs)){
+ $c = $cycle + (int)$regs[1];
+ $s = ereg_replace("\\[[0-9-][0-9]\\]", sprintf("[%02d]", $c), $s);
+ }
+ if(strlen($s) > 0)
+ echo "$s\n";
+ }
+}
+
+function printBit($isAfterSet, $bitNum)
+{
+ ob_start();
+ if($isAfterSet){
+?>
+ ifioclr USBIN, USBMINUS ;[00] <--- sample
+ rjmp bit#IsClr ;[01]
+ andi shift, ~(7 << #) ;[02]
+ breq unstuff#s ;[03]
+ in phase, USBIN ;[04] <- phase
+ rjmp bit@AfterSet ;[05]
+unstuff#s:
+ in phase, USBIN ;[05] <- phase (one cycle too late)
+ andi fix, ~(1 << #) ;[06]
+ nop2 ;[-1]
+ nop2 ;[01]
+bit#IsClr:
+ ifrset phase, USBMINUS ;[03] check phase only if D- changed
+ lpm ;[04]
+ in phase, USBIN ;[05] <- phase (one cycle too late)
+ ori shift, 1 << # ;[06]
+<?php
+ }else{
+?>
+ ifioset USBIN, USBMINUS ;[00] <--- sample
+ rjmp bit#IsSet ;[01]
+ andi shift, ~(7 << #) ;[02]
+ breq unstuff#c ;[03]
+ in phase, USBIN ;[04] <- phase
+ rjmp bit@AfterClr ;[05]
+unstuff#c:
+ in phase, USBIN ;[05] <- phase (one cycle too late)
+ andi fix, ~(1 << #) ;[06]
+ nop2 ;[-1]
+ nop2 ;[01]
+bit#IsSet:
+ ifrclr phase, USBMINUS ;[03] check phase only if D- changed
+ lpm ;[04]
+ in phase, USBIN ;[05] <- phase (one cycle too late)
+ ori shift, 1 << # ;[06]
+<?php
+ }
+ printCmdBuffer($bitNum);
+}
+
+$bitStartCycles = array(1, 9, 17, 26, 34, 42, 51, 59);
+for($i = 0; $i < 16; $i++){
+ $bit = $i % 8;
+ $emitClrCode = ($i + (int)($i / 8)) % 2;
+ $cycle = $bitStartCycles[$bit];
+ if($emitClrCode){
+ printf("bit%dAfterClr:\n", $bit);
+ }else{
+ printf("bit%dAfterSet:\n", $bit);
+ }
+ ob_start();
+ echo " ***** ;[-1]\n";
+ printCmdBuffer($bit);
+ printBit(!$emitClrCode, $bit);
+ if($i == 7)
+ echo "\n";
+}
+
+?>
+*****************************************************************************/
diff --git a/tmk_core/protocol/vusb/usbdrv/usbdrvasm15.inc b/tmk_core/protocol/vusb/usbdrv/usbdrvasm15.inc
new file mode 100644
index 000000000..401b7f8ff
--- /dev/null
+++ b/tmk_core/protocol/vusb/usbdrv/usbdrvasm15.inc
@@ -0,0 +1,423 @@
+/* Name: usbdrvasm15.inc
+ * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
+ * Author: contributed by V. Bosch
+ * Creation Date: 2007-08-06
+ * Tabsize: 4
+ * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
+ * Revision: $Id: usbdrvasm15.inc 740 2009-04-13 18:23:31Z cs $
+ */
+
+/* Do not link this file! Link usbdrvasm.S instead, which includes the
+ * appropriate implementation!
+ */
+
+/*
+General Description:
+This file is the 15 MHz version of the asssembler part of the USB driver. It
+requires a 15 MHz crystal (not a ceramic resonator and not a calibrated RC
+oscillator).
+
+See usbdrv.h for a description of the entire driver.
+
+Since almost all of this code is timing critical, don't change unless you
+really know what you are doing! Many parts require not only a maximum number
+of CPU cycles, but even an exact number of cycles!
+*/
+
+;max stack usage: [ret(2), YL, SREG, YH, bitcnt, shift, x1, x2, x3, x4, cnt] = 12 bytes
+;nominal frequency: 15 MHz -> 10.0 cycles per bit, 80.0 cycles per byte
+; Numbers in brackets are clocks counted from center of last sync bit
+; when instruction starts
+
+;----------------------------------------------------------------------------
+; order of registers pushed:
+; YL, SREG [sofError] YH, shift, x1, x2, x3, bitcnt, cnt, x4
+;----------------------------------------------------------------------------
+USB_INTR_VECTOR:
+ push YL ;2 push only what is necessary to sync with edge ASAP
+ in YL, SREG ;1
+ push YL ;2
+;----------------------------------------------------------------------------
+; Synchronize with sync pattern:
+;
+; sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K]
+; sync up with J to K edge during sync pattern -- use fastest possible loops
+;The first part waits at most 1 bit long since we must be in sync pattern.
+;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to
+;waitForJ, ensure that this prerequisite is met.
+waitForJ:
+ inc YL
+ sbis USBIN, USBMINUS
+ brne waitForJ ; just make sure we have ANY timeout
+;-------------------------------------------------------------------------------
+; The following code results in a sampling window of < 1/4 bit
+; which meets the spec.
+;-------------------------------------------------------------------------------
+waitForK: ;-
+ sbis USBIN, USBMINUS ;1 [00] <-- sample
+ rjmp foundK ;2 [01]
+ sbis USBIN, USBMINUS ; <-- sample
+ rjmp foundK
+ sbis USBIN, USBMINUS ; <-- sample
+ rjmp foundK
+ sbis USBIN, USBMINUS ; <-- sample
+ rjmp foundK
+ sbis USBIN, USBMINUS ; <-- sample
+ rjmp foundK
+ sbis USBIN, USBMINUS ; <-- sample
+ rjmp foundK
+#if USB_COUNT_SOF
+ lds YL, usbSofCount
+ inc YL
+ sts usbSofCount, YL
+#endif /* USB_COUNT_SOF */
+#ifdef USB_SOF_HOOK
+ USB_SOF_HOOK
+#endif
+ rjmp sofError
+;------------------------------------------------------------------------------
+; {3, 5} after falling D- edge, average delay: 4 cycles [we want 5 for
+; center sampling]
+; we have 1 bit time for setup purposes, then sample again.
+; Numbers in brackets are cycles from center of first sync (double K)
+; bit after the instruction
+;------------------------------------------------------------------------------
+foundK: ;- [02]
+ lds YL, usbInputBufOffset;2 [03+04] tx loop
+ push YH ;2 [05+06]
+ clr YH ;1 [07]
+ subi YL, lo8(-(usbRxBuf)) ;1 [08] [rx loop init]
+ sbci YH, hi8(-(usbRxBuf)) ;1 [09] [rx loop init]
+ push shift ;2 [10+11]
+ ser shift ;1 [12]
+ sbis USBIN, USBMINUS ;1 [-1] [13] <--sample:we want two bits K (sample 1 cycle too early)
+ rjmp haveTwoBitsK ;2 [00] [14]
+ pop shift ;2 [15+16] undo the push from before
+ pop YH ;2 [17+18] undo the push from before
+ rjmp waitForK ;2 [19+20] this was not the end of sync, retry
+; The entire loop from waitForK until rjmp waitForK above must not exceed two
+; bit times (= 20 cycles).
+
+;----------------------------------------------------------------------------
+; push more registers and initialize values while we sample the first bits:
+;----------------------------------------------------------------------------
+haveTwoBitsK: ;- [01]
+ push x1 ;2 [02+03]
+ push x2 ;2 [04+05]
+ push x3 ;2 [06+07]
+ push bitcnt ;2 [08+09]
+ in x1, USBIN ;1 [00] [10] <-- sample bit 0
+ bst x1, USBMINUS ;1 [01]
+ bld shift, 0 ;1 [02]
+ push cnt ;2 [03+04]
+ ldi cnt, USB_BUFSIZE ;1 [05]
+ push x4 ;2 [06+07] tx loop
+ rjmp rxLoop ;2 [08]
+;----------------------------------------------------------------------------
+; Receiver loop (numbers in brackets are cycles within byte after instr)
+;----------------------------------------------------------------------------
+unstuff0: ;- [07] (branch taken)
+ andi x3, ~0x01 ;1 [08]
+ mov x1, x2 ;1 [09] x2 contains last sampled (stuffed) bit
+ in x2, USBIN ;1 [00] [10] <-- sample bit 1 again
+ andi x2, USBMASK ;1 [01]
+ breq se0Hop ;1 [02] SE0 check for bit 1
+ ori shift, 0x01 ;1 [03] 0b00000001
+ nop ;1 [04]
+ rjmp didUnstuff0 ;2 [05]
+;-----------------------------------------------------
+unstuff1: ;- [05] (branch taken)
+ mov x2, x1 ;1 [06] x1 contains last sampled (stuffed) bit
+ andi x3, ~0x02 ;1 [07]
+ ori shift, 0x02 ;1 [08] 0b00000010
+ nop ;1 [09]
+ in x1, USBIN ;1 [00] [10] <-- sample bit 2 again
+ andi x1, USBMASK ;1 [01]
+ breq se0Hop ;1 [02] SE0 check for bit 2
+ rjmp didUnstuff1 ;2 [03]
+;-----------------------------------------------------
+unstuff2: ;- [05] (branch taken)
+ andi x3, ~0x04 ;1 [06]
+ ori shift, 0x04 ;1 [07] 0b00000100
+ mov x1, x2 ;1 [08] x2 contains last sampled (stuffed) bit
+ nop ;1 [09]
+ in x2, USBIN ;1 [00] [10] <-- sample bit 3
+ andi x2, USBMASK ;1 [01]
+ breq se0Hop ;1 [02] SE0 check for bit 3
+ rjmp didUnstuff2 ;2 [03]
+;-----------------------------------------------------
+unstuff3: ;- [00] [10] (branch taken)
+ in x2, USBIN ;1 [01] [11] <-- sample stuffed bit 3 one cycle too late
+ andi x2, USBMASK ;1 [02]
+ breq se0Hop ;1 [03] SE0 check for stuffed bit 3
+ andi x3, ~0x08 ;1 [04]
+ ori shift, 0x08 ;1 [05] 0b00001000
+ rjmp didUnstuff3 ;2 [06]
+;----------------------------------------------------------------------------
+; extra jobs done during bit interval:
+;
+; bit 0: store, clear [SE0 is unreliable here due to bit dribbling in hubs],
+; overflow check, jump to the head of rxLoop
+; bit 1: SE0 check
+; bit 2: SE0 check, recovery from delay [bit 0 tasks took too long]
+; bit 3: SE0 check, recovery from delay [bit 0 tasks took too long]
+; bit 4: SE0 check, none
+; bit 5: SE0 check, none
+; bit 6: SE0 check, none
+; bit 7: SE0 check, reconstruct: x3 is 0 at bit locations we changed, 1 at others
+;----------------------------------------------------------------------------
+rxLoop: ;- [09]
+ in x2, USBIN ;1 [00] [10] <-- sample bit 1 (or possibly bit 0 stuffed)
+ andi x2, USBMASK ;1 [01]
+ brne SkipSe0Hop ;1 [02]
+se0Hop: ;- [02]
+ rjmp se0 ;2 [03] SE0 check for bit 1
+SkipSe0Hop: ;- [03]
+ ser x3 ;1 [04]
+ andi shift, 0xf9 ;1 [05] 0b11111001
+ breq unstuff0 ;1 [06]
+didUnstuff0: ;- [06]
+ eor x1, x2 ;1 [07]
+ bst x1, USBMINUS ;1 [08]
+ bld shift, 1 ;1 [09]
+ in x1, USBIN ;1 [00] [10] <-- sample bit 2 (or possibly bit 1 stuffed)
+ andi x1, USBMASK ;1 [01]
+ breq se0Hop ;1 [02] SE0 check for bit 2
+ andi shift, 0xf3 ;1 [03] 0b11110011
+ breq unstuff1 ;1 [04] do remaining work for bit 1
+didUnstuff1: ;- [04]
+ eor x2, x1 ;1 [05]
+ bst x2, USBMINUS ;1 [06]
+ bld shift, 2 ;1 [07]
+ nop2 ;2 [08+09]
+ in x2, USBIN ;1 [00] [10] <-- sample bit 3 (or possibly bit 2 stuffed)
+ andi x2, USBMASK ;1 [01]
+ breq se0Hop ;1 [02] SE0 check for bit 3
+ andi shift, 0xe7 ;1 [03] 0b11100111
+ breq unstuff2 ;1 [04]
+didUnstuff2: ;- [04]
+ eor x1, x2 ;1 [05]
+ bst x1, USBMINUS ;1 [06]
+ bld shift, 3 ;1 [07]
+didUnstuff3: ;- [07]
+ andi shift, 0xcf ;1 [08] 0b11001111
+ breq unstuff3 ;1 [09]
+ in x1, USBIN ;1 [00] [10] <-- sample bit 4
+ andi x1, USBMASK ;1 [01]
+ breq se0Hop ;1 [02] SE0 check for bit 4
+ eor x2, x1 ;1 [03]
+ bst x2, USBMINUS ;1 [04]
+ bld shift, 4 ;1 [05]
+didUnstuff4: ;- [05]
+ andi shift, 0x9f ;1 [06] 0b10011111
+ breq unstuff4 ;1 [07]
+ nop2 ;2 [08+09]
+ in x2, USBIN ;1 [00] [10] <-- sample bit 5
+ andi x2, USBMASK ;1 [01]
+ breq se0 ;1 [02] SE0 check for bit 5
+ eor x1, x2 ;1 [03]
+ bst x1, USBMINUS ;1 [04]
+ bld shift, 5 ;1 [05]
+didUnstuff5: ;- [05]
+ andi shift, 0x3f ;1 [06] 0b00111111
+ breq unstuff5 ;1 [07]
+ nop2 ;2 [08+09]
+ in x1, USBIN ;1 [00] [10] <-- sample bit 6
+ andi x1, USBMASK ;1 [01]
+ breq se0 ;1 [02] SE0 check for bit 6
+ eor x2, x1 ;1 [03]
+ bst x2, USBMINUS ;1 [04]
+ bld shift, 6 ;1 [05]
+didUnstuff6: ;- [05]
+ cpi shift, 0x02 ;1 [06] 0b00000010
+ brlo unstuff6 ;1 [07]
+ nop2 ;2 [08+09]
+ in x2, USBIN ;1 [00] [10] <-- sample bit 7
+ andi x2, USBMASK ;1 [01]
+ breq se0 ;1 [02] SE0 check for bit 7
+ eor x1, x2 ;1 [03]
+ bst x1, USBMINUS ;1 [04]
+ bld shift, 7 ;1 [05]
+didUnstuff7: ;- [05]
+ cpi shift, 0x04 ;1 [06] 0b00000100
+ brlo unstuff7 ;1 [07]
+ eor x3, shift ;1 [08] reconstruct: x3 is 0 at bit locations we changed, 1 at others
+ nop ;1 [09]
+ in x1, USBIN ;1 [00] [10] <-- sample bit 0
+ st y+, x3 ;2 [01+02] store data
+ eor x2, x1 ;1 [03]
+ bst x2, USBMINUS ;1 [04]
+ bld shift, 0 ;1 [05]
+ subi cnt, 1 ;1 [06]
+ brcs overflow ;1 [07]
+ rjmp rxLoop ;2 [08]
+;-----------------------------------------------------
+unstuff4: ;- [08]
+ andi x3, ~0x10 ;1 [09]
+ in x1, USBIN ;1 [00] [10] <-- sample stuffed bit 4
+ andi x1, USBMASK ;1 [01]
+ breq se0 ;1 [02] SE0 check for stuffed bit 4
+ ori shift, 0x10 ;1 [03]
+ rjmp didUnstuff4 ;2 [04]
+;-----------------------------------------------------
+unstuff5: ;- [08]
+ ori shift, 0x20 ;1 [09]
+ in x2, USBIN ;1 [00] [10] <-- sample stuffed bit 5
+ andi x2, USBMASK ;1 [01]
+ breq se0 ;1 [02] SE0 check for stuffed bit 5
+ andi x3, ~0x20 ;1 [03]
+ rjmp didUnstuff5 ;2 [04]
+;-----------------------------------------------------
+unstuff6: ;- [08]
+ andi x3, ~0x40 ;1 [09]
+ in x1, USBIN ;1 [00] [10] <-- sample stuffed bit 6
+ andi x1, USBMASK ;1 [01]
+ breq se0 ;1 [02] SE0 check for stuffed bit 6
+ ori shift, 0x40 ;1 [03]
+ rjmp didUnstuff6 ;2 [04]
+;-----------------------------------------------------
+unstuff7: ;- [08]
+ andi x3, ~0x80 ;1 [09]
+ in x2, USBIN ;1 [00] [10] <-- sample stuffed bit 7
+ andi x2, USBMASK ;1 [01]
+ breq se0 ;1 [02] SE0 check for stuffed bit 7
+ ori shift, 0x80 ;1 [03]
+ rjmp didUnstuff7 ;2 [04]
+
+macro POP_STANDARD ; 16 cycles
+ pop x4
+ pop cnt
+ pop bitcnt
+ pop x3
+ pop x2
+ pop x1
+ pop shift
+ pop YH
+ endm
+macro POP_RETI ; 5 cycles
+ pop YL
+ out SREG, YL
+ pop YL
+ endm
+
+#include "asmcommon.inc"
+
+;---------------------------------------------------------------------------
+; USB spec says:
+; idle = J
+; J = (D+ = 0), (D- = 1)
+; K = (D+ = 1), (D- = 0)
+; Spec allows 7.5 bit times from EOP to SOP for replies
+;---------------------------------------------------------------------------
+bitstuffN: ;- [04]
+ eor x1, x4 ;1 [05]
+ clr x2 ;1 [06]
+ nop ;1 [07]
+ rjmp didStuffN ;1 [08]
+;---------------------------------------------------------------------------
+bitstuff6: ;- [04]
+ eor x1, x4 ;1 [05]
+ clr x2 ;1 [06]
+ rjmp didStuff6 ;1 [07]
+;---------------------------------------------------------------------------
+bitstuff7: ;- [02]
+ eor x1, x4 ;1 [03]
+ clr x2 ;1 [06]
+ nop ;1 [05]
+ rjmp didStuff7 ;1 [06]
+;---------------------------------------------------------------------------
+sendNakAndReti: ;- [-19]
+ ldi x3, USBPID_NAK ;1 [-18]
+ rjmp sendX3AndReti ;1 [-17]
+;---------------------------------------------------------------------------
+sendAckAndReti: ;- [-17]
+ ldi cnt, USBPID_ACK ;1 [-16]
+sendCntAndReti: ;- [-16]
+ mov x3, cnt ;1 [-15]
+sendX3AndReti: ;- [-15]
+ ldi YL, 20 ;1 [-14] x3==r20 address is 20
+ ldi YH, 0 ;1 [-13]
+ ldi cnt, 2 ;1 [-12]
+; rjmp usbSendAndReti fallthrough
+;---------------------------------------------------------------------------
+;usbSend:
+;pointer to data in 'Y'
+;number of bytes in 'cnt' -- including sync byte [range 2 ... 12]
+;uses: x1...x4, btcnt, shift, cnt, Y
+;Numbers in brackets are time since first bit of sync pattern is sent
+;We need not to match the transfer rate exactly because the spec demands
+;only 1.5% precision anyway.
+usbSendAndReti: ;- [-13] 13 cycles until SOP
+ in x2, USBDDR ;1 [-12]
+ ori x2, USBMASK ;1 [-11]
+ sbi USBOUT, USBMINUS ;2 [-09-10] prepare idle state; D+ and D- must have been 0 (no pullups)
+ in x1, USBOUT ;1 [-08] port mirror for tx loop
+ out USBDDR, x2 ;1 [-07] <- acquire bus
+ ; need not init x2 (bitstuff history) because sync starts with 0
+ ldi x4, USBMASK ;1 [-06] exor mask
+ ldi shift, 0x80 ;1 [-05] sync byte is first byte sent
+ ldi bitcnt, 6 ;1 [-04]
+txBitLoop: ;- [-04] [06]
+ sbrs shift, 0 ;1 [-03] [07]
+ eor x1, x4 ;1 [-02] [08]
+ ror shift ;1 [-01] [09]
+didStuffN: ;- [09]
+ out USBOUT, x1 ;1 [00] [10] <-- out N
+ ror x2 ;1 [01]
+ cpi x2, 0xfc ;1 [02]
+ brcc bitstuffN ;1 [03]
+ dec bitcnt ;1 [04]
+ brne txBitLoop ;1 [05]
+ sbrs shift, 0 ;1 [06]
+ eor x1, x4 ;1 [07]
+ ror shift ;1 [08]
+didStuff6: ;- [08]
+ nop ;1 [09]
+ out USBOUT, x1 ;1 [00] [10] <-- out 6
+ ror x2 ;1 [01]
+ cpi x2, 0xfc ;1 [02]
+ brcc bitstuff6 ;1 [03]
+ sbrs shift, 0 ;1 [04]
+ eor x1, x4 ;1 [05]
+ ror shift ;1 [06]
+ ror x2 ;1 [07]
+didStuff7: ;- [07]
+ ldi bitcnt, 6 ;1 [08]
+ cpi x2, 0xfc ;1 [09]
+ out USBOUT, x1 ;1 [00] [10] <-- out 7
+ brcc bitstuff7 ;1 [01]
+ ld shift, y+ ;2 [02+03]
+ dec cnt ;1 [04]
+ brne txBitLoop ;1 [05]
+makeSE0:
+ cbr x1, USBMASK ;1 [06] prepare SE0 [spec says EOP may be 19 to 23 cycles]
+ lds x2, usbNewDeviceAddr;2 [07+08]
+ lsl x2 ;1 [09] we compare with left shifted address
+;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm:
+;set address only after data packet was sent, not after handshake
+ out USBOUT, x1 ;1 [00] [10] <-- out SE0-- from now 2 bits==20 cycl. until bus idle
+ subi YL, 20 + 2 ;1 [01] Only assign address on data packets, not ACK/NAK in x3
+ sbci YH, 0 ;1 [02]
+ breq skipAddrAssign ;1 [03]
+ sts usbDeviceAddr, x2 ;2 [04+05] if not skipped: SE0 is one cycle longer
+;----------------------------------------------------------------------------
+;end of usbDeviceAddress transfer
+skipAddrAssign: ;- [03/04]
+ ldi x2, 1<<USB_INTR_PENDING_BIT ;1 [05] int0 occurred during TX -- clear pending flag
+ USB_STORE_PENDING(x2) ;1 [06]
+ ori x1, USBIDLE ;1 [07]
+ in x2, USBDDR ;1 [08]
+ cbr x2, USBMASK ;1 [09] set both pins to input
+ mov x3, x1 ;1 [10]
+ cbr x3, USBMASK ;1 [11] configure no pullup on both pins
+ ldi x4, 3 ;1 [12]
+se0Delay: ;- [12] [15]
+ dec x4 ;1 [13] [16]
+ brne se0Delay ;1 [14] [17]
+ nop2 ;2 [18+19]
+ out USBOUT, x1 ;1 [20] <--out J (idle) -- end of SE0 (EOP sig.)
+ out USBDDR, x2 ;1 [21] <--release bus now
+ out USBOUT, x3 ;1 [22] <--ensure no pull-up resistors are active
+ rjmp doReturn ;1 [23]
+;---------------------------------------------------------------------------
diff --git a/tmk_core/protocol/vusb/usbdrv/usbdrvasm16.inc b/tmk_core/protocol/vusb/usbdrv/usbdrvasm16.inc
new file mode 100644
index 000000000..207b6e48a
--- /dev/null
+++ b/tmk_core/protocol/vusb/usbdrv/usbdrvasm16.inc
@@ -0,0 +1,346 @@
+/* Name: usbdrvasm16.inc
+ * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
+ * Author: Christian Starkjohann
+ * Creation Date: 2007-06-15
+ * Tabsize: 4
+ * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
+ * Revision: $Id: usbdrvasm16.inc 760 2009-08-09 18:59:43Z cs $
+ */
+
+/* Do not link this file! Link usbdrvasm.S instead, which includes the
+ * appropriate implementation!
+ */
+
+/*
+General Description:
+This file is the 16 MHz version of the asssembler part of the USB driver. It
+requires a 16 MHz crystal (not a ceramic resonator and not a calibrated RC
+oscillator).
+
+See usbdrv.h for a description of the entire driver.
+
+Since almost all of this code is timing critical, don't change unless you
+really know what you are doing! Many parts require not only a maximum number
+of CPU cycles, but even an exact number of cycles!
+*/
+
+;max stack usage: [ret(2), YL, SREG, YH, bitcnt, shift, x1, x2, x3, x4, cnt] = 12 bytes
+;nominal frequency: 16 MHz -> 10.6666666 cycles per bit, 85.333333333 cycles per byte
+; Numbers in brackets are clocks counted from center of last sync bit
+; when instruction starts
+
+USB_INTR_VECTOR:
+;order of registers pushed: YL, SREG YH, [sofError], bitcnt, shift, x1, x2, x3, x4, cnt
+ push YL ;[-25] push only what is necessary to sync with edge ASAP
+ in YL, SREG ;[-23]
+ push YL ;[-22]
+ push YH ;[-20]
+;----------------------------------------------------------------------------
+; Synchronize with sync pattern:
+;----------------------------------------------------------------------------
+;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K]
+;sync up with J to K edge during sync pattern -- use fastest possible loops
+;The first part waits at most 1 bit long since we must be in sync pattern.
+;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to
+;waitForJ, ensure that this prerequisite is met.
+waitForJ:
+ inc YL
+ sbis USBIN, USBMINUS
+ brne waitForJ ; just make sure we have ANY timeout
+waitForK:
+;The following code results in a sampling window of < 1/4 bit which meets the spec.
+ sbis USBIN, USBMINUS ;[-15]
+ rjmp foundK ;[-14]
+ sbis USBIN, USBMINUS
+ rjmp foundK
+ sbis USBIN, USBMINUS
+ rjmp foundK
+ sbis USBIN, USBMINUS
+ rjmp foundK
+ sbis USBIN, USBMINUS
+ rjmp foundK
+ sbis USBIN, USBMINUS
+ rjmp foundK
+#if USB_COUNT_SOF
+ lds YL, usbSofCount
+ inc YL
+ sts usbSofCount, YL
+#endif /* USB_COUNT_SOF */
+#ifdef USB_SOF_HOOK
+ USB_SOF_HOOK
+#endif
+ rjmp sofError
+foundK: ;[-12]
+;{3, 5} after falling D- edge, average delay: 4 cycles [we want 5 for center sampling]
+;we have 1 bit time for setup purposes, then sample again. Numbers in brackets
+;are cycles from center of first sync (double K) bit after the instruction
+ push bitcnt ;[-12]
+; [---] ;[-11]
+ lds YL, usbInputBufOffset;[-10]
+; [---] ;[-9]
+ clr YH ;[-8]
+ subi YL, lo8(-(usbRxBuf));[-7] [rx loop init]
+ sbci YH, hi8(-(usbRxBuf));[-6] [rx loop init]
+ push shift ;[-5]
+; [---] ;[-4]
+ ldi bitcnt, 0x55 ;[-3] [rx loop init]
+ sbis USBIN, USBMINUS ;[-2] we want two bits K (sample 2 cycles too early)
+ rjmp haveTwoBitsK ;[-1]
+ pop shift ;[0] undo the push from before
+ pop bitcnt ;[2] undo the push from before
+ rjmp waitForK ;[4] this was not the end of sync, retry
+; The entire loop from waitForK until rjmp waitForK above must not exceed two
+; bit times (= 21 cycles).
+
+;----------------------------------------------------------------------------
+; push more registers and initialize values while we sample the first bits:
+;----------------------------------------------------------------------------
+haveTwoBitsK:
+ push x1 ;[1]
+ push x2 ;[3]
+ push x3 ;[5]
+ ldi shift, 0 ;[7]
+ ldi x3, 1<<4 ;[8] [rx loop init] first sample is inverse bit, compensate that
+ push x4 ;[9] == leap
+
+ in x1, USBIN ;[11] <-- sample bit 0
+ andi x1, USBMASK ;[12]
+ bst x1, USBMINUS ;[13]
+ bld shift, 7 ;[14]
+ push cnt ;[15]
+ ldi leap, 0 ;[17] [rx loop init]
+ ldi cnt, USB_BUFSIZE;[18] [rx loop init]
+ rjmp rxbit1 ;[19] arrives at [21]
+
+;----------------------------------------------------------------------------
+; Receiver loop (numbers in brackets are cycles within byte after instr)
+;----------------------------------------------------------------------------
+
+; duration of unstuffing code should be 10.66666667 cycles. We adjust "leap"
+; accordingly to approximate this value in the long run.
+
+unstuff6:
+ andi x2, USBMASK ;[03]
+ ori x3, 1<<6 ;[04] will not be shifted any more
+ andi shift, ~0x80;[05]
+ mov x1, x2 ;[06] sampled bit 7 is actually re-sampled bit 6
+ subi leap, -1 ;[07] total duration = 11 bits -> subtract 1/3
+ rjmp didUnstuff6 ;[08]
+
+unstuff7:
+ ori x3, 1<<7 ;[09] will not be shifted any more
+ in x2, USBIN ;[00] [10] re-sample bit 7
+ andi x2, USBMASK ;[01]
+ andi shift, ~0x80;[02]
+ subi leap, 2 ;[03] total duration = 10 bits -> add 1/3
+ rjmp didUnstuff7 ;[04]
+
+unstuffEven:
+ ori x3, 1<<6 ;[09] will be shifted right 6 times for bit 0
+ in x1, USBIN ;[00] [10]
+ andi shift, ~0x80;[01]
+ andi x1, USBMASK ;[02]
+ breq se0 ;[03]
+ subi leap, -1 ;[04] total duration = 11 bits -> subtract 1/3
+ nop2 ;[05]
+ rjmp didUnstuffE ;[06]
+
+unstuffOdd:
+ ori x3, 1<<5 ;[09] will be shifted right 4 times for bit 1
+ in x2, USBIN ;[00] [10]
+ andi shift, ~0x80;[01]
+ andi x2, USBMASK ;[02]
+ breq se0 ;[03]
+ subi leap, -1 ;[04] total duration = 11 bits -> subtract 1/3
+ nop2 ;[05]
+ rjmp didUnstuffO ;[06]
+
+rxByteLoop:
+ andi x1, USBMASK ;[03]
+ eor x2, x1 ;[04]
+ subi leap, 1 ;[05]
+ brpl skipLeap ;[06]
+ subi leap, -3 ;1 one leap cycle every 3rd byte -> 85 + 1/3 cycles per byte
+ nop ;1
+skipLeap:
+ subi x2, 1 ;[08]
+ ror shift ;[09]
+didUnstuff6:
+ cpi shift, 0xfc ;[10]
+ in x2, USBIN ;[00] [11] <-- sample bit 7
+ brcc unstuff6 ;[01]
+ andi x2, USBMASK ;[02]
+ eor x1, x2 ;[03]
+ subi x1, 1 ;[04]
+ ror shift ;[05]
+didUnstuff7:
+ cpi shift, 0xfc ;[06]
+ brcc unstuff7 ;[07]
+ eor x3, shift ;[08] reconstruct: x3 is 1 at bit locations we changed, 0 at others
+ st y+, x3 ;[09] store data
+rxBitLoop:
+ in x1, USBIN ;[00] [11] <-- sample bit 0/2/4
+ andi x1, USBMASK ;[01]
+ eor x2, x1 ;[02]
+ andi x3, 0x3f ;[03] topmost two bits reserved for 6 and 7
+ subi x2, 1 ;[04]
+ ror shift ;[05]
+ cpi shift, 0xfc ;[06]
+ brcc unstuffEven ;[07]
+didUnstuffE:
+ lsr x3 ;[08]
+ lsr x3 ;[09]
+rxbit1:
+ in x2, USBIN ;[00] [10] <-- sample bit 1/3/5
+ andi x2, USBMASK ;[01]
+ breq se0 ;[02]
+ eor x1, x2 ;[03]
+ subi x1, 1 ;[04]
+ ror shift ;[05]
+ cpi shift, 0xfc ;[06]
+ brcc unstuffOdd ;[07]
+didUnstuffO:
+ subi bitcnt, 0xab;[08] == addi 0x55, 0x55 = 0x100/3
+ brcs rxBitLoop ;[09]
+
+ subi cnt, 1 ;[10]
+ in x1, USBIN ;[00] [11] <-- sample bit 6
+ brcc rxByteLoop ;[01]
+ rjmp overflow
+
+macro POP_STANDARD ; 14 cycles
+ pop cnt
+ pop x4
+ pop x3
+ pop x2
+ pop x1
+ pop shift
+ pop bitcnt
+ endm
+macro POP_RETI ; 7 cycles
+ pop YH
+ pop YL
+ out SREG, YL
+ pop YL
+ endm
+
+#include "asmcommon.inc"
+
+; USB spec says:
+; idle = J
+; J = (D+ = 0), (D- = 1)
+; K = (D+ = 1), (D- = 0)
+; Spec allows 7.5 bit times from EOP to SOP for replies
+
+bitstuffN:
+ eor x1, x4 ;[5]
+ ldi x2, 0 ;[6]
+ nop2 ;[7]
+ nop ;[9]
+ out USBOUT, x1 ;[10] <-- out
+ rjmp didStuffN ;[0]
+
+bitstuff6:
+ eor x1, x4 ;[5]
+ ldi x2, 0 ;[6] Carry is zero due to brcc
+ rol shift ;[7] compensate for ror shift at branch destination
+ rjmp didStuff6 ;[8]
+
+bitstuff7:
+ ldi x2, 0 ;[2] Carry is zero due to brcc
+ rjmp didStuff7 ;[3]
+
+
+sendNakAndReti:
+ ldi x3, USBPID_NAK ;[-18]
+ rjmp sendX3AndReti ;[-17]
+sendAckAndReti:
+ ldi cnt, USBPID_ACK ;[-17]
+sendCntAndReti:
+ mov x3, cnt ;[-16]
+sendX3AndReti:
+ ldi YL, 20 ;[-15] x3==r20 address is 20
+ ldi YH, 0 ;[-14]
+ ldi cnt, 2 ;[-13]
+; rjmp usbSendAndReti fallthrough
+
+;usbSend:
+;pointer to data in 'Y'
+;number of bytes in 'cnt' -- including sync byte [range 2 ... 12]
+;uses: x1...x4, btcnt, shift, cnt, Y
+;Numbers in brackets are time since first bit of sync pattern is sent
+;We don't match the transfer rate exactly (don't insert leap cycles every third
+;byte) because the spec demands only 1.5% precision anyway.
+usbSendAndReti: ; 12 cycles until SOP
+ in x2, USBDDR ;[-12]
+ ori x2, USBMASK ;[-11]
+ sbi USBOUT, USBMINUS;[-10] prepare idle state; D+ and D- must have been 0 (no pullups)
+ in x1, USBOUT ;[-8] port mirror for tx loop
+ out USBDDR, x2 ;[-7] <- acquire bus
+; need not init x2 (bitstuff history) because sync starts with 0
+ ldi x4, USBMASK ;[-6] exor mask
+ ldi shift, 0x80 ;[-5] sync byte is first byte sent
+txByteLoop:
+ ldi bitcnt, 0x35 ;[-4] [6] binary 0011 0101
+txBitLoop:
+ sbrs shift, 0 ;[-3] [7]
+ eor x1, x4 ;[-2] [8]
+ out USBOUT, x1 ;[-1] [9] <-- out N
+ ror shift ;[0] [10]
+ ror x2 ;[1]
+didStuffN:
+ cpi x2, 0xfc ;[2]
+ brcc bitstuffN ;[3]
+ lsr bitcnt ;[4]
+ brcc txBitLoop ;[5]
+ brne txBitLoop ;[6]
+
+ sbrs shift, 0 ;[7]
+ eor x1, x4 ;[8]
+didStuff6:
+ out USBOUT, x1 ;[-1] [9] <-- out 6
+ ror shift ;[0] [10]
+ ror x2 ;[1]
+ cpi x2, 0xfc ;[2]
+ brcc bitstuff6 ;[3]
+ ror shift ;[4]
+didStuff7:
+ ror x2 ;[5]
+ sbrs x2, 7 ;[6]
+ eor x1, x4 ;[7]
+ nop ;[8]
+ cpi x2, 0xfc ;[9]
+ out USBOUT, x1 ;[-1][10] <-- out 7
+ brcc bitstuff7 ;[0] [11]
+ ld shift, y+ ;[1]
+ dec cnt ;[3]
+ brne txByteLoop ;[4]
+;make SE0:
+ cbr x1, USBMASK ;[5] prepare SE0 [spec says EOP may be 21 to 25 cycles]
+ lds x2, usbNewDeviceAddr;[6]
+ lsl x2 ;[8] we compare with left shifted address
+ subi YL, 20 + 2 ;[9] Only assign address on data packets, not ACK/NAK in x3
+ sbci YH, 0 ;[10]
+ out USBOUT, x1 ;[11] <-- out SE0 -- from now 2 bits = 22 cycles until bus idle
+;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm:
+;set address only after data packet was sent, not after handshake
+ breq skipAddrAssign ;[0]
+ sts usbDeviceAddr, x2; if not skipped: SE0 is one cycle longer
+skipAddrAssign:
+;end of usbDeviceAddress transfer
+ ldi x2, 1<<USB_INTR_PENDING_BIT;[2] int0 occurred during TX -- clear pending flag
+ USB_STORE_PENDING(x2) ;[3]
+ ori x1, USBIDLE ;[4]
+ in x2, USBDDR ;[5]
+ cbr x2, USBMASK ;[6] set both pins to input
+ mov x3, x1 ;[7]
+ cbr x3, USBMASK ;[8] configure no pullup on both pins
+ ldi x4, 4 ;[9]
+se0Delay:
+ dec x4 ;[10] [13] [16] [19]
+ brne se0Delay ;[11] [14] [17] [20]
+ out USBOUT, x1 ;[21] <-- out J (idle) -- end of SE0 (EOP signal)
+ out USBDDR, x2 ;[22] <-- release bus now
+ out USBOUT, x3 ;[23] <-- ensure no pull-up resistors are active
+ rjmp doReturn
diff --git a/tmk_core/protocol/vusb/usbdrv/usbdrvasm165.inc b/tmk_core/protocol/vusb/usbdrv/usbdrvasm165.inc
new file mode 100644
index 000000000..79b3c61cf
--- /dev/null
+++ b/tmk_core/protocol/vusb/usbdrv/usbdrvasm165.inc
@@ -0,0 +1,453 @@
+/* Name: usbdrvasm165.inc
+ * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
+ * Author: Christian Starkjohann
+ * Creation Date: 2007-04-22
+ * Tabsize: 4
+ * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
+ * Revision: $Id: usbdrvasm165.inc 740 2009-04-13 18:23:31Z cs $
+ */
+
+/* Do not link this file! Link usbdrvasm.S instead, which includes the
+ * appropriate implementation!
+ */
+
+/*
+General Description:
+This file is the 16.5 MHz version of the USB driver. It is intended for the
+ATTiny45 and similar controllers running on 16.5 MHz internal RC oscillator.
+This version contains a phase locked loop in the receiver routine to cope with
+slight clock rate deviations of up to +/- 1%.
+
+See usbdrv.h for a description of the entire driver.
+
+Since almost all of this code is timing critical, don't change unless you
+really know what you are doing! Many parts require not only a maximum number
+of CPU cycles, but even an exact number of cycles!
+*/
+
+;Software-receiver engine. Strict timing! Don't change unless you can preserve timing!
+;interrupt response time: 4 cycles + insn running = 7 max if interrupts always enabled
+;max allowable interrupt latency: 59 cycles -> max 52 cycles interrupt disable
+;max stack usage: [ret(2), r0, SREG, YL, YH, shift, x1, x2, x3, x4, cnt] = 12 bytes
+;nominal frequency: 16.5 MHz -> 11 cycles per bit
+; 16.3125 MHz < F_CPU < 16.6875 MHz (+/- 1.1%)
+; Numbers in brackets are clocks counted from center of last sync bit
+; when instruction starts
+
+
+USB_INTR_VECTOR:
+;order of registers pushed: YL, SREG [sofError], r0, YH, shift, x1, x2, x3, x4, cnt
+ push YL ;[-23] push only what is necessary to sync with edge ASAP
+ in YL, SREG ;[-21]
+ push YL ;[-20]
+;----------------------------------------------------------------------------
+; Synchronize with sync pattern:
+;----------------------------------------------------------------------------
+;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K]
+;sync up with J to K edge during sync pattern -- use fastest possible loops
+;The first part waits at most 1 bit long since we must be in sync pattern.
+;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to
+;waitForJ, ensure that this prerequisite is met.
+waitForJ:
+ inc YL
+ sbis USBIN, USBMINUS
+ brne waitForJ ; just make sure we have ANY timeout
+waitForK:
+;The following code results in a sampling window of < 1/4 bit which meets the spec.
+ sbis USBIN, USBMINUS ;[-15]
+ rjmp foundK ;[-14]
+ sbis USBIN, USBMINUS
+ rjmp foundK
+ sbis USBIN, USBMINUS
+ rjmp foundK
+ sbis USBIN, USBMINUS
+ rjmp foundK
+ sbis USBIN, USBMINUS
+ rjmp foundK
+ sbis USBIN, USBMINUS
+ rjmp foundK
+#if USB_COUNT_SOF
+ lds YL, usbSofCount
+ inc YL
+ sts usbSofCount, YL
+#endif /* USB_COUNT_SOF */
+#ifdef USB_SOF_HOOK
+ USB_SOF_HOOK
+#endif
+ rjmp sofError
+foundK: ;[-12]
+;{3, 5} after falling D- edge, average delay: 4 cycles [we want 5 for center sampling]
+;we have 1 bit time for setup purposes, then sample again. Numbers in brackets
+;are cycles from center of first sync (double K) bit after the instruction
+ push r0 ;[-12]
+; [---] ;[-11]
+ push YH ;[-10]
+; [---] ;[-9]
+ lds YL, usbInputBufOffset;[-8]
+; [---] ;[-7]
+ clr YH ;[-6]
+ subi YL, lo8(-(usbRxBuf));[-5] [rx loop init]
+ sbci YH, hi8(-(usbRxBuf));[-4] [rx loop init]
+ mov r0, x2 ;[-3] [rx loop init]
+ sbis USBIN, USBMINUS ;[-2] we want two bits K (sample 2 cycles too early)
+ rjmp haveTwoBitsK ;[-1]
+ pop YH ;[0] undo the pushes from before
+ pop r0 ;[2]
+ rjmp waitForK ;[4] this was not the end of sync, retry
+; The entire loop from waitForK until rjmp waitForK above must not exceed two
+; bit times (= 22 cycles).
+
+;----------------------------------------------------------------------------
+; push more registers and initialize values while we sample the first bits:
+;----------------------------------------------------------------------------
+haveTwoBitsK: ;[1]
+ push shift ;[1]
+ push x1 ;[3]
+ push x2 ;[5]
+ push x3 ;[7]
+ ldi shift, 0xff ;[9] [rx loop init]
+ ori x3, 0xff ;[10] [rx loop init] == ser x3, clear zero flag
+
+ in x1, USBIN ;[11] <-- sample bit 0
+ bst x1, USBMINUS ;[12]
+ bld shift, 0 ;[13]
+ push x4 ;[14] == phase
+; [---] ;[15]
+ push cnt ;[16]
+; [---] ;[17]
+ ldi phase, 0 ;[18] [rx loop init]
+ ldi cnt, USB_BUFSIZE;[19] [rx loop init]
+ rjmp rxbit1 ;[20]
+; [---] ;[21]
+
+;----------------------------------------------------------------------------
+; Receiver loop (numbers in brackets are cycles within byte after instr)
+;----------------------------------------------------------------------------
+/*
+byte oriented operations done during loop:
+bit 0: store data
+bit 1: SE0 check
+bit 2: overflow check
+bit 3: catch up
+bit 4: rjmp to achieve conditional jump range
+bit 5: PLL
+bit 6: catch up
+bit 7: jump, fixup bitstuff
+; 87 [+ 2] cycles
+------------------------------------------------------------------
+*/
+continueWithBit5:
+ in x2, USBIN ;[055] <-- bit 5
+ eor r0, x2 ;[056]
+ or phase, r0 ;[057]
+ sbrc phase, USBMINUS ;[058]
+ lpm ;[059] optional nop3; modifies r0
+ in phase, USBIN ;[060] <-- phase
+ eor x1, x2 ;[061]
+ bst x1, USBMINUS ;[062]
+ bld shift, 5 ;[063]
+ andi shift, 0x3f ;[064]
+ in x1, USBIN ;[065] <-- bit 6
+ breq unstuff5 ;[066] *** unstuff escape
+ eor phase, x1 ;[067]
+ eor x2, x1 ;[068]
+ bst x2, USBMINUS ;[069]
+ bld shift, 6 ;[070]
+didUnstuff6: ;[ ]
+ in r0, USBIN ;[071] <-- phase
+ cpi shift, 0x02 ;[072]
+ brlo unstuff6 ;[073] *** unstuff escape
+didUnstuff5: ;[ ]
+ nop2 ;[074]
+; [---] ;[075]
+ in x2, USBIN ;[076] <-- bit 7
+ eor x1, x2 ;[077]
+ bst x1, USBMINUS ;[078]
+ bld shift, 7 ;[079]
+didUnstuff7: ;[ ]
+ eor r0, x2 ;[080]
+ or phase, r0 ;[081]
+ in r0, USBIN ;[082] <-- phase
+ cpi shift, 0x04 ;[083]
+ brsh rxLoop ;[084]
+; [---] ;[085]
+unstuff7: ;[ ]
+ andi x3, ~0x80 ;[085]
+ ori shift, 0x80 ;[086]
+ in x2, USBIN ;[087] <-- sample stuffed bit 7
+ nop ;[088]
+ rjmp didUnstuff7 ;[089]
+; [---] ;[090]
+ ;[080]
+
+unstuff5: ;[067]
+ eor phase, x1 ;[068]
+ andi x3, ~0x20 ;[069]
+ ori shift, 0x20 ;[070]
+ in r0, USBIN ;[071] <-- phase
+ mov x2, x1 ;[072]
+ nop ;[073]
+ nop2 ;[074]
+; [---] ;[075]
+ in x1, USBIN ;[076] <-- bit 6
+ eor r0, x1 ;[077]
+ or phase, r0 ;[078]
+ eor x2, x1 ;[079]
+ bst x2, USBMINUS ;[080]
+ bld shift, 6 ;[081] no need to check bitstuffing, we just had one
+ in r0, USBIN ;[082] <-- phase
+ rjmp didUnstuff5 ;[083]
+; [---] ;[084]
+ ;[074]
+
+unstuff6: ;[074]
+ andi x3, ~0x40 ;[075]
+ in x1, USBIN ;[076] <-- bit 6 again
+ ori shift, 0x40 ;[077]
+ nop2 ;[078]
+; [---] ;[079]
+ rjmp didUnstuff6 ;[080]
+; [---] ;[081]
+ ;[071]
+
+unstuff0: ;[013]
+ eor r0, x2 ;[014]
+ or phase, r0 ;[015]
+ andi x2, USBMASK ;[016] check for SE0
+ in r0, USBIN ;[017] <-- phase
+ breq didUnstuff0 ;[018] direct jump to se0 would be too long
+ andi x3, ~0x01 ;[019]
+ ori shift, 0x01 ;[020]
+ mov x1, x2 ;[021] mov existing sample
+ in x2, USBIN ;[022] <-- bit 1 again
+ rjmp didUnstuff0 ;[023]
+; [---] ;[024]
+ ;[014]
+
+unstuff1: ;[024]
+ eor r0, x1 ;[025]
+ or phase, r0 ;[026]
+ andi x3, ~0x02 ;[027]
+ in r0, USBIN ;[028] <-- phase
+ ori shift, 0x02 ;[029]
+ mov x2, x1 ;[030]
+ rjmp didUnstuff1 ;[031]
+; [---] ;[032]
+ ;[022]
+
+unstuff2: ;[035]
+ eor r0, x2 ;[036]
+ or phase, r0 ;[037]
+ andi x3, ~0x04 ;[038]
+ in r0, USBIN ;[039] <-- phase
+ ori shift, 0x04 ;[040]
+ mov x1, x2 ;[041]
+ rjmp didUnstuff2 ;[042]
+; [---] ;[043]
+ ;[033]
+
+unstuff3: ;[043]
+ in x2, USBIN ;[044] <-- bit 3 again
+ eor r0, x2 ;[045]
+ or phase, r0 ;[046]
+ andi x3, ~0x08 ;[047]
+ ori shift, 0x08 ;[048]
+ nop ;[049]
+ in r0, USBIN ;[050] <-- phase
+ rjmp didUnstuff3 ;[051]
+; [---] ;[052]
+ ;[042]
+
+unstuff4: ;[053]
+ andi x3, ~0x10 ;[054]
+ in x1, USBIN ;[055] <-- bit 4 again
+ ori shift, 0x10 ;[056]
+ rjmp didUnstuff4 ;[057]
+; [---] ;[058]
+ ;[048]
+
+rxLoop: ;[085]
+ eor x3, shift ;[086] reconstruct: x3 is 0 at bit locations we changed, 1 at others
+ in x1, USBIN ;[000] <-- bit 0
+ st y+, x3 ;[001]
+; [---] ;[002]
+ eor r0, x1 ;[003]
+ or phase, r0 ;[004]
+ eor x2, x1 ;[005]
+ in r0, USBIN ;[006] <-- phase
+ ser x3 ;[007]
+ bst x2, USBMINUS ;[008]
+ bld shift, 0 ;[009]
+ andi shift, 0xf9 ;[010]
+rxbit1: ;[ ]
+ in x2, USBIN ;[011] <-- bit 1
+ breq unstuff0 ;[012] *** unstuff escape
+ andi x2, USBMASK ;[013] SE0 check for bit 1
+didUnstuff0: ;[ ] Z only set if we detected SE0 in bitstuff
+ breq se0 ;[014]
+ eor r0, x2 ;[015]
+ or phase, r0 ;[016]
+ in r0, USBIN ;[017] <-- phase
+ eor x1, x2 ;[018]
+ bst x1, USBMINUS ;[019]
+ bld shift, 1 ;[020]
+ andi shift, 0xf3 ;[021]
+didUnstuff1: ;[ ]
+ in x1, USBIN ;[022] <-- bit 2
+ breq unstuff1 ;[023] *** unstuff escape
+ eor r0, x1 ;[024]
+ or phase, r0 ;[025]
+ subi cnt, 1 ;[026] overflow check
+ brcs overflow ;[027]
+ in r0, USBIN ;[028] <-- phase
+ eor x2, x1 ;[029]
+ bst x2, USBMINUS ;[030]
+ bld shift, 2 ;[031]
+ andi shift, 0xe7 ;[032]
+didUnstuff2: ;[ ]
+ in x2, USBIN ;[033] <-- bit 3
+ breq unstuff2 ;[034] *** unstuff escape
+ eor r0, x2 ;[035]
+ or phase, r0 ;[036]
+ eor x1, x2 ;[037]
+ bst x1, USBMINUS ;[038]
+ in r0, USBIN ;[039] <-- phase
+ bld shift, 3 ;[040]
+ andi shift, 0xcf ;[041]
+didUnstuff3: ;[ ]
+ breq unstuff3 ;[042] *** unstuff escape
+ nop ;[043]
+ in x1, USBIN ;[044] <-- bit 4
+ eor x2, x1 ;[045]
+ bst x2, USBMINUS ;[046]
+ bld shift, 4 ;[047]
+didUnstuff4: ;[ ]
+ eor r0, x1 ;[048]
+ or phase, r0 ;[049]
+ in r0, USBIN ;[050] <-- phase
+ andi shift, 0x9f ;[051]
+ breq unstuff4 ;[052] *** unstuff escape
+ rjmp continueWithBit5;[053]
+; [---] ;[054]
+
+macro POP_STANDARD ; 16 cycles
+ pop cnt
+ pop x4
+ pop x3
+ pop x2
+ pop x1
+ pop shift
+ pop YH
+ pop r0
+ endm
+macro POP_RETI ; 5 cycles
+ pop YL
+ out SREG, YL
+ pop YL
+ endm
+
+#include "asmcommon.inc"
+
+
+; USB spec says:
+; idle = J
+; J = (D+ = 0), (D- = 1)
+; K = (D+ = 1), (D- = 0)
+; Spec allows 7.5 bit times from EOP to SOP for replies
+
+bitstuff7:
+ eor x1, x4 ;[4]
+ ldi x2, 0 ;[5]
+ nop2 ;[6] C is zero (brcc)
+ rjmp didStuff7 ;[8]
+
+bitstuffN:
+ eor x1, x4 ;[5]
+ ldi x2, 0 ;[6]
+ lpm ;[7] 3 cycle NOP, modifies r0
+ out USBOUT, x1 ;[10] <-- out
+ rjmp didStuffN ;[0]
+
+#define bitStatus x3
+
+sendNakAndReti:
+ ldi cnt, USBPID_NAK ;[-19]
+ rjmp sendCntAndReti ;[-18]
+sendAckAndReti:
+ ldi cnt, USBPID_ACK ;[-17]
+sendCntAndReti:
+ mov r0, cnt ;[-16]
+ ldi YL, 0 ;[-15] R0 address is 0
+ ldi YH, 0 ;[-14]
+ ldi cnt, 2 ;[-13]
+; rjmp usbSendAndReti fallthrough
+
+;usbSend:
+;pointer to data in 'Y'
+;number of bytes in 'cnt' -- including sync byte [range 2 ... 12]
+;uses: x1...x4, shift, cnt, Y
+;Numbers in brackets are time since first bit of sync pattern is sent
+usbSendAndReti: ; 12 cycles until SOP
+ in x2, USBDDR ;[-12]
+ ori x2, USBMASK ;[-11]
+ sbi USBOUT, USBMINUS;[-10] prepare idle state; D+ and D- must have been 0 (no pullups)
+ in x1, USBOUT ;[-8] port mirror for tx loop
+ out USBDDR, x2 ;[-7] <- acquire bus
+; need not init x2 (bitstuff history) because sync starts with 0
+ ldi x4, USBMASK ;[-6] exor mask
+ ldi shift, 0x80 ;[-5] sync byte is first byte sent
+ ldi bitStatus, 0xff ;[-4] init bit loop counter, works for up to 12 bytes
+byteloop:
+bitloop:
+ sbrs shift, 0 ;[8] [-3]
+ eor x1, x4 ;[9] [-2]
+ out USBOUT, x1 ;[10] [-1] <-- out
+ ror shift ;[0]
+ ror x2 ;[1]
+didStuffN:
+ cpi x2, 0xfc ;[2]
+ brcc bitstuffN ;[3]
+ nop ;[4]
+ subi bitStatus, 37 ;[5] 256 / 7 ~=~ 37
+ brcc bitloop ;[6] when we leave the loop, bitStatus has almost the initial value
+ sbrs shift, 0 ;[7]
+ eor x1, x4 ;[8]
+ ror shift ;[9]
+didStuff7:
+ out USBOUT, x1 ;[10] <-- out
+ ror x2 ;[0]
+ cpi x2, 0xfc ;[1]
+ brcc bitstuff7 ;[2]
+ ld shift, y+ ;[3]
+ dec cnt ;[5]
+ brne byteloop ;[6]
+;make SE0:
+ cbr x1, USBMASK ;[7] prepare SE0 [spec says EOP may be 21 to 25 cycles]
+ lds x2, usbNewDeviceAddr;[8]
+ lsl x2 ;[10] we compare with left shifted address
+ out USBOUT, x1 ;[11] <-- out SE0 -- from now 2 bits = 22 cycles until bus idle
+;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm:
+;set address only after data packet was sent, not after handshake
+ subi YL, 2 ;[0] Only assign address on data packets, not ACK/NAK in r0
+ sbci YH, 0 ;[1]
+ breq skipAddrAssign ;[2]
+ sts usbDeviceAddr, x2; if not skipped: SE0 is one cycle longer
+skipAddrAssign:
+;end of usbDeviceAddress transfer
+ ldi x2, 1<<USB_INTR_PENDING_BIT;[4] int0 occurred during TX -- clear pending flag
+ USB_STORE_PENDING(x2) ;[5]
+ ori x1, USBIDLE ;[6]
+ in x2, USBDDR ;[7]
+ cbr x2, USBMASK ;[8] set both pins to input
+ mov x3, x1 ;[9]
+ cbr x3, USBMASK ;[10] configure no pullup on both pins
+ ldi x4, 4 ;[11]
+se0Delay:
+ dec x4 ;[12] [15] [18] [21]
+ brne se0Delay ;[13] [16] [19] [22]
+ out USBOUT, x1 ;[23] <-- out J (idle) -- end of SE0 (EOP signal)
+ out USBDDR, x2 ;[24] <-- release bus now
+ out USBOUT, x3 ;[25] <-- ensure no pull-up resistors are active
+ rjmp doReturn
+
diff --git a/tmk_core/protocol/vusb/usbdrv/usbdrvasm18-crc.inc b/tmk_core/protocol/vusb/usbdrv/usbdrvasm18-crc.inc
new file mode 100644
index 000000000..f83347df7
--- /dev/null
+++ b/tmk_core/protocol/vusb/usbdrv/usbdrvasm18-crc.inc
@@ -0,0 +1,707 @@
+/* Name: usbdrvasm18.inc
+ * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
+ * Author: Lukas Schrittwieser (based on 20 MHz usbdrvasm20.inc by Jeroen Benschop)
+ * Creation Date: 2009-01-20
+ * Tabsize: 4
+ * Copyright: (c) 2008 by Lukas Schrittwieser and OBJECTIVE DEVELOPMENT Software GmbH
+ * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
+ * Revision: $Id: usbdrvasm18-crc.inc 740 2009-04-13 18:23:31Z cs $
+ */
+
+/* Do not link this file! Link usbdrvasm.S instead, which includes the
+ * appropriate implementation!
+ */
+
+/*
+General Description:
+This file is the 18 MHz version of the asssembler part of the USB driver. It
+requires a 18 MHz crystal (not a ceramic resonator and not a calibrated RC
+oscillator).
+
+See usbdrv.h for a description of the entire driver.
+
+Since almost all of this code is timing critical, don't change unless you
+really know what you are doing! Many parts require not only a maximum number
+of CPU cycles, but even an exact number of cycles!
+*/
+
+
+;max stack usage: [ret(2), YL, SREG, YH, [sofError], bitcnt(x5), shift, x1, x2, x3, x4, cnt, ZL, ZH] = 14 bytes
+;nominal frequency: 18 MHz -> 12 cycles per bit
+; Numbers in brackets are clocks counted from center of last sync bit
+; when instruction starts
+;register use in receive loop to receive the data bytes:
+; shift assembles the byte currently being received
+; x1 holds the D+ and D- line state
+; x2 holds the previous line state
+; cnt holds the number of bytes left in the receive buffer
+; x3 holds the higher crc byte (see algorithm below)
+; x4 is used as temporary register for the crc algorithm
+; x5 is used for unstuffing: when unstuffing the last received bit is inverted in shift (to prevent further
+; unstuffing calls. In the same time the corresponding bit in x5 is cleared to mark the bit as beening iverted
+; zl lower crc value and crc table index
+; zh used for crc table accesses
+
+;--------------------------------------------------------------------------------------------------------------
+; CRC mods:
+; table driven crc checker, Z points to table in prog space
+; ZL is the lower crc byte, x3 is the higher crc byte
+; x4 is used as temp register to store different results
+; the initialization of the crc register is not 0xFFFF but 0xFE54. This is because during the receipt of the
+; first data byte an virtual zero data byte is added to the crc register, this results in the correct initial
+; value of 0xFFFF at beginning of the second data byte before the first data byte is added to the crc.
+; The magic number 0xFE54 results form the crc table: At tabH[0x54] = 0xFF = crcH (required) and
+; tabL[0x54] = 0x01 -> crcL = 0x01 xor 0xFE = 0xFF
+; bitcnt is renamed to x5 and is used for unstuffing purposes, the unstuffing works like in the 12MHz version
+;--------------------------------------------------------------------------------------------------------------
+; CRC algorithm:
+; The crc register is formed by x3 (higher byte) and ZL (lower byte). The algorithm uses a 'reversed' form
+; i.e. that it takes the least significant bit first and shifts to the right. So in fact the highest order
+; bit seen from the polynomial devision point of view is the lsb of ZL. (If this sounds strange to you i
+; propose a research on CRC :-) )
+; Each data byte received is xored to ZL, the lower crc byte. This byte now builds the crc
+; table index. Next the new high byte is loaded from the table and stored in x4 until we have space in x3
+; (its destination).
+; Afterwards the lower table is loaded from the table and stored in ZL (the old index is overwritten as
+; we don't need it anymore. In fact this is a right shift by 8 bits.) Now the old crc high value is xored
+; to ZL, this is the second shift of the old crc value. Now x4 (the temp reg) is moved to x3 and the crc
+; calculation is done.
+; Prior to the first byte the two CRC register have to be initialized to 0xFFFF (as defined in usb spec)
+; however the crc engine also runs during the receipt of the first byte, therefore x3 and zl are initialized
+; to a magic number which results in a crc value of 0xFFFF after the first complete byte.
+;
+; This algorithm is split into the extra cycles of the different bits:
+; bit7: XOR the received byte to ZL
+; bit5: load the new high byte to x4
+; bit6: load the lower xor byte from the table, xor zl and x3, store result in zl (=the new crc low value)
+; move x4 (the new high byte) to x3, the crc value is ready
+;
+
+
+macro POP_STANDARD ; 18 cycles
+ pop ZH
+ pop ZL
+ pop cnt
+ pop x5
+ pop x3
+ pop x2
+ pop x1
+ pop shift
+ pop x4
+ endm
+macro POP_RETI ; 7 cycles
+ pop YH
+ pop YL
+ out SREG, YL
+ pop YL
+ endm
+
+macro CRC_CLEANUP_AND_CHECK
+ ; the last byte has already been xored with the lower crc byte, we have to do the table lookup and xor
+ ; x3 is the higher crc byte, zl the lower one
+ ldi ZH, hi8(usbCrcTableHigh);[+1] get the new high byte from the table
+ lpm x2, Z ;[+2][+3][+4]
+ ldi ZH, hi8(usbCrcTableLow);[+5] get the new low xor byte from the table
+ lpm ZL, Z ;[+6][+7][+8]
+ eor ZL, x3 ;[+7] xor the old high byte with the value from the table, x2:ZL now holds the crc value
+ cpi ZL, 0x01 ;[+8] if the crc is ok we have a fixed remainder value of 0xb001 in x2:ZL (see usb spec)
+ brne ignorePacket ;[+9] detected a crc fault -> paket is ignored and retransmitted by the host
+ cpi x2, 0xb0 ;[+10]
+ brne ignorePacket ;[+11] detected a crc fault -> paket is ignored and retransmitted by the host
+ endm
+
+
+USB_INTR_VECTOR:
+;order of registers pushed: YL, SREG, YH, [sofError], x4, shift, x1, x2, x3, x5, cnt, ZL, ZH
+ push YL ;[-28] push only what is necessary to sync with edge ASAP
+ in YL, SREG ;[-26]
+ push YL ;[-25]
+ push YH ;[-23]
+;----------------------------------------------------------------------------
+; Synchronize with sync pattern:
+;----------------------------------------------------------------------------
+;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K]
+;sync up with J to K edge during sync pattern -- use fastest possible loops
+;The first part waits at most 1 bit long since we must be in sync pattern.
+;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to
+;waitForJ, ensure that this prerequisite is met.
+waitForJ:
+ inc YL
+ sbis USBIN, USBMINUS
+ brne waitForJ ; just make sure we have ANY timeout
+waitForK:
+;The following code results in a sampling window of < 1/4 bit which meets the spec.
+ sbis USBIN, USBMINUS ;[-17]
+ rjmp foundK ;[-16]
+ sbis USBIN, USBMINUS
+ rjmp foundK
+ sbis USBIN, USBMINUS
+ rjmp foundK
+ sbis USBIN, USBMINUS
+ rjmp foundK
+ sbis USBIN, USBMINUS
+ rjmp foundK
+ sbis USBIN, USBMINUS
+ rjmp foundK
+ sbis USBIN, USBMINUS
+ rjmp foundK
+ sbis USBIN, USBMINUS
+ rjmp foundK
+ sbis USBIN, USBMINUS
+ rjmp foundK
+#if USB_COUNT_SOF
+ lds YL, usbSofCount
+ inc YL
+ sts usbSofCount, YL
+#endif /* USB_COUNT_SOF */
+#ifdef USB_SOF_HOOK
+ USB_SOF_HOOK
+#endif
+ rjmp sofError
+foundK: ;[-15]
+;{3, 5} after falling D- edge, average delay: 4 cycles
+;bit0 should be at 30 (2.5 bits) for center sampling. Currently at 4 so 26 cylces till bit 0 sample
+;use 1 bit time for setup purposes, then sample again. Numbers in brackets
+;are cycles from center of first sync (double K) bit after the instruction
+ push x4 ;[-14]
+; [---] ;[-13]
+ lds YL, usbInputBufOffset;[-12] used to toggle the two usb receive buffers
+; [---] ;[-11]
+ clr YH ;[-10]
+ subi YL, lo8(-(usbRxBuf));[-9] [rx loop init]
+ sbci YH, hi8(-(usbRxBuf));[-8] [rx loop init]
+ push shift ;[-7]
+; [---] ;[-6]
+ ldi shift, 0x80 ;[-5] the last bit is the end of byte marker for the pid receiver loop
+ clc ;[-4] the carry has to be clear for receipt of pid bit 0
+ sbis USBIN, USBMINUS ;[-3] we want two bits K (sample 3 cycles too early)
+ rjmp haveTwoBitsK ;[-2]
+ pop shift ;[-1] undo the push from before
+ pop x4 ;[1]
+ rjmp waitForK ;[3] this was not the end of sync, retry
+; The entire loop from waitForK until rjmp waitForK above must not exceed two
+; bit times (= 24 cycles).
+
+;----------------------------------------------------------------------------
+; push more registers and initialize values while we sample the first bits:
+;----------------------------------------------------------------------------
+haveTwoBitsK:
+ push x1 ;[0]
+ push x2 ;[2]
+ push x3 ;[4] crc high byte
+ ldi x2, 1<<USBPLUS ;[6] [rx loop init] current line state is K state. D+=="1", D-=="0"
+ push x5 ;[7]
+ push cnt ;[9]
+ ldi cnt, USB_BUFSIZE ;[11]
+
+
+;--------------------------------------------------------------------------------------------------------------
+; receives the pid byte
+; there is no real unstuffing algorithm implemented here as a stuffing bit is impossible in the pid byte.
+; That's because the last four bits of the byte are the inverted of the first four bits. If we detect a
+; unstuffing condition something went wrong and abort
+; shift has to be initialized to 0x80
+;--------------------------------------------------------------------------------------------------------------
+
+; pid bit 0 - used for even more register saving (we need the z pointer)
+ in x1, USBIN ;[0] sample line state
+ andi x1, USBMASK ;[1] filter only D+ and D- bits
+ eor x2, x1 ;[2] generate inverted of actual bit
+ sbrc x2, USBMINUS ;[3] if the bit is set we received a zero
+ sec ;[4]
+ ror shift ;[5] we perform no unstuffing check here as this is the first bit
+ mov x2, x1 ;[6]
+ push ZL ;[7]
+ ;[8]
+ push ZH ;[9]
+ ;[10]
+ ldi x3, 0xFE ;[11] x3 is the high order crc value
+
+
+bitloopPid:
+ in x1, USBIN ;[0] sample line state
+ andi x1, USBMASK ;[1] filter only D+ and D- bits
+ breq nse0 ;[2] both lines are low so handle se0
+ eor x2, x1 ;[3] generate inverted of actual bit
+ sbrc x2, USBMINUS ;[4] set the carry if we received a zero
+ sec ;[5]
+ ror shift ;[6]
+ ldi ZL, 0x54 ;[7] ZL is the low order crc value
+ ser x4 ;[8] the is no bit stuffing check here as the pid bit can't be stuffed. if so
+ ; some error occured. In this case the paket is discarded later on anyway.
+ mov x2, x1 ;[9] prepare for the next cycle
+ brcc bitloopPid ;[10] while 0s drop out of shift we get the next bit
+ eor x4, shift ;[11] invert all bits in shift and store result in x4
+
+;--------------------------------------------------------------------------------------------------------------
+; receives data bytes and calculates the crc
+; the last USBIN state has to be in x2
+; this is only the first half, due to branch distanc limitations the second half of the loop is near the end
+; of this asm file
+;--------------------------------------------------------------------------------------------------------------
+
+rxDataStart:
+ in x1, USBIN ;[0] sample line state (note: a se0 check is not useful due to bit dribbling)
+ ser x5 ;[1] prepare the unstuff marker register
+ eor x2, x1 ;[2] generates the inverted of the actual bit
+ bst x2, USBMINUS ;[3] copy the bit from x2
+ bld shift, 0 ;[4] and store it in shift
+ mov x2, shift ;[5] make a copy of shift for unstuffing check
+ andi x2, 0xF9 ;[6] mask the last six bits, if we got six zeros (which are six ones in fact)
+ breq unstuff0 ;[7] then Z is set now and we branch to the unstuffing handler
+didunstuff0:
+ subi cnt, 1 ;[8] cannot use dec because it doesn't affect the carry flag
+ brcs nOverflow ;[9] Too many bytes received. Ignore packet
+ st Y+, x4 ;[10] store the last received byte
+ ;[11] st needs two cycles
+
+; bit1
+ in x2, USBIN ;[0] sample line state
+ andi x1, USBMASK ;[1] check for se0 during bit 0
+ breq nse0 ;[2]
+ andi x2, USBMASK ;[3] check se0 during bit 1
+ breq nse0 ;[4]
+ eor x1, x2 ;[5]
+ bst x1, USBMINUS ;[6]
+ bld shift, 1 ;[7]
+ mov x1, shift ;[8]
+ andi x1, 0xF3 ;[9]
+ breq unstuff1 ;[10]
+didunstuff1:
+ nop ;[11]
+
+; bit2
+ in x1, USBIN ;[0] sample line state
+ andi x1, USBMASK ;[1] check for se0 (as there is nothing else to do here
+ breq nOverflow ;[2]
+ eor x2, x1 ;[3] generates the inverted of the actual bit
+ bst x2, USBMINUS ;[4]
+ bld shift, 2 ;[5] store the bit
+ mov x2, shift ;[6]
+ andi x2, 0xE7 ;[7] if we have six zeros here (which means six 1 in the stream)
+ breq unstuff2 ;[8] the next bit is a stuffing bit
+didunstuff2:
+ nop2 ;[9]
+ ;[10]
+ nop ;[11]
+
+; bit3
+ in x2, USBIN ;[0] sample line state
+ andi x2, USBMASK ;[1] check for se0
+ breq nOverflow ;[2]
+ eor x1, x2 ;[3]
+ bst x1, USBMINUS ;[4]
+ bld shift, 3 ;[5]
+ mov x1, shift ;[6]
+ andi x1, 0xCF ;[7]
+ breq unstuff3 ;[8]
+didunstuff3:
+ nop ;[9]
+ rjmp rxDataBit4 ;[10]
+ ;[11]
+
+; the avr branch instructions allow an offset of +63 insturction only, so we need this
+; 'local copy' of se0
+nse0:
+ rjmp se0 ;[4]
+ ;[5]
+; the same same as for se0 is needed for overflow and StuffErr
+nOverflow:
+stuffErr:
+ rjmp overflow
+
+
+unstuff0: ;[8] this is the branch delay of breq unstuffX
+ andi x1, USBMASK ;[9] do an se0 check here (if the last crc byte ends with 5 one's we might end up here
+ breq didunstuff0 ;[10] event tough the message is complete -> jump back and store the byte
+ ori shift, 0x01 ;[11] invert the last received bit to prevent furhter unstuffing
+ in x2, USBIN ;[0] we have some free cycles so we could check for bit stuffing errors
+ andi x5, 0xFE ;[1] mark this bit as inverted (will be corrected before storing shift)
+ eor x1, x2 ;[2] x1 and x2 have to be different because the stuff bit is always a zero
+ andi x1, USBMASK ;[3] mask the interesting bits
+ breq stuffErr ;[4] if the stuff bit is a 1-bit something went wrong
+ mov x1, x2 ;[5] the next bit expects the last state to be in x1
+ rjmp didunstuff0 ;[6]
+ ;[7] jump delay of rjmp didunstuffX
+
+unstuff1: ;[11] this is the jump delay of breq unstuffX
+ in x1, USBIN ;[0] we have some free cycles so we could check for bit stuffing errors
+ ori shift, 0x02 ;[1] invert the last received bit to prevent furhter unstuffing
+ andi x5, 0xFD ;[2] mark this bit as inverted (will be corrected before storing shift)
+ eor x2, x1 ;[3] x1 and x2 have to be different because the stuff bit is always a zero
+ andi x2, USBMASK ;[4] mask the interesting bits
+ breq stuffErr ;[5] if the stuff bit is a 1-bit something went wrong
+ mov x2, x1 ;[6] the next bit expects the last state to be in x2
+ nop2 ;[7]
+ ;[8]
+ rjmp didunstuff1 ;[9]
+ ;[10] jump delay of rjmp didunstuffX
+
+unstuff2: ;[9] this is the jump delay of breq unstuffX
+ ori shift, 0x04 ;[10] invert the last received bit to prevent furhter unstuffing
+ andi x5, 0xFB ;[11] mark this bit as inverted (will be corrected before storing shift)
+ in x2, USBIN ;[0] we have some free cycles so we could check for bit stuffing errors
+ eor x1, x2 ;[1] x1 and x2 have to be different because the stuff bit is always a zero
+ andi x1, USBMASK ;[2] mask the interesting bits
+ breq stuffErr ;[3] if the stuff bit is a 1-bit something went wrong
+ mov x1, x2 ;[4] the next bit expects the last state to be in x1
+ nop2 ;[5]
+ ;[6]
+ rjmp didunstuff2 ;[7]
+ ;[8] jump delay of rjmp didunstuffX
+
+unstuff3: ;[9] this is the jump delay of breq unstuffX
+ ori shift, 0x08 ;[10] invert the last received bit to prevent furhter unstuffing
+ andi x5, 0xF7 ;[11] mark this bit as inverted (will be corrected before storing shift)
+ in x1, USBIN ;[0] we have some free cycles so we could check for bit stuffing errors
+ eor x2, x1 ;[1] x1 and x2 have to be different because the stuff bit is always a zero
+ andi x2, USBMASK ;[2] mask the interesting bits
+ breq stuffErr ;[3] if the stuff bit is a 1-bit something went wrong
+ mov x2, x1 ;[4] the next bit expects the last state to be in x2
+ nop2 ;[5]
+ ;[6]
+ rjmp didunstuff3 ;[7]
+ ;[8] jump delay of rjmp didunstuffX
+
+
+
+; the include has to be here due to branch distance restirctions
+#define __USE_CRC__
+#include "asmcommon.inc"
+
+
+
+; USB spec says:
+; idle = J
+; J = (D+ = 0), (D- = 1)
+; K = (D+ = 1), (D- = 0)
+; Spec allows 7.5 bit times from EOP to SOP for replies
+; 7.5 bit times is 90 cycles. ...there is plenty of time
+
+
+sendNakAndReti:
+ ldi x3, USBPID_NAK ;[-18]
+ rjmp sendX3AndReti ;[-17]
+sendAckAndReti:
+ ldi cnt, USBPID_ACK ;[-17]
+sendCntAndReti:
+ mov x3, cnt ;[-16]
+sendX3AndReti:
+ ldi YL, 20 ;[-15] x3==r20 address is 20
+ ldi YH, 0 ;[-14]
+ ldi cnt, 2 ;[-13]
+; rjmp usbSendAndReti fallthrough
+
+;usbSend:
+;pointer to data in 'Y'
+;number of bytes in 'cnt' -- including sync byte [range 2 ... 12]
+;uses: x1...x4, btcnt, shift, cnt, Y
+;Numbers in brackets are time since first bit of sync pattern is sent
+
+usbSendAndReti: ; 12 cycles until SOP
+ in x2, USBDDR ;[-12]
+ ori x2, USBMASK ;[-11]
+ sbi USBOUT, USBMINUS;[-10] prepare idle state; D+ and D- must have been 0 (no pullups)
+ in x1, USBOUT ;[-8] port mirror for tx loop
+ out USBDDR, x2 ;[-6] <- acquire bus
+ ldi x2, 0 ;[-6] init x2 (bitstuff history) because sync starts with 0
+ ldi x4, USBMASK ;[-5] exor mask
+ ldi shift, 0x80 ;[-4] sync byte is first byte sent
+txByteLoop:
+ ldi bitcnt, 0x40 ;[-3]=[9] binary 01000000
+txBitLoop: ; the loop sends the first 7 bits of the byte
+ sbrs shift, 0 ;[-2]=[10] if we have to send a 1 don't change the line state
+ eor x1, x4 ;[-1]=[11]
+ out USBOUT, x1 ;[0]
+ ror shift ;[1]
+ ror x2 ;[2] transfers the last sent bit to the stuffing history
+didStuffN:
+ nop ;[3]
+ nop ;[4]
+ cpi x2, 0xfc ;[5] if we sent six consecutive ones
+ brcc bitstuffN ;[6]
+ lsr bitcnt ;[7]
+ brne txBitLoop ;[8] restart the loop while the 1 is still in the bitcount
+
+; transmit bit 7
+ sbrs shift, 0 ;[9]
+ eor x1, x4 ;[10]
+didStuff7:
+ ror shift ;[11]
+ out USBOUT, x1 ;[0] transfer bit 7 to the pins
+ ror x2 ;[1] move the bit into the stuffing history
+ cpi x2, 0xfc ;[2]
+ brcc bitstuff7 ;[3]
+ ld shift, y+ ;[4] get next byte to transmit
+ dec cnt ;[5] decrement byte counter
+ brne txByteLoop ;[7] if we have more bytes start next one
+ ;[8] branch delay
+
+;make SE0:
+ cbr x1, USBMASK ;[8] prepare SE0 [spec says EOP may be 25 to 30 cycles]
+ lds x2, usbNewDeviceAddr;[9]
+ lsl x2 ;[11] we compare with left shifted address
+ out USBOUT, x1 ;[0] <-- out SE0 -- from now 2 bits = 24 cycles until bus idle
+ subi YL, 20 + 2 ;[1] Only assign address on data packets, not ACK/NAK in x3
+ sbci YH, 0 ;[2]
+;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm:
+;set address only after data packet was sent, not after handshake
+ breq skipAddrAssign ;[3]
+ sts usbDeviceAddr, x2 ; if not skipped: SE0 is one cycle longer
+skipAddrAssign:
+;end of usbDeviceAddress transfer
+ ldi x2, 1<<USB_INTR_PENDING_BIT;[5] int0 occurred during TX -- clear pending flag
+ USB_STORE_PENDING(x2) ;[6]
+ ori x1, USBIDLE ;[7]
+ in x2, USBDDR ;[8]
+ cbr x2, USBMASK ;[9] set both pins to input
+ mov x3, x1 ;[10]
+ cbr x3, USBMASK ;[11] configure no pullup on both pins
+ ldi x4, 4 ;[12]
+se0Delay:
+ dec x4 ;[13] [16] [19] [22]
+ brne se0Delay ;[14] [17] [20] [23]
+ out USBOUT, x1 ;[24] <-- out J (idle) -- end of SE0 (EOP signal)
+ out USBDDR, x2 ;[25] <-- release bus now
+ out USBOUT, x3 ;[26] <-- ensure no pull-up resistors are active
+ rjmp doReturn
+
+bitstuffN:
+ eor x1, x4 ;[8] generate a zero
+ ldi x2, 0 ;[9] reset the bit stuffing history
+ nop2 ;[10]
+ out USBOUT, x1 ;[0] <-- send the stuffing bit
+ rjmp didStuffN ;[1]
+
+bitstuff7:
+ eor x1, x4 ;[5]
+ ldi x2, 0 ;[6] reset bit stuffing history
+ clc ;[7] fill a zero into the shift register
+ rol shift ;[8] compensate for ror shift at branch destination
+ rjmp didStuff7 ;[9]
+ ;[10] jump delay
+
+;--------------------------------------------------------------------------------------------------------------
+; receives data bytes and calculates the crc
+; second half of the data byte receiver loop
+; most parts of the crc algorithm are here
+;--------------------------------------------------------------------------------------------------------------
+
+nOverflow2:
+ rjmp overflow
+
+rxDataBit4:
+ in x1, USBIN ;[0] sample line state
+ andi x1, USBMASK ;[1] check for se0
+ breq nOverflow2 ;[2]
+ eor x2, x1 ;[3]
+ bst x2, USBMINUS ;[4]
+ bld shift, 4 ;[5]
+ mov x2, shift ;[6]
+ andi x2, 0x9F ;[7]
+ breq unstuff4 ;[8]
+didunstuff4:
+ nop2 ;[9][10]
+ nop ;[11]
+
+; bit5
+ in x2, USBIN ;[0] sample line state
+ ldi ZH, hi8(usbCrcTableHigh);[1] use the table for the higher byte
+ eor x1, x2 ;[2]
+ bst x1, USBMINUS ;[3]
+ bld shift, 5 ;[4]
+ mov x1, shift ;[5]
+ andi x1, 0x3F ;[6]
+ breq unstuff5 ;[7]
+didunstuff5:
+ lpm x4, Z ;[8] load the higher crc xor-byte and store it for later use
+ ;[9] lpm needs 3 cycles
+ ;[10]
+ ldi ZH, hi8(usbCrcTableLow);[11] load the lower crc xor byte adress
+
+; bit6
+ in x1, USBIN ;[0] sample line state
+ eor x2, x1 ;[1]
+ bst x2, USBMINUS ;[2]
+ bld shift, 6 ;[3]
+ mov x2, shift ;[4]
+ andi x2, 0x7E ;[5]
+ breq unstuff6 ;[6]
+didunstuff6:
+ lpm ZL, Z ;[7] load the lower xor crc byte
+ ;[8] lpm needs 3 cycles
+ ;[9]
+ eor ZL, x3 ;[10] xor the old high crc byte with the low xor-byte
+ mov x3, x4 ;[11] move the new high order crc value from temp to its destination
+
+; bit7
+ in x2, USBIN ;[0] sample line state
+ eor x1, x2 ;[1]
+ bst x1, USBMINUS ;[2]
+ bld shift, 7 ;[3] now shift holds the complete but inverted data byte
+ mov x1, shift ;[4]
+ andi x1, 0xFC ;[5]
+ breq unstuff7 ;[6]
+didunstuff7:
+ eor x5, shift ;[7] x5 marks all bits which have not been inverted by the unstuffing subs
+ mov x4, x5 ;[8] keep a copy of the data byte it will be stored during next bit0
+ eor ZL, x4 ;[9] feed the actual byte into the crc algorithm
+ rjmp rxDataStart ;[10] next byte
+ ;[11] during the reception of the next byte this one will be fed int the crc algorithm
+
+unstuff4: ;[9] this is the jump delay of rjmp unstuffX
+ ori shift, 0x10 ;[10] invert the last received bit to prevent furhter unstuffing
+ andi x5, 0xEF ;[11] mark this bit as inverted (will be corrected before storing shift)
+ in x2, USBIN ;[0] we have some free cycles so we could check for bit stuffing errors
+ eor x1, x2 ;[1] x1 and x2 have to be different because the stuff bit is always a zero
+ andi x1, USBMASK ;[2] mask the interesting bits
+ breq stuffErr2 ;[3] if the stuff bit is a 1-bit something went wrong
+ mov x1, x2 ;[4] the next bit expects the last state to be in x1
+ nop2 ;[5]
+ ;[6]
+ rjmp didunstuff4 ;[7]
+ ;[8] jump delay of rjmp didunstuffX
+
+unstuff5: ;[8] this is the jump delay of rjmp unstuffX
+ nop ;[9]
+ ori shift, 0x20 ;[10] invert the last received bit to prevent furhter unstuffing
+ andi x5, 0xDF ;[11] mark this bit as inverted (will be corrected before storing shift)
+ in x1, USBIN ;[0] we have some free cycles so we could check for bit stuffing errors
+ eor x2, x1 ;[1] x1 and x2 have to be different because the stuff bit is always a zero
+ andi x2, USBMASK ;[2] mask the interesting bits
+ breq stuffErr2 ;[3] if the stuff bit is a 1-bit something went wrong
+ mov x2, x1 ;[4] the next bit expects the last state to be in x2
+ nop ;[5]
+ rjmp didunstuff5 ;[6]
+ ;[7] jump delay of rjmp didunstuffX
+
+unstuff6: ;[7] this is the jump delay of rjmp unstuffX
+ nop2 ;[8]
+ ;[9]
+ ori shift, 0x40 ;[10] invert the last received bit to prevent furhter unstuffing
+ andi x5, 0xBF ;[11] mark this bit as inverted (will be corrected before storing shift)
+ in x2, USBIN ;[0] we have some free cycles so we could check for bit stuffing errors
+ eor x1, x2 ;[1] x1 and x2 have to be different because the stuff bit is always a zero
+ andi x1, USBMASK ;[2] mask the interesting bits
+ breq stuffErr2 ;[3] if the stuff bit is a 1-bit something went wrong
+ mov x1, x2 ;[4] the next bit expects the last state to be in x1
+ rjmp didunstuff6 ;[5]
+ ;[6] jump delay of rjmp didunstuffX
+
+unstuff7: ;[7] this is the jump delay of rjmp unstuffX
+ nop ;[8]
+ nop ;[9]
+ ori shift, 0x80 ;[10] invert the last received bit to prevent furhter unstuffing
+ andi x5, 0x7F ;[11] mark this bit as inverted (will be corrected before storing shift)
+ in x1, USBIN ;[0] we have some free cycles so we could check for bit stuffing errors
+ eor x2, x1 ;[1] x1 and x2 have to be different because the stuff bit is always a zero
+ andi x2, USBMASK ;[2] mask the interesting bits
+ breq stuffErr2 ;[3] if the stuff bit is a 1-bit something went wrong
+ mov x2, x1 ;[4] the next bit expects the last state to be in x2
+ rjmp didunstuff7 ;[5]
+ ;[6] jump delay of rjmp didunstuff7
+
+; local copy of the stuffErr desitnation for the second half of the receiver loop
+stuffErr2:
+ rjmp stuffErr
+
+;--------------------------------------------------------------------------------------------------------------
+; The crc table follows. It has to be aligned to enable a fast loading of the needed bytes.
+; There are two tables of 256 entries each, the low and the high byte table.
+; Table values were generated with the following C code:
+/*
+#include <stdio.h>
+int main (int argc, char **argv)
+{
+ int i, j;
+ for (i=0; i<512; i++){
+ unsigned short crc = i & 0xff;
+ for(j=0; j<8; j++) crc = (crc >> 1) ^ ((crc & 1) ? 0xa001 : 0);
+ if((i & 7) == 0) printf("\n.byte ");
+ printf("0x%02x, ", (i > 0xff ? (crc >> 8) : crc) & 0xff);
+ if(i == 255) printf("\n");
+ }
+ return 0;
+}
+
+// Use the following algorithm to compute CRC values:
+ushort computeCrc(uchar *msg, uchar msgLen)
+{
+ uchar i;
+ ushort crc = 0xffff;
+ for(i = 0; i < msgLen; i++)
+ crc = usbCrcTable16[lo8(crc) ^ msg[i]] ^ hi8(crc);
+ return crc;
+}
+*/
+
+.balign 256
+usbCrcTableLow:
+.byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
+.byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
+.byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
+.byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
+.byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
+.byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
+.byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
+.byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
+.byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
+.byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
+.byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
+.byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
+.byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
+.byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
+.byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
+.byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
+.byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
+.byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
+.byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
+.byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
+.byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
+.byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
+.byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
+.byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
+.byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
+.byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
+.byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
+.byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
+.byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
+.byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
+.byte 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41
+.byte 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
+
+; .balign 256
+usbCrcTableHigh:
+.byte 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2
+.byte 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04
+.byte 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E
+.byte 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8
+.byte 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A
+.byte 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC
+.byte 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6
+.byte 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10
+.byte 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32
+.byte 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4
+.byte 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE
+.byte 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38
+.byte 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA
+.byte 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C
+.byte 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26
+.byte 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0
+.byte 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62
+.byte 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4
+.byte 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE
+.byte 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68
+.byte 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA
+.byte 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C
+.byte 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76
+.byte 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0
+.byte 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92
+.byte 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54
+.byte 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E
+.byte 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98
+.byte 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A
+.byte 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C
+.byte 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86
+.byte 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40
+
diff --git a/tmk_core/protocol/vusb/usbdrv/usbdrvasm20.inc b/tmk_core/protocol/vusb/usbdrv/usbdrvasm20.inc
new file mode 100644
index 000000000..303abaf64
--- /dev/null
+++ b/tmk_core/protocol/vusb/usbdrv/usbdrvasm20.inc
@@ -0,0 +1,360 @@
+/* Name: usbdrvasm20.inc
+ * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
+ * Author: Jeroen Benschop
+ * Based on usbdrvasm16.inc from Christian Starkjohann
+ * Creation Date: 2008-03-05
+ * Tabsize: 4
+ * Copyright: (c) 2008 by Jeroen Benschop and OBJECTIVE DEVELOPMENT Software GmbH
+ * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
+ * Revision: $Id: usbdrvasm20.inc 740 2009-04-13 18:23:31Z cs $
+ */
+
+/* Do not link this file! Link usbdrvasm.S instead, which includes the
+ * appropriate implementation!
+ */
+
+/*
+General Description:
+This file is the 20 MHz version of the asssembler part of the USB driver. It
+requires a 20 MHz crystal (not a ceramic resonator and not a calibrated RC
+oscillator).
+
+See usbdrv.h for a description of the entire driver.
+
+Since almost all of this code is timing critical, don't change unless you
+really know what you are doing! Many parts require not only a maximum number
+of CPU cycles, but even an exact number of cycles!
+*/
+
+#define leap2 x3
+#ifdef __IAR_SYSTEMS_ASM__
+#define nextInst $+2
+#else
+#define nextInst .+0
+#endif
+
+;max stack usage: [ret(2), YL, SREG, YH, bitcnt, shift, x1, x2, x3, x4, cnt] = 12 bytes
+;nominal frequency: 20 MHz -> 13.333333 cycles per bit, 106.666667 cycles per byte
+; Numbers in brackets are clocks counted from center of last sync bit
+; when instruction starts
+;register use in receive loop:
+; shift assembles the byte currently being received
+; x1 holds the D+ and D- line state
+; x2 holds the previous line state
+; x4 (leap) is used to add a leap cycle once every three bytes received
+; X3 (leap2) is used to add a leap cycle once every three stuff bits received
+; bitcnt is used to determine when a stuff bit is due
+; cnt holds the number of bytes left in the receive buffer
+
+USB_INTR_VECTOR:
+;order of registers pushed: YL, SREG YH, [sofError], bitcnt, shift, x1, x2, x3, x4, cnt
+ push YL ;[-28] push only what is necessary to sync with edge ASAP
+ in YL, SREG ;[-26]
+ push YL ;[-25]
+ push YH ;[-23]
+;----------------------------------------------------------------------------
+; Synchronize with sync pattern:
+;----------------------------------------------------------------------------
+;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K]
+;sync up with J to K edge during sync pattern -- use fastest possible loops
+;The first part waits at most 1 bit long since we must be in sync pattern.
+;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to
+;waitForJ, ensure that this prerequisite is met.
+waitForJ:
+ inc YL
+ sbis USBIN, USBMINUS
+ brne waitForJ ; just make sure we have ANY timeout
+waitForK:
+;The following code results in a sampling window of < 1/4 bit which meets the spec.
+ sbis USBIN, USBMINUS ;[-19]
+ rjmp foundK ;[-18]
+ sbis USBIN, USBMINUS
+ rjmp foundK
+ sbis USBIN, USBMINUS
+ rjmp foundK
+ sbis USBIN, USBMINUS
+ rjmp foundK
+ sbis USBIN, USBMINUS
+ rjmp foundK
+ sbis USBIN, USBMINUS
+ rjmp foundK
+ sbis USBIN, USBMINUS
+ rjmp foundK
+ sbis USBIN, USBMINUS
+ rjmp foundK
+ sbis USBIN, USBMINUS
+ rjmp foundK
+#if USB_COUNT_SOF
+ lds YL, usbSofCount
+ inc YL
+ sts usbSofCount, YL
+#endif /* USB_COUNT_SOF */
+#ifdef USB_SOF_HOOK
+ USB_SOF_HOOK
+#endif
+ rjmp sofError
+foundK: ;[-16]
+;{3, 5} after falling D- edge, average delay: 4 cycles
+;bit0 should be at 34 for center sampling. Currently at 4 so 30 cylces till bit 0 sample
+;use 1 bit time for setup purposes, then sample again. Numbers in brackets
+;are cycles from center of first sync (double K) bit after the instruction
+ push bitcnt ;[-16]
+; [---] ;[-15]
+ lds YL, usbInputBufOffset;[-14]
+; [---] ;[-13]
+ clr YH ;[-12]
+ subi YL, lo8(-(usbRxBuf));[-11] [rx loop init]
+ sbci YH, hi8(-(usbRxBuf));[-10] [rx loop init]
+ push shift ;[-9]
+; [---] ;[-8]
+ ldi shift,0x40 ;[-7] set msb to "1" so processing bit7 can be detected
+ nop2 ;[-6]
+; [---] ;[-5]
+ ldi bitcnt, 5 ;[-4] [rx loop init]
+ sbis USBIN, USBMINUS ;[-3] we want two bits K (sample 3 cycles too early)
+ rjmp haveTwoBitsK ;[-2]
+ pop shift ;[-1] undo the push from before
+ pop bitcnt ;[1]
+ rjmp waitForK ;[3] this was not the end of sync, retry
+; The entire loop from waitForK until rjmp waitForK above must not exceed two
+; bit times (= 27 cycles).
+
+;----------------------------------------------------------------------------
+; push more registers and initialize values while we sample the first bits:
+;----------------------------------------------------------------------------
+haveTwoBitsK:
+ push x1 ;[0]
+ push x2 ;[2]
+ push x3 ;[4] (leap2)
+ ldi leap2, 0x55 ;[6] add leap cycle on 2nd,5th,8th,... stuff bit
+ push x4 ;[7] == leap
+ ldi leap, 0x55 ;[9] skip leap cycle on 2nd,5th,8th,... byte received
+ push cnt ;[10]
+ ldi cnt, USB_BUFSIZE ;[12] [rx loop init]
+ ldi x2, 1<<USBPLUS ;[13] current line state is K state. D+=="1", D-=="0"
+bit0:
+ in x1, USBIN ;[0] sample line state
+ andi x1, USBMASK ;[1] filter only D+ and D- bits
+ rjmp handleBit ;[2] make bit0 14 cycles long
+
+;----------------------------------------------------------------------------
+; Process bit7. However, bit 6 still may need unstuffing.
+;----------------------------------------------------------------------------
+
+b6checkUnstuff:
+ dec bitcnt ;[9]
+ breq unstuff6 ;[10]
+bit7:
+ subi cnt, 1 ;[11] cannot use dec becaus it does not affect the carry flag
+ brcs overflow ;[12] Too many bytes received. Ignore packet
+ in x1, USBIN ;[0] sample line state
+ andi x1, USBMASK ;[1] filter only D+ and D- bits
+ cpse x1, x2 ;[2] when previous line state equals current line state, handle "1"
+ rjmp b7handle0 ;[3] when line state differs, handle "0"
+ sec ;[4]
+ ror shift ;[5] shift "1" into the data
+ st y+, shift ;[6] store the data into the buffer
+ ldi shift, 0x40 ;[7] reset data for receiving the next byte
+ subi leap, 0x55 ;[9] trick to introduce a leap cycle every 3 bytes
+ brcc nextInst ;[10 or 11] it will fail after 85 bytes. However low speed can only receive 11
+ dec bitcnt ;[11 or 12]
+ brne bit0 ;[12 or 13]
+ ldi x1, 1 ;[13 or 14] unstuffing bit 7
+ in bitcnt, USBIN ;[0] sample stuff bit
+ rjmp unstuff ;[1]
+
+b7handle0:
+ mov x2,x1 ;[5] Set x2 to current line state
+ ldi bitcnt, 6 ;[6]
+ lsr shift ;[7] shift "0" into the data
+ st y+, shift ;[8] store data into the buffer
+ ldi shift, 0x40 ;[10] reset data for receiving the next byte
+ subi leap, 0x55 ;[11] trick to introduce a leap cycle every 3 bytes
+ brcs bit0 ;[12] it will fail after 85 bytes. However low speed can only receive 11
+ rjmp bit0 ;[13]
+
+
+;----------------------------------------------------------------------------
+; Handle unstuff
+; x1==0xFF indicate unstuffing bit6
+;----------------------------------------------------------------------------
+
+unstuff6:
+ ldi x1,0xFF ;[12] indicate unstuffing bit 6
+ in bitcnt, USBIN ;[0] sample stuff bit
+ nop ;[1] fix timing
+unstuff: ;b0-5 b6 b7
+ mov x2,bitcnt ;[3] [2] [3] Set x2 to match line state
+ subi leap2, 0x55 ;[4] [3] [4] delay loop
+ brcs nextInst ;[5] [4] [5] add one cycle every three stuff bits
+ sbci leap2,0 ;[6] [5] [6]
+ ldi bitcnt,6 ;[7] [6] [7] reset bit stuff counter
+ andi x2, USBMASK ;[8] [7] [8] only keep D+ and D-
+ cpi x1,0 ;[9] [8] [9]
+ brmi bit7 ;[10] [9] [10] finished unstuffing bit6 When x1<0
+ breq bitloop ;[11] --- [11] finished unstuffing bit0-5 when x1=0
+ nop ;--- --- [12]
+ in x1, USBIN ;--- --- [0] sample line state for bit0
+ andi x1, USBMASK ;--- --- [1] filter only D+ and D- bits
+ rjmp handleBit ;--- --- [2] make bit0 14 cycles long
+
+;----------------------------------------------------------------------------
+; Receiver loop (numbers in brackets are cycles within byte after instr)
+;----------------------------------------------------------------------------
+bitloop:
+ in x1, USBIN ;[0] sample line state
+ andi x1, USBMASK ;[1] filter only D+ and D- bits
+ breq se0 ;[2] both lines are low so handle se0
+handleBit:
+ cpse x1, x2 ;[3] when previous line state equals current line state, handle "1"
+ rjmp handle0 ;[4] when line state differs, handle "0"
+ sec ;[5]
+ ror shift ;[6] shift "1" into the data
+ brcs b6checkUnstuff ;[7] When after shift C is set, next bit is bit7
+ nop2 ;[8]
+ dec bitcnt ;[10]
+ brne bitloop ;[11]
+ ldi x1,0 ;[12] indicate unstuff for bit other than bit6 or bit7
+ in bitcnt, USBIN ;[0] sample stuff bit
+ rjmp unstuff ;[1]
+
+handle0:
+ mov x2, x1 ;[6] Set x2 to current line state
+ ldi bitcnt, 6 ;[7] reset unstuff counter.
+ lsr shift ;[8] shift "0" into the data
+ brcs bit7 ;[9] When after shift C is set, next bit is bit7
+ nop ;[10]
+ rjmp bitloop ;[11]
+
+;----------------------------------------------------------------------------
+; End of receive loop. Now start handling EOP
+;----------------------------------------------------------------------------
+
+macro POP_STANDARD ; 14 cycles
+ pop cnt
+ pop x4
+ pop x3
+ pop x2
+ pop x1
+ pop shift
+ pop bitcnt
+ endm
+macro POP_RETI ; 7 cycles
+ pop YH
+ pop YL
+ out SREG, YL
+ pop YL
+ endm
+
+
+
+#include "asmcommon.inc"
+
+; USB spec says:
+; idle = J
+; J = (D+ = 0), (D- = 1)
+; K = (D+ = 1), (D- = 0)
+; Spec allows 7.5 bit times from EOP to SOP for replies
+; 7.5 bit times is 100 cycles. This implementation arrives a bit later at se0
+; then specified in the include file but there is plenty of time
+
+bitstuffN:
+ eor x1, x4 ;[8]
+ ldi x2, 0 ;[9]
+ nop2 ;[10]
+ out USBOUT, x1 ;[12] <-- out
+ rjmp didStuffN ;[0]
+
+bitstuff7:
+ eor x1, x4 ;[6]
+ ldi x2, 0 ;[7] Carry is zero due to brcc
+ rol shift ;[8] compensate for ror shift at branch destination
+ nop2 ;[9]
+ rjmp didStuff7 ;[11]
+
+sendNakAndReti:
+ ldi x3, USBPID_NAK ;[-18]
+ rjmp sendX3AndReti ;[-17]
+sendAckAndReti:
+ ldi cnt, USBPID_ACK ;[-17]
+sendCntAndReti:
+ mov x3, cnt ;[-16]
+sendX3AndReti:
+ ldi YL, 20 ;[-15] x3==r20 address is 20
+ ldi YH, 0 ;[-14]
+ ldi cnt, 2 ;[-13]
+; rjmp usbSendAndReti fallthrough
+
+;usbSend:
+;pointer to data in 'Y'
+;number of bytes in 'cnt' -- including sync byte [range 2 ... 12]
+;uses: x1...x4, btcnt, shift, cnt, Y
+;Numbers in brackets are time since first bit of sync pattern is sent
+;We don't match the transfer rate exactly (don't insert leap cycles every third
+;byte) because the spec demands only 1.5% precision anyway.
+usbSendAndReti: ; 12 cycles until SOP
+ in x2, USBDDR ;[-12]
+ ori x2, USBMASK ;[-11]
+ sbi USBOUT, USBMINUS;[-10] prepare idle state; D+ and D- must have been 0 (no pullups)
+ in x1, USBOUT ;[-8] port mirror for tx loop
+ out USBDDR, x2 ;[-7] <- acquire bus
+; need not init x2 (bitstuff history) because sync starts with 0
+ ldi x4, USBMASK ;[-6] exor mask
+ ldi shift, 0x80 ;[-5] sync byte is first byte sent
+txByteLoop:
+ ldi bitcnt, 0x49 ;[-4] [10] binary 01001001
+txBitLoop:
+ sbrs shift, 0 ;[-3] [10] [11]
+ eor x1, x4 ;[-2] [11] [12]
+ out USBOUT, x1 ;[-1] [12] [13] <-- out N
+ ror shift ;[0] [13] [14]
+ ror x2 ;[1]
+didStuffN:
+ nop2 ;[2]
+ nop ;[4]
+ cpi x2, 0xfc ;[5]
+ brcc bitstuffN ;[6]
+ lsr bitcnt ;[7]
+ brcc txBitLoop ;[8]
+ brne txBitLoop ;[9]
+
+ sbrs shift, 0 ;[10]
+ eor x1, x4 ;[11]
+didStuff7:
+ out USBOUT, x1 ;[-1] [13] <-- out 7
+ ror shift ;[0] [14]
+ ror x2 ;[1]
+ nop ;[2]
+ cpi x2, 0xfc ;[3]
+ brcc bitstuff7 ;[4]
+ ld shift, y+ ;[5]
+ dec cnt ;[7]
+ brne txByteLoop ;[8]
+;make SE0:
+ cbr x1, USBMASK ;[9] prepare SE0 [spec says EOP may be 25 to 30 cycles]
+ lds x2, usbNewDeviceAddr;[10]
+ lsl x2 ;[12] we compare with left shifted address
+ out USBOUT, x1 ;[13] <-- out SE0 -- from now 2 bits = 22 cycles until bus idle
+ subi YL, 20 + 2 ;[0] Only assign address on data packets, not ACK/NAK in x3
+ sbci YH, 0 ;[1]
+;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm:
+;set address only after data packet was sent, not after handshake
+ breq skipAddrAssign ;[2]
+ sts usbDeviceAddr, x2; if not skipped: SE0 is one cycle longer
+skipAddrAssign:
+;end of usbDeviceAddress transfer
+ ldi x2, 1<<USB_INTR_PENDING_BIT;[4] int0 occurred during TX -- clear pending flag
+ USB_STORE_PENDING(x2) ;[5]
+ ori x1, USBIDLE ;[6]
+ in x2, USBDDR ;[7]
+ cbr x2, USBMASK ;[8] set both pins to input
+ mov x3, x1 ;[9]
+ cbr x3, USBMASK ;[10] configure no pullup on both pins
+ ldi x4, 5 ;[11]
+se0Delay:
+ dec x4 ;[12] [15] [18] [21] [24]
+ brne se0Delay ;[13] [16] [19] [22] [25]
+ out USBOUT, x1 ;[26] <-- out J (idle) -- end of SE0 (EOP signal)
+ out USBDDR, x2 ;[27] <-- release bus now
+ out USBOUT, x3 ;[28] <-- ensure no pull-up resistors are active
+ rjmp doReturn
diff --git a/tmk_core/protocol/vusb/usbdrv/usbportability.h b/tmk_core/protocol/vusb/usbdrv/usbportability.h
new file mode 100644
index 000000000..476184dc6
--- /dev/null
+++ b/tmk_core/protocol/vusb/usbdrv/usbportability.h
@@ -0,0 +1,144 @@
+/* Name: usbportability.h
+ * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
+ * Author: Christian Starkjohann
+ * Creation Date: 2008-06-17
+ * Tabsize: 4
+ * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
+ * This Revision: $Id: usbportability.h 785 2010-05-30 17:57:07Z cs $
+ */
+
+/*
+General Description:
+This header is intended to contain all (or at least most of) the compiler
+and library dependent stuff. The C code is written for avr-gcc and avr-libc.
+The API of other development environments is converted to gcc's and avr-libc's
+API by means of defines.
+
+This header also contains all system includes since they depend on the
+development environment.
+
+Thanks to Oleg Semyonov for his help with the IAR tools port!
+*/
+
+#ifndef __usbportability_h_INCLUDED__
+#define __usbportability_h_INCLUDED__
+
+/* We check explicitly for IAR and CodeVision. Default is avr-gcc/avr-libc. */
+
+/* ------------------------------------------------------------------------- */
+#if defined __IAR_SYSTEMS_ICC__ || defined __IAR_SYSTEMS_ASM__ /* check for IAR */
+/* ------------------------------------------------------------------------- */
+
+#ifndef ENABLE_BIT_DEFINITIONS
+# define ENABLE_BIT_DEFINITIONS 1 /* Enable bit definitions */
+#endif
+
+/* Include IAR headers */
+#include <ioavr.h>
+#ifndef __IAR_SYSTEMS_ASM__
+# include <inavr.h>
+#endif
+
+#define __attribute__(arg) /* not supported on IAR */
+
+#ifdef __IAR_SYSTEMS_ASM__
+# define __ASSEMBLER__ /* IAR does not define standard macro for asm */
+#endif
+
+#ifdef __HAS_ELPM__
+# define PROGMEM __farflash
+#else
+# define PROGMEM __flash
+#endif
+
+#define USB_READ_FLASH(addr) (*(PROGMEM char *)(addr))
+
+/* The following definitions are not needed by the driver, but may be of some
+ * help if you port a gcc based project to IAR.
+ */
+#define cli() __disable_interrupt()
+#define sei() __enable_interrupt()
+#define wdt_reset() __watchdog_reset()
+#define _BV(x) (1 << (x))
+
+/* assembler compatibility macros */
+#define nop2 rjmp $+2 /* jump to next instruction */
+#define XL r26
+#define XH r27
+#define YL r28
+#define YH r29
+#define ZL r30
+#define ZH r31
+#define lo8(x) LOW(x)
+#define hi8(x) (((x)>>8) & 0xff) /* not HIGH to allow XLINK to make a proper range check */
+
+/* Depending on the device you use, you may get problems with the way usbdrv.h
+ * handles the differences between devices. Since IAR does not use #defines
+ * for MCU registers, we can't check for the existence of a particular
+ * register with an #ifdef. If the autodetection mechanism fails, include
+ * definitions for the required USB_INTR_* macros in your usbconfig.h. See
+ * usbconfig-prototype.h and usbdrv.h for details.
+ */
+
+/* ------------------------------------------------------------------------- */
+#elif __CODEVISIONAVR__ /* check for CodeVision AVR */
+/* ------------------------------------------------------------------------- */
+/* This port is not working (yet) */
+
+/* #define F_CPU _MCU_CLOCK_FREQUENCY_ seems to be defined automatically */
+
+#include <io.h>
+#include <delay.h>
+
+#define __attribute__(arg) /* not supported on IAR */
+
+#define PROGMEM __flash
+#define USB_READ_FLASH(addr) (*(PROGMEM char *)(addr))
+
+#ifndef __ASSEMBLER__
+static inline void cli(void)
+{
+ #asm("cli");
+}
+static inline void sei(void)
+{
+ #asm("sei");
+}
+#endif
+#define _delay_ms(t) delay_ms(t)
+#define _BV(x) (1 << (x))
+#define USB_CFG_USE_SWITCH_STATEMENT 1 /* macro for if() cascase fails for unknown reason */
+
+#define macro .macro
+#define endm .endmacro
+#define nop2 rjmp .+0 /* jump to next instruction */
+
+/* ------------------------------------------------------------------------- */
+#else /* default development environment is avr-gcc/avr-libc */
+/* ------------------------------------------------------------------------- */
+
+#include <avr/io.h>
+#ifdef __ASSEMBLER__
+# define _VECTOR(N) __vector_ ## N /* io.h does not define this for asm */
+#else
+# include <avr/pgmspace.h>
+#endif
+
+#if USB_CFG_DRIVER_FLASH_PAGE
+# define USB_READ_FLASH(addr) pgm_read_byte_far(((long)USB_CFG_DRIVER_FLASH_PAGE << 16) | (long)(addr))
+#else
+# define USB_READ_FLASH(addr) pgm_read_byte(addr)
+#endif
+
+#define macro .macro
+#define endm .endm
+#define nop2 rjmp .+0 /* jump to next instruction */
+
+#endif /* development environment */
+
+/* for conveniecne, ensure that PRG_RDB exists */
+#ifndef PRG_RDB
+# define PRG_RDB(addr) USB_READ_FLASH(addr)
+#endif
+#endif /* __usbportability_h_INCLUDED__ */
diff --git a/tmk_core/protocol/vusb/vusb.c b/tmk_core/protocol/vusb/vusb.c
new file mode 100644
index 000000000..eaa1c512d
--- /dev/null
+++ b/tmk_core/protocol/vusb/vusb.c
@@ -0,0 +1,496 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdint.h>
+#include "usbdrv.h"
+#include "usbconfig.h"
+#include "host.h"
+#include "report.h"
+#include "print.h"
+#include "debug.h"
+#include "host_driver.h"
+#include "vusb.h"
+
+
+static uint8_t vusb_keyboard_leds = 0;
+static uint8_t vusb_idle_rate = 0;
+
+/* Keyboard report send buffer */
+#define KBUF_SIZE 16
+static report_keyboard_t kbuf[KBUF_SIZE];
+static uint8_t kbuf_head = 0;
+static uint8_t kbuf_tail = 0;
+
+typedef struct {
+ uint8_t modifier;
+ uint8_t reserved;
+ uint8_t keycode[6];
+} keyboard_report_t;
+
+static keyboard_report_t keyboard_report; // sent to PC
+
+/* transfer keyboard report from buffer */
+void vusb_transfer_keyboard(void)
+{
+ if (usbInterruptIsReady()) {
+ if (kbuf_head != kbuf_tail) {
+ usbSetInterrupt((void *)&kbuf[kbuf_tail], sizeof(report_keyboard_t));
+ kbuf_tail = (kbuf_tail + 1) % KBUF_SIZE;
+ if (debug_keyboard) {
+ print("V-USB: kbuf["); pdec(kbuf_tail); print("->"); pdec(kbuf_head); print("](");
+ phex((kbuf_head < kbuf_tail) ? (KBUF_SIZE - kbuf_tail + kbuf_head) : (kbuf_head - kbuf_tail));
+ print(")\n");
+ }
+ }
+ }
+}
+
+
+/*------------------------------------------------------------------*
+ * Host driver
+ *------------------------------------------------------------------*/
+static uint8_t keyboard_leds(void);
+static void send_keyboard(report_keyboard_t *report);
+static void send_mouse(report_mouse_t *report);
+static void send_system(uint16_t data);
+static void send_consumer(uint16_t data);
+
+static host_driver_t driver = {
+ keyboard_leds,
+ send_keyboard,
+ send_mouse,
+ send_system,
+ send_consumer
+};
+
+host_driver_t *vusb_driver(void)
+{
+ return &driver;
+}
+
+static uint8_t keyboard_leds(void) {
+ return vusb_keyboard_leds;
+}
+
+static void send_keyboard(report_keyboard_t *report)
+{
+ uint8_t next = (kbuf_head + 1) % KBUF_SIZE;
+ if (next != kbuf_tail) {
+ kbuf[kbuf_head] = *report;
+ kbuf_head = next;
+ } else {
+ debug("kbuf: full\n");
+ }
+
+ // NOTE: send key strokes of Macro
+ usbPoll();
+ vusb_transfer_keyboard();
+}
+
+
+typedef struct {
+ uint8_t report_id;
+ report_mouse_t report;
+} __attribute__ ((packed)) vusb_mouse_report_t;
+
+static void send_mouse(report_mouse_t *report)
+{
+ vusb_mouse_report_t r = {
+ .report_id = REPORT_ID_MOUSE,
+ .report = *report
+ };
+ if (usbInterruptIsReady3()) {
+ usbSetInterrupt3((void *)&r, sizeof(vusb_mouse_report_t));
+ }
+}
+
+
+typedef struct {
+ uint8_t report_id;
+ uint16_t usage;
+} __attribute__ ((packed)) report_extra_t;
+
+static void send_system(uint16_t data)
+{
+ static uint16_t last_data = 0;
+ if (data == last_data) return;
+ last_data = data;
+
+ report_extra_t report = {
+ .report_id = REPORT_ID_SYSTEM,
+ .usage = data
+ };
+ if (usbInterruptIsReady3()) {
+ usbSetInterrupt3((void *)&report, sizeof(report));
+ }
+}
+
+static void send_consumer(uint16_t data)
+{
+ static uint16_t last_data = 0;
+ if (data == last_data) return;
+ last_data = data;
+
+ report_extra_t report = {
+ .report_id = REPORT_ID_CONSUMER,
+ .usage = data
+ };
+ if (usbInterruptIsReady3()) {
+ usbSetInterrupt3((void *)&report, sizeof(report));
+ }
+}
+
+
+
+/*------------------------------------------------------------------*
+ * Request from host *
+ *------------------------------------------------------------------*/
+static struct {
+ uint16_t len;
+ enum {
+ NONE,
+ SET_LED
+ } kind;
+} last_req;
+
+usbMsgLen_t usbFunctionSetup(uchar data[8])
+{
+usbRequest_t *rq = (void *)data;
+
+ if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){ /* class request type */
+ if(rq->bRequest == USBRQ_HID_GET_REPORT){
+ debug("GET_REPORT:");
+ /* we only have one report type, so don't look at wValue */
+ usbMsgPtr = (void *)&keyboard_report;
+ return sizeof(keyboard_report);
+ }else if(rq->bRequest == USBRQ_HID_GET_IDLE){
+ debug("GET_IDLE: ");
+ //debug_hex(vusb_idle_rate);
+ usbMsgPtr = &vusb_idle_rate;
+ return 1;
+ }else if(rq->bRequest == USBRQ_HID_SET_IDLE){
+ vusb_idle_rate = rq->wValue.bytes[1];
+ debug("SET_IDLE: ");
+ debug_hex(vusb_idle_rate);
+ }else if(rq->bRequest == USBRQ_HID_SET_REPORT){
+ debug("SET_REPORT: ");
+ // Report Type: 0x02(Out)/ReportID: 0x00(none) && Interface: 0(keyboard)
+ if (rq->wValue.word == 0x0200 && rq->wIndex.word == 0) {
+ debug("SET_LED: ");
+ last_req.kind = SET_LED;
+ last_req.len = rq->wLength.word;
+ }
+ return USB_NO_MSG; // to get data in usbFunctionWrite
+ } else {
+ debug("UNKNOWN:");
+ }
+ }else{
+ debug("VENDOR:");
+ /* no vendor specific requests implemented */
+ }
+ debug("\n");
+ return 0; /* default for not implemented requests: return no data back to host */
+}
+
+uchar usbFunctionWrite(uchar *data, uchar len)
+{
+ if (last_req.len == 0) {
+ return -1;
+ }
+ switch (last_req.kind) {
+ case SET_LED:
+ debug("SET_LED: ");
+ debug_hex(data[0]);
+ debug("\n");
+ vusb_keyboard_leds = data[0];
+ last_req.len = 0;
+ return 1;
+ break;
+ case NONE:
+ default:
+ return -1;
+ break;
+ }
+ return 1;
+}
+
+
+
+/*------------------------------------------------------------------*
+ * Descriptors *
+ *------------------------------------------------------------------*/
+
+/*
+ * Report Descriptor for keyboard
+ *
+ * from an example in HID spec appendix
+ */
+const PROGMEM uchar keyboard_hid_report[] = {
+ 0x05, 0x01, // Usage Page (Generic Desktop),
+ 0x09, 0x06, // Usage (Keyboard),
+ 0xA1, 0x01, // Collection (Application),
+ 0x75, 0x01, // Report Size (1),
+ 0x95, 0x08, // Report Count (8),
+ 0x05, 0x07, // Usage Page (Key Codes),
+ 0x19, 0xE0, // Usage Minimum (224),
+ 0x29, 0xE7, // Usage Maximum (231),
+ 0x15, 0x00, // Logical Minimum (0),
+ 0x25, 0x01, // Logical Maximum (1),
+ 0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte
+ 0x95, 0x01, // Report Count (1),
+ 0x75, 0x08, // Report Size (8),
+ 0x81, 0x03, // Input (Constant), ;Reserved byte
+ 0x95, 0x05, // Report Count (5),
+ 0x75, 0x01, // Report Size (1),
+ 0x05, 0x08, // Usage Page (LEDs),
+ 0x19, 0x01, // Usage Minimum (1),
+ 0x29, 0x05, // Usage Maximum (5),
+ 0x91, 0x02, // Output (Data, Variable, Absolute), ;LED report
+ 0x95, 0x01, // Report Count (1),
+ 0x75, 0x03, // Report Size (3),
+ 0x91, 0x03, // Output (Constant), ;LED report padding
+ 0x95, 0x06, // Report Count (6),
+ 0x75, 0x08, // Report Size (8),
+ 0x15, 0x00, // Logical Minimum (0),
+ 0x25, 0xFF, 0x00 // Logical Maximum(255),
+ 0x05, 0x07, // Usage Page (Key Codes),
+ 0x19, 0x00, // Usage Minimum (0),
+ 0x29, 0xFF, // Usage Maximum (255),
+ 0x81, 0x00, // Input (Data, Array),
+ 0xc0 // End Collection
+};
+
+/*
+ * Report Descriptor for mouse
+ *
+ * Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension
+ * http://www.microchip.com/forums/tm.aspx?high=&m=391435&mpage=1#391521
+ * http://www.keil.com/forum/15671/
+ * http://www.microsoft.com/whdc/device/input/wheel.mspx
+ */
+const PROGMEM uchar mouse_hid_report[] = {
+ /* mouse */
+ 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+ 0x09, 0x02, // USAGE (Mouse)
+ 0xa1, 0x01, // COLLECTION (Application)
+ 0x85, REPORT_ID_MOUSE, // REPORT_ID (1)
+ 0x09, 0x01, // USAGE (Pointer)
+ 0xa1, 0x00, // COLLECTION (Physical)
+ // ---------------------------- Buttons
+ 0x05, 0x09, // USAGE_PAGE (Button)
+ 0x19, 0x01, // USAGE_MINIMUM (Button 1)
+ 0x29, 0x05, // USAGE_MAXIMUM (Button 5)
+ 0x15, 0x00, // LOGICAL_MINIMUM (0)
+ 0x25, 0x01, // LOGICAL_MAXIMUM (1)
+ 0x75, 0x01, // REPORT_SIZE (1)
+ 0x95, 0x05, // REPORT_COUNT (5)
+ 0x81, 0x02, // INPUT (Data,Var,Abs)
+ 0x75, 0x03, // REPORT_SIZE (3)
+ 0x95, 0x01, // REPORT_COUNT (1)
+ 0x81, 0x03, // INPUT (Cnst,Var,Abs)
+ // ---------------------------- X,Y position
+ 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+ 0x09, 0x30, // USAGE (X)
+ 0x09, 0x31, // USAGE (Y)
+ 0x15, 0x81, // LOGICAL_MINIMUM (-127)
+ 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
+ 0x75, 0x08, // REPORT_SIZE (8)
+ 0x95, 0x02, // REPORT_COUNT (2)
+ 0x81, 0x06, // INPUT (Data,Var,Rel)
+ // ---------------------------- Vertical wheel
+ 0x09, 0x38, // USAGE (Wheel)
+ 0x15, 0x81, // LOGICAL_MINIMUM (-127)
+ 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
+ 0x35, 0x00, // PHYSICAL_MINIMUM (0) - reset physical
+ 0x45, 0x00, // PHYSICAL_MAXIMUM (0)
+ 0x75, 0x08, // REPORT_SIZE (8)
+ 0x95, 0x01, // REPORT_COUNT (1)
+ 0x81, 0x06, // INPUT (Data,Var,Rel)
+ // ---------------------------- Horizontal wheel
+ 0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
+ 0x0a, 0x38, 0x02, // USAGE (AC Pan)
+ 0x15, 0x81, // LOGICAL_MINIMUM (-127)
+ 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
+ 0x75, 0x08, // REPORT_SIZE (8)
+ 0x95, 0x01, // REPORT_COUNT (1)
+ 0x81, 0x06, // INPUT (Data,Var,Rel)
+ 0xc0, // END_COLLECTION
+ 0xc0, // END_COLLECTION
+ /* system control */
+ 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+ 0x09, 0x80, // USAGE (System Control)
+ 0xa1, 0x01, // COLLECTION (Application)
+ 0x85, REPORT_ID_SYSTEM, // REPORT_ID (2)
+ 0x15, 0x01, // LOGICAL_MINIMUM (0x1)
+ 0x25, 0xb7, 0x00 // LOGICAL_MAXIMUM (0xb7)
+ 0x19, 0x01, // USAGE_MINIMUM (0x1)
+ 0x29, 0xb7, // USAGE_MAXIMUM (0xb7)
+ 0x75, 0x10, // REPORT_SIZE (16)
+ 0x95, 0x01, // REPORT_COUNT (1)
+ 0x81, 0x00, // INPUT (Data,Array,Abs)
+ 0xc0, // END_COLLECTION
+ /* consumer */
+ 0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
+ 0x09, 0x01, // USAGE (Consumer Control)
+ 0xa1, 0x01, // COLLECTION (Application)
+ 0x85, REPORT_ID_CONSUMER, // REPORT_ID (3)
+ 0x15, 0x01, // LOGICAL_MINIMUM (0x1)
+ 0x26, 0x9c, 0x02, // LOGICAL_MAXIMUM (0x29c)
+ 0x19, 0x01, // USAGE_MINIMUM (0x1)
+ 0x2a, 0x9c, 0x02, // USAGE_MAXIMUM (0x29c)
+ 0x75, 0x10, // REPORT_SIZE (16)
+ 0x95, 0x01, // REPORT_COUNT (1)
+ 0x81, 0x00, // INPUT (Data,Array,Abs)
+ 0xc0, // END_COLLECTION
+};
+
+
+/*
+ * Descriptor for compite device: Keyboard + Mouse
+ *
+ * contains: device, interface, HID and endpoint descriptors
+ */
+#if USB_CFG_DESCR_PROPS_CONFIGURATION
+const PROGMEM char usbDescriptorConfiguration[] = { /* USB configuration descriptor */
+ 9, /* sizeof(usbDescriptorConfiguration): length of descriptor in bytes */
+ USBDESCR_CONFIG, /* descriptor type */
+ 9 + (9 + 9 + 7) + (9 + 9 + 7), 0,
+ //18 + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT3 + 9, 0,
+ /* total length of data returned (including inlined descriptors) */
+ 2, /* number of interfaces in this configuration */
+ 1, /* index of this configuration */
+ 0, /* configuration name string index */
+#if USB_CFG_IS_SELF_POWERED
+ (1 << 7) | USBATTR_SELFPOWER, /* attributes */
+#else
+ (1 << 7), /* attributes */
+#endif
+ USB_CFG_MAX_BUS_POWER/2, /* max USB current in 2mA units */
+
+ /*
+ * Keyboard interface
+ */
+ /* Interface descriptor */
+ 9, /* sizeof(usbDescrInterface): length of descriptor in bytes */
+ USBDESCR_INTERFACE, /* descriptor type */
+ 0, /* index of this interface */
+ 0, /* alternate setting for this interface */
+ USB_CFG_HAVE_INTRIN_ENDPOINT, /* endpoints excl 0: number of endpoint descriptors to follow */
+ USB_CFG_INTERFACE_CLASS,
+ USB_CFG_INTERFACE_SUBCLASS,
+ USB_CFG_INTERFACE_PROTOCOL,
+ 0, /* string index for interface */
+ /* HID descriptor */
+ 9, /* sizeof(usbDescrHID): length of descriptor in bytes */
+ USBDESCR_HID, /* descriptor type: HID */
+ 0x01, 0x01, /* BCD representation of HID version */
+ 0x00, /* target country code */
+ 0x01, /* number of HID Report (or other HID class) Descriptor infos to follow */
+ 0x22, /* descriptor type: report */
+ sizeof(keyboard_hid_report), 0, /* total length of report descriptor */
+ /* Endpoint descriptor */
+#if USB_CFG_HAVE_INTRIN_ENDPOINT /* endpoint descriptor for endpoint 1 */
+ 7, /* sizeof(usbDescrEndpoint) */
+ USBDESCR_ENDPOINT, /* descriptor type = endpoint */
+ (char)0x81, /* IN endpoint number 1 */
+ 0x03, /* attrib: Interrupt endpoint */
+ 8, 0, /* maximum packet size */
+ USB_CFG_INTR_POLL_INTERVAL, /* in ms */
+#endif
+
+ /*
+ * Mouse interface
+ */
+ /* Interface descriptor */
+ 9, /* sizeof(usbDescrInterface): length of descriptor in bytes */
+ USBDESCR_INTERFACE, /* descriptor type */
+ 1, /* index of this interface */
+ 0, /* alternate setting for this interface */
+ USB_CFG_HAVE_INTRIN_ENDPOINT3, /* endpoints excl 0: number of endpoint descriptors to follow */
+ 0x03, /* CLASS: HID */
+ 0, /* SUBCLASS: none */
+ 0, /* PROTOCOL: none */
+ 0, /* string index for interface */
+ /* HID descriptor */
+ 9, /* sizeof(usbDescrHID): length of descriptor in bytes */
+ USBDESCR_HID, /* descriptor type: HID */
+ 0x01, 0x01, /* BCD representation of HID version */
+ 0x00, /* target country code */
+ 0x01, /* number of HID Report (or other HID class) Descriptor infos to follow */
+ 0x22, /* descriptor type: report */
+ sizeof(mouse_hid_report), 0, /* total length of report descriptor */
+#if USB_CFG_HAVE_INTRIN_ENDPOINT3 /* endpoint descriptor for endpoint 3 */
+ /* Endpoint descriptor */
+ 7, /* sizeof(usbDescrEndpoint) */
+ USBDESCR_ENDPOINT, /* descriptor type = endpoint */
+ (char)(0x80 | USB_CFG_EP3_NUMBER), /* IN endpoint number 3 */
+ 0x03, /* attrib: Interrupt endpoint */
+ 8, 0, /* maximum packet size */
+ USB_CFG_INTR_POLL_INTERVAL, /* in ms */
+#endif
+};
+#endif
+
+
+USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq)
+{
+ usbMsgLen_t len = 0;
+
+/*
+ debug("usbFunctionDescriptor: ");
+ debug_hex(rq->bmRequestType); debug(" ");
+ debug_hex(rq->bRequest); debug(" ");
+ debug_hex16(rq->wValue.word); debug(" ");
+ debug_hex16(rq->wIndex.word); debug(" ");
+ debug_hex16(rq->wLength.word); debug("\n");
+*/
+ switch (rq->wValue.bytes[1]) {
+#if USB_CFG_DESCR_PROPS_CONFIGURATION
+ case USBDESCR_CONFIG:
+ usbMsgPtr = (unsigned char *)usbDescriptorConfiguration;
+ len = sizeof(usbDescriptorConfiguration);
+ break;
+#endif
+ case USBDESCR_HID:
+ switch (rq->wValue.bytes[0]) {
+ case 0:
+ usbMsgPtr = (unsigned char *)(usbDescriptorConfiguration + 9 + 9);
+ len = 9;
+ break;
+ case 1:
+ usbMsgPtr = (unsigned char *)(usbDescriptorConfiguration + 9 + (9 + 9 + 7) + 9);
+ len = 9;
+ break;
+ }
+ break;
+ case USBDESCR_HID_REPORT:
+ /* interface index */
+ switch (rq->wIndex.word) {
+ case 0:
+ usbMsgPtr = keyboard_hid_report;
+ len = sizeof(keyboard_hid_report);
+ break;
+ case 1:
+ usbMsgPtr = mouse_hid_report;
+ len = sizeof(mouse_hid_report);
+ break;
+ }
+ break;
+ }
+ //debug("desc len: "); debug_hex(len); debug("\n");
+ return len;
+}
diff --git a/tmk_core/protocol/vusb/vusb.h b/tmk_core/protocol/vusb/vusb.h
new file mode 100644
index 000000000..5accf233b
--- /dev/null
+++ b/tmk_core/protocol/vusb/vusb.h
@@ -0,0 +1,27 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef VUSB_H
+#define VUSB_H
+
+#include "host_driver.h"
+
+
+host_driver_t *vusb_driver(void);
+void vusb_transfer_keyboard(void);
+
+#endif
diff --git a/tmk_core/readme.md b/tmk_core/readme.md
new file mode 100644
index 000000000..f460d0ed4
--- /dev/null
+++ b/tmk_core/readme.md
@@ -0,0 +1,150 @@
+TMK Keyboard Firmware Core Library
+==================================
+This is a keyboard firmware library with some useful features for Atmel AVR and Cortex-M.
+
+Source code is available here: <https://github.com/tmk/tmk_keyboard/tree/core>
+
+
+Updates
+-------
+#### 2016/02/10
+flabbergast's Chibios protocol was merged from <https://github.com/flabbergast/tmk_keyboard/tree/chibios>. See [protocol/chibios/README.md](protocol/chibios/README.md). Chibios protocol supports Cortex-M such as STM32 and Kinetis.
+
+#### 2015/04/22
+separated with TMK Keyboard Firmware Collection
+
+
+
+Features
+--------
+These features can be used in your keyboard.
+
+* Multi-layer Keymap - Multiple keyboard layouts with layer switching
+* Mouse key - Mouse control with keyboard
+* System Control Key - Power Down, Sleep, Wake Up and USB Remote Wake up
+* Media Control Key - Volume Down/Up, Mute, Next/Prev track, Play, Stop and etc
+* USB NKRO - 120 keys(+ 8 modifiers) simultaneously
+* PS/2 mouse support - PS/2 mouse(TrackPoint) as composite device
+* Keyboard protocols - PS/2, ADB, M0110, Sun and other old keyboard protocols
+* User Function - Customizable function of key with writing code
+* Macro - Very primitive at this time
+* Keyboard Tricks - Oneshot modifier and modifier with tapping feature
+* Debug Console - Messages for debug and interaction with firmware
+* Virtual DIP Switch - Configurations stored EEPROM(Boot Magic)
+* Locking CapsLock - Mechanical switch support for CapsLock
+* Breathing Sleep LED - Sleep indicator with charm during USB suspend
+* Backlight - Control backlight levels
+
+
+
+TMK Keyboard Firmware Collection
+--------------------------------
+Complete firmwares for various keyboards and protocol converters.
+
+<https://github.com/tmk/tmk_keyboard>
+
+
+
+License
+-------
+**GPLv2** or later. Some protocol files are under **Modified BSD License**.
+LUFA, PJRC and V-USB stack have their own license respectively.
+
+
+
+Build Firmware and Program Controller
+-------------------------------------
+See [doc/build.md](doc/build.md).
+
+
+
+Start Your Own Project
+-----------------------
+**TBD**
+### Config.h Options
+#### 1. USB vendor/product ID and device description
+ #define VENDOR_ID 0xFEED
+ #define PRODUCT_ID 0xBEEF
+ #define MANUFACTURER t.m.k.
+ #define PRODUCT Macway mod
+ #define DESCRIPTION t.m.k. keyboard firmware for Macway mod
+
+#### 2. Keyboard matrix configuration
+ #define MATRIX_ROWS 8
+ #define MATRIX_COLS 8
+ #define MATRIX_HAS_GHOST
+
+
+
+Architecture
+------------
+ Architecture Diagram
+ +---------------+---------------+-------------+
+ | Host | Keyboard | Matrix, LED |
+ ___________ |-----------+-+ +-------------+ | +-----------|
+ / /| Keys/Mouse | Protocol |d| | Action | | | Protocol |
+ /__________/ |<-----------| LUFA |r| | Layer, Tap | | | Matrix |
+ |.--------.| | LED | V-USB |i| |-------------| | | PS/2,IBM | __________________
+ || || |----------->| PJRC |v| | Keymap | | | ADB,M0110| Keys / /_/_/_/_/_/_/_/ /|
+ || Host || | Console | iWRAP(BT)|e| | Mousekey | | | SUN/NEWS |<----------/ /_/_/_/_/_/_/_/ / /
+ ||________||/.<-----------| UART |r| | Report | | | X68K/PC98| Control / /_/_/_/_/_/_/_/ / /
+ `_========_'/| |---------------------------------------------|-------->/___ /_______/ ___/ /
+ |_o______o_|/ | Sendchar, Print, Debug, Command, ... | |_________________|/
+ +---------------------------------------------+ Keyboard
+
+
+
+Debugging
+--------
+Use PJRC's `hid_listen` to see debug messages. You can use the tool for debug even if firmware use LUFA stack.
+
+You can use xprintf() to display debug info on `hid_listen`, see `common/xprintf.h`.
+
+
+
+Files and Directories
+-------------------
+### Top
+* common/ - common codes
+* protocol/ - keyboard protocol support
+* doc/ - documents
+* common.mk - Makefile for common
+* protocol.mk - Makefile for protocol
+* rules.mk - Makefile for build rules
+
+### Common
+* host.h
+* host_driver.h
+* keyboard.h
+* command.h
+* keymap.h
+* action.h
+* keycode.h
+* matrix.h
+* led.h
+* mousekey.h
+* report.h
+* debug.h
+* print.h
+* bootloader.h
+* sendchar.h
+* timer.h
+* util.h
+
+### Keyboard Protocols
+* lufa/ - LUFA USB stack
+* pjrc/ - PJRC USB stack
+* vusb/ - Objective Development V-USB
+* iwrap/ - Bluetooth HID for Bluegiga iWRAP
+* ps2.c - PS/2 protocol
+* adb.c - Apple Desktop Bus protocol
+* m0110.c - Macintosh 128K/512K/Plus keyboard protocol
+* news.c - Sony NEWS keyboard protocol
+* x68k.c - Sharp X68000 keyboard protocol
+* serial_soft.c - Asynchronous Serial protocol implemented by software
+
+
+
+Coding Style
+-------------
+- Doesn't use Tab to indent, use 4-spaces instead.
diff --git a/tmk_core/ring_buffer.h b/tmk_core/ring_buffer.h
new file mode 100644
index 000000000..7bdebbcf3
--- /dev/null
+++ b/tmk_core/ring_buffer.h
@@ -0,0 +1,53 @@
+#ifndef RING_BUFFER_H
+#define RING_BUFFER_H
+/*--------------------------------------------------------------------
+ * Ring buffer to store scan codes from keyboard
+ *------------------------------------------------------------------*/
+#define RBUF_SIZE 32
+static uint8_t rbuf[RBUF_SIZE];
+static uint8_t rbuf_head = 0;
+static uint8_t rbuf_tail = 0;
+static inline void rbuf_enqueue(uint8_t data)
+{
+ uint8_t sreg = SREG;
+ cli();
+ uint8_t next = (rbuf_head + 1) % RBUF_SIZE;
+ if (next != rbuf_tail) {
+ rbuf[rbuf_head] = data;
+ rbuf_head = next;
+ } else {
+ print("rbuf: full\n");
+ }
+ SREG = sreg;
+}
+static inline uint8_t rbuf_dequeue(void)
+{
+ uint8_t val = 0;
+
+ uint8_t sreg = SREG;
+ cli();
+ if (rbuf_head != rbuf_tail) {
+ val = rbuf[rbuf_tail];
+ rbuf_tail = (rbuf_tail + 1) % RBUF_SIZE;
+ }
+ SREG = sreg;
+
+ return val;
+}
+static inline bool rbuf_has_data(void)
+{
+ uint8_t sreg = SREG;
+ cli();
+ bool has_data = (rbuf_head != rbuf_tail);
+ SREG = sreg;
+ return has_data;
+}
+static inline void rbuf_clear(void)
+{
+ uint8_t sreg = SREG;
+ cli();
+ rbuf_head = rbuf_tail = 0;
+ SREG = sreg;
+}
+
+#endif /* RING_BUFFER_H */
diff --git a/tmk_core/rules.mk b/tmk_core/rules.mk
new file mode 100644
index 000000000..352e9314b
--- /dev/null
+++ b/tmk_core/rules.mk
@@ -0,0 +1,516 @@
+# Hey Emacs, this is a -*- makefile -*-
+#----------------------------------------------------------------------------
+# WinAVR Makefile Template written by Eric B. Weddington, Jg Wunsch, et al.
+#
+# Released to the Public Domain
+#
+# Additional material for this makefile was written by:
+# Peter Fleury
+# Tim Henigan
+# Colin O'Flynn
+# Reiner Patommel
+# Markus Pfaff
+# Sander Pool
+# Frederik Rouleau
+# Carlos Lamas
+#
+
+
+# Output format. (can be srec, ihex, binary)
+FORMAT = ihex
+
+# Optimization level, can be [0, 1, 2, 3, s].
+# 0 = turn off optimization. s = optimize for size.
+# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
+OPT = s
+
+COLOR ?= true
+
+ifeq ($(COLOR),true)
+ NO_COLOR=\033[0m
+ OK_COLOR=\033[32;01m
+ ERROR_COLOR=\033[31;01m
+ WARN_COLOR=\033[33;01m
+ BLUE=\033[0;34m
+ BOLD=\033[1m
+endif
+
+ifdef quick
+ QUICK = $(quick)
+endif
+
+QUICK ?= false
+AUTOGEN ?= false
+
+ifneq ($(shell awk --version 2>/dev/null),)
+ AWK=awk
+else
+ AWK=cat && test
+endif
+
+OK_STRING=$(OK_COLOR)[OK]$(NO_COLOR)\n
+ERROR_STRING=$(ERROR_COLOR)[ERRORS]$(NO_COLOR)\n
+WARN_STRING=$(WARN_COLOR)[WARNINGS]$(NO_COLOR)\n
+
+ifndef $(SILENT)
+ SILENT = false
+endif
+
+TAB_LOG = printf "\n$$LOG\n\n" | $(AWK) '{ sub(/^/," | "); print }'
+TAB_LOG_PLAIN = printf "$$LOG\n"
+AWK_STATUS = $(AWK) '{ printf " %-10s\n", $$1; }'
+AWK_CMD = $(AWK) '{ printf "%-99s", $$0; }'
+PRINT_ERROR = ($(SILENT) ||printf " $(ERROR_STRING)" | $(AWK_STATUS)) && $(TAB_LOG) && false
+PRINT_WARNING = ($(SILENT) || printf " $(WARN_STRING)" | $(AWK_STATUS)) && $(TAB_LOG)
+PRINT_ERROR_PLAIN = ($(SILENT) ||printf " $(ERROR_STRING)" | $(AWK_STATUS)) && $(TAB_LOG_PLAIN) && false && break
+PRINT_WARNING_PLAIN = ($(SILENT) || printf " $(WARN_STRING)" | $(AWK_STATUS)) && $(TAB_LOG_PLAIN)
+PRINT_OK = $(SILENT) || printf " $(OK_STRING)" | $(AWK_STATUS)
+BUILD_CMD = LOG=$$($(CMD) 2>&1) ; if [ $$? -gt 0 ]; then $(PRINT_ERROR); elif [ "$$LOG" != "" ] ; then $(PRINT_WARNING); else $(PRINT_OK); fi;
+
+# List any extra directories to look for include files here.
+# Each directory must be seperated by a space.
+# Use forward slashes for directory separators.
+# For a directory that has spaces, enclose it in quotes.
+EXTRAINCDIRS += $(subst :, ,$(VPATH))
+
+
+# Compiler flag to set the C Standard level.
+# c89 = "ANSI" C
+# gnu89 = c89 plus GCC extensions
+# c99 = ISO C99 standard (not yet fully implemented)
+# gnu99 = c99 plus GCC extensions
+CSTANDARD = -std=gnu99
+
+
+# Place -D or -U options here for C sources
+CDEFS += $(OPT_DEFS)
+
+
+# Place -D or -U options here for ASM sources
+ADEFS += $(OPT_DEFS)
+
+
+# Place -D or -U options here for C++ sources
+#CPPDEFS += -D__STDC_LIMIT_MACROS
+#CPPDEFS += -D__STDC_CONSTANT_MACROS
+CPPDEFS += $(OPT_DEFS)
+
+
+
+#---------------- Compiler Options C ----------------
+# -g*: generate debugging information
+# -O*: optimization level
+# -f...: tuning, see GCC manual and avr-libc documentation
+# -Wall...: warning level
+# -Wa,...: tell GCC to pass this to the assembler.
+# -adhlns...: create assembler listing
+CFLAGS += -g$(DEBUG)
+CFLAGS += $(CDEFS)
+CFLAGS += -O$(OPT)
+# add color
+ifeq ($(COLOR),true)
+ifeq ("$(shell echo "int main(){}" | $(CC) -fdiagnostics-color -x c - -o /dev/null 2>&1)", "")
+ CFLAGS+= -fdiagnostics-color
+endif
+endif
+CFLAGS += -Wall
+CFLAGS += -Wstrict-prototypes
+#CFLAGS += -mshort-calls
+#CFLAGS += -fno-unit-at-a-time
+#CFLAGS += -Wundef
+#CFLAGS += -Wunreachable-code
+#CFLAGS += -Wsign-compare
+CFLAGS += -Wa,-adhlns=$(@:%.o=%.lst)
+CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
+CFLAGS += $(CSTANDARD)
+ifdef CONFIG_H
+ CFLAGS += -include $(CONFIG_H)
+endif
+
+
+#---------------- Compiler Options C++ ----------------
+# -g*: generate debugging information
+# -O*: optimization level
+# -f...: tuning, see GCC manual and avr-libc documentation
+# -Wall...: warning level
+# -Wa,...: tell GCC to pass this to the assembler.
+# -adhlns...: create assembler listing
+CPPFLAGS += -g$(DEBUG)
+CPPFLAGS += $(CPPDEFS)
+CPPFLAGS += -O$(OPT)
+# to supress "warning: only initialized variables can be placed into program memory area"
+CPPFLAGS += -w
+CPPFLAGS += -Wall
+CPPFLAGS += -Wundef
+#CPPFLAGS += -mshort-calls
+#CPPFLAGS += -fno-unit-at-a-time
+#CPPFLAGS += -Wstrict-prototypes
+#CPPFLAGS += -Wunreachable-code
+#CPPFLAGS += -Wsign-compare
+CPPFLAGS += -Wa,-adhlns=$(@:%.o=%.lst)
+CPPFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
+#CPPFLAGS += $(CSTANDARD)
+ifdef CONFIG_H
+ CPPFLAGS += -include $(CONFIG_H)
+endif
+
+
+#---------------- Assembler Options ----------------
+# -Wa,...: tell GCC to pass this to the assembler.
+# -adhlns: create listing
+# -gstabs: have the assembler create line number information; note that
+# for use in COFF files, additional information about filenames
+# and function names needs to be present in the assembler source
+# files -- see avr-libc docs [FIXME: not yet described there]
+# -listing-cont-lines: Sets the maximum number of continuation lines of hex
+# dump that will be displayed for a given single line of source input.
+ASFLAGS += $(ADEFS) -Wa,-adhlns=$(@:%.o=%.lst),-gstabs,--listing-cont-lines=100
+ASFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
+ifdef CONFIG_H
+ ASFLAGS += -include $(CONFIG_H)
+endif
+
+#---------------- Library Options ----------------
+# Minimalistic printf version
+PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
+
+# Floating point printf version (requires MATH_LIB = -lm below)
+PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
+
+# If this is left blank, then it will use the Standard printf version.
+PRINTF_LIB =
+#PRINTF_LIB = $(PRINTF_LIB_MIN)
+#PRINTF_LIB = $(PRINTF_LIB_FLOAT)
+
+
+# Minimalistic scanf version
+SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
+
+# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
+SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
+
+# If this is left blank, then it will use the Standard scanf version.
+SCANF_LIB =
+#SCANF_LIB = $(SCANF_LIB_MIN)
+#SCANF_LIB = $(SCANF_LIB_FLOAT)
+
+
+MATH_LIB = -lm
+
+
+#---------------- Linker Options ----------------
+# -Wl,...: tell GCC to pass this to linker.
+# -Map: create map file
+# --cref: add cross reference to map file
+#
+# Comennt out "--relax" option to avoid a error such:
+# (.vectors+0x30): relocation truncated to fit: R_AVR_13_PCREL against symbol `__vector_12'
+#
+LDFLAGS += -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref
+#LDFLAGS += -Wl,--relax
+LDFLAGS += $(EXTMEMOPTS)
+LDFLAGS += $(patsubst %,-L%,$(EXTRALIBDIRS))
+LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
+#LDFLAGS += -T linker_script.x
+# You can give EXTRALDFLAGS at 'make' command line.
+LDFLAGS += $(EXTRALDFLAGS)
+
+# Define programs and commands.
+SHELL = sh
+REMOVE = rm -f
+REMOVEDIR = rmdir
+COPY = cp
+WINSHELL = cmd
+SECHO = $(SILENT) || echo
+
+# Define Messages
+# English
+MSG_ERRORS_NONE = Errors: none
+MSG_BEGIN = -------- begin --------
+MSG_END = -------- end --------
+MSG_SIZE_BEFORE = Size before:
+MSG_SIZE_AFTER = Size after:
+MSG_COFF = Converting to AVR COFF:
+MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
+MSG_FLASH = Creating load file for Flash:
+MSG_EEPROM = Creating load file for EEPROM:
+MSG_BIN = Creating binary load file for Flash:
+MSG_EXTENDED_LISTING = Creating Extended Listing:
+MSG_SYMBOL_TABLE = Creating Symbol Table:
+MSG_LINKING = Linking:
+MSG_COMPILING = Compiling:
+MSG_COMPILING_CPP = Compiling:
+MSG_ASSEMBLING = Assembling:
+MSG_CLEANING = Cleaning project:
+MSG_CREATING_LIBRARY = Creating library:
+MSG_SUBMODULE_DIRTY = $(WARN_COLOR)WARNING:$(NO_COLOR)\n \
+ Some git sub-modules are out of date or modified, please consider runnning:$(BOLD)\n\
+ git submodule sync --recursive\n\
+ git submodule update --init --recursive$(NO_COLOR)\n\n\
+ You can ignore this warning if you are not compiling any ChibiOS keyboards,\n\
+ or if you have modified the ChibiOS libraries yourself. \n\n
+
+
+# Define all object files.
+OBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(patsubst %.cpp,$(OBJDIR)/%.o,$(patsubst %.S,$(OBJDIR)/%.o,$(SRC))))
+
+# Define all listing files.
+LST = $(patsubst %.c,$(OBJDIR)/%.lst,$(patsubst %.cpp,$(OBJDIR)/%.lst,$(patsubst %.S,$(OBJDIR)/%.lst,$(SRC))))
+
+
+# Compiler flags to generate dependency files.
+#GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d
+GENDEPFLAGS = -MMD -MP -MF $(BUILD_DIR)/.dep/$(subst /,_,$@).d
+
+
+# Combine all necessary flags and optional flags.
+# Add target processor to flags.
+# You can give extra flags at 'make' command line like: make EXTRAFLAGS=-DFOO=bar
+ALL_CFLAGS = $(MCUFLAGS) $(CFLAGS) $(GENDEPFLAGS) $(EXTRAFLAGS)
+ALL_CPPFLAGS = $(MCUFLAGS) -x c++ $(CPPFLAGS) $(GENDEPFLAGS) $(EXTRAFLAGS)
+ALL_ASFLAGS = $(MCUFLAGS) -x assembler-with-cpp $(ASFLAGS) $(EXTRAFLAGS)
+
+# Default target.
+all:
+ @$(MAKE) begin
+ @$(MAKE) gccversion
+ @$(MAKE) sizebefore
+ @$(MAKE) clean_list # force clean each time
+ @$(MAKE) build
+ @$(MAKE) sizeafter
+ @$(MAKE) end
+
+# Quick make that doesn't clean
+quick:
+ @$(MAKE) begin
+ @$(MAKE) gccversion
+ @$(MAKE) sizebefore
+ @$(MAKE) build
+ @$(MAKE) sizeafter
+ @$(MAKE) end
+
+# Change the build target to build a HEX file or a library.
+build: elf hex
+#build: elf hex eep lss sym
+#build: lib
+
+
+elf: $(BUILD_DIR)/$(TARGET).elf
+hex: $(BUILD_DIR)/$(TARGET).hex
+eep: $(BUILD_DIR)/$(TARGET).eep
+lss: $(BUILD_DIR)/$(TARGET).lss
+sym: $(BUILD_DIR)/$(TARGET).sym
+LIBNAME=lib$(TARGET).a
+lib: $(LIBNAME)
+
+
+
+# Eye candy.
+# AVR Studio 3.x does not check make's exit code but relies on
+# the following magic strings to be generated by the compile job.
+begin:
+ @$(SECHO) $(MSG_BEGIN)
+ git submodule status --recursive | \
+ while IFS= read -r x; do \
+ case "$$x" in \
+ \ *) ;; \
+ *) printf "$(MSG_SUBMODULE_DIRTY)";break;; \
+ esac \
+ done
+
+end:
+ @$(SECHO) $(MSG_END)
+
+
+# Display size of file.
+HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
+#ELFSIZE = $(SIZE) --mcu=$(MCU) --format=avr $(TARGET).elf
+ELFSIZE = $(SIZE) $(BUILD_DIR)/$(TARGET).elf
+
+sizebefore:
+ @if test -f $(TARGET).hex; then $(SECHO) $(MSG_SIZE_BEFORE); $(SILENT) || $(HEXSIZE); \
+ 2>/dev/null; $(SECHO); fi
+
+sizeafter:
+ @if test -f $(TARGET).hex; then $(SECHO); $(SECHO) $(MSG_SIZE_AFTER); $(SILENT) || $(HEXSIZE); \
+ 2>/dev/null; $(SECHO); fi
+ # test file sizes eventually
+ # @if [[ $($(SIZE) --target=$(FORMAT) $(TARGET).hex | $(AWK) 'NR==2 {print "0x"$5}') -gt 0x200 ]]; then $(SECHO) "File is too big!"; fi
+
+# Display compiler version information.
+gccversion :
+ @$(SILENT) || $(CC) --version
+
+# Create final output files (.hex, .eep) from ELF output file.
+%.hex: %.elf
+ @$(SILENT) || printf "$(MSG_FLASH) $@" | $(AWK_CMD)
+ $(eval CMD=$(HEX) $< $@)
+ @$(BUILD_CMD)
+ @if $(AUTOGEN); then \
+ $(SILENT) || printf "Copying $(TARGET).hex to keymaps/$(KEYMAP)/$(KEYBOARD)_$(KEYMAP).hex\n"; \
+ $(COPY) $@ $(KEYMAP_PATH)/$(KEYBOARD)_$(KEYMAP).hex; \
+ else \
+ $(COPY) $@ $(TARGET).hex; \
+ fi
+
+%.eep: %.elf
+ @$(SILENT) || printf "$(MSG_EEPROM) $@" | $(AWK_CMD)
+ $(eval CMD=$(EEP) $< $@ || exit 0)
+ @$(BUILD_CMD)
+
+# Create extended listing file from ELF output file.
+%.lss: %.elf
+ @$(SILENT) || printf "$(MSG_EXTENDED_LISTING) $@" | $(AWK_CMD)
+ $(eval CMD=$(OBJDUMP) -h -S -z $< > $@)
+ @$(BUILD_CMD)
+
+# Create a symbol table from ELF output file.
+%.sym: %.elf
+ @$(SILENT) || printf "$(MSG_SYMBOL_TABLE) $@" | $(AWK_CMD)
+ $(eval CMD=$(NM) -n $< > $@ )
+ @$(BUILD_CMD)
+
+%.bin: %.elf
+ @$(SILENT) || printf "$(MSG_BIN) $@" | $(AWK_CMD)
+ $(eval CMD=$(BIN) $< $@ || exit 0)
+ @$(BUILD_CMD)
+
+# Create library from object files.
+.SECONDARY : $(BUILD_DIR)/$(TARGET).a
+.PRECIOUS : $(OBJ)
+%.a: $(OBJ)
+ @$(SILENT) || printf "$(MSG_CREATING_LIBRARY) $@" | $(AWK_CMD)
+ $(eval CMD=$(AR) $@ $(OBJ) )
+ @$(BUILD_CMD)
+
+# Link: create ELF output file from object files.
+.SECONDARY : $(BUILD_DIR)/$(TARGET).elf
+.PRECIOUS : $(OBJ)
+%.elf: $(OBJ)
+ @$(SILENT) || printf "$(MSG_LINKING) $@" | $(AWK_CMD)
+ $(eval CMD=$(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS))
+ @$(BUILD_CMD)
+
+# Compile: create object files from C source files.
+$(OBJDIR)/%.o : %.c
+ @mkdir -p $(@D)
+ @$(SILENT) || printf "$(MSG_COMPILING) $<" | $(AWK_CMD)
+ $(eval CMD=$(CC) -c $(ALL_CFLAGS) $< -o $@)
+ @$(BUILD_CMD)
+
+# Compile: create object files from C++ source files.
+$(OBJDIR)/%.o : %.cpp
+ @mkdir -p $(@D)
+ @$(SILENT) || printf "$(MSG_COMPILING_CPP) $<" | $(AWK_CMD)
+ $(eval CMD=$(CC) -c $(ALL_CPPFLAGS) $< -o $@)
+ @$(BUILD_CMD)
+
+# Compile: create assembler files from C source files.
+%.s : %.c
+ @$(SILENT) || printf "$(MSG_ASSEMBLING) $<" | $(AWK_CMD)
+ $(eval CMD=$(CC) -S $(ALL_CFLAGS) $< -o $@)
+ @$(BUILD_CMD)
+
+# Compile: create assembler files from C++ source files.
+%.s : %.cpp
+ @$(SILENT) || printf "$(MSG_ASSEMBLING) $<" | $(AWK_CMD)
+ $(eval CMD=$(CC) -S $(ALL_CPPFLAGS) $< -o $@)
+ @$(BUILD_CMD)
+
+# Assemble: create object files from assembler source files.
+$(OBJDIR)/%.o : %.S
+ @mkdir -p $(@D)
+ @$(SILENT) || printf "$(MSG_ASSEMBLING) $<" | $(AWK_CMD)
+ $(eval CMD=$(CC) -c $(ALL_ASFLAGS) $< -o $@)
+ @$(BUILD_CMD)
+
+# Create preprocessed source for use in sending a bug report.
+%.i : %.c
+ $(CC) -E -mmcu=$(MCU) $(CFLAGS) $< -o $@
+
+# Target: clean project.
+clean: begin clean_list end
+
+clean_list :
+ @$(REMOVE) -r $(BUILD_DIR)
+ @$(REMOVE) -r $(TOP_DIR)/$(BUILD_DIR)
+ @$(REMOVE) -r $(KEYBOARD_PATH)/$(BUILD_DIR)
+ @if $$SUBPROJECT; then $(REMOVE) -r $(SUBPROJECT_PATH)/$(BUILD_DIR); fi
+ @$(REMOVE) -r $(KEYMAP_PATH)/$(BUILD_DIR)
+
+show_path:
+ @echo VPATH=$(VPATH)
+ @echo SRC=$(SRC)
+
+SUBDIRS := $(filter-out %/util/ %/doc/ %/keymaps/ %/old_keymap_files/,$(dir $(wildcard $(TOP_DIR)/keyboards/**/*/Makefile)))
+SUBDIRS := $(SUBDIRS) $(dir $(wildcard $(TOP_DIR)/keyboards/*/.))
+SUBDIRS := $(sort $(SUBDIRS))
+# $(error $(SUBDIRS))
+all-keyboards-defaults-%:
+ @for x in $(SUBDIRS) ; do \
+ printf "Compiling with default: $$x" | $(AWK_CMD); \
+ LOG=$$($(MAKE) -C $$x $(subst all-keyboards-defaults-,,$@) VERBOSE=$(VERBOSE) COLOR=$(COLOR) SILENT=true 2>&1) ; if [ $$? -gt 0 ]; then $(PRINT_ERROR_PLAIN); elif [ "$$LOG" != "" ] ; then $(PRINT_WARNING_PLAIN); else $(PRINT_OK); fi; \
+ done
+
+all-keyboards-defaults: all-keyboards-defaults-all
+
+KEYBOARDS := $(SUBDIRS:$(TOP_DIR)/keyboards/%/=/keyboards/%)
+all-keyboards-all: $(addsuffix -all,$(KEYBOARDS))
+all-keyboards-quick: $(addsuffix -quick,$(KEYBOARDS))
+all-keyboards-clean: $(addsuffix -clean,$(KEYBOARDS))
+all-keyboards: all-keyboards-all
+
+define make_keyboard
+$(eval KEYBOARD=$(patsubst /keyboards/%,%,$1))
+$(eval SUBPROJECT=$(lastword $(subst /, ,$(KEYBOARD))))
+$(eval KEYBOARD=$(firstword $(subst /, ,$(KEYBOARD))))
+$(eval KEYMAPS=$(notdir $(patsubst %/.,%,$(wildcard $(TOP_DIR)/keyboards/$(KEYBOARD)/keymaps/*/.))))
+$(eval KEYMAPS+=$(notdir $(patsubst %/.,%,$(wildcard $(TOP_DIR)/keyboards/$(KEYBOARD)/$(SUBPROJECT)/keymaps/*/.))))
+@for x in $(KEYMAPS) ; do \
+ printf "Compiling $(BOLD)$(KEYBOARD)/$(SUBPROJECT)$(NO_COLOR) with $(BOLD)$$x$(NO_COLOR)" | $(AWK) '{ printf "%-118s", $$0; }'; \
+ LOG=$$($(MAKE) -C $(TOP_DIR)$1 $2 keymap=$$x VERBOSE=$(VERBOSE) COLOR=$(COLOR) SILENT=true 2>&1) ; if [ $$? -gt 0 ]; then $(PRINT_ERROR_PLAIN); elif [ "$$LOG" != "" ] ; then $(PRINT_WARNING_PLAIN); else $(PRINT_OK); fi; \
+done
+endef
+
+define make_keyboard_helper
+# Just remove the -quick, -all and so on from the first argument and pass it forward
+$(call make_keyboard,$(subst -$2,,$1),$2)
+endef
+
+/keyboards/%-quick:
+ $(call make_keyboard_helper,$@,quick)
+/keyboards/%-all:
+ $(call make_keyboard_helper,$@,all)
+/keyboards/%-clean:
+ $(call make_keyboard_helper,$@,clean)
+/keyboards/%:
+ $(call make_keyboard_helper,$@,all)
+
+all-keymaps-%:
+ $(eval MAKECONFIG=$(call get_target,all-keymaps,$@))
+ $(eval KEYMAPS=$(notdir $(patsubst %/.,%,$(wildcard $(TOP_DIR)/keyboards/$(KEYBOARD)/keymaps/*/.))))
+ @for x in $(KEYMAPS) ; do \
+ printf "Compiling $(BOLD)$(KEYBOARD)$(NO_COLOR) with $(BOLD)$$x$(NO_COLOR)" | $(AWK) '{ printf "%-118s", $$0; }'; \
+ LOG=$$($(MAKE) $(subst all-keymaps-,,$@) keyboard=$(KEYBOARD) keymap=$$x VERBOSE=$(VERBOSE) COLOR=$(COLOR) SILENT=true 2>&1) ; if [ $$? -gt 0 ]; then $(PRINT_ERROR_PLAIN); elif [ "$$LOG" != "" ] ; then $(PRINT_WARNING_PLAIN); else $(PRINT_OK); fi; \
+ done
+
+all-keymaps: all-keymaps-all
+
+# Create build directory
+$(shell mkdir $(BUILD_DIR) 2>/dev/null)
+
+# Create object files directory
+$(shell mkdir $(OBJDIR) 2>/dev/null)
+
+
+# Include the dependency files.
+-include $(shell mkdir $(BUILD_DIR)/.dep 2>/dev/null) $(wildcard $(BUILD_DIR)/.dep/*)
+
+
+# Listing of phony targets.
+.PHONY : all quick begin finish end sizebefore sizeafter gccversion \
+build elf hex eep lss sym coff extcoff \
+clean clean_list debug gdb-config show_path \
+program teensy dfu flip dfu-ee flip-ee dfu-start \
+all-keyboards-defaults all-keyboards all-keymaps \
+all-keyboards-defaults-% all-keyboards-% all-keymaps-%
diff --git a/tmk_core/tool/chibios/.gitignore b/tmk_core/tool/chibios/.gitignore
new file mode 100644
index 000000000..88bbafe34
--- /dev/null
+++ b/tmk_core/tool/chibios/.gitignore
@@ -0,0 +1,2 @@
+chibios
+chibios-contrib
diff --git a/tmk_core/tool/chibios/ch-bootloader-jump.patch b/tmk_core/tool/chibios/ch-bootloader-jump.patch
new file mode 100644
index 000000000..d88657621
--- /dev/null
+++ b/tmk_core/tool/chibios/ch-bootloader-jump.patch
@@ -0,0 +1,116 @@
+diff --git a/os/common/ports/ARMCMx/compilers/GCC/crt0_v6m.s b/os/common/ports/ARMCMx/compilers/GCC/crt0_v6m.s
+index 51a79bb..42d07bd 100644
+--- a/os/common/ports/ARMCMx/compilers/GCC/crt0_v6m.s
++++ b/os/common/ports/ARMCMx/compilers/GCC/crt0_v6m.s
+@@ -105,6 +105,13 @@
+ #define CRT0_CALL_DESTRUCTORS TRUE
+ #endif
+
++/**
++ * @brief Magic number for jumping to bootloader.
++ */
++#if !defined(MAGIC_BOOTLOADER_NUMBER) || defined(__DOXYGEN__)
++#define MAGIC_BOOTLOADER_NUMBER 0xDEADBEEF
++#endif
++
+ /*===========================================================================*/
+ /* Code section. */
+ /*===========================================================================*/
+@@ -124,6 +131,17 @@
+ .thumb_func
+ .global Reset_Handler
+ Reset_Handler:
++
++#ifdef STM32_BOOTLOADER_ADDRESS
++ /* jump to bootloader code */
++ ldr r0, =__ram0_end__-4
++ ldr r1, =MAGIC_BOOTLOADER_NUMBER
++ ldr r2, [r0, #0]
++ str r0, [r0, #0] /* erase stored magic */
++ cmp r2, r1
++ beq Bootloader_Jump
++#endif /* STM32_BOOTLOADER_ADDRESS */
++
+ /* Interrupts are globally masked initially.*/
+ cpsid i
+
+@@ -242,6 +260,21 @@ endfiniloop:
+ ldr r1, =__default_exit
+ bx r1
+
++#ifdef STM32_BOOTLOADER_ADDRESS
++/*
++ * Jump-to-bootloader function.
++ */
++
++ .align 2
++ .thumb_func
++Bootloader_Jump:
++ ldr r0, =STM32_BOOTLOADER_ADDRESS
++ ldr r1, [r0, #0]
++ mov sp, r1
++ ldr r0, [r0, #4]
++ bx r0
++#endif /* STM32_BOOTLOADER_ADDRESS */
++
+ #endif
+
+ /** @} */
+diff --git a/os/common/ports/ARMCMx/compilers/GCC/crt0_v7m.s b/os/common/ports/ARMCMx/compilers/GCC/crt0_v7m.s
+index 4812a29..dca9f88 100644
+--- a/os/common/ports/ARMCMx/compilers/GCC/crt0_v7m.s
++++ b/os/common/ports/ARMCMx/compilers/GCC/crt0_v7m.s
+@@ -140,6 +140,13 @@
+ #define CRT0_CPACR_INIT 0x00F00000
+ #endif
+
++/**
++ * @brief Magic number for jumping to bootloader.
++ */
++#if !defined(MAGIC_BOOTLOADER_NUMBER) || defined(__DOXYGEN__)
++#define MAGIC_BOOTLOADER_NUMBER 0xDEADBEEF
++#endif
++
+ /*===========================================================================*/
+ /* Code section. */
+ /*===========================================================================*/
+@@ -164,6 +171,17 @@
+ .thumb_func
+ .global Reset_Handler
+ Reset_Handler:
++
++#ifdef STM32_BOOTLOADER_ADDRESS
++ /* jump to bootloader code */
++ ldr r0, =__ram0_end__-4
++ ldr r1, =MAGIC_BOOTLOADER_NUMBER
++ ldr r2, [r0, #0]
++ str r0, [r0, #0] /* erase stored magic */
++ cmp r2, r1
++ beq Bootloader_Jump
++#endif /* STM32_BOOTLOADER_ADDRESS */
++
+ /* Interrupts are globally masked initially.*/
+ cpsid i
+
+@@ -305,6 +323,21 @@ endfiniloop:
+ /* Branching to the defined exit handler.*/
+ b __default_exit
+
++#ifdef STM32_BOOTLOADER_ADDRESS
++/*
++ * Jump-to-bootloader function.
++ */
++
++ .align 2
++ .thumb_func
++Bootloader_Jump:
++ ldr r0, =STM32_BOOTLOADER_ADDRESS
++ ldr r1, [r0, #0]
++ mov sp, r1
++ ldr r0, [r0, #4]
++ bx r0
++#endif /* STM32_BOOTLOADER_ADDRESS */
++
+ #endif /* !defined(__DOXYGEN__) */
+
+ /** @} */
diff --git a/util/1-setup-path-win.bat b/util/1-setup-path-win.bat
new file mode 100644
index 000000000..699aee215
--- /dev/null
+++ b/util/1-setup-path-win.bat
@@ -0,0 +1,66 @@
+@SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
+@ECHO OFF
+SET CMDLINERUNSTR=%SystemRoot%\system32\cmd.exe
+
+DEL script1.log > NUL 2>&1
+DEL add-paths.log > NUL 2>&1
+DEL add-paths-detail.log > NUL 2>&1
+DEL UPDATE > NUL 2>&1
+
+ELEVATE -wait add-paths.bat >> script1.log 2>&1
+
+IF ERRORLEVEL 1 (
+ ECHO You denied admin access. Rerun the script, and be sure to press the yes button this time.
+) ELSE (
+ TYPE add-paths.log 2> NUL
+)
+ECHO.
+
+:: Branch to UpdateEnv if we need to update
+IF EXIST UPDATE (
+ DEL UPDATE
+ GOTO UpdateEnv
+)
+
+GOTO ExitBatch
+
+:: -----------------------------------------------------------------------------
+
+:UpdateEnv
+ECHO Making updated PATH go live . . .
+REG delete HKCU\Environment /F /V TEMPVAR > NUL 2>&1
+setx TEMPVAR 1 > NUL
+REG delete HKCU\Environment /F /V TEMPVAR > NUL 2>&1
+IF NOT !cmdcmdline! == !CMDLINERUNSTR! (CALL :KillExplorer)
+GOTO ExitBatch
+
+:: -----------------------------------------------------------------------------
+
+:ExitBatch
+ENDLOCAL
+PAUSE
+EXIT /b
+
+:: -----------------------------------------------------------------------------
+
+:KillExplorer
+ECHO.
+ECHO.
+ECHO Your desktop will be restarted.
+ECHO.
+ECHO All file explorer windows except for the one you launched this script from WILL BE CLOSED.
+ECHO.
+ECHO Press enter when ready, or close this window if you would rather do a full restart of your computer at a later time.
+ECHO.
+PAUSE
+ping -n 5 127.0.0.1 > NUL 2>&1
+ECHO Killing process Explorer.exe. . .
+ECHO.
+taskkill /f /im explorer.exe > NUL
+ECHO.
+ECHO Your desktop is now loading. . .
+ECHO.
+ping -n 5 127.0.0.1 > NUL 2>&1
+START explorer.exe
+START explorer.exe %CD%
+EXIT /b \ No newline at end of file
diff --git a/util/2-setup-environment-win.bat b/util/2-setup-environment-win.bat
new file mode 100644
index 000000000..3e54cc776
--- /dev/null
+++ b/util/2-setup-environment-win.bat
@@ -0,0 +1,72 @@
+@SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
+@ECHO OFF
+
+CD %~dp0
+
+SET STARTINGDIR=%CD%
+echo %STARTINGDIR%
+
+:: Check for admin privilages
+SETX /M test test > nul 2>&1
+IF NOT ["%ERRORLEVEL%"]==["0"] (
+ ELEVATE -wait 2-setup-environment-win.bat & goto :EOF
+)
+
+DEL %STARTINGDIR%\environment-setup.log
+
+:: Make sure path to MinGW exists - if so, CD to it
+SET MINGWPATH="C:\MinGW\bin"
+IF NOT EXIST !MINGWPATH! (ECHO Path not found: %MINGWPATH%. Did you install MinGW to the default location? && GOTO ExitBatch)
+CD /D %MINGWPATH%
+
+ECHO.
+ECHO ------------------------------------------
+ECHO Installing wget and unzip
+ECHO ------------------------------------------
+ECHO.
+mingw-get install msys-wget-bin msys-unzip-bin
+
+MKDIR temp
+CD temp
+
+ECHO.
+ECHO ------------------------------------------
+ECHO Installing dfu-programmer.
+ECHO ------------------------------------------
+ECHO.
+wget 'http://downloads.sourceforge.net/project/dfu-programmer/dfu-programmer/0.7.2/dfu-programmer-win-0.7.2.zip' >> %STARTINGDIR%\environment-setup.log
+unzip -o dfu-programmer-win-0.7.2.zip >> %STARTINGDIR%\environment-setup.log
+COPY dfu-programmer.exe .. >> %STARTINGDIR%\environment-setup.log
+
+ECHO ------------------------------------------
+ECHO Downloading driver
+ECHO ------------------------------------------
+wget http://downloads.sourceforge.net/project/libusb-win32/libusb-win32-releases/1.2.6.0/libusb-win32-bin-1.2.6.0.zip >> %STARTINGDIR%\environment-setup.log
+unzip -o libusb-win32-bin-1.2.6.0.zip >> %STARTINGDIR%\environment-setup.log
+COPY libusb-win32-bin-1.2.6.0\bin\x86\libusb0_x86.dll ../libusb0.dll >> %STARTINGDIR%\environment-setup.log
+
+ECHO.
+ECHO ------------------------------------------
+ECHO Installing driver. Accept prompt.
+ECHO ------------------------------------------
+ECHO.
+IF EXIST "%WinDir%\System32\PnPUtil.exe" (%WinDir%\System32\PnPUtil.exe -i -a dfu-prog-usb-1.2.2\atmel_usb_dfu.inf && GOTO PNPUTILFOUND)
+IF EXIST "%WinDir%\Sysnative\PnPUtil.exe" (%WinDir%\Sysnative\PnPUtil.exe -i -a dfu-prog-usb-1.2.2\atmel_usb_dfu.inf && GOTO PNPUTILFOUND)
+
+ECHO FAILED. Could not find PnPUtil.exe in "%WinDir%\System32" or "%WinDir%\Sysnative".
+
+:PNPUTILFOUND
+
+:: Wait then delete directory
+ping -n 5 127.0.0.1 > NUL 2>&1
+CD ..
+RD /s /q temp
+
+ECHO ------------------------------------------
+ECHO Finished!
+
+:ExitBatch
+CD /D %STARTINGDIR%
+ENDLOCAL
+PAUSE
+EXIT /b \ No newline at end of file
diff --git a/util/ELEVATE_LICENSE.md b/util/ELEVATE_LICENSE.md
new file mode 100644
index 000000000..1cf4fda91
--- /dev/null
+++ b/util/ELEVATE_LICENSE.md
@@ -0,0 +1,25 @@
+Elevate was downloaded from [here](https://jpassing.com/2007/12/08/launch-elevated-processes-from-the-command-line/).
+
+### LICENSE
+
+The MIT License (MIT)
+
+Copyright (c) <year> <copyright holders>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE. \ No newline at end of file
diff --git a/util/add-paths.bat b/util/add-paths.bat
new file mode 100644
index 000000000..ab3d91da1
--- /dev/null
+++ b/util/add-paths.bat
@@ -0,0 +1,30 @@
+@SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
+@ECHO off
+
+SET NEWPATH1="C:\MinGW\msys\1.0\bin"
+SET NEWPATH2="C:\MinGW\bin"
+
+CD %~dp0
+
+ECHO. > add-paths.log
+
+CALL :AddPath %NEWPATH1%
+CALL :AddPath %NEWPATH2%
+
+EXIT /b
+
+:AddPath <pathToAdd>
+ECHO %PATH% | FINDSTR /C:"%~1" > nul
+IF ERRORLEVEL 1 (
+ REG add "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /f /v PATH /t REG_SZ /d "%PATH%;%~1" >> add-paths-detail.log
+ IF ERRORLEVEL 0 (
+ ECHO Adding %1 . . . Success! >> add-paths.log
+ SET "PATH=%PATH%;%~1"
+ COPY NUL UPDATE
+ ) ELSE (
+ ECHO Adding %1 . . . FAILED. Run this script with administrator privileges. >> add-paths.log
+ )
+) ELSE (
+ ECHO Skipping %1 - Already in PATH >> add-paths.log
+ )
+EXIT /b \ No newline at end of file
diff --git a/util/bootloader.hex b/util/bootloader.hex
new file mode 100755
index 000000000..275aeacba
--- /dev/null
+++ b/util/bootloader.hex
@@ -0,0 +1,253 @@
+:020000020000FC
+:047000000C948D3E21
+:047028000C94B73DD0
+:10702F0012010002FF010020EB03F42F0000010208
+:10703F00030109021200010100803209040000005F
+:10704F00000000000C03410054004D0045004C00AF
+:10705F001603410054006D00330032005500340018
+:10706F004400460055000C0331002E0030002E0066
+:10707F0030000403090416010C0100000C0000018C
+:02708F006C7F14
+:1070920012BD01BDF89A00B5089501E00895F9996D
+:1070A200FECF12BD01BD20BDFA9AF99AF6CFF99929
+:1070B200FECF0C944938F80104910895F8013491F7
+:1070C20031962491890108950091610000930C0189
+:1070D20000E80093610001E00093610005BF02E057
+:1070E20005BF0C9486380091D70001600093D70049
+:1070F200A89507EF04BF0091600000610093600053
+:1071020000E00093600001E008950E94AA3D0E9401
+:10711200B53DFDCF0CD00F7708D0006806D00061D6
+:1071220004D0016028D0789408950093D80000918B
+:10713200D8000895FCDF00621ED04CD009B500FFD4
+:10714200FDCFF5DF0F7D17D00091E0000E7F009399
+:10715200E0000091E000077F0093E0000091E20070
+:1071620001600093E2000091E20008600093E200F7
+:1071720078940C94743B0093D800089500910D010B
+:10718200002359F40091D90000FF07C0D0DF006846
+:10719200F2DF01E000930D01CDDFE0E2F2E00081D9
+:1071A200018100FF0DC0008111811E7F11830083C8
+:1071B20001E00093EA0000E00093EA0000931E025F
+:1071C20000E00093E9000091E80003FF02C00E9482
+:1071D200F23B0895A89539D000E40093600000E0E6
+:1071E200009381000093800010E0009385000093DB
+:1071F200840001E006BB00918100036000938100DE
+:107202000091600007FFFCCF00E80093600010933C
+:107212008100A89507EF04BF18D010936000209159
+:1072220084003091850010938100109380001093A8
+:1072320085001093840001E006BB2D3D354010F01F
+:1072420002E101C002E009BD089500916000006101
+:107252000093600008950E94AD3E239741D100E063
+:1072620000930901B5D104811581012B51F437D165
+:1072720000910701002309F4B9C000E0009307015F
+:10728200B5C058D102FFFDCF37D1068335D1009367
+:107292000F0132D1009310012FD1009311012CD193
+:1072A2000093120129D10093130102852091130149
+:1072B20030911201409111015091100116811A95DD
+:1072C20041F01250A9F01A9599F11A9509F473C078
+:1072D2008BC010910F01113011F411E001C010E0C8
+:1072E200138799D00C3F11F414D17FC077D17DC0A0
+:1072F20092D010910F01112329F01A9549F01A9595
+:10730200A9F073C010E013870C3F09F06EC0ECCFF8
+:1073120056D103C04CD109F468C00D911C9144D1DF
+:107322000F3FC1F305E0009309015FC011E0EBCF0D
+:10733200D2D029F00250E1F10A9541F056C0FDD0B9
+:107342000E94A33F0FEF00930A014FC0552319F08B
+:107352005A9579F04AC04ED00DEF04BF74D0EAD0EE
+:1073620003FFFDCF67D051D04AD008E00093600000
+:10737200FFCF40D068D0DED003FFFDCF5BD03FD03F
+:1073820044D00FEF1FE004C009811A810150104060
+:1073920009831A8309811A81012BB1F700E800934E
+:1073A200610000910C01009361000C940000FFCF7A
+:1073B20001E003871AC08FD019F00A9539F015C081
+:1073C200535098F4BAD002E000870FC0505339F0FE
+:1073D2005A9541F05F52B1F35A95A1F306C002E00B
+:1073E2000883F0CF01E0FCCFA8D079D02396E4E067
+:1073F2000C94BA3E01E005BF00E005BF089500917C
+:10740200D8000F770093D800089509B50D7F09BD04
+:1074120000E009BD08955183408333832283109194
+:10742200E8001B7F1093E8001091E8001F7710938B
+:10743200E80008955DD053D0F8940091E000016017
+:107442000093E000089579D04AC0219749D0009175
+:107452000601035019F00250B9F00BC03CD021F0E4
+:107462000A9559F00A9529F400910A010C3F19F482
+:1074720050D02196089567D0FCCF0091010100936E
+:10748200F100009100010AC01091100124D019F0FE
+:107492000A9549F0EECF135018F400E00093F10082
+:1074A2001ED044D0E6CF105339F01A9539F01F524E
+:1074B20041F01A9541F0F4CF08E5F0CF00E006D094
+:1074C200EDCF02E0FCCF04E001D0E8CF10E020E0F5
+:1074D20030E00C94113F00910F010023089521C068
+:1074E2000BD008D007D00093040106D00093050109
+:1074F20021D00BC000D008830091F10008950091C3
+:10750200EB0000620093EB0015D0077F0093E800C8
+:107512000895F5DF02E00093080103E000930901FA
+:10752200089559D007D000FFFDCF089503D002FF80
+:10753200FDCF03C00091E8000895FCDF0B7FE6DF7A
+:10754200F9DF0F77E3CF0E94AC3E42D038D006C0BD
+:107552002BD00093F1002BD059F43DD0082F092BEA
+:10756200A9F0E8DF02FD12C0E5DF00FFFDCF4424F1
+:10757200042D4394003289F300910B0100230D91F5
+:107582001C9131F311970E945838E3CFD3DF00FFEB
+:10759200FDCF21D0CFDF00FFFDCFCCDF02FFFDCF3B
+:1075A200CCDFE5E00C94B93E11970C945C380D9158
+:1075B2001C910F5F1F4F1C930E93019708958281B8
+:1075C200938100811181801B910B0196DF01089547
+:1075D200E0E0F1E00895AEDF0E7F98CF0E94A93E71
+:1075E200F7DF80819181A081B181AF710481158122
+:1075F20000521040048315830AC000910B0100233E
+:1076020031F4A301920103E911E00E943B3F47D00C
+:10761200B8F1662477242C0111C06EDFF301ED5618
+:10762200FE4F008301E0600E00E0701E01960091A3
+:10763200F200002311F033D0B8F47FDF30D0E8F24B
+:10764200F301B096E238F040C0F674DF02FFFDCFDE
+:107652000091F200BDDF24813581201B304024835C
+:107662003583E5CF49DFAA95AA23E1F700910B0103
+:10767200013099F62091F1008C010E945038D6CF4A
+:1076820004811581012B21F055DF02FFFDCF55DF6B
+:10769200A2DF50DF00FFFDCFE8E00C94B63EE0E051
+:1076A200F1E0028113810817190708952091EB0078
+:1076B20021602093EB000093EC000091ED0002703A
+:1076C200012B0093ED000091ED0002600093ED00AC
+:1076D2001091EE00012F000F00E0001F0895412FCE
+:1076E2000093E900089500E009D000FD05C000E024
+:1076F200F7DF10E202E0DACF00E00895F1DF009157
+:10770200EB0008950F770132A9F5112369F11A955B
+:1077120059F01A9561F01A9569F01A95F9F01A95CF
+:10772200C1F01A95D9F024C00E942C3920C00E94C1
+:10773200263A1DC029D00091090123D001E01FD0B3
+:1077420020D0009108011BD00E94923A0E94973AE1
+:107752000EC01AD00091080114D007C002E00093B5
+:10776200080100E0009309010FD00E94923A03C081
+:107772000E94803A02C001E0089500E0089501D01D
+:1077820000E00093F10008950091E800077F009364
+:10779200E800089508950350F9F4112339F01A9579
+:1077A20051F01A9581F01A9599F016C004E016D09E
+:1077B20001E810E703C011D003E510E7E7E1F2E0CA
+:1077C20000831183D8CF06E109D00FE510E7F6CF89
+:1077D20004D005E710E7F2CFD0CF0CE000931A02F5
+:1077E200089527D120D100931D02E1D0212F11232A
+:1077F20029F12A95E9F02250F1F0225099F02A95C8
+:1078020049F0225061F02A9581F02A95E1F02A95FB
+:10781200E9F023C0003809F44FC00C94833B0038D0
+:10782200E1F7C8C00023C9F71EC00023B1F72DC07D
+:10783200033098F744C1033080F70BC1003868F376
+:10784200033858F7C9C0013841F77BC1013051F400
+:10785200FCD0BFD000FD06C0FCCF0E94833B0023BA
+:1078620009F41ED008951091E3001078DCD00F7750
+:10787200012B0093E300E9D0ACD000FFFDCF0091D3
+:10788200E30000680093E300089591D0123040F4C1
+:107892000FD010931E02DAD000911E020C94CB3B43
+:1078A2000091EB0001D004C000620093EB00089548
+:1078B2000091E800077FC0C0BA93AA93229700E024
+:1078C2000093190274D0AFD0202F2A9519F02A956F
+:1078D200E9F022C002E100931A020FE210E7E7E1A9
+:1078E200F2E0008311839DD008839DD00983E0DFFD
+:1078F20000911A0210E02881398102171307A8F4B7
+:107902000F7181F401E00093190211C002E10093AA
+:107912001A0201E410E7E3CF0E94CC3B002319F7DF
+:107922008ED040C01093190202C020931A027ED05A
+:10793200A7E1B2E001C08AD000911A02002309F146
+:1079420048D004FD1EC045D000FD03C042D004FF54
+:10795200FACF10E0012F1395003281F0ED91FC91E6
+:107962001197049133D02D913C912F5F3F4F3C935F
+:107972002E93FD0103810A95038361F72AD004FF48
+:10798200DACF00911902013039F423D004FD04C08A
+:1079920020D000FFFDCF5AD01CD004FFFDCF46D02F
+:1079A20018D00B7F49D02296A991B99108951091D0
+:1079B200F10008957DDF00911E0208D047D009D062
+:1079C2000F773AD006D002FFFDCFBFC00093F1007F
+:1079D20008950091E800089524D010911D021058D6
+:1079E20029F01A9589F01A9591F019C061DF00917A
+:1079F2001C02ECDF00E0EADF29D0EBDF02FFFDCF63
+:107A020018D0E7DF0F770CC053DF00E0F2CF51D080
+:107A12000F7710E0F801E55EFD4F0081EACF0FD04D
+:107A22000BC001D000D00091F1000895D2DF0F7E8B
+:107A320003C00091E8000B7F0093E80008950091D5
+:107A4200EB0032DFC6DF077F089532DFC2DF0E7F31
+:107A5200F3CF00911D02002329F00A9509F10A953E
+:107A620031F01EC0E0DF0A9561D0D9F41AC061D0AE
+:107A7200B9F4D9DF0F7711F416D01BD00093E900C7
+:107A82001091EB0010FF0BC00ED010E01093E90034
+:107A920021E0F801E55EFD4F20834FD003C042D0C4
+:107AA20045D0CFDFC9CF1091EB0010621093EB00ED
+:107AB20008951091E800177F1093E800089500914F
+:107AC2001D02002311F4AFDF02C0013011F4B7DF51
+:107AD200B3CF023031F52DD019F52091F1002F7777
+:107AE2002093E90023D000FF19C081F01FD000616C
+:107AF200DCDE01E010E0422F0E949F3E0093EA008C
+:107B020000E00093EA0012D00860CFDE0BD030E034
+:107B1200F901E55EFD4F008310D0DACF03D0D7CF55
+:107B2200BFDE089500E00093E90008950091EB00A4
+:107B3200089579DF3CDF00230895BADE4ADF0E7F25
+:107B4200089583DF46DF02FFFDCF73DF42DF0F7749
+:107B520073CF0091D70001600093D7000E948B3849
+:107B620000E000931F0208950C94BF388A93FA93A1
+:107B7200EA933A922A921A920A927A936A935A93BF
+:107B82004A933A932A931A930A938FB70091DA0091
+:107B920000FF24C00091D80000FF20C00EEF009328
+:107BA200DA000091D90000FF11C001E000930D013D
+:107BB200ABD0026096D09AD00860A2D00E949B38C7
+:107BC2000091E0000E7F0093E00008C000E0009307
+:107BD2000D0100931E0298D0046083D07FD002FF73
+:107BE20005C084D002FF02C00BEF75D077D000FF32
+:107BF2001BC07CD000FF18C001E000930E016AD0C8
+:107C020083D000626ED00EEF6FD0006179D06ED05B
+:107C12000F7D76D00091D80000620093D80009B59C
+:107C22000D7F09BD00E009BD59D004FF20C05ED020
+:107C320004FF1DC009B500FD05C00E94EB3809B55F
+:107C420000FFFDCF0091D8000F7D0093D80042D0F5
+:107C520000910E01002359F04CD00FEE45D00F7E5B
+:107C620052D000643ED042D001604AD042D036D0D9
+:107C720005FF0FC03BD005FF0CC000E000930E01D2
+:107C820035D00F7E3DD00FED2FD00F7D3CD0006858
+:107C920028D024D003FF0DC029D003FF0AC000E082
+:107CA20000931F0207EF17D00E94743B2DD0116082
+:107CB20018D08FBF09911991299139914991599100
+:107CC200699179910990199029903990E991F991E6
+:107CD200899118950FEE0093E10008950091E1005B
+:107CE20008951183008308950093E1000091E2005A
+:107CF20008950091E200006203D00091E200086062
+:107D02000093E2000895FCDFE0E2F2E000811181DD
+:107D1200089500008895FECF01E60DBF02E00EBF78
+:107D2200C2EED2E00E947438002311F00E94D33ECA
+:107D32000E9465380E948A3E0C948A3E4A951AF047
+:107D4200000F111FFBCF0895BA92AA929A928A92BB
+:107D52007A926A925A924A92BA93AA939A938A937D
+:107D62000895BB84AA84998488847F806E805D8014
+:107D72004C80BB81AA8199818881F0E00FB6F8948A
+:107D8200CE0FDF1F0FBE089520E006D0E9F7089559
+:107D9200259102D0E9F708952D9301501040202F2C
+:107DA200212B089585E890E7FC0105911491FC01CF
+:107DB2003296A591B491FC01349625913491422FCB
+:107DC200432B19F0F901E4DF01C0DEDF069610E76C
+:107DD2008139910748F308952F930CD02F9101D048
+:107DE20008953CD0F12FE02F45E047BFE89536D00B
+:107DF20012D0089533D0F12FE02F43E047BFE8952A
+:107E02002DD008952BD0F12FE02F43E047BFE89506
+:107E120025D001D0089522D041E147BFE8951EC088
+:107E22001DD0F12FE02F41E247BFC895002D16C0AB
+:107E320015D0F12FE02F49E047BFC895002D0EC0A5
+:107E4200F32FE22F012E102E41E047BFE89506C026
+:107E520005D0002E29E027BFE89500C0022E27B7E3
+:107E620020FDFCCF202D0895022E27B726FDFCCF42
+:107E7200202D08950E94A53E22974801C901DA01EA
+:107E820010C05BD001E0A00E00E0B01E00E4A0161E
+:107E920000E0B00608F440C0830120E030E00E9418
+:107EA200F23E0A2F0B2B09F440C0082F0F7710E087
+:107EB2002C01401A510A320100E4A02E03C00A2FFD
+:107EC2000B2BE1F04816590680F0F40101914F01A5
+:107ED2000983119729F001914F010883119711C06D
+:107EE200F2013196049108830CC0F20104910983D6
+:107EF2003196E817F907A1F7F401EDCF1BD00883FB
+:107F020019839201088119810E94213F16D0AA94F7
+:107F1200B1F62301AA24BB240DD0312F0F3F3F4FCE
+:107F220009F4AFCF83011DD0B7CF01E02296ECE078
+:107F32000C94B23E82010C945F3802E0400E00E0E5
+:107F4200501E08959A938A9380E090E08C0109D0A4
+:107F520080589F4F8F3F0FE69007C0F38991999108
+:107F6200089520E030E00C94FB3E00000000000089
+:067F720000000000FC000D
+:107FE4000C94ED3E0C94113F0C94193F0C94213FDA
+:0C7FF4000C94F23E0C94033F0C94293FC7
+:040000030000700089
+:00000001FF
diff --git a/util/elevate.exe b/util/elevate.exe
new file mode 100644
index 000000000..fc6180ec9
--- /dev/null
+++ b/util/elevate.exe
Binary files differ
diff --git a/util/install_dependencies.sh b/util/install_dependencies.sh
new file mode 100644
index 000000000..24564a2ac
--- /dev/null
+++ b/util/install_dependencies.sh
@@ -0,0 +1,92 @@
+#!/usr/bin/env bash
+# This script will attempt to setup the Linux dependencies for compiling QMK/TMK
+
+# This could probably go much lower, but since we are including an Arch vagrant,
+# making it the first match makes sense
+
+if [[ -n "$(type -P pacman )" ]]; then
+ # Arch linux and derivatives like Apricity
+ # Future improvements:
+ # Allow user to speed up package installs using powerpill/wget tweaks
+ # Always run the pacman mirror update script if possible when vagrant comes up
+ # This will ensure that users never get stalled on a horribly slow mirror
+ pacman -Syyu --needed --noconfirm
+ pacman -S --needed --noconfirm \
+ base-devel \
+ avr-gcc \
+ avr-binutils \
+ avr-libc \
+ dfu-util \
+ arm-none-eabi-gcc \
+ arm-none-eabi-binutils \
+ arm-none-eabi-newlib \
+ git
+
+elif [[ -n "$(type -P apt-get)" ]]; then
+ # Debian and derivatives
+ # This block performs completely non-interactive updates {{
+ export DEBIAN_FRONTEND=noninteractive
+ export DEBCONF_NONINTERACTIVE_SEEN=true
+ echo "grub-pc hold" | dpkg --set-selections
+ apt-get -y update
+ apt-get -y --allow-unauthenticated upgrade \
+ -o Dpkg::Options::="--force-confdef" \
+ -o Dpkg::Options::="--force-confold"
+ # }}
+ apt-get install -y \
+ build-essential \
+ gcc \
+ unzip \
+ wget \
+ zip \
+ gcc-avr \
+ binutils-avr \
+ avr-libc \
+ dfu-programmer \
+ dfu-util \
+ gcc-arm-none-eabi \
+ binutils-arm-none-eabi \
+ libnewlib-arm-none-eabi \
+ git
+
+elif [[ -n "$(type -P yum)" ]]; then
+ # Fedora, CentOS or RHEL and derivatives
+ yum -y makecache && yum -y update
+ yum -y install \
+ gcc \
+ glibc-headers \
+ kernel-devel \
+ kernel-headers \
+ make \
+ perl \
+ git \
+ wget \
+ avr-binutils \
+ avr-gcc \
+ avr-libc \
+ dfu-programmer \
+ dfu-util \
+ gcc-arm-none-eabi \
+ binutils-arm-none-eabi \
+ libnewlib-arm-none-eabi \
+ git
+ # The listed eabi pacackes do unfortunately not exist for CentOS,
+ # But at least in Fedora they do, so try to install them anyway
+ # TODO: Build them from sources, if the installation fails
+
+elif [[ -n "$(type -P zypper)" ]]; then
+ # openSUSE
+ zypper --non-interactive refresh && zypper --non-interactive update
+ zypper --non-interactive install \
+ git \
+ make \
+ gcc \
+ kernel-devel \
+ patch \
+ wget \
+ dfu-programmer \
+ git
+ # TODO: The avr and eabi tools are not available as default packages, so we need
+ # another way to install them
+
+fi
diff --git a/util/new_project.sh b/util/new_project.sh
new file mode 100755
index 000000000..b3535f449
--- /dev/null
+++ b/util/new_project.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+# Script to make a new quantum project
+# Jack Humbert 2015
+
+if [ -z "$1" ]; then
+ echo "Usage: $0 <keyboard_name>"
+ exit 1
+fi
+
+cd "$(dirname "$0")/.."
+
+KEYBOARD=$1
+KEYBOARD_UPPERCASE=$(echo $1 | awk '{print toupper($0)}')
+
+mkdir keyboards/$1
+mkdir keyboards/$1/keymaps
+mkdir keyboards/$1/keymaps/default
+sed -e "s;%KEYBOARD%;$KEYBOARD;g" -e "s;%KEYBOARD_UPPERCASE%;$KEYBOARD_UPPERCASE;g" quantum/template/template.h > keyboards/$KEYBOARD/$KEYBOARD.h
+sed -e "s;%KEYBOARD%;$KEYBOARD;g" quantum/template/template.c > keyboards/$KEYBOARD/$KEYBOARD.c
+sed -e "s;%KEYBOARD%;$KEYBOARD;g" quantum/template/config.h > keyboards/$KEYBOARD/config.h
+sed -e "s;%KEYBOARD%;$KEYBOARD;g" quantum/template/readme.md > keyboards/$KEYBOARD/readme.md
+sed -e "s;%KEYBOARD%;$KEYBOARD;g" quantum/template/Makefile > keyboards/$KEYBOARD/Makefile
+sed -e "s;%KEYBOARD%;$KEYBOARD;g" quantum/template/keymaps/default/config.h > keyboards/$KEYBOARD/keymaps/default/config.h
+sed -e "s;%KEYBOARD%;$KEYBOARD;g" quantum/template/keymaps/default/keymap.c > keyboards/$KEYBOARD/keymaps/default/keymap.c
+sed -e "s;%KEYBOARD%;$KEYBOARD;g" quantum/template/keymaps/default/Makefile > keyboards/$KEYBOARD/keymaps/default/Makefile
+sed -e "s;%KEYBOARD%;$KEYBOARD;g" quantum/template/keymaps/default/readme.md > keyboards/$KEYBOARD/keymaps/default/readme.md
+
+echo "######################################################"
+echo "# /keyboards/$KEYBOARD project created. To start"
+echo "# working on things, cd into keyboards/$KEYBOARD"
+echo "######################################################"
diff --git a/util/travis_compiled_push.sh b/util/travis_compiled_push.sh
new file mode 100644
index 000000000..01317f4be
--- /dev/null
+++ b/util/travis_compiled_push.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+set -o errexit -o nounset
+
+rev=$(git rev-parse --short HEAD)
+
+git config --global user.name "Travis CI"
+git config --global user.email "jack.humb+travis.ci@gmail.com"
+
+find . -name ".build" | xargs rm -rf
+cd ..
+git clone https://$GH_TOKEN@github.com/jackhumbert/qmk.fm.git
+cd qmk.fm
+git submodule update --init --recursive
+rm -rf keyboard
+rm -rf keyboards
+cp -r ../qmk_firmware/keyboards .
+cp ../qmk_firmware/readme.md qmk_readme.md
+./generate.sh
+
+git add -A
+git commit -m "generated from qmk_firmware/$TRAVIS_BRANCH@${rev}"
+git push \ No newline at end of file